Fix double free of play policy in a race condition. am: 4b86f1dbae am: 02dcf3a9c0

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/13472357

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I00787d876547200248e374b2faa7479a20757ef6
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
new file mode 100644
index 0000000..37d714c
--- /dev/null
+++ b/MainlineFiles.cfg
@@ -0,0 +1,34 @@
+# 
+# mainline files for frameworks/av
+#
+# ignore comment (#) lines and blank lines
+# rest are path prefixes starting at root of the project
+# (so OWNERS, not frameworks/av/OWNERS)
+# 
+# path
+# INCLUDE path
+# EXCLUDE path
+#
+# 'path' and 'INCLUDE path' are identical -- they both indicate that this path
+# is part of mainline
+# EXCLUDE indicates that this is not part of mainline,
+# so 'foo/' and 'EXCLUDE foo/nope'
+# means everything under foo/ is part of mainline EXCEPT foo/nope.
+# INCLUDE/EXCLUDE/INCLUDE nested structuring is not supported
+#
+# matching is purely prefix
+# so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
+# if you want to exclude a directory, best to use a pattern like "foo/"
+#
+
+media/codec2/components/
+media/codecs/
+media/extractors/
+media/libstagefright/codecs/amrnb/
+media/libstagefright/codecs/amrwb/
+media/libstagefright/codecs/amrwbenc/
+media/libstagefright/codecs/common/
+media/libstagefright/codecs/flac/
+media/libstagefright/codecs/m4v_h263/
+media/libstagefright/codecs/mp3dec/
+media/libstagefright/mpeg2ts
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..ae920c0
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,2 @@
+[Hook Scripts]
+mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_partial.sh ${REPO_ROOT} ${PREUPLOAD_FILES}
diff --git a/apex/Android.bp b/apex/Android.bp
index 42a620b..c1ef3d8 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -14,6 +14,7 @@
 
 apex_defaults {
     name: "com.android.media-defaults",
+    updatable: true,
     java_libs: ["updatable-media"],
     multilib: {
         first: {
@@ -35,12 +36,23 @@
     },
     prebuilts: [
         "mediaextractor.policy",
+        "code_coverage.policy",
+        "crash_dump.policy",
     ],
     key: "com.android.media.key",
     certificate: ":com.android.media.certificate",
 
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media-androidManifest",
+
+    // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
+    // min_sdk_version should be 29. This enables the build system to make
+    // sure the package compatible to Android 10 in two ways:
+    // - build the APEX package compatible to Android 10
+    //   so that the package can be installed.
+    // - build artifacts (lib/javalib/bin) against Android 10 SDK
+    //   so that the artifacts can run.
+    min_sdk_version: "29",
 }
 
 apex {
@@ -61,6 +73,7 @@
 
 apex_defaults {
     name: "com.android.media.swcodec-defaults",
+    updatable: true,
     binaries: [
         "mediaswcodec",
     ],
@@ -68,6 +81,8 @@
         "com.android.media.swcodec-mediaswcodec.rc",
         "com.android.media.swcodec-ld.config.txt",
         "mediaswcodec.policy",
+        "code_coverage.policy",
+        "crash_dump.policy",
         "mediaswcodec.xml",
     ],
     use_vendor: true,
@@ -76,6 +91,15 @@
 
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media.swcodec-androidManifest",
+
+    // IMPORTANT: For the APEX to be installed on Android 10 (API 29),
+    // min_sdk_version should be 29. This enables the build system to make
+    // sure the package compatible to Android 10 in two ways:
+    // - build the APEX package compatible to Android 10
+    //   so that the package can be installed.
+    // - build artifacts (lib/javalib/bin) against Android 10 SDK
+    //   so that the artifacts can run.
+    min_sdk_version: "29",
 }
 
 prebuilt_etc {
diff --git a/apex/AndroidManifest-media.xml b/apex/AndroidManifest-media.xml
index 1af4586..b020cba 100644
--- a/apex/AndroidManifest-media.xml
+++ b/apex/AndroidManifest-media.xml
@@ -19,8 +19,10 @@
   <!-- APEX does not have classes.dex -->
   <application android:hasCode="false" />
   <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
-  <uses-sdk
+  <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
+  <!--uses-sdk
       android:maxSdkVersion="29"
       android:targetSdkVersion="29"
   />
+  -->
 </manifest>
diff --git a/apex/AndroidManifest-swcodec.xml b/apex/AndroidManifest-swcodec.xml
index de50864..1a28d19 100644
--- a/apex/AndroidManifest-swcodec.xml
+++ b/apex/AndroidManifest-swcodec.xml
@@ -19,8 +19,10 @@
   <!-- APEX does not have classes.dex -->
   <application android:hasCode="false" />
   <!-- Setting maxSdk to lock the module to Q. minSdk is auto-set by build system -->
-  <uses-sdk
+  <!-- TODO: Uncomment this when the R API level is fixed. b/148281152 -->
+  <!--uses-sdk
       android:maxSdkVersion="29"
       android:targetSdkVersion="29"
   />
+  -->
 </manifest>
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
index a2e98cc..f036516 100644
--- a/apex/TEST_MAPPING
+++ b/apex/TEST_MAPPING
@@ -3,5 +3,30 @@
     {
       "path": "system/apex/tests"
     }
+  ],
+  "presubmit": [
+    // The following tests validate codec and drm path.
+    {
+      "name": "GtsMediaTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+        }
+      ]
+    },
+    {
+      "name": "GtsExoPlayerTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.SocPresubmit"
+        },
+        {
+          "include-filter": "com.google.android.exoplayer.gts.DashTest#testWidevine23FpsH264Fixed"
+        }
+      ]
+    }
   ]
 }
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index af8ec06..713f0b7 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -22,12 +22,18 @@
 namespace.default.search.paths      = /apex/com.android.media.swcodec/${LIB}
 namespace.default.asan.search.paths = /apex/com.android.media.swcodec/${LIB}
 
+# Below lines are required to be able to access libs in APEXes which are
+# actually symlinks to the files under /system/lib. The symlinks exist for
+# bundled APEXes to reduce space.
+namespace.default.permitted.paths   = /system/${LIB}
+namespace.default.asan.permitted.paths = /system/${LIB}
+
 namespace.default.links = platform
 
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.default.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
 
 ###############################################################################
 # "platform" namespace
@@ -38,13 +44,18 @@
 namespace.platform.isolated = true
 
 namespace.platform.search.paths  = /system/${LIB}
-namespace.platform.search.paths += /apex/com.android.runtime/${LIB}
 namespace.platform.asan.search.paths  = /data/asan/system/${LIB}
 namespace.platform.asan.search.paths +=           /system/${LIB}
+
+# TODO(b/140790209): These directories are wrong in R and later because they
+# only contain Bionic internal libraries dependencies that should not be
+# accessed from the outside. However, they may be necessary for APEX builds that
+# are pushed to Q. Remove them as soon as Q compatibility is no longer required.
+namespace.platform.search.paths += /apex/com.android.runtime/${LIB}
 namespace.platform.asan.search.paths += /apex/com.android.runtime/${LIB}
 
 # /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
-# Add /apex/... pat to the permitted paths because linker uses realpath(3)
+# Add /apex/... path to the permitted paths because linker uses realpath(3)
 # to check the accessibility of the lib. We could add this to search.paths
 # instead but that makes the resolution of bionic libs be dependent on
 # the order of /system/lib and /apex/... in search.paths. If /apex/...
@@ -127,7 +138,13 @@
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.sphal.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
 
 # Add a link for libz.so which is llndk on devices where VNDK is not enforced.
 namespace.sphal.link.platform.shared_libs += libz.so
+
+# With VNDK APEX, /system/${LIB}/vndk-sp${VNDK_VER} is a symlink to the following.
+# Add /apex/... path to the permitted paths because linker uses realpath(3)
+# to check the accessibility of the lib.
+namespace.sphal.permitted.paths += /apex/com.android.vndk.${VNDK_APEX_VER}/${LIB}
+namespace.sphal.asan.permitted.paths += /apex/com.android.vndk.${VNDK_APEX_VER}/${LIB}
diff --git a/apex/manifest.json b/apex/manifest.json
index b11187d..ddd642e 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media",
-  "version": 299900000
+  "version": 300000000
 }
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 09c436d..2320fd7 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media.swcodec",
-  "version": 299900000
+  "version": 300000000
 }
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 701ced7..a04ab3f 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -12,18 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-apex {
+apex_test {
     name: "test_com.android.media",
     manifest: "test_manifest.json",
-    file_contexts: "com.android.media",
+    file_contexts: ":com.android.media-file_contexts",
     defaults: ["com.android.media-defaults"],
+    prebuilts: ["sdkinfo_45"],
     installable: false,
 }
 
-apex {
+apex_test {
     name: "test_com.android.media.swcodec",
     manifest: "test_manifest_codec.json",
-    file_contexts: "com.android.media.swcodec",
+    file_contexts: ":com.android.media.swcodec-file_contexts",
     defaults: ["com.android.media.swcodec-defaults"],
     installable: false,
 }
diff --git a/apex/testing/test_manifest.json b/apex/testing/test_manifest.json
index ddd642e..e1295a2 100644
--- a/apex/testing/test_manifest.json
+++ b/apex/testing/test_manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media",
-  "version": 300000000
+  "version": 2147483647
 }
diff --git a/camera/Android.bp b/camera/Android.bp
index 2800595..fa36bb3 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -40,6 +40,7 @@
         "ICameraRecordingProxy.cpp",
         "ICameraRecordingProxyListener.cpp",
         "camera2/CaptureRequest.cpp",
+        "camera2/ConcurrentCamera.cpp",
         "camera2/OutputConfiguration.cpp",
         "camera2/SessionConfiguration.cpp",
         "camera2/SubmitInfo.cpp",
@@ -66,7 +67,7 @@
          "include",
          "include/camera"
     ],
-    export_shared_lib_headers: ["libcamera_metadata"],
+    export_shared_lib_headers: ["libcamera_metadata", "libnativewindow", "libgui"],
 
     cflags: [
         "-Werror",
@@ -85,7 +86,9 @@
         "aidl/android/hardware/ICameraServiceProxy.aidl",
         "aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl",
         "aidl/android/hardware/camera2/ICameraDeviceUser.aidl",
+        "aidl/android/hardware/camera2/ICameraOfflineSession.aidl",
     ],
+    path: "aidl",
 }
 
 // Extra AIDL files that are used by framework.jar but not libcamera_client
@@ -96,4 +99,5 @@
         "aidl/android/hardware/ICamera.aidl",
         "aidl/android/hardware/ICameraClient.aidl",
     ],
+    path: "aidl",
 }
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index c6c35ef..84d1d93 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -347,6 +347,20 @@
     return c->setPreviewCallbackTarget(callbackProducer);
 }
 
+status_t Camera::setAudioRestriction(int32_t mode)
+{
+    sp <::android::hardware::ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->setAudioRestriction(mode);
+}
+
+int32_t Camera::getGlobalAudioRestriction()
+{
+    sp <::android::hardware::ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    return c->getGlobalAudioRestriction();
+}
+
 // callback from camera service
 void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
 {
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index c53e6c3..aecb70a 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -60,6 +60,13 @@
     if (res != OK) return res;
 
     res = parcel->writeInt32(status);
+    if (res != OK) return res;
+
+    std::vector<String16> unavailablePhysicalIds16;
+    for (auto& id8 : unavailablePhysicalIds) {
+        unavailablePhysicalIds16.push_back(String16(id8));
+    }
+    res = parcel->writeString16Vector(unavailablePhysicalIds16);
     return res;
 }
 
@@ -70,6 +77,14 @@
     cameraId = String8(tempCameraId);
 
     res = parcel->readInt32(&status);
+    if (res != OK) return res;
+
+    std::vector<String16> unavailablePhysicalIds16;
+    res = parcel->readString16Vector(&unavailablePhysicalIds16);
+    if (res != OK) return res;
+    for (auto& id16 : unavailablePhysicalIds16) {
+        unavailablePhysicalIds.push_back(String8(id16));
+    }
     return res;
 }
 
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 92fe84b..135384a 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -46,6 +46,15 @@
     mBuffer = clone_camera_metadata(other.mBuffer);
 }
 
+CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL),  mLocked(false) {
+    acquire(other);
+}
+
+CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
+    acquire(other);
+    return *this;
+}
+
 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
         mBuffer(NULL), mLocked(false) {
     acquire(buffer);
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index 1d8e8c4..755051c 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -49,6 +49,9 @@
         }
         errorPhysicalCameraId = cameraId;
     }
+    parcel->readInt64(&lastCompletedRegularFrameNumber);
+    parcel->readInt64(&lastCompletedReprocessFrameNumber);
+    parcel->readInt64(&lastCompletedZslFrameNumber);
 
     return OK;
 }
@@ -76,6 +79,9 @@
     } else {
         parcel->writeBool(false);
     }
+    parcel->writeInt64(lastCompletedRegularFrameNumber);
+    parcel->writeInt64(lastCompletedReprocessFrameNumber);
+    parcel->writeInt64(lastCompletedZslFrameNumber);
 
     return OK;
 }
@@ -117,6 +123,12 @@
         mMetadata(), mResultExtras() {
 }
 
+CaptureResult::CaptureResult(CaptureResult &&otherResult) {
+    mMetadata = std::move(otherResult.mMetadata);
+    mResultExtras = otherResult.mResultExtras;
+    mPhysicalMetadatas = std::move(otherResult.mPhysicalMetadatas);
+}
+
 CaptureResult::CaptureResult(const CaptureResult &otherResult) {
     mResultExtras = otherResult.mResultExtras;
     mMetadata = otherResult.mMetadata;
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index f0945c7..b83edf7 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -56,6 +56,8 @@
     SET_VIDEO_BUFFER_TARGET,
     RELEASE_RECORDING_FRAME_HANDLE,
     RELEASE_RECORDING_FRAME_HANDLE_BATCH,
+    SET_AUDIO_RESTRICTION,
+    GET_GLOBAL_AUDIO_RESTRICTION,
 };
 
 class BpCamera: public BpInterface<ICamera>
@@ -191,6 +193,21 @@
         }
     }
 
+    status_t setAudioRestriction(int32_t mode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(SET_AUDIO_RESTRICTION, data, &reply);
+        return reply.readInt32();
+    }
+
+    int32_t getGlobalAudioRestriction() {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        remote()->transact(GET_GLOBAL_AUDIO_RESTRICTION, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t setVideoBufferMode(int32_t videoBufferMode)
     {
         ALOGV("setVideoBufferMode: %d", videoBufferMode);
@@ -494,6 +511,17 @@
             reply->writeInt32(setVideoTarget(st));
             return NO_ERROR;
         } break;
+        case SET_AUDIO_RESTRICTION: {
+            CHECK_INTERFACE(ICamera, data, reply);
+            int32_t mode = data.readInt32();
+            reply->writeInt32(setAudioRestriction(mode));
+            return NO_ERROR;
+        } break;
+        case GET_GLOBAL_AUDIO_RESTRICTION: {
+            CHECK_INTERFACE(ICamera, data, reply);
+            reply->writeInt32(getGlobalAudioRestriction());
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 8620f36..c02c81b 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -139,15 +139,18 @@
             CHECK_INTERFACE(ICameraClient, data, reply);
             int32_t msgType = data.readInt32();
             sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
-            camera_frame_metadata_t *metadata = NULL;
+            camera_frame_metadata_t metadata;
             if (data.dataAvail() > 0) {
-                metadata = new camera_frame_metadata_t;
-                metadata->number_of_faces = data.readInt32();
-                metadata->faces = (camera_face_t *) data.readInplace(
-                        sizeof(camera_face_t) * metadata->number_of_faces);
+                metadata.number_of_faces = data.readInt32();
+                if (metadata.number_of_faces <= 0 ||
+                        metadata.number_of_faces > (int32_t)(INT32_MAX / sizeof(camera_face_t))) {
+                    ALOGE("%s: Too large face count: %d", __FUNCTION__, metadata.number_of_faces);
+                    return BAD_VALUE;
+                }
+                metadata.faces = (camera_face_t *) data.readInplace(
+                        sizeof(camera_face_t) * metadata.number_of_faces);
             }
-            dataCallback(msgType, imageData, metadata);
-            if (metadata) delete metadata;
+            dataCallback(msgType, imageData, &metadata);
             return NO_ERROR;
         } break;
         case DATA_CALLBACK_TIMESTAMP: {
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 3e8992a..ac7a35b 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -22,6 +22,8 @@
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.params.VendorTagDescriptor;
 import android.hardware.camera2.params.VendorTagDescriptorCache;
+import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
+import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.ICameraServiceListener;
 import android.hardware.CameraInfo;
@@ -87,6 +89,7 @@
     ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
             String cameraId,
             String opPackageName,
+            @nullable String featureId,
             int clientUid);
 
     /**
@@ -113,6 +116,25 @@
     CameraStatus[] addListener(ICameraServiceListener listener);
 
     /**
+     * Get a list of combinations of camera ids which support concurrent streaming.
+     *
+     */
+    ConcurrentCameraIdCombination[] getConcurrentCameraIds();
+
+    /**
+      * Check whether a particular set of session configurations are concurrently supported by the
+      * corresponding camera ids.
+      *
+      * @param sessions the set of camera id and session configuration pairs to be queried.
+      * @return true  - the set of concurrent camera id and stream combinations is supported.
+      *         false - the set of concurrent camera id and stream combinations is not supported
+      *                 OR the method was called with a set of camera ids not returned by
+      *                 getConcurrentCameraIds().
+      */
+    boolean isConcurrentSessionConfigurationSupported(
+            in CameraIdAndSessionConfiguration[] sessions);
+
+    /**
      * Remove listener for changes to camera device and flashlight state.
      */
     void removeListener(ICameraServiceListener listener);
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index 47580f8..c54813c 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -54,6 +54,12 @@
     oneway void onStatusChanged(int status, String cameraId);
 
     /**
+     * Notify registered client about status changes for a physical camera backing
+     * a logical camera.
+     */
+    oneway void onPhysicalCameraStatusChanged(int status, String cameraId, String physicalCameraId);
+
+    /**
      * The torch mode status of a camera.
      *
      * Initial status will be transmitted with onTorchStatusChanged immediately
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 49dfde8..b183ccc 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -17,6 +17,8 @@
 package android.hardware.camera2;
 
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraOfflineSession;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.SessionConfiguration;
@@ -81,8 +83,9 @@
      * @param operatingMode The kind of session to create; either NORMAL_MODE or
      *     CONSTRAINED_HIGH_SPEED_MODE. Must be a non-negative value.
      * @param sessionParams Session wide camera parameters
+     * @return a list of stream ids that can be used in offline mode via "switchToOffline"
      */
-    void endConfigure(int operatingMode, in CameraMetadataNative sessionParams);
+    int[] endConfigure(int operatingMode, in CameraMetadataNative sessionParams);
 
     /**
       * Check whether a particular session configuration has camera device
@@ -155,4 +158,37 @@
     void updateOutputConfiguration(int streamId, in OutputConfiguration outputConfiguration);
 
     void finalizeOutputConfigurations(int streamId, in OutputConfiguration outputConfiguration);
+
+
+    // Keep in sync with public API in
+    // frameworks/base/core/java/android/hardware/camera2/CameraDevice.java
+    const int AUDIO_RESTRICTION_NONE = 0;
+    const int AUDIO_RESTRICTION_VIBRATION = 1;
+    const int AUDIO_RESTRICTION_VIBRATION_SOUND = 3;
+
+    /**
+      * Set audio restriction mode for this camera device.
+      *
+      * @param mode the audio restriction mode ID as above
+      *
+      */
+    void setCameraAudioRestriction(int mode);
+
+    /**
+      * Get global audio restriction mode for all camera clients.
+      *
+      * @return the currently applied system-wide audio restriction mode
+      */
+    int getGlobalAudioRestriction();
+
+    /**
+     * Offline processing main entry point
+     *
+     * @param callbacks Object that will receive callbacks from offline session
+     * @param offlineOutputIds The ID of streams that needs to be preserved in offline session
+     *
+     * @return Offline session object.
+     */
+    ICameraOfflineSession switchToOffline(in ICameraDeviceCallbacks callbacks,
+            in int[] offlineOutputIds);
 }
diff --git a/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl b/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl
new file mode 100644
index 0000000..ab030ab
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/ICameraOfflineSession.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 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.hardware.camera2;
+
+ /** @hide */
+interface ICameraOfflineSession
+{
+    void disconnect();
+}
diff --git a/camera/aidl/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.aidl b/camera/aidl/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.aidl
new file mode 100644
index 0000000..ca89ad8
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.utils;
+
+/** @hide */
+parcelable CameraIdAndSessionConfiguration cpp_header "camera/camera2/ConcurrentCamera.h";
diff --git a/camera/aidl/android/hardware/camera2/utils/ConcurrentCameraIdCombination.aidl b/camera/aidl/android/hardware/camera2/utils/ConcurrentCameraIdCombination.aidl
new file mode 100644
index 0000000..4b35c31
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/utils/ConcurrentCameraIdCombination.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.utils;
+
+/** @hide */
+parcelable ConcurrentCameraIdCombination cpp_header "camera/camera2/ConcurrentCamera.h";
diff --git a/camera/camera2/ConcurrentCamera.cpp b/camera/camera2/ConcurrentCamera.cpp
new file mode 100644
index 0000000..01a695c
--- /dev/null
+++ b/camera/camera2/ConcurrentCamera.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "ConcurrentCamera"
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+#include <camera/camera2/ConcurrentCamera.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace utils {
+
+ConcurrentCameraIdCombination::ConcurrentCameraIdCombination() = default;
+
+ConcurrentCameraIdCombination::ConcurrentCameraIdCombination(
+        std::vector<std::string> &&combination) : mConcurrentCameraIds(std::move(combination)) { }
+
+ConcurrentCameraIdCombination::~ConcurrentCameraIdCombination() = default;
+
+status_t ConcurrentCameraIdCombination::readFromParcel(const android::Parcel* parcel) {
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    status_t err = OK;
+    mConcurrentCameraIds.clear();
+    int32_t cameraIdCount = 0;
+    if ((err = parcel->readInt32(&cameraIdCount)) != OK) {
+        ALOGE("%s: Failed to read the camera id count from parcel: %d", __FUNCTION__, err);
+        return err;
+    }
+    for (int32_t i = 0; i < cameraIdCount; i++) {
+        String16 id;
+        if ((err = parcel->readString16(&id)) != OK) {
+            ALOGE("%s: Failed to read camera id!", __FUNCTION__);
+            return err;
+        }
+        mConcurrentCameraIds.push_back(std::string(String8(id).string()));
+    }
+    return OK;
+}
+
+status_t ConcurrentCameraIdCombination::writeToParcel(android::Parcel* parcel) const {
+
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    status_t err = OK;
+
+    if ((err = parcel->writeInt32(mConcurrentCameraIds.size())) != OK) {
+        ALOGE("%s: Failed to write the camera id count to parcel: %d", __FUNCTION__, err);
+        return err;
+    }
+
+    for (const auto &it : mConcurrentCameraIds) {
+        if ((err = parcel->writeString16(String16(it.c_str()))) != OK) {
+            ALOGE("%s: Failed to write the camera id string to parcel: %d", __FUNCTION__, err);
+            return err;
+        }
+    }
+    return OK;
+}
+
+CameraIdAndSessionConfiguration::CameraIdAndSessionConfiguration() = default;
+CameraIdAndSessionConfiguration::~CameraIdAndSessionConfiguration() = default;
+
+status_t CameraIdAndSessionConfiguration::readFromParcel(const android::Parcel* parcel) {
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    status_t err = OK;
+    String16 id;
+    if ((err = parcel->readString16(&id)) != OK) {
+        ALOGE("%s: Failed to read camera id!", __FUNCTION__);
+        return err;
+    }
+    if ((err = mSessionConfiguration.readFromParcel(parcel)) != OK) {
+        ALOGE("%s: Failed to read sessionConfiguration!", __FUNCTION__);
+        return err;
+    }
+    mCameraId = std::string(String8(id).string());
+    return OK;
+}
+
+status_t CameraIdAndSessionConfiguration::writeToParcel(android::Parcel* parcel) const {
+
+    if (parcel == nullptr) {
+        ALOGE("%s: Null parcel", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    status_t err = OK;
+    if ((err = parcel->writeString16(String16(mCameraId.c_str()))) != OK) {
+        ALOGE("%s: Failed to write camera id!", __FUNCTION__);
+        return err;
+    }
+
+    if ((err = mSessionConfiguration.writeToParcel(parcel) != OK)) {
+        ALOGE("%s: Failed to write session configuration!", __FUNCTION__);
+        return err;
+    }
+    return OK;
+}
+
+} // namespace utils
+} // namespace camera2
+} // namespace hardware
+} // namespace android
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index ecaba3a..dc7f88a 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -17,6 +17,10 @@
 
     srcs: ["main_cameraserver.cpp"],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "libcameraservice",
         "liblog",
@@ -25,10 +29,10 @@
         "libgui",
         "libbinder",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.6",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.4",
@@ -44,6 +48,6 @@
     init_rc: ["cameraserver.rc"],
 
     vintf_fragments: [
-        "manifest_android.frameworks.cameraservice.service@2.0.xml",
+        "manifest_android.frameworks.cameraservice.service@2.1.xml",
     ],
 }
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
index a9aae0b..8f51458 100644
--- a/camera/cameraserver/cameraserver.rc
+++ b/camera/cameraserver/cameraserver.rc
@@ -3,5 +3,5 @@
     user cameraserver
     group audio camera input drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
+    task_profiles CameraServiceCapacity MaxPerformance
     rlimit rtprio 10 10
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
deleted file mode 100644
index 601c717..0000000
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
-    <hal>
-        <name>android.frameworks.cameraservice.service</name>
-        <transport>hwbinder</transport>
-        <version>2.0</version>
-        <interface>
-            <name>ICameraService</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml
new file mode 100644
index 0000000..5a15b35
--- /dev/null
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.1.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+    <hal>
+        <name>android.frameworks.cameraservice.service</name>
+        <transport>hwbinder</transport>
+        <version>2.1</version>
+        <interface>
+            <name>ICameraService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 430aa1c..2cdb617 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -167,6 +167,9 @@
 
             sp<ICameraRecordingProxy> getRecordingProxy();
 
+            status_t     setAudioRestriction(int32_t mode);
+            int32_t      getGlobalAudioRestriction();
+
     // ICameraClient interface
     virtual void        notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
     virtual void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index 74a2dce..499b0e6 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -80,10 +80,16 @@
      */
     int32_t status;
 
+    /**
+     * Unavailable physical camera names for a multi-camera device
+     */
+    std::vector<String8> unavailablePhysicalIds;
+
     virtual status_t writeToParcel(android::Parcel* parcel) const;
     virtual status_t readFromParcel(const android::Parcel* parcel);
 
-    CameraStatus(String8 id, int32_t s) : cameraId(id), status(s) {}
+    CameraStatus(String8 id, int32_t s, const std::vector<String8>& unavailSubIds) :
+            cameraId(id), status(s), unavailablePhysicalIds(unavailSubIds) {}
     CameraStatus() : status(ICameraServiceListener::STATUS_PRESENT) {}
 };
 
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index 844bb80..9d1b5c7 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -40,6 +40,11 @@
      * dataCapacity extra storage */
     CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10);
 
+    /**
+     * Move constructor, acquires other's metadata buffer
+     */
+    CameraMetadata(CameraMetadata &&other);
+
     ~CameraMetadata();
 
     /** Takes ownership of passed-in buffer */
@@ -54,6 +59,11 @@
     CameraMetadata &operator=(const camera_metadata_t *buffer);
 
     /**
+     * Move assignment operator, acquires other's metadata buffer
+     */
+    CameraMetadata &operator=(CameraMetadata &&other);
+
+    /**
      * Get reference to the underlying metadata buffer. Ownership remains with
      * the CameraMetadata object, but non-const CameraMetadata methods will not
      * work until unlock() is called. Note that the lock has nothing to do with
diff --git a/camera/include/camera/CaptureResult.h b/camera/include/camera/CaptureResult.h
index ef830b5..f163c1e 100644
--- a/camera/include/camera/CaptureResult.h
+++ b/camera/include/camera/CaptureResult.h
@@ -76,6 +76,34 @@
      */
     String16  errorPhysicalCameraId;
 
+    // The last completed frame numbers shouldn't be checked in onResultReceived() and notifyError()
+    // because the output buffers could be arriving after onResultReceived() and
+    // notifyError(). Given this constraint, we check it for each
+    // onCaptureStarted, and if there is no further onCaptureStarted(),
+    // check for onDeviceIdle() to clear out all pending frame numbers.
+
+    /**
+     * The latest regular request frameNumber for which all buffers and capture result have been
+     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
+     * none has completed.
+     */
+    int64_t lastCompletedRegularFrameNumber;
+
+    /**
+     * The latest reprocess request frameNumber for which all buffers and capture result have been
+     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
+     * none has completed.
+     */
+    int64_t lastCompletedReprocessFrameNumber;
+
+    /**
+     * The latest Zsl request frameNumber for which all buffers and capture result have been
+     * returned or notified as an BUFFER_ERROR/RESULT_ERROR/REQUEST_ERROR. -1 if
+     * none has completed.
+     */
+    int64_t lastCompletedZslFrameNumber;
+
+
     /**
      * Constructor initializes object as invalid by setting requestId to be -1.
      */
@@ -87,7 +115,10 @@
           frameNumber(0),
           partialResultCount(0),
           errorStreamId(-1),
-          errorPhysicalCameraId() {
+          errorPhysicalCameraId(),
+          lastCompletedRegularFrameNumber(-1),
+          lastCompletedReprocessFrameNumber(-1),
+          lastCompletedZslFrameNumber(-1) {
     }
 
     /**
@@ -135,6 +166,8 @@
 
     CaptureResult(const CaptureResult& otherResult);
 
+    CaptureResult(CaptureResult &&captureResult);
+
     status_t                readFromParcel(android::Parcel* parcel);
     status_t                writeToParcel(android::Parcel* parcel) const;
 };
diff --git a/camera/include/camera/VendorTagDescriptor.h b/camera/include/camera/VendorTagDescriptor.h
index 6f55890..b2fbf3a 100644
--- a/camera/include/camera/VendorTagDescriptor.h
+++ b/camera/include/camera/VendorTagDescriptor.h
@@ -188,8 +188,8 @@
             sp<android::VendorTagDescriptor> *desc /*out*/);
 
     // Parcelable interface
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
+    status_t writeToParcel(android::Parcel* parcel) const override;
+    status_t readFromParcel(const android::Parcel* parcel) override;
 
     // Returns the number of vendor tags defined.
     int getTagCount(metadata_vendor_id_t id) const;
diff --git a/camera/include/camera/android/hardware/ICamera.h b/camera/include/camera/android/hardware/ICamera.h
index 80823d6..ec19e5d 100644
--- a/camera/include/camera/android/hardware/ICamera.h
+++ b/camera/include/camera/android/hardware/ICamera.h
@@ -140,6 +140,12 @@
     // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
     virtual status_t        setVideoTarget(
             const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+
+    // Set the audio restriction mode
+    virtual status_t        setAudioRestriction(int32_t mode) = 0;
+
+    // Get the global audio restriction mode
+    virtual int32_t         getGlobalAudioRestriction() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/camera/include/camera/camera2/ConcurrentCamera.h b/camera/include/camera/camera2/ConcurrentCamera.h
new file mode 100644
index 0000000..ac99fd5
--- /dev/null
+++ b/camera/include/camera/camera2/ConcurrentCamera.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA2_UTIL_CONCURRENTCAMERA_H
+#define ANDROID_HARDWARE_CAMERA2_UTIL_CONCURRENTCAMERA_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <camera2/OutputConfiguration.h>
+#include <camera2/SessionConfiguration.h>
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace utils {
+
+struct ConcurrentCameraIdCombination : public Parcelable {
+    std::vector<std::string> mConcurrentCameraIds;
+    ConcurrentCameraIdCombination();
+    ConcurrentCameraIdCombination(std::vector<std::string> &&combination);
+    virtual ~ConcurrentCameraIdCombination();
+
+    virtual status_t writeToParcel(android::Parcel *parcel) const override;
+    virtual status_t readFromParcel(const android::Parcel* parcel) override;
+};
+
+struct CameraIdAndSessionConfiguration : public Parcelable {
+    std::string mCameraId;
+    SessionConfiguration mSessionConfiguration;
+
+    CameraIdAndSessionConfiguration();
+    virtual ~CameraIdAndSessionConfiguration();
+
+    virtual status_t writeToParcel(android::Parcel *parcel) const override;
+    virtual status_t readFromParcel(const android::Parcel* parcel) override;
+};
+
+} // namespace utils
+} // namespace camera2
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index a2ee65d..7ba82c1 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -57,6 +57,9 @@
         "libmediandk",
         "libnativewindow",
     ],
+    header_libs: [
+        "jni_headers",
+    ],
     cflags: [
         "-fvisibility=hidden",
         "-DEXPORT=__attribute__ ((visibility (\"default\")))",
@@ -107,7 +110,6 @@
     ],
 
     shared_libs: [
-        "libhwbinder",
         "libfmq",
         "libhidlbase",
         "libhardware",
@@ -121,8 +123,8 @@
         "android.frameworks.cameraservice.device@2.0",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
+        "android.frameworks.cameraservice.service@2.1",
     ],
-
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
         "libarect",
@@ -139,11 +141,13 @@
 }
 
 cc_test {
-    name: "AImageReaderVendorTest",
+    name: "ACameraNdkVendorTest",
     vendor: true,
-    srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"],
+    srcs: [
+        "ndk_vendor/tests/AImageReaderVendorTest.cpp",
+        "ndk_vendor/tests/ACameraManagerTest.cpp",
+    ],
     shared_libs: [
-        "libhwbinder",
         "libcamera2ndk_vendor",
         "libcamera_metadata",
         "libmediandk",
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 9a39ed8..7d3a53e 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -26,6 +26,76 @@
 
 using namespace android;
 
+#ifndef __ANDROID_VNDK__
+namespace {
+
+constexpr const char* android_hardware_camera2_CameraMetadata_jniClassName =
+    "android/hardware/camera2/CameraMetadata";
+constexpr const char* android_hardware_camera2_CameraCharacteristics_jniClassName =
+    "android/hardware/camera2/CameraCharacteristics";
+constexpr const char* android_hardware_camera2_CaptureResult_jniClassName =
+    "android/hardware/camera2/CaptureResult";
+
+jclass android_hardware_camera2_CameraCharacteristics_clazz = nullptr;
+jclass android_hardware_camera2_CaptureResult_clazz = nullptr;
+jmethodID android_hardware_camera2_CameraMetadata_getNativeMetadataPtr = nullptr;
+
+// Called at most once to initializes global variables used by JNI.
+bool InitJni(JNIEnv* env) {
+    // From C++11 onward, static initializers are guaranteed to be executed at most once,
+    // even if called from multiple threads.
+    static bool ok = [env]() -> bool {
+        const jclass cameraMetadataClazz = env->FindClass(
+            android_hardware_camera2_CameraMetadata_jniClassName);
+        if (cameraMetadataClazz == nullptr) {
+            return false;
+        }
+        const jmethodID cameraMetadata_getNativeMetadataPtr =
+            env->GetMethodID(cameraMetadataClazz, "getNativeMetadataPtr", "()J");
+        if (cameraMetadata_getNativeMetadataPtr == nullptr) {
+            return false;
+        }
+
+        const jclass cameraCharacteristics_clazz = env->FindClass(
+            android_hardware_camera2_CameraCharacteristics_jniClassName);
+        if (cameraCharacteristics_clazz == nullptr) {
+            return false;
+        }
+
+        const jclass captureResult_clazz = env->FindClass(
+            android_hardware_camera2_CaptureResult_jniClassName);
+        if (captureResult_clazz == nullptr) {
+            return false;
+        }
+
+        android_hardware_camera2_CameraMetadata_getNativeMetadataPtr =
+            cameraMetadata_getNativeMetadataPtr;
+        android_hardware_camera2_CameraCharacteristics_clazz =
+            static_cast<jclass>(env->NewGlobalRef(cameraCharacteristics_clazz));
+        android_hardware_camera2_CaptureResult_clazz =
+            static_cast<jclass>(env->NewGlobalRef(captureResult_clazz));
+
+        return true;
+    }();
+    return ok;
+}
+
+// Given cameraMetadata, an instance of android.hardware.camera2.CameraMetadata, invokes
+// cameraMetadata.getNativeMetadataPtr() and returns it as a std::shared_ptr<CameraMetadata>*.
+std::shared_ptr<CameraMetadata>* CameraMetadata_getNativeMetadataPtr(JNIEnv* env,
+        jobject cameraMetadata) {
+    if (cameraMetadata == nullptr) {
+        ALOGE("%s: Invalid Java CameraMetadata object.", __FUNCTION__);
+        return nullptr;
+    }
+    jlong ret = env->CallLongMethod(cameraMetadata,
+                                    android_hardware_camera2_CameraMetadata_getNativeMetadataPtr);
+    return reinterpret_cast<std::shared_ptr<CameraMetadata>* >(ret);
+}
+
+}  // namespace
+#endif  /* __ANDROID_VNDK__ */
+
 EXPORT
 camera_status_t ACameraMetadata_getConstEntry(
         const ACameraMetadata* acm, uint32_t tag, ACameraMetadata_const_entry* entry) {
@@ -58,7 +128,7 @@
         return nullptr;
     }
     ACameraMetadata* copy = new ACameraMetadata(*src);
-    copy->incStrong((void*) ACameraMetadata_copy);
+    copy->incStrong(/*id=*/(void*) ACameraMetadata_copy);
     return copy;
 }
 
@@ -86,3 +156,33 @@
 
     return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
 }
+
+#ifndef __ANDROID_VNDK__
+EXPORT
+ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata) {
+    ATRACE_CALL();
+
+    const bool ok = InitJni(env);
+    LOG_ALWAYS_FATAL_IF(!ok, "Failed to find CameraMetadata Java classes.");
+
+    if (cameraMetadata == nullptr) {
+        return nullptr;
+    }
+
+    ACameraMetadata::ACAMERA_METADATA_TYPE type;
+    if (env->IsInstanceOf(cameraMetadata,
+        android_hardware_camera2_CameraCharacteristics_clazz)) {
+        type = ACameraMetadata::ACM_CHARACTERISTICS;
+    } else if (env->IsInstanceOf(cameraMetadata,
+        android_hardware_camera2_CaptureResult_clazz)) {
+        type = ACameraMetadata::ACM_RESULT;
+    } else {
+        return nullptr;
+    }
+
+    auto sharedData = CameraMetadata_getNativeMetadataPtr(env, cameraMetadata);
+    ACameraMetadata* output = new ACameraMetadata(*sharedData, type);
+    output->incStrong(/*id=*/(void*) ACameraMetadata_fromCameraMetadata);
+    return output;
+}
+#endif  /* __ANDROID_VNDK__ */
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 46a8dae..c15c5a5 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -710,7 +710,8 @@
     if ((sessionParameters != nullptr) && (sessionParameters->settings != nullptr)) {
         params.append(sessionParameters->settings->getInternalData());
     }
-    remoteRet = mRemote->endConfigure(/*isConstrainedHighSpeed*/ false, params);
+    std::vector<int> offlineStreamIds;
+    remoteRet = mRemote->endConfigure(/*isConstrainedHighSpeed*/ false, params, &offlineStreamIds);
     if (remoteRet.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
         ALOGE("Camera device %s cannnot support app output configuration: %s", getId(),
                 remoteRet.toString8().string());
@@ -1335,56 +1336,97 @@
 void
 CameraDevice::checkAndFireSequenceCompleteLocked() {
     int64_t completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
-    //std::map<int, int64_t> mSequenceLastFrameNumberMap;
     auto it = mSequenceLastFrameNumberMap.begin();
     while (it != mSequenceLastFrameNumberMap.end()) {
         int sequenceId = it->first;
-        int64_t lastFrameNumber = it->second;
-        bool seqCompleted = false;
-        bool hasCallback  = true;
+        int64_t lastFrameNumber = it->second.lastFrameNumber;
+        bool hasCallback = true;
+
+        if (mRemote == nullptr) {
+            ALOGW("Camera %s closed while checking sequence complete", getId());
+            return;
+        }
+        ALOGV("%s: seq %d's last frame number %" PRId64 ", completed %" PRId64,
+                __FUNCTION__, sequenceId, lastFrameNumber, completedFrameNumber);
+        if (!it->second.isSequenceCompleted) {
+            // Check if there is callback for this sequence
+            // This should not happen because we always register callback (with nullptr inside)
+            if (mSequenceCallbackMap.count(sequenceId) == 0) {
+                ALOGW("No callback found for sequenceId %d", sequenceId);
+                hasCallback = false;
+            }
+
+            if (lastFrameNumber <= completedFrameNumber) {
+                ALOGV("Mark sequenceId %d as sequence completed", sequenceId);
+                it->second.isSequenceCompleted = true;
+            }
+
+            if (it->second.isSequenceCompleted && hasCallback) {
+                auto cbIt = mSequenceCallbackMap.find(sequenceId);
+                CallbackHolder cbh = cbIt->second;
+
+                // send seq complete callback
+                sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
+                msg->setPointer(kContextKey, cbh.mContext);
+                msg->setObject(kSessionSpKey, cbh.mSession);
+                msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
+                msg->setInt32(kSequenceIdKey, sequenceId);
+                msg->setInt64(kFrameNumberKey, lastFrameNumber);
+
+                // Clear the session sp before we send out the message
+                // This will guarantee the rare case where the message is processed
+                // before cbh goes out of scope and causing we call the session
+                // destructor while holding device lock
+                cbh.mSession.clear();
+                postSessionMsgAndCleanup(msg);
+            }
+        }
+
+        if (it->second.isSequenceCompleted && it->second.isInflightCompleted) {
+            if (mSequenceCallbackMap.find(sequenceId) != mSequenceCallbackMap.end()) {
+                mSequenceCallbackMap.erase(sequenceId);
+            }
+            it = mSequenceLastFrameNumberMap.erase(it);
+            ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
+        } else {
+            ++it;
+        }
+    }
+}
+
+void
+CameraDevice::removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber) {
+    auto it = mSequenceLastFrameNumberMap.begin();
+    while (it != mSequenceLastFrameNumberMap.end()) {
+        int sequenceId = it->first;
+        int64_t lastFrameNumber = it->second.lastFrameNumber;
 
         if (mRemote == nullptr) {
             ALOGW("Camera %s closed while checking sequence complete", getId());
             return;
         }
 
-        // Check if there is callback for this sequence
-        // This should not happen because we always register callback (with nullptr inside)
-        if (mSequenceCallbackMap.count(sequenceId) == 0) {
-            ALOGW("No callback found for sequenceId %d", sequenceId);
-            hasCallback = false;
-        }
+        ALOGV("%s: seq %d's last frame number %" PRId64
+                ", completed inflight frame number %" PRId64,
+                __FUNCTION__, sequenceId, lastFrameNumber,
+                lastCompletedRegularFrameNumber);
+        if (lastFrameNumber <= lastCompletedRegularFrameNumber) {
+            if (it->second.isSequenceCompleted) {
+                // Check if there is callback for this sequence
+                // This should not happen because we always register callback (with nullptr inside)
+                if (mSequenceCallbackMap.count(sequenceId) == 0) {
+                    ALOGW("No callback found for sequenceId %d", sequenceId);
+                } else {
+                    mSequenceCallbackMap.erase(sequenceId);
+                }
 
-        if (lastFrameNumber <= completedFrameNumber) {
-            ALOGV("seq %d reached last frame %" PRId64 ", completed %" PRId64,
-                    sequenceId, lastFrameNumber, completedFrameNumber);
-            seqCompleted = true;
-        }
-
-        if (seqCompleted && hasCallback) {
-            // remove callback holder from callback map
-            auto cbIt = mSequenceCallbackMap.find(sequenceId);
-            CallbackHolder cbh = cbIt->second;
-            mSequenceCallbackMap.erase(cbIt);
-            // send seq complete callback
-            sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
-            msg->setPointer(kContextKey, cbh.mContext);
-            msg->setObject(kSessionSpKey, cbh.mSession);
-            msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
-            msg->setInt32(kSequenceIdKey, sequenceId);
-            msg->setInt64(kFrameNumberKey, lastFrameNumber);
-
-            // Clear the session sp before we send out the message
-            // This will guarantee the rare case where the message is processed
-            // before cbh goes out of scope and causing we call the session
-            // destructor while holding device lock
-            cbh.mSession.clear();
-            postSessionMsgAndCleanup(msg);
-        }
-
-        // No need to track sequence complete if there is no callback registered
-        if (seqCompleted || !hasCallback) {
-            it = mSequenceLastFrameNumberMap.erase(it);
+                it = mSequenceLastFrameNumberMap.erase(it);
+                ALOGV("%s: Remove holder for sequenceId %d", __FUNCTION__, sequenceId);
+            } else {
+                ALOGV("Mark sequenceId %d as inflight completed", sequenceId);
+                it->second.isInflightCompleted = true;
+                ++it;
+            }
         } else {
             ++it;
         }
@@ -1479,6 +1521,9 @@
         return ret;
     }
 
+    dev->removeCompletedCallbackHolderLocked(
+             std::numeric_limits<int64_t>::max()/*lastCompletedRegularFrameNumber*/);
+
     if (dev->mIdle) {
         // Already in idle state. Possibly other thread did waitUntilIdle
         return ret;
@@ -1521,6 +1566,9 @@
         return ret;
     }
 
+    dev->removeCompletedCallbackHolderLocked(
+            resultExtras.lastCompletedRegularFrameNumber);
+
     int sequenceId = resultExtras.requestId;
     int32_t burstId = resultExtras.burstId;
 
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 6c2ceb3..d937865 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -267,8 +267,23 @@
     static const int REQUEST_ID_NONE = -1;
     int mRepeatingSequenceId = REQUEST_ID_NONE;
 
-    // sequence id -> last frame number map
-    std::map<int, int64_t> mSequenceLastFrameNumberMap;
+    // sequence id -> last frame number holder map
+    struct RequestLastFrameNumberHolder {
+        int64_t lastFrameNumber;
+        // Whether the current sequence is completed (capture results are
+        // generated). May be set to true, but
+        // not removed from the map if not all inflight requests in the sequence
+        // have been completed.
+        bool isSequenceCompleted = false;
+        // Whether all inflight requests in the sequence are completed
+        // (capture results and buffers are generated). May be
+        // set to true, but not removed from the map yet if the capture results
+        // haven't been delivered to the app yet.
+        bool isInflightCompleted = false;
+        RequestLastFrameNumberHolder(int64_t lastFN) :
+                lastFrameNumber(lastFN) {}
+    };
+    std::map<int, RequestLastFrameNumberHolder> mSequenceLastFrameNumberMap;
 
     struct CallbackHolder {
         CallbackHolder(sp<ACameraCaptureSession>          session,
@@ -338,6 +353,7 @@
 
     void checkRepeatingSequenceCompleteLocked(const int sequenceId, const int64_t lastFrameNumber);
     void checkAndFireSequenceCompleteLocked();
+    void removeCompletedCallbackHolderLocked(int64_t lastCompletedRegularFrameNumber);
 
     // Misc variables
     int32_t mShadingMapSize[2];   // const after constructor
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 9d40fd7..b58ebe2 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -32,8 +32,10 @@
 namespace acam {
 // Static member definitions
 const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
+const char* CameraManagerGlobal::kPhysicalCameraIdKey   = "PhysicalCameraId";
 const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
 const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
+const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
 Mutex                CameraManagerGlobal::sLock;
 CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
 
@@ -76,6 +78,10 @@
 
 sp<hardware::ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
+    return getCameraServiceLocked();
+}
+
+sp<hardware::ICameraService> CameraManagerGlobal::getCameraServiceLocked() {
     if (mCameraService.get() == nullptr) {
         if (isCameraServiceDisabled()) {
             return mCameraService;
@@ -112,7 +118,7 @@
                 return nullptr;
             }
             if (mHandler == nullptr) {
-                mHandler = new CallbackHandler();
+                mHandler = new CallbackHandler(this);
             }
             mCbLooper->registerHandler(mHandler);
         }
@@ -125,6 +131,11 @@
         mCameraService->addListener(mCameraServiceListener, &cameraStatuses);
         for (auto& c : cameraStatuses) {
             onStatusChangedLocked(c.status, c.cameraId);
+
+            for (auto& unavailablePhysicalId : c.unavailablePhysicalIds) {
+                onStatusChangedLocked(hardware::ICameraServiceListener::STATUS_NOT_PRESENT,
+                        c.cameraId, unavailablePhysicalId);
+            }
         }
 
         // setup vendor tags
@@ -195,20 +206,55 @@
 
 void CameraManagerGlobal::registerExtendedAvailabilityCallback(
         const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    mCallbacks.insert(cb);
+    return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
 }
 
 void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
         const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
     Mutex::Autolock _l(mLock);
+
+    drainPendingCallbacksLocked();
+
     Callback cb(callback);
     mCallbacks.erase(cb);
 }
 
 void CameraManagerGlobal::registerAvailabilityCallback(
         const ACameraManager_AvailabilityCallbacks *callback) {
+    return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
+}
+
+void CameraManagerGlobal::unregisterAvailabilityCallback(
+        const ACameraManager_AvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+
+    drainPendingCallbacksLocked();
+
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+void CameraManagerGlobal::onCallbackCalled() {
+    Mutex::Autolock _l(mLock);
+    if (mPendingCallbackCnt > 0) {
+        mPendingCallbackCnt--;
+    }
+    mCallbacksCond.signal();
+}
+
+void CameraManagerGlobal::drainPendingCallbacksLocked() {
+    while (mPendingCallbackCnt > 0) {
+        auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
+        if (res != NO_ERROR) {
+            ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
+                    __FUNCTION__, strerror(-res), res);
+            break;
+        }
+    }
+}
+
+template<class T>
+void CameraManagerGlobal::registerAvailCallback(const T *callback) {
     Mutex::Autolock _l(mLock);
     Callback cb(callback);
     auto pair = mCallbacks.insert(cb);
@@ -216,40 +262,67 @@
     if (pair.second) {
         for (auto& pair : mDeviceStatusMap) {
             const String8& cameraId = pair.first;
-            int32_t status = pair.second;
+            int32_t status = pair.second.getStatus();
+            // Don't send initial callbacks for camera ids which don't support
+            // camera2
+            if (!pair.second.supportsHAL3) {
+                continue;
+            }
 
+            // Camera available/unavailable callback
             sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-            ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
-                    callback->onCameraAvailable : callback->onCameraUnavailable;
-            msg->setPointer(kCallbackFpKey, (void *) cb);
-            msg->setPointer(kContextKey, callback->context);
+            ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+            msg->setPointer(kContextKey, cb.mContext);
             msg->setString(kCameraIdKey, AString(cameraId));
+            mPendingCallbackCnt++;
             msg->post();
+
+            // Physical camera unavailable callback
+            std::set<String8> unavailablePhysicalCameras =
+                    pair.second.getUnavailablePhysicalIds();
+            for (const auto& physicalCameraId : unavailablePhysicalCameras) {
+                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+                        cb.mPhysicalCamUnavailable;
+                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+                msg->setPointer(kContextKey, cb.mContext);
+                msg->setString(kCameraIdKey, AString(cameraId));
+                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+                mPendingCallbackCnt++;
+                msg->post();
+            }
         }
     }
 }
 
-void CameraManagerGlobal::unregisterAvailabilityCallback(
-        const ACameraManager_AvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    mCallbacks.erase(cb);
+bool CameraManagerGlobal::supportsCamera2ApiLocked(const String8 &cameraId) {
+    bool camera2Support = false;
+    auto cs = getCameraServiceLocked();
+    binder::Status serviceRet =
+        cs->supportsCameraApi(String16(cameraId),
+                hardware::ICameraService::API_VERSION_2, &camera2Support);
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId  %s",
+                __FUNCTION__, cameraId.c_str());
+        return false;
+    }
+    return camera2Support;
 }
 
 void CameraManagerGlobal::getCameraIdList(std::vector<String8>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
-    auto cs = getCameraService();
     Mutex::Autolock _l(mLock);
-
+    // Needed to make sure we're connected to cameraservice
+    getCameraServiceLocked();
     for(auto& deviceStatus : mDeviceStatusMap) {
-        if (deviceStatus.second == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
-                deviceStatus.second == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
+        int32_t status = deviceStatus.second.getStatus();
+        if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
+                status == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
             continue;
         }
-        bool camera2Support = false;
-        binder::Status serviceRet = cs->supportsCameraApi(String16(deviceStatus.first),
-                hardware::ICameraService::API_VERSION_2, &camera2Support);
-        if (!serviceRet.isOk() || !camera2Support) {
+        if (!deviceStatus.second.supportsHAL3) {
             continue;
         }
         cameraIds->push_back(deviceStatus.first);
@@ -278,6 +351,16 @@
 }
 
 void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+      const sp<AMessage> &msg) {
+    onMessageReceivedInternal(msg);
+    if (msg->what() == kWhatSendSingleCallback ||
+            msg->what() == kWhatSendSingleAccessCallback ||
+            msg->what() == kWhatSendSinglePhysicalCameraCallback) {
+        notifyParent();
+    }
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
         const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSendSingleCallback:
@@ -321,12 +404,52 @@
             (*cb)(context);
             break;
         }
+        case kWhatSendSinglePhysicalCameraCallback:
+        {
+            ACameraManager_PhysicalCameraAvailabilityCallback cb;
+            void* context;
+            AString cameraId;
+            AString physicalCameraId;
+            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+            if (!found) {
+                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+                return;
+            }
+            if (cb == nullptr) {
+                // Physical camera callback is null
+                return;
+            }
+            found = msg->findPointer(kContextKey, &context);
+            if (!found) {
+                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kCameraIdKey, &cameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
+                return;
+            }
+            (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
+            break;
+        }
         default:
             ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
             break;
     }
 }
 
+void CameraManagerGlobal::CallbackHandler::notifyParent() {
+    sp<CameraManagerGlobal> parent = mParent.promote();
+    if (parent != nullptr) {
+        parent->onCallbackCalled();
+    }
+}
+
 binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() {
     sp<CameraManagerGlobal> cm = mCameraManager.promote();
     if (cm != nullptr) {
@@ -348,6 +471,17 @@
     return binder::Status::ok();
 }
 
+binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+        int32_t status, const String16& cameraId, const String16& physicalCameraId) {
+    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+    if (cm != nullptr) {
+        cm->onStatusChanged(status, String8(cameraId), String8(physicalCameraId));
+    } else {
+        ALOGE("Cannot deliver physical camera status change. Global camera manager died");
+    }
+    return binder::Status::ok();
+}
+
 void CameraManagerGlobal::onCameraAccessPrioritiesChanged() {
     Mutex::Autolock _l(mLock);
     for (auto cb : mCallbacks) {
@@ -356,6 +490,7 @@
         if (cbFp != nullptr) {
             msg->setPointer(kCallbackFpKey, (void *) cbFp);
             msg->setPointer(kContextKey, cb.mContext);
+            mPendingCallbackCnt++;
             msg->post();
         }
     }
@@ -377,7 +512,7 @@
     bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
     int32_t oldStatus = firstStatus ?
             status : // first status
-            mDeviceStatusMap[cameraId];
+            mDeviceStatusMap[cameraId].getStatus();
 
     if (!firstStatus &&
             isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
@@ -385,22 +520,113 @@
         return;
     }
 
+    bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
+    if (firstStatus) {
+        mDeviceStatusMap.emplace(std::piecewise_construct,
+                std::forward_as_tuple(cameraId),
+                std::forward_as_tuple(status, supportsHAL3));
+    } else {
+        mDeviceStatusMap[cameraId].updateStatus(status);
+    }
     // Iterate through all registered callbacks
-    mDeviceStatusMap[cameraId] = status;
-    for (auto cb : mCallbacks) {
-        sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-        ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
-                cb.mAvailable : cb.mUnavailable;
-        msg->setPointer(kCallbackFpKey, (void *) cbFp);
-        msg->setPointer(kContextKey, cb.mContext);
-        msg->setString(kCameraIdKey, AString(cameraId));
-        msg->post();
+    if (supportsHAL3) {
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+            ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId));
+            mPendingCallbackCnt++;
+            msg->post();
+        }
     }
     if (status == hardware::ICameraServiceListener::STATUS_NOT_PRESENT) {
         mDeviceStatusMap.erase(cameraId);
     }
 }
 
+void CameraManagerGlobal::onStatusChanged(
+        int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+    Mutex::Autolock _l(mLock);
+    onStatusChangedLocked(status, cameraId, physicalCameraId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+        int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+    if (!validStatus(status)) {
+        ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+        return;
+    }
+
+    auto logicalStatus = mDeviceStatusMap.find(cameraId);
+    if (logicalStatus == mDeviceStatusMap.end()) {
+        ALOGE("%s: Physical camera id %s status change on a non-present id %s",
+                __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
+        return;
+    }
+    int32_t logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
+    if (logicalCamStatus != hardware::ICameraServiceListener::STATUS_PRESENT &&
+            logicalCamStatus != hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+        ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+                __FUNCTION__, physicalCameraId.string(), status, logicalCamStatus);
+        return;
+    }
+
+    bool supportsHAL3 = supportsCamera2ApiLocked(cameraId);
+
+    bool updated = false;
+    if (status == hardware::ICameraServiceListener::STATUS_PRESENT) {
+        updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
+    } else {
+        updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
+    }
+
+    // Iterate through all registered callbacks
+    if (supportsHAL3 && updated) {
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+            ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId));
+            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+            mPendingCallbackCnt++;
+            msg->post();
+        }
+    }
+}
+
+int32_t CameraManagerGlobal::StatusAndHAL3Support::getStatus() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return status;
+}
+
+void CameraManagerGlobal::StatusAndHAL3Support::updateStatus(int32_t newStatus) {
+    std::lock_guard<std::mutex> lock(mLock);
+    status = newStatus;
+}
+
+bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
+        const String8& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto result = unavailablePhysicalIds.insert(physicalCameraId);
+    return result.second;
+}
+
+bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
+        const String8& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto count = unavailablePhysicalIds.erase(physicalCameraId);
+    return count > 0;
+}
+
+std::set<String8> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return unavailablePhysicalIds;
+}
+
 } // namespace acam
 } // namespace android
 
@@ -517,7 +743,7 @@
     // No way to get package name from native.
     // Send a zero length package name and let camera service figure it out from UID
     binder::Status serviceRet = cs->connectDevice(
-            callbacks, String16(cameraId), String16(""),
+            callbacks, String16(cameraId), String16(""), std::unique_ptr<String16>(),
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 28fec82..ccbfaa9 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -66,9 +66,12 @@
 
   private:
     sp<hardware::ICameraService> mCameraService;
-    const int          kCameraServicePollDelay = 500000; // 0.5s
-    const char*        kCameraServiceName      = "media.camera";
-    Mutex              mLock;
+    const int                    kCameraServicePollDelay = 500000; // 0.5s
+    const char*                  kCameraServiceName      = "media.camera";
+    Mutex                        mLock;
+
+    template<class T>
+    void registerAvailCallback(const T *callback);
 
     class DeathNotifier : public IBinder::DeathRecipient {
       public:
@@ -85,6 +88,8 @@
       public:
         explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
         virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId);
+        virtual binder::Status onPhysicalCameraStatusChanged(int32_t status,
+                const String16& cameraId, const String16& physicalCameraId);
 
         // Torch API not implemented yet
         virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
@@ -110,18 +115,24 @@
             mAvailable(callback->onCameraAvailable),
             mUnavailable(callback->onCameraUnavailable),
             mAccessPriorityChanged(nullptr),
+            mPhysicalCamAvailable(nullptr),
+            mPhysicalCamUnavailable(nullptr),
             mContext(callback->context) {}
 
         explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) :
             mAvailable(callback->availabilityCallbacks.onCameraAvailable),
             mUnavailable(callback->availabilityCallbacks.onCameraUnavailable),
             mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged),
+            mPhysicalCamAvailable(callback->onPhysicalCameraAvailable),
+            mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable),
             mContext(callback->availabilityCallbacks.context) {}
 
         bool operator == (const Callback& other) const {
             return (mAvailable == other.mAvailable &&
                     mUnavailable == other.mUnavailable &&
                     mAccessPriorityChanged == other.mAccessPriorityChanged &&
+                    mPhysicalCamAvailable == other.mPhysicalCamAvailable &&
+                    mPhysicalCamUnavailable == other.mPhysicalCamUnavailable &&
                     mContext == other.mContext);
         }
         bool operator != (const Callback& other) const {
@@ -130,6 +141,12 @@
         bool operator < (const Callback& other) const {
             if (*this == other) return false;
             if (mContext != other.mContext) return mContext < other.mContext;
+            if (mPhysicalCamAvailable != other.mPhysicalCamAvailable) {
+                return mPhysicalCamAvailable < other.mPhysicalCamAvailable;
+            }
+            if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable) {
+                return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable;
+            }
             if (mAccessPriorityChanged != other.mAccessPriorityChanged) {
                 return mAccessPriorityChanged < other.mAccessPriorityChanged;
             }
@@ -142,32 +159,53 @@
         ACameraManager_AvailabilityCallback mAvailable;
         ACameraManager_AvailabilityCallback mUnavailable;
         ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
         void*                               mContext;
     };
+
+    android::Condition mCallbacksCond;
+    size_t mPendingCallbackCnt = 0;
+    void onCallbackCalled();
+    void drainPendingCallbacksLocked();
+
     std::set<Callback> mCallbacks;
 
     // definition of handler and message
     enum {
         kWhatSendSingleCallback,
         kWhatSendSingleAccessCallback,
+        kWhatSendSinglePhysicalCameraCallback,
     };
     static const char* kCameraIdKey;
+    static const char* kPhysicalCameraIdKey;
     static const char* kCallbackFpKey;
     static const char* kContextKey;
+    static const nsecs_t kCallbackDrainTimeout;
     class CallbackHandler : public AHandler {
       public:
-        CallbackHandler() {}
+        CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
         void onMessageReceived(const sp<AMessage> &msg) override;
+
+      private:
+        wp<CameraManagerGlobal> mParent;
+        void notifyParent();
+        void onMessageReceivedInternal(const sp<AMessage> &msg);
     };
     sp<CallbackHandler> mHandler;
     sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
 
+    sp<hardware::ICameraService> getCameraServiceLocked();
     void onCameraAccessPrioritiesChanged();
     void onStatusChanged(int32_t status, const String8& cameraId);
     void onStatusChangedLocked(int32_t status, const String8& cameraId);
+    void onStatusChanged(int32_t status, const String8& cameraId, const String8& physicalCameraId);
+    void onStatusChangedLocked(int32_t status, const String8& cameraId,
+           const String8& physicalCameraId);
     // Utils for status
     static bool validStatus(int32_t status);
     static bool isStatusAvailable(int32_t status);
+    bool supportsCamera2ApiLocked(const String8 &cameraId);
 
     // The sort logic must match the logic in
     // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
@@ -190,8 +228,26 @@
         }
     };
 
+    struct StatusAndHAL3Support {
+      private:
+        int32_t status = hardware::ICameraServiceListener::STATUS_NOT_PRESENT;
+        mutable std::mutex mLock;
+        std::set<String8> unavailablePhysicalIds;
+      public:
+        const bool supportsHAL3 = false;
+        StatusAndHAL3Support(int32_t st, bool HAL3support):
+                status(st), supportsHAL3(HAL3support) { };
+        StatusAndHAL3Support() = default;
+
+        bool addUnavailablePhysicalId(const String8& physicalCameraId);
+        bool removeUnavailablePhysicalId(const String8& physicalCameraId);
+        int32_t getStatus();
+        void updateStatus(int32_t newStatus);
+        std::set<String8> getUnavailablePhysicalIds();
+    };
+
     // Map camera_id -> status
-    std::map<String8, int32_t, CameraIdComparator> mDeviceStatusMap;
+    std::map<String8, StatusAndHAL3Support, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 77dcd48..bfa60d9 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -28,7 +28,28 @@
  * ACameraMetadata Implementation
  */
 ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
-        mData(buffer), mType(type) {
+        mData(std::make_shared<CameraMetadata>(buffer)),
+        mType(type) {
+    init();
+}
+
+ACameraMetadata::ACameraMetadata(const std::shared_ptr<CameraMetadata>& cameraMetadata,
+        ACAMERA_METADATA_TYPE type) :
+        mData(cameraMetadata),
+        mType(type) {
+    init();
+}
+
+ACameraMetadata::ACameraMetadata(const ACameraMetadata& other) :
+        mData(std::make_shared<CameraMetadata>(*(other.mData))),
+        mType(other.mType) {
+}
+
+ACameraMetadata::~ACameraMetadata() {
+}
+
+void
+ACameraMetadata::init() {
     if (mType == ACM_CHARACTERISTICS) {
         filterUnsupportedFeatures();
         filterStreamConfigurations();
@@ -61,7 +82,7 @@
 void
 ACameraMetadata::filterUnsupportedFeatures() {
     // Hide unsupported capabilities (reprocessing)
-    camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    camera_metadata_entry entry = mData->find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
     if (entry.count == 0 || entry.type != TYPE_BYTE) {
         ALOGE("%s: malformed available capability key! count %zu, type %d",
                 __FUNCTION__, entry.count, entry.type);
@@ -80,7 +101,7 @@
             }
         }
     }
-    mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
+    mData->update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
 }
 
 void
@@ -118,12 +139,20 @@
     const int STREAM_WIDTH_OFFSET = 1;
     const int STREAM_HEIGHT_OFFSET = 2;
     const int STREAM_DURATION_OFFSET = 3;
-    camera_metadata_entry entry = mData.find(tag);
-    if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT64) {
+
+    camera_metadata_entry entry = mData->find(tag);
+
+    if (entry.count == 0) {
+        // Duration keys can be missing when corresponding capture feature is not supported
+        return;
+    }
+
+    if (entry.count % 4 || entry.type != TYPE_INT64) {
         ALOGE("%s: malformed duration key %d! count %zu, type %d",
                 __FUNCTION__, tag, entry.count, entry.type);
         return;
     }
+
     Vector<int64_t> filteredDurations;
     filteredDurations.setCapacity(entry.count * 2);
 
@@ -194,7 +223,7 @@
         }
     }
 
-    mData.update(tag, filteredDurations);
+    mData->update(tag, filteredDurations);
 }
 
 void
@@ -204,7 +233,7 @@
     const int STREAM_WIDTH_OFFSET = 1;
     const int STREAM_HEIGHT_OFFSET = 2;
     const int STREAM_IS_INPUT_OFFSET = 3;
-    camera_metadata_entry entry = mData.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+    camera_metadata_entry entry = mData->find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
     if (entry.count > 0 && (entry.count % 4 || entry.type != TYPE_INT32)) {
         ALOGE("%s: malformed available stream configuration key! count %zu, type %d",
                 __FUNCTION__, entry.count, entry.type);
@@ -234,10 +263,10 @@
     }
 
     if (filteredStreamConfigs.size() > 0) {
-        mData.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
+        mData->update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
     }
 
-    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
+    entry = mData->find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
     if (entry.count > 0 && (entry.count % 4 || entry.type != TYPE_INT32)) {
         ALOGE("%s: malformed available depth stream configuration key! count %zu, type %d",
                 __FUNCTION__, entry.count, entry.type);
@@ -270,11 +299,11 @@
     }
 
     if (filteredDepthStreamConfigs.size() > 0) {
-        mData.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
+        mData->update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
                 filteredDepthStreamConfigs);
     }
 
-    entry = mData.find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
+    entry = mData->find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
     Vector<int32_t> filteredHeicStreamConfigs;
     filteredHeicStreamConfigs.setCapacity(entry.count);
 
@@ -297,9 +326,9 @@
         filteredHeicStreamConfigs.push_back(height);
         filteredHeicStreamConfigs.push_back(isInput);
     }
-    mData.update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
+    mData->update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
 
-    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
+    entry = mData->find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
     Vector<int32_t> filteredDynamicDepthStreamConfigs;
     filteredDynamicDepthStreamConfigs.setCapacity(entry.count);
 
@@ -322,7 +351,7 @@
         filteredDynamicDepthStreamConfigs.push_back(height);
         filteredDynamicDepthStreamConfigs.push_back(isInput);
     }
-    mData.update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+    mData->update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
             filteredDynamicDepthStreamConfigs);
 }
 
@@ -343,7 +372,7 @@
 
     Mutex::Autolock _l(mLock);
 
-    camera_metadata_ro_entry rawEntry = mData.find(tag);
+    camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData.get())->find(tag);
     if (rawEntry.count == 0) {
         ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
         return ACAMERA_ERROR_METADATA_NOT_FOUND;
@@ -390,9 +419,9 @@
                          /*out*/const uint32_t** tags) const {
     Mutex::Autolock _l(mLock);
     if (mTags.size() == 0) {
-        size_t entry_count = mData.entryCount();
+        size_t entry_count = mData->entryCount();
         mTags.setCapacity(entry_count);
-        const camera_metadata_t* rawMetadata = mData.getAndLock();
+        const camera_metadata_t* rawMetadata = mData->getAndLock();
         for (size_t i = 0; i < entry_count; i++) {
             camera_metadata_ro_entry_t entry;
             int ret = get_camera_metadata_ro_entry(rawMetadata, i, &entry);
@@ -405,7 +434,7 @@
                 mTags.push_back(entry.tag);
             }
         }
-        mData.unlock(rawMetadata);
+        mData->unlock(rawMetadata);
     }
 
     *numTags = mTags.size();
@@ -415,7 +444,7 @@
 
 const CameraMetadata&
 ACameraMetadata::getInternalData() const {
-    return mData;
+    return (*mData);
 }
 
 bool
@@ -479,6 +508,8 @@
         case ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE:
         case ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST:
         case ACAMERA_CONTROL_ENABLE_ZSL:
+        case ACAMERA_CONTROL_EXTENDED_SCENE_MODE:
+        case ACAMERA_CONTROL_ZOOM_RATIO:
         case ACAMERA_EDGE_MODE:
         case ACAMERA_FLASH_MODE:
         case ACAMERA_HOT_PIXEL_MODE:
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index 97f7f48..084a60b 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -18,6 +18,7 @@
 
 #include <unordered_set>
 #include <vector>
+#include <memory>
 
 #include <sys/types.h>
 #include <utils/Mutex.h>
@@ -36,8 +37,8 @@
 using namespace android;
 
 /**
- * ACameraMetadata opaque struct definition
- * Leave outside of android namespace because it's NDK struct
+ * ACameraMetadata is an opaque struct definition.
+ * It is intentionally left outside of the android namespace because it's NDK struct.
  */
 struct ACameraMetadata : public RefBase {
   public:
@@ -47,11 +48,19 @@
         ACM_RESULT,          // Read only
     } ACAMERA_METADATA_TYPE;
 
-    // Takes ownership of pass-in buffer
-    ACameraMetadata(camera_metadata_t *buffer, ACAMERA_METADATA_TYPE type);
-    // Clone
-    ACameraMetadata(const ACameraMetadata& other) :
-            mData(other.mData), mType(other.mType) {};
+    // Constructs a ACameraMetadata that takes ownership of `buffer`.
+    ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type);
+
+    // Constructs a ACameraMetadata that shares its data with something else, like a Java object
+    ACameraMetadata(const std::shared_ptr<CameraMetadata>& cameraMetadata,
+            ACAMERA_METADATA_TYPE type);
+
+    // Copy constructor.
+    //
+    // Always makes a deep copy.
+    ACameraMetadata(const ACameraMetadata& other);
+
+    ~ACameraMetadata();
 
     camera_status_t getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const;
 
@@ -70,6 +79,9 @@
 
   private:
 
+    // Common code called by constructors.
+    void init();
+
     // This function does not check whether the capability passed to it is valid.
     // The caller must make sure that it is.
     bool isNdkSupportedCapability(const int32_t capability);
@@ -95,11 +107,11 @@
 
         status_t ret = OK;
         if (count == 0 && data == nullptr) {
-            ret = mData.erase(tag);
+            ret = mData->erase(tag);
         } else {
             // Here we have to use reinterpret_cast because the NDK data type is
             // exact copy of internal data type but they do not inherit from each other
-            ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
+            ret = mData->update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
         }
 
         if (ret == OK) {
@@ -110,10 +122,12 @@
         }
     }
 
-    // guard access of public APIs: get/update/getTags
-    mutable Mutex    mLock;
-    CameraMetadata   mData;
-    mutable Vector<uint32_t> mTags; // updated in getTags, cleared by update
+    // Guard access of public APIs: get/update/getTags.
+    mutable Mutex mLock;
+
+    std::shared_ptr<CameraMetadata> mData;
+
+    mutable Vector<uint32_t> mTags; // Updated by `getTags()`, cleared by `update()`.
     const ACAMERA_METADATA_TYPE mType;
 
     static std::unordered_set<uint32_t> sSystemTags;
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index 2cc8a97..0a2ee57 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -123,6 +123,21 @@
         const char* cameraId);
 
 /**
+ * Definition of physical camera availability callbacks.
+ *
+ * @param context The optional application context provided by user in
+ *                {@link ACameraManager_AvailabilityCallbacks}.
+ * @param cameraId The ID of the logical multi-camera device whose physical camera status is
+ *                 changing. The memory of this argument is owned by camera framework and will
+ *                 become invalid immediately after this callback returns.
+ * @param physicalCameraId The ID of the physical camera device whose status is changing. The
+ *                 memory of this argument is owned by camera framework and will become invalid
+ *                 immediately after this callback returns.
+ */
+typedef void (*ACameraManager_PhysicalCameraAvailabilityCallback)(void* context,
+        const char* cameraId, const char* physicalCameraId);
+
+/**
  * A listener for camera devices becoming available or unavailable to open.
  *
  * <p>Cameras become available when they are no longer in use, or when a new
@@ -176,6 +191,9 @@
  *
  * <p>Removing a callback that isn't registered has no effect.</p>
  *
+ * <p>This function must not be called with a mutex lock also held by
+ * the availability callbacks.</p>
+ *
  * @param manager the {@link ACameraManager} of interest.
  * @param callback the {@link ACameraManager_AvailabilityCallbacks} to be unregistered.
  *
@@ -320,8 +338,15 @@
     /// Called when there is camera access permission change
     ACameraManager_AccessPrioritiesChangedCallback onCameraAccessPrioritiesChanged;
 
+    /// Called when a physical camera becomes available
+    ACameraManager_PhysicalCameraAvailabilityCallback onPhysicalCameraAvailable __INTRODUCED_IN(30);
+
+    /// Called when a physical camera becomes unavailable
+    ACameraManager_PhysicalCameraAvailabilityCallback onPhysicalCameraUnavailable
+            __INTRODUCED_IN(30);
+
     /// Reserved for future use, please ensure that all entries are set to NULL
-    void *reserved[6];
+    void *reserved[4];
 } ACameraManager_ExtendedAvailabilityCallbacks;
 
 /**
@@ -360,6 +385,9 @@
  *
  * <p>Removing a callback that isn't registered has no effect.</p>
  *
+ * <p>This function must not be called with a mutex lock also held by
+ * the extended availability callbacks.</p>
+ *
  * @param manager the {@link ACameraManager} of interest.
  * @param callback the {@link ACameraManager_ExtendedAvailabilityCallbacks} to be unregistered.
  *
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index 9bbfb83..072bb02 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -39,6 +39,12 @@
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+#ifndef __ANDROID_VNDK__
+#if __ANDROID_API__ >= 30
+#include "jni.h"
+#endif  /* __ANDROID_API__ >= 30 */
+#endif  /* __ANDROID_VNDK__ */
+
 #include "NdkCameraError.h"
 #include "NdkCameraMetadataTags.h"
 
@@ -255,6 +261,37 @@
 
 #endif /* __ANDROID_API__ >= 29 */
 
+#ifndef __ANDROID_VNDK__
+#if __ANDROID_API__ >= 30
+
+/**
+ * Return a {@link ACameraMetadata} that references the same data as
+ * {@link cameraMetadata}, which is an instance of
+ * {@link android.hardware.camera2.CameraMetadata} (e.g., a
+ * {@link android.hardware.camera2.CameraCharacteristics} or
+ * {@link android.hardware.camera2.CaptureResult}).
+ *
+ * <p>The returned ACameraMetadata must be freed by the application by {@link ACameraMetadata_free}
+ * after application is done using it.</p>
+ *
+ * <p>The ACameraMetadata maintains a reference count to the underlying data, so
+ * it can be used independently of the Java object, and it remains valid even if
+ * the Java metadata is garbage collected.
+ *
+ * @param env the JNI environment.
+ * @param cameraMetadata the source {@link android.hardware.camera2.CameraMetadata} from which the
+ *                       returned {@link ACameraMetadata} is a view.
+ *
+ * @return a valid ACameraMetadata pointer or NULL if {@link cameraMetadata} is null or not a valid
+ *         instance of {@link android.hardware.camera2.CameraMetadata}.
+ *
+ */
+ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata)
+        __INTRODUCED_IN(30);
+
+#endif /* __ANDROID_API__ >= 30 */
+#endif  /* __ANDROID_VNDK__ */
+
 __END_DECLS
 
 #endif /* _NDK_CAMERA_METADATA_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 8dd6e00..1354fce 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -140,7 +140,7 @@
      * application controls how the color mapping is performed.</p>
      * <p>We define the expected processing pipeline below. For consistency
      * across devices, this is always the case with TRANSFORM_MATRIX.</p>
-     * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+     * <p>When either FAST or HIGH_QUALITY is used, the camera device may
      * do additional processing but ACAMERA_COLOR_CORRECTION_GAINS and
      * ACAMERA_COLOR_CORRECTION_TRANSFORM will still be provided by the
      * camera device (in the results) and be roughly correct.</p>
@@ -518,11 +518,22 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>Starting from API level 30, the coordinate system of activeArraySize or
+     * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not
+     * pre-zoom field of view. This means that the same aeRegions values at different
+     * ACAMERA_CONTROL_ZOOM_RATIO represent different parts of the scene. The aeRegions
+     * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+     * zoomed field of view. If ACAMERA_CONTROL_ZOOM_RATIO is set to 1.0 (default), the same
+     * aeRegions at different ACAMERA_SCALER_CROP_REGION still represent the same parts of the
+     * scene as they do before. See ACAMERA_CONTROL_ZOOM_RATIO for details. Whether to use
+     * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+     * mode.</p>
      * <p>The data representation is <code>int[5 * area_count]</code>.
      * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
      * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
      * ymax.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -698,11 +709,22 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata. If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>Starting from API level 30, the coordinate system of activeArraySize or
+     * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not
+     * pre-zoom field of view. This means that the same afRegions values at different
+     * ACAMERA_CONTROL_ZOOM_RATIO represent different parts of the scene. The afRegions
+     * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+     * zoomed field of view. If ACAMERA_CONTROL_ZOOM_RATIO is set to 1.0 (default), the same
+     * afRegions at different ACAMERA_SCALER_CROP_REGION still represent the same parts of the
+     * scene as they do before. See ACAMERA_CONTROL_ZOOM_RATIO for details. Whether to use
+     * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+     * mode.</p>
      * <p>The data representation is <code>int[5 * area_count]</code>.
      * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
      * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
      * ymax.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -873,11 +895,22 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
+     * <p>Starting from API level 30, the coordinate system of activeArraySize or
+     * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not
+     * pre-zoom field of view. This means that the same awbRegions values at different
+     * ACAMERA_CONTROL_ZOOM_RATIO represent different parts of the scene. The awbRegions
+     * coordinates are relative to the activeArray/preCorrectionActiveArray representing the
+     * zoomed field of view. If ACAMERA_CONTROL_ZOOM_RATIO is set to 1.0 (default), the same
+     * awbRegions at different ACAMERA_SCALER_CROP_REGION still represent the same parts of
+     * the scene as they do before. See ACAMERA_CONTROL_ZOOM_RATIO for details. Whether to use
+     * activeArraySize or preCorrectionActiveArraySize still depends on distortion correction
+     * mode.</p>
      * <p>The data representation is <code>int[5 * area_count]</code>.
      * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
      * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
      * ymax.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -951,10 +984,10 @@
      * capture parameters itself.</p>
      * <p>When set to AUTO, the individual algorithm controls in
      * ACAMERA_CONTROL_* are in effect, such as ACAMERA_CONTROL_AF_MODE.</p>
-     * <p>When set to USE_SCENE_MODE, the individual controls in
+     * <p>When set to USE_SCENE_MODE or USE_EXTENDED_SCENE_MODE, the individual controls in
      * ACAMERA_CONTROL_* are mostly disabled, and the camera device
-     * implements one of the scene mode settings (such as ACTION,
-     * SUNSET, or PARTY) as it wishes. The camera device scene mode
+     * implements one of the scene mode or extended scene mode settings (such as ACTION,
+     * SUNSET, PARTY, or BOKEH) as it wishes. The camera device scene mode
      * 3A settings are provided by {@link ACameraCaptureSession_captureCallback_result capture results}.</p>
      * <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
      * is that this frame will not be used by camera device background 3A statistics
@@ -1126,10 +1159,17 @@
      * </ul>
      * <p>For devices at the LIMITED level or above:</p>
      * <ul>
-     * <li>For YUV_420_888 burst capture use case, this list will always include (<code>min</code>, <code>max</code>)
-     * and (<code>max</code>, <code>max</code>) where <code>min</code> &lt;= 15 and <code>max</code> = the maximum output frame rate of the
+     * <li>For devices that advertise NIR color filter arrangement in
+     * ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT, this list will always include
+     * (<code>max</code>, <code>max</code>) where <code>max</code> = the maximum output frame rate of the maximum YUV_420_888
+     * output size.</li>
+     * <li>For devices advertising any color filter arrangement other than NIR, or devices not
+     * advertising color filter arrangement, this list will always include (<code>min</code>, <code>max</code>) and
+     * (<code>max</code>, <code>max</code>) where <code>min</code> &lt;= 15 and <code>max</code> = the maximum output frame rate of the
      * maximum YUV_420_888 output size.</li>
      * </ul>
+     *
+     * @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
      */
     ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES =            // int32[2*n]
             ACAMERA_CONTROL_START + 20,
@@ -1304,7 +1344,7 @@
     /**
      * <p>List of the maximum number of regions that can be used for metering in
      * auto-exposure (AE), auto-white balance (AWB), and auto-focus (AF);
-     * this corresponds to the the maximum number of elements in
+     * this corresponds to the maximum number of elements in
      * ACAMERA_CONTROL_AE_REGIONS, ACAMERA_CONTROL_AWB_REGIONS,
      * and ACAMERA_CONTROL_AF_REGIONS.</p>
      *
@@ -1727,6 +1767,204 @@
      */
     ACAMERA_CONTROL_AF_SCENE_CHANGE =                           // byte (acamera_metadata_enum_android_control_af_scene_change_t)
             ACAMERA_CONTROL_START + 42,
+    /**
+     * <p>The list of extended scene modes for ACAMERA_CONTROL_EXTENDED_SCENE_MODE that are supported
+     * by this camera device, and each extended scene mode's maximum streaming (non-stall) size
+     * with  effect.</p>
+     *
+     * @see ACAMERA_CONTROL_EXTENDED_SCENE_MODE
+     *
+     * <p>Type: int32[3*n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>For DISABLED mode, the camera behaves normally with no extended scene mode enabled.</p>
+     * <p>For BOKEH_STILL_CAPTURE mode, the maximum streaming dimension specifies the limit
+     * under which bokeh is effective when capture intent is PREVIEW. Note that when capture
+     * intent is PREVIEW, the bokeh effect may not be as high in quality compared to
+     * STILL_CAPTURE intent in order to maintain reasonable frame rate. The maximum streaming
+     * dimension must be one of the YUV_420_888 or PRIVATE resolutions in
+     * availableStreamConfigurations, or (0, 0) if preview bokeh is not supported. If the
+     * application configures a stream larger than the maximum streaming dimension, bokeh
+     * effect may not be applied for this stream for PREVIEW intent.</p>
+     * <p>For BOKEH_CONTINUOUS mode, the maximum streaming dimension specifies the limit under
+     * which bokeh is effective. This dimension must be one of the YUV_420_888 or PRIVATE
+     * resolutions in availableStreamConfigurations, and if the sensor maximum resolution is
+     * larger than or equal to 1080p, the maximum streaming dimension must be at least 1080p.
+     * If the application configures a stream with larger dimension, the stream may not have
+     * bokeh effect applied.</p>
+     */
+    ACAMERA_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES =   // int32[3*n]
+            ACAMERA_CONTROL_START + 43,
+    /**
+     * <p>The ranges of supported zoom ratio for non-DISABLED ACAMERA_CONTROL_EXTENDED_SCENE_MODE.</p>
+     *
+     * @see ACAMERA_CONTROL_EXTENDED_SCENE_MODE
+     *
+     * <p>Type: float[2*n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>When extended scene mode is set, the camera device may have limited range of zoom ratios
+     * compared to when extended scene mode is DISABLED. This tag lists the zoom ratio ranges
+     * for all supported non-DISABLED extended scene modes, in the same order as in
+     * android.control.availableExtended.</p>
+     * <p>Range [1.0, 1.0] means that no zoom (optical or digital) is supported.</p>
+     */
+    ACAMERA_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES = 
+                                                                // float[2*n]
+            ACAMERA_CONTROL_START + 44,
+    /**
+     * <p>Whether extended scene mode is enabled for a particular capture request.</p>
+     *
+     * <p>Type: byte (acamera_metadata_enum_android_control_extended_scene_mode_t)</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul></p>
+     *
+     * <p>With bokeh mode, the camera device may blur out the parts of scene that are not in
+     * focus, creating a bokeh (or shallow depth of field) effect for people or objects.</p>
+     * <p>When set to BOKEH_STILL_CAPTURE mode with STILL_CAPTURE capture intent, due to the extra
+     * processing needed for high quality bokeh effect, the stall may be longer than when
+     * capture intent is not STILL_CAPTURE.</p>
+     * <p>When set to BOKEH_STILL_CAPTURE mode with PREVIEW capture intent,</p>
+     * <ul>
+     * <li>If the camera device has BURST_CAPTURE capability, the frame rate requirement of
+     * BURST_CAPTURE must still be met.</li>
+     * <li>All streams not larger than the maximum streaming dimension for BOKEH_STILL_CAPTURE mode
+     * (queried via {@link ACAMERA_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_CAPABILITIES })
+     * will have preview bokeh effect applied.</li>
+     * </ul>
+     * <p>When set to BOKEH_CONTINUOUS mode, configured streams dimension should not exceed this mode's
+     * maximum streaming dimension in order to have bokeh effect applied. Bokeh effect may not
+     * be available for streams larger than the maximum streaming dimension.</p>
+     * <p>Switching between different extended scene modes may involve reconfiguration of the camera
+     * pipeline, resulting in long latency. The application should check this key against the
+     * available session keys queried via
+     * {@link ACameraManager_getCameraCharacteristics }.</p>
+     * <p>For a logical multi-camera, bokeh may be implemented by stereo vision from sub-cameras
+     * with different field of view. As a result, when bokeh mode is enabled, the camera device
+     * may override ACAMERA_SCALER_CROP_REGION or ACAMERA_CONTROL_ZOOM_RATIO, and the field of
+     * view may be smaller than when bokeh mode is off.</p>
+     *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
+     * @see ACAMERA_SCALER_CROP_REGION
+     */
+    ACAMERA_CONTROL_EXTENDED_SCENE_MODE =                       // byte (acamera_metadata_enum_android_control_extended_scene_mode_t)
+            ACAMERA_CONTROL_START + 45,
+    /**
+     * <p>Minimum and maximum zoom ratios supported by this camera device.</p>
+     *
+     * <p>Type: float[2]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>If the camera device supports zoom-out from 1x zoom, minZoom will be less than 1.0, and
+     * setting ACAMERA_CONTROL_ZOOM_RATIO to values less than 1.0 increases the camera's field
+     * of view.</p>
+     *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
+     */
+    ACAMERA_CONTROL_ZOOM_RATIO_RANGE =                          // float[2]
+            ACAMERA_CONTROL_START + 46,
+    /**
+     * <p>The desired zoom ratio</p>
+     *
+     * <p>Type: float</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul></p>
+     *
+     * <p>Instead of using ACAMERA_SCALER_CROP_REGION for zoom, the application can now choose to
+     * use this tag to specify the desired zoom level.</p>
+     * <p>By using this control, the application gains a simpler way to control zoom, which can
+     * be a combination of optical and digital zoom. For example, a multi-camera system may
+     * contain more than one lens with different focal lengths, and the user can use optical
+     * zoom by switching between lenses. Using zoomRatio has benefits in the scenarios below:</p>
+     * <ul>
+     * <li>Zooming in from a wide-angle lens to a telephoto lens: A floating-point ratio provides
+     *   better precision compared to an integer value of ACAMERA_SCALER_CROP_REGION.</li>
+     * <li>Zooming out from a wide lens to an ultrawide lens: zoomRatio supports zoom-out whereas
+     *   ACAMERA_SCALER_CROP_REGION doesn't.</li>
+     * </ul>
+     * <p>To illustrate, here are several scenarios of different zoom ratios, crop regions,
+     * and output streams, for a hypothetical camera device with an active array of size
+     * <code>(2000,1500)</code>.</p>
+     * <ul>
+     * <li>Camera Configuration:<ul>
+     * <li>Active array size: <code>2000x1500</code> (3 MP, 4:3 aspect ratio)</li>
+     * <li>Output stream #1: <code>640x480</code> (VGA, 4:3 aspect ratio)</li>
+     * <li>Output stream #2: <code>1280x720</code> (720p, 16:9 aspect ratio)</li>
+     * </ul>
+     * </li>
+     * <li>Case #1: 4:3 crop region with 2.0x zoom ratio<ul>
+     * <li>Zoomed field of view: 1/4 of original field of view</li>
+     * <li>Crop region: <code>Rect(0, 0, 2000, 1500) // (left, top, right, bottom)</code> (post zoom)</li>
+     * </ul>
+     * </li>
+     * <li><img alt="4:3 aspect ratio crop diagram" src="../images/camera2/metadata/android.control.zoomRatio/zoom-ratio-2-crop-43.png" /><ul>
+     * <li><code>640x480</code> stream source area: <code>(0, 0, 2000, 1500)</code> (equal to crop region)</li>
+     * <li><code>1280x720</code> stream source area: <code>(0, 187, 2000, 1312)</code> (letterboxed)</li>
+     * </ul>
+     * </li>
+     * <li>Case #2: 16:9 crop region with 2.0x zoom.<ul>
+     * <li>Zoomed field of view: 1/4 of original field of view</li>
+     * <li>Crop region: <code>Rect(0, 187, 2000, 1312)</code></li>
+     * <li><img alt="16:9 aspect ratio crop diagram" src="../images/camera2/metadata/android.control.zoomRatio/zoom-ratio-2-crop-169.png" /></li>
+     * <li><code>640x480</code> stream source area: <code>(250, 187, 1750, 1312)</code> (pillarboxed)</li>
+     * <li><code>1280x720</code> stream source area: <code>(0, 187, 2000, 1312)</code> (equal to crop region)</li>
+     * </ul>
+     * </li>
+     * <li>Case #3: 1:1 crop region with 0.5x zoom out to ultrawide lens.<ul>
+     * <li>Zoomed field of view: 4x of original field of view (switched from wide lens to ultrawide lens)</li>
+     * <li>Crop region: <code>Rect(250, 0, 1750, 1500)</code></li>
+     * <li><img alt="1:1 aspect ratio crop diagram" src="../images/camera2/metadata/android.control.zoomRatio/zoom-ratio-0.5-crop-11.png" /></li>
+     * <li><code>640x480</code> stream source area: <code>(250, 187, 1750, 1312)</code> (letterboxed)</li>
+     * <li><code>1280x720</code> stream source area: <code>(250, 328, 1750, 1172)</code> (letterboxed)</li>
+     * </ul>
+     * </li>
+     * </ul>
+     * <p>As seen from the graphs above, the coordinate system of cropRegion now changes to the
+     * effective after-zoom field-of-view, and is represented by the rectangle of (0, 0,
+     * activeArrayWith, activeArrayHeight). The same applies to AE/AWB/AF regions, and faces.
+     * This coordinate system change isn't applicable to RAW capture and its related
+     * metadata such as intrinsicCalibration and lensShadingMap.</p>
+     * <p>Using the same hypothetical example above, and assuming output stream #1 (640x480) is
+     * the viewfinder stream, the application can achieve 2.0x zoom in one of two ways:</p>
+     * <ul>
+     * <li>zoomRatio = 2.0, scaler.cropRegion = (0, 0, 2000, 1500)</li>
+     * <li>zoomRatio = 1.0 (default), scaler.cropRegion = (500, 375, 1500, 1125)</li>
+     * </ul>
+     * <p>If the application intends to set aeRegions to be top-left quarter of the viewfinder
+     * field-of-view, the ACAMERA_CONTROL_AE_REGIONS should be set to (0, 0, 1000, 750) with
+     * zoomRatio set to 2.0. Alternatively, the application can set aeRegions to the equivalent
+     * region of (500, 375, 1000, 750) for zoomRatio of 1.0. If the application doesn't
+     * explicitly set ACAMERA_CONTROL_ZOOM_RATIO, its value defaults to 1.0.</p>
+     * <p>One limitation of controlling zoom using zoomRatio is that the ACAMERA_SCALER_CROP_REGION
+     * must only be used for letterboxing or pillarboxing of the sensor active array, and no
+     * FREEFORM cropping can be used with ACAMERA_CONTROL_ZOOM_RATIO other than 1.0.</p>
+     *
+     * @see ACAMERA_CONTROL_AE_REGIONS
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
+     * @see ACAMERA_SCALER_CROP_REGION
+     */
+    ACAMERA_CONTROL_ZOOM_RATIO =                                // float
+            ACAMERA_CONTROL_START + 47,
     ACAMERA_CONTROL_END,
 
     /**
@@ -2195,8 +2433,11 @@
      * frames before the lens can change to the requested focal length.
      * While the focal length is still changing, ACAMERA_LENS_STATE will
      * be set to MOVING.</p>
-     * <p>Optical zoom will not be supported on most devices.</p>
+     * <p>Optical zoom via this control will not be supported on most devices. Starting from API
+     * level 30, the camera device may combine optical and digital zoom through the
+     * ACAMERA_CONTROL_ZOOM_RATIO control.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_LENS_APERTURE
      * @see ACAMERA_LENS_FOCUS_DISTANCE
      * @see ACAMERA_LENS_STATE
@@ -2306,6 +2547,11 @@
      * <p><code>p' = Rp</code></p>
      * <p>where <code>p</code> is in the device sensor coordinate system, and
      *  <code>p'</code> is in the camera-oriented coordinate system.</p>
+     * <p>If ACAMERA_LENS_POSE_REFERENCE is UNDEFINED, the quaternion rotation cannot
+     *  be accurately represented by the camera device, and will be represented by
+     *  default values matching its default facing.</p>
+     *
+     * @see ACAMERA_LENS_POSE_REFERENCE
      */
     ACAMERA_LENS_POSE_ROTATION =                                // float[4]
             ACAMERA_LENS_START + 6,
@@ -2346,6 +2592,8 @@
      * <p>When ACAMERA_LENS_POSE_REFERENCE is GYROSCOPE, then this position is relative to
      * the center of the primary gyroscope on the device. The axis definitions are the same as
      * with PRIMARY_CAMERA.</p>
+     * <p>When ACAMERA_LENS_POSE_REFERENCE is UNDEFINED, this position cannot be accurately
+     * represented by the camera device, and will be represented as <code>(0, 0, 0)</code>.</p>
      *
      * @see ACAMERA_LENS_DISTORTION
      * @see ACAMERA_LENS_INTRINSIC_CALIBRATION
@@ -2488,8 +2736,10 @@
     ACAMERA_LENS_RADIAL_DISTORTION =                            // Deprecated! DO NOT USE
             ACAMERA_LENS_START + 11,
     /**
-     * <p>The origin for ACAMERA_LENS_POSE_TRANSLATION.</p>
+     * <p>The origin for ACAMERA_LENS_POSE_TRANSLATION, and the accuracy of
+     * ACAMERA_LENS_POSE_TRANSLATION and ACAMERA_LENS_POSE_ROTATION.</p>
      *
+     * @see ACAMERA_LENS_POSE_ROTATION
      * @see ACAMERA_LENS_POSE_TRANSLATION
      *
      * <p>Type: byte (acamera_metadata_enum_android_lens_pose_reference_t)</p>
@@ -3085,32 +3335,70 @@
      * <p>For devices not supporting ACAMERA_DISTORTION_CORRECTION_MODE control, the coordinate
      * system always follows that of ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with <code>(0, 0)</code> being
      * the top-left pixel of the active array.</p>
-     * <p>For devices supporting ACAMERA_DISTORTION_CORRECTION_MODE control, the coordinate
-     * system depends on the mode being set.
-     * When the distortion correction mode is OFF, the coordinate system follows
-     * ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, with
-     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
-     * When the distortion correction mode is not OFF, the coordinate system follows
-     * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
-     * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
-     * <p>Output streams use this rectangle to produce their output,
-     * cropping to a smaller region if necessary to maintain the
-     * stream's aspect ratio, then scaling the sensor input to
+     * <p>For devices supporting ACAMERA_DISTORTION_CORRECTION_MODE control, the coordinate system
+     * depends on the mode being set.  When the distortion correction mode is OFF, the
+     * coordinate system follows ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, with <code>(0,
+     * 0)</code> being the top-left pixel of the pre-correction active array.  When the distortion
+     * correction mode is not OFF, the coordinate system follows
+     * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with <code>(0, 0)</code> being the top-left pixel of the
+     * active array.</p>
+     * <p>Output streams use this rectangle to produce their output, cropping to a smaller region
+     * if necessary to maintain the stream's aspect ratio, then scaling the sensor input to
      * match the output's configured resolution.</p>
-     * <p>The crop region is applied after the RAW to other color
-     * space (e.g. YUV) conversion. Since raw streams
-     * (e.g. RAW16) don't have the conversion stage, they are not
+     * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
+     * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage, they are not
      * croppable. The crop region will be ignored by raw streams.</p>
-     * <p>For non-raw streams, any additional per-stream cropping will
-     * be done to maximize the final pixel area of the stream.</p>
-     * <p>For example, if the crop region is set to a 4:3 aspect
-     * ratio, then 4:3 streams will use the exact crop
-     * region. 16:9 streams will further crop vertically
-     * (letterbox).</p>
-     * <p>Conversely, if the crop region is set to a 16:9, then 4:3
-     * outputs will crop horizontally (pillarbox), and 16:9
-     * streams will match exactly. These additional crops will
-     * be centered within the crop region.</p>
+     * <p>For non-raw streams, any additional per-stream cropping will be done to maximize the
+     * final pixel area of the stream.</p>
+     * <p>For example, if the crop region is set to a 4:3 aspect ratio, then 4:3 streams will use
+     * the exact crop region. 16:9 streams will further crop vertically (letterbox).</p>
+     * <p>Conversely, if the crop region is set to a 16:9, then 4:3 outputs will crop horizontally
+     * (pillarbox), and 16:9 streams will match exactly. These additional crops will be
+     * centered within the crop region.</p>
+     * <p>To illustrate, here are several scenarios of different crop regions and output streams,
+     * for a hypothetical camera device with an active array of size <code>(2000,1500)</code>.  Note that
+     * several of these examples use non-centered crop regions for ease of illustration; such
+     * regions are only supported on devices with FREEFORM capability
+     * (ACAMERA_SCALER_CROPPING_TYPE <code>== FREEFORM</code>), but this does not affect the way the crop
+     * rules work otherwise.</p>
+     * <ul>
+     * <li>Camera Configuration:<ul>
+     * <li>Active array size: <code>2000x1500</code> (3 MP, 4:3 aspect ratio)</li>
+     * <li>Output stream #1: <code>640x480</code> (VGA, 4:3 aspect ratio)</li>
+     * <li>Output stream #2: <code>1280x720</code> (720p, 16:9 aspect ratio)</li>
+     * </ul>
+     * </li>
+     * <li>Case #1: 4:3 crop region with 2x digital zoom<ul>
+     * <li>Crop region: <code>Rect(500, 375, 1500, 1125) // (left, top, right, bottom)</code></li>
+     * <li><img alt="4:3 aspect ratio crop diagram" src="../images/camera2/metadata/android.scaler.cropRegion/crop-region-43-ratio.png" /></li>
+     * <li><code>640x480</code> stream source area: <code>(500, 375, 1500, 1125)</code> (equal to crop region)</li>
+     * <li><code>1280x720</code> stream source area: <code>(500, 469, 1500, 1031)</code> (letterboxed)</li>
+     * </ul>
+     * </li>
+     * <li>Case #2: 16:9 crop region with ~1.5x digital zoom.<ul>
+     * <li>Crop region: <code>Rect(500, 375, 1833, 1125)</code></li>
+     * <li><img alt="16:9 aspect ratio crop diagram" src="../images/camera2/metadata/android.scaler.cropRegion/crop-region-169-ratio.png" /></li>
+     * <li><code>640x480</code> stream source area: <code>(666, 375, 1666, 1125)</code> (pillarboxed)</li>
+     * <li><code>1280x720</code> stream source area: <code>(500, 375, 1833, 1125)</code> (equal to crop region)</li>
+     * </ul>
+     * </li>
+     * <li>Case #3: 1:1 crop region with ~2.6x digital zoom.<ul>
+     * <li>Crop region: <code>Rect(500, 375, 1250, 1125)</code></li>
+     * <li><img alt="1:1 aspect ratio crop diagram" src="../images/camera2/metadata/android.scaler.cropRegion/crop-region-11-ratio.png" /></li>
+     * <li><code>640x480</code> stream source area: <code>(500, 469, 1250, 1031)</code> (letterboxed)</li>
+     * <li><code>1280x720</code> stream source area: <code>(500, 543, 1250, 957)</code> (letterboxed)</li>
+     * </ul>
+     * </li>
+     * <li>Case #4: Replace <code>640x480</code> stream with <code>1024x1024</code> stream, with 4:3 crop region:<ul>
+     * <li>Crop region: <code>Rect(500, 375, 1500, 1125)</code></li>
+     * <li><img alt="Square output, 4:3 aspect ratio crop diagram" src="../images/camera2/metadata/android.scaler.cropRegion/crop-region-43-square-ratio.png" /></li>
+     * <li><code>1024x1024</code> stream source area: <code>(625, 375, 1375, 1125)</code> (pillarboxed)</li>
+     * <li><code>1280x720</code> stream source area: <code>(500, 469, 1500, 1031)</code> (letterboxed)</li>
+     * <li>Note that in this case, neither of the two outputs is a subset of the other, with
+     *   each containing image data the other doesn't have.</li>
+     * </ul>
+     * </li>
+     * </ul>
      * <p>If the coordinate system is ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, the width and height
      * of the crop region cannot be set to be smaller than
      * <code>floor( activeArraySize.width / ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM )</code> and
@@ -3121,14 +3409,30 @@
      * and
      * <code>floor( preCorrectionActiveArraySize.height / ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM )</code>,
      * respectively.</p>
-     * <p>The camera device may adjust the crop region to account
-     * for rounding and other hardware requirements; the final
-     * crop region used will be included in the output capture
-     * result.</p>
+     * <p>The camera device may adjust the crop region to account for rounding and other hardware
+     * requirements; the final crop region used will be included in the output capture result.</p>
+     * <p>The camera sensor output aspect ratio depends on factors such as output stream
+     * combination and ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, and shouldn't be adjusted by using
+     * this control. And the camera device will treat different camera sensor output sizes
+     * (potentially with in-sensor crop) as the same crop of
+     * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE. As a result, the application shouldn't assume the
+     * maximum crop region always maps to the same aspect ratio or field of view for the
+     * sensor output.</p>
+     * <p>Starting from API level 30, it's strongly recommended to use ACAMERA_CONTROL_ZOOM_RATIO
+     * to take advantage of better support for zoom with logical multi-camera. The benefits
+     * include better precision with optical-digital zoom combination, and ability to do
+     * zoom-out from 1.0x. When using ACAMERA_CONTROL_ZOOM_RATIO for zoom, the crop region in
+     * the capture request should be left as the default activeArray size. The
+     * coordinate system is post-zoom, meaning that the activeArraySize or
+     * preCorrectionActiveArraySize covers the camera device's field of view "after" zoom.  See
+     * ACAMERA_CONTROL_ZOOM_RATIO for details.</p>
      * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
      *
+     * @see ACAMERA_CONTROL_AE_TARGET_FPS_RANGE
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
      * @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
+     * @see ACAMERA_SCALER_CROPPING_TYPE
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
@@ -3154,6 +3458,12 @@
      * <p>Crop regions that have a width or height that is smaller
      * than this ratio allows will be rounded up to the minimum
      * allowed size by the camera device.</p>
+     * <p>Starting from API level 30, when using ACAMERA_CONTROL_ZOOM_RATIO to zoom in or out,
+     * the application must use ACAMERA_CONTROL_ZOOM_RATIO_RANGE to query both the minimum and
+     * maximum zoom ratio.</p>
+     *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
+     * @see ACAMERA_CONTROL_ZOOM_RATIO_RANGE
      */
     ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM =                 // float
             ACAMERA_SCALER_START + 4,
@@ -3328,8 +3638,24 @@
      * <p>Camera devices that support FREEFORM cropping will support any crop region that
      * is inside of the active array. The camera device will apply the same crop region and
      * return the final used crop region in capture result metadata ACAMERA_SCALER_CROP_REGION.</p>
+     * <p>Starting from API level 30,</p>
+     * <ul>
+     * <li>If the camera device supports FREEFORM cropping, in order to do FREEFORM cropping, the
+     * application must set ACAMERA_CONTROL_ZOOM_RATIO to 1.0, and use ACAMERA_SCALER_CROP_REGION
+     * for zoom.</li>
+     * <li>To do CENTER_ONLY zoom, the application has below 2 options:<ol>
+     * <li>Set ACAMERA_CONTROL_ZOOM_RATIO to 1.0; adjust zoom by ACAMERA_SCALER_CROP_REGION.</li>
+     * <li>Adjust zoom by ACAMERA_CONTROL_ZOOM_RATIO; use ACAMERA_SCALER_CROP_REGION to crop
+     * the field of view vertically (letterboxing) or horizontally (pillarboxing), but not
+     * windowboxing.</li>
+     * </ol>
+     * </li>
+     * <li>Setting ACAMERA_CONTROL_ZOOM_RATIO to values different than 1.0 and
+     * ACAMERA_SCALER_CROP_REGION to be windowboxing at the same time is undefined behavior.</li>
+     * </ul>
      * <p>LEGACY capability devices will only support CENTER_ONLY cropping.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
@@ -3536,11 +3862,19 @@
      * output capture result.</p>
      * <p>This control is only effective if ACAMERA_CONTROL_AE_MODE or ACAMERA_CONTROL_MODE is set to
      * OFF; otherwise the auto-exposure algorithm will override this value.</p>
+     * <p>Note that for devices supporting postRawSensitivityBoost, the total sensitivity applied
+     * to the final processed image is the combination of ACAMERA_SENSOR_SENSITIVITY and
+     * ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST. In case the application uses the sensor
+     * sensitivity from last capture result of an auto request for a manual request, in order
+     * to achieve the same brightness in the output image, the application should also
+     * set postRawSensitivityBoost.</p>
      *
      * @see ACAMERA_CONTROL_AE_MODE
      * @see ACAMERA_CONTROL_MODE
+     * @see ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST
      * @see ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE
      * @see ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY
+     * @see ACAMERA_SENSOR_SENSITIVITY
      */
     ACAMERA_SENSOR_SENSITIVITY =                                // int32
             ACAMERA_SENSOR_START + 2,
@@ -4055,8 +4389,8 @@
     ACAMERA_SENSOR_AVAILABLE_TEST_PATTERN_MODES =               // int32[n]
             ACAMERA_SENSOR_START + 25,
     /**
-     * <p>Duration between the start of first row exposure
-     * and the start of last row exposure.</p>
+     * <p>Duration between the start of exposure for the first row of the image sensor,
+     * and the start of exposure for one past the last row of the image sensor.</p>
      *
      * <p>Type: int64</p>
      *
@@ -4065,12 +4399,22 @@
      *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
      * </ul></p>
      *
-     * <p>This is the exposure time skew between the first and last
-     * row exposure start times. The first row and the last row are
-     * the first and last rows inside of the
+     * <p>This is the exposure time skew between the first and <code>(last+1)</code> row exposure start times. The
+     * first row and the last row are the first and last rows inside of the
      * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.</p>
-     * <p>For typical camera sensors that use rolling shutters, this is also equivalent
-     * to the frame readout time.</p>
+     * <p>For typical camera sensors that use rolling shutters, this is also equivalent to the frame
+     * readout time.</p>
+     * <p>If the image sensor is operating in a binned or cropped mode due to the current output
+     * target resolutions, it's possible this skew is reported to be larger than the exposure
+     * time, for example, since it is based on the full array even if a partial array is read
+     * out. Be sure to scale the number to cover the section of the sensor actually being used
+     * for the outputs you care about. So if your output covers N rows of the active array of
+     * height H, scale this value by N/H to get the total skew for that viewport.</p>
+     * <p><em>Note:</em> Prior to Android 11, this field was described as measuring duration from
+     * first to last row of the image sensor, which is not equal to the frame readout time for a
+     * rolling shutter sensor. Implementations generally reported the latter value, so to resolve
+     * the inconsistency, the description has been updated to range from (first, last+1) row
+     * exposure start, instead.</p>
      *
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
@@ -4621,9 +4965,20 @@
      * When the distortion correction mode is not OFF, the coordinate system follows
      * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
      * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
-     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE == FULL</p>
+     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE == FULL.</p>
+     * <p>Starting from API level 30, the coordinate system of activeArraySize or
+     * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not
+     * pre-zoomRatio field of view. This means that if the relative position of faces and
+     * the camera device doesn't change, when zooming in by increasing
+     * ACAMERA_CONTROL_ZOOM_RATIO, the face landmarks move farther away from the center of the
+     * activeArray or preCorrectionActiveArray. If ACAMERA_CONTROL_ZOOM_RATIO is set to 1.0
+     * (default), the face landmarks coordinates won't change as ACAMERA_SCALER_CROP_REGION
+     * changes. See ACAMERA_CONTROL_ZOOM_RATIO for details. Whether to use activeArraySize or
+     * preCorrectionActiveArraySize still depends on distortion correction mode.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
+     * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_STATISTICS_FACE_DETECT_MODE
@@ -4652,10 +5007,21 @@
      * When the distortion correction mode is not OFF, the coordinate system follows
      * ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
      * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
-     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF
-     * The data representation is <code>int[4]</code>, which maps to <code>(left, top, right, bottom)</code>.</p>
+     * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF.</p>
+     * <p>Starting from API level 30, the coordinate system of activeArraySize or
+     * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not
+     * pre-zoomRatio field of view. This means that if the relative position of faces and
+     * the camera device doesn't change, when zooming in by increasing
+     * ACAMERA_CONTROL_ZOOM_RATIO, the face rectangles grow larger and move farther away from
+     * the center of the activeArray or preCorrectionActiveArray. If ACAMERA_CONTROL_ZOOM_RATIO
+     * is set to 1.0 (default), the face rectangles won't change as ACAMERA_SCALER_CROP_REGION
+     * changes. See ACAMERA_CONTROL_ZOOM_RATIO for details. Whether to use activeArraySize or
+     * preCorrectionActiveArraySize still depends on distortion correction mode.</p>
+     * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, right, bottom)</code>.</p>
      *
+     * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
+     * @see ACAMERA_SCALER_CROP_REGION
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_STATISTICS_FACE_DETECT_MODE
@@ -5694,10 +6060,11 @@
      * </ul></p>
      *
      * <p>The accuracy of the frame timestamp synchronization determines the physical cameras'
-     * ability to start exposure at the same time. If the sensorSyncType is CALIBRATED,
-     * the physical camera sensors usually run in master-slave mode so that their shutter
-     * time is synchronized. For APPROXIMATE sensorSyncType, the camera sensors usually run in
-     * master-master mode, and there could be offset between their start of exposure.</p>
+     * ability to start exposure at the same time. If the sensorSyncType is CALIBRATED, the
+     * physical camera sensors usually run in leader/follower mode where one sensor generates a
+     * timing signal for the other, so that their shutter time is synchronized. For APPROXIMATE
+     * sensorSyncType, the camera sensors usually run in leader/leader mode, where both sensors
+     * use their own timing generator, and there could be offset between their start of exposure.</p>
      * <p>In both cases, all images generated for a particular capture request still carry the same
      * timestamps, so that they can be used to look up the matching frame number and
      * onCaptureStarted callback.</p>
@@ -6581,6 +6948,7 @@
      * This setting can only be used if scene mode is supported (i.e.
      * ACAMERA_CONTROL_AVAILABLE_SCENE_MODES
      * contain some modes other than DISABLED).</p>
+     * <p>For extended scene modes such as BOKEH, please use USE_EXTENDED_SCENE_MODE instead.</p>
      *
      * @see ACAMERA_CONTROL_AVAILABLE_SCENE_MODES
      */
@@ -6598,6 +6966,18 @@
      */
     ACAMERA_CONTROL_MODE_OFF_KEEP_STATE                              = 3,
 
+    /**
+     * <p>Use a specific extended scene mode.</p>
+     * <p>When extended scene mode is on, the camera device may override certain control
+     * parameters, such as targetFpsRange, AE, AWB, and AF modes, to achieve best power and
+     * quality tradeoffs. Only the mandatory stream combinations of LIMITED hardware level
+     * are guaranteed.</p>
+     * <p>This setting can only be used if extended scene mode is supported (i.e.
+     * android.control.availableExtendedSceneModes
+     * contains some modes other than DISABLED).</p>
+     */
+    ACAMERA_CONTROL_MODE_USE_EXTENDED_SCENE_MODE                     = 4,
+
 } acamera_metadata_enum_android_control_mode_t;
 
 // ACAMERA_CONTROL_SCENE_MODE
@@ -6987,6 +7367,31 @@
 
 } acamera_metadata_enum_android_control_af_scene_change_t;
 
+// ACAMERA_CONTROL_EXTENDED_SCENE_MODE
+typedef enum acamera_metadata_enum_acamera_control_extended_scene_mode {
+    /**
+     * <p>Extended scene mode is disabled.</p>
+     */
+    ACAMERA_CONTROL_EXTENDED_SCENE_MODE_DISABLED                     = 0,
+
+    /**
+     * <p>High quality bokeh mode is enabled for all non-raw streams (including YUV,
+     * JPEG, and IMPLEMENTATION_DEFINED) when capture intent is STILL_CAPTURE. Due to the
+     * extra image processing, this mode may introduce additional stall to non-raw streams.
+     * This mode should be used in high quality still capture use case.</p>
+     */
+    ACAMERA_CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE          = 1,
+
+    /**
+     * <p>Bokeh effect must not slow down capture rate relative to sensor raw output,
+     * and the effect is applied to all processed streams no larger than the maximum
+     * streaming dimension. This mode should be used if performance and power are a
+     * priority, such as video recording.</p>
+     */
+    ACAMERA_CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS             = 2,
+
+} acamera_metadata_enum_android_control_extended_scene_mode_t;
+
 
 
 // ACAMERA_EDGE_MODE
@@ -7213,6 +7618,19 @@
      */
     ACAMERA_LENS_POSE_REFERENCE_GYROSCOPE                            = 1,
 
+    /**
+     * <p>The camera device cannot represent the values of ACAMERA_LENS_POSE_TRANSLATION
+     * and ACAMERA_LENS_POSE_ROTATION accurately enough. One such example is a camera device
+     * on the cover of a foldable phone: in order to measure the pose translation and rotation,
+     * some kind of hinge position sensor would be needed.</p>
+     * <p>The value of ACAMERA_LENS_POSE_TRANSLATION must be all zeros, and
+     * ACAMERA_LENS_POSE_ROTATION must be values matching its default facing.</p>
+     *
+     * @see ACAMERA_LENS_POSE_ROTATION
+     * @see ACAMERA_LENS_POSE_TRANSLATION
+     */
+    ACAMERA_LENS_POSE_REFERENCE_UNDEFINED                            = 2,
+
 } acamera_metadata_enum_android_lens_pose_reference_t;
 
 
@@ -7593,14 +8011,20 @@
      * <p>The camera device is a logical camera backed by two or more physical cameras.</p>
      * <p>In API level 28, the physical cameras must also be exposed to the application via
      * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>.</p>
-     * <p>Starting from API level 29, some or all physical cameras may not be independently
-     * exposed to the application, in which case the physical camera IDs will not be
-     * available in <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. But the
+     * <p>Starting from API level 29:</p>
+     * <ul>
+     * <li>Some or all physical cameras may not be independently exposed to the application,
+     * in which case the physical camera IDs will not be available in
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraIdList">CameraManager#getCameraIdList</a>. But the
      * application can still query the physical cameras' characteristics by calling
-     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraCharacteristics">CameraManager#getCameraCharacteristics</a>. Additionally,
-     * if a physical camera is hidden from camera ID list, the mandatory stream combinations
-     * for that physical camera must be supported through the logical camera using physical
-     * streams.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraManager.html#getCameraCharacteristics">CameraManager#getCameraCharacteristics</a>.</li>
+     * <li>If a physical camera is hidden from camera ID list, the mandatory stream
+     * combinations for that physical camera must be supported through the logical camera
+     * using physical streams. One exception is that in API level 30, a physical camera
+     * may become unavailable via
+     * {@link ACameraManager_PhysicalCameraAvailabilityCallback }
+     * callback.</li>
+     * </ul>
      * <p>Combinations of logical and physical streams, or physical streams from different
      * physical cameras are not guaranteed. However, if the camera device supports
      * {@link ACameraDevice_isSessionConfigurationSupported },
@@ -7671,19 +8095,35 @@
      * <li>ACAMERA_LENS_POSE_REFERENCE</li>
      * <li>ACAMERA_LENS_DISTORTION</li>
      * </ul>
-     * <p>The field of view of all non-RAW physical streams must be the same or as close as
-     * possible to that of non-RAW logical streams. If the requested FOV is outside of the
-     * range supported by the physical camera, the physical stream for that physical camera
-     * will use either the maximum or minimum scaler crop region, depending on which one is
-     * closer to the requested FOV. For example, for a logical camera with wide-tele lens
-     * configuration where the wide lens is the default, if the logical camera's crop region
-     * is set to maximum, the physical stream for the tele lens will be configured to its
-     * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
-     * configuration where the normal lens is the default, when the logical camera's crop
-     * region is set to maximum, the FOV of the logical streams will be that of the normal
-     * lens. The FOV of the physical streams for the wide lens will be the same as the
-     * logical stream, by making the crop region smaller than its active array size to
-     * compensate for the smaller focal length.</p>
+     * <p>The field of view of non-RAW physical streams must not be smaller than that of the
+     * non-RAW logical streams, or the maximum field-of-view of the physical camera,
+     * whichever is smaller. The application should check the physical capture result
+     * metadata for how the physical streams are cropped or zoomed. More specifically, given
+     * the physical camera result metadata, the effective horizontal field-of-view of the
+     * physical camera is:</p>
+     * <pre><code>fov = 2 * atan2(cropW * sensorW / (2 * zoomRatio * activeArrayW), focalLength)
+     * </code></pre>
+     * <p>where the equation parameters are the physical camera's crop region width, physical
+     * sensor width, zoom ratio, active array width, and focal length respectively. Typically
+     * the physical stream of active physical camera has the same field-of-view as the
+     * logical streams. However, the same may not be true for physical streams from
+     * non-active physical cameras. For example, if the logical camera has a wide-ultrawide
+     * configuration where the wide lens is the default, when the crop region is set to the
+     * logical camera's active array size, (and the zoom ratio set to 1.0 starting from
+     * Android 11), a physical stream for the ultrawide camera may prefer outputing images
+     * with larger field-of-view than that of the wide camera for better stereo matching
+     * margin or more robust motion tracking. At the same time, the physical non-RAW streams'
+     * field of view must not be smaller than the requested crop region and zoom ratio, as
+     * long as it's within the physical lens' capability. For example, for a logical camera
+     * with wide-tele lens configuration where the wide lens is the default, if the logical
+     * camera's crop region is set to maximum size, and zoom ratio set to 1.0, the physical
+     * stream for the tele lens will be configured to its maximum size crop region (no zoom).</p>
+     * <p><em>Deprecated:</em> Prior to Android 11, the field of view of all non-RAW physical streams
+     * cannot be larger than that of non-RAW logical streams. If the logical camera has a
+     * wide-ultrawide lens configuration where the wide lens is the default, when the logical
+     * camera's crop region is set to maximum size, the FOV of the physical streams for the
+     * ultrawide lens will be the same as the logical stream, by making the crop region
+     * smaller than its active array size to compensate for the smaller focal length.</p>
      * <p>Even if the underlying physical cameras have different RAW characteristics (such as
      * size or CFA pattern), a logical camera can still advertise RAW capability. In this
      * case, when the application configures a RAW stream, the camera device will make sure
@@ -7751,6 +8191,13 @@
      */
     ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA         = 13,
 
+    /**
+     * <p>The camera device is only accessible by Android's system components and privileged
+     * applications. Processes need to have the android.permission.SYSTEM_CAMERA in
+     * addition to android.permission.CAMERA in order to connect to this camera device.</p>
+     */
+    ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA             = 14,
+
 } acamera_metadata_enum_android_request_available_capabilities_t;
 
 
@@ -8047,12 +8494,16 @@
 // ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
 typedef enum acamera_metadata_enum_acamera_sensor_info_timestamp_source {
     /**
-     * <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in nanoseconds and monotonic,
-     * but can not be compared to timestamps from other subsystems
-     * (e.g. accelerometer, gyro etc.), or other instances of the same or different
-     * camera devices in the same system. Timestamps between streams and results for
-     * a single camera instance are comparable, and the timestamps for all buffers
-     * and the result metadata generated by a single capture are identical.</p>
+     * <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in nanoseconds and monotonic, but can
+     * not be compared to timestamps from other subsystems (e.g. accelerometer, gyro etc.),
+     * or other instances of the same or different camera devices in the same system with
+     * accuracy. However, the timestamps are roughly in the same timebase as
+     * <a href="https://developer.android.com/reference/android/os/SystemClock.html#uptimeMillis">SystemClock#uptimeMillis</a>.  The accuracy is sufficient for tasks
+     * like A/V synchronization for video recording, at least, and the timestamps can be
+     * directly used together with timestamps from the audio subsystem for that task.</p>
+     * <p>Timestamps between streams and results for a single camera instance are comparable,
+     * and the timestamps for all buffers and the result metadata generated by a single
+     * capture are identical.</p>
      *
      * @see ACAMERA_SENSOR_TIMESTAMP
      */
@@ -8062,6 +8513,14 @@
      * <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in the same timebase as
      * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,
      * and they can be compared to other timestamps using that base.</p>
+     * <p>When buffers from a REALTIME device are passed directly to a video encoder from the
+     * camera, automatic compensation is done to account for differing timebases of the
+     * audio and camera subsystems.  If the application is receiving buffers and then later
+     * sending them to a video encoder or other application where they are compared with
+     * audio subsystem timestamps or similar, this compensation is not present.  In those
+     * cases, applications need to adjust the timestamps themselves.  Since <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a> and <a href="https://developer.android.com/reference/android/os/SystemClock.html#uptimeMillis">SystemClock#uptimeMillis</a> only diverge while the device is asleep, an
+     * offset between the two sources can be measured once per active session and applied
+     * to timestamps for sufficient accuracy for A/V sync.</p>
      *
      * @see ACAMERA_SENSOR_TIMESTAMP
      */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index b6f1553..2b630db 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -31,6 +31,7 @@
     ACameraMetadata_getAllTags;
     ACameraMetadata_getConstEntry;
     ACameraMetadata_isLogicalMultiCamera; # introduced=29
+    ACameraMetadata_fromCameraMetadata; # introduced=30
     ACameraOutputTarget_create;
     ACameraOutputTarget_free;
     ACaptureRequest_addTarget;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index 70c887a..5aa9c46 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -36,15 +36,16 @@
 namespace android {
 namespace acam {
 
-using frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
 
 // Static member definitions
 const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
+const char* CameraManagerGlobal::kPhysicalCameraIdKey   = "PhysicalCameraId";
 const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp";
 const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
+const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
 Mutex                CameraManagerGlobal::sLock;
 CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
 
@@ -249,7 +250,7 @@
                 return nullptr;
             }
             if (mHandler == nullptr) {
-                mHandler = new CallbackHandler();
+                mHandler = new CallbackHandler(this);
             }
             mCbLooper->registerHandler(mHandler);
         }
@@ -258,9 +259,9 @@
         if (mCameraServiceListener == nullptr) {
             mCameraServiceListener = new CameraServiceListener(this);
         }
-        hidl_vec<CameraStatusAndId> cameraStatuses{};
+        hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> cameraStatuses{};
         Status status = Status::NO_ERROR;
-        auto remoteRet = mCameraService->addListener(mCameraServiceListener,
+        auto remoteRet = mCameraService->addListener_2_1(mCameraServiceListener,
                                                      [&status, &cameraStatuses](Status s,
                                                                                 auto &retStatuses) {
                                                          status = s;
@@ -277,7 +278,15 @@
         }
 
         for (auto& c : cameraStatuses) {
-            onStatusChangedLocked(c);
+            onStatusChangedLocked(c.v2_0);
+
+            for (auto& unavailablePhysicalId : c.unavailPhysicalCameraIds) {
+                PhysicalCameraStatusAndId statusAndId;
+                statusAndId.deviceStatus = CameraDeviceStatus::STATUS_NOT_PRESENT;
+                statusAndId.cameraId = c.v2_0.cameraId;
+                statusAndId.physicalCameraId = unavailablePhysicalId;
+                onStatusChangedLocked(statusAndId);
+            }
         }
     }
     return mCameraService;
@@ -293,7 +302,7 @@
         for (auto& pair : cm->mDeviceStatusMap) {
             CameraStatusAndId cameraStatusAndId;
             cameraStatusAndId.cameraId = pair.first;
-            cameraStatusAndId.deviceStatus = pair.second;
+            cameraStatusAndId.deviceStatus = pair.second.getStatus();
             cm->onStatusChangedLocked(cameraStatusAndId);
         }
         cm->mCameraService.clear();
@@ -303,6 +312,51 @@
 
 void CameraManagerGlobal::registerAvailabilityCallback(
         const ACameraManager_AvailabilityCallbacks *callback) {
+    return registerAvailCallback<ACameraManager_AvailabilityCallbacks>(callback);
+}
+
+void CameraManagerGlobal::unregisterAvailabilityCallback(
+        const ACameraManager_AvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    drainPendingCallbacksLocked();
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+void CameraManagerGlobal::registerExtendedAvailabilityCallback(
+        const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+    return registerAvailCallback<ACameraManager_ExtendedAvailabilityCallbacks>(callback);
+}
+
+void CameraManagerGlobal::unregisterExtendedAvailabilityCallback(
+        const ACameraManager_ExtendedAvailabilityCallbacks *callback) {
+    Mutex::Autolock _l(mLock);
+    drainPendingCallbacksLocked();
+    Callback cb(callback);
+    mCallbacks.erase(cb);
+}
+
+void CameraManagerGlobal::onCallbackCalled() {
+    Mutex::Autolock _l(mLock);
+    if (mPendingCallbackCnt > 0) {
+        mPendingCallbackCnt--;
+    }
+    mCallbacksCond.signal();
+}
+
+void CameraManagerGlobal::drainPendingCallbacksLocked() {
+    while (mPendingCallbackCnt > 0) {
+        auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout);
+        if (res != NO_ERROR) {
+            ALOGE("%s: Error waiting to drain callbacks: %s(%d)",
+                    __FUNCTION__, strerror(-res), res);
+            break;
+        }
+    }
+}
+
+template <class T>
+void CameraManagerGlobal::registerAvailCallback(const T *callback) {
     Mutex::Autolock _l(mLock);
     Callback cb(callback);
     auto pair = mCallbacks.insert(cb);
@@ -310,34 +364,44 @@
     if (pair.second) {
         for (auto& pair : mDeviceStatusMap) {
             const hidl_string& cameraId = pair.first;
-            CameraDeviceStatus status = pair.second;
+            CameraDeviceStatus status = pair.second.getStatus();
 
+            // Camera available/unavailable callback
             sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
-            ACameraManager_AvailabilityCallback cb = isStatusAvailable(status) ?
-                    callback->onCameraAvailable : callback->onCameraUnavailable;
-            msg->setPointer(kCallbackFpKey, (void *) cb);
-            msg->setPointer(kContextKey, callback->context);
+            ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
+                    cb.mAvailable : cb.mUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+            msg->setPointer(kContextKey, cb.mContext);
             msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            mPendingCallbackCnt++;
             msg->post();
+
+            // Physical camera unavailable callback
+            std::set<hidl_string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
+            for (const auto& physicalCameraId : unavailPhysicalIds) {
+                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+                        cb.mPhysicalCamUnavailable;
+                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+                msg->setPointer(kContextKey, cb.mContext);
+                msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+                mPendingCallbackCnt++;
+                msg->post();
+            }
         }
     }
 }
 
-void CameraManagerGlobal::unregisterAvailabilityCallback(
-        const ACameraManager_AvailabilityCallbacks *callback) {
-    Mutex::Autolock _l(mLock);
-    Callback cb(callback);
-    mCallbacks.erase(cb);
-}
-
 void CameraManagerGlobal::getCameraIdList(std::vector<hidl_string>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
     auto cs = getCameraService();
     Mutex::Autolock _l(mLock);
 
     for(auto& deviceStatus : mDeviceStatusMap) {
-        if (deviceStatus.second == CameraDeviceStatus::STATUS_NOT_PRESENT ||
-                deviceStatus.second == CameraDeviceStatus::STATUS_ENUMERATING) {
+        CameraDeviceStatus status = deviceStatus.second.getStatus();
+        if (status == CameraDeviceStatus::STATUS_NOT_PRESENT ||
+                status == CameraDeviceStatus::STATUS_ENUMERATING) {
             continue;
         }
         cameraIds->push_back(deviceStatus.first);
@@ -366,6 +430,15 @@
 }
 
 void CameraManagerGlobal::CallbackHandler::onMessageReceived(
+      const sp<AMessage> &msg) {
+    onMessageReceivedInternal(msg);
+    if (msg->what() == kWhatSendSingleCallback ||
+            msg->what() == kWhatSendSinglePhysicalCameraCallback) {
+        notifyParent();
+    }
+}
+
+void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal(
         const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSendSingleCallback:
@@ -391,12 +464,48 @@
             (*cb)(context, cameraId.c_str());
             break;
         }
+        case kWhatSendSinglePhysicalCameraCallback:
+        {
+            ACameraManager_PhysicalCameraAvailabilityCallback cb;
+            void* context;
+            AString cameraId;
+            AString physicalCameraId;
+            bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
+            if (!found) {
+                ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
+                return;
+            }
+            found = msg->findPointer(kContextKey, &context);
+            if (!found) {
+                ALOGE("%s: Cannot find callback context!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kCameraIdKey, &cameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
+                return;
+            }
+            found = msg->findString(kPhysicalCameraIdKey, &physicalCameraId);
+            if (!found) {
+                ALOGE("%s: Cannot find physical camera ID!", __FUNCTION__);
+                return;
+            }
+            (*cb)(context, cameraId.c_str(), physicalCameraId.c_str());
+            break;
+        }
         default:
             ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
             break;
     }
 }
 
+void CameraManagerGlobal::CallbackHandler::notifyParent() {
+    sp<CameraManagerGlobal> parent = mParent.promote();
+    if (parent != nullptr) {
+        parent->onCallbackCalled();
+    }
+}
+
 hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onStatusChanged(
         const CameraStatusAndId &statusAndId) {
     sp<CameraManagerGlobal> cm = mCameraManager.promote();
@@ -426,7 +535,7 @@
     bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
     CameraDeviceStatus oldStatus = firstStatus ?
             status : // first status
-            mDeviceStatusMap[cameraId];
+            mDeviceStatusMap[cameraId].getStatus();
 
     if (!firstStatus &&
             isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
@@ -435,7 +544,7 @@
     }
 
     // Iterate through all registered callbacks
-    mDeviceStatusMap[cameraId] = status;
+    mDeviceStatusMap[cameraId].updateStatus(status);
     for (auto cb : mCallbacks) {
         sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
         ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
@@ -443,6 +552,7 @@
         msg->setPointer(kCallbackFpKey, (void *) cbFp);
         msg->setPointer(kContextKey, cb.mContext);
         msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+        mPendingCallbackCnt++;
         msg->post();
     }
     if (status == CameraDeviceStatus::STATUS_NOT_PRESENT) {
@@ -450,6 +560,99 @@
     }
 }
 
+hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+    if (cm != nullptr) {
+        cm->onStatusChanged(statusAndId);
+    } else {
+        ALOGE("Cannot deliver status change. Global camera manager died");
+    }
+    return Void();
+}
+
+void CameraManagerGlobal::onStatusChanged(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    Mutex::Autolock _l(mLock);
+    onStatusChangedLocked(statusAndId);
+}
+
+void CameraManagerGlobal::onStatusChangedLocked(
+        const PhysicalCameraStatusAndId &statusAndId) {
+    hidl_string cameraId = statusAndId.cameraId;
+    hidl_string physicalCameraId = statusAndId.physicalCameraId;
+    CameraDeviceStatus status = statusAndId.deviceStatus;
+    if (!validStatus(status)) {
+        ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+        return;
+    }
+
+    auto logicalStatus = mDeviceStatusMap.find(cameraId);
+    if (logicalStatus == mDeviceStatusMap.end()) {
+        ALOGE("%s: Physical camera id %s status change on a non-present id %s",
+                __FUNCTION__, physicalCameraId.c_str(), cameraId.c_str());
+        return;
+    }
+    CameraDeviceStatus logicalCamStatus = mDeviceStatusMap[cameraId].getStatus();
+    if (logicalCamStatus != CameraDeviceStatus::STATUS_PRESENT &&
+            logicalCamStatus != CameraDeviceStatus::STATUS_NOT_AVAILABLE) {
+        ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+                __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
+        return;
+    }
+
+    bool updated = false;
+    if (status == CameraDeviceStatus::STATUS_PRESENT) {
+        updated = mDeviceStatusMap[cameraId].removeUnavailablePhysicalId(physicalCameraId);
+    } else {
+        updated = mDeviceStatusMap[cameraId].addUnavailablePhysicalId(physicalCameraId);
+    }
+
+    // Iterate through all registered callbacks
+    if (updated) {
+        for (auto cb : mCallbacks) {
+            sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+            ACameraManager_PhysicalCameraAvailabilityCallback cbFp = isStatusAvailable(status) ?
+                    cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFp);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+            mPendingCallbackCnt++;
+            msg->post();
+        }
+    }
+}
+
+CameraDeviceStatus CameraManagerGlobal::CameraStatus::getStatus() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return status;
+}
+
+void CameraManagerGlobal::CameraStatus::updateStatus(CameraDeviceStatus newStatus) {
+    std::lock_guard<std::mutex> lock(mLock);
+    status = newStatus;
+}
+
+bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
+        const hidl_string& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto result = unavailablePhysicalIds.insert(physicalCameraId);
+    return result.second;
+}
+
+bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
+        const hidl_string& physicalCameraId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    auto count = unavailablePhysicalIds.erase(physicalCameraId);
+    return count > 0;
+}
+
+std::set<hidl_string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return unavailablePhysicalIds;
+}
+
 } // namespace acam
 } // namespace android
 
@@ -574,9 +777,8 @@
 
     if (!serviceRet.isOk() || status != Status::NO_ERROR) {
         ALOGE("%s: connect camera device failed", __FUNCTION__);
-        // TODO: Convert serviceRet to camera_status_t
         delete device;
-        return ACAMERA_ERROR_UNKNOWN;
+        return utils::convertFromHidl(status);
     }
     if (deviceRemote == nullptr) {
         ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 2c62d44..85da3e9 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -21,6 +21,8 @@
 
 #include <android-base/parseint.h>
 #include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
 
 #include <CameraMetadata.h>
 #include <utils/StrongPointer.h>
@@ -36,9 +38,10 @@
 namespace android {
 namespace acam {
 
-using ICameraService = frameworks::cameraservice::service::V2_0::ICameraService;
+using ICameraService = frameworks::cameraservice::service::V2_1::ICameraService;
 using CameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus;
-using ICameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener;
+using ICameraServiceListener = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
+using PhysicalCameraStatusAndId = frameworks::cameraservice::service::V2_1::PhysicalCameraStatusAndId;
 using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 using Status = frameworks::cameraservice::common::V2_0::Status;
 using VendorTagSection = frameworks::cameraservice::common::V2_0::VendorTagSection;
@@ -65,9 +68,9 @@
             const ACameraManager_AvailabilityCallbacks *callback);
 
     void registerExtendedAvailabilityCallback(
-            const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {}
+            const ACameraManager_ExtendedAvailabilityCallbacks* callback);
     void unregisterExtendedAvailabilityCallback(
-            const ACameraManager_ExtendedAvailabilityCallbacks* /*callback*/) {}
+            const ACameraManager_ExtendedAvailabilityCallbacks* callback);
 
     /**
      * Return camera IDs that support camera2
@@ -94,6 +97,8 @@
         explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
         android::hardware::Return<void> onStatusChanged(
             const CameraStatusAndId &statusAndId) override;
+        android::hardware::Return<void> onPhysicalCameraStatusChanged(
+            const PhysicalCameraStatusAndId &statusAndId) override;
 
       private:
         const wp<CameraManagerGlobal> mCameraManager;
@@ -105,11 +110,25 @@
         explicit Callback(const ACameraManager_AvailabilityCallbacks *callback) :
             mAvailable(callback->onCameraAvailable),
             mUnavailable(callback->onCameraUnavailable),
+            mAccessPriorityChanged(nullptr),
+            mPhysicalCamAvailable(nullptr),
+            mPhysicalCamUnavailable(nullptr),
             mContext(callback->context) {}
 
+        explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) :
+            mAvailable(callback->availabilityCallbacks.onCameraAvailable),
+            mUnavailable(callback->availabilityCallbacks.onCameraUnavailable),
+            mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged),
+            mPhysicalCamAvailable(callback->onPhysicalCameraAvailable),
+            mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable),
+            mContext(callback->availabilityCallbacks.context) {}
+
         bool operator == (const Callback& other) const {
             return (mAvailable == other.mAvailable &&
                     mUnavailable == other.mUnavailable &&
+                    mAccessPriorityChanged == other.mAccessPriorityChanged &&
+                    mPhysicalCamAvailable == other.mPhysicalCamAvailable &&
+                    mPhysicalCamUnavailable == other.mPhysicalCamUnavailable &&
                     mContext == other.mContext);
         }
         bool operator != (const Callback& other) const {
@@ -119,6 +138,12 @@
             if (*this == other) return false;
             if (mContext != other.mContext) return mContext < other.mContext;
             if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
+            if (mAccessPriorityChanged != other.mAccessPriorityChanged)
+                    return mAccessPriorityChanged < other.mAccessPriorityChanged;
+            if (mPhysicalCamAvailable != other.mPhysicalCamAvailable)
+                    return mPhysicalCamAvailable < other.mPhysicalCamAvailable;
+            if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable)
+                    return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable;
             return mUnavailable < other.mUnavailable;
         }
         bool operator > (const Callback& other) const {
@@ -126,27 +151,45 @@
         }
         ACameraManager_AvailabilityCallback mAvailable;
         ACameraManager_AvailabilityCallback mUnavailable;
+        ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable;
+        ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
         void*                               mContext;
     };
+
+    android::Condition mCallbacksCond;
+    size_t mPendingCallbackCnt = 0;
+    void onCallbackCalled();
+    void drainPendingCallbacksLocked();
+
     std::set<Callback> mCallbacks;
 
     // definition of handler and message
     enum {
-        kWhatSendSingleCallback
+        kWhatSendSingleCallback,
+        kWhatSendSinglePhysicalCameraCallback,
     };
     static const char* kCameraIdKey;
+    static const char* kPhysicalCameraIdKey;
     static const char* kCallbackFpKey;
     static const char* kContextKey;
+    static const nsecs_t kCallbackDrainTimeout;
     class CallbackHandler : public AHandler {
       public:
-        CallbackHandler() {}
+        CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
         void onMessageReceived(const sp<AMessage> &msg) override;
+      private:
+        wp<CameraManagerGlobal> mParent;
+        void notifyParent();
+        void onMessageReceivedInternal(const sp<AMessage> &msg);
     };
     sp<CallbackHandler> mHandler;
     sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
 
     void onStatusChanged(const CameraStatusAndId &statusAndId);
     void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
+    void onStatusChanged(const PhysicalCameraStatusAndId &statusAndId);
+    void onStatusChangedLocked(const PhysicalCameraStatusAndId &statusAndId);
     bool setupVendorTags();
 
     // Utils for status
@@ -174,8 +217,27 @@
         }
     };
 
+    struct CameraStatus {
+      private:
+        CameraDeviceStatus status = CameraDeviceStatus::STATUS_NOT_PRESENT;
+        mutable std::mutex mLock;
+        std::set<hidl_string> unavailablePhysicalIds;
+      public:
+        CameraStatus(CameraDeviceStatus st): status(st) { };
+        CameraStatus() = default;
+
+        bool addUnavailablePhysicalId(const hidl_string& physicalCameraId);
+        bool removeUnavailablePhysicalId(const hidl_string& physicalCameraId);
+        CameraDeviceStatus getStatus();
+        void updateStatus(CameraDeviceStatus newStatus);
+        std::set<hidl_string> getUnavailablePhysicalIds();
+    };
+
+    template <class T>
+    void registerAvailCallback(const T *callback);
+
     // Map camera_id -> status
-    std::map<hidl_string, CameraDeviceStatus, CameraIdComparator> mDeviceStatusMap;
+    std::map<hidl_string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
diff --git a/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp
new file mode 100644
index 0000000..a20a290
--- /dev/null
+++ b/camera/ndk/ndk_vendor/tests/ACameraManagerTest.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ACameraManagerTest"
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+
+#include <mutex>
+#include <set>
+#include <string>
+
+#include <utils/Log.h>
+#include <camera/NdkCameraError.h>
+#include <camera/NdkCameraManager.h>
+
+namespace {
+
+class CameraServiceListener {
+  public:
+    typedef std::set<std::pair<std::string, std::string>> StringPairSet;
+
+    static void onAvailable(void* obj, const char* cameraId) {
+        ALOGV("Camera %s onAvailable", cameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnAvailableCount++;
+        thiz->mAvailableMap[cameraId] = true;
+        return;
+    }
+
+    static void onUnavailable(void* obj, const char* cameraId) {
+        ALOGV("Camera %s onUnavailable", cameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnUnavailableCount++;
+        thiz->mAvailableMap[cameraId] = false;
+        return;
+    }
+
+    static void onCameraAccessPrioritiesChanged(void* /*obj*/) {
+        return;
+    }
+
+    static void onPhysicalCameraAvailable(void* obj, const char* cameraId,
+            const char* physicalCameraId) {
+        ALOGV("Camera %s : %s onAvailable", cameraId, physicalCameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mOnPhysicalCameraAvailableCount++;
+        return;
+    }
+
+    static void onPhysicalCameraUnavailable(void* obj, const char* cameraId,
+            const char* physicalCameraId) {
+        ALOGV("Camera %s : %s onUnavailable", cameraId, physicalCameraId);
+        if (obj == nullptr) {
+            return;
+        }
+        CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
+        std::lock_guard<std::mutex> lock(thiz->mMutex);
+        thiz->mUnavailablePhysicalCameras.emplace(cameraId, physicalCameraId);
+        return;
+    }
+
+    void resetCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mOnAvailableCount = 0;
+        mOnUnavailableCount = 0;
+        mOnPhysicalCameraAvailableCount = 0;
+        mUnavailablePhysicalCameras.clear();
+        return;
+    }
+
+    int getAvailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnAvailableCount;
+    }
+
+    int getUnavailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnUnavailableCount;
+    }
+
+    int getPhysicalCameraAvailableCount() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mOnPhysicalCameraAvailableCount;
+    }
+
+    StringPairSet getUnavailablePhysicalCameras() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mUnavailablePhysicalCameras;
+    }
+
+    bool isAvailable(const char* cameraId) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (mAvailableMap.count(cameraId) == 0) {
+            return false;
+        }
+        return mAvailableMap[cameraId];
+    }
+
+  private:
+    std::mutex mMutex;
+    int mOnAvailableCount = 0;
+    int mOnUnavailableCount = 0;
+    int mOnPhysicalCameraAvailableCount = 0;
+    std::map<std::string, bool> mAvailableMap;
+    StringPairSet mUnavailablePhysicalCameras;
+};
+
+class ACameraManagerTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mCameraManager = ACameraManager_create();
+        if (mCameraManager == nullptr) {
+            ALOGE("Failed to create ACameraManager.");
+            return;
+        }
+
+        camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
+        if (ret != ACAMERA_OK) {
+            ALOGE("Failed to get cameraIdList: ret=%d", ret);
+            return;
+        }
+        if (mCameraIdList->numCameras < 1) {
+            ALOGW("Device has no camera on board.");
+            return;
+        }
+    }
+    void TearDown() override {
+        // Destroy camera manager
+        if (mCameraIdList) {
+            ACameraManager_deleteCameraIdList(mCameraIdList);
+            mCameraIdList = nullptr;
+        }
+        if (mCameraManager) {
+            ACameraManager_delete(mCameraManager);
+            mCameraManager = nullptr;
+        }
+    }
+
+    // Camera manager
+    ACameraManager* mCameraManager = nullptr;
+    ACameraIdList* mCameraIdList = nullptr;
+    CameraServiceListener mAvailabilityListener;
+    ACameraManager_ExtendedAvailabilityCallbacks mCbs = {
+        {
+            &mAvailabilityListener,
+                CameraServiceListener::onAvailable,
+                CameraServiceListener::onUnavailable
+        },
+        CameraServiceListener::onCameraAccessPrioritiesChanged,
+        CameraServiceListener::onPhysicalCameraAvailable,
+        CameraServiceListener::onPhysicalCameraUnavailable,
+        {}
+    };
+};
+
+TEST_F(ACameraManagerTest, testCameraManagerExtendedAvailabilityCallbacks) {
+    camera_status_t ret = ACameraManager_registerExtendedAvailabilityCallback(mCameraManager,
+            &mCbs);
+    ASSERT_EQ(ret, ACAMERA_OK);
+
+    sleep(1);
+
+    // Should at least get onAvailable for each camera once
+    ASSERT_EQ(mAvailabilityListener.getAvailableCount(), mCameraIdList->numCameras);
+
+    // Expect no available callbacks for physical cameras
+    int availablePhysicalCamera = mAvailabilityListener.getPhysicalCameraAvailableCount();
+    ASSERT_EQ(availablePhysicalCamera, 0);
+
+    CameraServiceListener::StringPairSet unavailablePhysicalCameras;
+    CameraServiceListener::StringPairSet physicalCameraIdPairs;
+
+    unavailablePhysicalCameras = mAvailabilityListener.getUnavailablePhysicalCameras();
+    for (int i = 0; i < mCameraIdList->numCameras; i++) {
+        const char* cameraId = mCameraIdList->cameraIds[i];
+        ASSERT_NE(cameraId, nullptr);
+        ASSERT_TRUE(mAvailabilityListener.isAvailable(cameraId));
+
+        ACameraMetadata* chars = nullptr;
+        ret = ACameraManager_getCameraCharacteristics(mCameraManager, cameraId, &chars);
+        ASSERT_EQ(ret, ACAMERA_OK);
+        ASSERT_NE(chars, nullptr);
+
+        size_t physicalCameraCnt = 0;
+        const char *const* physicalCameraIds = nullptr;
+        if (!ACameraMetadata_isLogicalMultiCamera(
+                chars, &physicalCameraCnt, &physicalCameraIds)) {
+            ACameraMetadata_free(chars);
+            continue;
+        }
+        for (size_t j = 0; j < physicalCameraCnt; j++) {
+            physicalCameraIdPairs.emplace(cameraId, physicalCameraIds[j]);
+        }
+        ACameraMetadata_free(chars);
+    }
+    for (const auto& unavailIdPair : unavailablePhysicalCameras) {
+        bool validPair = false;
+        for (const auto& idPair : physicalCameraIdPairs) {
+            if (idPair.first == unavailIdPair.first && idPair.second == unavailIdPair.second) {
+                validPair = true;
+                break;
+            }
+        }
+        // Expect valid unavailable physical cameras
+        ASSERT_TRUE(validPair);
+    }
+
+    ret = ACameraManager_unregisterExtendedAvailabilityCallback(mCameraManager, &mCbs);
+    ASSERT_EQ(ret, ACAMERA_OK);
+}
+
+}  // namespace
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index dc5afc5..8ccded2 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -57,7 +57,7 @@
 #include <algorithm>
 
 using namespace android;
-using ::android::hardware::ICameraServiceDefault;
+using ::android::hardware::ICameraService;
 using ::android::hardware::camera2::ICameraDeviceUser;
 
 #define ASSERT_NOT_NULL(x) \
@@ -83,6 +83,12 @@
         return binder::Status::ok();
     };
 
+    virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
+            const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
+        // No op
+        return binder::Status::ok();
+    };
+
     virtual binder::Status onTorchStatusChanged(int32_t status, const String16& cameraId) {
         Mutex::Autolock l(mLock);
         mCameraTorchStatuses[cameraId] = status;
@@ -372,7 +378,8 @@
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
-                hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+                std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                /*out*/&device);
         EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
         device->disconnect();
@@ -414,7 +421,8 @@
         {
             SCOPED_TRACE("openNewDevice");
             binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
-                    hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+                    std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+                    /*out*/&device);
             EXPECT_TRUE(res.isOk()) << res;
         }
         auto p = std::make_pair(callbacks, device);
@@ -507,7 +515,9 @@
         EXPECT_TRUE(res.isOk()) << res;
         EXPECT_LE(0, streamId);
         CameraMetadata sessionParams;
-        res = device->endConfigure(/*isConstrainedHighSpeed*/ false, sessionParams);
+        std::vector<int> offlineStreamIds;
+        res = device->endConfigure(/*isConstrainedHighSpeed*/ false, sessionParams,
+                &offlineStreamIds);
         EXPECT_TRUE(res.isOk()) << res;
         EXPECT_FALSE(callbacks->hadError());
 
@@ -518,7 +528,7 @@
         bool queryStatus;
         res = device->isSessionConfigurationSupported(sessionConfiguration, &queryStatus);
         EXPECT_TRUE(res.isOk() ||
-                (res.serviceSpecificErrorCode() == ICameraServiceDefault::ERROR_INVALID_OPERATION))
+                (res.serviceSpecificErrorCode() == ICameraService::ERROR_INVALID_OPERATION))
                 << res;
         if (res.isOk()) {
             EXPECT_TRUE(queryStatus);
@@ -618,7 +628,8 @@
         EXPECT_TRUE(res.isOk()) << res;
         res = device->deleteStream(streamId);
         EXPECT_TRUE(res.isOk()) << res;
-        res = device->endConfigure(/*isConstrainedHighSpeed*/ false, sessionParams);
+        res = device->endConfigure(/*isConstrainedHighSpeed*/ false, sessionParams,
+                &offlineStreamIds);
         EXPECT_TRUE(res.isOk()) << res;
 
         sleep(/*second*/1); // allow some time for errors to show up, if any
diff --git a/cmds/screenrecord/Android.bp b/cmds/screenrecord/Android.bp
index 86476cd..d7d905f 100644
--- a/cmds/screenrecord/Android.bp
+++ b/cmds/screenrecord/Android.bp
@@ -24,9 +24,15 @@
         "Program.cpp",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+        "libmediametrics_headers",
+    ],
+
     shared_libs: [
         "libstagefright",
         "libmedia",
+        "libmediandk",
         "libmedia_omx",
         "libutils",
         "libbinder",
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 7aa655f..f4fb626 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -37,23 +37,28 @@
 
 #include <binder/IPCThreadState.h>
 #include <utils/Errors.h>
+#include <utils/SystemClock.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
 
+#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/ISurfaceComposer.h>
-#include <ui/DisplayInfo.h>
+#include <media/MediaCodecBuffer.h>
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaFormatPriv.h>
+#include <media/NdkMediaMuxer.h>
 #include <media/openmax/OMX_IVCommon.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaMuxer.h>
 #include <media/stagefright/PersistentSurface.h>
-#include <media/ICrypto.h>
-#include <media/MediaCodecBuffer.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <mediadrm/ICrypto.h>
+#include <ui/DisplayConfig.h>
+#include <ui/DisplayState.h>
 
 #include "screenrecord.h"
 #include "Overlay.h"
@@ -63,16 +68,16 @@
 using android::ALooper;
 using android::AMessage;
 using android::AString;
-using android::DisplayInfo;
+using android::DisplayConfig;
 using android::FrameOutput;
 using android::IBinder;
 using android::IGraphicBufferProducer;
 using android::ISurfaceComposer;
 using android::MediaCodec;
 using android::MediaCodecBuffer;
-using android::MediaMuxer;
 using android::Overlay;
 using android::PersistentSurface;
+using android::PhysicalDisplayId;
 using android::ProcessState;
 using android::Rect;
 using android::String8;
@@ -81,20 +86,21 @@
 using android::sp;
 using android::status_t;
 
-using android::DISPLAY_ORIENTATION_0;
-using android::DISPLAY_ORIENTATION_180;
-using android::DISPLAY_ORIENTATION_90;
 using android::INVALID_OPERATION;
 using android::NAME_NOT_FOUND;
 using android::NO_ERROR;
 using android::UNKNOWN_ERROR;
 
+namespace ui = android::ui;
+
 static const uint32_t kMinBitRate = 100000;         // 0.1Mbps
 static const uint32_t kMaxBitRate = 200 * 1000000;  // 200Mbps
 static const uint32_t kMaxTimeLimitSec = 180;       // 3 minutes
 static const uint32_t kFallbackWidth = 1280;        // 720p
 static const uint32_t kFallbackHeight = 720;
 static const char* kMimeTypeAvc = "video/avc";
+static const char* kMimeTypeApplicationOctetstream = "application/octet-stream";
+static const char* kWinscopeMagicString = "#VV1NSC0PET1ME!#";
 
 // Command-line parameters.
 static bool gVerbose = false;           // chatty on stdout
@@ -113,7 +119,7 @@
 static uint32_t gBitRate = 20000000;     // 20Mbps
 static uint32_t gTimeLimitSec = kMaxTimeLimitSec;
 static uint32_t gBframes = 0;
-
+static PhysicalDisplayId gPhysicalDisplayId;
 // Set by signal handler to stop recording.
 static volatile bool gStopRequested = false;
 
@@ -266,14 +272,15 @@
 static status_t setDisplayProjection(
         SurfaceComposerClient::Transaction& t,
         const sp<IBinder>& dpy,
-        const DisplayInfo& mainDpyInfo) {
+        const ui::DisplayState& displayState) {
+    const ui::Size& viewport = displayState.viewport;
 
     // Set the region of the layer stack we're interested in, which in our
     // case is "all of it".
-    Rect layerStackRect(mainDpyInfo.viewportW, mainDpyInfo.viewportH);
+    Rect layerStackRect(viewport);
 
     // We need to preserve the aspect ratio of the display.
-    float displayAspect = (float) mainDpyInfo.viewportH / (float) mainDpyInfo.viewportW;
+    float displayAspect = viewport.getHeight() / static_cast<float>(viewport.getWidth());
 
 
     // Set the way we map the output onto the display surface (which will
@@ -323,7 +330,7 @@
     }
 
     t.setDisplayProjection(dpy,
-            gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0,
+            gRotate ? ui::ROTATION_90 : ui::ROTATION_0,
             layerStackRect, displayRect);
     return NO_ERROR;
 }
@@ -332,16 +339,16 @@
  * Configures the virtual display.  When this completes, virtual display
  * frames will start arriving from the buffer producer.
  */
-static status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo,
+static status_t prepareVirtualDisplay(
+        const ui::DisplayState& displayState,
         const sp<IGraphicBufferProducer>& bufferProducer,
         sp<IBinder>* pDisplayHandle) {
     sp<IBinder> dpy = SurfaceComposerClient::createDisplay(
             String8("ScreenRecorder"), false /*secure*/);
-
     SurfaceComposerClient::Transaction t;
     t.setDisplaySurface(dpy, bufferProducer);
-    setDisplayProjection(t, dpy, mainDpyInfo);
-    t.setDisplayLayerStack(dpy, 0);    // default stack
+    setDisplayProjection(t, dpy, displayState);
+    t.setDisplayLayerStack(dpy, displayState.layerStack);
     t.apply();
 
     *pDisplayHandle = dpy;
@@ -350,6 +357,56 @@
 }
 
 /*
+ * Writes an unsigned integer byte-by-byte in little endian order regardless
+ * of the platform endianness.
+ */
+template <typename UINT>
+static void writeValueLE(UINT value, uint8_t* buffer) {
+    for (int i = 0; i < sizeof(UINT); ++i) {
+        buffer[i] = static_cast<uint8_t>(value);
+        value >>= 8;
+    }
+}
+
+/*
+ * Saves frames presentation time relative to the elapsed realtime clock in microseconds
+ * preceded by a Winscope magic string and frame count to a metadata track.
+ * This metadata is used by the Winscope tool to sync video with SurfaceFlinger
+ * and WindowManager traces.
+ *
+ * The metadata is written as a binary array as follows:
+ * - winscope magic string (kWinscopeMagicString constant), without trailing null char,
+ * - the number of recorded frames (as little endian uint32),
+ * - for every frame its presentation time relative to the elapsed realtime clock in microseconds
+ *   (as little endian uint64).
+ */
+static status_t writeWinscopeMetadata(const Vector<int64_t>& timestamps,
+        const ssize_t metaTrackIdx, AMediaMuxer *muxer) {
+    ALOGV("Writing metadata");
+    int64_t systemTimeToElapsedTimeOffsetMicros = (android::elapsedRealtimeNano()
+        - systemTime(SYSTEM_TIME_MONOTONIC)) / 1000;
+    sp<ABuffer> buffer = new ABuffer(timestamps.size() * sizeof(int64_t)
+        + sizeof(uint32_t) + strlen(kWinscopeMagicString));
+    uint8_t* pos = buffer->data();
+    strcpy(reinterpret_cast<char*>(pos), kWinscopeMagicString);
+    pos += strlen(kWinscopeMagicString);
+    writeValueLE<uint32_t>(timestamps.size(), pos);
+    pos += sizeof(uint32_t);
+    for (size_t idx = 0; idx < timestamps.size(); ++idx) {
+        writeValueLE<uint64_t>(static_cast<uint64_t>(timestamps[idx]
+            + systemTimeToElapsedTimeOffsetMicros), pos);
+        pos += sizeof(uint64_t);
+    }
+    AMediaCodecBufferInfo bufferInfo = {
+        0,
+        static_cast<int32_t>(buffer->size()),
+        timestamps[0],
+        0
+    };
+    return AMediaMuxer_writeSampleData(muxer, metaTrackIdx, buffer->data(), &bufferInfo);
+}
+
+/*
  * Runs the MediaCodec encoder, sending the output to the MediaMuxer.  The
  * input frames are coming from the virtual display as fast as SurfaceFlinger
  * wants to send them.
@@ -359,15 +416,17 @@
  * The muxer must *not* have been started before calling.
  */
 static status_t runEncoder(const sp<MediaCodec>& encoder,
-        const sp<MediaMuxer>& muxer, FILE* rawFp, const sp<IBinder>& mainDpy,
-        const sp<IBinder>& virtualDpy, uint8_t orientation) {
+        AMediaMuxer *muxer, FILE* rawFp, const sp<IBinder>& display,
+        const sp<IBinder>& virtualDpy, ui::Rotation orientation) {
     static int kTimeout = 250000;   // be responsive on signal
     status_t err;
     ssize_t trackIdx = -1;
+    ssize_t metaTrackIdx = -1;
     uint32_t debugNumFrames = 0;
     int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC);
     int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec);
-    DisplayInfo mainDpyInfo;
+    Vector<int64_t> timestamps;
+    bool firstFrame = true;
 
     assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
 
@@ -384,6 +443,11 @@
         int64_t ptsUsec;
         uint32_t flags;
 
+        if (firstFrame) {
+            ATRACE_NAME("first_frame");
+            firstFrame = false;
+        }
+
         if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) {
             if (gVerbose) {
                 printf("Time limit reached\n");
@@ -417,16 +481,16 @@
                     //
                     // Polling for changes is inefficient and wrong, but the
                     // useful stuff is hard to get at without a Dalvik VM.
-                    err = SurfaceComposerClient::getDisplayInfo(mainDpy,
-                            &mainDpyInfo);
+                    ui::DisplayState displayState;
+                    err = SurfaceComposerClient::getDisplayState(display, &displayState);
                     if (err != NO_ERROR) {
-                        ALOGW("getDisplayInfo(main) failed: %d", err);
-                    } else if (orientation != mainDpyInfo.orientation) {
-                        ALOGD("orientation changed, now %d", mainDpyInfo.orientation);
+                        ALOGW("getDisplayState() failed: %d", err);
+                    } else if (orientation != displayState.orientation) {
+                        ALOGD("orientation changed, now %s", toCString(displayState.orientation));
                         SurfaceComposerClient::Transaction t;
-                        setDisplayProjection(t, virtualDpy, mainDpyInfo);
+                        setDisplayProjection(t, virtualDpy, displayState);
                         t.apply();
-                        orientation = mainDpyInfo.orientation;
+                        orientation = displayState.orientation;
                     }
                 }
 
@@ -458,13 +522,21 @@
                     // TODO
                     sp<ABuffer> buffer = new ABuffer(
                             buffers[bufIndex]->data(), buffers[bufIndex]->size());
-                    err = muxer->writeSampleData(buffer, trackIdx,
-                            ptsUsec, flags);
+                    AMediaCodecBufferInfo bufferInfo = {
+                        0,
+                        static_cast<int32_t>(buffer->size()),
+                        ptsUsec,
+                        flags
+                    };
+                    err = AMediaMuxer_writeSampleData(muxer, trackIdx, buffer->data(), &bufferInfo);
                     if (err != NO_ERROR) {
                         fprintf(stderr,
                             "Failed writing data to muxer (err=%d)\n", err);
                         return err;
                     }
+                    if (gOutputFormat == FORMAT_MP4) {
+                        timestamps.add(ptsUsec);
+                    }
                 }
                 debugNumFrames++;
             }
@@ -489,10 +561,18 @@
                 ALOGV("Encoder format changed");
                 sp<AMessage> newFormat;
                 encoder->getOutputFormat(&newFormat);
+                // TODO remove when MediaCodec has been replaced with AMediaCodec
+                AMediaFormat *ndkFormat = AMediaFormat_fromMsg(&newFormat);
                 if (muxer != NULL) {
-                    trackIdx = muxer->addTrack(newFormat);
+                    trackIdx = AMediaMuxer_addTrack(muxer, ndkFormat);
+                    if (gOutputFormat == FORMAT_MP4) {
+                        AMediaFormat *metaFormat = AMediaFormat_new();
+                        AMediaFormat_setString(metaFormat, AMEDIAFORMAT_KEY_MIME, kMimeTypeApplicationOctetstream);
+                        metaTrackIdx = AMediaMuxer_addTrack(muxer, metaFormat);
+                        AMediaFormat_delete(metaFormat);
+                    }
                     ALOGV("Starting muxer");
-                    err = muxer->start();
+                    err = AMediaMuxer_start(muxer);
                     if (err != NO_ERROR) {
                         fprintf(stderr, "Unable to start muxer (err=%d)\n", err);
                         return err;
@@ -527,6 +607,13 @@
                         systemTime(CLOCK_MONOTONIC) - startWhenNsec));
         fflush(stdout);
     }
+    if (metaTrackIdx >= 0 && !timestamps.isEmpty()) {
+        err = writeWinscopeMetadata(timestamps, metaTrackIdx, muxer);
+        if (err != NO_ERROR) {
+            fprintf(stderr, "Failed writing metadata to muxer (err=%d)\n", err);
+            return err;
+        }
+    }
     return NO_ERROR;
 }
 
@@ -591,32 +678,41 @@
     self->startThreadPool();
 
     // Get main display parameters.
-    const sp<IBinder> mainDpy = SurfaceComposerClient::getInternalDisplayToken();
-    if (mainDpy == nullptr) {
+    sp<IBinder> display = SurfaceComposerClient::getPhysicalDisplayToken(
+            gPhysicalDisplayId);
+    if (display == nullptr) {
         fprintf(stderr, "ERROR: no display\n");
         return NAME_NOT_FOUND;
     }
 
-    DisplayInfo mainDpyInfo;
-    err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo);
+    ui::DisplayState displayState;
+    err = SurfaceComposerClient::getDisplayState(display, &displayState);
     if (err != NO_ERROR) {
-        fprintf(stderr, "ERROR: unable to get display characteristics\n");
+        fprintf(stderr, "ERROR: unable to get display state\n");
         return err;
     }
 
+    DisplayConfig displayConfig;
+    err = SurfaceComposerClient::getActiveDisplayConfig(display, &displayConfig);
+    if (err != NO_ERROR) {
+        fprintf(stderr, "ERROR: unable to get display config\n");
+        return err;
+    }
+
+    const ui::Size& viewport = displayState.viewport;
     if (gVerbose) {
-        printf("Main display is %dx%d @%.2ffps (orientation=%u)\n",
-                mainDpyInfo.viewportW, mainDpyInfo.viewportH, mainDpyInfo.fps,
-                mainDpyInfo.orientation);
+        printf("Display is %dx%d @%.2ffps (orientation=%s), layerStack=%u\n",
+                viewport.getWidth(), viewport.getHeight(), displayConfig.refreshRate,
+                toCString(displayState.orientation), displayState.layerStack);
         fflush(stdout);
     }
 
     // Encoder can't take odd number as config
     if (gVideoWidth == 0) {
-        gVideoWidth = floorToEven(mainDpyInfo.viewportW);
+        gVideoWidth = floorToEven(viewport.getWidth());
     }
     if (gVideoHeight == 0) {
-        gVideoHeight = floorToEven(mainDpyInfo.viewportH);
+        gVideoHeight = floorToEven(viewport.getHeight());
     }
 
     // Configure and start the encoder.
@@ -624,7 +720,7 @@
     sp<FrameOutput> frameOutput;
     sp<IGraphicBufferProducer> encoderInputSurface;
     if (gOutputFormat != FORMAT_FRAMES && gOutputFormat != FORMAT_RAW_FRAMES) {
-        err = prepareEncoder(mainDpyInfo.fps, &encoder, &encoderInputSurface);
+        err = prepareEncoder(displayConfig.refreshRate, &encoder, &encoderInputSurface);
 
         if (err != NO_ERROR && !gSizeSpecified) {
             // fallback is defined for landscape; swap if we're in portrait
@@ -637,8 +733,7 @@
                         gVideoWidth, gVideoHeight, newWidth, newHeight);
                 gVideoWidth = newWidth;
                 gVideoHeight = newHeight;
-                err = prepareEncoder(mainDpyInfo.fps, &encoder,
-                        &encoderInputSurface);
+                err = prepareEncoder(displayConfig.refreshRate, &encoder, &encoderInputSurface);
             }
         }
         if (err != NO_ERROR) return err;
@@ -685,13 +780,13 @@
 
     // Configure virtual display.
     sp<IBinder> dpy;
-    err = prepareVirtualDisplay(mainDpyInfo, bufferProducer, &dpy);
+    err = prepareVirtualDisplay(displayState, bufferProducer, &dpy);
     if (err != NO_ERROR) {
         if (encoder != NULL) encoder->release();
         return err;
     }
 
-    sp<MediaMuxer> muxer = NULL;
+    AMediaMuxer *muxer = nullptr;
     FILE* rawFp = NULL;
     switch (gOutputFormat) {
         case FORMAT_MP4:
@@ -710,15 +805,15 @@
                 abort();
             }
             if (gOutputFormat == FORMAT_MP4) {
-                muxer = new MediaMuxer(fd, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+                muxer = AMediaMuxer_new(fd, AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
             } else if (gOutputFormat == FORMAT_WEBM) {
-                muxer = new MediaMuxer(fd, MediaMuxer::OUTPUT_FORMAT_WEBM);
+                muxer = AMediaMuxer_new(fd, AMEDIAMUXER_OUTPUT_FORMAT_WEBM);
             } else {
-                muxer = new MediaMuxer(fd, MediaMuxer::OUTPUT_FORMAT_THREE_GPP);
+                muxer = AMediaMuxer_new(fd, AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP);
             }
             close(fd);
             if (gRotate) {
-                muxer->setOrientationHint(90);  // TODO: does this do anything?
+                AMediaMuxer_setOrientationHint(muxer, 90); // TODO: does this do anything?
             }
             break;
         }
@@ -768,8 +863,7 @@
         }
     } else {
         // Main encoder loop.
-        err = runEncoder(encoder, muxer, rawFp, mainDpy, dpy,
-                mainDpyInfo.orientation);
+        err = runEncoder(encoder, muxer, rawFp, display, dpy, displayState.orientation);
         if (err != NO_ERROR) {
             fprintf(stderr, "Encoder failed (err=%d)\n", err);
             // fall through to cleanup
@@ -789,7 +883,7 @@
     if (muxer != NULL) {
         // If we don't stop muxer explicitly, i.e. let the destructor run,
         // it may hang (b/11050628).
-        err = muxer->stop();
+        err = AMediaMuxer_stop(muxer);
     } else if (rawFp != stdout) {
         fclose(rawFp);
     }
@@ -935,6 +1029,9 @@
         "    in videos captured to illustrate bugs.\n"
         "--time-limit TIME\n"
         "    Set the maximum recording time, in seconds.  Default / maximum is %d.\n"
+        "--display-id ID\n"
+        "    specify the physical display ID to record. Default is the primary display.\n"
+        "    see \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n"
         "--verbose\n"
         "    Display interesting information on stdout.\n"
         "--help\n"
@@ -966,9 +1063,18 @@
         { "monotonic-time",     no_argument,        NULL, 'm' },
         { "persistent-surface", no_argument,        NULL, 'p' },
         { "bframes",            required_argument,  NULL, 'B' },
+        { "display-id",         required_argument,  NULL, 'd' },
         { NULL,                 0,                  NULL, 0 }
     };
 
+    std::optional<PhysicalDisplayId> displayId = SurfaceComposerClient::getInternalDisplayId();
+    if (!displayId) {
+        fprintf(stderr, "Failed to get token for internal display\n");
+        return 1;
+    }
+
+    gPhysicalDisplayId = *displayId;
+
     while (true) {
         int optionIndex = 0;
         int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
@@ -1063,6 +1169,18 @@
                 return 2;
             }
             break;
+        case 'd':
+            gPhysicalDisplayId = atoll(optarg);
+            if (gPhysicalDisplayId == 0) {
+                fprintf(stderr, "Please specify a valid physical display id\n");
+                return 2;
+            } else if (SurfaceComposerClient::
+                    getPhysicalDisplayToken(gPhysicalDisplayId) == nullptr) {
+                fprintf(stderr, "Invalid physical display id: %"
+                        ANDROID_PHYSICAL_DISPLAY_ID_FORMAT "\n", gPhysicalDisplayId);
+                return 2;
+            }
+            break;
         default:
             if (ic != '?') {
                 fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
diff --git a/cmds/screenrecord/screenrecord.h b/cmds/screenrecord/screenrecord.h
index 9b058c2..cec7c13 100644
--- a/cmds/screenrecord/screenrecord.h
+++ b/cmds/screenrecord/screenrecord.h
@@ -18,6 +18,6 @@
 #define SCREENRECORD_SCREENRECORD_H
 
 #define kVersionMajor 1
-#define kVersionMinor 2
+#define kVersionMinor 3
 
 #endif /*SCREENRECORD_SCREENRECORD_H*/
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 6eb2e9f..6470fb1 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -3,26 +3,30 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=       \
+        AudioPlayer.cpp \
         stagefright.cpp \
         jpeg.cpp        \
         SineSource.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright libmedia libmedia_omx libutils libbinder \
+        libstagefright libmedia libmedia_codeclist libutils libbinder \
         libstagefright_foundation libjpeg libui libgui libcutils liblog \
-        libhidlbase \
+        libhidlbase libdatasource libaudioclient \
         android.hardware.media.omx@1.0 \
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
         frameworks/av/media/libstagefright/include \
         frameworks/native/include/media/openmax \
-        external/jpeg \
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_SYSTEM_EXT_MODULE:= true
 LOCAL_MODULE:= stagefright
 
 include $(BUILD_EXECUTABLE)
@@ -32,14 +36,19 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
+        AudioPlayer.cpp \
         SineSource.cpp    \
         record.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libdatasource libaudioclient
 
 LOCAL_C_INCLUDES:= \
+        frameworks/av/camera/include \
         frameworks/av/media/libstagefright \
         frameworks/native/include/media/openmax \
         frameworks/native/include/media/hardware
@@ -57,12 +66,15 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
+        AudioPlayer.cpp \
         recordvideo.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libaudioclient
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -83,12 +95,16 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
+        AudioPlayer.cpp \
         SineSource.cpp    \
         audioloop.cpp
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright libmedia liblog libutils libbinder \
-        libstagefright_foundation
+        libstagefright_foundation libaudioclient
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -109,9 +125,12 @@
 LOCAL_SRC_FILES:=         \
         stream.cpp    \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libui libgui \
-        libstagefright_foundation libmedia libcutils
+        libstagefright_foundation libmedia libcutils libdatasource
 
 LOCAL_C_INCLUDES:= \
         frameworks/av/media/libstagefright \
@@ -133,6 +152,10 @@
         codec.cpp               \
         SimplePlayer.cpp        \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediadrm_headers \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libmedia libmedia_omx libaudioclient libui libgui libcutils
@@ -154,22 +177,24 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-        filters/argbtorgba.rs \
-        filters/nightvision.rs \
-        filters/saturation.rs \
+        filters/argbtorgba.rscript \
+        filters/nightvision.rscript \
+        filters/saturation.rscript \
         mediafilter.cpp \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediadrm_headers \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright \
         liblog \
         libutils \
         libbinder \
         libstagefright_foundation \
-        libmedia \
         libmedia_omx \
         libui \
         libgui \
-        libcutils \
         libRScpp \
 
 LOCAL_C_INCLUDES:= \
@@ -201,6 +226,9 @@
 LOCAL_SRC_FILES:=               \
         muxer.cpp            \
 
+LOCAL_HEADER_LIBRARIES := \
+        libmediametrics_headers \
+
 LOCAL_SHARED_LIBRARIES := \
         libstagefright liblog libutils libbinder libstagefright_foundation \
         libcutils libc
diff --git a/cmds/stagefright/AudioPlayer.cpp b/cmds/stagefright/AudioPlayer.cpp
new file mode 100644
index 0000000..eb76953
--- /dev/null
+++ b/cmds/stagefright/AudioPlayer.cpp
@@ -0,0 +1,689 @@
+/*
+ * Copyright (C) 2009 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 <inttypes.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioPlayer"
+#include <utils/Log.h>
+#include <cutils/compiler.h>
+
+#include <binder/IPCThreadState.h>
+#include <media/AudioTrack.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/openmax/OMX_Audio.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALookup.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "AudioPlayer.h"
+
+namespace android {
+
+AudioPlayer::AudioPlayer(
+        const sp<MediaPlayerBase::AudioSink> &audioSink,
+        uint32_t flags)
+    : mInputBuffer(NULL),
+      mSampleRate(0),
+      mLatencyUs(0),
+      mFrameSize(0),
+      mNumFramesPlayed(0),
+      mNumFramesPlayedSysTimeUs(ALooper::GetNowUs()),
+      mPositionTimeMediaUs(-1),
+      mPositionTimeRealUs(-1),
+      mSeeking(false),
+      mReachedEOS(false),
+      mFinalStatus(OK),
+      mSeekTimeUs(0),
+      mStarted(false),
+      mIsFirstBuffer(false),
+      mFirstBufferResult(OK),
+      mFirstBuffer(NULL),
+      mAudioSink(audioSink),
+      mPlaying(false),
+      mStartPosUs(0),
+      mCreateFlags(flags) {
+}
+
+AudioPlayer::~AudioPlayer() {
+    if (mStarted) {
+        reset();
+    }
+}
+
+void AudioPlayer::setSource(const sp<MediaSource> &source) {
+    CHECK(mSource == NULL);
+    mSource = source;
+}
+
+ALookup<audio_format_t, int32_t> sAudioFormatToPcmEncoding {
+    {
+        { AUDIO_FORMAT_PCM_16_BIT, kAudioEncodingPcm16bit },
+        { AUDIO_FORMAT_PCM_8_BIT,  kAudioEncodingPcm8bit  },
+        { AUDIO_FORMAT_PCM_FLOAT,  kAudioEncodingPcmFloat },
+    }
+};
+
+status_t AudioPlayer::start(bool sourceAlreadyStarted) {
+    CHECK(!mStarted);
+    CHECK(mSource != NULL);
+
+    status_t err;
+    if (!sourceAlreadyStarted) {
+        err = mSource->start();
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+    // of playback, if there is one, getFormat below will retrieve the
+    // updated format, if there isn't, we'll stash away the valid buffer
+    // of data to be used on the first audio callback.
+
+    CHECK(mFirstBuffer == NULL);
+
+    MediaSource::ReadOptions options;
+    if (mSeeking) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeeking = false;
+    }
+
+    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
+    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+        ALOGV("INFO_FORMAT_CHANGED!!!");
+
+        CHECK(mFirstBuffer == NULL);
+        mFirstBufferResult = OK;
+        mIsFirstBuffer = false;
+    } else {
+        mIsFirstBuffer = true;
+    }
+
+    sp<MetaData> format = mSource->getFormat();
+
+    if (format == NULL) {
+        ALOGE("No metadata b/118620871");
+        android_errorWriteLog(0x534e4554, "118620871");
+        return BAD_VALUE;
+    }
+
+    const char *mime;
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    CHECK(success);
+    CHECK(useOffload() || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
+
+    success = format->findInt32(kKeySampleRate, &mSampleRate);
+    CHECK(success);
+
+    int32_t numChannels, channelMask;
+    success = format->findInt32(kKeyChannelCount, &numChannels);
+    CHECK(success);
+
+    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
+        // log only when there's a risk of ambiguity of channel mask selection
+        ALOGI_IF(numChannels > 2,
+                "source format didn't specify channel mask, using (%d) channel order", numChannels);
+        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    }
+
+    audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
+    int32_t pcmEncoding;
+    if (format->findInt32(kKeyPcmEncoding, &pcmEncoding)) {
+        sAudioFormatToPcmEncoding.map(pcmEncoding, &audioFormat);
+    }
+
+    if (useOffload()) {
+        if (mapMimeToAudioFormat(audioFormat, mime) != OK) {
+            ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime);
+            audioFormat = AUDIO_FORMAT_INVALID;
+        } else {
+            ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, audioFormat);
+        }
+
+        int32_t aacaot = -1;
+        if ((audioFormat == AUDIO_FORMAT_AAC) && format->findInt32(kKeyAACAOT, &aacaot)) {
+            // Redefine AAC format corrosponding to aac profile
+            mapAACProfileToAudioFormat(audioFormat,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+        }
+    }
+
+    int avgBitRate = -1;
+    format->findInt32(kKeyBitRate, &avgBitRate);
+
+    if (mAudioSink.get() != NULL) {
+
+        uint32_t flags = AUDIO_OUTPUT_FLAG_NONE;
+        audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
+
+        if (allowDeepBuffering()) {
+            flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+        }
+        if (useOffload()) {
+            flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+
+            int64_t durationUs;
+            if (format->findInt64(kKeyDuration, &durationUs)) {
+                offloadInfo.duration_us = durationUs;
+            } else {
+                offloadInfo.duration_us = -1;
+            }
+
+            offloadInfo.sample_rate = mSampleRate;
+            offloadInfo.channel_mask = channelMask;
+            offloadInfo.format = audioFormat;
+            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
+            offloadInfo.bit_rate = avgBitRate;
+            offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0);
+            offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0);
+        }
+
+        status_t err = mAudioSink->open(
+                mSampleRate, numChannels, channelMask, audioFormat,
+                DEFAULT_AUDIOSINK_BUFFERCOUNT,
+                &AudioPlayer::AudioSinkCallback,
+                this,
+                (audio_output_flags_t)flags,
+                useOffload() ? &offloadInfo : NULL);
+
+        if (err == OK) {
+            mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
+            mFrameSize = mAudioSink->frameSize();
+
+            if (useOffload()) {
+                // If the playback is offloaded to h/w we pass the
+                // HAL some metadata information
+                // We don't want to do this for PCM because it will be going
+                // through the AudioFlinger mixer before reaching the hardware
+                sendMetaDataToHal(mAudioSink, format);
+            }
+
+            err = mAudioSink->start();
+            // do not alter behavior for non offloaded tracks: ignore start status.
+            if (!useOffload()) {
+                err = OK;
+            }
+        }
+
+        if (err != OK) {
+            if (mFirstBuffer != NULL) {
+                mFirstBuffer->release();
+                mFirstBuffer = NULL;
+            }
+
+            if (!sourceAlreadyStarted) {
+                mSource->stop();
+            }
+
+            return err;
+        }
+
+    } else {
+        // playing to an AudioTrack, set up mask if necessary
+        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
+                audio_channel_out_mask_from_count(numChannels) : channelMask;
+        if (0 == audioMask) {
+            return BAD_VALUE;
+        }
+
+        mAudioTrack = new AudioTrack(
+                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
+                0 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this,
+                0 /*notificationFrames*/);
+
+        if ((err = mAudioTrack->initCheck()) != OK) {
+            mAudioTrack.clear();
+
+            if (mFirstBuffer != NULL) {
+                mFirstBuffer->release();
+                mFirstBuffer = NULL;
+            }
+
+            if (!sourceAlreadyStarted) {
+                mSource->stop();
+            }
+
+            return err;
+        }
+
+        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
+        mFrameSize = mAudioTrack->frameSize();
+
+        mAudioTrack->start();
+    }
+
+    mStarted = true;
+    mPlaying = true;
+
+    return OK;
+}
+
+void AudioPlayer::pause(bool playPendingSamples) {
+    CHECK(mStarted);
+
+    if (playPendingSamples) {
+        if (mAudioSink.get() != NULL) {
+            mAudioSink->stop();
+        } else {
+            mAudioTrack->stop();
+        }
+
+        mNumFramesPlayed = 0;
+        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
+    } else {
+        if (mAudioSink.get() != NULL) {
+            mAudioSink->pause();
+        } else {
+            mAudioTrack->pause();
+        }
+    }
+
+    mPlaying = false;
+}
+
+status_t AudioPlayer::resume() {
+    CHECK(mStarted);
+    status_t err;
+
+    if (mAudioSink.get() != NULL) {
+        err = mAudioSink->start();
+    } else {
+        err = mAudioTrack->start();
+    }
+
+    if (err == OK) {
+        mPlaying = true;
+    }
+
+    return err;
+}
+
+void AudioPlayer::reset() {
+    CHECK(mStarted);
+
+    ALOGV("reset: mPlaying=%d mReachedEOS=%d useOffload=%d",
+                                mPlaying, mReachedEOS, useOffload() );
+
+    if (mAudioSink.get() != NULL) {
+        mAudioSink->stop();
+        // If we're closing and have reached EOS, we don't want to flush
+        // the track because if it is offloaded there could be a small
+        // amount of residual data in the hardware buffer which we must
+        // play to give gapless playback.
+        // But if we're resetting when paused or before we've reached EOS
+        // we can't be doing a gapless playback and there could be a large
+        // amount of data queued in the hardware if the track is offloaded,
+        // so we must flush to prevent a track switch being delayed playing
+        // the buffered data that we don't want now
+        if (!mPlaying || !mReachedEOS) {
+            mAudioSink->flush();
+        }
+
+        mAudioSink->close();
+    } else {
+        mAudioTrack->stop();
+
+        if (!mPlaying || !mReachedEOS) {
+            mAudioTrack->flush();
+        }
+
+        mAudioTrack.clear();
+    }
+
+    // Make sure to release any buffer we hold onto so that the
+    // source is able to stop().
+
+    if (mFirstBuffer != NULL) {
+        mFirstBuffer->release();
+        mFirstBuffer = NULL;
+    }
+
+    if (mInputBuffer != NULL) {
+        ALOGV("AudioPlayer releasing input buffer.");
+
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    mSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    // When offloading, the OMX component is not used so this hack
+    // is not needed
+    if (!useOffload()) {
+        wp<MediaSource> tmp = mSource;
+        mSource.clear();
+        while (tmp.promote() != NULL) {
+            usleep(1000);
+        }
+    } else {
+        mSource.clear();
+    }
+    IPCThreadState::self()->flushCommands();
+
+    mNumFramesPlayed = 0;
+    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
+    mPositionTimeMediaUs = -1;
+    mPositionTimeRealUs = -1;
+    mSeeking = false;
+    mSeekTimeUs = 0;
+    mReachedEOS = false;
+    mFinalStatus = OK;
+    mStarted = false;
+    mPlaying = false;
+    mStartPosUs = 0;
+}
+
+// static
+void AudioPlayer::AudioCallback(int event, void *user, void *info) {
+    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
+}
+
+bool AudioPlayer::reachedEOS(status_t *finalStatus) {
+    *finalStatus = OK;
+
+    Mutex::Autolock autoLock(mLock);
+    *finalStatus = mFinalStatus;
+    return mReachedEOS;
+}
+
+status_t AudioPlayer::setPlaybackRate(const AudioPlaybackRate &rate) {
+    if (mAudioSink.get() != NULL) {
+        return mAudioSink->setPlaybackRate(rate);
+    } else if (mAudioTrack != 0){
+        return mAudioTrack->setPlaybackRate(rate);
+    } else {
+        return NO_INIT;
+    }
+}
+
+status_t AudioPlayer::getPlaybackRate(AudioPlaybackRate *rate /* nonnull */) {
+    if (mAudioSink.get() != NULL) {
+        return mAudioSink->getPlaybackRate(rate);
+    } else if (mAudioTrack != 0) {
+        *rate = mAudioTrack->getPlaybackRate();
+        return OK;
+    } else {
+        return NO_INIT;
+    }
+}
+
+// static
+size_t AudioPlayer::AudioSinkCallback(
+        MediaPlayerBase::AudioSink * /* audioSink */,
+        void *buffer, size_t size, void *cookie,
+        MediaPlayerBase::AudioSink::cb_event_t event) {
+    AudioPlayer *me = (AudioPlayer *)cookie;
+
+    switch(event) {
+    case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
+        return me->fillBuffer(buffer, size);
+
+    case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
+        ALOGV("AudioSinkCallback: stream end");
+        me->mReachedEOS = true;
+        break;
+
+    case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
+        ALOGV("AudioSinkCallback: Tear down event");
+        break;
+    }
+
+    return 0;
+}
+
+void AudioPlayer::AudioCallback(int event, void *info) {
+    switch (event) {
+    case AudioTrack::EVENT_MORE_DATA:
+        {
+        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
+        buffer->size = numBytesWritten;
+        }
+        break;
+
+    case AudioTrack::EVENT_STREAM_END:
+        mReachedEOS = true;
+        break;
+    }
+}
+
+size_t AudioPlayer::fillBuffer(void *data, size_t size) {
+    if (mNumFramesPlayed == 0) {
+        ALOGV("AudioCallback");
+    }
+
+    if (mReachedEOS) {
+        return 0;
+    }
+
+    size_t size_done = 0;
+    size_t size_remaining = size;
+    while (size_remaining > 0) {
+        MediaSource::ReadOptions options;
+        bool refreshSeekTime = false;
+
+        {
+            Mutex::Autolock autoLock(mLock);
+
+            if (mSeeking) {
+                if (mIsFirstBuffer) {
+                    if (mFirstBuffer != NULL) {
+                        mFirstBuffer->release();
+                        mFirstBuffer = NULL;
+                    }
+                    mIsFirstBuffer = false;
+                }
+
+                options.setSeekTo(mSeekTimeUs);
+                refreshSeekTime = true;
+
+                if (mInputBuffer != NULL) {
+                    mInputBuffer->release();
+                    mInputBuffer = NULL;
+                }
+
+                mSeeking = false;
+            }
+        }
+
+        if (mInputBuffer == NULL) {
+            status_t err;
+
+            if (mIsFirstBuffer) {
+                mInputBuffer = mFirstBuffer;
+                mFirstBuffer = NULL;
+                err = mFirstBufferResult;
+
+                mIsFirstBuffer = false;
+            } else {
+                err = mSource->read(&mInputBuffer, &options);
+            }
+
+            CHECK((err == OK && mInputBuffer != NULL)
+                   || (err != OK && mInputBuffer == NULL));
+
+            Mutex::Autolock autoLock(mLock);
+
+            if (err != OK) {
+                if (!mReachedEOS) {
+                    if (useOffload()) {
+                        // no more buffers to push - stop() and wait for STREAM_END
+                        // don't set mReachedEOS until stream end received
+                        if (mAudioSink != NULL) {
+                            mAudioSink->stop();
+                        } else {
+                            mAudioTrack->stop();
+                        }
+                    } else {
+                        mReachedEOS = true;
+                    }
+                }
+
+                mFinalStatus = err;
+                break;
+            }
+
+            if (mAudioSink != NULL) {
+                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
+            } else {
+                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
+            }
+
+            if(mInputBuffer->range_length() != 0) {
+                CHECK(mInputBuffer->meta_data().findInt64(
+                        kKeyTime, &mPositionTimeMediaUs));
+            }
+
+            // need to adjust the mStartPosUs for offload decoding since parser
+            // might not be able to get the exact seek time requested.
+            if (refreshSeekTime) {
+                if (useOffload()) {
+                    mStartPosUs = mPositionTimeMediaUs;
+                    ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
+                }
+                // clear seek time with mLock locked and once we have valid mPositionTimeMediaUs
+                // and mPositionTimeRealUs
+                // before clearing mSeekTimeUs check if a new seek request has been received while
+                // we were reading from the source with mLock released.
+                if (!mSeeking) {
+                    mSeekTimeUs = 0;
+                }
+            }
+
+            if (!useOffload()) {
+                mPositionTimeRealUs =
+                    ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+                        / mSampleRate;
+                ALOGV("buffer->size() = %zu, "
+                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
+                     mInputBuffer->range_length(),
+                     mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
+            }
+
+        }
+
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+
+            continue;
+        }
+
+        size_t copy = size_remaining;
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        }
+
+        memcpy((char *)data + size_done,
+               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
+                                mInputBuffer->range_length() - copy);
+
+        size_done += copy;
+        size_remaining -= copy;
+    }
+
+    if (useOffload()) {
+        // We must ask the hardware what it has played
+        mPositionTimeRealUs = getOutputPlayPositionUs_l();
+        ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
+             mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
+    }
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        mNumFramesPlayed += size_done / mFrameSize;
+        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
+    }
+
+    return size_done;
+}
+
+int64_t AudioPlayer::getOutputPlayPositionUs_l()
+{
+    uint32_t playedSamples = 0;
+    uint32_t sampleRate;
+    if (mAudioSink != NULL) {
+        mAudioSink->getPosition(&playedSamples);
+        sampleRate = mAudioSink->getSampleRate();
+    } else {
+        mAudioTrack->getPosition(&playedSamples);
+        sampleRate = mAudioTrack->getSampleRate();
+    }
+    if (sampleRate != 0) {
+        mSampleRate = sampleRate;
+    }
+
+    int64_t playedUs;
+    if (mSampleRate != 0) {
+        playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate;
+    } else {
+        playedUs = 0;
+    }
+
+    // HAL position is relative to the first buffer we sent at mStartPosUs
+    const int64_t renderedDuration = mStartPosUs + playedUs;
+    ALOGV("getOutputPlayPositionUs_l %" PRId64, renderedDuration);
+    return renderedDuration;
+}
+
+status_t AudioPlayer::seekTo(int64_t time_us) {
+    Mutex::Autolock autoLock(mLock);
+
+    ALOGV("seekTo( %" PRId64 " )", time_us);
+
+    mSeeking = true;
+    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
+    mReachedEOS = false;
+    mSeekTimeUs = time_us;
+    mStartPosUs = time_us;
+
+    // Flush resets the number of played frames
+    mNumFramesPlayed = 0;
+    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
+
+    if (mAudioSink != NULL) {
+        if (mPlaying) {
+            mAudioSink->pause();
+        }
+        mAudioSink->flush();
+        if (mPlaying) {
+            mAudioSink->start();
+        }
+    } else {
+        if (mPlaying) {
+            mAudioTrack->pause();
+        }
+        mAudioTrack->flush();
+        if (mPlaying) {
+            mAudioTrack->start();
+        }
+    }
+
+    return OK;
+}
+
+}
diff --git a/cmds/stagefright/AudioPlayer.h b/cmds/stagefright/AudioPlayer.h
new file mode 100644
index 0000000..43550ea
--- /dev/null
+++ b/cmds/stagefright/AudioPlayer.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2009 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 AUDIO_PLAYER_H_
+
+#define AUDIO_PLAYER_H_
+
+#include <media/AudioResamplerPublic.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class AudioTrack;
+struct AwesomePlayer;
+
+class AudioPlayer {
+public:
+    enum {
+        REACHED_EOS,
+        SEEK_COMPLETE
+    };
+
+    enum {
+        ALLOW_DEEP_BUFFERING = 0x01,
+        USE_OFFLOAD = 0x02,
+        HAS_VIDEO   = 0x1000,
+        IS_STREAMING = 0x2000
+
+    };
+
+    AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
+                uint32_t flags = 0);
+
+    virtual ~AudioPlayer();
+
+    // Caller retains ownership of "source".
+    void setSource(const sp<MediaSource> &source);
+
+    status_t start(bool sourceAlreadyStarted = false);
+
+    void pause(bool playPendingSamples = false);
+    status_t resume();
+
+    status_t seekTo(int64_t time_us);
+
+    bool isSeeking();
+    bool reachedEOS(status_t *finalStatus);
+
+    status_t setPlaybackRate(const AudioPlaybackRate &rate);
+    status_t getPlaybackRate(AudioPlaybackRate *rate /* nonnull */);
+
+private:
+    sp<MediaSource> mSource;
+    sp<AudioTrack> mAudioTrack;
+
+    MediaBufferBase *mInputBuffer;
+
+    int mSampleRate;
+    int64_t mLatencyUs;
+    size_t mFrameSize;
+
+    Mutex mLock;
+    int64_t mNumFramesPlayed;
+    int64_t mNumFramesPlayedSysTimeUs;
+
+    int64_t mPositionTimeMediaUs;
+    int64_t mPositionTimeRealUs;
+
+    bool mSeeking;
+    bool mReachedEOS;
+    status_t mFinalStatus;
+    int64_t mSeekTimeUs;
+
+    bool mStarted;
+
+    bool mIsFirstBuffer;
+    status_t mFirstBufferResult;
+    MediaBufferBase *mFirstBuffer;
+
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+
+    bool mPlaying;
+    int64_t mStartPosUs;
+    const uint32_t mCreateFlags;
+
+    static void AudioCallback(int event, void *user, void *info);
+    void AudioCallback(int event, void *info);
+
+    static size_t AudioSinkCallback(
+            MediaPlayerBase::AudioSink *audioSink,
+            void *data, size_t size, void *me,
+            MediaPlayerBase::AudioSink::cb_event_t event);
+
+    size_t fillBuffer(void *data, size_t size);
+
+    void reset();
+
+    int64_t getOutputPlayPositionUs_l();
+
+    bool allowDeepBuffering() const { return (mCreateFlags & ALLOW_DEEP_BUFFERING) != 0; }
+    bool useOffload() const { return (mCreateFlags & USE_OFFLOAD) != 0; }
+
+    AudioPlayer(const AudioPlayer &);
+    AudioPlayer &operator=(const AudioPlayer &);
+};
+
+}  // namespace android
+
+#endif  // AUDIO_PLAYER_H_
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index afb7db3..f4b8164 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -23,7 +23,7 @@
 #include <gui/Surface.h>
 
 #include <media/AudioTrack.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
index 1817291..6f1d98c 100644
--- a/cmds/stagefright/SineSource.h
+++ b/cmds/stagefright/SineSource.h
@@ -2,7 +2,7 @@
 
 #define SINE_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <utils/Compat.h>
 
 namespace android {
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index d4f2e8d..84a6d6b 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -29,11 +29,11 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AMRWriter.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/SimpleDecodingSource.h>
+#include "AudioPlayer.h"
 #include "SineSource.h"
 
 using namespace android;
@@ -107,8 +107,11 @@
 
     if (useMic) {
         // talk into the appropriate microphone for the duration
+        audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+        attr.source = AUDIO_SOURCE_MIC;
+
         source = new AudioSource(
-                AUDIO_SOURCE_MIC,
+                &attr,
                 String16(),
                 sampleRate,
                 channels);
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index e5a4337..c26e0b9 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -23,7 +23,7 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/MediaCodecBuffer.h>
@@ -39,7 +39,7 @@
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/Surface.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
 
 static void usage(const char *me) {
     fprintf(stderr, "usage: %s [-a] use audio\n"
@@ -414,11 +414,12 @@
         const sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
         CHECK(display != nullptr);
 
-        DisplayInfo info;
-        CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+        DisplayConfig config;
+        CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
 
-        ssize_t displayWidth = info.w;
-        ssize_t displayHeight = info.h;
+        const ui::Size& resolution = config.resolution;
+        const ssize_t displayWidth = resolution.getWidth();
+        const ssize_t displayHeight = resolution.getHeight();
 
         ALOGV("display is %zd x %zd\n", displayWidth, displayHeight);
 
diff --git a/cmds/stagefright/filters/argbtorgba.rs b/cmds/stagefright/filters/argbtorgba.rscript
similarity index 100%
rename from cmds/stagefright/filters/argbtorgba.rs
rename to cmds/stagefright/filters/argbtorgba.rscript
diff --git a/cmds/stagefright/filters/nightvision.rs b/cmds/stagefright/filters/nightvision.rscript
similarity index 100%
rename from cmds/stagefright/filters/nightvision.rs
rename to cmds/stagefright/filters/nightvision.rscript
diff --git a/cmds/stagefright/filters/saturation.rs b/cmds/stagefright/filters/saturation.rscript
similarity index 100%
rename from cmds/stagefright/filters/saturation.rs
rename to cmds/stagefright/filters/saturation.rscript
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index 2cf6955..b894545 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -24,9 +24,9 @@
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaCodecBuffer.h>
+#include <mediadrm/ICrypto.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -34,7 +34,7 @@
 #include <media/stagefright/NuMediaExtractor.h>
 #include <media/stagefright/RenderScriptWrapper.h>
 #include <OMX_IVCommon.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
 
 #include "RenderScript.h"
 #include "ScriptC_argbtorgba.h"
@@ -751,11 +751,12 @@
         const android::sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
         CHECK(display != nullptr);
 
-        DisplayInfo info;
-        CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+        DisplayConfig config;
+        CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
 
-        ssize_t displayWidth = info.w;
-        ssize_t displayHeight = info.h;
+        const ui::Size& resolution = config.resolution;
+        const ssize_t displayWidth = resolution.getWidth();
+        const ssize_t displayHeight = resolution.getHeight();
 
         ALOGV("display is %zd x %zd", displayWidth, displayHeight);
 
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 95a16f3..37091c4 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -17,12 +17,11 @@
 #include "SineSource.h"
 
 #include <binder/ProcessState.h>
+#include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaCodecSource.h>
@@ -33,6 +32,8 @@
 #include <media/stagefright/SimpleDecodingSource.h>
 #include <media/MediaPlayerInterface.h>
 
+#include "AudioPlayer.h"
+
 using namespace android;
 
 static const int32_t kAudioBitRate = 12200;
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index a63b9b9..01a178e 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include "SineSource.h"
-
 #include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -25,8 +23,8 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index bf36be0..c430f05 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -31,18 +31,15 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
-#include <media/ICrypto.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include "include/NuCachedSource2.h"
-#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/JPEGSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaCodec.h>
@@ -69,6 +66,8 @@
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
 
+#include "AudioPlayer.h"
+
 using namespace android;
 
 static long gNumRepetitions;
@@ -305,7 +304,7 @@
             seekTimeUs = -1;
 
             if (shouldSeek) {
-                seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
+                seekTimeUs = (rand() * (float)durationUs) / (float)RAND_MAX;
                 options.setSeekTo(seekTimeUs);
 
                 printf("seeking to %" PRId64 " us (%.2f secs)\n",
@@ -989,7 +988,7 @@
                 failed = false;
                 printf("getFrameAtTime(%s) => OK\n", filename);
 
-                VideoFrame *frame = (VideoFrame *)mem->pointer();
+                VideoFrame *frame = (VideoFrame *)mem->unsecurePointer();
 
                 CHECK_EQ(writeJpegFile("/sdcard/out.jpg",
                             frame->getFlattenedData(),
@@ -1086,7 +1085,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 35bdbc0..250d26b 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -21,14 +21,14 @@
 #include <binder/ProcessState.h>
 #include <cutils/properties.h> // for property_get
 
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IStreamSource.h>
 #include <media/mediaplayer.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MediaExtractor.h>
@@ -42,7 +42,7 @@
 #include <gui/Surface.h>
 
 #include <fcntl.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
 
 using namespace android;
 
@@ -116,7 +116,7 @@
 
     sp<IMemory> mem = mBuffers.itemAt(index);
 
-    ssize_t n = read(mFd, mem->pointer(), mem->size());
+    ssize_t n = read(mFd, mem->unsecurePointer(), mem->size());
     if (n <= 0) {
         mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
     } else {
@@ -164,7 +164,7 @@
     : mCurrentBufferIndex(-1),
       mCurrentBufferOffset(0) {
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
     CHECK(dataSource != NULL);
 
@@ -238,7 +238,7 @@
             copy = mem->size() - mCurrentBufferOffset;
         }
 
-        memcpy((uint8_t *)mem->pointer() + mCurrentBufferOffset, data, copy);
+        memcpy((uint8_t *)mem->unsecurePointer() + mCurrentBufferOffset, data, copy);
         mCurrentBufferOffset += copy;
 
         if (mCurrentBufferOffset == mem->size()) {
@@ -321,11 +321,12 @@
     const sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
     CHECK(display != nullptr);
 
-    DisplayInfo info;
-    CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+    DisplayConfig config;
+    CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
 
-    ssize_t displayWidth = info.w;
-    ssize_t displayHeight = info.h;
+    const ui::Size& resolution = config.resolution;
+    const ssize_t displayWidth = resolution.getWidth();
+    const ssize_t displayHeight = resolution.getHeight();
 
     ALOGV("display is %zd x %zd\n", displayWidth, displayHeight);
 
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
new file mode 100644
index 0000000..2595e3e
--- /dev/null
+++ b/drm/TEST_MAPPING
@@ -0,0 +1,27 @@
+{
+  "presubmit": [
+    // The following tests validate codec and drm path.
+    {
+      "name": "GtsMediaTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+        }
+      ]
+    },
+    {
+      "name": "GtsExoPlayerTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.SocPresubmit"
+        },
+        {
+          "include-filter": "com.google.android.exoplayer.gts.DashTest#testWidevine23FpsH264Fixed"
+        }
+      ]
+    }
+  ]
+}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index c25a0a1..b68e6c2 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -24,12 +24,15 @@
     ],
 
     shared_libs: [
-        "libmedia",
+        "libmediametrics",
+        "libmediautils",
+        "libcutils",
         "libutils",
         "liblog",
         "libbinder",
         "libdl",
         "libselinux",
+        "libstagefright_foundation",
     ],
 
     static_libs: ["libdrmframeworkcommon"],
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index afbcb39..9a32cc5 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -16,10 +16,14 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmManager(Native)"
-#include "utils/Log.h"
 
+#include <cutils/properties.h>
 #include <utils/String8.h>
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
 #include <drm/DrmInfo.h>
+
 #include <drm/DrmInfoEvent.h>
 #include <drm/DrmRights.h>
 #include <drm/DrmConstraints.h>
@@ -28,17 +32,36 @@
 #include <drm/DrmInfoRequest.h>
 #include <drm/DrmSupportInfo.h>
 #include <drm/DrmConvertedStatus.h>
+#include <media/MediaMetricsItem.h>
 #include <IDrmEngine.h>
 
 #include "DrmManager.h"
 #include "ReadWriteUtils.h"
 
+#include <algorithm>
+
 #define DECRYPT_FILE_ERROR (-1)
 
 using namespace android;
 
 const String8 DrmManager::EMPTY_STRING("");
 
+const std::map<const char*, size_t> DrmManager::kMethodIdMap {
+    {"getConstraints"     , DrmManagerMethodId::GET_CONSTRAINTS       },
+    {"getMetadata"        , DrmManagerMethodId::GET_METADATA          },
+    {"canHandle"          , DrmManagerMethodId::CAN_HANDLE            },
+    {"processDrmInfo"     , DrmManagerMethodId::PROCESS_DRM_INFO      },
+    {"acquireDrmInfo"     , DrmManagerMethodId::ACQUIRE_DRM_INFO      },
+    {"saveRights"         , DrmManagerMethodId::SAVE_RIGHTS           },
+    {"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
+    {"getDrmObjectType"   , DrmManagerMethodId::GET_DRM_OBJECT_TYPE   },
+    {"checkRightsStatus"  , DrmManagerMethodId::CHECK_RIGHTS_STATUS   },
+    {"removeRights"       , DrmManagerMethodId::REMOVE_RIGHTS         },
+    {"removeAllRights"    , DrmManagerMethodId::REMOVE_ALL_RIGHTS     },
+    {"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION  },
+    {"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION  }
+};
+
 DrmManager::DrmManager() :
     mDecryptSessionId(0),
     mConvertId(0) {
@@ -47,7 +70,104 @@
 }
 
 DrmManager::~DrmManager() {
+    if (mMetricsLooper != NULL) {
+        mMetricsLooper->stop();
+    }
+    flushEngineMetrics();
+}
 
+void DrmManager::initMetricsLooper() {
+    if (mMetricsLooper != NULL) {
+        return;
+    }
+    mMetricsLooper = new ALooper;
+    mMetricsLooper->setName("DrmManagerMetricsLooper");
+    mMetricsLooper->start();
+    mMetricsLooper->registerHandler(this);
+
+    sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
+    msg->post(getMetricsFlushPeriodUs());
+}
+
+void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatFlushMetrics:
+        {
+            flushEngineMetrics();
+            msg->post(getMetricsFlushPeriodUs());
+            break;
+        }
+        default:
+        {
+            ALOGW("Unrecognized message type: %zd", msg->what());
+        }
+    }
+}
+
+int64_t DrmManager::getMetricsFlushPeriodUs() {
+    return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
+}
+
+void DrmManager::recordEngineMetrics(
+        const char func[], const String8& plugInId8, const String8& mimeType) {
+    IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
+    std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
+    ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
+
+    Mutex::Autolock _l(mMetricsLock);
+    auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
+    if (metrics.mPluginId.empty()) {
+        metrics.mPluginId = plugInId;
+        metrics.mCallingUid = callingUid;
+        if (NULL != info) {
+            metrics.mDescription = info->getDescription().c_str();
+        }
+    }
+
+    if (!mimeType.isEmpty()) {
+        metrics.mMimeTypes.insert(mimeType.c_str());
+    } else if (NULL != info) {
+        DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
+        while (mimeIter.hasNext()) {
+            metrics.mMimeTypes.insert(mimeIter.next().c_str());
+        }
+    }
+
+    size_t methodId = kMethodIdMap.at(func);
+    if (methodId < metrics.mMethodCounts.size()) {
+        metrics.mMethodCounts[methodId]++;
+    }
+}
+
+void DrmManager::flushEngineMetrics() {
+    using namespace std::string_literals;
+    Mutex::Autolock _l(mMetricsLock);
+    for (auto kv : mPluginMetrics) {
+        DrmManagerMetrics& metrics = kv.second;
+        std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
+        item->setUid(metrics.mCallingUid);
+        item->setCString("plugin_id", metrics.mPluginId.c_str());
+        item->setCString("description", metrics.mDescription.c_str());
+
+        std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
+        std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
+        for (size_t i = 1; i < mimeTypes.size() ; i++) {
+            mimeTypesStr.append(",").append(mimeTypes[i]);
+        }
+        item->setCString("mime_types", mimeTypesStr.c_str());
+
+        for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
+            item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
+        }
+
+        if (!item->selfrecord()) {
+            ALOGE("Failed to record metrics");
+        }
+    }
+    mPluginMetrics.clear();
 }
 
 int DrmManager::addUniqueId(bool isNative) {
@@ -152,22 +272,30 @@
 
 DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
     Mutex::Autolock _l(mLock);
+    DrmConstraints *constraints = NULL;
     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.getConstraints(uniqueId, path, action);
+        constraints = rDrmEngine.getConstraints(uniqueId, path, action);
     }
-    return NULL;
+    if (NULL != constraints) {
+        recordEngineMetrics(__func__, plugInId);
+    }
+    return constraints;
 }
 
 DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
     Mutex::Autolock _l(mLock);
+    DrmMetadata *meta = NULL;
     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.getMetadata(uniqueId, path);
+        meta = rDrmEngine.getMetadata(uniqueId, path);
     }
-    return NULL;
+    if (NULL != meta) {
+        recordEngineMetrics(__func__, plugInId);
+    }
+    return meta;
 }
 
 bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
@@ -175,6 +303,10 @@
     const String8 plugInId = getSupportedPlugInId(mimeType);
     bool result = (EMPTY_STRING != plugInId) ? true : false;
 
+    if (result) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
+
     if (0 < path.length()) {
         if (result) {
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
@@ -191,12 +323,17 @@
 
 DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
     Mutex::Autolock _l(mLock);
-    const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
+    DrmInfoStatus *infoStatus = NULL;
+    const String8 mimeType = drmInfo->getMimeType();
+    const String8 plugInId = getSupportedPlugInId(mimeType);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
+        infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
     }
-    return NULL;
+    if (NULL != infoStatus) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
+    return infoStatus;
 }
 
 bool DrmManager::canHandle(int uniqueId, const String8& path) {
@@ -208,6 +345,7 @@
         result = rDrmEngine.canHandle(uniqueId, path);
 
         if (result) {
+            recordEngineMetrics(__func__, plugInPathList[i]);
             break;
         }
     }
@@ -216,54 +354,75 @@
 
 DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
     Mutex::Autolock _l(mLock);
-    const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
+    DrmInfo *info = NULL;
+    const String8 mimeType = drmInfoRequest->getMimeType();
+    const String8 plugInId = getSupportedPlugInId(mimeType);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
+        info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
     }
-    return NULL;
+    if (NULL != info) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
+    return info;
 }
 
 status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
             const String8& rightsPath, const String8& contentPath) {
     Mutex::Autolock _l(mLock);
-    const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
+    const String8 mimeType = drmRights.getMimeType();
+    const String8 plugInId = getSupportedPlugInId(mimeType);
     status_t result = DRM_ERROR_UNKNOWN;
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
         result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
     }
+    if (DRM_NO_ERROR == result) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
     return result;
 }
 
 String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
     Mutex::Autolock _l(mLock);
+    String8 mimeType(EMPTY_STRING);
     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
+        mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
     }
-    return EMPTY_STRING;
+    if (!mimeType.isEmpty()) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
+    return mimeType;
 }
 
 int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
     Mutex::Autolock _l(mLock);
+    int type = DrmObjectType::UNKNOWN;
     const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
+        type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
     }
-    return DrmObjectType::UNKNOWN;
+    if (DrmObjectType::UNKNOWN != type) {
+        recordEngineMetrics(__func__, plugInId, mimeType);
+    }
+    return type;
 }
 
 int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
     Mutex::Autolock _l(mLock);
+    int rightsStatus = RightsStatus::RIGHTS_INVALID;
     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
     if (EMPTY_STRING != plugInId) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
-        return rDrmEngine.checkRightsStatus(uniqueId, path, action);
+        rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
     }
-    return RightsStatus::RIGHTS_INVALID;
+    if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
+        recordEngineMetrics(__func__, plugInId);
+    }
+    return rightsStatus;
 }
 
 status_t DrmManager::consumeRights(
@@ -307,6 +466,9 @@
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
         result = rDrmEngine.removeRights(uniqueId, path);
     }
+    if (DRM_NO_ERROR == result) {
+        recordEngineMetrics(__func__, plugInId);
+    }
     return result;
 }
 
@@ -319,6 +481,7 @@
         if (DRM_NO_ERROR != result) {
             break;
         }
+        recordEngineMetrics(__func__, plugInIdList[index]);
     }
     return result;
 }
@@ -335,6 +498,7 @@
             ++mConvertId;
             convertId = mConvertId;
             mConvertSessionMap.add(convertId, &rDrmEngine);
+            recordEngineMetrics(__func__, plugInId, mimeType);
         }
     }
     return convertId;
@@ -415,6 +579,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+                recordEngineMetrics(__func__, plugInId, String8(mime));
                 break;
             }
         }
@@ -443,6 +608,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+                recordEngineMetrics(__func__, plugInId, String8(mime));
                 break;
             }
         }
@@ -472,6 +638,7 @@
             if (DRM_NO_ERROR == result) {
                 ++mDecryptSessionId;
                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+                recordEngineMetrics(__func__, plugInId, mimeType);
                 break;
             }
         }
diff --git a/drm/drmserver/DrmManager.h b/drm/drmserver/DrmManager.h
index 26222bc..350fcf4 100644
--- a/drm/drmserver/DrmManager.h
+++ b/drm/drmserver/DrmManager.h
@@ -17,13 +17,26 @@
 #ifndef __DRM_MANAGER_H__
 #define __DRM_MANAGER_H__
 
+#include <drm/drm_framework_common.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <sys/types.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
-#include <drm/drm_framework_common.h>
+
 #include "IDrmEngine.h"
 #include "PlugInManager.h"
 #include "IDrmServiceListener.h"
 
+#include <array>
+#include <cstddef>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
 namespace android {
 
 class IDrmManager;
@@ -40,6 +53,31 @@
 class DrmSupportInfo;
 class ActionDescription;
 
+enum DrmManagerMethodId {
+  GET_CONSTRAINTS,
+  GET_METADATA,
+  CAN_HANDLE,
+  PROCESS_DRM_INFO,
+  ACQUIRE_DRM_INFO,
+  SAVE_RIGHTS,
+  GET_ORIGINAL_MIME_TYPE,
+  GET_DRM_OBJECT_TYPE,
+  CHECK_RIGHTS_STATUS,
+  REMOVE_RIGHTS,
+  REMOVE_ALL_RIGHTS,
+  OPEN_CONVERT_SESSION,
+  OPEN_DECRYPT_SESSION,
+  NUM_METHODS,
+};
+
+struct DrmManagerMetrics {
+    std::string mPluginId;
+    std::string mDescription;
+    std::set<std::string> mMimeTypes;
+    std::array<int64_t, DrmManagerMethodId::NUM_METHODS> mMethodCounts{};
+    uid_t mCallingUid;
+};
+
 /**
  * This is implementation class for DRM Manager. This class delegates the
  * functionality to corresponding DRM Engine.
@@ -47,7 +85,7 @@
  * The DrmManagerService class creates an instance of this class.
  *
  */
-class DrmManager : public IDrmEngine::OnInfoListener {
+class DrmManager : public AHandler, public IDrmEngine::OnInfoListener {
 public:
     DrmManager();
     virtual ~DrmManager();
@@ -134,6 +172,8 @@
 
     void onInfo(const DrmInfoEvent& event);
 
+    void initMetricsLooper();
+
 private:
     String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
 
@@ -143,13 +183,24 @@
 
     bool canHandle(int uniqueId, const String8& path);
 
+    void onMessageReceived(const sp<AMessage> &msg);
+
+    int64_t getMetricsFlushPeriodUs();
+
+    void recordEngineMetrics(const char func[],
+            const String8& plugInId, const String8& mimeType = String8(""));
+
+    void flushEngineMetrics();
+
 private:
     enum {
         kMaxNumUniqueIds = 0x1000,
+        kWhatFlushMetrics = 'metr',
     };
 
     bool mUniqueIdArray[kMaxNumUniqueIds];
     static const String8 EMPTY_STRING;
+    static const std::map<const char*, size_t> kMethodIdMap;
 
     int mDecryptSessionId;
     int mConvertId;
@@ -157,11 +208,15 @@
     Mutex mListenerLock;
     Mutex mDecryptLock;
     Mutex mConvertLock;
+    Mutex mMetricsLock;
     TPlugInManager<IDrmEngine> mPlugInManager;
     KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
     KeyedVector< int, IDrmEngine*> mConvertSessionMap;
     KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
     KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+
+    std::map<std::pair<uid_t, std::string>, DrmManagerMetrics> mPluginMetrics;
+    sp<ALooper> mMetricsLooper;
 };
 
 };
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 2600a2c..c830c6e 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -19,7 +19,7 @@
 #include <utils/Log.h>
 
 #include <private/android_filesystem_config.h>
-#include <media/MemoryLeakTrackUtil.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
 
 #include <errno.h>
 #include <utils/threads.h>
@@ -130,13 +130,14 @@
         mDrmManager(NULL) {
     ALOGV("created");
     mDrmManager = new DrmManager();
+    mDrmManager->initMetricsLooper();
     mDrmManager->loadPlugIns();
 }
 
 DrmManagerService::~DrmManagerService() {
     ALOGV("Destroyed");
     mDrmManager->unloadPlugIns();
-    delete mDrmManager; mDrmManager = NULL;
+    mDrmManager = NULL;
 }
 
 int DrmManagerService::addUniqueId(bool isNative) {
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index 2e27a3c..f9b8bef 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -142,7 +142,7 @@
     virtual status_t dump(int fd, const Vector<String16>& args);
 
 private:
-    DrmManager* mDrmManager;
+    sp<DrmManager> mDrmManager;
 };
 
 };
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index d6db1d4..1700a95 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -2,39 +2,67 @@
 // libmediadrm
 //
 
-// TODO: change it back to cc_library_shared when MediaPlayer2 switches to
-// using NdkMediaDrm, instead of MediaDrm.java.
-cc_library {
+cc_library_headers {
+    name: "libmediadrm_headers",
+
+    export_include_dirs: [
+        "interface"
+    ],
+
+}
+
+cc_library_shared {
     name: "libmediadrm",
 
     srcs: [
         "DrmPluginPath.cpp",
         "DrmSessionManager.cpp",
-        "ICrypto.cpp",
-        "IDrm.cpp",
-        "IDrmClient.cpp",
-        "IMediaDrmService.cpp",
         "SharedLibrary.cpp",
         "DrmHal.cpp",
         "CryptoHal.cpp",
+        "DrmUtils.cpp",
+    ],
+
+    local_include_dirs: [
+        "include",
+        "interface"
+    ],
+
+    export_include_dirs: [
+        "include"
+    ],
+
+    header_libs: [
+        "libmedia_headers",
     ],
 
     shared_libs: [
-        "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libdl",
         "liblog",
+        "libmedia",
         "libmediadrmmetrics_lite",
-        "libmediametrics",
+        "libmediametrics#1",
         "libmediautils",
         "libstagefright_foundation",
         "libutils",
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
+        "android.hardware.drm@1.3",
         "libhidlallocatorutils",
         "libhidlbase",
-        "libhidltransport",
+    ],
+
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
     ],
 
     cflags: [
@@ -52,16 +80,21 @@
         "protos/metrics.proto",
     ],
 
+    local_include_dirs: [
+        "include"
+    ],
+
     proto: {
         export_proto_headers: true,
         type: "lite",
     },
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
-        "libbinder",
-        "libhidlbase",
         "liblog",
         "libmediametrics",
         "libprotobuf-cpp-lite",
@@ -83,17 +116,22 @@
         "protos/metrics.proto",
     ],
 
+    local_include_dirs: [
+        "include"
+    ],
+
     proto: {
         export_proto_headers: true,
         type: "full",
     },
+    header_libs: [
+        "libmedia_headers",
+    ],
     shared_libs: [
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
         "libbase",
-        "libbinder",
-        "libhidlbase",
         "liblog",
         "libmediametrics",
         "libprotobuf-cpp-full",
@@ -107,3 +145,30 @@
     ],
 }
 
+cc_library_shared {
+    name: "libmediadrmmetrics_consumer",
+    srcs: [
+        "DrmMetricsConsumer.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libmedia/include"
+    ],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libmediadrm",
+        "libmediadrmmetrics_full",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libmediametrics_headers",
+        "libstagefright_foundation_headers",
+    ],
+}
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index d62ccd6..18772e0 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -19,9 +19,8 @@
 #include <utils/Log.h>
 
 #include <android/hardware/drm/1.0/types.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
-
-#include <binder/IMemory.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -45,9 +44,9 @@
 using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hidl::manager::V1_0::IServiceManager;
 using ::android::sp;
 
 typedef drm::V1_2::Status Status_V1_2;
@@ -119,7 +118,6 @@
 CryptoHal::CryptoHal()
     : mFactories(makeCryptoFactories()),
       mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
-      mNextBufferId(0),
       mHeapSeqNum(0) {
 }
 
@@ -129,9 +127,9 @@
 Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
     Vector<sp<ICryptoFactory>> factories;
 
-    auto manager = ::IServiceManager::getService();
+    auto manager = hardware::defaultServiceManager1_2();
     if (manager != NULL) {
-        manager->listByInterface(drm::V1_0::ICryptoFactory::descriptor,
+        manager->listManifestByInterface(drm::V1_0::ICryptoFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
                     for (const auto &instance : registered) {
                         auto factory = drm::V1_0::ICryptoFactory::getService(instance);
@@ -142,7 +140,7 @@
                     }
                 }
             );
-        manager->listByInterface(drm::V1_1::ICryptoFactory::descriptor,
+        manager->listManifestByInterface(drm::V1_1::ICryptoFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
                     for (const auto &instance : registered) {
                         auto factory = drm::V1_1::ICryptoFactory::getService(instance);
@@ -252,26 +250,23 @@
 
 
 /**
- * If the heap base isn't set, get the heap base from the IMemory
+ * If the heap base isn't set, get the heap base from the HidlMemory
  * and send it to the HAL so it can map a remote heap of the same
  * size.  Once the heap base is established, shared memory buffers
  * are sent by providing an offset into the heap and a buffer size.
  */
-int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
-    using ::android::hardware::fromHeap;
-    using ::android::hardware::HidlMemory;
-
-    if (heap == NULL) {
-        ALOGE("setHeapBase(): heap is NULL");
+int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) {
+    if (heap == NULL || mHeapSeqNum < 0) {
+        ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
         return -1;
     }
 
     Mutex::Autolock autoLock(mLock);
 
     int32_t seqNum = mHeapSeqNum++;
-    sp<HidlMemory> hidlMemory = fromHeap(heap);
-    mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize()));
-    Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++);
+    uint32_t bufferId = static_cast<uint32_t>(seqNum);
+    mHeapSizes.add(seqNum, heap->size());
+    Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
     return seqNum;
 }
@@ -286,60 +281,40 @@
      * TODO: Add a releaseSharedBuffer method in a future DRM HAL
      * API version to make this explicit.
      */
-    ssize_t index = mHeapBases.indexOfKey(seqNum);
+    ssize_t index = mHeapSizes.indexOfKey(seqNum);
     if (index >= 0) {
         if (mPlugin != NULL) {
-            uint32_t bufferId = mHeapBases[index].getBufferId();
+            uint32_t bufferId = static_cast<uint32_t>(seqNum);
             Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
             ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
         }
-        mHeapBases.removeItem(seqNum);
+        mHeapSizes.removeItem(seqNum);
     }
 }
 
-status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
-    ssize_t offset;
-    size_t size;
-
-    if (memory == NULL || buffer == NULL) {
-        return UNEXPECTED_NULL;
-    }
-
-    sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
-    if (heap == NULL) {
-        return UNEXPECTED_NULL;
-    }
-
+status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) {
+    int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
     // memory must be in one of the heaps that have been set
-    if (mHeapBases.indexOfKey(seqNum) < 0) {
+    if (mHeapSizes.indexOfKey(seqNum) < 0) {
         return UNKNOWN_ERROR;
     }
 
-    // heap must be the same size as the one that was set in setHeapBase
-    if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
-        android_errorWriteLog(0x534e4554, "76221123");
-        return UNKNOWN_ERROR;
-     }
-
     // memory must be within the address space of the heap
-    if (memory->pointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset()  ||
-            heap->getSize() < memory->offset() + memory->size() ||
-            SIZE_MAX - memory->offset() < memory->size()) {
+    size_t heapSize = mHeapSizes.valueFor(seqNum);
+    if (heapSize < buffer.offset + buffer.size ||
+            SIZE_MAX - buffer.offset < buffer.size) {
         android_errorWriteLog(0x534e4554, "76221123");
         return UNKNOWN_ERROR;
     }
 
-    buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
-    buffer->offset = offset >= 0 ? offset : 0;
-    buffer->size = size;
     return OK;
 }
 
 ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
         CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-        const ICrypto::SourceBuffer &source, size_t offset,
+        const ::SharedBuffer &hSource, size_t offset,
         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-        const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+        const ::DestinationBuffer &hDestination, AString *errorDetailMsg) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -377,28 +352,21 @@
     }
     auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
 
-    int32_t heapSeqNum = source.mHeapSeqNum;
     bool secure;
-    ::DestinationBuffer hDestination;
-    if (destination.mType == kDestinationTypeSharedMemory) {
-        hDestination.type = BufferType::SHARED_MEMORY;
-        status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
-                &hDestination.nonsecureMemory);
+    if (hDestination.type == BufferType::SHARED_MEMORY) {
+        status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
         if (status != OK) {
             return status;
         }
         secure = false;
-    } else if (destination.mType == kDestinationTypeNativeHandle) {
-        hDestination.type = BufferType::NATIVE_HANDLE;
-        hDestination.secureMemory = hidl_handle(destination.mHandle);
+    } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
         secure = true;
     } else {
         android_errorWriteLog(0x534e4554, "70526702");
         return UNKNOWN_ERROR;
     }
 
-    ::SharedBuffer hSource;
-    status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
+    status_t status = checkSharedBuffer(hSource);
     if (status != OK) {
         return status;
     }
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 919f4ee..f218041 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,14 +20,14 @@
 
 #include <utils/Log.h>
 
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <android/binder_manager.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
 #include <android/hardware/drm/1.2/types.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
-
 #include <media/EventMetric.h>
+#include <media/MediaMetrics.h>
 #include <media/PluginMetricsReporting.h>
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -38,6 +38,10 @@
 #include <mediadrm/DrmHal.h>
 #include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <mediadrm/DrmUtils.h>
+
+#include <vector>
 
 using drm::V1_0::KeyedVector;
 using drm::V1_0::KeyRequestType;
@@ -57,7 +61,6 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hidl::manager::V1_0::IServiceManager;
 using ::android::os::PersistableBundle;
 using ::android::sp;
 
@@ -97,17 +100,6 @@
 
 #define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
 
-static inline int getCallingPid() {
-    return IPCThreadState::self()->getCallingPid();
-}
-
-static bool checkPermission(const char* permissionString) {
-    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
-    bool ok = checkCallingPermission(String16(permissionString));
-    if (!ok) ALOGE("Request requires %s", permissionString);
-    return ok;
-}
-
 static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
     Vector<uint8_t> vector;
     vector.appendArray(vec.data(), vec.size());
@@ -295,28 +287,19 @@
     }
 }
 
-
 Mutex DrmHal::mLock;
 
-struct DrmSessionClient : public DrmSessionClientInterface {
-    explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
+struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
+    explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
+      : mSessionId(sessionId),
+        mDrm(drm) {}
 
-    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
-        sp<DrmHal> drm = mDrm.promote();
-        if (drm == NULL) {
-            return true;
-        }
-        status_t err = drm->closeSession(sessionId);
-        if (err != OK) {
-            return false;
-        }
-        drm->sendEvent(EventType::SESSION_RECLAIMED,
-                toHidlVec(sessionId), hidl_vec<uint8_t>());
-        return true;
-    }
+    ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+    ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
 
-protected:
-    virtual ~DrmSessionClient() {}
+    const Vector<uint8_t> mSessionId;
+
+    virtual ~DrmSessionClient();
 
 private:
     wp<DrmHal> mDrm;
@@ -324,9 +307,48 @@
     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
 };
 
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+    auto sessionId = mSessionId;
+    sp<DrmHal> drm = mDrm.promote();
+    if (drm == NULL) {
+        *_aidl_return = true;
+        return ::ndk::ScopedAStatus::ok();
+    }
+    status_t err = drm->closeSession(sessionId);
+    if (err != OK) {
+        *_aidl_return = false;
+        return ::ndk::ScopedAStatus::ok();
+    }
+    drm->sendEvent(EventType::SESSION_RECLAIMED,
+            toHidlVec(sessionId), hidl_vec<uint8_t>());
+    *_aidl_return = true;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
+    String8 name;
+    sp<DrmHal> drm = mDrm.promote();
+    if (drm == NULL) {
+        name.append("<deleted>");
+    } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK
+        || name.isEmpty()) {
+      name.append("<Get vendor failed or is empty>");
+    }
+    name.append("[");
+    for (size_t i = 0; i < mSessionId.size(); ++i) {
+        name.appendFormat("%02x", mSessionId[i]);
+    }
+    name.append("]");
+    *_aidl_return = name;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+DrmHal::DrmSessionClient::~DrmSessionClient() {
+    DrmSessionManager::Instance()->removeSession(mSessionId);
+}
+
 DrmHal::DrmHal()
-   : mDrmSessionClient(new DrmSessionClient(this)),
-     mFactories(makeDrmFactories()),
+   : mFactories(makeDrmFactories()),
      mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
 }
 
@@ -335,14 +357,13 @@
     auto openSessions = mOpenSessions;
     for (size_t i = 0; i < openSessions.size(); i++) {
         mLock.unlock();
-        closeSession(openSessions[i]);
+        closeSession(openSessions[i]->mSessionId);
         mLock.lock();
     }
     mOpenSessions.clear();
 }
 
 DrmHal::~DrmHal() {
-    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
 }
 
 void DrmHal::cleanup() {
@@ -368,44 +389,8 @@
     mPluginV1_2.clear();
 }
 
-Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
-    Vector<sp<IDrmFactory>> factories;
-
-    auto manager = hardware::defaultServiceManager1_2();
-
-    if (manager != NULL) {
-        manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor,
-                [&factories](const hidl_vec<hidl_string> &registered) {
-                    for (const auto &instance : registered) {
-                        auto factory = drm::V1_0::IDrmFactory::getService(instance);
-                        if (factory != NULL) {
-                            factories.push_back(factory);
-                        }
-                    }
-                }
-            );
-        manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor,
-                [&factories](const hidl_vec<hidl_string> &registered) {
-                    for (const auto &instance : registered) {
-                        auto factory = drm::V1_1::IDrmFactory::getService(instance);
-                        if (factory != NULL) {
-                            factories.push_back(factory);
-                        }
-                    }
-                }
-            );
-        manager->listByInterface(drm::V1_2::IDrmFactory::descriptor,
-                [&factories](const hidl_vec<hidl_string> &registered) {
-                    for (const auto &instance : registered) {
-                        auto factory = drm::V1_2::IDrmFactory::getService(instance);
-                        if (factory != NULL) {
-                            factories.push_back(factory);
-                        }
-                    }
-                }
-            );
-    }
-
+std::vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
+    std::vector<sp<IDrmFactory>> factories(DrmUtils::MakeDrmFactories());
     if (factories.size() == 0) {
         // must be in passthrough mode, load the default passthrough service
         auto passthrough = IDrmFactory::getService();
@@ -423,6 +408,7 @@
         const uint8_t uuid[16], const String8& appPackageName) {
     mAppPackageName = appPackageName;
     mMetrics.SetAppPackageName(appPackageName);
+    mMetrics.SetAppUid(AIBinder_getCallingUid());
 
     sp<IDrmPlugin> plugin;
     Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
@@ -449,12 +435,6 @@
 status_t DrmHal::setListener(const sp<IDrmClient>& listener)
 {
     Mutex::Autolock lock(mEventLock);
-    if (mListener != NULL){
-        IInterface::asBinder(mListener)->unlinkToDeath(this);
-    }
-    if (listener != NULL) {
-        IInterface::asBinder(listener)->linkToDeath(this);
-    }
     mListener = listener;
     return NO_ERROR;
 }
@@ -468,10 +448,6 @@
     mEventLock.unlock();
 
     if (listener != NULL) {
-        Parcel obj;
-        writeByteArray(obj, sessionId);
-        writeByteArray(obj, data);
-
         Mutex::Autolock lock(mNotifyLock);
         DrmPlugin::EventType eventType;
         switch(hEventType) {
@@ -493,7 +469,7 @@
         default:
             return Void();
         }
-        listener->notify(eventType, 0, &obj);
+        listener->sendEvent(eventType, sessionId, data);
     }
     return Void();
 }
@@ -506,12 +482,8 @@
     mEventLock.unlock();
 
     if (listener != NULL) {
-        Parcel obj;
-        writeByteArray(obj, sessionId);
-        obj.writeInt64(expiryTimeInMS);
-
         Mutex::Autolock lock(mNotifyLock);
-        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+        listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
     }
     return Void();
 }
@@ -528,21 +500,17 @@
 }
 
 Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
-        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        const hidl_vec<KeyStatus>& hKeyStatusList, bool hasNewUsableKey) {
 
     mEventLock.lock();
     sp<IDrmClient> listener = mListener;
     mEventLock.unlock();
 
     if (listener != NULL) {
-        Parcel obj;
-        writeByteArray(obj, sessionId);
-
-        size_t nKeys = keyStatusList.size();
-        obj.writeInt32(nKeys);
+        std::vector<DrmKeyStatus> keyStatusList;
+        size_t nKeys = hKeyStatusList.size();
         for (size_t i = 0; i < nKeys; ++i) {
-            const KeyStatus &keyStatus = keyStatusList[i];
-            writeByteArray(obj, keyStatus.keyId);
+            const KeyStatus &keyStatus = hKeyStatusList[i];
             uint32_t type;
             switch(keyStatus.type) {
             case KeyStatusType::USABLE:
@@ -565,19 +533,18 @@
                 type = DrmPlugin::kKeyStatusType_InternalError;
                 break;
             }
-            obj.writeInt32(type);
+            keyStatusList.push_back({type, keyStatus.keyId});
             mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
         }
-        obj.writeInt32(hasNewUsableKey);
 
         Mutex::Autolock lock(mNotifyLock);
-        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+        listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
     } else {
         // There's no listener. But we still want to count the key change
         // events.
-        size_t nKeys = keyStatusList.size();
+        size_t nKeys = hKeyStatusList.size();
         for (size_t i = 0; i < nKeys; i++) {
-            mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
+            mMetrics.mKeyStatusChangeCounter.Increment(hKeyStatusList[i].type);
         }
     }
 
@@ -592,10 +559,8 @@
     mEventLock.unlock();
 
     if (listener != NULL) {
-        Parcel obj;
-        writeByteArray(obj, sessionId);
         Mutex::Autolock lock(mNotifyLock);
-        listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+        listener->sendSessionLostState(sessionId);
     }
     return Void();
 }
@@ -740,7 +705,7 @@
             // reclaimSession may call back to closeSession, since mLock is
             // shared between Drm instances, we should unlock here to avoid
             // deadlock.
-            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+            retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
             mLock.lock();
         } else {
             retry = false;
@@ -748,9 +713,11 @@
     } while (retry);
 
     if (err == OK) {
-        DrmSessionManager::Instance()->addSession(getCallingPid(),
-                mDrmSessionClient, sessionId);
-        mOpenSessions.push(sessionId);
+        std::shared_ptr<DrmSessionClient> client =
+                ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
+        DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
+                std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
+        mOpenSessions.push_back(client);
         mMetrics.SetSessionStart(sessionId);
     }
 
@@ -766,9 +733,9 @@
     if (status.isOk()) {
         if (status == Status::OK) {
             DrmSessionManager::Instance()->removeSession(sessionId);
-            for (size_t i = 0; i < mOpenSessions.size(); i++) {
-                if (mOpenSessions[i] == sessionId) {
-                    mOpenSessions.removeAt(i);
+            for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+                if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+                    mOpenSessions.erase(i);
                     break;
                 }
             }
@@ -895,9 +862,8 @@
 status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
         Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
     Mutex::Autolock autoLock(mLock);
-    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
-
     INIT_CHECK();
+    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
@@ -1363,11 +1329,11 @@
     return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
 }
 
-status_t DrmHal::getMetrics(PersistableBundle* metrics) {
-    if (metrics == nullptr) {
+status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer> &consumer) {
+    if (consumer == nullptr) {
         return UNEXPECTED_NULL;
     }
-    mMetrics.Export(metrics);
+    consumer->consumeFrameworkMetrics(mMetrics);
 
     // Append vendor metrics if they are supported.
     if (mPluginV1_1 != NULL) {
@@ -1394,11 +1360,7 @@
                     if (status != Status::OK) {
                       ALOGV("Error getting plugin metrics: %d", status);
                     } else {
-                        PersistableBundle pluginBundle;
-                        if (MediaDrmMetrics::HidlMetricsToBundle(
-                                pluginMetrics, &pluginBundle) == OK) {
-                            metrics->putPersistableBundle(String16(vendor), pluginBundle);
-                        }
+                      consumer->consumeHidlMetrics(vendor, pluginMetrics);
                     }
                     err = toStatusT(status);
                 });
@@ -1532,10 +1494,6 @@
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
-        return -EPERM;
-    }
-
     DrmSessionManager::Instance()->useSession(sessionId);
 
     status_t err = UNKNOWN_ERROR;
@@ -1553,39 +1511,23 @@
     return hResult.isOk() ? err : DEAD_OBJECT;
 }
 
-void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
-{
-    cleanup();
-}
-
-void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
-{
-    if (vec.size()) {
-        obj.writeInt32(vec.size());
-        obj.write(vec.data(), vec.size());
-    } else {
-        obj.writeInt32(0);
-    }
-}
-
 void DrmHal::reportFrameworkMetrics() const
 {
-    std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));
-    item->generateSessionID();
-    item->setPkgName(mMetrics.GetAppPackageName().c_str());
+    mediametrics_handle_t item(mediametrics_create("mediadrm"));
+    mediametrics_setUid(item, mMetrics.GetAppUid());
     String8 vendor;
     String8 description;
     status_t result = getPropertyStringInternal(String8("vendor"), vendor);
     if (result != OK) {
         ALOGE("Failed to get vendor from drm plugin: %d", result);
     } else {
-        item->setCString("vendor", vendor.c_str());
+        mediametrics_setCString(item, "vendor", vendor.c_str());
     }
     result = getPropertyStringInternal(String8("description"), description);
     if (result != OK) {
         ALOGE("Failed to get description from drm plugin: %d", result);
     } else {
-        item->setCString("description", description.c_str());
+        mediametrics_setCString(item, "description", description.c_str());
     }
 
     std::string serializedMetrics;
@@ -1596,11 +1538,12 @@
     std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
                                                         serializedMetrics.size());
     if (!b64EncodedMetrics.empty()) {
-        item->setCString("serialized_metrics", b64EncodedMetrics.c_str());
+        mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
     }
-    if (!item->selfrecord()) {
+    if (!mediametrics_selfRecord(item)) {
         ALOGE("Failed to self record framework metrics");
     }
+    mediametrics_delete(item);
 }
 
 void DrmHal::reportPluginMetrics() const
@@ -1614,7 +1557,7 @@
         std::string metricsString = toBase64StringNoPad(metricsVector.array(),
                                                         metricsVector.size());
         status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
-                                                       description, mAppPackageName);
+                                                       description, mMetrics.GetAppUid());
         if (res != OK) {
             ALOGE("Metrics were retrieved but could not be reported: %d", res);
         }
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index 3080802..996fd19 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -29,143 +29,12 @@
 using ::android::String16;
 using ::android::String8;
 using ::android::drm_metrics::DrmFrameworkMetrics;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
 using ::android::hardware::drm::V1_0::EventType;
 using ::android::hardware::drm::V1_2::KeyStatusType;
 using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::os::PersistableBundle;
 
 namespace {
 
-template <typename T> std::string GetAttributeName(T type);
-
-template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
-    static const char *type_names[] = {"USABLE", "EXPIRED",
-                                       "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
-                                       "INTERNAL_ERROR"};
-    if (((size_t)type) > arraysize(type_names)) {
-        return "UNKNOWN_TYPE";
-    }
-    return type_names[(size_t)type];
-}
-
-template <> std::string GetAttributeName<EventType>(EventType type) {
-    static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
-                                       "KEY_EXPIRED", "VENDOR_DEFINED",
-                                       "SESSION_RECLAIMED"};
-    if (((size_t)type) > arraysize(type_names)) {
-        return "UNKNOWN_TYPE";
-    }
-    return type_names[(size_t)type];
-}
-
-template <typename T>
-void ExportCounterMetric(const android::CounterMetric<T> &counter,
-                         PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    std::string success_count_name = counter.metric_name() + ".ok.count";
-    std::string error_count_name = counter.metric_name() + ".error.count";
-    std::vector<int64_t> status_values;
-    counter.ExportValues(
-        [&](const android::status_t status, const int64_t value) {
-            if (status == android::OK) {
-                metrics->putLong(android::String16(success_count_name.c_str()),
-                                 value);
-            } else {
-                int64_t total_errors(0);
-                metrics->getLong(android::String16(error_count_name.c_str()),
-                                 &total_errors);
-                metrics->putLong(android::String16(error_count_name.c_str()),
-                                 total_errors + value);
-                status_values.push_back(status);
-            }
-        });
-    if (!status_values.empty()) {
-        std::string error_list_name = counter.metric_name() + ".error.list";
-        metrics->putLongVector(android::String16(error_list_name.c_str()),
-                               status_values);
-    }
-}
-
-template <typename T>
-void ExportCounterMetricWithAttributeNames(
-    const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    counter.ExportValues([&](const T &attribute, const int64_t value) {
-        std::string name = counter.metric_name() + "." +
-                           GetAttributeName(attribute) + ".count";
-        metrics->putLong(android::String16(name.c_str()), value);
-    });
-}
-
-template <typename T>
-void ExportEventMetric(const android::EventMetric<T> &event,
-                       PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    std::string success_count_name = event.metric_name() + ".ok.count";
-    std::string error_count_name = event.metric_name() + ".error.count";
-    std::string timing_name = event.metric_name() + ".ok.average_time_micros";
-    std::vector<int64_t> status_values;
-    event.ExportValues([&](const android::status_t &status,
-                           const android::EventStatistics &value) {
-        if (status == android::OK) {
-            metrics->putLong(android::String16(success_count_name.c_str()),
-                             value.count);
-            metrics->putLong(android::String16(timing_name.c_str()),
-                             value.mean);
-        } else {
-            int64_t total_errors(0);
-            metrics->getLong(android::String16(error_count_name.c_str()),
-                             &total_errors);
-            metrics->putLong(android::String16(error_count_name.c_str()),
-                             total_errors + value.count);
-            status_values.push_back(status);
-        }
-    });
-    if (!status_values.empty()) {
-        std::string error_list_name = event.metric_name() + ".error.list";
-        metrics->putLongVector(android::String16(error_list_name.c_str()),
-                               status_values);
-    }
-}
-
-void ExportSessionLifespans(
-    const std::map<std::string, std::pair<int64_t, int64_t>> &mSessionLifespans,
-    PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-
-    if (mSessionLifespans.empty()) {
-        return;
-    }
-
-    PersistableBundle startTimesBundle;
-    PersistableBundle endTimesBundle;
-    for (auto it = mSessionLifespans.begin(); it != mSessionLifespans.end();
-         it++) {
-        String16 key(it->first.c_str(), it->first.size());
-        startTimesBundle.putLong(key, it->second.first);
-        endTimesBundle.putLong(key, it->second.second);
-    }
-    metrics->putPersistableBundle(
-        android::String16("drm.mediadrm.session_start_times_ms"),
-        startTimesBundle);
-    metrics->putPersistableBundle(
-        android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
-}
-
 std::string ToHexString(const android::Vector<uint8_t> &sessionId) {
     std::ostringstream out;
     out << std::hex << std::setfill('0');
@@ -175,31 +44,6 @@
     return out.str();
 }
 
-template <typename CT>
-void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
-              const CT &value, PersistableBundle *bundle) {
-    switch (type) {
-    case DrmMetricGroup::ValueType::INT64_TYPE:
-        bundle->putLong(name, value.int64Value);
-        break;
-    case DrmMetricGroup::ValueType::DOUBLE_TYPE:
-        bundle->putDouble(name, value.doubleValue);
-        break;
-    case DrmMetricGroup::ValueType::STRING_TYPE:
-        bundle->putString(name, String16(value.stringValue.c_str()));
-        break;
-    default:
-        ALOGE("Unexpected value type: %hhu", type);
-    }
-}
-
-inline String16 MakeIndexString(unsigned int index) {
-  std::string str("[");
-  str.append(std::to_string(index));
-  str.append("]");
-  return String16(str.c_str());
-}
-
 } // namespace
 
 namespace android {
@@ -237,23 +81,6 @@
     }
 }
 
-void MediaDrmMetrics::Export(PersistableBundle *metrics) {
-    if (!metrics) {
-        ALOGE("metrics was unexpectedly null.");
-        return;
-    }
-    ExportCounterMetric(mOpenSessionCounter, metrics);
-    ExportCounterMetric(mCloseSessionCounter, metrics);
-    ExportEventMetric(mGetKeyRequestTimeUs, metrics);
-    ExportEventMetric(mProvideKeyResponseTimeUs, metrics);
-    ExportCounterMetric(mGetProvisionRequestCounter, metrics);
-    ExportCounterMetric(mProvideProvisionResponseCounter, metrics);
-    ExportCounterMetricWithAttributeNames(mKeyStatusChangeCounter, metrics);
-    ExportCounterMetricWithAttributeNames(mEventCounter, metrics);
-    ExportCounterMetric(mGetDeviceUniqueIdCounter, metrics);
-    ExportSessionLifespans(mSessionLifespans, metrics);
-}
-
 status_t MediaDrmMetrics::GetSerializedMetrics(std::string *serializedMetrics) {
 
     if (!serializedMetrics) {
@@ -361,62 +188,14 @@
     return OK;
 }
 
+std::map<std::string, std::pair<int64_t, int64_t>> MediaDrmMetrics::GetSessionLifespans() const {
+  return mSessionLifespans;
+}
+
 int64_t MediaDrmMetrics::GetCurrentTimeMs() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
     return ((int64_t)tv.tv_sec * 1000) + ((int64_t)tv.tv_usec / 1000);
 }
 
-status_t MediaDrmMetrics::HidlMetricsToBundle(
-    const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
-    PersistableBundle *bundleMetricGroups) {
-    if (bundleMetricGroups == nullptr) {
-        return UNEXPECTED_NULL;
-    }
-    if (hidlMetricGroups.size() == 0) {
-        return OK;
-    }
-
-    int groupIndex = 0;
-    std::map<String16, int> indexMap;
-    for (const auto &hidlMetricGroup : hidlMetricGroups) {
-        PersistableBundle bundleMetricGroup;
-        for (const auto &hidlMetric : hidlMetricGroup.metrics) {
-            String16 metricName(hidlMetric.name.c_str());
-            PersistableBundle bundleMetric;
-            // Add metric component values.
-            for (const auto &value : hidlMetric.values) {
-                SetValue(String16(value.componentName.c_str()), value.type,
-                         value, &bundleMetric);
-            }
-            // Set metric attributes.
-            PersistableBundle bundleMetricAttributes;
-            for (const auto &attribute : hidlMetric.attributes) {
-                SetValue(String16(attribute.name.c_str()), attribute.type,
-                         attribute, &bundleMetricAttributes);
-            }
-            // Add attributes to the bundle metric.
-            bundleMetric.putPersistableBundle(String16("attributes"),
-                                              bundleMetricAttributes);
-            // Add one layer of indirection, allowing for repeated metric names.
-            PersistableBundle repeatedMetrics;
-            bundleMetricGroup.getPersistableBundle(metricName,
-                                                   &repeatedMetrics);
-            int index = indexMap[metricName];
-            repeatedMetrics.putPersistableBundle(MakeIndexString(index),
-                                                 bundleMetric);
-            indexMap[metricName] = ++index;
-
-            // Add the bundle metric to the group of metrics.
-            bundleMetricGroup.putPersistableBundle(metricName,
-                                                   repeatedMetrics);
-        }
-        // Add the bundle metric group to the collection of groups.
-        bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
-                                                 bundleMetricGroup);
-    }
-
-    return OK;
-}
-
 } // namespace android
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
new file mode 100644
index 0000000..b47b4ff
--- /dev/null
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 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_TAG "DrmMetricsConsumer"
+
+#include <android-base/macros.h>
+#include <mediadrm/DrmMetricsConsumer.h>
+#include <mediadrm/DrmMetrics.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+using ::android::String16;
+using ::android::String8;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_2::KeyStatusType;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::os::PersistableBundle;
+
+namespace {
+
+template <typename T> std::string GetAttributeName(T type);
+
+template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
+    static const char *type_names[] = {"USABLE", "EXPIRED",
+                                       "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
+                                       "INTERNAL_ERROR"};
+    if (((size_t)type) > arraysize(type_names)) {
+        return "UNKNOWN_TYPE";
+    }
+    return type_names[(size_t)type];
+}
+
+template <> std::string GetAttributeName<EventType>(EventType type) {
+    static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
+                                       "KEY_EXPIRED", "VENDOR_DEFINED",
+                                       "SESSION_RECLAIMED"};
+    if (((size_t)type) > arraysize(type_names)) {
+        return "UNKNOWN_TYPE";
+    }
+    return type_names[(size_t)type];
+}
+
+template <typename T>
+void ExportCounterMetric(const android::CounterMetric<T> &counter,
+                         PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    std::string success_count_name = counter.metric_name() + ".ok.count";
+    std::string error_count_name = counter.metric_name() + ".error.count";
+    std::vector<int64_t> status_values;
+    counter.ExportValues(
+        [&](const android::status_t status, const int64_t value) {
+            if (status == android::OK) {
+                metrics->putLong(android::String16(success_count_name.c_str()),
+                                 value);
+            } else {
+                int64_t total_errors(0);
+                metrics->getLong(android::String16(error_count_name.c_str()),
+                                 &total_errors);
+                metrics->putLong(android::String16(error_count_name.c_str()),
+                                 total_errors + value);
+                status_values.push_back(status);
+            }
+        });
+    if (!status_values.empty()) {
+        std::string error_list_name = counter.metric_name() + ".error.list";
+        metrics->putLongVector(android::String16(error_list_name.c_str()),
+                               status_values);
+    }
+}
+
+template <typename T>
+void ExportCounterMetricWithAttributeNames(
+    const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    counter.ExportValues([&](const T &attribute, const int64_t value) {
+        std::string name = counter.metric_name() + "." +
+                           GetAttributeName(attribute) + ".count";
+        metrics->putLong(android::String16(name.c_str()), value);
+    });
+}
+
+template <typename T>
+void ExportEventMetric(const android::EventMetric<T> &event,
+                       PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+    std::string success_count_name = event.metric_name() + ".ok.count";
+    std::string error_count_name = event.metric_name() + ".error.count";
+    std::string timing_name = event.metric_name() + ".ok.average_time_micros";
+    std::vector<int64_t> status_values;
+    event.ExportValues([&](const android::status_t &status,
+                           const android::EventStatistics &value) {
+        if (status == android::OK) {
+            metrics->putLong(android::String16(success_count_name.c_str()),
+                             value.count);
+            metrics->putLong(android::String16(timing_name.c_str()),
+                             value.mean);
+        } else {
+            int64_t total_errors(0);
+            metrics->getLong(android::String16(error_count_name.c_str()),
+                             &total_errors);
+            metrics->putLong(android::String16(error_count_name.c_str()),
+                             total_errors + value.count);
+            status_values.push_back(status);
+        }
+    });
+    if (!status_values.empty()) {
+        std::string error_list_name = event.metric_name() + ".error.list";
+        metrics->putLongVector(android::String16(error_list_name.c_str()),
+                               status_values);
+    }
+}
+
+void ExportSessionLifespans(
+    const std::map<std::string, std::pair<int64_t, int64_t>> &sessionLifespans,
+    PersistableBundle *metrics) {
+    if (!metrics) {
+        ALOGE("metrics was unexpectedly null.");
+        return;
+    }
+
+    if (sessionLifespans.empty()) {
+        return;
+    }
+
+    PersistableBundle startTimesBundle;
+    PersistableBundle endTimesBundle;
+    for (auto it = sessionLifespans.begin(); it != sessionLifespans.end();
+         it++) {
+        String16 key(it->first.c_str(), it->first.size());
+        startTimesBundle.putLong(key, it->second.first);
+        endTimesBundle.putLong(key, it->second.second);
+    }
+    metrics->putPersistableBundle(
+        android::String16("drm.mediadrm.session_start_times_ms"),
+        startTimesBundle);
+    metrics->putPersistableBundle(
+        android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
+}
+
+template <typename CT>
+void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
+              const CT &value, PersistableBundle *bundle) {
+    switch (type) {
+    case DrmMetricGroup::ValueType::INT64_TYPE:
+        bundle->putLong(name, value.int64Value);
+        break;
+    case DrmMetricGroup::ValueType::DOUBLE_TYPE:
+        bundle->putDouble(name, value.doubleValue);
+        break;
+    case DrmMetricGroup::ValueType::STRING_TYPE:
+        bundle->putString(name, String16(value.stringValue.c_str()));
+        break;
+    default:
+        ALOGE("Unexpected value type: %hhu", type);
+    }
+}
+
+inline String16 MakeIndexString(unsigned int index) {
+  std::string str("[");
+  str.append(std::to_string(index));
+  str.append("]");
+  return String16(str.c_str());
+}
+
+} // namespace
+
+namespace android {
+
+status_t DrmMetricsConsumer::consumeFrameworkMetrics(const MediaDrmMetrics &metrics) {
+    ExportCounterMetric(metrics.mOpenSessionCounter, mBundle);
+    ExportCounterMetric(metrics.mCloseSessionCounter, mBundle);
+    ExportEventMetric(metrics.mGetKeyRequestTimeUs, mBundle);
+    ExportEventMetric(metrics.mProvideKeyResponseTimeUs, mBundle);
+    ExportCounterMetric(metrics.mGetProvisionRequestCounter, mBundle);
+    ExportCounterMetric(metrics.mProvideProvisionResponseCounter, mBundle);
+    ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, mBundle);
+    ExportCounterMetricWithAttributeNames(metrics.mEventCounter, mBundle);
+    ExportCounterMetric(metrics.mGetDeviceUniqueIdCounter, mBundle);
+    ExportSessionLifespans(metrics.GetSessionLifespans(), mBundle);
+    return android::OK;
+}
+
+status_t DrmMetricsConsumer::consumeHidlMetrics(
+        const String8 &vendor,
+        const hidl_vec<DrmMetricGroup> &pluginMetrics) {
+    PersistableBundle pluginBundle;
+    if (DrmMetricsConsumer::HidlMetricsToBundle(
+            pluginMetrics, &pluginBundle) == OK) {
+        mBundle->putPersistableBundle(String16(vendor), pluginBundle);
+    }
+    return android::OK;
+}
+
+status_t DrmMetricsConsumer::HidlMetricsToBundle(
+    const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
+    PersistableBundle *bundleMetricGroups) {
+    if (bundleMetricGroups == nullptr) {
+        return UNEXPECTED_NULL;
+    }
+    if (hidlMetricGroups.size() == 0) {
+        return OK;
+    }
+
+    int groupIndex = 0;
+    std::map<String16, int> indexMap;
+    for (const auto &hidlMetricGroup : hidlMetricGroups) {
+        PersistableBundle bundleMetricGroup;
+        for (const auto &hidlMetric : hidlMetricGroup.metrics) {
+            String16 metricName(hidlMetric.name.c_str());
+            PersistableBundle bundleMetric;
+            // Add metric component values.
+            for (const auto &value : hidlMetric.values) {
+                SetValue(String16(value.componentName.c_str()), value.type,
+                         value, &bundleMetric);
+            }
+            // Set metric attributes.
+            PersistableBundle bundleMetricAttributes;
+            for (const auto &attribute : hidlMetric.attributes) {
+                SetValue(String16(attribute.name.c_str()), attribute.type,
+                         attribute, &bundleMetricAttributes);
+            }
+            // Add attributes to the bundle metric.
+            bundleMetric.putPersistableBundle(String16("attributes"),
+                                              bundleMetricAttributes);
+            // Add one layer of indirection, allowing for repeated metric names.
+            PersistableBundle repeatedMetrics;
+            bundleMetricGroup.getPersistableBundle(metricName,
+                                                   &repeatedMetrics);
+            int index = indexMap[metricName];
+            repeatedMetrics.putPersistableBundle(MakeIndexString(index),
+                                                 bundleMetric);
+            indexMap[metricName] = ++index;
+
+            // Add the bundle metric to the group of metrics.
+            bundleMetricGroup.putPersistableBundle(metricName,
+                                                   repeatedMetrics);
+        }
+        // Add the bundle metric group to the collection of groups.
+        bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
+                                                 bundleMetricGroup);
+    }
+
+    return OK;
+}
+
+} // namespace android
+
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 375644c..5292705 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -18,17 +18,32 @@
 #define LOG_TAG "DrmSessionManager"
 #include <utils/Log.h>
 
-#include <binder/IPCThreadState.h>
-#include <binder/IProcessInfoService.h>
-#include <binder/IServiceManager.h>
-#include <media/stagefright/ProcessInfo.h>
-#include <mediadrm/DrmSessionClientInterface.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <aidl/android/media/MediaResourceParcel.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <cutils/properties.h>
+#include <mediadrm/DrmUtils.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <unistd.h>
 #include <utils/String8.h>
 
+#include <vector>
+
 namespace android {
 
+using aidl::android::media::MediaResourceParcel;
+
+namespace {
+void ResourceManagerServiceDied(void* cookie) {
+    auto thiz = static_cast<DrmSessionManager*>(cookie);
+    thiz->binderDied();
+}
+}
+
+using ::ndk::ScopedAStatus;
+
 static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
     String8 sessionIdStr;
     for (size_t i = 0; i < sessionId.size(); ++i) {
@@ -37,6 +52,30 @@
     return sessionIdStr;
 }
 
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
+    auto v = reinterpret_cast<const Byte *>(vector.array());
+    std::vector<Byte> vec(v, v + vector.size());
+    return vec;
+}
+
+static std::vector<MediaResourceParcel> toResourceVec(
+        const Vector<uint8_t> &sessionId, int64_t value) {
+    using Type = aidl::android::media::MediaResourceType;
+    using SubType = aidl::android::media::MediaResourceSubType;
+    std::vector<MediaResourceParcel> resources;
+    MediaResourceParcel resource{
+            Type::kDrmSession, SubType::kUnspecifiedSubType,
+            toStdVec<int8_t>(sessionId), value};
+    resources.push_back(resource);
+    return resources;
+}
+
+static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
+    ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+    return IResourceManagerService::fromBinder(binder);
+}
+
 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
     if (sessionId1.size() != sessionId2.size()) {
         return false;
@@ -51,189 +90,118 @@
 
 sp<DrmSessionManager> DrmSessionManager::Instance() {
     static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+    drmSessionManager->init();
     return drmSessionManager;
 }
 
 DrmSessionManager::DrmSessionManager()
-    : mProcessInfo(new ProcessInfo()),
-      mTime(0) {}
+    : DrmSessionManager(getResourceManagerService()) {
+}
 
-DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
-    : mProcessInfo(processInfo),
-      mTime(0) {}
+DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
+    : mService(service),
+      mInitialized(false),
+      mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
+    if (mService == NULL) {
+        ALOGE("Failed to init ResourceManagerService");
+    }
+}
 
-DrmSessionManager::~DrmSessionManager() {}
+DrmSessionManager::~DrmSessionManager() {
+    if (mService != NULL) {
+        AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+    }
+}
 
-void DrmSessionManager::addSession(
-        int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) {
-    ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(),
+void DrmSessionManager::init() {
+    Mutex::Autolock lock(mLock);
+    if (mInitialized) {
+        return;
+    }
+    mInitialized = true;
+    if (mService != NULL) {
+        AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+    }
+}
+
+void DrmSessionManager::addSession(int pid,
+        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());
 
     Mutex::Autolock lock(mLock);
-    SessionInfo info;
-    info.drm = drm;
-    info.sessionId = sessionId;
-    info.timeStamp = getTime_l();
-    ssize_t index = mSessionMap.indexOfKey(pid);
-    if (index < 0) {
-        // new pid
-        SessionInfos infosForPid;
-        infosForPid.push_back(info);
-        mSessionMap.add(pid, infosForPid);
-    } else {
-        mSessionMap.editValueAt(index).push_back(info);
+    if (mService == NULL) {
+        return;
     }
+
+    static int64_t clientId = 0;
+    mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
+    mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
 }
 
 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
     ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
 
     Mutex::Autolock lock(mLock);
-    for (size_t i = 0; i < mSessionMap.size(); ++i) {
-        SessionInfos& infos = mSessionMap.editValueAt(i);
-        for (size_t j = 0; j < infos.size(); ++j) {
-            SessionInfo& info = infos.editItemAt(j);
-            if (isEqualSessionId(sessionId, info.sessionId)) {
-                info.timeStamp = getTime_l();
-                return;
-            }
-        }
+    auto it = mSessionMap.find(toStdVec(sessionId));
+    if (mService == NULL || it == mSessionMap.end()) {
+        return;
     }
+
+    auto info = it->second;
+    mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
 }
 
 void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
     ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
 
     Mutex::Autolock lock(mLock);
-    for (size_t i = 0; i < mSessionMap.size(); ++i) {
-        SessionInfos& infos = mSessionMap.editValueAt(i);
-        for (size_t j = 0; j < infos.size(); ++j) {
-            if (isEqualSessionId(sessionId, infos[j].sessionId)) {
-                infos.removeAt(j);
-                return;
-            }
-        }
+    auto it = mSessionMap.find(toStdVec(sessionId));
+    if (mService == NULL || it == mSessionMap.end()) {
+        return;
     }
-}
 
-void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) {
-    ALOGV("removeDrm(%p)", drm.get());
-
-    Mutex::Autolock lock(mLock);
-    bool found = false;
-    for (size_t i = 0; i < mSessionMap.size(); ++i) {
-        SessionInfos& infos = mSessionMap.editValueAt(i);
-        for (size_t j = 0; j < infos.size();) {
-            if (infos[j].drm == drm) {
-                ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string());
-                j = infos.removeAt(j);
-                found = true;
-            } else {
-                ++j;
-            }
-        }
-        if (found) {
-            break;
-        }
-    }
+    auto info = it->second;
+    // removeClient instead of removeSession because each client has only one session
+    mService->removeClient(info.pid, info.clientId);
+    mSessionMap.erase(it);
 }
 
 bool DrmSessionManager::reclaimSession(int callingPid) {
     ALOGV("reclaimSession(%d)", callingPid);
 
-    sp<DrmSessionClientInterface> drm;
-    Vector<uint8_t> sessionId;
-    int lowestPriorityPid;
-    int lowestPriority;
-    {
-        Mutex::Autolock lock(mLock);
-        int callingPriority;
-        if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
-            return false;
-        }
-        if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
-            return false;
-        }
-        if (lowestPriority <= callingPriority) {
-            return false;
-        }
+    // unlock early because reclaimResource might callback into removeSession
+    mLock.lock();
+    std::shared_ptr<IResourceManagerService> service(mService);
+    mLock.unlock();
 
-        if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) {
-            return false;
-        }
-    }
-
-    if (drm == NULL) {
+    if (service == NULL) {
         return false;
     }
 
-    ALOGV("reclaim session(%s) opened by pid %d",
-            GetSessionIdString(sessionId).string(), lowestPriorityPid);
-
-    return drm->reclaimSession(sessionId);
+    // cannot update mSessionMap because we do not know which sessionId is reclaimed;
+    // we rely on IResourceManagerClient to removeSession in reclaimResource
+    Vector<uint8_t> dummy;
+    bool success;
+    ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+    return status.isOk() && success;
 }
 
-int64_t DrmSessionManager::getTime_l() {
-    return mTime++;
+size_t DrmSessionManager::getSessionCount() const {
+    Mutex::Autolock lock(mLock);
+    return mSessionMap.size();
 }
 
-bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
-    int pid = -1;
-    int priority = -1;
-    for (size_t i = 0; i < mSessionMap.size(); ++i) {
-        if (mSessionMap.valueAt(i).size() == 0) {
-            // no opened session by this process.
-            continue;
-        }
-        int tempPid = mSessionMap.keyAt(i);
-        int tempPriority;
-        if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
-            // shouldn't happen.
-            return false;
-        }
-        if (pid == -1) {
-            pid = tempPid;
-            priority = tempPriority;
-        } else {
-            if (tempPriority > priority) {
-                pid = tempPid;
-                priority = tempPriority;
-            }
-        }
-    }
-    if (pid != -1) {
-        *lowestPriorityPid = pid;
-        *lowestPriority = priority;
-    }
-    return (pid != -1);
+bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const {
+    Mutex::Autolock lock(mLock);
+    return mSessionMap.count(toStdVec(sessionId));
 }
 
-bool DrmSessionManager::getLeastUsedSession_l(
-        int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) {
-    ssize_t index = mSessionMap.indexOfKey(pid);
-    if (index < 0) {
-        return false;
-    }
-
-    int leastUsedIndex = -1;
-    int64_t minTs = LLONG_MAX;
-    const SessionInfos& infos = mSessionMap.valueAt(index);
-    for (size_t j = 0; j < infos.size(); ++j) {
-        if (leastUsedIndex == -1) {
-            leastUsedIndex = j;
-            minTs = infos[j].timeStamp;
-        } else {
-            if (infos[j].timeStamp < minTs) {
-                leastUsedIndex = j;
-                minTs = infos[j].timeStamp;
-            }
-        }
-    }
-    if (leastUsedIndex != -1) {
-        *drm = infos[leastUsedIndex].drm;
-        *sessionId = infos[leastUsedIndex].sessionId;
-    }
-    return (leastUsedIndex != -1);
+void DrmSessionManager::binderDied() {
+    ALOGW("ResourceManagerService died.");
+    Mutex::Autolock lock(mLock);
+    mService.reset();
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
new file mode 100644
index 0000000..d85fa61
--- /dev/null
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2019 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 "DrmUtils"
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.3/ICryptoFactory.h>
+#include <android/hardware/drm/1.3/IDrmFactory.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/HidlSupport.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/String16.h>
+#include <cutils/properties.h>
+
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/ICrypto.h>
+#include <mediadrm/IDrm.h>
+
+using HServiceManager = ::android::hidl::manager::V1_2::IServiceManager;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::drm;
+
+namespace android {
+namespace DrmUtils {
+
+namespace {
+
+template<typename Hal>
+Hal *MakeObject(status_t *pstatus) {
+    status_t err = OK;
+    status_t &status = pstatus ? *pstatus : err;
+    auto obj = new Hal();
+    status = obj->initCheck();
+    if (status != OK && status != NO_INIT) {
+        return NULL;
+    }
+    return obj;
+}
+
+template <typename Hal, typename V>
+void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
+    sp<HServiceManager> serviceManager = HServiceManager::getService();
+    if (serviceManager == nullptr) {
+        ALOGE("Failed to get service manager");
+        exit(-1);
+    }
+
+    serviceManager->listManifestByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> &registered) {
+        for (const auto &instance : registered) {
+            auto factory = Hal::getService(instance);
+            if (factory != nullptr) {
+                ALOGI("found %s %s", Hal::descriptor, instance.c_str());
+                if (!uuid || factory->isCryptoSchemeSupported(uuid)) {
+                    factories.push_back(factory);
+                }
+            }
+        }
+    });
+}
+
+hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+    hidl_vec<uint8_t> vec(size);
+    if (ptr != nullptr) {
+        memcpy(vec.data(), ptr, size);
+    }
+    return vec;
+}
+
+hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+    if (ptr == nullptr) {
+        return hidl_array<uint8_t, 16>();
+    }
+    return hidl_array<uint8_t, 16>(ptr);
+}
+
+sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
+                                     const uint8_t uuid[16], const char *appPackageName) {
+    sp<::V1_0::IDrmPlugin> plugin;
+    factory->createPlugin(toHidlArray16(uuid), hidl_string(appPackageName),
+                          [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+                              if (status != ::V1_0::Status::OK) {
+                                  return;
+                              }
+                              plugin = hPlugin;
+                          });
+    return plugin;
+}
+
+sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
+                                           const uint8_t uuid[16], const void *initData,
+                                           size_t initDataSize) {
+    sp<::V1_0::ICryptoPlugin> plugin;
+    factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
+                          [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+                              if (status != ::V1_0::Status::OK) {
+                                  return;
+                              }
+                              plugin = hPlugin;
+                          });
+    return plugin;
+}
+
+} // namespace
+
+bool UseDrmService() {
+    return property_get_bool("mediadrm.use_mediadrmserver", true);
+}
+
+sp<IDrm> MakeDrm(status_t *pstatus) {
+    return MakeObject<DrmHal>(pstatus);
+}
+
+sp<ICrypto> MakeCrypto(status_t *pstatus) {
+    return MakeObject<CryptoHal>(pstatus);
+}
+
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16]) {
+    std::vector<sp<::V1_0::IDrmFactory>> drmFactories;
+    MakeHidlFactories<::V1_0::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_1::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_2::IDrmFactory>(uuid, drmFactories);
+    MakeHidlFactories<::V1_3::IDrmFactory>(uuid, drmFactories);
+    return drmFactories;
+}
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+                                              const char *appPackageName) {
+    std::vector<sp<::V1_0::IDrmPlugin>> plugins;
+    for (const auto &factory : MakeDrmFactories(uuid)) {
+        plugins.push_back(MakeDrmPlugin(factory, uuid, appPackageName));
+    }
+    return plugins;
+}
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]) {
+    std::vector<sp<::V1_0::ICryptoFactory>> cryptoFactories;
+    MakeHidlFactories<::V1_0::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_2::ICryptoFactory>(uuid, cryptoFactories);
+    MakeHidlFactories<::V1_3::ICryptoFactory>(uuid, cryptoFactories);
+    return cryptoFactories;
+}
+
+std::vector<sp<ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16], const void *initData,
+                                                 size_t initDataSize) {
+    std::vector<sp<ICryptoPlugin>> plugins;
+    for (const auto &factory : MakeCryptoFactories(uuid)) {
+        plugins.push_back(MakeCryptoPlugin(factory, uuid, initData, initDataSize));
+    }
+    return plugins;
+}
+
+}  // namespace DrmUtils
+}  // namespace android
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
deleted file mode 100644
index 8d8d088..0000000
--- a/drm/libmediadrm/ICrypto.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (C) 2012 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 "ICrypto"
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <cutils/log.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/ICrypto.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
-    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
-    IS_CRYPTO_SUPPORTED,
-    CREATE_PLUGIN,
-    DESTROY_PLUGIN,
-    REQUIRES_SECURE_COMPONENT,
-    DECRYPT,
-    NOTIFY_RESOLUTION,
-    SET_MEDIADRM_SESSION,
-    SET_HEAP,
-    UNSET_HEAP,
-};
-
-struct BpCrypto : public BpInterface<ICrypto> {
-    explicit BpCrypto(const sp<IBinder> &impl)
-        : BpInterface<ICrypto>(impl) {
-    }
-
-    virtual status_t initCheck() const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        remote()->transact(INIT_CHECK, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
-
-        return reply.readInt32() != 0;
-    }
-
-    virtual status_t createPlugin(
-            const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeInt32(opaqueSize);
-
-        if (opaqueSize > 0) {
-            data.write(opaqueData, opaqueSize);
-        }
-
-        remote()->transact(CREATE_PLUGIN, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t destroyPlugin() {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        remote()->transact(DESTROY_PLUGIN, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual bool requiresSecureDecoderComponent(
-            const char *mime) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeCString(mime);
-        remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
-
-        return reply.readInt32() != 0;
-    }
-
-    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
-            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const SourceBuffer &source, size_t offset,
-            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const DestinationBuffer &destination, AString *errorDetailMsg) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        data.writeInt32(pattern.mEncryptBlocks);
-        data.writeInt32(pattern.mSkipBlocks);
-
-        static const uint8_t kDummy[16] = { 0 };
-
-        if (key == NULL) {
-            key = kDummy;
-        }
-
-        if (iv == NULL) {
-            iv = kDummy;
-        }
-
-        data.write(key, 16);
-        data.write(iv, 16);
-
-        size_t totalSize = 0;
-        for (size_t i = 0; i < numSubSamples; ++i) {
-            totalSize += subSamples[i].mNumBytesOfEncryptedData;
-            totalSize += subSamples[i].mNumBytesOfClearData;
-        }
-
-        data.writeInt32(totalSize);
-        data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
-        data.writeInt32(source.mHeapSeqNum);
-        data.writeInt32(offset);
-
-        data.writeInt32(numSubSamples);
-        data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
-        data.writeInt32((int32_t)destination.mType);
-        if (destination.mType == kDestinationTypeNativeHandle) {
-            if (destination.mHandle == NULL) {
-                return BAD_VALUE;
-            }
-            data.writeNativeHandle(destination.mHandle);
-        } else {
-            if (destination.mSharedMemory == NULL) {
-                return BAD_VALUE;
-            }
-            data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
-        }
-
-        remote()->transact(DECRYPT, data, &reply);
-
-        ssize_t result = reply.readInt32();
-
-        if (isCryptoError(result)) {
-            AString msg = reply.readCString();
-            if (errorDetailMsg) {
-                *errorDetailMsg = msg;
-            }
-        }
-
-        return result;
-    }
-
-    virtual void notifyResolution(
-        uint32_t width, uint32_t height) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(width);
-        data.writeInt32(height);
-        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
-    }
-
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
-
-        return reply.readInt32();
-    }
-
-    virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        status_t err = remote()->transact(SET_HEAP, data, &reply);
-        if (err != NO_ERROR) {
-            return -1;
-        }
-        int32_t seqNum;
-        if (reply.readInt32(&seqNum) != NO_ERROR) {
-            return -1;
-        }
-        return seqNum;
-    }
-
-    virtual void unsetHeap(int32_t seqNum) {
-        Parcel data, reply;
-        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(seqNum);
-        remote()->transact(UNSET_HEAP, data, &reply);
-        return;
-    }
-
-
-private:
-    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
-        uint32_t size = reply.readInt32();
-        vector.insertAt((size_t)0, size);
-        reply.read(vector.editArray(), size);
-    }
-
-    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
-        data.writeInt32(vector.size());
-        data.write(vector.array(), vector.size());
-    }
-
-    DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
-};
-
-IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
-    uint32_t size = data.readInt32();
-    if (vector.insertAt((size_t)0, size) < 0) {
-        vector.clear();
-    }
-    if (data.read(vector.editArray(), size) != NO_ERROR) {
-        vector.clear();
-        android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
-    }
-}
-
-void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
-    reply->writeInt32(vector.size());
-    reply->write(vector.array(), vector.size());
-}
-
-status_t BnCrypto::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch (code) {
-        case INIT_CHECK:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            reply->writeInt32(initCheck());
-
-            return OK;
-        }
-
-        case IS_CRYPTO_SUPPORTED:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            reply->writeInt32(isCryptoSchemeSupported(uuid));
-
-            return OK;
-        }
-
-        case CREATE_PLUGIN:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            uint8_t uuid[16] = {0};
-            if (data.read(uuid, sizeof(uuid)) != NO_ERROR) {
-                android_errorWriteLog(0x534e4554, "144767096");
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-
-            size_t opaqueSize = data.readInt32();
-            void *opaqueData = NULL;
-
-            const size_t kMaxOpaqueSize = 100 * 1024;
-            if (opaqueSize > kMaxOpaqueSize) {
-                return BAD_VALUE;
-            }
-
-            opaqueData = malloc(opaqueSize);
-            if (NULL == opaqueData) {
-                return NO_MEMORY;
-            }
-
-            if (data.read(opaqueData, opaqueSize) != NO_ERROR) {
-                android_errorWriteLog(0x534e4554, "144767096");
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-            reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
-
-            free(opaqueData);
-            opaqueData = NULL;
-
-            return OK;
-        }
-
-        case DESTROY_PLUGIN:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            reply->writeInt32(destroyPlugin());
-
-            return OK;
-        }
-
-        case REQUIRES_SECURE_COMPONENT:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            const char *mime = data.readCString();
-            if (mime == NULL) {
-                reply->writeInt32(BAD_VALUE);
-            } else {
-                reply->writeInt32(requiresSecureDecoderComponent(mime));
-            }
-
-            return OK;
-        }
-
-        case DECRYPT:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
-            CryptoPlugin::Pattern pattern;
-            pattern.mEncryptBlocks = data.readInt32();
-            pattern.mSkipBlocks = data.readInt32();
-
-            uint8_t key[16];
-            data.read(key, sizeof(key));
-
-            uint8_t iv[16];
-            data.read(iv, sizeof(iv));
-
-            size_t totalSize = data.readInt32();
-
-            SourceBuffer source;
-
-            source.mSharedMemory =
-                interface_cast<IMemory>(data.readStrongBinder());
-            if (source.mSharedMemory == NULL) {
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-            source.mHeapSeqNum = data.readInt32();
-
-            int32_t offset = data.readInt32();
-
-            int32_t numSubSamples = data.readInt32();
-            if (numSubSamples < 0 || numSubSamples > 0xffff) {
-                reply->writeInt32(BAD_VALUE);
-                return OK;
-            }
-
-            std::unique_ptr<CryptoPlugin::SubSample[]> subSamples =
-                    std::make_unique<CryptoPlugin::SubSample[]>(numSubSamples);
-
-            data.read(subSamples.get(),
-                    sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
-            DestinationBuffer destination;
-            destination.mType = (DestinationType)data.readInt32();
-            if (destination.mType == kDestinationTypeNativeHandle) {
-                destination.mHandle = data.readNativeHandle();
-                if (destination.mHandle == NULL) {
-                    reply->writeInt32(BAD_VALUE);
-                    return OK;
-                }
-            } else if (destination.mType == kDestinationTypeSharedMemory) {
-                destination.mSharedMemory =
-                        interface_cast<IMemory>(data.readStrongBinder());
-                if (destination.mSharedMemory == NULL) {
-                    reply->writeInt32(BAD_VALUE);
-                    return OK;
-                }
-                sp<IMemory> dest = destination.mSharedMemory;
-                if (totalSize > dest->size() ||
-                        (size_t)dest->offset() > dest->size() - totalSize) {
-                    reply->writeInt32(BAD_VALUE);
-                    android_errorWriteLog(0x534e4554, "71389378");
-                    return OK;
-                }
-            } else {
-                reply->writeInt32(BAD_VALUE);
-                android_errorWriteLog(0x534e4554, "70526702");
-                return OK;
-            }
-
-            AString errorDetailMsg;
-            ssize_t result;
-
-            size_t sumSubsampleSizes = 0;
-            bool overflow = false;
-            for (int32_t i = 0; i < numSubSamples; ++i) {
-                CryptoPlugin::SubSample &ss = subSamples[i];
-                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
-                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
-                } else {
-                    overflow = true;
-                }
-                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
-                    sumSubsampleSizes += ss.mNumBytesOfClearData;
-                } else {
-                    overflow = true;
-                }
-            }
-
-            if (overflow || sumSubsampleSizes != totalSize) {
-                result = -EINVAL;
-            } else if (totalSize > source.mSharedMemory->size()) {
-                result = -EINVAL;
-            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
-                result = -EINVAL;
-            } else {
-                result = decrypt(key, iv, mode, pattern, source, offset,
-                        subSamples.get(), numSubSamples, destination, &errorDetailMsg);
-            }
-
-            reply->writeInt32(result);
-
-            if (isCryptoError(result)) {
-                reply->writeCString(errorDetailMsg.c_str());
-            }
-
-            if (destination.mType == kDestinationTypeNativeHandle) {
-                int err;
-                if ((err = native_handle_close(destination.mHandle)) < 0) {
-                    ALOGW("secure buffer native_handle_close failed: %d", err);
-                }
-                if ((err = native_handle_delete(destination.mHandle)) < 0) {
-                    ALOGW("secure buffer native_handle_delete failed: %d", err);
-                }
-            }
-
-            subSamples.reset();
-            return OK;
-        }
-
-        case NOTIFY_RESOLUTION:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-
-            int32_t width = data.readInt32();
-            int32_t height = data.readInt32();
-            notifyResolution(width, height);
-
-            return OK;
-        }
-
-        case SET_MEDIADRM_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            reply->writeInt32(setMediaDrmSession(sessionId));
-            return OK;
-        }
-
-        case SET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            sp<IMemoryHeap> heap =
-                interface_cast<IMemoryHeap>(data.readStrongBinder());
-            reply->writeInt32(setHeap(heap));
-            return OK;
-        }
-
-        case UNSET_HEAP:
-        {
-            CHECK_INTERFACE(ICrypto, data, reply);
-            int32_t seqNum = data.readInt32();
-            unsetHeap(seqNum);
-            return OK;
-        }
-
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
deleted file mode 100644
index c2cc429..0000000
--- a/drm/libmediadrm/IDrm.cpp
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * Copyright (C) 2013 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 "IDrm"
-#include <utils/Log.h>
-
-#include <binder/Parcel.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/IDrm.h>
-
-namespace android {
-
-enum {
-    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
-    IS_CRYPTO_SUPPORTED,
-    CREATE_PLUGIN,
-    DESTROY_PLUGIN,
-    OPEN_SESSION,
-    CLOSE_SESSION,
-    GET_KEY_REQUEST,
-    PROVIDE_KEY_RESPONSE,
-    REMOVE_KEYS,
-    RESTORE_KEYS,
-    QUERY_KEY_STATUS,
-    GET_PROVISION_REQUEST,
-    PROVIDE_PROVISION_RESPONSE,
-    GET_SECURE_STOPS,
-    RELEASE_SECURE_STOPS,
-    GET_PROPERTY_STRING,
-    GET_PROPERTY_BYTE_ARRAY,
-    SET_PROPERTY_STRING,
-    SET_PROPERTY_BYTE_ARRAY,
-    GET_METRICS,
-    SET_CIPHER_ALGORITHM,
-    SET_MAC_ALGORITHM,
-    ENCRYPT,
-    DECRYPT,
-    SIGN,
-    SIGN_RSA,
-    VERIFY,
-    SET_LISTENER,
-    GET_SECURE_STOP,
-    REMOVE_ALL_SECURE_STOPS,
-    GET_HDCP_LEVELS,
-    GET_NUMBER_OF_SESSIONS,
-    GET_SECURITY_LEVEL,
-    REMOVE_SECURE_STOP,
-    GET_SECURE_STOP_IDS,
-    GET_OFFLINE_LICENSE_KEYSET_IDS,
-    REMOVE_OFFLINE_LICENSE,
-    GET_OFFLINE_LICENSE_STATE
-};
-
-struct BpDrm : public BpInterface<IDrm> {
-    explicit BpDrm(const sp<IBinder> &impl)
-        : BpInterface<IDrm>(impl) {
-    }
-
-    virtual status_t initCheck() const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        status_t status = remote()->transact(INIT_CHECK, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
-            DrmPlugin::SecurityLevel level, bool *isSupported) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeString8(mimeType);
-        data.writeInt32(level);
-
-        status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
-        if (status != OK) {
-            ALOGE("isCryptoSchemeSupported: binder call failed: %d", status);
-            return status;
-        }
-        *isSupported = static_cast<bool>(reply.readInt32());
-
-        return reply.readInt32();
-    }
-
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8& appPackageName) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.write(uuid, 16);
-        data.writeString8(appPackageName);
-        status_t status = remote()->transact(CREATE_PLUGIN, data, &reply);
-        if (status != OK) {
-            ALOGE("createPlugin: binder call failed: %d", status);
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t destroyPlugin() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        status_t status = remote()->transact(DESTROY_PLUGIN, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t openSession(DrmPlugin::SecurityLevel level,
-            Vector<uint8_t> &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.writeInt32(level);
-
-        status_t status = remote()->transact(OPEN_SESSION, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, sessionId);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(CLOSE_SESSION, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t
-        getKeyRequest(Vector<uint8_t> const &sessionId,
-                      Vector<uint8_t> const &initData,
-                      String8 const &mimeType, DrmPlugin::KeyType keyType,
-                      KeyedVector<String8, String8> const &optionalParameters,
-                      Vector<uint8_t> &request, String8 &defaultUrl,
-                      DrmPlugin::KeyRequestType *keyRequestType) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, initData);
-        data.writeString8(mimeType);
-        data.writeInt32((uint32_t)keyType);
-
-        data.writeInt32(optionalParameters.size());
-        for (size_t i = 0; i < optionalParameters.size(); ++i) {
-            data.writeString8(optionalParameters.keyAt(i));
-            data.writeString8(optionalParameters.valueAt(i));
-        }
-
-        status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, request);
-        defaultUrl = reply.readString8();
-        *keyRequestType = static_cast<DrmPlugin::KeyRequestType>(reply.readInt32());
-
-        return reply.readInt32();
-    }
-
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        writeVector(data, sessionId);
-        writeVector(data, response);
-
-        status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, keySetId);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(REMOVE_KEYS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(RESTORE_KEYS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                        KeyedVector<String8, String8> &infoMap) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(QUERY_KEY_STATUS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        infoMap.clear();
-        size_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            String8 key = reply.readString8();
-            String8 value = reply.readString8();
-            infoMap.add(key, value);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaultUrl) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(certType);
-        data.writeString8(certAuthority);
-        status_t status = remote()->transact(GET_PROVISION_REQUEST, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, request);
-        defaultUrl = reply.readString8();
-
-        return reply.readInt32();
-    }
-
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, response);
-        status_t status = remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, certificate);
-        readVector(reply, wrappedKey);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        secureStops.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> secureStop;
-            readVector(reply, secureStop);
-            secureStops.push_back(secureStop);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        secureStopIds.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> secureStopId;
-            readVector(reply, secureStopId);
-            secureStopIds.push_back(secureStopId);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssid);
-        status_t status = remote()->transact(GET_SECURE_STOP, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, secureStop);
-        return reply.readInt32();
-    }
-
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssRelease);
-        status_t status = remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, ssid);
-        status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t removeAllSecureStops() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t> > &keySetIds) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_OFFLINE_LICENSE_KEYSET_IDS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        keySetIds.clear();
-        uint32_t count = reply.readInt32();
-        for (size_t i = 0; i < count; i++) {
-            Vector<uint8_t> keySetId;
-            readVector(reply, keySetId);
-            keySetIds.push_back(keySetId);
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(REMOVE_OFFLINE_LICENSE, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
-            DrmPlugin::OfflineLicenseState *licenseState) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, keySetId);
-        status_t status = remote()->transact(GET_OFFLINE_LICENSE_STATE, data, &reply);
-        if (status != OK) {
-            *licenseState = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown;
-            return status;
-        }
-        *licenseState = static_cast<DrmPlugin::OfflineLicenseState>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getPropertyString(String8 const &name, String8 &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        status_t status = remote()->transact(GET_PROPERTY_STRING, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        value = reply.readString8();
-        return reply.readInt32();
-    }
-
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connected,
-            DrmPlugin::HdcpLevel *max) const {
-        Parcel data, reply;
-
-        if (connected == NULL || max == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_HDCP_LEVELS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *connected = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
-        *max = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getNumberOfSessions(uint32_t *open, uint32_t *max) const {
-        Parcel data, reply;
-
-        if (open == NULL || max == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_NUMBER_OF_SESSIONS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *open = reply.readInt32();
-        *max = reply.readInt32();
-        return reply.readInt32();
-    }
-
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
-            DrmPlugin::SecurityLevel *level) const {
-        Parcel data, reply;
-
-        if (level == NULL) {
-            return BAD_VALUE;
-        }
-
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        status_t status = remote()->transact(GET_SECURITY_LEVEL, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        *level = static_cast<DrmPlugin::SecurityLevel>(reply.readInt32());
-        return reply.readInt32();
-    }
-
-    virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        status_t status = remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        readVector(reply, value);
-        return reply.readInt32();
-    }
-
-    virtual status_t setPropertyString(String8 const &name, String8 const &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        data.writeString8(value);
-        status_t status = remote()->transact(SET_PROPERTY_STRING, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value) const {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeString8(name);
-        writeVector(data, value);
-        status_t status = remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-
-        return reply.readInt32();
-    }
-
-    virtual status_t getMetrics(os::PersistableBundle *metrics) {
-        if (metrics == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        status_t status = remote()->transact(GET_METRICS, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        // The reply data is ordered as
-        // 1) 32 bit integer reply followed by
-        // 2) Serialized PersistableBundle containing metrics.
-        status_t reply_status;
-        if (reply.readInt32(&reply_status) != OK
-           || reply_status != OK) {
-          ALOGE("Failed to read getMetrics response code from parcel. %d",
-                reply_status);
-          return reply_status;
-        }
-
-        status = metrics->readFromParcel(&reply);
-        if (status != OK) {
-            ALOGE("Failed to read metrics from parcel. %d", status);
-            return status;
-        }
-        return reply_status;
-    }
-
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        status_t status = remote()->transact(SET_CIPHER_ALGORITHM, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        status_t status = remote()->transact(SET_MAC_ALGORITHM, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, input);
-        writeVector(data, iv);
-
-        status_t status = remote()->transact(ENCRYPT, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, output);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, input);
-        writeVector(data, iv);
-
-        status_t status = remote()->transact(DECRYPT, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, output);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, message);
-
-        status_t status = remote()->transact(SIGN, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, signature);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        writeVector(data, keyId);
-        writeVector(data, message);
-        writeVector(data, signature);
-
-        status_t status = remote()->transact(VERIFY, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        match = (bool)reply.readInt32();
-        return reply.readInt32();
-    }
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
-                             Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        writeVector(data, sessionId);
-        data.writeString8(algorithm);
-        writeVector(data, message);
-        writeVector(data, wrappedKey);
-
-        status_t status = remote()->transact(SIGN_RSA, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        readVector(reply, signature);
-
-        return reply.readInt32();
-    }
-
-    virtual status_t setListener(const sp<IDrmClient>& listener) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(listener));
-        status_t status = remote()->transact(SET_LISTENER, data, &reply);
-        if (status != OK) {
-            return status;
-        }
-        return reply.readInt32();
-    }
-
-private:
-    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
-        uint32_t size = reply.readInt32();
-        vector.insertAt((size_t)0, size);
-        reply.read(vector.editArray(), size);
-    }
-
-    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
-        data.writeInt32(vector.size());
-        data.write(vector.array(), vector.size());
-    }
-
-    DISALLOW_EVIL_CONSTRUCTORS(BpDrm);
-};
-
-IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
-    uint32_t size = data.readInt32();
-    if (vector.insertAt((size_t)0, size) < 0) {
-        vector.clear();
-    }
-    if (data.read(vector.editArray(), size) != NO_ERROR) {
-        vector.clear();
-        android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
-    }
-}
-
-void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
-    reply->writeInt32(vector.size());
-    reply->write(vector.array(), vector.size());
-}
-
-status_t BnDrm::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch (code) {
-        case INIT_CHECK:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(initCheck());
-            return OK;
-        }
-
-        case IS_CRYPTO_SUPPORTED:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            String8 mimeType = data.readString8();
-            DrmPlugin::SecurityLevel level =
-                    static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
-            bool isSupported = false;
-            status_t result = isCryptoSchemeSupported(uuid, mimeType, level, &isSupported);
-            reply->writeInt32(isSupported);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case CREATE_PLUGIN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint8_t uuid[16];
-            data.read(uuid, sizeof(uuid));
-            String8 appPackageName = data.readString8();
-            reply->writeInt32(createPlugin(uuid, appPackageName));
-            return OK;
-        }
-
-        case DESTROY_PLUGIN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(destroyPlugin());
-            return OK;
-        }
-
-        case OPEN_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            DrmPlugin::SecurityLevel level =
-                    static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
-            Vector<uint8_t> sessionId;
-            status_t result = openSession(level, sessionId);
-            writeVector(reply, sessionId);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case CLOSE_SESSION:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            reply->writeInt32(closeSession(sessionId));
-            return OK;
-        }
-
-        case GET_KEY_REQUEST:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, initData;
-
-            readVector(data, sessionId);
-            readVector(data, initData);
-            String8 mimeType = data.readString8();
-            DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
-
-            KeyedVector<String8, String8> optionalParameters;
-            uint32_t count = data.readInt32();
-            for (size_t i = 0; i < count; ++i) {
-                String8 key, value;
-                key = data.readString8();
-                value = data.readString8();
-                optionalParameters.add(key, value);
-            }
-
-            Vector<uint8_t> request;
-            String8 defaultUrl;
-            DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
-
-            status_t result = getKeyRequest(sessionId, initData, mimeType,
-                    keyType, optionalParameters, request, defaultUrl,
-                    &keyRequestType);
-
-            writeVector(reply, request);
-            reply->writeString8(defaultUrl);
-            reply->writeInt32(static_cast<int32_t>(keyRequestType));
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case PROVIDE_KEY_RESPONSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, response, keySetId;
-            readVector(data, sessionId);
-            readVector(data, response);
-            uint32_t result = provideKeyResponse(sessionId, response, keySetId);
-            writeVector(reply, keySetId);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case REMOVE_KEYS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            reply->writeInt32(removeKeys(keySetId));
-            return OK;
-        }
-
-        case RESTORE_KEYS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keySetId;
-            readVector(data, sessionId);
-            readVector(data, keySetId);
-            reply->writeInt32(restoreKeys(sessionId, keySetId));
-            return OK;
-        }
-
-        case QUERY_KEY_STATUS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            KeyedVector<String8, String8> infoMap;
-            status_t result = queryKeyStatus(sessionId, infoMap);
-            size_t count = infoMap.size();
-            reply->writeInt32(count);
-            for (size_t i = 0; i < count; ++i) {
-                reply->writeString8(infoMap.keyAt(i));
-                reply->writeString8(infoMap.valueAt(i));
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROVISION_REQUEST:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 certType = data.readString8();
-            String8 certAuthority = data.readString8();
-
-            Vector<uint8_t> request;
-            String8 defaultUrl;
-            status_t result = getProvisionRequest(certType, certAuthority,
-                                                  request, defaultUrl);
-            writeVector(reply, request);
-            reply->writeString8(defaultUrl);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case PROVIDE_PROVISION_RESPONSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> response;
-            Vector<uint8_t> certificate;
-            Vector<uint8_t> wrappedKey;
-            readVector(data, response);
-            status_t result = provideProvisionResponse(response, certificate, wrappedKey);
-            writeVector(reply, certificate);
-            writeVector(reply, wrappedKey);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > secureStops;
-            status_t result = getSecureStops(secureStops);
-            size_t count = secureStops.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = secureStops.begin();
-            while(iter != secureStops.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOP_IDS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > secureStopIds;
-            status_t result = getSecureStopIds(secureStopIds);
-            size_t count = secureStopIds.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = secureStopIds.begin();
-            while(iter != secureStopIds.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURE_STOP:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssid, secureStop;
-            readVector(data, ssid);
-            status_t result = getSecureStop(ssid, secureStop);
-            writeVector(reply, secureStop);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case RELEASE_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssRelease;
-            readVector(data, ssRelease);
-            reply->writeInt32(releaseSecureStops(ssRelease));
-            return OK;
-        }
-
-        case REMOVE_SECURE_STOP:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> ssid;
-            readVector(data, ssid);
-            reply->writeInt32(removeSecureStop(ssid));
-            return OK;
-        }
-
-        case REMOVE_ALL_SECURE_STOPS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(removeAllSecureStops());
-            return OK;
-        }
-
-        case GET_HDCP_LEVELS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
-            DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
-            status_t result = getHdcpLevels(&connected, &max);
-            reply->writeInt32(connected);
-            reply->writeInt32(max);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_NUMBER_OF_SESSIONS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            uint32_t open = 0, max = 0;
-            status_t result = getNumberOfSessions(&open, &max);
-            reply->writeInt32(open);
-            reply->writeInt32(max);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_SECURITY_LEVEL:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
-            status_t result = getSecurityLevel(sessionId, &level);
-            reply->writeInt32(level);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_OFFLINE_LICENSE_KEYSET_IDS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            List<Vector<uint8_t> > keySetIds;
-            status_t result = getOfflineLicenseKeySetIds(keySetIds);
-            size_t count = keySetIds.size();
-            reply->writeInt32(count);
-            List<Vector<uint8_t> >::iterator iter = keySetIds.begin();
-            while(iter != keySetIds.end()) {
-                size_t size = iter->size();
-                reply->writeInt32(size);
-                reply->write(iter->array(), iter->size());
-                iter++;
-            }
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case REMOVE_OFFLINE_LICENSE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            reply->writeInt32(removeOfflineLicense(keySetId));
-            return OK;
-        }
-
-        case GET_OFFLINE_LICENSE_STATE:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> keySetId;
-            readVector(data, keySetId);
-            DrmPlugin::OfflineLicenseState state;
-            state = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown;
-            status_t result = getOfflineLicenseState(keySetId, &state);
-            reply->writeInt32(static_cast<DrmPlugin::OfflineLicenseState>(state));
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROPERTY_STRING:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            String8 value;
-            status_t result = getPropertyString(name, value);
-            reply->writeString8(value);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case GET_PROPERTY_BYTE_ARRAY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            Vector<uint8_t> value;
-            status_t result = getPropertyByteArray(name, value);
-            writeVector(reply, value);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SET_PROPERTY_STRING:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            String8 value = data.readString8();
-            reply->writeInt32(setPropertyString(name, value));
-            return OK;
-        }
-
-        case SET_PROPERTY_BYTE_ARRAY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            String8 name = data.readString8();
-            Vector<uint8_t> value;
-            readVector(data, value);
-            reply->writeInt32(setPropertyByteArray(name, value));
-            return OK;
-        }
-
-        case GET_METRICS:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-
-            os::PersistableBundle metrics;
-            status_t result = getMetrics(&metrics);
-            // The reply data is ordered as
-            // 1) 32 bit integer reply followed by
-            // 2) Serialized PersistableBundle containing metrics.
-            // Only write the metrics if the getMetrics result was
-            // OK and we successfully added the status to reply.
-            status_t parcel_result = reply->writeInt32(result);
-            if (result == OK && parcel_result == OK) {
-                parcel_result = metrics.writeToParcel(reply);
-            }
-            return parcel_result;
-        }
-
-        case SET_CIPHER_ALGORITHM:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
-            return OK;
-        }
-
-        case SET_MAC_ALGORITHM:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
-            return OK;
-        }
-
-        case ENCRYPT:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, input, iv, output;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, input);
-            readVector(data, iv);
-            uint32_t result = encrypt(sessionId, keyId, input, iv, output);
-            writeVector(reply, output);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case DECRYPT:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, input, iv, output;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, input);
-            readVector(data, iv);
-            uint32_t result = decrypt(sessionId, keyId, input, iv, output);
-            writeVector(reply, output);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SIGN:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, message, signature;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, message);
-            uint32_t result = sign(sessionId, keyId, message, signature);
-            writeVector(reply, signature);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case VERIFY:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, keyId, message, signature;
-            readVector(data, sessionId);
-            readVector(data, keyId);
-            readVector(data, message);
-            readVector(data, signature);
-            bool match = false;
-            uint32_t result = verify(sessionId, keyId, message, signature, match);
-            reply->writeInt32(match);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-        case SIGN_RSA:
-        {
-            CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId, message, wrappedKey, signature;
-            readVector(data, sessionId);
-            String8 algorithm = data.readString8();
-            readVector(data, message);
-            readVector(data, wrappedKey);
-            uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
-            writeVector(reply, signature);
-            reply->writeInt32(result);
-            return OK;
-        }
-
-    case SET_LISTENER: {
-        CHECK_INTERFACE(IDrm, data, reply);
-        sp<IDrmClient> listener =
-            interface_cast<IDrmClient>(data.readStrongBinder());
-        reply->writeInt32(setListener(listener));
-        return NO_ERROR;
-    } break;
-
-    default:
-        return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/drm/libmediadrm/IDrmClient.cpp b/drm/libmediadrm/IDrmClient.cpp
deleted file mode 100644
index 357de9d..0000000
--- a/drm/libmediadrm/IDrmClient.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-**
-** Copyright 2013, 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 "IDrmClient"
-#include <utils/Log.h>
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <media/IMediaPlayerClient.h>
-#include <mediadrm/IDrmClient.h>
-
-namespace android {
-
-enum {
-    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpDrmClient: public BpInterface<IDrmClient>
-{
-public:
-    explicit BpDrmClient(const sp<IBinder>& impl)
-        : BpInterface<IDrmClient>(impl)
-    {
-    }
-
-    virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDrmClient::getInterfaceDescriptor());
-        data.writeInt32((int)eventType);
-        data.writeInt32(extra);
-        if (obj && obj->dataSize() > 0) {
-            data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
-        }
-        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(DrmClient, "android.media.IDrmClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnDrmClient::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case NOTIFY: {
-            CHECK_INTERFACE(IDrmClient, data, reply);
-            int eventType = data.readInt32();
-            int extra = data.readInt32();
-            Parcel obj;
-            if (data.dataAvail() > 0) {
-                obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
-            }
-
-            notify((DrmPlugin::EventType)eventType, extra, &obj);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/IMediaDrmService.cpp b/drm/libmediadrm/IMediaDrmService.cpp
deleted file mode 100644
index f320d0b..0000000
--- a/drm/libmediadrm/IMediaDrmService.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-**
-** Copyright 2015, 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 <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <mediadrm/ICrypto.h>
-#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/String8.h>
-
-namespace android {
-
-enum {
-    MAKE_CRYPTO = IBinder::FIRST_CALL_TRANSACTION,
-    MAKE_DRM,
-};
-
-class BpMediaDrmService: public BpInterface<IMediaDrmService>
-{
-public:
-    explicit BpMediaDrmService(const sp<IBinder>& impl)
-        : BpInterface<IMediaDrmService>(impl)
-    {
-    }
-
-    virtual sp<ICrypto> makeCrypto() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
-        remote()->transact(MAKE_CRYPTO, data, &reply);
-        return interface_cast<ICrypto>(reply.readStrongBinder());
-    }
-
-    virtual sp<IDrm> makeDrm() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
-        remote()->transact(MAKE_DRM, data, &reply);
-        return interface_cast<IDrm>(reply.readStrongBinder());
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaDrmService, "android.media.IMediaDrmService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaDrmService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-        case MAKE_CRYPTO: {
-            CHECK_INTERFACE(IMediaDrmService, data, reply);
-            sp<ICrypto> crypto = makeCrypto();
-            reply->writeStrongBinder(IInterface::asBinder(crypto));
-            return NO_ERROR;
-        } break;
-        case MAKE_DRM: {
-            CHECK_INTERFACE(IMediaDrmService, data, reply);
-            sp<IDrm> drm = makeDrm();
-            reply->writeStrongBinder(IInterface::asBinder(drm));
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp
index 8cd6f96..b0abf83 100644
--- a/drm/libmediadrm/PluginMetricsReporting.cpp
+++ b/drm/libmediadrm/PluginMetricsReporting.cpp
@@ -21,7 +21,7 @@
 
 #include <inttypes.h>
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
 #include <utils/Log.h>
 
 
@@ -33,20 +33,18 @@
 
 status_t reportVendorMetrics(const std::string& metrics,
                              const String8& name,
-                             const String8& appPackageName) {
-    std::unique_ptr<MediaAnalyticsItem> analyticsItem(MediaAnalyticsItem::create(name.c_str()));
-    analyticsItem->generateSessionID();
-
-    std::string app_package_name(appPackageName.c_str(), appPackageName.size());
-    analyticsItem->setPkgName(app_package_name);
+                             uid_t appUid) {
+    mediametrics_handle_t analyticsItem(mediametrics_create(name.c_str()));
+    mediametrics_setUid(analyticsItem, appUid);
     if (metrics.size() > 0) {
-        analyticsItem->setCString(kSerializedMetricsField, metrics.c_str());
+        mediametrics_setCString(analyticsItem, kSerializedMetricsField, metrics.c_str());
     }
 
-    if (!analyticsItem->selfrecord()) {
-      ALOGE("selfrecord() returned false. sessioId %" PRId64, analyticsItem->getSessionID());
+    if (!mediametrics_selfRecord(analyticsItem)) {
+      ALOGE("%s: selfrecord() returned false", __func__);
     }
 
+    mediametrics_delete(analyticsItem);
     return OK;
 }
 
@@ -69,13 +67,13 @@
 status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
                                 const String8& vendor,
                                 const String8& description,
-                                const String8& appPackageName) {
+                                uid_t appUid) {
 
     String8 name = String8::format("drm.vendor.%s.%s",
                                    sanitize(vendor).c_str(),
                                    sanitize(description).c_str());
 
-    return reportVendorMetrics(b64EncodedMetrics, name, appPackageName);
+    return reportVendorMetrics(b64EncodedMetrics, name, appUid);
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/TEST_MAPPING b/drm/libmediadrm/TEST_MAPPING
new file mode 100644
index 0000000..bc15879
--- /dev/null
+++ b/drm/libmediadrm/TEST_MAPPING
@@ -0,0 +1,26 @@
+{
+  "presubmit": [
+    {
+      "name": "GtsMediaTestCases",
+      "options" : [
+        {
+	  "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.MediaDrmTest"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineDashPolicyTests"
+        }
+      ]
+    }
+  ],
+  "imports": [
+    {
+      "path": "frameworks/av/drm/mediadrm/plugins"
+    }
+  ]
+}
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
new file mode 100644
index 0000000..c9fda67
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 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 CRYPTO_HAL_H_
+
+#define CRYPTO_HAL_H_
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
+
+#include <mediadrm/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::DestinationBuffer;
+
+using ::android::hardware::HidlMemory;
+
+class IMemoryHeap;
+
+namespace android {
+
+struct CryptoHal : public ICrypto {
+    CryptoHal();
+    virtual ~CryptoHal();
+
+    virtual status_t initCheck() const;
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+    virtual status_t createPlugin(
+            const uint8_t uuid[16], const void *data, size_t size);
+
+    virtual status_t destroyPlugin();
+
+    virtual bool requiresSecureDecoderComponent(
+            const char *mime) const;
+
+    virtual void notifyResolution(uint32_t width, uint32_t height);
+
+    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+
+    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+            const ::SharedBuffer &source, size_t offset,
+            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+            const ::DestinationBuffer &destination,
+            AString *errorDetailMsg);
+
+    virtual int32_t setHeap(const sp<HidlMemory>& heap) {
+        return setHeapBase(heap);
+    }
+    virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
+
+private:
+    mutable Mutex mLock;
+
+    const Vector<sp<ICryptoFactory>> mFactories;
+    sp<ICryptoPlugin> mPlugin;
+    sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
+
+    /**
+     * mInitCheck is:
+     *   NO_INIT if a plugin hasn't been created yet
+     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+     *   OK after a plugin has been created and mPlugin is valid
+     */
+    status_t mInitCheck;
+
+    KeyedVector<int32_t, size_t> mHeapSizes;
+    int32_t mHeapSeqNum;
+
+    Vector<sp<ICryptoFactory>> makeCryptoFactories();
+    sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+            const uint8_t uuid[16], const void *initData, size_t size);
+
+    int32_t setHeapBase(const sp<HidlMemory>& heap);
+    void clearHeapBase(int32_t seqNum);
+
+    status_t checkSharedBuffer(const ::SharedBuffer& buffer);
+
+    DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
+};
+
+}  // namespace android
+
+#endif  // CRYPTO_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
new file mode 100644
index 0000000..3b4639b
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2017 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 DRM_HAL_H_
+
+#define DRM_HAL_H_
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
+
+#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::EventType;
+using drm::V1_0::IDrmFactory;
+using drm::V1_0::IDrmPlugin;
+using drm::V1_0::IDrmPluginListener;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeyStatus;
+using drm::V1_2::OfflineLicenseState;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
+    if (l.size() != r.size()) return false;
+    return memcmp(l.array(), r.array(), l.size()) == 0;
+}
+
+struct DrmHal : public IDrm,
+                public IDrmPluginListener_V1_2 {
+
+    struct DrmSessionClient;
+
+    DrmHal();
+    virtual ~DrmHal();
+
+    virtual status_t initCheck() const;
+
+    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
+                                             const String8& mimeType,
+                                             DrmPlugin::SecurityLevel level,
+                                             bool *isSupported);
+
+    virtual status_t createPlugin(const uint8_t uuid[16],
+                                  const String8 &appPackageName);
+
+    virtual status_t destroyPlugin();
+
+    virtual status_t openSession(DrmPlugin::SecurityLevel level,
+            Vector<uint8_t> &sessionId);
+
+    virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+
+    virtual status_t
+        getKeyRequest(Vector<uint8_t> const &sessionId,
+                      Vector<uint8_t> const &initData,
+                      String8 const &mimeType, DrmPlugin::KeyType keyType,
+                      KeyedVector<String8, String8> const &optionalParameters,
+                      Vector<uint8_t> &request, String8 &defaultUrl,
+                      DrmPlugin::KeyRequestType *keyRequestType);
+
+    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                        Vector<uint8_t> const &response,
+                                        Vector<uint8_t> &keySetId);
+
+    virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+
+    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+                                 Vector<uint8_t> const &keySetId);
+
+    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                    KeyedVector<String8, String8> &infoMap) const;
+
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
+                                         String8 &defaulUrl);
+
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey);
+
+    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
+    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
+    virtual status_t removeAllSecureStops();
+
+    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+            DrmPlugin::HdcpLevel *maxLevel) const;
+    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+            uint32_t *maxSessions) const;
+    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+            DrmPlugin::SecurityLevel *level) const;
+
+    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
+    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+            DrmPlugin::OfflineLicenseState *licenseState) const;
+
+    virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+    virtual status_t getPropertyByteArray(String8 const &name,
+                                          Vector<uint8_t> &value ) const;
+    virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+    virtual status_t setPropertyByteArray(String8 const &name,
+                                          Vector<uint8_t> const &value ) const;
+    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+
+    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                        String8 const &algorithm);
+
+    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                     String8 const &algorithm);
+
+    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output);
+
+    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output);
+
+    virtual status_t sign(Vector<uint8_t> const &sessionId,
+                          Vector<uint8_t> const &keyId,
+                          Vector<uint8_t> const &message,
+                          Vector<uint8_t> &signature);
+
+    virtual status_t verify(Vector<uint8_t> const &sessionId,
+                            Vector<uint8_t> const &keyId,
+                            Vector<uint8_t> const &message,
+                            Vector<uint8_t> const &signature,
+                            bool &match);
+
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature);
+
+    virtual status_t setListener(const sp<IDrmClient>& listener);
+
+    // Methods of IDrmPluginListener
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS);
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
+
+    Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+
+    Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
+
+private:
+    static Mutex mLock;
+
+    sp<IDrmClient> mListener;
+    mutable Mutex mEventLock;
+    mutable Mutex mNotifyLock;
+
+    const std::vector<sp<IDrmFactory>> mFactories;
+    sp<IDrmPlugin> mPlugin;
+    sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
+    sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
+    String8 mAppPackageName;
+
+    // Mutable to allow modification within GetPropertyByteArray.
+    mutable MediaDrmMetrics mMetrics;
+
+    std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
+    void closeOpenSessions();
+    void cleanup();
+
+    /**
+     * mInitCheck is:
+     *   NO_INIT if a plugin hasn't been created yet
+     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+     *   OK after a plugin has been created and mPlugin is valid
+     */
+    status_t mInitCheck;
+
+    std::vector<sp<IDrmFactory>> makeDrmFactories();
+    sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
+            const uint8_t uuid[16], const String8& appPackageName);
+
+    void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+    void reportPluginMetrics() const;
+    void reportFrameworkMetrics() const;
+    status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
+    status_t getPropertyByteArrayInternal(String8 const &name,
+                                          Vector<uint8_t> &value) const;
+    status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+                                           const uint8_t uuid[16],
+                                           const String8 &mimeType,
+                                           DrmPlugin::SecurityLevel level,
+                                           bool *isSupported);
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
+};
+
+}  // namespace android
+
+#endif  // DRM_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
new file mode 100644
index 0000000..100b8f7
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 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 DRM_METRICS_H_
+#define DRM_METRICS_H_
+
+#include <map>
+
+#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/drm/1.1/types.h>
+#include <android/hardware/drm/1.2/types.h>
+#include <binder/PersistableBundle.h>
+#include <media/CounterMetric.h>
+#include <media/EventMetric.h>
+#include <sys/types.h>
+
+namespace android {
+
+/**
+ * This class contains the definition of metrics captured within MediaDrm.
+ * It also contains a method for exporting all of the metrics to a
+ * PersistableBundle.
+ */
+class MediaDrmMetrics {
+ public:
+  explicit MediaDrmMetrics();
+  virtual ~MediaDrmMetrics() {};
+  // Count of openSession calls.
+  CounterMetric<status_t> mOpenSessionCounter;
+  // Count of closeSession calls.
+  CounterMetric<status_t> mCloseSessionCounter;
+  // Count and timing of getKeyRequest calls.
+  EventMetric<status_t> mGetKeyRequestTimeUs;
+  // Count and timing of provideKeyResponse calls.
+  EventMetric<status_t> mProvideKeyResponseTimeUs;
+  // Count of getProvisionRequest calls.
+  CounterMetric<status_t> mGetProvisionRequestCounter;
+  // Count of provideProvisionResponse calls.
+  CounterMetric<status_t> mProvideProvisionResponseCounter;
+
+  // Count of key status events broken out by status type.
+  CounterMetric<::android::hardware::drm::V1_2::KeyStatusType>
+      mKeyStatusChangeCounter;
+  // Count of events broken out by event type
+  CounterMetric<::android::hardware::drm::V1_0::EventType> mEventCounter;
+
+  // Count getPropertyByteArray calls to retrieve the device unique id.
+  CounterMetric<status_t> mGetDeviceUniqueIdCounter;
+
+  // Adds a session start time record.
+  void SetSessionStart(const Vector<uint8_t>& sessionId);
+
+  // Adds a session end time record.
+  void SetSessionEnd(const Vector<uint8_t>& sessionId);
+
+  // The app package name is the application package name that is using the
+  // instance. The app package name is held here for convenience. It is not
+  // serialized or exported with the metrics.
+  void SetAppPackageName(const String8& appPackageName) { mAppPackageName = appPackageName; }
+  const String8& GetAppPackageName() { return mAppPackageName; }
+
+  void SetAppUid(uid_t appUid) { mAppUid = appUid; }
+  uid_t GetAppUid() const { return mAppUid; }
+
+  // Get the serialized metrics. Metrics are formatted as a serialized
+  // DrmFrameworkMetrics proto. If there is a failure serializing the metrics,
+  // this returns an error. The parameter |serlializedMetrics| is owned by the
+  // caller and must not be null.
+  status_t GetSerializedMetrics(std::string* serializedMetrics);
+
+  // Get copy of session lifetimes.
+  std::map<std::string, std::pair<int64_t, int64_t>> GetSessionLifespans() const;
+
+ protected:
+  // This is visible for testing only.
+  virtual int64_t GetCurrentTimeMs();
+
+ private:
+  // Session lifetimes. A pair of values representing the milliseconds since
+  // epoch, UTC. The first value is the start time, the second is the end time.
+  std::map<std::string, std::pair<int64_t, int64_t>> mSessionLifespans;
+
+  String8 mAppPackageName;
+  uid_t mAppUid{~0u};
+};
+
+}  // namespace android
+
+#endif  // DRM_METRICS_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h
new file mode 100644
index 0000000..bbbf4b5
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsConsumer.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 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 <binder/PersistableBundle.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/Errors.h>
+
+#ifndef ANDROID_METRICSCONSUMER_H_
+
+#define ANDROID_METRICSCONSUMER_H_
+
+namespace android {
+
+/**
+ * IDrmMetricsConsumer which saves IDrm/ICrypto metrics into a PersistableBundle.
+ *
+ * Example usage:
+ *
+ *   PersistableBundle bundle;
+ *   DrmMetricsConsumer consumer(&bundle);
+ *   drm->exportMetrics(&consumer);
+ *   crypto->exportMetrics(&consumer);
+ *   // bundle now contains metrics from drm/crypto.
+ *
+ */
+struct DrmMetricsConsumer : public IDrmMetricsConsumer {
+    DrmMetricsConsumer(os::PersistableBundle *bundle) : mBundle(bundle) {}
+
+    status_t consumeFrameworkMetrics(const MediaDrmMetrics &) override;
+
+    status_t consumeHidlMetrics(
+            const String8 &/*vendor*/,
+            const hidl_vec<DrmMetricGroup> &/*pluginMetrics*/) override;
+
+    // Converts the DRM plugin metrics to a PersistableBundle. All of the metrics
+    // found in |pluginMetrics| are added to the |metricsBundle| parameter.
+    // |pluginBundle| is owned by the caller and must not be null.
+    //
+    // Each item in the pluginMetrics vector is added as a new PersistableBundle. E.g.
+    // DrmMetricGroup {
+    //   metrics[0] {
+    //     name: "buf_copy"
+    //     attributes[0] {
+    //       name: "size"
+    //       type: INT64_TYPE
+    //       int64Value: 1024
+    //     }
+    //     values[0] {
+    //       componentName: "operation_count"
+    //       type: INT64_TYPE
+    //       int64Value: 75
+    //     }
+    //     values[1] {
+    //       component_name: "average_time_seconds"
+    //       type: DOUBLE_TYPE
+    //       doubleValue: 0.00000042
+    //     }
+    //   }
+    // }
+    //
+    // becomes
+    //
+    // metricsBundle {
+    //   "0": (PersistableBundle) {
+    //     "attributes" : (PersistableBundle) {
+    //       "size" : (int64) 1024
+    //     }
+    //     "operation_count" : (int64) 75
+    //     "average_time_seconds" : (double) 0.00000042
+    //   }
+    //
+    static status_t HidlMetricsToBundle(
+            const hardware::hidl_vec<hardware::drm::V1_1::DrmMetricGroup>& pluginMetrics,
+            os::PersistableBundle* metricsBundle);
+
+private:
+    os::PersistableBundle *mBundle;
+    DISALLOW_EVIL_CONSTRUCTORS(DrmMetricsConsumer);
+};
+
+}  // namespace android
+
+#endif // ANDROID_METRICSCONSUMER_H_
diff --git a/media/libmedia/include/media/DrmPluginPath.h b/drm/libmediadrm/include/mediadrm/DrmPluginPath.h
similarity index 100%
rename from media/libmedia/include/media/DrmPluginPath.h
rename to drm/libmediadrm/include/mediadrm/DrmPluginPath.h
diff --git a/media/libmedia/include/media/DrmSessionClientInterface.h b/drm/libmediadrm/include/mediadrm/DrmSessionClientInterface.h
similarity index 100%
rename from media/libmedia/include/media/DrmSessionClientInterface.h
rename to drm/libmediadrm/include/mediadrm/DrmSessionClientInterface.h
diff --git a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
new file mode 100644
index 0000000..9e43504
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 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 DRM_SESSION_MANAGER_H_
+
+#define DRM_SESSION_MANAGER_H_
+
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <android/binder_auto_utils.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace android {
+
+class DrmSessionManagerTest;
+
+using aidl::android::media::IResourceManagerClient;
+using aidl::android::media::IResourceManagerService;
+
+bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
+
+struct SessionInfo {
+    pid_t pid;
+    uid_t uid;
+    int64_t clientId;
+};
+
+typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap;
+
+struct DrmSessionManager : public RefBase {
+    static sp<DrmSessionManager> Instance();
+
+    DrmSessionManager();
+    explicit DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service);
+
+    void addSession(int pid,
+            const std::shared_ptr<IResourceManagerClient>& drm,
+            const Vector<uint8_t>& sessionId);
+    void useSession(const Vector<uint8_t>& sessionId);
+    void removeSession(const Vector<uint8_t>& sessionId);
+    bool reclaimSession(int callingPid);
+
+    // sanity check APIs
+    size_t getSessionCount() const;
+    bool containsSession(const Vector<uint8_t>& sessionId) const;
+
+    // implements DeathRecipient
+    void binderDied();
+
+protected:
+    virtual ~DrmSessionManager();
+
+private:
+    void init();
+
+    std::shared_ptr<IResourceManagerService> mService;
+    mutable Mutex mLock;
+    SessionInfoMap mSessionMap;
+    bool mInitialized;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
+};
+
+}  // namespace android
+
+#endif  // DRM_SESSION_MANAGER_H_
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
new file mode 100644
index 0000000..0177c24
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 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 <media/stagefright/foundation/ABase.h>
+#include <media/drm/DrmAPI.h>
+#include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+
+#ifndef ANDROID_IDRM_H_
+
+#define ANDROID_IDRM_H_
+
+namespace android {
+
+struct AString;
+
+struct IDrm : public virtual RefBase {
+
+    virtual ~IDrm() {}
+
+    virtual status_t initCheck() const = 0;
+
+    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
+                                             const String8 &mimeType,
+                                             DrmPlugin::SecurityLevel securityLevel,
+                                             bool *result) = 0;
+
+    virtual status_t createPlugin(const uint8_t uuid[16],
+                                  const String8 &appPackageName) = 0;
+
+    virtual status_t destroyPlugin() = 0;
+
+    virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+            Vector<uint8_t> &sessionId) = 0;
+
+    virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
+
+    virtual status_t
+        getKeyRequest(Vector<uint8_t> const &sessionId,
+                      Vector<uint8_t> const &initData,
+                      String8 const &mimeType, DrmPlugin::KeyType keyType,
+                      KeyedVector<String8, String8> const &optionalParameters,
+                      Vector<uint8_t> &request, String8 &defaultUrl,
+                      DrmPlugin::KeyRequestType *keyRequestType) = 0;
+
+    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                        Vector<uint8_t> const &response,
+                                        Vector<uint8_t> &keySetId) = 0;
+
+    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
+
+    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+                                 Vector<uint8_t> const &keySetId) = 0;
+
+    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                    KeyedVector<String8, String8> &infoMap) const = 0;
+
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
+                                         String8 &defaulUrl) = 0;
+
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey) = 0;
+
+    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
+    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
+
+    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+    virtual status_t removeAllSecureStops() = 0;
+
+    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+            DrmPlugin::HdcpLevel *maxLevel)
+            const = 0;
+    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+            uint32_t *maxSessions) const = 0;
+    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+            DrmPlugin::SecurityLevel *level) const = 0;
+
+    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
+    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
+    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+            DrmPlugin::OfflineLicenseState *licenseState) const = 0;
+
+    virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
+    virtual status_t getPropertyByteArray(String8 const &name,
+                                          Vector<uint8_t> &value) const = 0;
+    virtual status_t setPropertyString(String8 const &name,
+                                       String8 const &value ) const = 0;
+    virtual status_t setPropertyByteArray(String8 const &name,
+                                          Vector<uint8_t> const &value) const = 0;
+
+    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
+
+    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                        String8 const &algorithm) = 0;
+
+    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                     String8 const &algorithm) = 0;
+
+    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output) = 0;
+
+    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+                             Vector<uint8_t> const &keyId,
+                             Vector<uint8_t> const &input,
+                             Vector<uint8_t> const &iv,
+                             Vector<uint8_t> &output) = 0;
+
+    virtual status_t sign(Vector<uint8_t> const &sessionId,
+                          Vector<uint8_t> const &keyId,
+                          Vector<uint8_t> const &message,
+                          Vector<uint8_t> &signature) = 0;
+
+    virtual status_t verify(Vector<uint8_t> const &sessionId,
+                            Vector<uint8_t> const &keyId,
+                            Vector<uint8_t> const &message,
+                            Vector<uint8_t> const &signature,
+                            bool &match) = 0;
+
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature) = 0;
+
+    virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
+
+protected:
+    IDrm() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDrm);
+};
+
+}  // namespace android
+
+#endif // ANDROID_IDRM_H_
diff --git a/drm/libmediadrm/include/mediadrm/IDrmClient.h b/drm/libmediadrm/include/mediadrm/IDrmClient.h
new file mode 100644
index 0000000..fe25ae1
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/IDrmClient.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 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 ANDROID_IDRMCLIENT_H
+#define ANDROID_IDRMCLIENT_H
+
+#include <utils/RefBase.h>
+#include <hidl/HidlSupport.h>
+#include <media/drm/DrmAPI.h>
+
+#include <cstdint>
+#include <vector>
+
+namespace android {
+
+struct DrmKeyStatus {
+    const uint32_t type;
+    const hardware::hidl_vec<uint8_t> keyId;
+};
+
+class IDrmClient: public virtual RefBase
+{
+public:
+    ~IDrmClient() {}
+
+    virtual void sendEvent(
+            DrmPlugin::EventType eventType,
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            const hardware::hidl_vec<uint8_t> &data) = 0;
+
+    virtual void sendExpirationUpdate(
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            int64_t expiryTimeInMS) = 0;
+
+    virtual void sendKeysChange(
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            const std::vector<DrmKeyStatus> &keyStatusList,
+            bool hasNewUsableKey) = 0;
+
+    virtual void sendSessionLostState(
+            const hardware::hidl_vec<uint8_t> &sessionId) = 0;
+
+protected:
+    IDrmClient() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDrmClient);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IDRMCLIENT_H
diff --git a/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
new file mode 100644
index 0000000..aef35c3
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 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 <android/hardware/drm/1.1/types.h>
+#include <hidl/HidlSupport.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#ifndef ANDROID_IDRMMETRICSCONSUMER_H_
+
+#define ANDROID_IDRMMETRICSCONSUMER_H_
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+
+namespace android {
+
+class MediaDrmMetrics;
+class String8;
+
+/**
+ * Interface to consume metrics produced by the IDrm/ICrypto
+ *
+ * To use with IDrm:
+ *   drm->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeFrameworkMetrics &
+ * IDrmMetricsConsumer::consumeHidlMetrics implementations
+ * would each be invoked once per call to IDrm::exportMetrics.
+ * |consumeFrameworkMetrics| would be called for plugin-agnostic
+ * framework metrics; |consumeHidlMetrics| would be called for
+ * plugin specific metrics.
+ *
+ * ----------------------------------------
+ *
+ * To use with ICrypto:
+ *   crypto->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeHidlMetrics implementation
+ * would each be invoked once per call to ICrypto::exportMetrics.
+ * ICrypto metrics are plugin agnostic.
+ *
+ * ----------------------------------------
+ *
+ * For an example implementation of IDrmMetricsConsumer, please
+ * see DrmMetricsConsumer. DrmMetricsConsumer consumes IDrm/ICrypto
+ * metrics and saves the metrics to a PersistableBundle.
+ *
+ */
+struct IDrmMetricsConsumer : public RefBase {
+
+    virtual ~IDrmMetricsConsumer() {}
+
+    /**
+     * Consume framework (plugin agnostic) MediaDrmMetrics
+     */
+    virtual status_t consumeFrameworkMetrics(const MediaDrmMetrics &) = 0;
+
+    /**
+     * Consume list of DrmMetricGroup with optional Drm vendor name
+     */
+    virtual status_t consumeHidlMetrics(
+            const String8 &vendor,
+            const hidl_vec<DrmMetricGroup> &pluginMetrics) = 0;
+
+protected:
+    IDrmMetricsConsumer() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDrmMetricsConsumer);
+};
+
+}  // namespace android
+
+#endif // ANDROID_IDRMMETRICSCONSUMER_H_
diff --git a/media/libmedia/include/media/SharedLibrary.h b/drm/libmediadrm/include/mediadrm/SharedLibrary.h
similarity index 100%
rename from media/libmedia/include/media/SharedLibrary.h
rename to drm/libmediadrm/include/mediadrm/SharedLibrary.h
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
new file mode 100644
index 0000000..20b3fe9
--- /dev/null
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_DRMUTILS_H
+#define ANDROID_DRMUTILS_H
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <utils/Errors.h>  // for status_t
+#include <utils/StrongPointer.h>
+#include <vector>
+
+using namespace ::android::hardware::drm;
+
+namespace android {
+
+struct ICrypto;
+struct IDrm;
+
+namespace DrmUtils {
+
+bool UseDrmService();
+
+sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
+
+sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);
+
+template<typename BA, typename PARCEL>
+void WriteByteArray(PARCEL &obj, const BA &vec) {
+    obj.writeInt32(vec.size());
+    if (vec.size()) {
+        obj.write(vec.data(), vec.size());
+    }
+}
+
+template<typename ET, typename BA, typename PARCEL>
+void WriteEventToParcel(
+        PARCEL &obj,
+        ET eventType,
+        const BA &sessionId,
+        const BA &data) {
+    WriteByteArray(obj, sessionId);
+    WriteByteArray(obj, data);
+    obj.writeInt32(eventType);
+}
+
+template<typename BA, typename PARCEL>
+void WriteExpirationUpdateToParcel(
+        PARCEL &obj,
+        const BA &sessionId,
+        int64_t expiryTimeInMS) {
+    WriteByteArray(obj, sessionId);
+    obj.writeInt64(expiryTimeInMS);
+}
+
+template<typename BA, typename KSL, typename PARCEL>
+void WriteKeysChange(
+        PARCEL &obj,
+        const BA &sessionId,
+        const KSL &keyStatusList,
+        bool hasNewUsableKey) {
+    WriteByteArray(obj, sessionId);
+    obj.writeInt32(keyStatusList.size());
+    for (const auto &keyStatus : keyStatusList) {
+        WriteByteArray(obj, keyStatus.keyId);
+        obj.writeInt32(keyStatus.type);
+    }
+    obj.writeInt32(hasNewUsableKey);
+}
+
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16] = nullptr);
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+                                                   const char *appPackageName);
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]);
+
+std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
+                                                         const void *initData, size_t initDataSize);
+
+} // namespace DrmUtils
+
+} // namespace android
+
+#endif // ANDROID_DRMUTILS_H
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
new file mode 100644
index 0000000..df980ae
--- /dev/null
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 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 <cutils/native_handle.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+#ifndef ANDROID_ICRYPTO_H_
+
+#define ANDROID_ICRYPTO_H_
+
+namespace android {
+namespace hardware {
+class HidlMemory;
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+struct DestinationBuffer;
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::SharedBuffer;
+
+namespace android {
+
+struct AString;
+
+struct ICrypto : public RefBase {
+
+    virtual ~ICrypto() {}
+
+    virtual status_t initCheck() const = 0;
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) = 0;
+
+    virtual status_t createPlugin(
+            const uint8_t uuid[16], const void *data, size_t size) = 0;
+
+    virtual status_t destroyPlugin() = 0;
+
+    virtual bool requiresSecureDecoderComponent(
+            const char *mime) const = 0;
+
+    virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
+
+    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
+
+    enum DestinationType {
+        kDestinationTypeSharedMemory, // non-secure
+        kDestinationTypeNativeHandle  // secure
+    };
+
+    virtual ssize_t decrypt(const uint8_t /*key*/[16], const uint8_t /*iv*/[16],
+            CryptoPlugin::Mode /*mode*/, const CryptoPlugin::Pattern &/*pattern*/,
+            const drm::V1_0::SharedBuffer &/*source*/, size_t /*offset*/,
+            const CryptoPlugin::SubSample * /*subSamples*/, size_t /*numSubSamples*/,
+            const drm::V1_0::DestinationBuffer &/*destination*/, AString * /*errorDetailMsg*/) = 0;
+
+    /**
+     * Declare the heap that the shared memory source buffers passed
+     * to decrypt will be allocated from. Returns a sequence number
+     * that subsequent decrypt calls can use to refer to the heap,
+     * with -1 indicating failure.
+     */
+    virtual int32_t setHeap(const sp<hardware::HidlMemory>& heap) = 0;
+    virtual void unsetHeap(int32_t seqNum) = 0;
+
+protected:
+    ICrypto() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
+};
+
+}  // namespace android
+
+#endif // ANDROID_ICRYPTO_H_
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index 9e0115e..6529387 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -3,8 +3,11 @@
 cc_test {
     name: "CounterMetric_test",
     srcs: ["CounterMetric_test.cpp"],
+    header_libs: [
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
     shared_libs: ["libmediadrm"],
-    include_dirs: ["frameworks/av/include/media"],
     cflags: [
       "-Werror",
       "-Wall",
@@ -14,6 +17,9 @@
 cc_test {
     name: "DrmMetrics_test",
     srcs: ["DrmMetrics_test.cpp"],
+    header_libs: [
+        "libmedia_headers"
+    ],
     shared_libs: [
       "android.hardware.drm@1.0",
       "android.hardware.drm@1.1",
@@ -21,6 +27,8 @@
       "libbinder",
       "libhidlbase",
       "liblog",
+      "libmediadrm",
+      "libmediadrmmetrics_consumer",
       "libmediadrmmetrics_full",
       "libmediametrics",
       "libprotobuf-cpp-full",
@@ -28,7 +36,7 @@
     ],
     static_libs: ["libgmock"],
     include_dirs: [
-      "frameworks/av/include/media",
+      "frameworks/av/drm/libmediadrm/include",
     ],
     cflags: [
         // Suppress unused parameter and no error options. These cause problems
@@ -40,12 +48,15 @@
 cc_test {
     name: "EventMetric_test",
     srcs: ["EventMetric_test.cpp"],
+    header_libs: [
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
     shared_libs: [
       "liblog",
       "libmediadrm",
       "libutils",
     ],
-    include_dirs: ["frameworks/av/include/media"],
     cflags: [
       "-Werror",
       "-Wall",
diff --git a/drm/libmediadrm/tests/CounterMetric_test.cpp b/drm/libmediadrm/tests/CounterMetric_test.cpp
index 6bca0da..c2becb4 100644
--- a/drm/libmediadrm/tests/CounterMetric_test.cpp
+++ b/drm/libmediadrm/tests/CounterMetric_test.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "CounterMetric.h"
+#include <media/CounterMetric.h>
 
 namespace android {
 
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index 5c8a1b0..f362d60 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "DrmMetricsTest"
 #include "mediadrm/DrmMetrics.h"
+#include "mediadrm/DrmMetricsConsumer.h"
 
 #include <android/hardware/drm/1.0/types.h>
 #include <android/hardware/drm/1.1/types.h>
@@ -58,8 +59,9 @@
 TEST_F(MediaDrmMetricsTest, EmptySuccess) {
   MediaDrmMetrics metrics;
   PersistableBundle bundle;
+  DrmMetricsConsumer consumer(&bundle);
 
-  metrics.Export(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_TRUE(bundle.empty());
 }
 
@@ -85,8 +87,9 @@
   metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
 
   PersistableBundle bundle;
+  DrmMetricsConsumer consumer(&bundle);
 
-  metrics.Export(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_EQ(11U, bundle.size());
 
   // Verify the list of pairs of int64 metrics.
@@ -174,7 +177,8 @@
   metrics.SetSessionEnd(sessionId1);
 
   PersistableBundle bundle;
-  metrics.Export(&bundle);
+  DrmMetricsConsumer consumer(&bundle);
+  consumer.consumeFrameworkMetrics(metrics);
   EXPECT_EQ(35U, bundle.size());
 
   // Verify the list of pairs of int64 metrics.
@@ -421,7 +425,7 @@
   hidl_vec<DrmMetricGroup> hidlMetricGroups;
   PersistableBundle bundleMetricGroups;
 
-  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
+  ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
   ASSERT_EQ(0U, bundleMetricGroups.size());
 }
 
@@ -441,7 +445,7 @@
           } } };
 
   PersistableBundle bundleMetricGroups;
-  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
+  ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
                                                      &bundleMetricGroups));
   ASSERT_EQ(1U, bundleMetricGroups.size());
   PersistableBundle bundleMetricGroup;
diff --git a/drm/libmediadrm/tests/EventMetric_test.cpp b/drm/libmediadrm/tests/EventMetric_test.cpp
index eb6c4f6..b3c3f62 100644
--- a/drm/libmediadrm/tests/EventMetric_test.cpp
+++ b/drm/libmediadrm/tests/EventMetric_test.cpp
@@ -16,7 +16,7 @@
 
 #include <gtest/gtest.h>
 
-#include "EventMetric.h"
+#include <media/EventMetric.h>
 
 namespace android {
 
diff --git a/drm/mediacas/plugins/clearkey/Android.bp b/drm/mediacas/plugins/clearkey/Android.bp
new file mode 100644
index 0000000..0113cb8
--- /dev/null
+++ b/drm/mediacas/plugins/clearkey/Android.bp
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_library_shared {
+    name: "libclearkeycasplugin",
+
+    srcs: [
+        "ClearKeyCasPlugin.cpp",
+        "ClearKeyFetcher.cpp",
+        "ClearKeyLicenseFetcher.cpp",
+        "ClearKeySessionLibrary.cpp",
+        "ecm.cpp",
+        "ecm_generator.cpp",
+        "JsonAssetLoader.cpp",
+        "protos/license_protos.proto",
+    ],
+
+    proprietary: true,
+    relative_install_path: "mediacas",
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+        "libcrypto",
+        "libstagefright_foundation",
+        "libprotobuf-cpp-lite",
+    ],
+
+    header_libs: ["media_plugin_headers"],
+
+    static_libs: ["libjsmn"],
+
+    proto: {
+        type: "full",
+        export_proto_headers: true,
+    },
+
+    include_dirs: [
+        "frameworks/av/include",
+        "frameworks/native/include/media",
+    ],
+}
diff --git a/drm/mediacas/plugins/clearkey/Android.mk b/drm/mediacas/plugins/clearkey/Android.mk
deleted file mode 100644
index 4b139a8..0000000
--- a/drm/mediacas/plugins/clearkey/Android.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    ClearKeyCasPlugin.cpp \
-    ClearKeyFetcher.cpp \
-    ClearKeyLicenseFetcher.cpp \
-    ClearKeySessionLibrary.cpp \
-    ecm.cpp \
-    ecm_generator.cpp \
-    JsonAssetLoader.cpp \
-    protos/license_protos.proto \
-
-LOCAL_MODULE := libclearkeycasplugin
-
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := mediacas
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils \
-    liblog \
-    libcrypto \
-    libstagefright_foundation \
-    libprotobuf-cpp-lite \
-
-LOCAL_HEADER_LIBRARIES := \
-    media_plugin_headers
-
-LOCAL_STATIC_LIBRARIES := \
-    libjsmn \
-
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-define proto_includes
-$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-endef
-
-LOCAL_C_INCLUDES += \
-    external/jsmn \
-    frameworks/av/include \
-    frameworks/native/include/media \
-    $(call proto_includes)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(call proto_includes)
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-#########################################################################
-# Build unit tests
-
-include $(LOCAL_PATH)/tests/Android.mk
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index bf35224..af7c367 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -97,7 +97,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 ClearKeyCasPlugin::ClearKeyCasPlugin(
         void *appData, CasPluginCallback callback)
-    : mCallback(callback), mCallbackExt(NULL), mAppData(appData) {
+    : mCallback(callback), mCallbackExt(NULL), mStatusCallback(NULL),
+    mAppData(appData) {
     ALOGV("CTOR");
 }
 
@@ -112,6 +113,13 @@
     ClearKeySessionLibrary::get()->destroyPlugin(this);
 }
 
+status_t ClearKeyCasPlugin::setStatusCallback(
+    CasPluginStatusCallback callback) {
+    ALOGV("setStatusCallback");
+    mStatusCallback = callback;
+    return OK;
+}
+
 status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
     ALOGV("setPrivateData");
 
@@ -135,6 +143,19 @@
     return ClearKeySessionLibrary::get()->addSession(this, sessionId);
 }
 
+status_t ClearKeyCasPlugin::openSession(uint32_t intent, uint32_t mode,
+    CasSessionId* sessionId) {
+    ALOGV("openSession with intent=%d, mode=%d", intent, mode);
+    // Echo the received information to the callback.
+    // Clear key plugin doesn't use any event, echo'ing for testing only.
+    if (mStatusCallback != NULL) {
+        mStatusCallback((void*)mAppData, intent, mode);
+    }
+
+    // Clear key plugin doesn't use intent and mode.
+    return ClearKeySessionLibrary::get()->addSession(this, sessionId);
+}
+
 status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
     ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).string());
     std::shared_ptr<ClearKeyCasSession> session =
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h
index f48d5b1..c6938e6 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h
@@ -71,11 +71,17 @@
     ClearKeyCasPlugin(void *appData, CasPluginCallbackExt callback);
     virtual ~ClearKeyCasPlugin();
 
+    virtual status_t setStatusCallback(
+            CasPluginStatusCallback callback) override;
+
     virtual status_t setPrivateData(
             const CasData &data) override;
 
     virtual status_t openSession(CasSessionId *sessionId) override;
 
+    virtual status_t openSession(uint32_t intent, uint32_t mode,
+                                     CasSessionId *sessionId) override;
+
     virtual status_t closeSession(
             const CasSessionId &sessionId) override;
 
@@ -105,6 +111,7 @@
     std::unique_ptr<KeyFetcher> mKeyFetcher;
     CasPluginCallback mCallback;
     CasPluginCallbackExt mCallbackExt;
+    CasPluginStatusCallback mStatusCallback;
     void* mAppData;
 };
 
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index eaa3390..cb69f91 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -89,7 +89,7 @@
     // asset_id change. If it sends an EcmContainer with 2 Ecms with different
     // asset_ids (old and new) then it might be best to prefetch the Emm.
     if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
-        ALOGW("Asset_id change from %llu to %" PRIu64, asset_.id(), *asset_id);
+        ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
         asset_.Clear();
     }
 
diff --git a/drm/mediacas/plugins/clearkey/ecm.cpp b/drm/mediacas/plugins/clearkey/ecm.cpp
index 9fde13a..b3b5218 100644
--- a/drm/mediacas/plugins/clearkey/ecm.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm.cpp
@@ -17,6 +17,8 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ecm"
 
+#include <inttypes.h>
+
 #include "ecm.h"
 #include "ecm_generator.h"
 #include "protos/license_protos.pb.h"
@@ -76,7 +78,7 @@
         return status;
     }
     if (asset.id() != asset_from_emm.id()) {
-        ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).",
+        ALOGE("Asset_id from Emm (%" PRIu64 ") does not match asset_id from Ecm (%" PRIu64 ").",
                 asset_from_emm.id(), asset.id());
         return CLEARKEY_STATUS_INVALID_PARAMETER;
     }
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.bp b/drm/mediacas/plugins/clearkey/tests/Android.bp
new file mode 100644
index 0000000..575863c
--- /dev/null
+++ b/drm/mediacas/plugins/clearkey/tests/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_test {
+    name: "ClearKeyFetcherTest",
+
+    srcs: ["ClearKeyFetcherTest.cpp"],
+
+    vendor: true,
+
+    // LOCAL_LDFLAGS is needed here for the test to use the plugin, because
+    // the plugin is not in standard library search path. Without this .so
+    // loading fails at run-time (linking is okay).
+    ldflags: [
+        "-Wl,--rpath,${ORIGIN}/../../../system/vendor/lib/mediacas",
+        "-Wl,--enable-new-dtags",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "libclearkeycasplugin",
+        "libstagefright_foundation",
+        "libprotobuf-cpp-lite",
+        "liblog",
+    ],
+
+    include_dirs: [
+        "frameworks/av/drm/mediacas/plugins/clearkey",
+        "frameworks/av/include",
+        "frameworks/native/include/media",
+    ],
+}
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.mk b/drm/mediacas/plugins/clearkey/tests/Android.mk
deleted file mode 100644
index e1545af..0000000
--- a/drm/mediacas/plugins/clearkey/tests/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    ClearKeyFetcherTest.cpp
-
-LOCAL_MODULE := ClearKeyFetcherTest
-LOCAL_VENDOR_MODULE := true
-
-# LOCAL_LDFLAGS is needed here for the test to use the plugin, because
-# the plugin is not in standard library search path. Without this .so
-# loading fails at run-time (linking is okay).
-LOCAL_LDFLAGS := \
-    -Wl,--rpath,\$${ORIGIN}/../../../system/vendor/lib/mediacas -Wl,--enable-new-dtags
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils libclearkeycasplugin libstagefright_foundation libprotobuf-cpp-lite liblog
-
-LOCAL_C_INCLUDES += \
-    $(TOP)/frameworks/av/drm/mediacas/plugins/clearkey \
-    $(TOP)/frameworks/av/include \
-    $(TOP)/frameworks/native/include/media \
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
-
-
-
diff --git a/drm/mediacas/plugins/mock/Android.bp b/drm/mediacas/plugins/mock/Android.bp
new file mode 100644
index 0000000..e8a3c6f
--- /dev/null
+++ b/drm/mediacas/plugins/mock/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_library_shared {
+    name: "libmockcasplugin",
+
+    srcs: [
+        "MockCasPlugin.cpp",
+        "MockSessionLibrary.cpp",
+    ],
+
+    proprietary: true,
+    relative_install_path: "mediacas",
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+    ],
+
+    header_libs: ["media_plugin_headers"],
+
+    include_dirs: [
+        "frameworks/av/include",
+        "frameworks/native/include/media",
+    ],
+}
diff --git a/drm/mediacas/plugins/mock/Android.mk b/drm/mediacas/plugins/mock/Android.mk
deleted file mode 100644
index a1d61da..0000000
--- a/drm/mediacas/plugins/mock/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    MockCasPlugin.cpp \
-    MockSessionLibrary.cpp \
-
-LOCAL_MODULE := libmockcasplugin
-
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := mediacas
-
-LOCAL_SHARED_LIBRARIES := \
-    libutils liblog
-
-LOCAL_HEADER_LIBRARIES := media_plugin_headers
-
-LOCAL_C_INCLUDES += \
-    $(TOP)/frameworks/av/include \
-    $(TOP)/frameworks/native/include/media \
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
index 2964791..f8bab0a 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
@@ -111,6 +111,12 @@
     MockSessionLibrary::get()->destroyPlugin(this);
 }
 
+status_t MockCasPlugin::setStatusCallback(
+    CasPluginStatusCallback /*callback*/) {
+    ALOGV("setStatusCallback");
+    return OK;
+}
+
 status_t MockCasPlugin::setPrivateData(const CasData& /*data*/) {
     ALOGV("setPrivateData");
     return OK;
@@ -121,6 +127,13 @@
     return MockSessionLibrary::get()->addSession(this, sessionId);
 }
 
+status_t MockCasPlugin::openSession(uint32_t intent, uint32_t mode,
+    CasSessionId* sessionId) {
+    ALOGV("openSession with intent=%d, mode=%d", intent, mode);
+    // Clear key plugin doesn't use intent and mode.
+    return MockSessionLibrary::get()->addSession(this, sessionId);
+}
+
 status_t MockCasPlugin::closeSession(const CasSessionId &sessionId) {
     ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).string());
     Mutex::Autolock lock(mLock);
diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.h b/drm/mediacas/plugins/mock/MockCasPlugin.h
index 74b540c..660fd44 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.h
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.h
@@ -65,11 +65,17 @@
     MockCasPlugin();
     virtual ~MockCasPlugin();
 
+    virtual status_t setStatusCallback(
+            CasPluginStatusCallback callback) override;
+
     virtual status_t setPrivateData(
             const CasData &data) override;
 
     virtual status_t openSession(CasSessionId *sessionId) override;
 
+    virtual status_t openSession(uint32_t intent, uint32_t mode,
+                                     CasSessionId *sessionId) override;
+
     virtual status_t closeSession(
             const CasSessionId &sessionId) override;
 
diff --git a/drm/mediadrm/plugins/TEST_MAPPING b/drm/mediadrm/plugins/TEST_MAPPING
new file mode 100644
index 0000000..7bd1568
--- /dev/null
+++ b/drm/mediadrm/plugins/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsMediaTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "android.media.cts.MediaDrmClearkeyTest"
+        },
+        {
+          "include-filter": "android.media.cts.MediaDrmMetricsTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp b/drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp
index 0259a42..4e7daec 100644
--- a/drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp
+++ b/drm/mediadrm/plugins/clearkey/common/ClearKeyUUID.cpp
@@ -20,20 +20,28 @@
 
 namespace clearkeydrm {
 
+namespace {
+
+const std::array<uint8_t, 16> kCommonPsshBoxUUID{
+    0x10,0x77,0xEF,0xEC,0xC0,0xB2,0x4D,0x02,
+    0xAC,0xE3,0x3C,0x1E,0x52,0xE2,0xFB,0x4B
+};
+
+// To be used in mpd to specify drm scheme for players
+const std::array<uint8_t, 16> kClearKeyUUID{
+    0xE2,0x71,0x9D,0x58,0xA9,0x85,0xB3,0xC9,
+    0x78,0x1A,0xB0,0x30,0xAF,0x78,0xD3,0x0E
+};
+
+}
+
 bool isClearKeyUUID(const uint8_t uuid[16]) {
-    static const uint8_t kCommonPsshBoxUUID[16] = {
-        0x10,0x77,0xEF,0xEC,0xC0,0xB2,0x4D,0x02,
-        0xAC,0xE3,0x3C,0x1E,0x52,0xE2,0xFB,0x4B
-    };
+    return !memcmp(uuid, kCommonPsshBoxUUID.data(), kCommonPsshBoxUUID.size()) ||
+           !memcmp(uuid, kClearKeyUUID.data(), kClearKeyUUID.size());
+}
 
-    // To be used in mpd to specify drm scheme for players
-    static const uint8_t kClearKeyUUID[16] = {
-        0xE2,0x71,0x9D,0x58,0xA9,0x85,0xB3,0xC9,
-        0x78,0x1A,0xB0,0x30,0xAF,0x78,0xD3,0x0E
-    };
-
-    return !memcmp(uuid, kCommonPsshBoxUUID, sizeof(kCommonPsshBoxUUID)) ||
-           !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
+std::vector<std::array<uint8_t, 16>> getSupportedCryptoSchemes() {
+    return {kCommonPsshBoxUUID, kClearKeyUUID};
 }
 
 } // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h b/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
index ac99418..fe10fba 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
@@ -17,12 +17,16 @@
 #ifndef CLEARKEY_UUID_H_
 #define CLEARKEY_UUID_H_
 
-#include <stdint.h>
+#include <array>
+#include <cstdint>
+#include <vector>
 
 namespace clearkeydrm {
 
 bool isClearKeyUUID(const uint8_t uuid[16]);
 
+std::vector<std::array<uint8_t, 16>> getSupportedCryptoSchemes();
+
 } // namespace clearkeydrm
 
 #endif // CLEARKEY_UUID_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index e91e918..a194416 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -43,12 +43,12 @@
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
+        "android.hardware.drm@1.3",
         "libbase",
         "libbinder",
         "libcrypto",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
         "liblog",
         "libprotobuf-cpp-lite",
         "libutils",
@@ -78,16 +78,37 @@
     },
     srcs: ["protos/DeviceFiles.proto"],
 }
+
 cc_binary {
     name: "android.hardware.drm@1.2-service.clearkey",
     defaults: ["clearkey_service_defaults"],
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.drm@1.2-service.clearkey.rc"],
+    vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
 }
+
 cc_binary {
     name: "android.hardware.drm@1.2-service-lazy.clearkey",
     overrides: ["android.hardware.drm@1.2-service.clearkey"],
     defaults: ["clearkey_service_defaults"],
     srcs: ["serviceLazy.cpp"],
     init_rc: ["android.hardware.drm@1.2-service-lazy.clearkey.rc"],
+    vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
+}
+
+cc_binary {
+    name: "android.hardware.drm@1.3-service.clearkey",
+    defaults: ["clearkey_service_defaults"],
+    srcs: ["service.cpp"],
+    init_rc: ["android.hardware.drm@1.3-service.clearkey.rc"],
+    vintf_fragments: ["manifest_android.hardware.drm@1.3-service.clearkey.xml"],
+}
+
+cc_binary {
+    name: "android.hardware.drm@1.3-service-lazy.clearkey",
+    overrides: ["android.hardware.drm@1.3-service.clearkey"],
+    defaults: ["clearkey_service_defaults"],
+    srcs: ["serviceLazy.cpp"],
+    init_rc: ["android.hardware.drm@1.3-service-lazy.clearkey.rc"],
+    vintf_fragments: ["manifest_android.hardware.drm@1.3-service.clearkey.xml"],
 }
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
index 1410d77..bfb0e05 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
 extern "C" {
@@ -38,7 +38,7 @@
 } // extern "C"
 
 }  // namespace clearkey
-}  // namespace V1_2
+}  // namespace V1_3
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
index 2a48db6..a6ed3bd 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
@@ -27,9 +27,12 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_2::clearkey::CryptoPlugin;
+
 Return<bool> CryptoFactory::isCryptoSchemeSupported(
     const hidl_array<uint8_t, 16> &uuid)
 {
@@ -60,7 +63,7 @@
 }
 
 } // namespace clearkey
-} // namespace V1_2
+} // namespace V1_3
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
index 9fb5bbe..1ce8269 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
@@ -15,6 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
+#include <vector>
 #define LOG_TAG "hidl_ClearKeyDrmFactory"
 #include <utils/Log.h>
 
@@ -30,11 +31,13 @@
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
 using ::android::hardware::drm::V1_0::Status;
 using ::android::hardware::drm::V1_1::SecurityLevel;
+using ::android::hardware::drm::V1_2::clearkey::DrmPlugin;
+using ::android::hardware::drm::V1_2::clearkey::SessionLibrary;
 using ::android::hardware::Void;
 
 Return<bool> DrmFactory::isCryptoSchemeSupported(
@@ -78,8 +81,31 @@
     return Void();
 }
 
+Return<void> DrmFactory::getSupportedCryptoSchemes(
+        getSupportedCryptoSchemes_cb _hidl_cb) {
+    std::vector<hidl_array<uint8_t, 16>> schemes;
+    for (const auto &scheme : clearkeydrm::getSupportedCryptoSchemes()) {
+        schemes.push_back(scheme);
+    }
+    _hidl_cb(schemes);
+    return Void();
+}
+
+Return<void> DrmFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /*args*/) {
+    if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
+        ALOGE("%s: missing fd for writing", __FUNCTION__);
+        return Void();
+    }
+
+    FILE* out = fdopen(dup(fd->data[0]), "w");
+    uint32_t currentSessions = SessionLibrary::get()->numOpenSessions();
+    fprintf(out, "current open sessions: %u\n", currentSessions);
+    fclose(out);
+    return Void();
+}
+
 } // namespace clearkey
-} // namespace V1_2
+} // namespace V1_3
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index c371e34..a77759e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -139,8 +139,13 @@
     std::vector<uint8_t> sessionId = session->sessionId();
 
     Status status = setSecurityLevel(sessionId, securityLevel);
+    if (status == Status::OK) {
+        mOpenSessionOkCount++;
+    } else {
+        mSessionLibrary->destroySession(session);
+        sessionId.clear();
+    }
     _hidl_cb(status, toHidlVec(sessionId));
-    mOpenSessionOkCount++;
     return Void();
 }
 
@@ -151,12 +156,12 @@
 
     sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
     if (session.get()) {
+        mSessionLibrary->destroySession(session);
         if (session->getMockError() != Status_V1_2::OK) {
             sendSessionLostState(sessionId);
             return Status::ERROR_DRM_INVALID_STATE;
         }
         mCloseSessionOkCount++;
-        mSessionLibrary->destroySession(session);
         return Status::OK;
     }
     mCloseSessionNotOpenedCount++;
@@ -357,6 +362,11 @@
 
     Status status = Status::OK;
     bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
+    if (scopeId.size() < kKeySetIdPrefix.size()) {
+        android_errorWriteLog(0x534e4554, "144507096");
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
+        return Void();
+    }
     bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
     if (isRelease) {
         keySetId.assign(scopeId.begin(), scopeId.end());
@@ -383,6 +393,7 @@
         if (isOfflineLicense) {
             if (isRelease) {
                 mFileHandle.DeleteLicense(keySetId);
+                mSessionLibrary->destroySession(session);
             } else {
                 if (!makeKeySetId(&keySetId)) {
                     _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
index ebb6fb8..8513434 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
@@ -96,7 +96,6 @@
     size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) +
                         sizeof(psshVersion1) + kSystemIdSize + sizeof(keyIdCount);
     if (initData.size() < headerSize) {
-        android_errorWriteLog(0x534e4554, "137282168");
         return Status::ERROR_DRM_CANNOT_HANDLE;
     }
 
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
index 5ba669d..c1abe7f 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
@@ -5,6 +5,7 @@
     interface android.hardware.drm@1.1::IDrmFactory clearkey
     interface android.hardware.drm@1.2::ICryptoFactory clearkey
     interface android.hardware.drm@1.2::IDrmFactory clearkey
+    disabled
     class hal
     user media
     group media mediadrm
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
new file mode 100644
index 0000000..1e0d431
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
@@ -0,0 +1,16 @@
+service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service-lazy.clearkey
+    interface android.hardware.drm@1.0::ICryptoFactory clearkey
+    interface android.hardware.drm@1.0::IDrmFactory clearkey
+    interface android.hardware.drm@1.1::ICryptoFactory clearkey
+    interface android.hardware.drm@1.1::IDrmFactory clearkey
+    interface android.hardware.drm@1.2::ICryptoFactory clearkey
+    interface android.hardware.drm@1.2::IDrmFactory clearkey
+    interface android.hardware.drm@1.3::ICryptoFactory clearkey
+    interface android.hardware.drm@1.3::IDrmFactory clearkey
+    disabled
+    oneshot
+    class hal
+    user media
+    group media mediadrm
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
new file mode 100644
index 0000000..8130511
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
@@ -0,0 +1,14 @@
+service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service.clearkey
+    interface android.hardware.drm@1.0::ICryptoFactory clearkey
+    interface android.hardware.drm@1.0::IDrmFactory clearkey
+    interface android.hardware.drm@1.1::ICryptoFactory clearkey
+    interface android.hardware.drm@1.1::IDrmFactory clearkey
+    interface android.hardware.drm@1.2::ICryptoFactory clearkey
+    interface android.hardware.drm@1.2::IDrmFactory clearkey
+    interface android.hardware.drm@1.3::ICryptoFactory clearkey
+    interface android.hardware.drm@1.3::IDrmFactory clearkey
+    class hal
+    user media
+    group media mediadrm
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
index 6368f3d..c1c188e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
@@ -17,17 +17,17 @@
 #ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
 #define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
 
-#include <android/hardware/drm/1.2/ICryptoFactory.h>
-#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.3/ICryptoFactory.h>
+#include <android/hardware/drm/1.3/IDrmFactory.h>
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_2::ICryptoFactory;
-using ::android::hardware::drm::V1_2::IDrmFactory;
+using ::android::hardware::drm::V1_3::ICryptoFactory;
+using ::android::hardware::drm::V1_3::IDrmFactory;
 
 extern "C" {
     IDrmFactory* createDrmFactory();
@@ -35,7 +35,7 @@
 }
 
 }  // namespace clearkey
-}  // namespace V1_2
+}  // namespace V1_3
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
index 203bb2d..cb4811b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
@@ -18,17 +18,17 @@
 #define CLEARKEY_CRYPTO_FACTORY_H_
 
 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.2/ICryptoFactory.h>
+#include <android/hardware/drm/1.3/ICryptoFactory.h>
 
 #include "ClearKeyTypes.h"
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
-using ::android::hardware::drm::V1_2::ICryptoFactory;
+using ::android::hardware::drm::V1_3::ICryptoFactory;
 using ::android::hardware::drm::V1_0::ICryptoPlugin;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_string;
@@ -52,7 +52,7 @@
 };
 
 } // namespace clearkey
-} // namespace V1_2
+} // namespace V1_3
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
index 4ca856d..63234cf 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
@@ -18,17 +18,19 @@
 #define CLEARKEY_DRM_FACTORY_H_
 
 #include <android/hardware/drm/1.2/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.3/IDrmFactory.h>
 
 #include "ClearKeyTypes.h"
 
 namespace android {
 namespace hardware {
 namespace drm {
-namespace V1_2 {
+namespace V1_3 {
 namespace clearkey {
 
+using ::android::hardware::drm::V1_1::SecurityLevel;
 using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 
@@ -51,12 +53,17 @@
             const hidl_string& appPackageName,
             createPlugin_cb _hidl_cb) override;
 
+    Return<void> getSupportedCryptoSchemes(
+            getSupportedCryptoSchemes_cb _hidl_cb) override;
+
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
+
 private:
     CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
 };
 
 } // namespace clearkey
-} // namespace V1_2
+} // namespace V1_3
 } // namespace drm
 } // namespace hardware
 } // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
new file mode 100644
index 0000000..16cba11
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.drm</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.2::ICryptoFactory/clearkey</fqname>
+        <fqname>@1.2::IDrmFactory/clearkey</fqname>
+    </hal>
+</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
new file mode 100644
index 0000000..229ee96
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.drm</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.3::ICryptoFactory/clearkey</fqname>
+        <fqname>@1.3::IDrmFactory/clearkey</fqname>
+    </hal>
+</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
index b39ea01..b62baae 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
@@ -25,10 +25,10 @@
 using ::android::hardware::joinRpcThreadpool;
 using ::android::sp;
 
-using android::hardware::drm::V1_2::ICryptoFactory;
-using android::hardware::drm::V1_2::IDrmFactory;
-using android::hardware::drm::V1_2::clearkey::CryptoFactory;
-using android::hardware::drm::V1_2::clearkey::DrmFactory;
+using android::hardware::drm::V1_3::ICryptoFactory;
+using android::hardware::drm::V1_3::IDrmFactory;
+using android::hardware::drm::V1_3::clearkey::CryptoFactory;
+using android::hardware::drm::V1_3::clearkey::DrmFactory;
 
 int main(int /* argc */, char** /* argv */) {
     sp<IDrmFactory> drmFactory = new DrmFactory;
diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
index 99fd883..b3e0179 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
@@ -25,10 +25,10 @@
 using ::android::hardware::joinRpcThreadpool;
 using ::android::sp;
 
-using android::hardware::drm::V1_2::ICryptoFactory;
-using android::hardware::drm::V1_2::IDrmFactory;
-using android::hardware::drm::V1_2::clearkey::CryptoFactory;
-using android::hardware::drm::V1_2::clearkey::DrmFactory;
+using android::hardware::drm::V1_3::ICryptoFactory;
+using android::hardware::drm::V1_3::IDrmFactory;
+using android::hardware::drm::V1_3::clearkey::CryptoFactory;
+using android::hardware::drm::V1_3::clearkey::DrmFactory;
 using android::hardware::LazyServiceRegistrar;
 
 int main(int /* argc */, char** /* argv */) {
@@ -38,7 +38,7 @@
     configureRpcThreadpool(8, true /* callerWillJoin */);
 
     // Setup hwbinder service
-    LazyServiceRegistrar serviceRegistrar;
+    auto serviceRegistrar = LazyServiceRegistrar::getInstance();
 
     // Setup hwbinder service
     CHECK_EQ(serviceRegistrar.registerService(drmFactory, "clearkey"), android::NO_ERROR)
diff --git a/include/camera b/include/camera
deleted file mode 120000
index 00848e3..0000000
--- a/include/camera
+++ /dev/null
@@ -1 +0,0 @@
-../camera/include/camera/
\ No newline at end of file
diff --git a/include/cpustats b/include/cpustats
deleted file mode 120000
index 4a02d41..0000000
--- a/include/cpustats
+++ /dev/null
@@ -1 +0,0 @@
-../media/libcpustats/include/cpustats/
\ No newline at end of file
diff --git a/include/drm/TEST_MAPPING b/include/drm/TEST_MAPPING
new file mode 100644
index 0000000..28e432e
--- /dev/null
+++ b/include/drm/TEST_MAPPING
@@ -0,0 +1,26 @@
+{
+  "presubmit": [
+    {
+      "name": "GtsMediaTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+        }
+      ]
+    },
+    {
+      "name": "GtsExoPlayerTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.SocPresubmit"
+        },
+        {
+          "include-filter": "com.google.android.exoplayer.gts.DashTest#testWidevine23FpsH264Fixed"
+        }
+      ]
+    }
+  ]
+}
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index d75f71c..d5f3ba2 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -317,14 +317,6 @@
     ~DecryptHandle() {
         delete decryptInfo; decryptInfo = NULL;
     }
-
-    bool operator<(const DecryptHandle& handle) const {
-        return (decryptId < handle.decryptId);
-    }
-
-    bool operator==(const DecryptHandle& handle) const {
-        return (decryptId == handle.decryptId);
-    }
 };
 
 };
diff --git a/include/media/AVSyncSettings.h b/include/media/AVSyncSettings.h
deleted file mode 120000
index bbe211f..0000000
--- a/include/media/AVSyncSettings.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/AVSyncSettings.h
\ No newline at end of file
diff --git a/include/media/AudioAttributes.h b/include/media/AudioAttributes.h
deleted file mode 120000
index 27ba471..0000000
--- a/include/media/AudioAttributes.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioAttributes.h
\ No newline at end of file
diff --git a/include/media/AudioBufferProvider.h b/include/media/AudioBufferProvider.h
deleted file mode 120000
index c4d6e79..0000000
--- a/include/media/AudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
deleted file mode 120000
index a0530e4..0000000
--- a/include/media/AudioClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/include/media/AudioCommonTypes.h b/include/media/AudioCommonTypes.h
deleted file mode 120000
index ae7c99a..0000000
--- a/include/media/AudioCommonTypes.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioCommonTypes.h
\ No newline at end of file
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
deleted file mode 120000
index bf52955..0000000
--- a/include/media/AudioEffect.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioEffect.h
\ No newline at end of file
diff --git a/include/media/AudioIoDescriptor.h b/include/media/AudioIoDescriptor.h
deleted file mode 120000
index 68f54c9..0000000
--- a/include/media/AudioIoDescriptor.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioIoDescriptor.h
\ No newline at end of file
diff --git a/include/media/AudioMixer.h b/include/media/AudioMixer.h
deleted file mode 120000
index de839c6..0000000
--- a/include/media/AudioMixer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioMixer.h
\ No newline at end of file
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
deleted file mode 120000
index a5889e5..0000000
--- a/include/media/AudioParameter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioParameter.h
\ No newline at end of file
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
deleted file mode 120000
index dd4cd53..0000000
--- a/include/media/AudioPolicy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioPolicy.h
\ No newline at end of file
diff --git a/include/media/AudioProductStrategy.h b/include/media/AudioProductStrategy.h
deleted file mode 120000
index 6bfaf11..0000000
--- a/include/media/AudioProductStrategy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioProductStrategy.h
\ No newline at end of file
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
deleted file mode 120000
index 7939dd3..0000000
--- a/include/media/AudioRecord.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioRecord.h
\ No newline at end of file
diff --git a/include/media/AudioResampler.h b/include/media/AudioResampler.h
deleted file mode 120000
index 771f1b8..0000000
--- a/include/media/AudioResampler.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioprocessing/include/media/AudioResampler.h
\ No newline at end of file
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
deleted file mode 120000
index 9fad2b7..0000000
--- a/include/media/AudioSystem.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioSystem.h
\ No newline at end of file
diff --git a/include/media/AudioTimestamp.h b/include/media/AudioTimestamp.h
deleted file mode 120000
index b6b9278..0000000
--- a/include/media/AudioTimestamp.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioTimestamp.h
\ No newline at end of file
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
deleted file mode 120000
index 303bfcd..0000000
--- a/include/media/AudioTrack.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioTrack.h
\ No newline at end of file
diff --git a/include/media/AudioVolumeGroup.h b/include/media/AudioVolumeGroup.h
deleted file mode 120000
index d6f1c99..0000000
--- a/include/media/AudioVolumeGroup.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/AudioVolumeGroup.h
\ No newline at end of file
diff --git a/include/media/BufferProviders.h b/include/media/BufferProviders.h
deleted file mode 120000
index 779bb15..0000000
--- a/include/media/BufferProviders.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/BufferProviders.h
\ No newline at end of file
diff --git a/include/media/BufferingSettings.h b/include/media/BufferingSettings.h
deleted file mode 120000
index 409203f..0000000
--- a/include/media/BufferingSettings.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/BufferingSettings.h
\ No newline at end of file
diff --git a/include/media/CharacterEncodingDetector.h b/include/media/CharacterEncodingDetector.h
deleted file mode 120000
index 2b28387..0000000
--- a/include/media/CharacterEncodingDetector.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CharacterEncodingDetector.h
\ No newline at end of file
diff --git a/include/media/CounterMetric.h b/include/media/CounterMetric.h
deleted file mode 120000
index baba043..0000000
--- a/include/media/CounterMetric.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CounterMetric.h
\ No newline at end of file
diff --git a/include/media/DataSource.h b/include/media/DataSource.h
deleted file mode 120000
index 198b27e..0000000
--- a/include/media/DataSource.h
+++ /dev/null
@@ -1 +0,0 @@
-stagefright/DataSource.h
\ No newline at end of file
diff --git a/include/media/DataSource.h b/include/media/DataSource.h
new file mode 100644
index 0000000..2abd5f5
--- /dev/null
+++ b/include/media/DataSource.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 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 DATA_SOURCE_H_
+
+#define DATA_SOURCE_H_
+
+#include <sys/types.h>
+
+#include <android/IDataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/DataSourceBase.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+
+namespace android {
+
+class String8;
+
+class DataSource : public DataSourceBase, public virtual RefBase {
+public:
+    DataSource() : mWrapper(NULL) {}
+
+    // returns a pointer to IDataSource if it is wrapped.
+    virtual sp<IDataSource> getIDataSource() const {
+        return nullptr;
+    }
+
+    virtual String8 toString() {
+        return String8("<unspecified>");
+    }
+
+    virtual status_t reconnectAtOffset(off64_t /*offset*/) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    virtual String8 getUri() {
+        return String8();
+    }
+
+    virtual bool getUri(char *uriString, size_t bufferSize) final {
+        int ret = snprintf(uriString, bufferSize, "%s", getUri().c_str());
+        return ret >= 0 && static_cast<size_t>(ret) < bufferSize;
+    }
+
+    virtual String8 getMIMEType() const {
+        return String8("application/octet-stream");
+    }
+
+    CDataSource *wrap() {
+        if (mWrapper) {
+            return mWrapper;
+        }
+        mWrapper = new CDataSource();
+        mWrapper->handle = this;
+
+        mWrapper->readAt = [](void *handle, off64_t offset, void *data, size_t size) -> ssize_t {
+            return ((DataSource*)handle)->readAt(offset, data, size);
+        };
+        mWrapper->getSize = [](void *handle, off64_t *size) -> status_t {
+            return ((DataSource*)handle)->getSize(size);
+        };
+        mWrapper->flags = [](void *handle) -> uint32_t {
+            return ((DataSource*)handle)->flags();
+        };
+        mWrapper->getUri = [](void *handle, char *uriString, size_t bufferSize) -> bool {
+            return ((DataSource*)handle)->getUri(uriString, bufferSize);
+        };
+        return mWrapper;
+    }
+
+protected:
+    virtual ~DataSource() {
+        delete mWrapper;
+    }
+
+private:
+    CDataSource *mWrapper;
+    DataSource(const DataSource &);
+    DataSource &operator=(const DataSource &);
+};
+
+}  // namespace android
+
+#endif  // DATA_SOURCE_H_
diff --git a/include/media/DataSourceBase.h b/include/media/DataSourceBase.h
deleted file mode 120000
index d2ab2f1..0000000
--- a/include/media/DataSourceBase.h
+++ /dev/null
@@ -1 +0,0 @@
-stagefright/DataSourceBase.h
\ No newline at end of file
diff --git a/include/media/EventLog.h b/include/media/EventLog.h
deleted file mode 120000
index 9b2c4bf..0000000
--- a/include/media/EventLog.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/utils/include/mediautils/EventLog.h
\ No newline at end of file
diff --git a/include/media/EventMetric.h b/include/media/EventMetric.h
deleted file mode 120000
index 5707d9a..0000000
--- a/include/media/EventMetric.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/EventMetric.h
\ No newline at end of file
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
deleted file mode 120000
index d653cc3..0000000
--- a/include/media/ExtendedAudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/ExtendedAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
deleted file mode 120000
index ef6f5be..0000000
--- a/include/media/IAudioFlinger.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioFlinger.h
\ No newline at end of file
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
deleted file mode 120000
index dc481e8..0000000
--- a/include/media/IAudioFlingerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioFlingerClient.h
\ No newline at end of file
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
deleted file mode 120000
index 08101fc..0000000
--- a/include/media/IAudioPolicyService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioPolicyService.h
\ No newline at end of file
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
deleted file mode 120000
index 0d4b3e7..0000000
--- a/include/media/IAudioPolicyServiceClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioPolicyServiceClient.h
\ No newline at end of file
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
deleted file mode 120000
index 7bab1fd..0000000
--- a/include/media/IAudioTrack.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IAudioTrack.h
\ No newline at end of file
diff --git a/include/media/IDataSource.h b/include/media/IDataSource.h
deleted file mode 120000
index 41cdd8b..0000000
--- a/include/media/IDataSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDataSource.h
\ No newline at end of file
diff --git a/include/media/IEffect.h b/include/media/IEffect.h
deleted file mode 120000
index 2fb8bfb..0000000
--- a/include/media/IEffect.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IEffect.h
\ No newline at end of file
diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h
deleted file mode 120000
index b4e39cf..0000000
--- a/include/media/IEffectClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/IEffectClient.h
\ No newline at end of file
diff --git a/include/media/IMediaAnalyticsService.h b/include/media/IMediaAnalyticsService.h
deleted file mode 120000
index a596d60..0000000
--- a/include/media/IMediaAnalyticsService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/IMediaAnalyticsService.h
\ No newline at end of file
diff --git a/include/media/IMediaCodecList.h b/include/media/IMediaCodecList.h
deleted file mode 120000
index 2186312..0000000
--- a/include/media/IMediaCodecList.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaCodecList.h
\ No newline at end of file
diff --git a/include/media/IMediaDeathNotifier.h b/include/media/IMediaDeathNotifier.h
deleted file mode 120000
index ce3b8f0..0000000
--- a/include/media/IMediaDeathNotifier.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaDeathNotifier.h
\ No newline at end of file
diff --git a/include/media/IMediaExtractor.h b/include/media/IMediaExtractor.h
deleted file mode 120000
index 8708c8c..0000000
--- a/include/media/IMediaExtractor.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaExtractor.h
\ No newline at end of file
diff --git a/include/media/IMediaExtractorService.h b/include/media/IMediaExtractorService.h
deleted file mode 120000
index 3ee9f1e..0000000
--- a/include/media/IMediaExtractorService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaExtractorService.h
\ No newline at end of file
diff --git a/include/media/IMediaHTTPConnection.h b/include/media/IMediaHTTPConnection.h
deleted file mode 120000
index 0970c15..0000000
--- a/include/media/IMediaHTTPConnection.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaHTTPConnection.h
\ No newline at end of file
diff --git a/include/media/IMediaHTTPService.h b/include/media/IMediaHTTPService.h
deleted file mode 120000
index b90c34f..0000000
--- a/include/media/IMediaHTTPService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaHTTPService.h
\ No newline at end of file
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
deleted file mode 120000
index 245a29d..0000000
--- a/include/media/IMediaLogService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaLogService.h
\ No newline at end of file
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
deleted file mode 120000
index 959df1a..0000000
--- a/include/media/IMediaMetadataRetriever.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaMetadataRetriever.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
deleted file mode 120000
index 9414d37..0000000
--- a/include/media/IMediaPlayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayer.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
deleted file mode 120000
index b6547ce..0000000
--- a/include/media/IMediaPlayerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayerClient.h
\ No newline at end of file
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
deleted file mode 120000
index 89c96cd..0000000
--- a/include/media/IMediaPlayerService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaPlayerService.h
\ No newline at end of file
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
deleted file mode 120000
index 57d192c..0000000
--- a/include/media/IMediaRecorder.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaRecorder.h
\ No newline at end of file
diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h
deleted file mode 120000
index 89f4359..0000000
--- a/include/media/IMediaRecorderClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaRecorderClient.h
\ No newline at end of file
diff --git a/include/media/IMediaSource.h b/include/media/IMediaSource.h
deleted file mode 120000
index 1330ad3..0000000
--- a/include/media/IMediaSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaSource.h
\ No newline at end of file
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
deleted file mode 120000
index 6d5b375..0000000
--- a/include/media/IOMX.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IOMX.h
\ No newline at end of file
diff --git a/include/media/IRemoteDisplay.h b/include/media/IRemoteDisplay.h
deleted file mode 120000
index 4b0cf10..0000000
--- a/include/media/IRemoteDisplay.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IRemoteDisplay.h
\ No newline at end of file
diff --git a/include/media/IRemoteDisplayClient.h b/include/media/IRemoteDisplayClient.h
deleted file mode 120000
index f29a2ee..0000000
--- a/include/media/IRemoteDisplayClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IRemoteDisplayClient.h
\ No newline at end of file
diff --git a/include/media/IResourceManagerClient.h b/include/media/IResourceManagerClient.h
deleted file mode 120000
index 100af9b..0000000
--- a/include/media/IResourceManagerClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IResourceManagerClient.h
\ No newline at end of file
diff --git a/include/media/IResourceManagerService.h b/include/media/IResourceManagerService.h
deleted file mode 120000
index 9b389c6..0000000
--- a/include/media/IResourceManagerService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IResourceManagerService.h
\ No newline at end of file
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
deleted file mode 120000
index 4943af9..0000000
--- a/include/media/IStreamSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IStreamSource.h
\ No newline at end of file
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
deleted file mode 120000
index 5483fda..0000000
--- a/include/media/JetPlayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/JetPlayer.h
\ No newline at end of file
diff --git a/include/media/LinearMap.h b/include/media/LinearMap.h
deleted file mode 120000
index 30d4ca8..0000000
--- a/include/media/LinearMap.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/LinearMap.h
\ No newline at end of file
diff --git a/include/media/MediaAnalyticsItem.h b/include/media/MediaAnalyticsItem.h
deleted file mode 120000
index e8124e0..0000000
--- a/include/media/MediaAnalyticsItem.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/MediaAnalyticsItem.h
\ No newline at end of file
diff --git a/include/media/MediaCodecBuffer.h b/include/media/MediaCodecBuffer.h
deleted file mode 120000
index 8c9aa76..0000000
--- a/include/media/MediaCodecBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaCodecBuffer.h
\ No newline at end of file
diff --git a/include/media/MediaCodecInfo.h b/include/media/MediaCodecInfo.h
deleted file mode 120000
index ff44ce4..0000000
--- a/include/media/MediaCodecInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaCodecInfo.h
\ No newline at end of file
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
deleted file mode 120000
index 1c53511..0000000
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaMetadataRetrieverInterface.h
\ No newline at end of file
diff --git a/include/media/MediaMetrics.h b/include/media/MediaMetrics.h
deleted file mode 120000
index 5f757e4..0000000
--- a/include/media/MediaMetrics.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediametrics/include/MediaMetrics.h
\ No newline at end of file
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
deleted file mode 120000
index 651c6e6..0000000
--- a/include/media/MediaProfiles.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaProfiles.h
\ No newline at end of file
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
deleted file mode 120000
index e40f992..0000000
--- a/include/media/MediaRecorderBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaRecorderBase.h
\ No newline at end of file
diff --git a/include/media/MediaResource.h b/include/media/MediaResource.h
deleted file mode 120000
index 91346aa..0000000
--- a/include/media/MediaResource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaResource.h
\ No newline at end of file
diff --git a/include/media/MediaResourcePolicy.h b/include/media/MediaResourcePolicy.h
deleted file mode 120000
index 5d165ee..0000000
--- a/include/media/MediaResourcePolicy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MediaResourcePolicy.h
\ No newline at end of file
diff --git a/include/media/MediaSource.h b/include/media/MediaSource.h
deleted file mode 120000
index 34bf65d..0000000
--- a/include/media/MediaSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libstagefright/include/media/stagefright/MediaSource.h
\ No newline at end of file
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
deleted file mode 120000
index 504173e..0000000
--- a/include/media/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MemoryLeakTrackUtil.h
\ No newline at end of file
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
deleted file mode 120000
index e421168..0000000
--- a/include/media/Metadata.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Metadata.h
\ No newline at end of file
diff --git a/include/media/MidiDeviceInfo.h b/include/media/MidiDeviceInfo.h
deleted file mode 120000
index 95da7cf..0000000
--- a/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MidiDeviceInfo.h
\ No newline at end of file
diff --git a/include/media/MidiIoWrapper.h b/include/media/MidiIoWrapper.h
deleted file mode 120000
index 786ec3d..0000000
--- a/include/media/MidiIoWrapper.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/MidiIoWrapper.h
\ No newline at end of file
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index 0196a0c..b3bf16d 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -107,12 +107,15 @@
      * createMmapBuffer() must be called before calling start()
      *
      * \param[in] client a AudioClient struct describing the client starting on this stream.
+     * \param[in] attr audio attributes provided by the client.
      * \param[out] handle unique handle for this instance. Used with stop().
      * \return OK in case of success.
      *         NO_INIT in case of initialization error
      *         INVALID_OPERATION if called out of sequence
      */
-    virtual status_t start(const AudioClient& client, audio_port_handle_t *handle) = 0;
+    virtual status_t start(const AudioClient& client,
+                           const audio_attributes_t *attr,
+                           audio_port_handle_t *handle) = 0;
 
     /**
      * Stop a stream operating in mmap mode.
diff --git a/include/media/Modulo.h b/include/media/Modulo.h
deleted file mode 120000
index 989c4cb..0000000
--- a/include/media/Modulo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Modulo.h
\ No newline at end of file
diff --git a/include/media/OMXBuffer.h b/include/media/OMXBuffer.h
deleted file mode 120000
index 00db207..0000000
--- a/include/media/OMXBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/OMXBuffer.h
\ No newline at end of file
diff --git a/include/media/OMXFenceParcelable.h b/include/media/OMXFenceParcelable.h
deleted file mode 120000
index c4c1b0a..0000000
--- a/include/media/OMXFenceParcelable.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/OMXFenceParcelable.h
\ No newline at end of file
diff --git a/include/media/PluginLoader.h b/include/media/PluginLoader.h
deleted file mode 120000
index 9101735..0000000
--- a/include/media/PluginLoader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/PluginLoader.h
\ No newline at end of file
diff --git a/include/media/PluginMetricsReporting.h b/include/media/PluginMetricsReporting.h
deleted file mode 120000
index 7d9a7a0..0000000
--- a/include/media/PluginMetricsReporting.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/PluginMetricsReporting.h
\ No newline at end of file
diff --git a/include/media/RecordBufferConverter.h b/include/media/RecordBufferConverter.h
deleted file mode 120000
index 2d7bc0c..0000000
--- a/include/media/RecordBufferConverter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/RecordBufferConverter.h
\ No newline at end of file
diff --git a/include/media/RingBuffer.h b/include/media/RingBuffer.h
deleted file mode 120000
index 9af28d5..0000000
--- a/include/media/RingBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/RingBuffer.h
\ No newline at end of file
diff --git a/include/media/SingleStateQueue.h b/include/media/SingleStateQueue.h
deleted file mode 120000
index 619f6ee..0000000
--- a/include/media/SingleStateQueue.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/SingleStateQueue.h
\ No newline at end of file
diff --git a/include/media/StringArray.h b/include/media/StringArray.h
deleted file mode 120000
index 616ce6c..0000000
--- a/include/media/StringArray.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/StringArray.h
\ No newline at end of file
diff --git a/include/media/TEST_MAPPING b/include/media/TEST_MAPPING
new file mode 100644
index 0000000..ac697da
--- /dev/null
+++ b/include/media/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/av/include/drm"
+    }
+  ]
+}
diff --git a/include/media/TimeCheck.h b/include/media/TimeCheck.h
deleted file mode 120000
index 85e17f9..0000000
--- a/include/media/TimeCheck.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/utils/include/mediautils/TimeCheck.h
\ No newline at end of file
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
deleted file mode 120000
index 33df0e3..0000000
--- a/include/media/ToneGenerator.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/media/ToneGenerator.h
\ No newline at end of file
diff --git a/include/media/TypeConverter.h b/include/media/TypeConverter.h
deleted file mode 120000
index 837af44..0000000
--- a/include/media/TypeConverter.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/TypeConverter.h
\ No newline at end of file
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
deleted file mode 120000
index ed2ec15..0000000
--- a/include/media/Visualizer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Visualizer.h
\ No newline at end of file
diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h
index 79afd6c..fe519bb 100644
--- a/include/media/VolumeShaper.h
+++ b/include/media/VolumeShaper.h
@@ -132,7 +132,7 @@
             , mDurationMs(1000.) {
         }
 
-        explicit Configuration(const Configuration &configuration)
+        Configuration(const Configuration &configuration)
             : Interpolator<S, T>(*static_cast<const Interpolator<S, T> *>(&configuration))
             , RefBase()
             , mType(configuration.mType)
@@ -361,7 +361,7 @@
             : Operation(flags, replaceId, std::numeric_limits<S>::quiet_NaN() /* xOffset */) {
         }
 
-        explicit Operation(const Operation &operation)
+        Operation(const Operation &operation)
             : Operation(operation.mFlags, operation.mReplaceId, operation.mXOffset) {
         }
 
diff --git a/include/media/audiohal b/include/media/audiohal
deleted file mode 120000
index f400582..0000000
--- a/include/media/audiohal
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudiohal/include/media/audiohal/
\ No newline at end of file
diff --git a/include/media/convert.h b/include/media/convert.h
deleted file mode 120000
index cb0d00d..0000000
--- a/include/media/convert.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/convert.h
\ No newline at end of file
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
deleted file mode 120000
index b401bab..0000000
--- a/include/media/mediametadataretriever.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediametadataretriever.h
\ No newline at end of file
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
deleted file mode 120000
index 06d537b..0000000
--- a/include/media/mediaplayer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediaplayer.h
\ No newline at end of file
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
deleted file mode 120000
index a24deb3..0000000
--- a/include/media/mediarecorder.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediarecorder.h
\ No newline at end of file
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
deleted file mode 120000
index 91479e0..0000000
--- a/include/media/mediascanner.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/mediascanner.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioBufferProviderSource.h b/include/media/nbaio/AudioBufferProviderSource.h
deleted file mode 120000
index 55841e7..0000000
--- a/include/media/nbaio/AudioBufferProviderSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/AudioBufferProviderSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
deleted file mode 120000
index f5bcc76..0000000
--- a/include/media/nbaio/AudioStreamInSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/AudioStreamInSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
deleted file mode 120000
index 43bfac5..0000000
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/AudioStreamOutSink.h
\ No newline at end of file
diff --git a/include/media/nbaio/LibsndfileSink.h b/include/media/nbaio/LibsndfileSink.h
deleted file mode 120000
index 8a13b6c..0000000
--- a/include/media/nbaio/LibsndfileSink.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/LibsndfileSink.h
\ No newline at end of file
diff --git a/include/media/nbaio/LibsndfileSource.h b/include/media/nbaio/LibsndfileSource.h
deleted file mode 120000
index 2750fde..0000000
--- a/include/media/nbaio/LibsndfileSource.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/LibsndfileSource.h
\ No newline at end of file
diff --git a/include/media/nbaio/MonoPipe.h b/include/media/nbaio/MonoPipe.h
deleted file mode 120000
index 4ea43be..0000000
--- a/include/media/nbaio/MonoPipe.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include_mono/media/nbaio/MonoPipe.h
\ No newline at end of file
diff --git a/include/media/nbaio/MonoPipeReader.h b/include/media/nbaio/MonoPipeReader.h
deleted file mode 120000
index 30f426c..0000000
--- a/include/media/nbaio/MonoPipeReader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include_mono/media/nbaio/MonoPipeReader.h
\ No newline at end of file
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
deleted file mode 120000
index ff6a151..0000000
--- a/include/media/nbaio/NBAIO.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include_mono/media/nbaio/NBAIO.h
\ No newline at end of file
diff --git a/include/media/nbaio/Pipe.h b/include/media/nbaio/Pipe.h
deleted file mode 120000
index a4bbbc9..0000000
--- a/include/media/nbaio/Pipe.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/Pipe.h
\ No newline at end of file
diff --git a/include/media/nbaio/PipeReader.h b/include/media/nbaio/PipeReader.h
deleted file mode 120000
index 64b21cf..0000000
--- a/include/media/nbaio/PipeReader.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/PipeReader.h
\ No newline at end of file
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
deleted file mode 120000
index 74a3b06..0000000
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnbaio/include/media/nbaio/SourceAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/nblog/NBLog.h b/include/media/nblog/NBLog.h
deleted file mode 120000
index 3cc366c..0000000
--- a/include/media/nblog/NBLog.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/NBLog.h
\ No newline at end of file
diff --git a/include/media/nblog/PerformanceAnalysis.h b/include/media/nblog/PerformanceAnalysis.h
deleted file mode 120000
index 6ead3bc..0000000
--- a/include/media/nblog/PerformanceAnalysis.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/PerformanceAnalysis.h
\ No newline at end of file
diff --git a/include/media/nblog/ReportPerformance.h b/include/media/nblog/ReportPerformance.h
deleted file mode 120000
index e9b8e80..0000000
--- a/include/media/nblog/ReportPerformance.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../media/libnblog/include/media/nblog/ReportPerformance.h
\ No newline at end of file
diff --git a/include/media/stagefright b/include/media/stagefright
deleted file mode 120000
index 5393f68..0000000
--- a/include/media/stagefright
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libstagefright/include/media/stagefright/
\ No newline at end of file
diff --git a/include/mediadrm/CryptoHal.h b/include/mediadrm/CryptoHal.h
deleted file mode 120000
index 92f3137..0000000
--- a/include/mediadrm/CryptoHal.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/CryptoHal.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmHal.h b/include/mediadrm/DrmHal.h
deleted file mode 120000
index 17bb667..0000000
--- a/include/mediadrm/DrmHal.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmHal.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmMetrics.h b/include/mediadrm/DrmMetrics.h
deleted file mode 120000
index abc966b..0000000
--- a/include/mediadrm/DrmMetrics.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmMetrics.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmPluginPath.h b/include/mediadrm/DrmPluginPath.h
deleted file mode 120000
index 9e05194..0000000
--- a/include/mediadrm/DrmPluginPath.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmPluginPath.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmSessionClientInterface.h b/include/mediadrm/DrmSessionClientInterface.h
deleted file mode 120000
index f4e3211..0000000
--- a/include/mediadrm/DrmSessionClientInterface.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmSessionClientInterface.h
\ No newline at end of file
diff --git a/include/mediadrm/DrmSessionManager.h b/include/mediadrm/DrmSessionManager.h
deleted file mode 120000
index f0a47bf..0000000
--- a/include/mediadrm/DrmSessionManager.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/DrmSessionManager.h
\ No newline at end of file
diff --git a/include/mediadrm/ICrypto.h b/include/mediadrm/ICrypto.h
deleted file mode 120000
index b250e07..0000000
--- a/include/mediadrm/ICrypto.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/ICrypto.h
\ No newline at end of file
diff --git a/include/mediadrm/IDrm.h b/include/mediadrm/IDrm.h
deleted file mode 120000
index 841bb1b..0000000
--- a/include/mediadrm/IDrm.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDrm.h
\ No newline at end of file
diff --git a/include/mediadrm/IDrmClient.h b/include/mediadrm/IDrmClient.h
deleted file mode 120000
index 10aa5c0..0000000
--- a/include/mediadrm/IDrmClient.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IDrmClient.h
\ No newline at end of file
diff --git a/include/mediadrm/IMediaDrmService.h b/include/mediadrm/IMediaDrmService.h
deleted file mode 120000
index f3c260f..0000000
--- a/include/mediadrm/IMediaDrmService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/IMediaDrmService.h
\ No newline at end of file
diff --git a/include/mediadrm/SharedLibrary.h b/include/mediadrm/SharedLibrary.h
deleted file mode 120000
index 9f8f5a4..0000000
--- a/include/mediadrm/SharedLibrary.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/SharedLibrary.h
\ No newline at end of file
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 5f19f74..9cabd8b 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -28,7 +28,7 @@
 #include <media/AudioResamplerPublic.h>
 #include <media/AudioTimestamp.h>
 #include <media/Modulo.h>
-#include <media/SingleStateQueue.h>
+#include <media/nbaio/SingleStateQueue.h>
 
 namespace android {
 
@@ -575,7 +575,7 @@
 class AudioTrackServerProxy : public ServerProxy {
 public:
     AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
-            size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0)
+            size_t frameSize, bool clientInServer, uint32_t sampleRate)
         : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer),
           mPlaybackRateObserver(&cblk->mPlaybackRateQueue),
           mUnderrunCount(0), mUnderrunning(false), mDrained(true) {
@@ -614,6 +614,8 @@
     // and thus which resulted in an underrun.
     virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
 
+    virtual uint32_t    getUnderrunCount() const { return mCblk->u.mStreaming.mUnderrunCount; }
+
     // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
     AudioPlaybackRate getPlaybackRate();
 
@@ -651,7 +653,7 @@
 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
 public:
     StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
-            size_t frameSize);
+            size_t frameSize, uint32_t sampleRate);
 protected:
     virtual ~StaticAudioTrackServerProxy() { }
 
diff --git a/include/private/media/TEST_MAPPING b/include/private/media/TEST_MAPPING
new file mode 100644
index 0000000..ac697da
--- /dev/null
+++ b/include/private/media/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "imports": [
+    {
+      "path": "frameworks/av/include/drm"
+    }
+  ]
+}
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 712f118..16e794a 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -41,7 +41,7 @@
             uint32_t angle, uint32_t bpp, bool hasData, size_t iccSize):
         mWidth(width), mHeight(height),
         mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
-        mTileWidth(tileWidth), mTileHeight(tileHeight),
+        mTileWidth(tileWidth), mTileHeight(tileHeight), mDurationUs(0),
         mRotationAngle(angle), mBytesPerPixel(bpp), mRowBytes(bpp * width),
         mSize(hasData ? (bpp * width * height) : 0),
         mIccSize(iccSize), mReserved(0) {
@@ -78,6 +78,7 @@
     uint32_t mDisplayHeight;   // Display height 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
     int32_t  mRotationAngle;   // Rotation angle, clockwise, should be multiple of 90
     uint32_t mBytesPerPixel;   // Number of bytes per pixel
     uint32_t mRowBytes;        // Number of bytes per row before rotation
diff --git a/include/soundtrigger/ISoundTrigger.h b/include/soundtrigger/ISoundTrigger.h
deleted file mode 100644
index c357caa..0000000
--- a/include/soundtrigger/ISoundTrigger.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_HARDWARE_ISOUNDTRIGGER_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class ISoundTrigger : public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(SoundTrigger);
-
-    virtual void detach() = 0;
-
-    virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
-                                    sound_model_handle_t *handle) = 0;
-
-    virtual status_t unloadSoundModel(sound_model_handle_t handle) = 0;
-
-    virtual status_t startRecognition(sound_model_handle_t handle,
-                                      const sp<IMemory>& dataMemory) = 0;
-    virtual status_t stopRecognition(sound_model_handle_t handle) = 0;
-    virtual status_t getModelState(sound_model_handle_t handle) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTrigger: public BnInterface<ISoundTrigger>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_H
diff --git a/include/soundtrigger/ISoundTriggerClient.h b/include/soundtrigger/ISoundTriggerClient.h
deleted file mode 100644
index 480429a..0000000
--- a/include/soundtrigger/ISoundTriggerClient.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class ISoundTriggerClient : public IInterface
-{
-public:
-
-    DECLARE_META_INTERFACE(SoundTriggerClient);
-
-    virtual void onRecognitionEvent(const sp<IMemory>& eventMemory) = 0;
-
-    virtual void onSoundModelEvent(const sp<IMemory>& eventMemory) = 0;
-
-    virtual void onServiceStateChange(const sp<IMemory>& eventMemory) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTriggerClient : public BnInterface<ISoundTriggerClient>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_CLIENT_H
diff --git a/include/soundtrigger/ISoundTriggerHwService.h b/include/soundtrigger/ISoundTriggerHwService.h
deleted file mode 100644
index 1faeb0f..0000000
--- a/include/soundtrigger/ISoundTriggerHwService.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
-#define ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class ISoundTrigger;
-class ISoundTriggerClient;
-
-class ISoundTriggerHwService : public IInterface
-{
-public:
-
-    DECLARE_META_INTERFACE(SoundTriggerHwService);
-
-    virtual status_t listModules(const String16& opPackageName,
-                                 struct sound_trigger_module_descriptor *modules,
-                                 uint32_t *numModules) = 0;
-
-    virtual status_t attach(const String16& opPackageName,
-                            const sound_trigger_module_handle_t handle,
-                            const sp<ISoundTriggerClient>& client,
-                            sp<ISoundTrigger>& module) = 0;
-
-    virtual status_t setCaptureState(bool active) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnSoundTriggerHwService: public BnInterface<ISoundTriggerHwService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_ISOUNDTRIGGER_SERVICE_H
diff --git a/include/soundtrigger/OWNERS b/include/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/include/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
deleted file mode 100644
index ccc61dc..0000000
--- a/include/soundtrigger/SoundTrigger.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_HARDWARE_SOUNDTRIGGER_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_H
-
-#include <binder/IBinder.h>
-#include <utils/threads.h>
-#include <soundtrigger/SoundTriggerCallback.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class MemoryDealer;
-
-class SoundTrigger : public BnSoundTriggerClient,
-                        public IBinder::DeathRecipient
-{
-public:
-
-    virtual ~SoundTrigger();
-
-    static  status_t listModules(const String16& opPackageName,
-                                 struct sound_trigger_module_descriptor *modules,
-                                 uint32_t *numModules);
-    static  sp<SoundTrigger> attach(const String16& opPackageName,
-                                    const sound_trigger_module_handle_t module,
-                                    const sp<SoundTriggerCallback>& callback);
-
-    static  status_t setCaptureState(bool active);
-
-            void detach();
-
-            status_t loadSoundModel(const sp<IMemory>& modelMemory,
-                                            sound_model_handle_t *handle);
-
-            status_t unloadSoundModel(sound_model_handle_t handle);
-
-            status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory);
-            status_t stopRecognition(sound_model_handle_t handle);
-            status_t getModelState(sound_model_handle_t handle);
-
-            // BpSoundTriggerClient
-            virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
-            virtual void onSoundModelEvent(const sp<IMemory>& eventMemory);
-            virtual void onServiceStateChange(const sp<IMemory>& eventMemory);
-
-            //IBinder::DeathRecipient
-            virtual void binderDied(const wp<IBinder>& who);
-
-            static status_t stringToGuid(const char *str, sound_trigger_uuid_t *guid);
-            static status_t guidToString(const sound_trigger_uuid_t *guid,
-                                         char *str, size_t maxLen);
-
-private:
-            SoundTrigger(sound_trigger_module_handle_t module,
-                            const sp<SoundTriggerCallback>&);
-            static const sp<ISoundTriggerHwService> getSoundTriggerHwService();
-
-            Mutex                               mLock;
-            sp<ISoundTrigger>                   mISoundTrigger;
-            sp<SoundTriggerCallback>            mCallback;
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_SOUNDTRIGGER_H
diff --git a/include/soundtrigger/SoundTriggerCallback.h b/include/soundtrigger/SoundTriggerCallback.h
deleted file mode 100644
index b5277f2..0000000
--- a/include/soundtrigger/SoundTriggerCallback.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
-
-#include <utils/RefBase.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-class SoundTriggerCallback : public RefBase
-{
-public:
-
-            SoundTriggerCallback() {}
-    virtual ~SoundTriggerCallback() {}
-
-    virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event) = 0;
-
-    virtual void onSoundModelEvent(struct sound_trigger_model_event *event) = 0;
-
-    virtual void onServiceStateChange(sound_trigger_service_state_t state) = 0;
-
-    virtual void onServiceDied() = 0;
-
-};
-
-}; // namespace android
-
-#endif //ANDROID_HARDWARE_SOUNDTRIGGER_CALLBACK_H
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
new file mode 100644
index 0000000..a6dfb21
--- /dev/null
+++ b/media/TEST_MAPPING
@@ -0,0 +1,32 @@
+{
+  "presubmit": [
+    {
+      "name": "GtsMediaTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+        }
+      ]
+    },
+    {
+      "name": "GtsExoPlayerTestCases",
+      "options" : [
+        {
+          "include-annotation": "android.platform.test.annotations.SocPresubmit"
+        },
+        {
+          "include-filter": "com.google.android.exoplayer.gts.DashTest#testWidevine23FpsH264Fixed"
+        }
+      ]
+    }
+  ],
+  "imports": [
+    {
+      "path": "frameworks/av/drm/mediadrm/plugins"
+    }
+  ]
+}
+
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 33b36b8..cf1c14c 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -9,21 +9,23 @@
 	libaaudioservice \
 	libaudioflinger \
 	libaudiopolicyservice \
+	libaudioprocessing \
 	libbinder \
 	libcutils \
 	liblog \
 	libhidlbase \
-	libhidltransport \
-	libhwbinder \
 	libmedia \
 	libmedialogservice \
 	libmediautils \
 	libnbaio \
 	libnblog \
-	libsoundtriggerservice \
 	libutils \
 	libvibrator
 
+LOCAL_HEADER_LIBRARIES := \
+	libaudiohal_headers \
+	libmediametrics_headers \
+
 # TODO oboeservice is the old folder name for aaudioservice. It will be changed.
 LOCAL_C_INCLUDES := \
 	frameworks/av/services/audioflinger \
@@ -34,30 +36,12 @@
 	frameworks/av/services/audiopolicy/service \
 	frameworks/av/services/medialog \
 	frameworks/av/services/oboeservice \
-	frameworks/av/services/radio \
-	frameworks/av/services/soundtrigger \
 	frameworks/av/media/libaaudio/include \
 	frameworks/av/media/libaaudio/src \
 	frameworks/av/media/libaaudio/src/binding \
-	frameworks/av/media/libmedia \
-	$(call include-path-for, audio-utils) \
+	frameworks/av/media/libmedia/include \
 	external/sonic \
 
-# If AUDIOSERVER_MULTILIB in device.mk is non-empty then it is used to control
-# the LOCAL_MULTILIB for all audioserver exclusive libraries.
-# This is relevant for 64 bit architectures where either or both
-# 32 and 64 bit libraries may be built.
-#
-# AUDIOSERVER_MULTILIB may be set as follows:
-#   32      to build 32 bit audioserver libraries and 32 bit audioserver.
-#   64      to build 64 bit audioserver libraries and 64 bit audioserver.
-#   both    to build both 32 bit and 64 bit libraries,
-#           and use primary target architecture (32 or 64) for audioserver.
-#   first   to build libraries and audioserver for the primary target architecture only.
-#   <empty> to build both 32 and 64 bit libraries and primary target audioserver.
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
 LOCAL_MODULE := audioserver
 
 LOCAL_INIT_RC := audioserver.rc
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index dfb1a3f..f05c2d2 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -2,20 +2,48 @@
     class core
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
-    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock
+    group audio camera drmrpc media mediadrm net_bt net_bt_admin net_bw_acct wakelock
     capabilities BLOCK_SUSPEND
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
-    onrestart restart vendor.audio-hal-2-0
-    onrestart restart vendor.audio-hal-4-0-msd
-    # Keep the original service name for backward compatibility when upgrading
-    # O-MR1 devices with framework-only.
-    onrestart restart audio-hal-2-0
+    task_profiles ProcessCapacityHigh HighPerformance
+
+    onrestart setprop sys.audio.restart.hal 1
 
 on property:vts.native_server.on=1
     stop audioserver
 on property:vts.native_server.on=0
     start audioserver
 
+on property:init.svc.audioserver=stopped
+    stop vendor.audio-hal
+    stop vendor.audio-hal-4-0-msd
+    # Keep the original service names for backward compatibility
+    stop vendor.audio-hal-2-0
+    stop audio-hal-2-0
+    # See b/155364397. Need to have HAL service running for VTS.
+    # Can't use 'restart' because then HAL service would restart
+    # audioserver bringing it back into running state.
+    start vendor.audio-hal
+    start vendor.audio-hal-4-0-msd
+    # Keep the original service names for backward compatibility
+    start vendor.audio-hal-2-0
+    start audio-hal-2-0
+
+on property:init.svc.audioserver=running
+    start vendor.audio-hal
+    start vendor.audio-hal-4-0-msd
+    # Keep the original service names for backward compatibility
+    start vendor.audio-hal-2-0
+    start audio-hal-2-0
+
+on property:sys.audio.restart.hal=1
+    restart vendor.audio-hal
+    restart vendor.audio-hal-4-0-msd
+    # Keep the original service names for backward compatibility
+    restart vendor.audio-hal-2-0
+    restart audio-hal-2-0
+    # reset the property
+    setprop sys.audio.restart.hal 0
+
 on init
     mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index db57248..f9f4f31 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -26,6 +26,7 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <hidl/HidlTransportSupport.h>
+#include <mediautils/LimitProcessMemory.h>
 #include <utils/Log.h>
 
 // from LOCAL_C_INCLUDES
@@ -35,8 +36,6 @@
 #include "AAudioService.h"
 #include "utility/AAudioUtilities.h"
 #include "MediaLogService.h"
-#include "MediaUtils.h"
-#include "SoundTriggerHwService.h"
 
 using namespace android;
 
@@ -148,7 +147,6 @@
             AAudioService::instantiate();
         }
 
-        SoundTriggerHwService::instantiate();
         ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
     }
diff --git a/media/bufferpool/1.0/AccessorImpl.cpp b/media/bufferpool/1.0/AccessorImpl.cpp
index a5366f6..0d7e92f 100644
--- a/media/bufferpool/1.0/AccessorImpl.cpp
+++ b/media/bufferpool/1.0/AccessorImpl.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BufferPoolAccessor"
+#define LOG_TAG "BufferPoolAccessor1.0"
 //#define LOG_NDEBUG 0
 
 #include <sys/types.h>
+#include <stdint.h>
 #include <time.h>
 #include <unistd.h>
 #include <utils/Log.h>
@@ -127,7 +128,6 @@
     return false;
 }
 
-int32_t Accessor::Impl::sPid = getpid();
 uint32_t Accessor::Impl::sSeqId = time(nullptr);
 
 Accessor::Impl::Impl(
@@ -145,14 +145,19 @@
     {
         std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
         if (newConnection) {
-            ConnectionId id = (int64_t)sPid << 32 | sSeqId;
+            int32_t pid = getpid();
+            ConnectionId id = (int64_t)pid << 32 | sSeqId;
             status = mBufferPool.mObserver.open(id, fmqDescPtr);
             if (status == ResultStatus::OK) {
                 newConnection->initialize(accessor, id);
                 *connection = newConnection;
                 *pConnectionId = id;
                 mBufferPool.mConnectionIds.insert(id);
-                ++sSeqId;
+                if (sSeqId == UINT32_MAX) {
+                   sSeqId = 0;
+                } else {
+                    ++sSeqId;
+                }
             }
         }
         mBufferPool.processStatusMessages();
@@ -248,7 +253,7 @@
     ALOGD("Destruction - bufferpool %p "
           "cached: %zu/%zuM, %zu/%d%% in use; "
           "allocs: %zu, %d%% recycled; "
-          "transfers: %zu, %d%% unfetced",
+          "transfers: %zu, %d%% unfetched",
           this, mStats.mBuffersCached, mStats.mSizeCached >> 20,
           mStats.mBuffersInUse, percentage(mStats.mBuffersInUse, mStats.mBuffersCached),
           mStats.mTotalAllocations, percentage(mStats.mTotalRecycles, mStats.mTotalAllocations),
diff --git a/media/bufferpool/1.0/AccessorImpl.h b/media/bufferpool/1.0/AccessorImpl.h
index 84cb685..a09cbe2 100644
--- a/media/bufferpool/1.0/AccessorImpl.h
+++ b/media/bufferpool/1.0/AccessorImpl.h
@@ -61,7 +61,6 @@
     // ConnectionId = pid : (timestamp_created + seqId)
     // in order to guarantee uniqueness for each connection
     static uint32_t sSeqId;
-    static int32_t sPid;
 
     const std::shared_ptr<BufferPoolAllocator> mAllocator;
 
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index c7ea70f..f817c76 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -16,8 +16,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhwbinder",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.media.bufferpool@1.0",
diff --git a/media/bufferpool/2.0/Accessor.cpp b/media/bufferpool/2.0/Accessor.cpp
index 57b4609..e05b12a 100644
--- a/media/bufferpool/2.0/Accessor.cpp
+++ b/media/bufferpool/2.0/Accessor.cpp
@@ -117,6 +117,10 @@
     Accessor::Impl::createInvalidator();
 }
 
+void Accessor::createEvictor() {
+    Accessor::Impl::createEvictor();
+}
+
 // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow.
 Return<void> Accessor::connect(
         const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer,
diff --git a/media/bufferpool/2.0/Accessor.h b/media/bufferpool/2.0/Accessor.h
index 8d02519..8b43301 100644
--- a/media/bufferpool/2.0/Accessor.h
+++ b/media/bufferpool/2.0/Accessor.h
@@ -187,6 +187,8 @@
 
     static void createInvalidator();
 
+    static void createEvictor();
+
 private:
     class Impl;
     std::shared_ptr<Impl> mImpl;
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 0d591d7..6111fea 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BufferPoolAccessor"
+#define LOG_TAG "BufferPoolAccessor2.0"
 //#define LOG_NDEBUG 0
 
 #include <sys/types.h>
+#include <stdint.h>
 #include <time.h>
 #include <unistd.h>
 #include <utils/Log.h>
@@ -38,6 +39,9 @@
 
     static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
     static constexpr size_t kMinBufferCountForEviction = 25;
+
+    static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
+    static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
 }
 
 // Buffer structure in bufferpool process
@@ -134,12 +138,18 @@
     return false;
 }
 
-int32_t Accessor::Impl::sPid = getpid();
-uint32_t Accessor::Impl::sSeqId = time(nullptr);
+#ifdef __ANDROID_VNDK__
+static constexpr uint32_t kSeqIdVndkBit = 1U << 31;
+#else
+static constexpr uint32_t kSeqIdVndkBit = 0;
+#endif
+
+static constexpr uint32_t kSeqIdMax = 0x7fffffff;
+uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax;
 
 Accessor::Impl::Impl(
         const std::shared_ptr<BufferPoolAllocator> &allocator)
-        : mAllocator(allocator) {}
+        : mAllocator(allocator), mScheduleEvictTs(0) {}
 
 Accessor::Impl::~Impl() {
 }
@@ -156,7 +166,8 @@
     {
         std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
         if (newConnection) {
-            ConnectionId id = (int64_t)sPid << 32 | sSeqId;
+            int32_t pid = getpid();
+            ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit;
             status = mBufferPool.mObserver.open(id, statusDescPtr);
             if (status == ResultStatus::OK) {
                 newConnection->initialize(accessor, id);
@@ -166,12 +177,17 @@
                 mBufferPool.mConnectionIds.insert(id);
                 mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
                 mBufferPool.mInvalidation.onConnect(id, observer);
-                ++sSeqId;
+                if (sSeqId == kSeqIdMax) {
+                   sSeqId = 0;
+                } else {
+                    ++sSeqId;
+                }
             }
 
         }
         mBufferPool.processStatusMessages();
         mBufferPool.cleanUp();
+        scheduleEvictIfNeeded();
     }
     return status;
 }
@@ -186,6 +202,7 @@
     // Since close# will be called after all works are finished, it is OK to
     // evict unused buffers.
     mBufferPool.cleanUp(true);
+    scheduleEvictIfNeeded();
     return ResultStatus::OK;
 }
 
@@ -212,6 +229,7 @@
         mBufferPool.handleOwnBuffer(connectionId, *bufferId);
     }
     mBufferPool.cleanUp();
+    scheduleEvictIfNeeded();
     return status;
 }
 
@@ -237,6 +255,7 @@
         }
     }
     mBufferPool.cleanUp();
+    scheduleEvictIfNeeded();
     return ResultStatus::CRITICAL_ERROR;
 }
 
@@ -304,7 +323,7 @@
     ALOGD("Destruction - bufferpool2 %p "
           "cached: %zu/%zuM, %zu/%d%% in use; "
           "allocs: %zu, %d%% recycled; "
-          "transfers: %zu, %d%% unfetced",
+          "transfers: %zu, %d%% unfetched",
           this, mStats.mBuffersCached, mStats.mSizeCached >> 20,
           mStats.mBuffersInUse, percentage(mStats.mBuffersInUse, mStats.mBuffersCached),
           mStats.mTotalAllocations, percentage(mStats.mTotalRecycles, mStats.mTotalAllocations),
@@ -879,6 +898,88 @@
     }
 }
 
+void Accessor::Impl::evictorThread(
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors,
+        std::mutex &mutex,
+        std::condition_variable &cv) {
+    std::list<const std::weak_ptr<Accessor::Impl>> evictList;
+    while (true) {
+        int expired = 0;
+        int evicted = 0;
+        {
+            nsecs_t now = systemTime();
+            std::unique_lock<std::mutex> lock(mutex);
+            if (accessors.size() == 0) {
+                cv.wait(lock);
+            }
+            auto it = accessors.begin();
+            while (it != accessors.end()) {
+                if (now > (it->second + kEvictDurationNs)) {
+                    ++expired;
+                    evictList.push_back(it->first);
+                    it = accessors.erase(it);
+                } else {
+                    ++it;
+                }
+            }
+        }
+        // evict idle accessors;
+        for (auto it = evictList.begin(); it != evictList.end(); ++it) {
+            const std::shared_ptr<Accessor::Impl> accessor = it->lock();
+            if (accessor) {
+                accessor->cleanUp(true);
+                ++evicted;
+            }
+        }
+        if (expired > 0) {
+            ALOGD("evictor expired: %d, evicted: %d", expired, evicted);
+        }
+        evictList.clear();
+        ::usleep(kEvictGranularityNs / 1000);
+    }
+}
+
+Accessor::Impl::AccessorEvictor::AccessorEvictor() {
+    std::thread evictor(
+            evictorThread,
+            std::ref(mAccessors),
+            std::ref(mMutex),
+            std::ref(mCv));
+    evictor.detach();
+}
+
+void Accessor::Impl::AccessorEvictor::addAccessor(
+        const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    bool notify = mAccessors.empty();
+    auto it = mAccessors.find(impl);
+    if (it == mAccessors.end()) {
+        mAccessors.emplace(impl, ts);
+    } else {
+        it->second = ts;
+    }
+    if (notify) {
+        mCv.notify_one();
+    }
+}
+
+std::unique_ptr<Accessor::Impl::AccessorEvictor> Accessor::Impl::sEvictor;
+
+void Accessor::Impl::createEvictor() {
+    if (!sEvictor) {
+        sEvictor = std::make_unique<Accessor::Impl::AccessorEvictor>();
+    }
+}
+
+void Accessor::Impl::scheduleEvictIfNeeded() {
+    nsecs_t now = systemTime();
+
+    if (now > (mScheduleEvictTs + kEvictGranularityNs)) {
+        mScheduleEvictTs = now;
+        sEvictor->addAccessor(shared_from_this(), now);
+    }
+}
+
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace bufferpool
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index 807e0f1..cd1b4d0 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -20,6 +20,7 @@
 #include <map>
 #include <set>
 #include <condition_variable>
+#include <utils/Timers.h>
 #include "Accessor.h"
 
 namespace android {
@@ -71,14 +72,17 @@
 
     static void createInvalidator();
 
+    static void createEvictor();
+
 private:
     // ConnectionId = pid : (timestamp_created + seqId)
     // in order to guarantee uniqueness for each connection
     static uint32_t sSeqId;
-    static int32_t sPid;
 
     const std::shared_ptr<BufferPoolAllocator> mAllocator;
 
+    nsecs_t mScheduleEvictTs;
+
     /**
      * Buffer pool implementation.
      *
@@ -390,6 +394,25 @@
         std::mutex &mutex,
         std::condition_variable &cv,
         bool &ready);
+
+    struct AccessorEvictor {
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> mAccessors;
+        std::mutex mMutex;
+        std::condition_variable mCv;
+
+        AccessorEvictor();
+        void addAccessor(const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts);
+    };
+
+    static std::unique_ptr<AccessorEvictor> sEvictor;
+
+    static void evictorThread(
+        std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors,
+        std::mutex &mutex,
+        std::condition_variable &cv);
+
+    void scheduleEvictIfNeeded();
+
 };
 
 }  // namespace implementation
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index e8a69c9..536f75e 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -16,8 +16,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhwbinder",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.media.bufferpool@2.0",
@@ -32,6 +30,9 @@
     name: "libstagefright_bufferpool@2.0.1",
     defaults: ["libstagefright_bufferpool@2.0-default"],
     vendor_available: true,
+    min_sdk_version: "29",
+    // TODO: b/147147992
+    double_loadable: true,
     cflags: [
         "-DBUFFERPOOL_CLONE_HANDLES",
     ],
@@ -42,6 +43,8 @@
     name: "libstagefright_bufferpool@2.0",
     defaults: ["libstagefright_bufferpool@2.0-default"],
     vendor_available: true,
+    // TODO: b/147147992
+    double_loadable: true,
     vndk: {
         enabled: true,
     },
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/bufferpool/2.0/ClientManager.cpp
index 87ee4e8..54a20b9 100644
--- a/media/bufferpool/2.0/ClientManager.cpp
+++ b/media/bufferpool/2.0/ClientManager.cpp
@@ -484,6 +484,7 @@
         sInstance = new ClientManager();
     }
     Accessor::createInvalidator();
+    Accessor::createEvictor();
     return sInstance;
 }
 
diff --git a/media/codec2/OWNERS b/media/codec2/OWNERS
new file mode 100644
index 0000000..46a9fca
--- /dev/null
+++ b/media/codec2/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+wonsik@google.com
+lajos@google.com
+pawin@google.com
+taklee@google.com
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
new file mode 100644
index 0000000..8afa1a8
--- /dev/null
+++ b/media/codec2/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsMediaTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+        },
+        // TODO: b/149314419
+        {
+          "exclude-filter": "android.media.cts.AudioPlaybackCaptureTest"
+        },
+        {
+          "exclude-filter": "android.media.cts.AudioRecordTest"
+        }
+      ]
+    }
+  ]
+}
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 2d4e126..677f316 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -40,6 +40,8 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM  0  /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS (0.25) /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
@@ -78,7 +80,8 @@
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
                 .withFields({C2F(mSampleRate, value).oneOf({
-                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+                    44100, 48000, 64000, 88200, 96000
                 })})
                 .withSetter(Setter<decltype(*mSampleRate)>::NonStrictValueWithNoDeps)
                 .build());
@@ -86,11 +89,18 @@
         addParameter(
                 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
                 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
-                .withFields({C2F(mChannelCount, value).inRange(1, 8)})
+                .withFields({C2F(mChannelCount, value).inRange(1, MAX_CHANNEL_COUNT)})
                 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
                 .build());
 
         addParameter(
+                DefineParam(mMaxChannelCount, C2_PARAMKEY_MAX_CHANNEL_COUNT)
+                .withDefault(new C2StreamMaxChannelCountInfo::input(0u, MAX_CHANNEL_COUNT))
+                .withFields({C2F(mMaxChannelCount, value).inRange(1, MAX_CHANNEL_COUNT)})
+                .withSetter(Setter<decltype(*mMaxChannelCount)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
                 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
                 .withDefault(new C2StreamBitrateInfo::input(0u, 64000))
                 .withFields({C2F(mBitrate, value).inRange(8000, 960000)})
@@ -189,6 +199,24 @@
                 })
                 .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps)
                 .build());
+
+        addParameter(
+                DefineParam(mDrcAlbumMode, C2_PARAMKEY_DRC_ALBUM_MODE)
+                .withDefault(new C2StreamDrcAlbumModeTuning::input(0u, C2Config::DRC_ALBUM_MODE_OFF))
+                .withFields({
+                    C2F(mDrcAlbumMode, value).oneOf({
+                            C2Config::DRC_ALBUM_MODE_OFF,
+                            C2Config::DRC_ALBUM_MODE_ON})
+                })
+                .withSetter(Setter<decltype(*mDrcAlbumMode)>::StrictValueWithNoDeps)
+                .build());
+
+        addParameter(
+                DefineParam(mDrcOutputLoudness, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS)
+                .withDefault(new C2StreamDrcOutputLoudnessTuning::output(0u, DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS))
+                .withFields({C2F(mDrcOutputLoudness, value).inRange(-57.75, 0.25)})
+                .withSetter(Setter<decltype(*mDrcOutputLoudness)>::StrictValueWithNoDeps)
+                .build());
     }
 
     bool isAdts() const { return mAacFormat->value == C2Config::AAC_PACKAGING_ADTS; }
@@ -203,6 +231,9 @@
     int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; }
     int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; }
     int32_t getDrcEffectType() const { return mDrcEffectType->value; }
+    int32_t getDrcAlbumMode() const { return mDrcAlbumMode->value; }
+    u_int32_t getMaxChannelCount() const { return mMaxChannelCount->value; }
+    int32_t getDrcOutputLoudness() const { return (mDrcOutputLoudness->value <= 0 ? -mDrcOutputLoudness->value * 4. + 0.5 : -1); }
 
 private:
     std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
@@ -217,6 +248,9 @@
     std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
     std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
     std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
+    std::shared_ptr<C2StreamDrcAlbumModeTuning::input> mDrcAlbumMode;
+    std::shared_ptr<C2StreamMaxChannelCountInfo::input> mMaxChannelCount;
+    std::shared_ptr<C2StreamDrcOutputLoudnessTuning::output> mDrcOutputLoudness;
     // TODO Add : C2StreamAacSbrModeTuning
 };
 
@@ -323,7 +357,7 @@
 
     //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
     int32_t compressMode = mIntf->getDrcCompressMode();
-    ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+    ALOGV("AAC decoder using desired DRC heavy compression switch of %d", compressMode);
     mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
 
     // DRC_PRES_MODE_WRAP_ENCODER_TARGET
@@ -336,9 +370,15 @@
     ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
     aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
 
-    // By default, the decoder creates a 5.1 channel downmix signal.
-    // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
-    aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
+    // AAC_UNIDRC_ALBUM_MODE
+    int32_t albumMode = mIntf->getDrcAlbumMode();
+    ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+    aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
+    // AAC_PCM_MAX_OUTPUT_CHANNELS
+    u_int32_t maxChannelCount = mIntf->getMaxChannelCount();
+    ALOGV("AAC decoder using maximum output channel count %d", maxChannelCount);
+    aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, maxChannelCount);
 
     return status;
 }
@@ -631,6 +671,7 @@
 
         INT prevSampleRate = mStreamInfo->sampleRate;
         INT prevNumChannels = mStreamInfo->numChannels;
+        INT prevOutLoudness = mStreamInfo->outputLoudness;
 
         aacDecoder_Fill(mAACDecoder,
                         inBuffer,
@@ -639,6 +680,48 @@
 
         // run DRC check
         mDrcWrap.submitStreamData(mStreamInfo);
+
+        // apply runtime updates
+        //  DRC_PRES_MODE_WRAP_DESIRED_TARGET
+        int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
+        ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
+        int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
+        ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
+        int32_t boostFactor = mIntf->getDrcBoostFactor();
+        ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
+
+        //  DRC_PRES_MODE_WRAP_DESIRED_HEAVY
+        int32_t compressMode = mIntf->getDrcCompressMode();
+        ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
+
+        // DRC_PRES_MODE_WRAP_ENCODER_TARGET
+        int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
+        ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
+        mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
+
+        // AAC_UNIDRC_SET_EFFECT
+        int32_t effectType = mIntf->getDrcEffectType();
+        ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
+        aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+
+        // AAC_UNIDRC_ALBUM_MODE
+        int32_t albumMode = mIntf->getDrcAlbumMode();
+        ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+        aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
+        // AAC_PCM_MAX_OUTPUT_CHANNELS
+        int32_t maxChannelCount = mIntf->getMaxChannelCount();
+        ALOGV("AAC decoder using maximum output channel count %d", maxChannelCount);
+        aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, maxChannelCount);
+
         mDrcWrap.update();
 
         UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
@@ -708,7 +791,6 @@
 
                 // After an error, replace bufferSize with the sum of the
                 // decodedSizes to resynchronize the in/out lists.
-                inInfo.decodedSizes.pop_back();
                 inInfo.bufferSize = std::accumulate(
                         inInfo.decodedSizes.begin(), inInfo.decodedSizes.end(), 0);
 
@@ -762,6 +844,68 @@
                 }
             }
             ALOGV("size = %zu", size);
+
+            if (mStreamInfo->outputLoudness != prevOutLoudness) {
+                C2StreamDrcOutputLoudnessTuning::output
+                        drcOutLoudness(0u, (float) (mStreamInfo->outputLoudness*-0.25));
+
+                std::vector<std::unique_ptr<C2SettingResult>> failures;
+                c2_status_t err = mIntf->config(
+                                    { &drcOutLoudness },
+                                    C2_MAY_BLOCK,
+                                    &failures);
+                if (err == OK) {
+                    work->worklets.front()->output.configUpdate.push_back(
+                        C2Param::Copy(drcOutLoudness));
+                } else {
+                    ALOGE("Getting output loudness failed");
+                }
+            }
+
+            // update config with values used for decoding:
+            //    Album mode, target reference level, DRC effect type, DRC attenuation and boost
+            //    factor, DRC compression mode, encoder target level and max channel count
+            // with input values as they were not modified by decoder
+
+            C2StreamDrcAttenuationFactorTuning::input currentAttenuationFactor(0u,
+                    (C2FloatValue) (attenuationFactor/127.));
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentAttenuationFactor));
+
+            C2StreamDrcBoostFactorTuning::input currentBoostFactor(0u,
+                    (C2FloatValue) (boostFactor/127.));
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentBoostFactor));
+
+            C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
+                    (C2Config::drc_compression_mode_t) compressMode);
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentCompressMode));
+
+            C2StreamDrcEncodedTargetLevelTuning::input currentEncodedTargetLevel(0u,
+                    (C2FloatValue) (encTargetLevel*-0.25));
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentEncodedTargetLevel));
+
+            C2StreamDrcAlbumModeTuning::input currentAlbumMode(0u,
+                    (C2Config::drc_album_mode_t) albumMode);
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentAlbumMode));
+
+            C2StreamDrcTargetReferenceLevelTuning::input currentTargetRefLevel(0u,
+                    (float) (targetRefLevel*-0.25));
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentTargetRefLevel));
+
+            C2StreamDrcEffectTypeTuning::input currentEffectype(0u,
+                    (C2Config::drc_effect_type_t) effectType);
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentEffectype));
+
+            C2StreamMaxChannelCountInfo::input currentMaxChannelCnt(0u, maxChannelCount);
+            work->worklets.front()->output.configUpdate.push_back(
+                    C2Param::Copy(currentMaxChannelCnt));
+
         } while (decoderErr == AAC_DEC_OK);
     }
 
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index be52a1d..2e85915 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -155,9 +155,7 @@
       mNumBytesPerInputFrame(0u),
       mOutBufferSize(0u),
       mSentCodecSpecificData(false),
-      mInputTimeSet(false),
       mInputSize(0),
-      mNextFrameTimestampUs(0),
       mSignalledError(false),
       mOutIndex(0u),
       mRemainderLen(0u) {
@@ -182,9 +180,9 @@
 
 c2_status_t C2SoftAacEnc::onStop() {
     mSentCodecSpecificData = false;
-    mInputTimeSet = false;
     mInputSize = 0u;
-    mNextFrameTimestampUs = 0;
+    mNextFrameTimestampUs.reset();
+    mLastFrameEndTimestampUs.reset();
     mSignalledError = false;
     mRemainderLen = 0;
     return C2_OK;
@@ -201,9 +199,9 @@
 
 c2_status_t C2SoftAacEnc::onFlush_sm() {
     mSentCodecSpecificData = false;
-    mInputTimeSet = false;
     mInputSize = 0u;
-    mNextFrameTimestampUs = 0;
+    mNextFrameTimestampUs.reset();
+    mLastFrameEndTimestampUs.reset();
     return C2_OK;
 }
 
@@ -295,6 +293,30 @@
     return OK;
 }
 
+static void MaybeLogTimestampWarning(
+        long long lastFrameEndTimestampUs, long long inputTimestampUs) {
+    using Clock = std::chrono::steady_clock;
+    thread_local Clock::time_point sLastLogTimestamp{};
+    thread_local int32_t sOverlapCount = -1;
+    if (Clock::now() - sLastLogTimestamp > std::chrono::minutes(1) || sOverlapCount < 0) {
+        AString countMessage = "";
+        if (sOverlapCount > 0) {
+            countMessage = AStringPrintf(
+                    "(%d overlapping timestamp detected since last log)", sOverlapCount);
+        }
+        ALOGI("Correcting overlapping timestamp: last frame ended at %lldus but "
+                "current frame is starting at %lldus. Using the last frame's end timestamp %s",
+                lastFrameEndTimestampUs, inputTimestampUs, countMessage.c_str());
+        sLastLogTimestamp = Clock::now();
+        sOverlapCount = 0;
+    } else {
+        ALOGV("Correcting overlapping timestamp: last frame ended at %lldus but "
+                "current frame is starting at %lldus. Using the last frame's end timestamp",
+                lastFrameEndTimestampUs, inputTimestampUs);
+        ++sOverlapCount;
+    }
+}
+
 void C2SoftAacEnc::process(
         const std::unique_ptr<C2Work> &work,
         const std::shared_ptr<C2BlockPool> &pool) {
@@ -366,9 +388,17 @@
         data = view.data();
         capacity = view.capacity();
     }
-    if (!mInputTimeSet && capacity > 0) {
-        mNextFrameTimestampUs = work->input.ordinal.timestamp;
-        mInputTimeSet = true;
+    c2_cntr64_t inputTimestampUs = work->input.ordinal.timestamp;
+    if (inputTimestampUs < mLastFrameEndTimestampUs.value_or(inputTimestampUs)) {
+        MaybeLogTimestampWarning(mLastFrameEndTimestampUs->peekll(), inputTimestampUs.peekll());
+        inputTimestampUs = *mLastFrameEndTimestampUs;
+    }
+    if (capacity > 0) {
+        if (!mNextFrameTimestampUs) {
+            mNextFrameTimestampUs = work->input.ordinal.timestamp;
+        }
+        mLastFrameEndTimestampUs = inputTimestampUs
+                + (capacity / sizeof(int16_t) * 1000000ll / channelCount / sampleRate);
     }
 
     size_t numFrames =
@@ -376,8 +406,7 @@
         / mNumBytesPerInputFrame;
     ALOGV("capacity = %zu; mInputSize = %zu; numFrames = %zu "
           "mNumBytesPerInputFrame = %u inputTS = %lld remaining = %zu",
-          capacity, mInputSize, numFrames,
-          mNumBytesPerInputFrame, work->input.ordinal.timestamp.peekll(),
+          capacity, mInputSize, numFrames, mNumBytesPerInputFrame, inputTimestampUs.peekll(),
           mRemainderLen);
 
     std::shared_ptr<C2LinearBlock> block;
@@ -505,8 +534,10 @@
                 mInputSize = 0;
                 int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
                         + outargs.numInSamples;
-                c2_cntr64_t currentFrameTimestampUs = mNextFrameTimestampUs;
-                mNextFrameTimestampUs = work->input.ordinal.timestamp
+                ALOGV("consumed = %d, capacity = %zu, inSamples = %d, outSamples = %d",
+                      consumed, capacity, inargs.numInSamples, outargs.numInSamples);
+                c2_cntr64_t currentFrameTimestampUs = *mNextFrameTimestampUs;
+                mNextFrameTimestampUs = inputTimestampUs
                         + (consumed * 1000000ll / channelCount / sampleRate);
                 std::shared_ptr<C2Buffer> buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
 #if 0
@@ -533,7 +564,7 @@
         }
         ALOGV("encoderErr = %d mInputSize = %zu "
               "inargs.numInSamples = %d, mNextFrameTimestampUs = %lld",
-              encoderErr, mInputSize, inargs.numInSamples, mNextFrameTimestampUs.peekll());
+              encoderErr, mInputSize, inargs.numInSamples, mNextFrameTimestampUs->peekll());
     }
     if (eos && inBufferSize[0] > 0) {
         if (numFrames && !block) {
@@ -617,9 +648,9 @@
 
     (void)pool;
     mSentCodecSpecificData = false;
-    mInputTimeSet = false;
     mInputSize = 0u;
-    mNextFrameTimestampUs = 0;
+    mNextFrameTimestampUs.reset();
+    mLastFrameEndTimestampUs.reset();
 
     // TODO: we don't have any pending work at this time to drain.
     return C2_OK;
diff --git a/media/codec2/components/aac/C2SoftAacEnc.h b/media/codec2/components/aac/C2SoftAacEnc.h
index 6ecfbdd..9a28280 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.h
+++ b/media/codec2/components/aac/C2SoftAacEnc.h
@@ -18,6 +18,7 @@
 #define ANDROID_C2_SOFT_AAC_ENC_H_
 
 #include <atomic>
+#include <optional>
 
 #include <SimpleC2Component.h>
 
@@ -54,9 +55,9 @@
     UINT mOutBufferSize;
 
     bool mSentCodecSpecificData;
-    bool mInputTimeSet;
     size_t mInputSize;
-    c2_cntr64_t mNextFrameTimestampUs;
+    std::optional<c2_cntr64_t> mNextFrameTimestampUs;
+    std::optional<c2_cntr64_t> mLastFrameEndTimestampUs;
 
     bool mSignalledError;
     std::atomic_uint64_t mOutIndex;
diff --git a/media/codec2/components/aac/DrcPresModeWrap.cpp b/media/codec2/components/aac/DrcPresModeWrap.cpp
index 5b9aebc..bee969b 100644
--- a/media/codec2/components/aac/DrcPresModeWrap.cpp
+++ b/media/codec2/components/aac/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
     mEncoderTarget = -1;
 
     /* Values from last time. */
-    /* Initialized to the same values as the desired values */
-    mLastTarget = -1;
-    mLastAttFactor = 0;
-    mLastBoostFactor = 0;
+    mLastTarget = -2;
+    mLastAttFactor = -1;
+    mLastBoostFactor = -1;
     mLastHeavy = 0;
 }
 
@@ -163,7 +162,7 @@
 
     if (mDataUpdate) {
         // sanity check
-        if (mDesTarget < MAX_TARGET_LEVEL){
+        if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
             mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
             newTarget = MAX_TARGET_LEVEL;
         }
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
index 6578ad2..f7943be 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.cpp
@@ -336,11 +336,10 @@
                 memset(output, 0, outSamples * sizeof(int16_t));
             } else {
                 int16_t FT;
-                RX_State_wb rx_state;
                 int16_t numRecSamples;
 
                 mime_unsorting(const_cast<uint8_t *>(&input[1]),
-                               mInputSampleBuffer, &FT, &FM, 1, &rx_state);
+                               mInputSampleBuffer, &FT, &FM, 1, &mRxState);
                 pvDecoder_AmrWb(FM, mInputSampleBuffer, output, &numRecSamples,
                                 mDecoderBuf, FT, mDecoderCookie);
                 if (numRecSamples != outSamples) {
diff --git a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
index 6384450..afe1537 100644
--- a/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
+++ b/media/codec2/components/amr_nb_wb/C2SoftAmrDec.h
@@ -18,6 +18,8 @@
 #define ANDROID_C2_SOFT_AMR_DEC_H_
 
 #include <SimpleC2Component.h>
+#include "gsmamr_dec.h"
+#include "pvamrwbdecoder.h"
 
 
 namespace android {
@@ -51,6 +53,7 @@
     void *mAmrHandle;
     void *mDecoderBuf;
     int16_t *mDecoderCookie;
+    RX_State_wb mRxState{};
 
     int16_t mInputSampleBuffer[477];
 
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 36137e6..c7046cb 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -29,6 +29,8 @@
 
 namespace android {
 
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
+
 // codecname set and passed in as a compile flag from Android.bp
 constexpr char COMPONENT_NAME[] = CODECNAME;
 
@@ -112,7 +114,7 @@
         addParameter(
             DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
                 .withDefault(
-                    new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                    new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -192,8 +194,8 @@
         const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 63) / 64) *
-                          ((maxSize.v.height + 63) / 64) * 3072);
+        me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+                * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
         return C2R::Ok();
     }
     static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index fa98178..d7b9e12 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -31,10 +31,11 @@
 namespace android {
 
 namespace {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder";
 constexpr uint32_t kDefaultOutputDelay = 8;
 constexpr uint32_t kMaxOutputDelay = 16;
+constexpr uint32_t kMinInputBytes = 4;
 }  // namespace
 
 class C2SoftAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -114,7 +115,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -227,7 +228,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 192);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 192), kMinInputBufferSize);
         return C2R::Ok();
     }
 
@@ -500,7 +502,7 @@
 status_t C2SoftAvcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN64(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -518,10 +520,20 @@
                                  size_t inSize,
                                  uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -537,7 +549,7 @@
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
     if (outBuffer) {
-        if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
+        if (outBuffer->height() < displayHeight) {
             ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
                   outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
             return false;
@@ -755,24 +767,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN64(mWidth)) {
-        mStride = ALIGN64(mWidth);
-        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -816,7 +825,7 @@
           inSize, (int)work->input.ordinal.timestamp.peeku(),
           (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
     size_t inPos = 0;
-    while (inPos < inSize) {
+    while (inPos < inSize && inSize - inPos >= kMinInputBytes) {
         if (C2_OK != ensureDecoderState(pool)) {
             mSignalledError = true;
             work->workletsProcessed = 1u;
@@ -903,12 +912,12 @@
                 work->result = C2_CORRUPTED;
                 return;
             }
-            continue;
         }
         if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN64(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+                mStride = ALIGN32(s_decode_op.u4_pic_wd);
+                setParams(mStride, IVD_DECODE_FRAME);
             }
             if (s_decode_op.u4_pic_wd != mWidth || s_decode_op.u4_pic_ht != mHeight) {
                 mWidth = s_decode_op.u4_pic_wd;
@@ -936,16 +945,7 @@
         if (s_decode_op.u4_output_present) {
             finishWork(s_decode_op.u4_ts, work);
         }
-        if (0 == s_decode_op.u4_num_bytes_consumed) {
-            ALOGD("Bytes consumed is zero. Ignoring remaining bytes");
-            break;
-        }
         inPos += s_decode_op.u4_num_bytes_consumed;
-        if (hasPicture && (inSize - inPos)) {
-            ALOGD("decoded frame in current access nal, ignoring further trailing bytes %d",
-                  (int)inSize - (int)inPos);
-            break;
-        }
     }
     if (eos) {
         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 4414a26..bd84de0 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -39,7 +39,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ih264d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ih264d_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ih264d_ctl_get_vui_params_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index b41c271..ab93ce3 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -40,7 +40,7 @@
 namespace {
 
 constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
-
+constexpr uint32_t kMinOutBufferSize = 524288;
 void ParseGop(
         const C2StreamGopTuning::output &gop,
         uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
@@ -103,7 +103,7 @@
 
         addParameter(
                 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
-                .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
+                .withDefault(new C2StreamPictureSizeInfo::input(0u, 16, 16))
                 .withFields({
                     C2F(mSize, width).inRange(2, 2560, 2),
                     C2F(mSize, height).inRange(2, 2560, 2),
@@ -129,7 +129,7 @@
 
         addParameter(
                 DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
-                .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
+                .withDefault(new C2StreamFrameRateInfo::output(0u, 1.))
                 // TODO: More restriction?
                 .withFields({C2F(mFrameRate, value).greaterThan(0.)})
                 .withSetter(Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
@@ -440,8 +440,7 @@
       mSignalledError(false),
       mCodecCtx(nullptr),
       mOutBlock(nullptr),
-      // TODO: output buffer size
-      mOutBufferSize(524288) {
+      mOutBufferSize(kMinOutBufferSize) {
 
     // If dump is enabled, then open create an empty file
     GENERATE_FILE_NAMES();
@@ -951,6 +950,9 @@
 
     mStride = width;
 
+    // Assume worst case output buffer size to be equal to number of bytes in input
+    mOutBufferSize = std::max(width * height * 3 / 2, kMinOutBufferSize);
+
     // TODO
     mIvVideoColorFormat = IV_YUV_420P;
 
diff --git a/media/codec2/components/base/SimpleC2Interface.cpp b/media/codec2/components/base/SimpleC2Interface.cpp
index c849a4e..29740d1 100644
--- a/media/codec2/components/base/SimpleC2Interface.cpp
+++ b/media/codec2/components/base/SimpleC2Interface.cpp
@@ -21,6 +21,7 @@
 // use MediaDefs here vs. MediaCodecConstants as this is not MediaCodec specific/dependent
 #include <media/stagefright/foundation/MediaDefs.h>
 
+#include <C2PlatformSupport.h>
 #include <SimpleC2Interface.h>
 
 namespace android {
@@ -38,6 +39,16 @@
     setDerivedInstance(this);
 
     addParameter(
+            DefineParam(mApiFeatures, C2_PARAMKEY_API_FEATURES)
+            .withConstValue(new C2ApiFeaturesSetting(C2Config::api_feature_t(
+                    API_REFLECTION |
+                    API_VALUES |
+                    API_CURRENT_VALUES |
+                    API_DEPENDENCY |
+                    API_SAME_INPUT_BUFFER)))
+            .build());
+
+    addParameter(
             DefineParam(mName, C2_PARAMKEY_COMPONENT_NAME)
             .withConstValue(AllocSharedString<C2ComponentNameSetting>(name.c_str()))
             .build());
@@ -85,22 +96,24 @@
     C2Allocator::id_t rawAllocator = C2AllocatorStore::DEFAULT_LINEAR;
     C2BlockPool::local_id_t rawPoolId = C2BlockPool::BASIC_LINEAR;
     C2BufferData::type_t codedBufferType = C2BufferData::LINEAR;
-    C2Allocator::id_t codedAllocator = C2AllocatorStore::DEFAULT_LINEAR;
+    int poolMask = GetCodec2PoolMask();
+    C2Allocator::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
+    C2Allocator::id_t codedAllocator = preferredLinearId;
     C2BlockPool::local_id_t codedPoolId = C2BlockPool::BASIC_LINEAR;
 
     switch (domain) {
-        case C2Component::DOMAIN_IMAGE:
+        case C2Component::DOMAIN_IMAGE: [[fallthrough]];
         case C2Component::DOMAIN_VIDEO:
             // TODO: should we define raw image? The only difference is timestamp handling
             rawBufferType = C2BufferData::GRAPHIC;
             rawMediaType = MEDIA_MIMETYPE_VIDEO_RAW;
-            rawAllocator = C2AllocatorStore::DEFAULT_GRAPHIC;
+            rawAllocator = C2PlatformAllocatorStore::GRALLOC;
             rawPoolId = C2BlockPool::BASIC_GRAPHIC;
             break;
         case C2Component::DOMAIN_AUDIO:
             rawBufferType = C2BufferData::LINEAR;
             rawMediaType = MEDIA_MIMETYPE_AUDIO_RAW;
-            rawAllocator = C2AllocatorStore::DEFAULT_LINEAR;
+            rawAllocator = preferredLinearId;
             rawPoolId = C2BlockPool::BASIC_LINEAR;
             break;
         default:
@@ -302,7 +315,6 @@
     Clients need to handle the following base params due to custom dependency.
 
     std::shared_ptr<C2ApiLevelSetting> mApiLevel;
-    std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures;
     std::shared_ptr<C2ComponentAttributesSetting> mAttrib;
 
     std::shared_ptr<C2PortSuggestedBufferCountTuning::input> mSuggestedInputBufferCount;
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index 35f689e..a081e28 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -9,10 +9,15 @@
     include_dirs: [
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libbase",
         "libbinder",
         "libcutils",
+        "libdatasource",
         "libgui",
         "liblog",
         "libstagefright",
diff --git a/media/codec2/components/cmds/codec2.cpp b/media/codec2/components/cmds/codec2.cpp
index f2cf545..d6025de 100644
--- a/media/codec2/components/cmds/codec2.cpp
+++ b/media/codec2/components/cmds/codec2.cpp
@@ -30,15 +30,15 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaHTTPService.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaExtractorFactory.h>
@@ -418,7 +418,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(nullptr /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(nullptr /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index e5eb51d..48cc51b 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -23,8 +23,11 @@
 
     srcs: ["C2SoftFlacEnc.cpp"],
 
-    static_libs: [
+    shared_libs: [
         "libaudioutils",
+    ],
+
+    static_libs: [
         "libFLAC",
     ],
 }
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index df677c2..23104dc 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -497,7 +497,7 @@
 status_t C2SoftHevcDec::initDecoder() {
     if (OK != createDecoder()) return UNKNOWN_ERROR;
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN64(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -515,10 +515,20 @@
                                   size_t inSize,
                                   uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -534,7 +544,7 @@
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
     if (outBuffer) {
-        if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
+        if (outBuffer->height() < displayHeight) {
             ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
                   outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
             return false;
@@ -752,24 +762,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN64(mWidth)) {
-        mStride = ALIGN64(mWidth);
-        if (OK != setParams(mStride, IVD_DECODE_FRAME)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
@@ -904,7 +911,7 @@
         if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN64(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
+                setParams(ALIGN32(s_decode_op.u4_pic_wd), IVD_DECODE_FRAME);
             }
             if (s_decode_op.u4_pic_wd != mWidth ||  s_decode_op.u4_pic_ht != mHeight) {
                 mWidth = s_decode_op.u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index ce63a6c..600d7c1 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -37,7 +37,7 @@
 #define ivdext_ctl_set_num_cores_op_t   ihevcd_cxa_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_vui_params_ip_t  ihevcd_cxa_ctl_get_vui_params_ip_t
 #define ivdext_ctl_get_vui_params_op_t  ihevcd_cxa_ctl_get_vui_params_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index b129b1b..c2d2540 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -42,6 +42,36 @@
 
 constexpr char COMPONENT_NAME[] = "c2.android.hevc.encoder";
 
+void ParseGop(
+        const C2StreamGopTuning::output &gop,
+        uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
+    uint32_t syncInt = 1;
+    uint32_t iInt = 1;
+    for (size_t i = 0; i < gop.flexCount(); ++i) {
+        const C2GopLayerStruct &layer = gop.m.values[i];
+        if (layer.count == UINT32_MAX) {
+            syncInt = 0;
+        } else if (syncInt <= UINT32_MAX / (layer.count + 1)) {
+            syncInt *= (layer.count + 1);
+        }
+        if ((layer.type_ & I_FRAME) == 0) {
+            if (layer.count == UINT32_MAX) {
+                iInt = 0;
+            } else if (iInt <= UINT32_MAX / (layer.count + 1)) {
+                iInt *= (layer.count + 1);
+            }
+        }
+        if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME) && maxBframes) {
+            *maxBframes = layer.count;
+        }
+    }
+    if (syncInterval) {
+        *syncInterval = syncInt;
+    }
+    if (iInterval) {
+        *iInterval = iInt;
+    }
+}
 } // namepsace
 
 class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -60,13 +90,21 @@
         setDerivedInstance(this);
 
         addParameter(
+                DefineParam(mGop, C2_PARAMKEY_GOP)
+                .withDefault(C2StreamGopTuning::output::AllocShared(
+                        0 /* flexCount */, 0u /* stream */))
+                .withFields({C2F(mGop, m.values[0].type_).any(),
+                             C2F(mGop, m.values[0].count).any()})
+                .withSetter(GopSetter)
+                .build());
+
+        addParameter(
                 DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
                 .withDefault(new C2PortActualDelayTuning::input(
                     DEFAULT_B_FRAMES + DEFAULT_RC_LOOKAHEAD))
                 .withFields({C2F(mActualInputDelay, value).inRange(
                     0, MAX_B_FRAMES + MAX_RC_LOOKAHEAD)})
-                .withSetter(
-                    Setter<decltype(*mActualInputDelay)>::StrictValueWithNoDeps)
+                .calculatedAs(InputDelaySetter, mGop)
                 .build());
 
         addParameter(
@@ -172,6 +210,17 @@
                 .build());
     }
 
+    static C2R InputDelaySetter(
+            bool mayBlock,
+            C2P<C2PortActualDelayTuning::input> &me,
+            const C2P<C2StreamGopTuning::output> &gop) {
+        (void)mayBlock;
+        uint32_t maxBframes = 0;
+        ParseGop(gop.v, nullptr, nullptr, &maxBframes);
+        me.set().value = maxBframes + DEFAULT_RC_LOOKAHEAD;
+        return C2R::Ok();
+    }
+
     static C2R BitrateSetter(bool mayBlock,
                              C2P<C2StreamBitrateInfo::output>& me) {
         (void)mayBlock;
@@ -270,6 +319,18 @@
         return C2R::Ok();
     }
 
+    static C2R GopSetter(bool mayBlock, C2P<C2StreamGopTuning::output> &me) {
+        (void)mayBlock;
+        for (size_t i = 0; i < me.v.flexCount(); ++i) {
+            const C2GopLayerStruct &layer = me.v.m.values[0];
+            if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME)
+                    && layer.count > MAX_B_FRAMES) {
+                me.set().m.values[i].count = MAX_B_FRAMES;
+            }
+        }
+        return C2R::Ok();
+    }
+
     UWORD32 getProfile_l() const {
         switch (mProfileLevel->profile) {
         case PROFILE_HEVC_MAIN:  [[fallthrough]];
@@ -338,6 +399,9 @@
     std::shared_ptr<C2StreamQualityTuning::output> getQuality_l() const {
         return mQuality;
     }
+    std::shared_ptr<C2StreamGopTuning::output> getGop_l() const {
+        return mGop;
+    }
 
    private:
     std::shared_ptr<C2StreamUsageTuning::input> mUsage;
@@ -350,6 +414,7 @@
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
     std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
     std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
+    std::shared_ptr<C2StreamGopTuning::output> mGop;
 };
 
 static size_t GetCPUCoreCount() {
@@ -449,7 +514,25 @@
         ALOGE("HEVC default init failed : 0x%x", err);
         return C2_CORRUPTED;
     }
-
+    mBframes = 0;
+    if (mGop && mGop->flexCount() > 0) {
+        uint32_t syncInterval = 1;
+        uint32_t iInterval = 1;
+        uint32_t maxBframes = 0;
+        ParseGop(*mGop, &syncInterval, &iInterval, &maxBframes);
+        if (syncInterval > 0) {
+            ALOGD("Updating IDR interval from GOP: old %u new %u", mIDRInterval, syncInterval);
+            mIDRInterval = syncInterval;
+        }
+        if (iInterval > 0) {
+            ALOGD("Updating I interval from GOP: old %u new %u", mIInterval, iInterval);
+            mIInterval = iInterval;
+        }
+        if (mBframes != maxBframes) {
+            ALOGD("Updating max B frames from GOP: old %u new %u", mBframes, maxBframes);
+            mBframes = maxBframes;
+        }
+    }
     // update configuration
     mEncParams.s_src_prms.i4_width = mSize->width;
     mEncParams.s_src_prms.i4_height = mSize->height;
@@ -463,12 +546,20 @@
         mBitrate->value << 1;
     mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_codec_level = mHevcEncLevel;
     mEncParams.s_coding_tools_prms.i4_max_i_open_gop_period = mIDRInterval;
-    mEncParams.s_coding_tools_prms.i4_max_cra_open_gop_period = mIDRInterval;
+    mEncParams.s_coding_tools_prms.i4_max_cra_open_gop_period = mIInterval;
     mIvVideoColorFormat = IV_YUV_420P;
     mEncParams.s_multi_thrd_prms.i4_max_num_cores = mNumCores;
     mEncParams.s_out_strm_prms.i4_codec_profile = mHevcEncProfile;
     mEncParams.s_lap_prms.i4_rc_look_ahead_pics = DEFAULT_RC_LOOKAHEAD;
-    mEncParams.s_coding_tools_prms.i4_max_temporal_layers = DEFAULT_B_FRAMES;
+    if (mBframes == 0) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 0;
+    } else if (mBframes <= 2) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 1;
+    } else if (mBframes <= 6) {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 2;
+    } else {
+        mEncParams.s_coding_tools_prms.i4_max_temporal_layers = 3;
+    }
 
     switch (mBitrateMode->value) {
         case C2Config::BITRATE_IGNORE:
@@ -523,6 +614,7 @@
 
 c2_status_t C2SoftHevcEnc::initEncoder() {
     CHECK(!mCodecCtx);
+
     {
         IntfImpl::Lock lock = mIntf->lock();
         mSize = mIntf->getSize_l();
@@ -532,8 +624,11 @@
         mHevcEncProfile = mIntf->getProfile_l();
         mHevcEncLevel = mIntf->getLevel_l();
         mIDRInterval = mIntf->getSyncFramePeriod_l();
+        mIInterval = mIntf->getSyncFramePeriod_l();
         mComplexity = mIntf->getComplexity_l();
         mQuality = mIntf->getQuality_l();
+        mGop = mIntf->getGop_l();
+        mRequestSync = mIntf->getRequestSync_l();
     }
 
     c2_status_t status = initEncParams();
@@ -862,7 +957,7 @@
         }
     }
 
-    // handle dynamic config parameters
+    // handle dynamic bitrate change
     {
         IntfImpl::Lock lock = mIntf->lock();
         std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
@@ -889,6 +984,26 @@
         work->workletsProcessed = 1u;
         return;
     }
+    // handle request key frame
+    {
+        IntfImpl::Lock lock = mIntf->lock();
+        std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync;
+        requestSync = mIntf->getRequestSync_l();
+        lock.unlock();
+        if (requestSync != mRequestSync) {
+            // we can handle IDR immediately
+            if (requestSync->value) {
+                // unset request
+                C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE);
+                std::vector<std::unique_ptr<C2SettingResult>> failures;
+                mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures);
+                ALOGV("Got sync request");
+                //Force this as an IDR frame
+                s_encode_ip.i4_force_idr_flag = 1;
+            }
+            mRequestSync = requestSync;
+        }
+    }
 
     uint64_t timeDelay = 0;
     uint64_t timeTaken = 0;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index f2c7642..5ea4602 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -67,6 +67,8 @@
     ihevce_static_cfg_params_t mEncParams;
     size_t mNumCores;
     UWORD32 mIDRInterval;
+    UWORD32 mIInterval;
+    UWORD32 mBframes;
     IV_COLOR_FORMAT_T mIvVideoColorFormat;
     UWORD32 mHevcEncProfile;
     UWORD32 mHevcEncLevel;
@@ -85,7 +87,8 @@
     std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
     std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
-
+    std::shared_ptr<C2StreamGopTuning::output> mGop;
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
 #ifdef FILE_DUMP_ENABLE
     char mInFile[200];
     char mOutFile[200];
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index df7b403..55dd475 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -29,7 +29,7 @@
 #include "impeg2d.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 constexpr char COMPONENT_NAME[] = "c2.android.mpeg2.decoder";
 
 class C2SoftMpeg2Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -47,6 +47,12 @@
         noInputLatency();
         noTimeStretch();
 
+        // TODO: Proper support for reorder depth.
+        addParameter(
+                DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
+                .withConstValue(new C2PortActualDelayTuning::output(3u))
+                .build());
+
         // TODO: output latency and reordering
 
         addParameter(
@@ -93,7 +99,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 2))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -207,7 +213,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 1
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 384), kMinInputBufferSize);
         return C2R::Ok();
     }
 
@@ -564,7 +571,7 @@
     if (OK != createDecoder()) return UNKNOWN_ERROR;
 
     mNumCores = MIN(getCpuCoreCount(), MAX_NUM_CORES);
-    mStride = ALIGN64(mWidth);
+    mStride = ALIGN32(mWidth);
     mSignalledError = false;
     resetPlugin();
     (void) setNumCores();
@@ -582,10 +589,20 @@
                                    size_t inSize,
                                    uint32_t tsMarker) {
     uint32_t displayStride = mStride;
+    if (outBuffer) {
+        C2PlanarLayout layout;
+        layout = outBuffer->layout();
+        displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    }
     uint32_t displayHeight = mHeight;
     size_t lumaSize = displayStride * displayHeight;
     size_t chromaSize = lumaSize >> 2;
 
+    if (mStride != displayStride) {
+        mStride = displayStride;
+        if (OK != setParams(mStride)) return false;
+    }
+
     ps_decode_ip->u4_size = sizeof(ivd_video_decode_ip_t);
     ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
     if (inBuffer) {
@@ -601,7 +618,7 @@
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
     ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
     if (outBuffer) {
-        if (outBuffer->width() < displayStride || outBuffer->height() < displayHeight) {
+        if (outBuffer->height() < displayHeight) {
             ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
                   outBuffer->width(), outBuffer->height(), displayStride, displayHeight);
             return false;
@@ -826,24 +843,21 @@
         ALOGE("not supposed to be here, invalid decoder context");
         return C2_CORRUPTED;
     }
-    if (mStride != ALIGN64(mWidth)) {
-        mStride = ALIGN64(mWidth);
-        if (OK != setParams(mStride)) return C2_CORRUPTED;
-    }
     if (mOutBlock &&
-            (mOutBlock->width() != mStride || mOutBlock->height() != mHeight)) {
+            (mOutBlock->width() != ALIGN32(mWidth) || mOutBlock->height() != mHeight)) {
         mOutBlock.reset();
     }
     if (!mOutBlock) {
         uint32_t format = HAL_PIXEL_FORMAT_YV12;
         C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
-        c2_status_t err = pool->fetchGraphicBlock(mStride, mHeight, format, usage, &mOutBlock);
+        c2_status_t err =
+            pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
         if (err != C2_OK) {
             ALOGE("fetchGraphicBlock for Output failed with status %d", err);
             return err;
         }
         ALOGV("provided (%dx%d) required (%dx%d)",
-              mOutBlock->width(), mOutBlock->height(), mStride, mHeight);
+              mOutBlock->width(), mOutBlock->height(), ALIGN32(mWidth), mHeight);
     }
 
     return C2_OK;
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index 65d3b87..fd66304a 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -37,7 +37,7 @@
 #define ivdext_ctl_set_num_cores_op_t   impeg2d_ctl_set_num_cores_op_t
 #define ivdext_ctl_get_seq_info_ip_t    impeg2d_ctl_get_seq_info_ip_t
 #define ivdext_ctl_get_seq_info_op_t    impeg2d_ctl_get_seq_info_op_t
-#define ALIGN64(x)                      ((((x) + 63) >> 6) << 6)
+#define ALIGN32(x)                      ((((x) + 31) >> 5) << 5)
 #define MAX_NUM_CORES                   4
 #define IVDEXT_CMD_CTL_SET_NUM_CORES    \
         (IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 7e6685e..61b286c 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -33,7 +33,7 @@
 #include "mp4dec_api.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 #ifdef MPEG4
 constexpr char COMPONENT_NAME[] = "c2.android.mpeg4.decoder";
 #else
@@ -149,11 +149,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-#ifdef MPEG4
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 1920 * 1088 * 3 / 2))
-#else
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 352 * 288 * 3 / 2))
-#endif
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -218,7 +214,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 1
-        me.set().value = (((maxSize.v.width + 15) / 16) * ((maxSize.v.height + 15) / 16) * 384);
+        me.set().value = c2_max((((maxSize.v.width + 15) / 16)
+                * ((maxSize.v.height + 15) / 16) * 384), kMinInputBufferSize);
         return C2R::Ok();
     }
 
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index 6b6974f..b7c1556 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -62,7 +62,7 @@
         addParameter(
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
-                .withFields({C2F(mSampleRate, value).equalTo(48000)})
+                .withFields({C2F(mSampleRate, value).inRange(8000, 48000)})
                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
                 .build());
 
diff --git a/media/codec2/components/vorbis/Android.bp b/media/codec2/components/vorbis/Android.bp
index a5f485d..bc1c380 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -7,5 +7,5 @@
 
     srcs: ["C2SoftVorbisDec.cpp"],
 
-    shared_libs: ["libvorbisidec"],
+    static_libs: ["libvorbisidec"],
 }
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index 18e6db2..15564d9 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -66,7 +66,7 @@
         addParameter(
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
-                .withFields({C2F(mSampleRate, value).inRange(8000, 96000)})
+                .withFields({C2F(mSampleRate, value).inRange(8000, 192000)})
                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
                 .build());
 
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index a759e8f..3eef1e3 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -30,7 +30,7 @@
 #include "C2SoftVpxDec.h"
 
 namespace android {
-
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
 #ifdef VP9
 constexpr char COMPONENT_NAME[] = "c2.android.vp9.decoder";
 #else
@@ -166,7 +166,7 @@
 
         addParameter(
                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
-                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+                .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
                 .withFields({
                     C2F(mMaxInputSize, value).any(),
                 })
@@ -244,7 +244,8 @@
                                   const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
         (void)mayBlock;
         // assume compression ratio of 2
-        me.set().value = (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072);
+        me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+                * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
         return C2R::Ok();
     }
 
@@ -783,7 +784,13 @@
         }
 
     }
-    CHECK(img->fmt == VPX_IMG_FMT_I420 || img->fmt == VPX_IMG_FMT_I42016);
+    if(img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_I42016) {
+        ALOGE("img->fmt %d not supported", img->fmt);
+        mSignalledError = true;
+        work->workletsProcessed = 1u;
+        work->result = C2_CORRUPTED;
+        return false;
+    }
 
     std::shared_ptr<C2GraphicBlock> block;
     uint32_t format = HAL_PIXEL_FORMAT_YV12;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 6dab70b..7e9090f 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -67,8 +67,9 @@
       mLastTimestamp(0x7FFFFFFFFFFFFFFFull),
       mSignalledOutputEos(false),
       mSignalledError(false) {
-    memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
-    mTemporalLayerBitrateRatio[0] = 100;
+    for (int i = 0; i < MAXTEMPORALLAYERS; i++) {
+        mTemporalLayerBitrateRatio[i] = 1.0f;
+    }
 }
 
 C2SoftVpxEnc::~C2SoftVpxEnc() {
@@ -123,7 +124,8 @@
         mFrameRate = mIntf->getFrameRate_l();
         mIntraRefresh = mIntf->getIntraRefresh_l();
         mRequestSync = mIntf->getRequestSync_l();
-        mTemporalLayers = mIntf->getTemporalLayers_l()->m.layerCount;
+        mLayering = mIntf->getTemporalLayers_l();
+        mTemporalLayers = mLayering->m.layerCount;
     }
 
     switch (mBitrateMode->value) {
@@ -225,6 +227,7 @@
             mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef;
             mTemporalPattern[6] = kTemporalUpdateLastRefAltRef;
             mTemporalPattern[7] = kTemporalUpdateNone;
+            mTemporalLayerBitrateRatio[0] = mLayering->m.bitrateRatios[0];
             mTemporalPatternLength = 8;
             break;
         case 3:
@@ -245,6 +248,8 @@
             mTemporalPattern[5] = kTemporalUpdateNone;
             mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef;
             mTemporalPattern[7] = kTemporalUpdateNone;
+            mTemporalLayerBitrateRatio[0] = mLayering->m.bitrateRatios[0];
+            mTemporalLayerBitrateRatio[1] = mLayering->m.bitrateRatios[1];
             mTemporalPatternLength = 8;
             break;
         default:
@@ -255,7 +260,7 @@
     for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) {
         mCodecConfiguration->ts_target_bitrate[i] =
             mCodecConfiguration->rc_target_bitrate *
-            mTemporalLayerBitrateRatio[i] / 100;
+            mTemporalLayerBitrateRatio[i];
     }
     if (mIntf->getSyncFramePeriod() >= 0) {
         mCodecConfiguration->kf_max_dist = mIntf->getSyncFramePeriod();
@@ -455,8 +460,8 @@
 
     const C2ConstGraphicBlock inBuffer =
         inputBuffer->data().graphicBlocks().front();
-    if (inBuffer.width() != mSize->width ||
-        inBuffer.height() != mSize->height) {
+    if (inBuffer.width() < mSize->width ||
+        inBuffer.height() < mSize->height) {
         ALOGE("unexpected Input buffer attributes %d(%d) x %d(%d)",
               inBuffer.width(), mSize->width, inBuffer.height(),
               mSize->height);
@@ -467,8 +472,8 @@
     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
     vpx_image_t raw_frame;
     const C2PlanarLayout &layout = rView->layout();
-    uint32_t width = rView->width();
-    uint32_t height = rView->height();
+    uint32_t width = mSize->width;
+    uint32_t height = mSize->height;
     if (width > 0x8000 || height > 0x8000) {
         ALOGE("Image too big: %u x %u", width, height);
         work->result = C2_BAD_VALUE;
@@ -514,7 +519,7 @@
                         return;
                     }
                     vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, stride, vstride,
-                                 mStrideAlign, (uint8_t*)rView->data()[0]);
+                                 mStrideAlign, mConversionBuffer.data());
                     vpx_img_set_rect(&raw_frame, 0, 0, width, height);
                 } else {
                     ALOGE("Conversion buffer is too small: %u x %u for %zu",
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 62ccd1b..5e34b8a 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -180,7 +180,7 @@
      size_t mTemporalLayers;
 
      // Temporal layer bitrare ratio in percentage
-     uint32_t mTemporalLayerBitrateRatio[MAXTEMPORALLAYERS];
+     float_t mTemporalLayerBitrateRatio[MAXTEMPORALLAYERS];
 
      // Temporal pattern type
      TemporalPatternType mTemporalPatternType;
@@ -218,6 +218,7 @@
     std::shared_ptr<C2StreamBitrateInfo::output> mBitrate;
     std::shared_ptr<C2StreamBitrateModeTuning::output> mBitrateMode;
     std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
+    std::shared_ptr<C2StreamTemporalLayeringTuning::output> mLayering;
 
      C2_DO_NOT_COPY(C2SoftVpxEnc);
 };
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index a3ebadb..951d058 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -87,7 +87,8 @@
                 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
                 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
                 .withFields({C2F(mSampleRate, value).oneOf({
-                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+                    7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+                    44100, 48000, 64000, 88200, 96000
                 })})
                 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
                 .build());
@@ -1309,69 +1310,84 @@
                                 &ui_exec_done);
     RETURN_IF_FATAL(err_code,  "IA_CMD_TYPE_DONE_QUERY");
 
-    if (ui_exec_done != 1) {
-        VOID* p_array;        // ITTIAM:buffer to handle gain payload
-        WORD32 buf_size = 0;  // ITTIAM:gain payload length
-        WORD32 bit_str_fmt = 1;
-        WORD32 gain_stream_flag = 1;
-
-        err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
-                                    IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size);
-        RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN");
-
-        err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
-                                    IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array);
-        RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF");
-
-        if (buf_size > 0) {
-            /*Set bitstream_split_format */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
-                                      IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
-            RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
-
-            memcpy(mDrcInBuf, p_array, buf_size);
-            /* Set number of bytes to be processed */
-            err_code =
-                ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size);
-            RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
-
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
-                                      IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag);
-            RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
-
-            /* Execute process */
-            err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
-                                      IA_CMD_TYPE_INIT_CPY_BSF_BUFF, nullptr);
-            RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
-
-            mMpegDDRCPresent = 1;
-        }
-    }
-
-    /* How much buffer is used in input buffers */
+    int32_t num_preroll = 0;
     err_code = ixheaacd_dec_api(mXheaacCodecHandle,
-                                IA_API_CMD_GET_CURIDX_INPUT_BUF,
-                                0,
-                                bytesConsumed);
-    RETURN_IF_FATAL(err_code,  "IA_API_CMD_GET_CURIDX_INPUT_BUF");
+                                IA_API_CMD_GET_CONFIG_PARAM,
+                                IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES,
+                                &num_preroll);
+    RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES");
 
-    /* Get the output bytes */
-    err_code = ixheaacd_dec_api(mXheaacCodecHandle,
-                                IA_API_CMD_GET_OUTPUT_BYTES,
-                                0,
-                                outBytes);
-    RETURN_IF_FATAL(err_code,  "IA_API_CMD_GET_OUTPUT_BYTES");
+    {
+      int32_t preroll_frame_offset = 0;
 
-    if (mMpegDDRCPresent == 1) {
-        memcpy(mDrcInBuf, mOutputBuffer, *outBytes);
-        err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes);
-        RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
+        do {
+            if (ui_exec_done != 1) {
+                VOID* p_array;        // ITTIAM:buffer to handle gain payload
+                WORD32 buf_size = 0;  // ITTIAM:gain payload length
+                WORD32 bit_str_fmt = 1;
+                WORD32 gain_stream_flag = 1;
 
-        err_code =
-            ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, nullptr);
-        RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
+                err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
+                                            IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size);
+                RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN");
 
-        memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
+                err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
+                                            IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array);
+                RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF");
+
+                if (buf_size > 0) {
+                    /*Set bitstream_split_format */
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
+                                            IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+
+                    memcpy(mDrcInBuf, p_array, buf_size);
+                    /* Set number of bytes to be processed */
+                    err_code =
+                        ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
+                                            IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+
+                    /* Execute process */
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
+                                            IA_CMD_TYPE_INIT_CPY_BSF_BUFF, nullptr);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+
+                    mMpegDDRCPresent = 1;
+                }
+            }
+
+            /* How much buffer is used in input buffers */
+            err_code = ixheaacd_dec_api(mXheaacCodecHandle,
+                                        IA_API_CMD_GET_CURIDX_INPUT_BUF,
+                                        0,
+                                        bytesConsumed);
+            RETURN_IF_FATAL(err_code,  "IA_API_CMD_GET_CURIDX_INPUT_BUF");
+
+            /* Get the output bytes */
+            err_code = ixheaacd_dec_api(mXheaacCodecHandle,
+                                        IA_API_CMD_GET_OUTPUT_BYTES,
+                                        0,
+                                        outBytes);
+            RETURN_IF_FATAL(err_code,  "IA_API_CMD_GET_OUTPUT_BYTES");
+
+            if (mMpegDDRCPresent == 1) {
+                memcpy(mDrcInBuf, mOutputBuffer + preroll_frame_offset, *outBytes);
+                preroll_frame_offset += *outBytes;
+                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes);
+                RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
+
+                err_code =
+                    ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, nullptr);
+                RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
+
+                memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
+            }
+            num_preroll--;
+        } while (num_preroll > 0);
     }
     return IA_NO_ERROR;
 }
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index a7e8997..ce1c9ac 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -1,15 +1,18 @@
 cc_library_headers {
     name: "libcodec2_headers",
     vendor_available: true,
+    min_sdk_version: "29",
     export_include_dirs: ["include"],
 }
 
 cc_library_shared {
     name: "libcodec2",
     vendor_available: true,
+    min_sdk_version: "29",
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     srcs: ["C2.cpp"],
 
diff --git a/media/codec2/core/OWNERS b/media/codec2/core/OWNERS
new file mode 100644
index 0000000..31ecca5
--- /dev/null
+++ b/media/codec2/core/OWNERS
@@ -0,0 +1,2 @@
+set noparent
+lajos@google.com
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 3820f90..29bccd5 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -58,6 +58,7 @@
     enum bitrate_mode_t : uint32_t;         ///< bitrate control mode
     enum drc_compression_mode_t : int32_t;  ///< DRC compression mode
     enum drc_effect_type_t : int32_t;       ///< DRC effect type
+    enum drc_album_mode_t : int32_t;        ///< DRC album mode
     enum intra_refresh_mode_t : uint32_t;   ///< intra refresh modes
     enum level_t : uint32_t;                ///< coding level
     enum ordinal_key_t : uint32_t;          ///< work ordering keys
@@ -218,6 +219,8 @@
     kParamIndexDrcBoostFactor, // drc, float (0-1)
     kParamIndexDrcAttenuationFactor, // drc, float (0-1)
     kParamIndexDrcEffectType, // drc, enum
+    kParamIndexDrcOutputLoudness, // drc, float (dBFS)
+    kParamIndexDrcAlbumMode, // drc, enum
 
     /* ============================== platform-defined parameters ============================== */
 
@@ -243,6 +246,9 @@
     kParamIndexTimestampGapAdjustment, // input-surface, struct
 
     kParamIndexSurfaceAllocator, // u32
+
+    // low latency mode
+    kParamIndexLowLatencyMode, // bool
 };
 
 }
@@ -272,16 +278,19 @@
         C2ApiLevelSetting;
 constexpr char C2_PARAMKEY_API_LEVEL[] = "api.level";
 
-enum C2Config::api_feature_t : uint64_t {
+C2ENUM(C2Config::api_feature_t, uint64_t,
     API_REFLECTION       = (1U << 0),  ///< ability to list supported parameters
     API_VALUES           = (1U << 1),  ///< ability to list supported values for each parameter
     API_CURRENT_VALUES   = (1U << 2),  ///< ability to list currently supported values for each parameter
     API_DEPENDENCY       = (1U << 3),  ///< have a defined parameter dependency
 
+    API_SAME_INPUT_BUFFER = (1U << 16),   ///< supporting multiple input buffers
+                                          ///< backed by the same allocation
+
     API_STREAMS          = (1ULL << 32),  ///< supporting variable number of streams
 
-    API_TUNNELING        = (1ULL << 48),  ///< tunneling API
-};
+    API_TUNNELING        = (1ULL << 48)   ///< tunneling API
+)
 
 // read-only
 typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::api_feature_t>, kParamIndexApiFeatures>
@@ -521,6 +530,7 @@
     PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7,      ///< Dolby Vision dvhe.07 profile
     PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8,      ///< Dolby Vision dvhe.08 profile
     PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9,      ///< Dolby Vision dvav.09 profile
+    PROFILE_DV_AV1_10 = _C2_PL_DV_BASE + 10,    ///< Dolby Vision dav1.10 profile
 
     // AV1 profiles
     PROFILE_AV1_0 = _C2_PL_AV1_BASE,            ///< AV1 Profile 0 (4:2:0, 8 to 10 bit)
@@ -804,6 +814,16 @@
 constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay";
 
 /**
+ * Enable/disable low latency mode.
+ * If true, low latency is preferred over low power. Disable power optimizations that
+ * may result in increased latency. For decoders, this means that the decoder does not
+ * hold input and output data more than required by the codec standards.
+ */
+typedef C2GlobalParam<C2Tuning, C2EasyBoolValue, kParamIndexLowLatencyMode>
+        C2GlobalLowLatencyModeTuning;
+constexpr char C2_PARAMKEY_LOW_LATENCY_MODE[] = "algo.low-latency";
+
+/**
  * Reference characteristics.
  *
  * The component may hold onto input and output buffers even after completing the corresponding
@@ -1928,6 +1948,24 @@
         C2StreamDrcEffectTypeTuning;
 constexpr char C2_PARAMKEY_DRC_EFFECT_TYPE[] = "coding.drc.effect-type";
 
+/**
+ * DRC album mode. Used during decoding.
+ */
+C2ENUM(C2Config::drc_album_mode_t, int32_t,
+    DRC_ALBUM_MODE_OFF = 0,
+    DRC_ALBUM_MODE_ON = 1
+)
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::drc_album_mode_t>, kParamIndexDrcAlbumMode>
+        C2StreamDrcAlbumModeTuning;
+constexpr char C2_PARAMKEY_DRC_ALBUM_MODE[] = "coding.drc.album-mode";
+
+/**
+ * DRC output loudness in dBFS. Retrieved during decoding
+ */
+ typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
+        C2StreamDrcOutputLoudnessTuning;
+ constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+
 /* --------------------------------------- AAC components --------------------------------------- */
 
 /**
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index f1f1536..3b73350 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -6,7 +6,7 @@
     defaults: ["hidl_defaults"],
 
     srcs: [
-        "ClientBlockHelper.cpp",
+        "OutputBufferQueue.cpp",
         "types.cpp",
     ],
 
@@ -48,6 +48,7 @@
 cc_library {
     name: "libcodec2_hidl@1.0",
     vendor_available: true,
+    min_sdk_version: "29",
 
     defaults: ["hidl_defaults"],
 
@@ -63,6 +64,7 @@
     ],
 
     header_libs: [
+        "libbinder_headers",
         "libsystem_headers",
         "libcodec2_internal", // private
     ],
@@ -80,15 +82,24 @@
         "libcodec2_vndk",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libstagefright_bufferpool@2.0.1",
-        "libstagefright_bufferqueue_helper",
+        "libstagefright_bufferqueue_helper_novndk",
         "libui",
         "libutils",
     ],
 
+    target: {
+        vendor: {
+            exclude_shared_libs: [
+                "libstagefright_bufferqueue_helper_novndk",
+            ],
+            shared_libs: [
+                "libstagefright_bufferqueue_helper",
+            ],
+        },
+    },
+
     export_include_dirs: [
         "include",
     ],
@@ -105,7 +116,7 @@
 
 // public dependency for Codec 2.0 HAL service implementations
 cc_defaults {
-    name: "libcodec2-hidl-defaults",
+    name: "libcodec2-hidl-defaults@1.0",
     defaults: ["libcodec2-impl-defaults"],
 
     shared_libs: [
@@ -116,7 +127,7 @@
 
 // public dependency for Codec 2.0 HAL client
 cc_defaults {
-    name: "libcodec2-hidl-client-defaults",
+    name: "libcodec2-hidl-client-defaults@1.0",
     defaults: ["libcodec2-impl-defaults"],
 
     shared_libs: [
diff --git a/media/codec2/hidl/1.0/utils/ClientBlockHelper.cpp b/media/codec2/hidl/1.0/utils/ClientBlockHelper.cpp
deleted file mode 100644
index 50790bc..0000000
--- a/media/codec2/hidl/1.0/utils/ClientBlockHelper.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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-block_helper"
-#include <android-base/logging.h>
-
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/ClientBlockHelper.h>
-#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
-
-#include <C2AllocatorGralloc.h>
-#include <C2BlockInternal.h>
-#include <C2Buffer.h>
-#include <C2PlatformSupport.h>
-
-#include <iomanip>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
-        V2_0::IGraphicBufferProducer;
-using B2HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
-        V2_0::utils::B2HGraphicBufferProducer;
-
-namespace /* unnamed */ {
-
-// Create a GraphicBuffer object from a graphic block.
-sp<GraphicBuffer> createGraphicBuffer(const C2ConstGraphicBlock& block) {
-    uint32_t width;
-    uint32_t height;
-    uint32_t format;
-    uint64_t usage;
-    uint32_t stride;
-    uint32_t generation;
-    uint64_t bqId;
-    int32_t bqSlot;
-    _UnwrapNativeCodec2GrallocMetadata(
-            block.handle(), &width, &height, &format, &usage,
-            &stride, &generation, &bqId, reinterpret_cast<uint32_t*>(&bqSlot));
-    native_handle_t *grallocHandle =
-            UnwrapNativeCodec2GrallocHandle(block.handle());
-    sp<GraphicBuffer> graphicBuffer =
-            new GraphicBuffer(grallocHandle,
-                              GraphicBuffer::CLONE_HANDLE,
-                              width, height, format,
-                              1, usage, stride);
-    native_handle_delete(grallocHandle);
-    return graphicBuffer;
-}
-
-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) {
-    for (const std::unique_ptr<C2Work>& work : workList) {
-        if (!work) {
-            continue;
-        }
-        for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
-            if (worklet) {
-                forEachBlock(worklet->output, process);
-            }
-        }
-    }
-}
-
-sp<HGraphicBufferProducer> getHgbp(const sp<IGraphicBufferProducer>& igbp) {
-    sp<HGraphicBufferProducer> hgbp =
-            igbp->getHalInterface<HGraphicBufferProducer>();
-    return hgbp ? hgbp :
-            new B2HGraphicBufferProducer(igbp);
-}
-
-status_t attachToBufferQueue(const C2ConstGraphicBlock& block,
-                             const sp<IGraphicBufferProducer>& igbp,
-                             uint32_t generation,
-                             int32_t* bqSlot) {
-    if (!igbp) {
-        LOG(WARNING) << "attachToBufferQueue -- null producer.";
-        return NO_INIT;
-    }
-
-    sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block);
-    graphicBuffer->setGenerationNumber(generation);
-
-    LOG(VERBOSE) << "attachToBufferQueue -- attaching buffer:"
-            << " block dimension " << block.width() << "x"
-                                   << block.height()
-            << ", graphicBuffer dimension " << graphicBuffer->getWidth() << "x"
-                                           << graphicBuffer->getHeight()
-            << std::hex << std::setfill('0')
-            << ", format 0x" << std::setw(8) << graphicBuffer->getPixelFormat()
-            << ", usage 0x" << std::setw(16) << graphicBuffer->getUsage()
-            << std::dec << std::setfill(' ')
-            << ", stride " << graphicBuffer->getStride()
-            << ", generation " << graphicBuffer->getGenerationNumber();
-
-    status_t result = igbp->attachBuffer(bqSlot, graphicBuffer);
-    if (result != OK) {
-        LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: "
-                        "status = " << result << ".";
-        return result;
-    }
-    LOG(VERBOSE) << "attachToBufferQueue -- attachBuffer returned slot #"
-                 << *bqSlot << ".";
-    return OK;
-}
-
-bool getBufferQueueAssignment(const C2ConstGraphicBlock& block,
-                              uint32_t* generation,
-                              uint64_t* bqId,
-                              int32_t* bqSlot) {
-    return _C2BlockFactory::GetBufferQueueData(
-            _C2BlockFactory::GetGraphicBlockPoolData(block),
-            generation, bqId, bqSlot);
-}
-} // unnamed namespace
-
-class OutputBufferQueue::Impl {
-    std::mutex mMutex;
-    sp<IGraphicBufferProducer> mIgbp;
-    uint32_t mGeneration;
-    uint64_t mBqId;
-    std::shared_ptr<int> mOwner;
-    // To migrate existing buffers
-    sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
-    std::weak_ptr<_C2BlockPoolData>
-                    mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
-
-public:
-    Impl(): mGeneration(0), mBqId(0) {}
-
-    bool configure(const sp<IGraphicBufferProducer>& igbp,
-                   uint32_t generation,
-                   uint64_t bqId) {
-        size_t tryNum = 0;
-        size_t success = 0;
-        sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
-        std::weak_ptr<_C2BlockPoolData>
-                poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
-        {
-            std::scoped_lock<std::mutex> l(mMutex);
-            if (generation == mGeneration) {
-                return false;
-            }
-            mIgbp = igbp;
-            mGeneration = generation;
-            mBqId = bqId;
-            mOwner = std::make_shared<int>(0);
-            for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
-                if (mBqId == 0 || !mBuffers[i]) {
-                    continue;
-                }
-                std::shared_ptr<_C2BlockPoolData> data = mPoolDatas[i].lock();
-                if (!data ||
-                    !_C2BlockFactory::BeginAttachBlockToBufferQueue(data)) {
-                    continue;
-                }
-                ++tryNum;
-                int bqSlot;
-                mBuffers[i]->setGenerationNumber(generation);
-                status_t result = igbp->attachBuffer(&bqSlot, mBuffers[i]);
-                if (result != OK) {
-                    continue;
-                }
-                bool attach =
-                        _C2BlockFactory::EndAttachBlockToBufferQueue(
-                                data, mOwner, getHgbp(mIgbp),
-                                generation, bqId, bqSlot);
-                if (!attach) {
-                    igbp->cancelBuffer(bqSlot, Fence::NO_FENCE);
-                    continue;
-                }
-                buffers[bqSlot] = mBuffers[i];
-                poolDatas[bqSlot] = data;
-                ++success;
-            }
-            for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
-                mBuffers[i] = buffers[i];
-                mPoolDatas[i] = poolDatas[i];
-            }
-        }
-        ALOGD("remote graphic buffer migration %zu/%zu", success, tryNum);
-        return true;
-    }
-
-    bool registerBuffer(const C2ConstGraphicBlock& block) {
-        std::shared_ptr<_C2BlockPoolData> data =
-                _C2BlockFactory::GetGraphicBlockPoolData(block);
-        if (!data) {
-            return false;
-        }
-        std::scoped_lock<std::mutex> l(mMutex);
-
-        if (!mIgbp) {
-            return false;
-        }
-
-        uint32_t oldGeneration;
-        uint64_t oldId;
-        int32_t oldSlot;
-        // If the block is not bufferqueue-based, do nothing.
-        if (!_C2BlockFactory::GetBufferQueueData(
-                data, &oldGeneration, &oldId, &oldSlot) || (oldId == 0)) {
-            return false;
-        }
-        // If the block's bqId is the same as the desired bqId, just hold.
-        if ((oldId == mBqId) && (oldGeneration == mGeneration)) {
-            LOG(VERBOSE) << "holdBufferQueueBlock -- import without attaching:"
-                         << " bqId " << oldId
-                         << ", bqSlot " << oldSlot
-                         << ", generation " << mGeneration
-                         << ".";
-            _C2BlockFactory::HoldBlockFromBufferQueue(data, mOwner, getHgbp(mIgbp));
-            mPoolDatas[oldSlot] = data;
-            mBuffers[oldSlot] = createGraphicBuffer(block);
-            mBuffers[oldSlot]->setGenerationNumber(mGeneration);
-            return true;
-        }
-        int32_t d = (int32_t) mGeneration - (int32_t) oldGeneration;
-        LOG(WARNING) << "receiving stale buffer: generation "
-                     << mGeneration << " , diff " << d  << " : slot "
-                     << oldSlot;
-        return false;
-    }
-
-    status_t outputBuffer(
-            const C2ConstGraphicBlock& block,
-            const BnGraphicBufferProducer::QueueBufferInput& input,
-            BnGraphicBufferProducer::QueueBufferOutput* output) {
-        uint32_t generation;
-        uint64_t bqId;
-        int32_t bqSlot;
-        bool display = displayBufferQueueBlock(block);
-        if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
-            bqId == 0) {
-            // Block not from bufferqueue -- it must be attached before queuing.
-
-            mMutex.lock();
-            sp<IGraphicBufferProducer> outputIgbp = mIgbp;
-            uint32_t outputGeneration = mGeneration;
-            mMutex.unlock();
-
-            status_t status = attachToBufferQueue(
-                    block, outputIgbp, outputGeneration, &bqSlot);
-            if (status != OK) {
-                LOG(WARNING) << "outputBuffer -- attaching failed.";
-                return INVALID_OPERATION;
-            }
-
-            status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
-                                         input, output);
-            if (status != OK) {
-                LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
-                           "on non-bufferqueue-based block. "
-                           "Error = " << status << ".";
-                return status;
-            }
-            return OK;
-        }
-
-        mMutex.lock();
-        sp<IGraphicBufferProducer> outputIgbp = mIgbp;
-        uint32_t outputGeneration = mGeneration;
-        uint64_t outputBqId = mBqId;
-        mMutex.unlock();
-
-        if (!outputIgbp) {
-            LOG(VERBOSE) << "outputBuffer -- output surface is null.";
-            return NO_INIT;
-        }
-
-        if (!display) {
-            LOG(WARNING) << "outputBuffer -- cannot display "
-                         "bufferqueue-based block to the bufferqueue.";
-            return UNKNOWN_ERROR;
-        }
-        if (bqId != outputBqId || generation != outputGeneration) {
-            int32_t diff = (int32_t) outputGeneration - (int32_t) generation;
-            LOG(WARNING) << "outputBuffer -- buffers from old generation to "
-                         << outputGeneration << " , diff: " << diff
-                         << " , slot: " << bqSlot;
-            return DEAD_OBJECT;
-        }
-
-        status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
-                                              input, output);
-        if (status != OK) {
-            LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
-                       "on bufferqueue-based block. "
-                       "Error = " << status << ".";
-            return status;
-        }
-        return OK;
-    }
-
-    Impl *getPtr() {
-        return this;
-    }
-
-    ~Impl() {}
-};
-
-OutputBufferQueue::OutputBufferQueue(): mImpl(new Impl()) {}
-
-OutputBufferQueue::~OutputBufferQueue() {}
-
-bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp,
-                                  uint32_t generation,
-                                  uint64_t bqId) {
-    return mImpl && mImpl->configure(igbp, generation, bqId);
-}
-
-status_t OutputBufferQueue::outputBuffer(
-    const C2ConstGraphicBlock& block,
-    const BnGraphicBufferProducer::QueueBufferInput& input,
-    BnGraphicBufferProducer::QueueBufferOutput* output) {
-    if (mImpl) {
-        return mImpl->outputBuffer(block, input, output);
-    }
-    return DEAD_OBJECT;
-}
-
-void OutputBufferQueue::holdBufferQueueBlocks(
-        const std::list<std::unique_ptr<C2Work>>& workList) {
-    if (!mImpl) {
-        return;
-    }
-    forEachBlock(workList,
-                 std::bind(&OutputBufferQueue::Impl::registerBuffer,
-                           mImpl->getPtr(), std::placeholders::_1));
-}
-
-}  // namespace utils
-}  // namespace V1_0
-}  // namespace c2
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index a9f20a4..8a84601 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -204,7 +204,8 @@
         const sp<::android::hardware::media::bufferpool::V2_0::
         IClientManager>& clientPoolManager)
       : mComponent{component},
-        mInterface{new ComponentInterface(component->intf(), store.get())},
+        mInterface{new ComponentInterface(component->intf(),
+                                          store->getParameterCache())},
         mListener{listener},
         mStore{store},
         mBufferPoolSender{clientPoolManager} {
diff --git a/media/codec2/hidl/1.0/utils/ComponentInterface.cpp b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
index 39e5357..12078e0 100644
--- a/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
@@ -87,10 +87,10 @@
 // ComponentInterface
 ComponentInterface::ComponentInterface(
         const std::shared_ptr<C2ComponentInterface>& intf,
-        ComponentStore* store)
+        const std::shared_ptr<ParameterCache>& cache)
       : mInterface{intf},
         mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
-    mInit = mConfigurable->init(store);
+    mInit = mConfigurable->init(cache);
 }
 
 c2_status_t ComponentInterface::status() const {
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index 1e0a190..9b9d449 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -102,8 +102,29 @@
 
 } // 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();
@@ -113,7 +134,12 @@
     mParamReflector = mStore->getParamReflector();
 
     // Retrieve supported parameters from store
-    mInit = mConfigurable->init(this);
+    using namespace std::placeholders;
+    mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+    mParameterCache->onStoreDestroyed();
 }
 
 c2_status_t ComponentStore::status() const {
@@ -146,6 +172,10 @@
     return res;
 }
 
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+    return mParameterCache;
+}
+
 // Methods from ::android::hardware::media::c2::V1_0::IComponentStore
 Return<void> ComponentStore::createComponent(
         const hidl_string& name,
@@ -187,7 +217,7 @@
     sp<IComponentInterface> interface;
     if (res == C2_OK) {
         onInterfaceLoaded(c2interface);
-        interface = new ComponentInterface(c2interface, this);
+        interface = new ComponentInterface(c2interface, mParameterCache);
     }
     _hidl_cb(static_cast<Status>(res), interface);
     return Void();
@@ -218,8 +248,9 @@
         _hidl_cb(Status::CORRUPTED, nullptr);
         return Void();
     }
+    using namespace std::placeholders;
     sp<InputSurface> inputSurface = new InputSurface(
-            this,
+            mParameterCache,
             std::make_shared<C2ReflectorHelper>(),
             source->getHGraphicBufferProducer(),
             source);
diff --git a/media/codec2/hidl/1.0/utils/Configurable.cpp b/media/codec2/hidl/1.0/utils/Configurable.cpp
index ec9c170..530576d 100644
--- a/media/codec2/hidl/1.0/utils/Configurable.cpp
+++ b/media/codec2/hidl/1.0/utils/Configurable.cpp
@@ -38,10 +38,11 @@
       : mIntf{std::move(intf)} {
 }
 
-c2_status_t CachedConfigurable::init(ComponentStore* store) {
+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 = store->validateSupportedParams(mSupportedParams);
+    c2_status_t validate = cache->validate(mSupportedParams);
     return init == C2_OK ? C2_OK : validate;
 }
 
diff --git a/media/codec2/hidl/1.0/utils/InputSurface.cpp b/media/codec2/hidl/1.0/utils/InputSurface.cpp
index 2b4ca85..c3c32e9 100644
--- a/media/codec2/hidl/1.0/utils/InputSurface.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurface.cpp
@@ -137,9 +137,9 @@
     }
     std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
     if (comp) {
-        connection = new InputSurfaceConnection(mSource, comp, mStore);
+        connection = new InputSurfaceConnection(mSource, comp, mParameterCache);
     } else {
-        connection = new InputSurfaceConnection(mSource, sink, mStore);
+        connection = new InputSurfaceConnection(mSource, sink, mParameterCache);
     }
     if (!connection->init()) {
         connection = nullptr;
@@ -153,11 +153,11 @@
 
 // Constructor is exclusive to ComponentStore.
 InputSurface::InputSurface(
-        const sp<ComponentStore>& store,
+        const std::shared_ptr<ParameterCache>& cache,
         const std::shared_ptr<C2ReflectorHelper>& reflector,
         const sp<HGraphicBufferProducer>& producer,
         const sp<GraphicBufferSource>& source)
-      : mStore{store},
+      : mParameterCache{cache},
         mProducer{producer},
         mSource{source},
         mIntf{std::make_shared<Interface>(reflector)},
@@ -165,7 +165,7 @@
                 std::make_unique<ConfigurableIntf>(
                     mIntf, source))} {
 
-    mConfigurable->init(store.get());
+    mConfigurable->init(mParameterCache);
 }
 
 }  // namespace utils
diff --git a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
index c9932ef..5ec88ec 100644
--- a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
@@ -160,12 +160,12 @@
             return false;
         }
         for (int32_t i = 0; i < kBufferCount; ++i) {
-            if (!mSource->onInputBufferAdded(i).isOk()) {
+            if (mSource->onInputBufferAdded(i) != OK) {
                 LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
                 return false;
             }
         }
-        if (!mSource->start().isOk()) {
+        if (mSource->start() != OK) {
             LOG(WARNING) << "Impl::init -- GBS failed to start.";
             return false;
         }
@@ -445,21 +445,21 @@
 InputSurfaceConnection::InputSurfaceConnection(
         const sp<GraphicBufferSource>& source,
         const std::shared_ptr<C2Component>& comp,
-        const sp<ComponentStore>& store)
+        const std::shared_ptr<ParameterCache>& cache)
       : mImpl{new Impl(source, comp)},
         mConfigurable{new CachedConfigurable(
             std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
-    mConfigurable->init(store.get());
+    mConfigurable->init(cache);
 }
 
 InputSurfaceConnection::InputSurfaceConnection(
         const sp<GraphicBufferSource>& source,
         const sp<IInputSink>& sink,
-        const sp<ComponentStore>& store)
+        const std::shared_ptr<ParameterCache>& cache)
       : mImpl{new Impl(source, sink)},
         mConfigurable{new CachedConfigurable(
             std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
-    mConfigurable->init(store.get());
+    mConfigurable->init(cache);
 }
 
 Return<Status> InputSurfaceConnection::disconnect() {
diff --git a/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
new file mode 100644
index 0000000..c4a72ef
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
@@ -0,0 +1,335 @@
+/*
+ * 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-OutputBufferQueue"
+#include <android-base/logging.h>
+
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+
+#include <C2AllocatorGralloc.h>
+#include <C2BlockInternal.h>
+#include <C2Buffer.h>
+#include <C2PlatformSupport.h>
+
+#include <iomanip>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
+        V2_0::IGraphicBufferProducer;
+using B2HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
+        V2_0::utils::B2HGraphicBufferProducer;
+
+namespace /* unnamed */ {
+
+// Create a GraphicBuffer object from a graphic block.
+sp<GraphicBuffer> createGraphicBuffer(const C2ConstGraphicBlock& block) {
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    uint64_t usage;
+    uint32_t stride;
+    uint32_t generation;
+    uint64_t bqId;
+    int32_t bqSlot;
+    _UnwrapNativeCodec2GrallocMetadata(
+            block.handle(), &width, &height, &format, &usage,
+            &stride, &generation, &bqId, reinterpret_cast<uint32_t*>(&bqSlot));
+    native_handle_t *grallocHandle =
+            UnwrapNativeCodec2GrallocHandle(block.handle());
+    sp<GraphicBuffer> graphicBuffer =
+            new GraphicBuffer(grallocHandle,
+                              GraphicBuffer::CLONE_HANDLE,
+                              width, height, format,
+                              1, usage, stride);
+    native_handle_delete(grallocHandle);
+    return graphicBuffer;
+}
+
+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) {
+    for (const std::unique_ptr<C2Work>& work : workList) {
+        if (!work) {
+            continue;
+        }
+        for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
+            if (worklet) {
+                forEachBlock(worklet->output, process);
+            }
+        }
+    }
+}
+
+sp<HGraphicBufferProducer> getHgbp(const sp<IGraphicBufferProducer>& igbp) {
+    sp<HGraphicBufferProducer> hgbp =
+            igbp->getHalInterface<HGraphicBufferProducer>();
+    return hgbp ? hgbp :
+            new B2HGraphicBufferProducer(igbp);
+}
+
+status_t attachToBufferQueue(const C2ConstGraphicBlock& block,
+                             const sp<IGraphicBufferProducer>& igbp,
+                             uint32_t generation,
+                             int32_t* bqSlot) {
+    if (!igbp) {
+        LOG(WARNING) << "attachToBufferQueue -- null producer.";
+        return NO_INIT;
+    }
+
+    sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block);
+    graphicBuffer->setGenerationNumber(generation);
+
+    LOG(VERBOSE) << "attachToBufferQueue -- attaching buffer:"
+            << " block dimension " << block.width() << "x"
+                                   << block.height()
+            << ", graphicBuffer dimension " << graphicBuffer->getWidth() << "x"
+                                           << graphicBuffer->getHeight()
+            << std::hex << std::setfill('0')
+            << ", format 0x" << std::setw(8) << graphicBuffer->getPixelFormat()
+            << ", usage 0x" << std::setw(16) << graphicBuffer->getUsage()
+            << std::dec << std::setfill(' ')
+            << ", stride " << graphicBuffer->getStride()
+            << ", generation " << graphicBuffer->getGenerationNumber();
+
+    status_t result = igbp->attachBuffer(bqSlot, graphicBuffer);
+    if (result != OK) {
+        LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: "
+                        "status = " << result << ".";
+        return result;
+    }
+    LOG(VERBOSE) << "attachToBufferQueue -- attachBuffer returned slot #"
+                 << *bqSlot << ".";
+    return OK;
+}
+
+bool getBufferQueueAssignment(const C2ConstGraphicBlock& block,
+                              uint32_t* generation,
+                              uint64_t* bqId,
+                              int32_t* bqSlot) {
+    return _C2BlockFactory::GetBufferQueueData(
+            _C2BlockFactory::GetGraphicBlockPoolData(block),
+            generation, bqId, bqSlot);
+}
+
+} // unnamed namespace
+
+OutputBufferQueue::OutputBufferQueue()
+      : mGeneration{0}, mBqId{0} {
+}
+
+OutputBufferQueue::~OutputBufferQueue() {
+}
+
+bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp,
+                                  uint32_t generation,
+                                  uint64_t bqId) {
+    size_t tryNum = 0;
+    size_t success = 0;
+    sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
+    std::weak_ptr<_C2BlockPoolData>
+            poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
+    {
+        std::scoped_lock<std::mutex> l(mMutex);
+        if (generation == mGeneration) {
+            return false;
+        }
+        mIgbp = igbp;
+        mGeneration = generation;
+        mBqId = bqId;
+        mOwner = std::make_shared<int>(0);
+        for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
+            if (mBqId == 0 || !mBuffers[i]) {
+                continue;
+            }
+            std::shared_ptr<_C2BlockPoolData> data = mPoolDatas[i].lock();
+            if (!data ||
+                !_C2BlockFactory::BeginAttachBlockToBufferQueue(data)) {
+                continue;
+            }
+            ++tryNum;
+            int bqSlot;
+            mBuffers[i]->setGenerationNumber(generation);
+            status_t result = igbp->attachBuffer(&bqSlot, mBuffers[i]);
+            if (result != OK) {
+                continue;
+            }
+            bool attach =
+                    _C2BlockFactory::EndAttachBlockToBufferQueue(
+                            data, mOwner, getHgbp(mIgbp),
+                            generation, bqId, bqSlot);
+            if (!attach) {
+                igbp->cancelBuffer(bqSlot, Fence::NO_FENCE);
+                continue;
+            }
+            buffers[bqSlot] = mBuffers[i];
+            poolDatas[bqSlot] = data;
+            ++success;
+        }
+        for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
+            mBuffers[i] = buffers[i];
+            mPoolDatas[i] = poolDatas[i];
+        }
+    }
+    ALOGD("remote graphic buffer migration %zu/%zu", success, tryNum);
+    return true;
+}
+
+bool OutputBufferQueue::registerBuffer(const C2ConstGraphicBlock& block) {
+    std::shared_ptr<_C2BlockPoolData> data =
+            _C2BlockFactory::GetGraphicBlockPoolData(block);
+    if (!data) {
+        return false;
+    }
+    std::scoped_lock<std::mutex> l(mMutex);
+
+    if (!mIgbp) {
+        return false;
+    }
+
+    uint32_t oldGeneration;
+    uint64_t oldId;
+    int32_t oldSlot;
+    // If the block is not bufferqueue-based, do nothing.
+    if (!_C2BlockFactory::GetBufferQueueData(
+            data, &oldGeneration, &oldId, &oldSlot) || (oldId == 0)) {
+        return false;
+    }
+    // If the block's bqId is the same as the desired bqId, just hold.
+    if ((oldId == mBqId) && (oldGeneration == mGeneration)) {
+        LOG(VERBOSE) << "holdBufferQueueBlock -- import without attaching:"
+                     << " bqId " << oldId
+                     << ", bqSlot " << oldSlot
+                     << ", generation " << mGeneration
+                     << ".";
+        _C2BlockFactory::HoldBlockFromBufferQueue(data, mOwner, getHgbp(mIgbp));
+        mPoolDatas[oldSlot] = data;
+        mBuffers[oldSlot] = createGraphicBuffer(block);
+        mBuffers[oldSlot]->setGenerationNumber(mGeneration);
+        return true;
+    }
+    int32_t d = (int32_t) mGeneration - (int32_t) oldGeneration;
+    LOG(WARNING) << "receiving stale buffer: generation "
+                 << mGeneration << " , diff " << d  << " : slot "
+                 << oldSlot;
+    return false;
+}
+
+status_t OutputBufferQueue::outputBuffer(
+        const C2ConstGraphicBlock& block,
+        const BnGraphicBufferProducer::QueueBufferInput& input,
+        BnGraphicBufferProducer::QueueBufferOutput* output) {
+    uint32_t generation;
+    uint64_t bqId;
+    int32_t bqSlot;
+    bool display = displayBufferQueueBlock(block);
+    if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
+        bqId == 0) {
+        // Block not from bufferqueue -- it must be attached before queuing.
+
+        mMutex.lock();
+        sp<IGraphicBufferProducer> outputIgbp = mIgbp;
+        uint32_t outputGeneration = mGeneration;
+        mMutex.unlock();
+
+        status_t status = attachToBufferQueue(
+                block, outputIgbp, outputGeneration, &bqSlot);
+        if (status != OK) {
+            LOG(WARNING) << "outputBuffer -- attaching failed.";
+            return INVALID_OPERATION;
+        }
+
+        status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+                                     input, output);
+        if (status != OK) {
+            LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
+                       "on non-bufferqueue-based block. "
+                       "Error = " << status << ".";
+            return status;
+        }
+        return OK;
+    }
+
+    mMutex.lock();
+    sp<IGraphicBufferProducer> outputIgbp = mIgbp;
+    uint32_t outputGeneration = mGeneration;
+    uint64_t outputBqId = mBqId;
+    mMutex.unlock();
+
+    if (!outputIgbp) {
+        LOG(VERBOSE) << "outputBuffer -- output surface is null.";
+        return NO_INIT;
+    }
+
+    if (!display) {
+        LOG(WARNING) << "outputBuffer -- cannot display "
+                     "bufferqueue-based block to the bufferqueue.";
+        return UNKNOWN_ERROR;
+    }
+    if (bqId != outputBqId || generation != outputGeneration) {
+        int32_t diff = (int32_t) outputGeneration - (int32_t) generation;
+        LOG(WARNING) << "outputBuffer -- buffers from old generation to "
+                     << outputGeneration << " , diff: " << diff
+                     << " , slot: " << bqSlot;
+        return DEAD_OBJECT;
+    }
+
+    status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+                                          input, output);
+    if (status != OK) {
+        LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
+                   "on bufferqueue-based block. "
+                   "Error = " << status << ".";
+        return status;
+    }
+    return OK;
+}
+
+void OutputBufferQueue::holdBufferQueueBlocks(
+        const std::list<std::unique_ptr<C2Work>>& workList) {
+    forEachBlock(workList,
+                 std::bind(&OutputBufferQueue::registerBuffer,
+                           this, std::placeholders::_1));
+}
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ClientBlockHelper.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ClientBlockHelper.h
deleted file mode 100644
index 0a2298c..0000000
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ClientBlockHelper.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 CLIENT_BLOCK_HELPER_H
-#define CLIENT_BLOCK_HELPER_H
-
-#include <gui/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/types.h>
-#include <C2Work.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-// BufferQueue-Based Block Operations
-// ==================================
-
-// Manage BufferQueue and graphic blocks for both component and codec.
-// Manage graphic blocks ownership consistently during surface change.
-struct OutputBufferQueue {
-
-    OutputBufferQueue();
-
-    ~OutputBufferQueue();
-
-    // Configure a new surface to render graphic blocks.
-    // Graphic blocks from older surface will be migrated to new surface.
-    bool configure(const sp<IGraphicBufferProducer>& igbp,
-                   uint32_t generation,
-                   uint64_t bqId);
-
-    // Render a graphic block to current surface.
-    status_t outputBuffer(
-            const C2ConstGraphicBlock& block,
-            const BnGraphicBufferProducer::QueueBufferInput& input,
-            BnGraphicBufferProducer::QueueBufferOutput* output);
-
-    // Call holdBufferQueueBlock() on output blocks in the given workList.
-    // The OutputBufferQueue will take the ownership of output blocks.
-    //
-    // Note: This function should be called after WorkBundle has been received
-    // from another process.
-    void holdBufferQueueBlocks(
-            const std::list<std::unique_ptr<C2Work>>& workList);
-
-private:
-
-    class Impl;
-    std::unique_ptr<Impl> mImpl;
-};
-
-}  // namespace utils
-}  // namespace V1_0
-}  // namespace c2
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
-#endif  // CLIENT_BLOCK_HELPER_H
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
index a5d235e..9102f92 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
@@ -45,7 +45,7 @@
 struct ComponentInterface : public IComponentInterface {
     ComponentInterface(
             const std::shared_ptr<C2ComponentInterface>& interface,
-            ComponentStore* store);
+            const std::shared_ptr<ParameterCache>& cache);
     c2_status_t status() const;
     virtual Return<sp<IConfigurable>> getConfigurable() override;
 
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index be80c62..fe7d048 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -54,7 +54,7 @@
 
 struct ComponentStore : public IComponentStore {
     ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
-    virtual ~ComponentStore() = default;
+    virtual ~ComponentStore();
 
     /**
      * Returns the status of the construction of this object.
@@ -68,6 +68,12 @@
     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;
+
     // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
     virtual Return<void> createComponent(
             const hidl_string& name,
@@ -98,6 +104,8 @@
 
 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);
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
index 8095185..8f49a97 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
@@ -79,6 +79,20 @@
 };
 
 /**
+ * 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.
  *
@@ -91,7 +105,8 @@
 struct CachedConfigurable : public IConfigurable {
     CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
 
-    c2_status_t init(ComponentStore* store);
+    // Populates mSupportedParams.
+    c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
 
     // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
 
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index 29ed7ff..062dcd9 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -57,30 +57,26 @@
             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;
 
-    sp<ComponentStore> mStore;
+    std::shared_ptr<ParameterCache> mParameterCache;
     sp<HGraphicBufferProducer> mProducer;
     sp<GraphicBufferSource> mSource;
     std::shared_ptr<Interface> mIntf;
     sp<CachedConfigurable> mConfigurable;
 
-    InputSurface(
-            const sp<ComponentStore>& store,
-            const std::shared_ptr<C2ReflectorHelper>& reflector,
-            const sp<HGraphicBufferProducer>& base,
-            const sp<GraphicBufferSource>& source);
-
     virtual ~InputSurface() override = default;
-
-    friend struct ComponentStore;
-
 };
 
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace c2
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
index 758b6b2..475ce8b 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
@@ -62,12 +62,12 @@
     InputSurfaceConnection(
             const sp<GraphicBufferSource>& source,
             const std::shared_ptr<C2Component>& comp,
-            const sp<ComponentStore>& store);
+            const std::shared_ptr<ParameterCache>& cache);
 
     InputSurfaceConnection(
             const sp<GraphicBufferSource>& source,
             const sp<IInputSink>& sink,
-            const sp<ComponentStore>& store);
+            const std::shared_ptr<ParameterCache>& cache);
 
     bool init();
 
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h
new file mode 100644
index 0000000..80368f7
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h
@@ -0,0 +1,85 @@
+/*
+ * 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_OUTPUT_BUFFER_QUEUE
+#define CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
+
+#include <gui/IGraphicBufferProducer.h>
+#include <codec2/hidl/1.0/types.h>
+#include <C2Work.h>
+
+struct C2_HIDE _C2BlockPoolData;
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+// BufferQueue-Based Block Operations
+// ==================================
+
+// Manage BufferQueue and graphic blocks for both component and codec.
+// Manage graphic blocks ownership consistently during surface change.
+struct OutputBufferQueue {
+
+    OutputBufferQueue();
+
+    ~OutputBufferQueue();
+
+    // Configure a new surface to render graphic blocks.
+    // Graphic blocks from older surface will be migrated to new surface.
+    bool configure(const sp<IGraphicBufferProducer>& igbp,
+                   uint32_t generation,
+                   uint64_t bqId);
+
+    // Render a graphic block to current surface.
+    status_t outputBuffer(
+            const C2ConstGraphicBlock& block,
+            const BnGraphicBufferProducer::QueueBufferInput& input,
+            BnGraphicBufferProducer::QueueBufferOutput* output);
+
+    // Call holdBufferQueueBlock() on output blocks in the given workList.
+    // The OutputBufferQueue will take the ownership of output blocks.
+    //
+    // Note: This function should be called after WorkBundle has been received
+    // from another process.
+    void holdBufferQueueBlocks(
+            const std::list<std::unique_ptr<C2Work>>& workList);
+
+private:
+
+    std::mutex mMutex;
+    sp<IGraphicBufferProducer> mIgbp;
+    uint32_t mGeneration;
+    uint64_t mBqId;
+    std::shared_ptr<int> mOwner;
+    // To migrate existing buffers
+    sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
+    std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
+
+    bool registerBuffer(const C2ConstGraphicBlock& block);
+};
+
+}  // namespace utils
+}  // namespace V1_0
+}  // namespace c2
+}  // namespace media
+}  // namespace hardware
+}  // namespace android
+
+#endif  // CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index a9928b3..f111f81 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -206,10 +206,23 @@
     std::mutex mMutex;
     sp<ClientManager> mSenderManager;
     sp<IClientManager> mReceiverManager;
-    int64_t mReceiverConnectionId;
-    int64_t mSourceConnectionId;
-    std::chrono::steady_clock::time_point mLastSent;
     std::chrono::steady_clock::duration mRefreshInterval;
+
+    struct Connection {
+        int64_t receiverConnectionId;
+        std::chrono::steady_clock::time_point lastSent;
+        Connection(int64_t receiverConnectionId,
+                   std::chrono::steady_clock::time_point lastSent)
+              : receiverConnectionId(receiverConnectionId),
+                lastSent(lastSent) {
+        }
+    };
+
+    // Map of connections.
+    //
+    // The key is the connection id. One sender-receiver pair may have multiple
+    // connections.
+    std::map<int64_t, Connection> mConnections;
 };
 
 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 04fa59c..c73cb52 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -969,8 +969,6 @@
         const sp<IClientManager>& receiverManager,
         std::chrono::steady_clock::duration refreshInterval)
     : mReceiverManager(receiverManager),
-      mSourceConnectionId(0),
-      mLastSent(std::chrono::steady_clock::now()),
       mRefreshInterval(refreshInterval) {
 }
 
@@ -980,6 +978,7 @@
     std::lock_guard<std::mutex> lock(mMutex);
     if (mReceiverManager != receiverManager) {
         mReceiverManager = receiverManager;
+        mConnections.clear();
     }
     mRefreshInterval = refreshInterval;
 }
@@ -987,12 +986,16 @@
 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;
     }
-    ResultStatus rs;
-    std::lock_guard<std::mutex> lock(mMutex);
     if (!mSenderManager) {
         mSenderManager = ClientManager::getInstance();
         if (!mSenderManager) {
@@ -1000,52 +1003,61 @@
             return ResultStatus::CRITICAL_ERROR;
         }
     }
-    int64_t connectionId = bpData->mConnectionId;
+
+    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();
-    std::chrono::steady_clock::duration interval = now - mLastSent;
-    if (mSourceConnectionId == 0 ||
-            mSourceConnectionId != connectionId ||
-            interval > mRefreshInterval) {
+    if (isNewConnection ||
+            (now - foundConnection->second.lastSent > mRefreshInterval)) {
         // Initialize the bufferpool connection.
-        mSourceConnectionId = connectionId;
-        if (mSourceConnectionId == 0) {
-            return ResultStatus::CRITICAL_ERROR;
-        }
-
-        int64_t receiverConnectionId;
-        rs = mSenderManager->registerSender(mReceiverManager,
-                                            connectionId,
-                                            &receiverConnectionId);
+        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 {
-            mReceiverConnectionId = receiverConnectionId;
+            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;
-    rs = mSenderManager->postSend(
-            mReceiverConnectionId, bpData, &transactionId, &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 = mReceiverConnectionId;
+    bpMessage->connectionId = receiverConnectionId;
     bpMessage->bufferId = bpData->mId;
     bpMessage->transactionId = transactionId;
     bpMessage->timestampUs = timestampUs;
-    mLastSent = now;
+    foundConnection->second.lastSent = now;
     return rs;
 }
 
diff --git a/media/codec2/hidl/1.0/vts/OWNERS b/media/codec2/hidl/1.0/vts/OWNERS
index 6733e0c..dbe89cf 100644
--- a/media/codec2/hidl/1.0/vts/OWNERS
+++ b/media/codec2/hidl/1.0/vts/OWNERS
@@ -5,5 +5,4 @@
 wonsik@google.com
 
 # VTS team
-yim@google.com
-zhuoyao@google.com
+dshi@google.com
diff --git a/media/codec2/hidl/1.0/vts/functional/Android.bp b/media/codec2/hidl/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..5ea4825
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/Android.bp
@@ -0,0 +1,111 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+filegroup {
+    name: "media_c2_v1_audio_decode_res",
+    path: "res",
+    srcs: [
+        "res/bbb_aac_stereo_128kbps_48000hz.aac",
+        "res/bbb_aac_stereo_128kbps_48000hz.info",
+        "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info",
+        "res/bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+        "res/bbb_amrwb_1ch_14kbps_16000hz.info",
+        "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info",
+        "res/bbb_flac_stereo_680kbps_48000hz.flac",
+        "res/bbb_flac_stereo_680kbps_48000hz.info",
+        "res/bbb_g711alaw_1ch_8khz.info",
+        "res/bbb_g711alaw_1ch_8khz.raw",
+        "res/bbb_g711mulaw_1ch_8khz.info",
+        "res/bbb_g711mulaw_1ch_8khz.raw",
+        "res/bbb_gsm_1ch_8khz_13kbps.info",
+        "res/bbb_gsm_1ch_8khz_13kbps.raw",
+        "res/bbb_mp3_stereo_192kbps_48000hz.info",
+        "res/bbb_mp3_stereo_192kbps_48000hz.mp3",
+        "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info",
+        "res/bbb_opus_stereo_128kbps_48000hz.info",
+        "res/bbb_opus_stereo_128kbps_48000hz.opus",
+        "res/bbb_raw_1ch_8khz_s32le.info",
+        "res/bbb_raw_1ch_8khz_s32le.raw",
+        "res/bbb_vorbis_stereo_128kbps_48000hz.info",
+        "res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
+        "res/sine_amrnb_1ch_12kbps_8000hz.amrnb",
+        "res/sine_amrnb_1ch_12kbps_8000hz.info",
+        "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info",
+    ],
+}
+
+filegroup {
+    name: "media_c2_v1_audio_encode_res",
+    path: "res",
+    srcs: [
+        "res/bbb_raw_2ch_48khz_s16le.raw",
+        "res/bbb_raw_1ch_8khz_s16le.raw",
+        "res/bbb_raw_1ch_16khz_s16le.raw",
+    ],
+}
+
+filegroup {
+    name: "media_c2_v1_video_decode_res",
+    path: "res",
+    srcs: [
+        "res/bbb_avc_176x144_300kbps_60fps.h264",
+        "res/bbb_avc_640x360_768kbps_30fps.h264",
+        "res/bbb_avc_176x144_300kbps_60fps.info",
+        "res/bbb_avc_640x360_768kbps_30fps.info",
+        "res/bbb_hevc_176x144_176kbps_60fps.hevc",
+        "res/bbb_hevc_640x360_1600kbps_30fps.hevc",
+        "res/bbb_hevc_176x144_176kbps_60fps.info",
+        "res/bbb_hevc_640x360_1600kbps_30fps.info",
+        "res/bbb_mpeg2_176x144_105kbps_25fps.m2v",
+        "res/bbb_mpeg2_352x288_1mbps_60fps.m2v",
+        "res/bbb_mpeg2_176x144_105kbps_25fps.info",
+        "res/bbb_mpeg2_352x288_1mbps_60fps.info",
+        "res/bbb_h263_352x288_300kbps_12fps.h263",
+        "res/bbb_h263_352x288_300kbps_12fps.info",
+        "res/bbb_mpeg4_352x288_512kbps_30fps.m4v",
+        "res/bbb_mpeg4_352x288_512kbps_30fps.info",
+        "res/bbb_vp8_176x144_240kbps_60fps.vp8",
+        "res/bbb_vp8_640x360_2mbps_30fps.vp8",
+        "res/bbb_vp8_176x144_240kbps_60fps.info",
+        "res/bbb_vp8_640x360_2mbps_30fps.info",
+        "res/bbb_vp9_176x144_285kbps_60fps.vp9",
+        "res/bbb_vp9_640x360_1600kbps_30fps.vp9",
+        "res/bbb_vp9_176x144_285kbps_60fps.info",
+        "res/bbb_vp9_640x360_1600kbps_30fps.info",
+        "res/bbb_av1_640_360.av1",
+        "res/bbb_av1_176_144.av1",
+        "res/bbb_av1_640_360.info",
+        "res/bbb_av1_176_144.info",
+        "res/bbb_vp9_704x480_280kbps_24fps_altref_2.vp9",
+        "res/bbb_vp9_704x480_280kbps_24fps_altref_2.info",
+        "res/bbb_avc_176x144_300kbps_60fps_chksum.md5",
+        "res/bbb_avc_640x360_768kbps_30fps_chksum.md5",
+        "res/bbb_hevc_176x144_176kbps_60fps_chksum.md5",
+        "res/bbb_hevc_640x360_1600kbps_30fps_chksum.md5",
+        "res/bbb_vp8_640x360_2mbps_30fps_chksm.md5",
+        "res/bbb_vp9_640x360_1600kbps_30fps_chksm.md5",
+        "res/bbb_av1_640_360_chksum.md5",
+        "res/bbb_av1_176_144_chksm.md5",
+    ],
+}
+
+filegroup {
+    name: "media_c2_v1_video_encode_res",
+    path: "res",
+    srcs: [
+        "res/bbb_352x288_420p_30fps_32frames.yuv",
+    ],
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
index 65f0d09..014cbe9 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
@@ -16,18 +16,22 @@
 
 cc_test {
     name: "VtsHalMediaC2V1_0TargetAudioDecTest",
+    stem: "vts_media_c2_v1_0_audio_dec_test",
     defaults: ["VtsHalMediaC2V1_0Defaults"],
     srcs: [
         "VtsHalMediaC2V1_0TargetAudioDecTest.cpp",
-        //"media_audio_hidl_test_common.cpp"
     ],
+    data: [":media_c2_v1_audio_decode_res"],
+    test_config: "VtsHalMediaC2V1_0TargetAudioDecTest.xml",
 }
 
 cc_test {
     name: "VtsHalMediaC2V1_0TargetAudioEncTest",
+    stem: "vts_media_c2_v1_0_audio_enc_test",
     defaults: ["VtsHalMediaC2V1_0Defaults"],
     srcs: [
         "VtsHalMediaC2V1_0TargetAudioEncTest.cpp",
-        //"media_audio_hidl_test_common.cpp"
     ],
+    data: [":media_c2_v1_audio_encode_res"],
+    test_config: "VtsHalMediaC2V1_0TargetAudioEncTest.xml",
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index a8a552c..3a47ae9 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -19,79 +19,61 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
-#include <algorithm>
+#include <hidl/GtestPrinter.h>
 #include <stdio.h>
-#include <fstream>
+#include <algorithm>
 
-#include <codec2/hidl/client.h>
 #include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
 
 using android::C2AllocatorIon;
 
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_audio_hidl_test_common.h"
 #include "media_c2_hidl_test_common.h"
 
-struct FrameInfo {
-    int bytesCount;
-    uint32_t flags;
-    int64_t timestamp;
-};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+        kDecodeTestParameters;
+
+static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;
+
+// Resource directory
+static std::string sResourceDir = "";
 
 class LinearBuffer : public C2Buffer {
-   public:
+  public:
     explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
-        : C2Buffer(
-              {block->share(block->offset(), block->size(), ::C2Fence())}) {}
+        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
 };
 
-static ComponentTestEnvironment* gEnv = nullptr;
-
 namespace {
 
-class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
-
-   public:
-    ::std::string getTestCaseInfo() const override {
-        return ::std::string() +
-                "Component: " + gEnv->getComponent().c_str() + " | " +
-                "Instance: " + gEnv->getInstance().c_str() + " | " +
-                "Res: " + gEnv->getRes().c_str();
-    }
-
+class Codec2AudioDecHidlTestBase : public ::testing::Test {
+  public:
     // google.codec2 Audio test setup
     virtual void SetUp() override {
-        Super::SetUp();
+        getParams();
         mDisableTest = false;
         ALOGV("Codec2AudioDecHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+                mInstanceName.c_str(),
+                !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener(
-            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
-                handleWorkDone(workItems);
-            }));
+        mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+            handleWorkDone(workItems);
+        }));
         ASSERT_NE(mListener, nullptr);
         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
             mWorkQueue.emplace_back(new C2Work);
         }
-        mClient->createComponent(gEnv->getComponent().c_str(), mListener,
-                                 &mComponent);
+        mClient->createComponent(mComponentName, mListener, &mComponent);
         ASSERT_NE(mComponent, nullptr);
 
-        std::shared_ptr<C2AllocatorStore> store =
-            android::GetCodec2PlatformAllocatorStore();
-        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
-                                       &mLinearAllocator),
-                 C2_OK);
-        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
-                                                          mBlockPoolId++);
+        std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
         ASSERT_NE(mLinearPool, nullptr);
 
         mCompName = unknown_comp;
@@ -100,27 +82,17 @@
             standardComp CompName;
         };
         const StringToName kStringToName[] = {
-            {"xaac", xaac},
-            {"mp3", mp3},
-            {"amrnb", amrnb},
-            {"amrwb", amrwb},
-            {"aac", aac},
-            {"vorbis", vorbis},
-            {"opus", opus},
-            {"pcm", pcm},
-            {"g711.alaw", g711alaw},
-            {"g711.mlaw", g711mlaw},
-            {"gsm", gsm},
-            {"raw", raw},
-            {"flac", flac},
+                {"xaac", xaac},          {"mp3", mp3}, {"amrnb", amrnb},
+                {"amrwb", amrwb},        {"aac", aac}, {"vorbis", vorbis},
+                {"opus", opus},          {"pcm", pcm}, {"g711.alaw", g711alaw},
+                {"g711.mlaw", g711mlaw}, {"gsm", gsm}, {"raw", raw},
+                {"flac", flac},
         };
-        const size_t kNumStringToName =
-            sizeof(kStringToName) / sizeof(kStringToName[0]);
+        const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
 
         // Find the component type
-        std::string comp = std::string(gEnv->getComponent());
         for (size_t i = 0; i < kNumStringToName; ++i) {
-            if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+            if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
                 mCompName = kStringToName[i].CompName;
                 break;
             }
@@ -128,6 +100,7 @@
         mEos = false;
         mFramesReceived = 0;
         mTimestampUs = 0u;
+        mWorkResult = C2_OK;
         mTimestampDevTest = false;
         if (mCompName == unknown_comp) mDisableTest = true;
         if (mDisableTest) std::cout << "[   WARN   ] Test Disabled \n";
@@ -139,9 +112,13 @@
             mComponent->release();
             mComponent = nullptr;
         }
-        Super::TearDown();
     }
 
+    // Get the test parameters from GetParam call.
+    virtual void getParams() {}
+
+    virtual void validateTimestampList(int32_t* bitStreamInfo);
+
     struct outputMetaData {
         uint64_t timestampUs;
         uint32_t rangeLength;
@@ -152,27 +129,30 @@
             if (!work->worklets.empty()) {
                 // For decoder components current timestamp always exceeds
                 // previous timestamp
+                mWorkResult |= work->result;
                 bool codecConfig = ((work->worklets.front()->output.flags &
                                      C2FrameData::FLAG_CODEC_CONFIG) != 0);
-                if (!codecConfig &&
-                    !work->worklets.front()->output.buffers.empty()) {
+                if (!codecConfig && !work->worklets.front()->output.buffers.empty()) {
                     EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
-                        mTimestampUs);
-                    mTimestampUs =
-                        work->worklets.front()->output.ordinal.timestamp.peeku();
-                    uint32_t rangeLength =
-                        work->worklets.front()->output.buffers[0]->data()
-                        .linearBlocks().front().map().get().capacity();
-                    //List of timestamp values and output size to calculate timestamp
+                              mTimestampUs);
+                    mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
+                    uint32_t rangeLength = work->worklets.front()
+                                                   ->output.buffers[0]
+                                                   ->data()
+                                                   .linearBlocks()
+                                                   .front()
+                                                   .map()
+                                                   .get()
+                                                   .capacity();
+                    // List of timestamp values and output size to calculate timestamp
                     if (mTimestampDevTest) {
                         outputMetaData meta = {mTimestampUs, rangeLength};
                         oBufferMetaData.push_back(meta);
                     }
                 }
                 bool mCsd = false;
-                workDone(mComponent, work, mFlushedIndices, mQueueLock,
-                         mQueueCondition, mWorkQueue, mEos, mCsd,
-                         mFramesReceived);
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+                         mEos, mCsd, mFramesReceived);
                 (void)mCsd;
             }
         }
@@ -195,15 +175,19 @@
         unknown_comp,
     };
 
+    std::string mInstanceName;
+    std::string mComponentName;
     bool mEos;
     bool mDisableTest;
     bool mTimestampDevTest;
     standardComp mCompName;
+
+    int32_t mWorkResult;
     uint64_t mTimestampUs;
     uint32_t mFramesReceived;
     std::list<uint64_t> mFlushedIndices;
     std::list<uint64_t> mTimestampUslist;
-    ::android::List<outputMetaData> oBufferMetaData;
+    std::list<outputMetaData> oBufferMetaData;
 
     C2BlockPool::local_id_t mBlockPoolId;
     std::shared_ptr<C2BlockPool> mLinearPool;
@@ -217,15 +201,23 @@
     std::shared_ptr<android::Codec2Client::Listener> mListener;
     std::shared_ptr<android::Codec2Client::Component> mComponent;
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
 };
 
-void validateComponent(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    Codec2AudioDecHidlTest::standardComp compName, bool& disableTest) {
+class Codec2AudioDecHidlTest
+    : public Codec2AudioDecHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+                       Codec2AudioDecHidlTest::standardComp compName, bool& disableTest) {
     // Validate its a C2 Component
     if (component->getName().find("c2") == std::string::npos) {
         ALOGE("Not a c2 component");
@@ -240,14 +232,12 @@
         return;
     }
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err =
-        component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
-                         C2_DONT_BLOCK, &queried);
+    c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK && queried.size() == 0) {
         ALOGE("Query media type failed => %d", c2err);
     } else {
-        std::string inputDomain =
-            ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+        std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
         if (inputDomain.find("audio/") == std::string::npos) {
             ALOGE("Expected Audio Component");
             disableTest = true;
@@ -265,16 +255,14 @@
 }
 
 // Set Default config param.
-bool setupConfigParam(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    int32_t* bitStreamInfo) {
+bool setupConfigParam(const std::shared_ptr<android::Codec2Client::Component>& component,
+                      int32_t* bitStreamInfo) {
     std::vector<std::unique_ptr<C2SettingResult>> failures;
     C2StreamSampleRateInfo::output sampleRateInfo(0u, bitStreamInfo[0]);
     C2StreamChannelCountInfo::output channelCountInfo(0u, bitStreamInfo[1]);
 
     std::vector<C2Param*> configParam{&sampleRateInfo, &channelCountInfo};
-    c2_status_t status =
-        component->config(configParam, C2_DONT_BLOCK, &failures);
+    c2_status_t status = component->config(configParam, C2_DONT_BLOCK, &failures);
     if (status == C2_OK && failures.size() == 0u) return true;
     return false;
 }
@@ -282,17 +270,15 @@
 // In decoder components, often the input parameters get updated upon
 // parsing the header of elementary stream. Client needs to collect this
 // information and reconfigure
-void getInputChannelInfo(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    Codec2AudioDecHidlTest::standardComp compName, int32_t* bitStreamInfo) {
+void getInputChannelInfo(const std::shared_ptr<android::Codec2Client::Component>& component,
+                         Codec2AudioDecHidlTest::standardComp compName, int32_t* bitStreamInfo) {
     // query nSampleRate and nChannels
     std::initializer_list<C2Param::Index> indices{
-        C2StreamSampleRateInfo::output::PARAM_TYPE,
-        C2StreamChannelCountInfo::output::PARAM_TYPE,
+            C2StreamSampleRateInfo::output::PARAM_TYPE,
+            C2StreamChannelCountInfo::output::PARAM_TYPE,
     };
     std::vector<std::unique_ptr<C2Param>> inParams;
-    c2_status_t status =
-        component->query({}, indices, C2_DONT_BLOCK, &inParams);
+    c2_status_t status = component->query({}, indices, C2_DONT_BLOCK, &inParams);
     if (status != C2_OK && inParams.size() == 0) {
         ALOGE("Query media type failed => %d", status);
         ASSERT_TRUE(false);
@@ -327,8 +313,8 @@
 #define STREAM_COUNT 2
 
 // LookUpTable of clips and metadata for component testing
-void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
-                        char* info, size_t streamIndex = 0) {
+void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL, char* info,
+                        size_t streamIndex = 0) {
     struct CompToURL {
         Codec2AudioDecHidlTest::standardComp comp;
         const char mURL[STREAM_COUNT][512];
@@ -337,52 +323,47 @@
     ASSERT_TRUE(streamIndex < STREAM_COUNT);
 
     static const CompToURL kCompToURL[] = {
-        {Codec2AudioDecHidlTest::standardComp::xaac,
-         {"bbb_aac_stereo_128kbps_48000hz.aac",
-          "bbb_aac_stereo_128kbps_48000hz.aac"},
-         {"bbb_aac_stereo_128kbps_48000hz.info",
-          "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
-        {Codec2AudioDecHidlTest::standardComp::mp3,
-         {"bbb_mp3_stereo_192kbps_48000hz.mp3",
-          "bbb_mp3_stereo_192kbps_48000hz.mp3"},
-         {"bbb_mp3_stereo_192kbps_48000hz.info",
-          "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
-        {Codec2AudioDecHidlTest::standardComp::aac,
-         {"bbb_aac_stereo_128kbps_48000hz.aac",
-          "bbb_aac_stereo_128kbps_48000hz.aac"},
-         {"bbb_aac_stereo_128kbps_48000hz.info",
-          "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
-        {Codec2AudioDecHidlTest::standardComp::amrnb,
-         {"sine_amrnb_1ch_12kbps_8000hz.amrnb",
-          "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
-         {"sine_amrnb_1ch_12kbps_8000hz.info",
-          "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
-        {Codec2AudioDecHidlTest::standardComp::amrwb,
-         {"bbb_amrwb_1ch_14kbps_16000hz.amrwb",
-          "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
-         {"bbb_amrwb_1ch_14kbps_16000hz.info",
-          "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
-        {Codec2AudioDecHidlTest::standardComp::vorbis,
-         {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
-         {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::opus,
-         {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
-         {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::g711alaw,
-         {"bbb_g711alaw_1ch_8khz.raw", ""},
-         {"bbb_g711alaw_1ch_8khz.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::g711mlaw,
-         {"bbb_g711mulaw_1ch_8khz.raw", ""},
-         {"bbb_g711mulaw_1ch_8khz.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::gsm,
-         {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
-         {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::raw,
-         {"bbb_raw_1ch_8khz_s32le.raw", ""},
-         {"bbb_raw_1ch_8khz_s32le.info", ""}},
-        {Codec2AudioDecHidlTest::standardComp::flac,
-         {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
-         {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::xaac,
+             {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
+             {"bbb_aac_stereo_128kbps_48000hz.info",
+              "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
+            {Codec2AudioDecHidlTest::standardComp::mp3,
+             {"bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.mp3"},
+             {"bbb_mp3_stereo_192kbps_48000hz.info",
+              "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
+            {Codec2AudioDecHidlTest::standardComp::aac,
+             {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
+             {"bbb_aac_stereo_128kbps_48000hz.info",
+              "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
+            {Codec2AudioDecHidlTest::standardComp::amrnb,
+             {"sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
+             {"sine_amrnb_1ch_12kbps_8000hz.info",
+              "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
+            {Codec2AudioDecHidlTest::standardComp::amrwb,
+             {"bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
+             {"bbb_amrwb_1ch_14kbps_16000hz.info",
+              "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
+            {Codec2AudioDecHidlTest::standardComp::vorbis,
+             {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
+             {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::opus,
+             {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
+             {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::g711alaw,
+             {"bbb_g711alaw_1ch_8khz.raw", ""},
+             {"bbb_g711alaw_1ch_8khz.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::g711mlaw,
+             {"bbb_g711mulaw_1ch_8khz.raw", ""},
+             {"bbb_g711mulaw_1ch_8khz.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::gsm,
+             {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
+             {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::raw,
+             {"bbb_raw_1ch_8khz_s32le.raw", ""},
+             {"bbb_raw_1ch_8khz_s32le.info", ""}},
+            {Codec2AudioDecHidlTest::standardComp::flac,
+             {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
+             {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -395,13 +376,11 @@
 }
 
 void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
-                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::mutex& queueLock, std::condition_variable& queueCondition,
                    std::list<std::unique_ptr<C2Work>>& workQueue,
-                   std::list<uint64_t>& flushedIndices,
-                   std::shared_ptr<C2BlockPool>& linearPool,
-                   std::ifstream& eleStream,
-                   android::Vector<FrameInfo>* Info,
-                   int offset, int range, bool signalEOS = true) {
+                   std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+                   std::ifstream& eleStream, android::Vector<FrameInfo>* Info, int offset,
+                   int range, bool signalEOS = true) {
     typedef std::unique_lock<std::mutex> ULock;
     int frameID = offset;
     int maxRetry = 0;
@@ -425,8 +404,7 @@
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
         if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1);
-        if (signalEOS && ((frameID == (int)Info->size() - 1) ||
-                          (frameID == (offset + range - 1))))
+        if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
         work->input.flags = (C2FrameData::flags_t)flags;
@@ -447,9 +425,8 @@
         if (size) {
             std::shared_ptr<C2LinearBlock> block;
             ASSERT_EQ(C2_OK,
-                    linearPool->fetchLinearBlock(
-                        size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
-                        &block));
+                      linearPool->fetchLinearBlock(
+                              size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
             ASSERT_TRUE(block);
 
             // Write View
@@ -481,65 +458,80 @@
     }
 }
 
-TEST_F(Codec2AudioDecHidlTest, validateCompName) {
-    if (mDisableTest) return;
+void Codec2AudioDecHidlTestBase::validateTimestampList(int32_t* bitStreamInfo) {
+    uint32_t samplesReceived = 0;
+    // Update SampleRate and ChannelCount
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+    int32_t nSampleRate = bitStreamInfo[0];
+    int32_t nChannels = bitStreamInfo[1];
+    std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
+    auto itOut = oBufferMetaData.begin();
+    EXPECT_EQ(*itIn, itOut->timestampUs);
+    uint64_t expectedTimeStamp = *itIn;
+    while (itOut != oBufferMetaData.end()) {
+        EXPECT_EQ(expectedTimeStamp, itOut->timestampUs);
+        if (expectedTimeStamp != itOut->timestampUs) break;
+        // buffer samples = ((total bytes) / (ac * (bits per sample / 8))
+        samplesReceived += ((itOut->rangeLength) / (nChannels * 2));
+        expectedTimeStamp = samplesReceived * 1000000ll / nSampleRate;
+        itOut++;
+    }
+    itIn = mTimestampUslist.end();
+    --itIn;
+    EXPECT_GT(expectedTimeStamp, *itIn);
+    oBufferMetaData.clear();
+    mTimestampUslist.clear();
+}
+
+TEST_P(Codec2AudioDecHidlTest, validateCompName) {
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ALOGV("Checks if the given component is a valid audio component");
     validateComponent(mComponent, mCompName, mDisableTest);
     ASSERT_EQ(mDisableTest, false);
 }
 
-TEST_F(Codec2AudioDecHidlTest, configComp) {
+TEST_P(Codec2AudioDecHidlTest, configComp) {
     description("Tests component specific configuration");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ASSERT_EQ(mComponent->start(), C2_OK);
     int32_t bitStreamInfo[2] = {0};
-    ASSERT_NO_FATAL_FAILURE(
-        getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+    ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
     setupConfigParam(mComponent, bitStreamInfo);
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
 class Codec2AudioDecDecodeTest
-    : public Codec2AudioDecHidlTest,
-      public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
+    : public Codec2AudioDecHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
 };
 
 TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
     description("Decodes input file");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    uint32_t streamIndex = GetParam().first;
-    bool signalEOS = GetParam().second;
+    uint32_t streamIndex = std::stoi(std::get<2>(GetParam()));
+    ;
+    bool signalEOS = !std::get<3>(GetParam()).compare("true");
     mTimestampDevTest = true;
     char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
+    android::Vector<FrameInfo> Info;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info, streamIndex);
-    if (!strcmp(mURL, gEnv->getRes().c_str())) {
-        ALOGV("EMPTY INPUT gEnv->getRes().c_str() %s mURL  %s ",
-              gEnv->getRes().c_str(), mURL);
+    if (!strcmp(mURL, sResourceDir.c_str())) {
+        ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL  %s ", sResourceDir.c_str(), mURL);
         return;
     }
 
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true);
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        bool codecConfig =
-            ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0;
-        if (mTimestampDevTest && !codecConfig)
-            mTimestampUslist.push_back(timestamp);
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
+
     // Reset total no of frames received
     mFramesReceived = 0;
     mTimestampUs = 0;
@@ -547,13 +539,8 @@
     if (mCompName == raw) {
         bitStreamInfo[0] = 8000;
         bitStreamInfo[1] = 1;
-    } else if (mCompName == g711alaw || mCompName == g711mlaw) {
-        // g711 test data is all 1-channel and has no embedded config info.
-        bitStreamInfo[0] = 8000;
-        bitStreamInfo[1] = 1;
     } else {
-        ASSERT_NO_FATAL_FAILURE(
-            getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
     }
     if (!setupConfigParam(mComponent, bitStreamInfo)) {
         std::cout << "[   WARN   ] Test Skipped \n";
@@ -561,101 +548,60 @@
     }
     ASSERT_EQ(mComponent->start(), C2_OK);
     ALOGV("mURL : %s", mURL);
+    std::ifstream eleStream;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, (int)Info.size(), signalEOS));
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          (int)Info.size(), signalEOS));
 
     // If EOS is not sent, sending empty input with EOS flag
     size_t infoSize = Info.size();
     if (!signalEOS) {
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
-        ASSERT_NO_FATAL_FAILURE(
-            testInputBuffer(mComponent, mQueueLock, mWorkQueue,
-                            C2FrameData::FLAG_END_OF_STREAM, false));
+        ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
         infoSize += 1;
     }
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     eleStream.close();
     if (mFramesReceived != infoSize) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGE("framesReceived : %d inputFrames : %zu", mFramesReceived,
-              infoSize);
+        ALOGE("framesReceived : %d inputFrames : %zu", mFramesReceived, infoSize);
         ASSERT_TRUE(false);
     }
     ASSERT_EQ(mEos, true);
+
     if (mTimestampDevTest) {
-        uint64_t expTs;
-        uint32_t samplesReceived = 0;
-        // Update SampleRate and ChannelCount
-        ASSERT_NO_FATAL_FAILURE(
-            getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
-        int nSampleRate = bitStreamInfo[0];
-        int nChannels = bitStreamInfo[1];
-        std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
-        android::List<outputMetaData>::iterator itOut = oBufferMetaData.begin();
-        EXPECT_EQ(*itIn, itOut->timestampUs);
-        expTs = *itIn;
-        while (itOut != oBufferMetaData.end()) {
-            EXPECT_EQ(expTs, itOut->timestampUs);
-            if (expTs != itOut->timestampUs) break;
-            // buffer samples = ((total bytes) / (ac * (bits per sample / 8))
-            samplesReceived += ((itOut->rangeLength) / (nChannels * 2));
-            expTs = samplesReceived * 1000000ll / nSampleRate;
-            itOut++;
-        }
-        itIn = mTimestampUslist.end();
-        --itIn;
-        EXPECT_GT(expTs, *itIn);
-        oBufferMetaData.clear();
-        mTimestampUslist.clear();
+        validateTimestampList(bitStreamInfo);
     }
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
-// DecodeTest with StreamIndex and EOS / No EOS
-INSTANTIATE_TEST_CASE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
-                        ::testing::Values(std::make_pair(0, false),
-                                          std::make_pair(0, true),
-                                          std::make_pair(1, false),
-                                          std::make_pair(1, true)));
 
 // thumbnail test
-TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
+TEST_P(Codec2AudioDecHidlTest, ThumbnailTest) {
     description("Test Request for thumbnail");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
+    android::Vector<FrameInfo> Info;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true);
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
+
     int32_t bitStreamInfo[2] = {0};
     if (mCompName == raw) {
         bitStreamInfo[0] = 8000;
         bitStreamInfo[1] = 1;
     } else {
-        ASSERT_NO_FATAL_FAILURE(
-            getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
     }
     if (!setupConfigParam(mComponent, bitStreamInfo)) {
         std::cout << "[   WARN   ] Test Skipped \n";
@@ -667,28 +613,30 @@
     // request EOS for thumbnail
     // signal EOS flag with last frame
     size_t i = -1;
+    uint32_t flags;
     do {
         i++;
         flags = 0;
         if (Info[i].flags) flags = 1u << (Info[i].flags - 1);
 
     } while (!(flags & SYNC_FRAME));
+    std::ifstream eleStream;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, i + 1));
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          i + 1));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     eleStream.close();
     EXPECT_GE(mFramesReceived, 1U);
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-TEST_F(Codec2AudioDecHidlTest, EOSTest) {
+TEST_P(Codec2AudioDecHidlTest, EOSTest) {
     description("Test empty input buffer with EOS flag");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     typedef std::unique_lock<std::mutex> ULock;
     ASSERT_EQ(mComponent->start(), C2_OK);
     std::unique_ptr<C2Work> work;
@@ -724,88 +672,65 @@
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-TEST_F(Codec2AudioDecHidlTest, FlushTest) {
+TEST_P(Codec2AudioDecHidlTest, FlushTest) {
     description("Tests Flush calls");
-    if (mDisableTest) return;
-    typedef std::unique_lock<std::mutex> ULock;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
+    android::Vector<FrameInfo> Info;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true);
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
-    mFlushedIndices.clear();
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
+
     int32_t bitStreamInfo[2] = {0};
     if (mCompName == raw) {
         bitStreamInfo[0] = 8000;
         bitStreamInfo[1] = 1;
     } else {
-        ASSERT_NO_FATAL_FAILURE(
-            getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
     }
     if (!setupConfigParam(mComponent, bitStreamInfo)) {
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
     ASSERT_EQ(mComponent->start(), C2_OK);
-    ALOGV("mURL : %s", mURL);
-    eleStream.open(mURL, std::ifstream::binary);
-    ASSERT_EQ(eleStream.is_open(), true);
-    // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
-    // frame after this so that the below section can be covered for all
-    // components
-    uint32_t numFramesFlushed = 128;
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, numFramesFlushed, false));
     // flush
     std::list<std::unique_ptr<C2Work>> flushedWork;
-    c2_status_t err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    uint64_t frameIndex;
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+
+    ALOGV("mURL : %s", mURL);
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+    // Decode 30 frames and flush.
+    uint32_t numFramesFlushed = FLUSH_INTERVAL;
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          numFramesFlushed, false));
+    // flush
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
+    ASSERT_NO_FATAL_FAILURE(
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+
     // Seek to next key frame and start decoding till the end
     mFlushedIndices.clear();
     int index = numFramesFlushed;
     bool keyFrame = false;
-    flags = 0;
+    uint32_t flags = 0;
     while (index < (int)Info.size()) {
         if (Info[index].flags) flags = 1u << (Info[index].flags - 1);
         if ((flags & SYNC_FRAME) == SYNC_FRAME) {
@@ -817,49 +742,32 @@
         index++;
     }
     if (keyFrame) {
-        ASSERT_NO_FATAL_FAILURE(
-            decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                          mFlushedIndices, mLinearPool, eleStream, &Info, index,
-                          (int)Info.size() - index));
+        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, &Info, index,
+                                              (int)Info.size() - index));
     }
     eleStream.close();
-    err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    ASSERT_EQ(mFlushedIndices.empty(), true);
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    // TODO: (b/154671521)
+    // Add assert for mWorkResult
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
+TEST_P(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
     description("Decode with multiple empty input frames");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     char mURL[512], info[512];
     std::ifstream eleStream, eleInfo;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
     eleInfo.open(info);
@@ -874,15 +782,16 @@
     // and empty input frames at an interval of 5 frames.
     while (1) {
         if (!(frameId % 5)) {
-            if (!(frameId % 20)) flags = 32;
-            else flags = 0;
+            if (!(frameId % 20))
+                flags = 32;
+            else
+                flags = 0;
             bytesCount = 0;
         } else {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
             eleInfo >> timestamp;
-            codecConfig = flags ?
-                ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
         }
         Info.push_back({bytesCount, flags, timestamp});
         frameId++;
@@ -893,8 +802,7 @@
         bitStreamInfo[0] = 8000;
         bitStreamInfo[1] = 1;
     } else {
-        ASSERT_NO_FATAL_FAILURE(
-            getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
     }
     if (!setupConfigParam(mComponent, bitStreamInfo)) {
         std::cout << "[   WARN   ] Test Skipped \n";
@@ -904,40 +812,171 @@
     ALOGV("mURL : %s", mURL);
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          (int)Info.size()));
 
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     if (!mEos) {
         ALOGV("Waiting for input consumption");
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     }
 
     eleStream.close();
     if (mFramesReceived != Info.size()) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
-              Info.size());
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size());
         ASSERT_TRUE(false);
     }
 
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+class Codec2AudioDecCsdInputTests
+    : public Codec2AudioDecHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+// Test the codecs for the following
+// start - csd - data… - (with/without)flush - data… - flush - data…
+TEST_P(Codec2AudioDecCsdInputTests, CSDFlushTest) {
+    description("Tests codecs for flush at different states");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+
+    char mURL[512], info[512];
+    android::Vector<FrameInfo> Info;
+
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
+    GetURLForComponent(mCompName, mURL, info);
+    if (!strcmp(mURL, sResourceDir.c_str())) {
+        ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL  %s ", sResourceDir.c_str(), mURL);
+        return;
+    }
+    ALOGV("mURL : %s", mURL);
+
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file";
+
+    int32_t bitStreamInfo[2] = {0};
+    if (mCompName == raw) {
+        bitStreamInfo[0] = 8000;
+        bitStreamInfo[1] = 1;
+    } else {
+        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+    }
+    if (!setupConfigParam(mComponent, bitStreamInfo)) {
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
+    }
+
+    ASSERT_EQ(mComponent->start(), C2_OK);
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+
+    bool signalEOS = false;
+    bool flushCsd = !std::get<2>(GetParam()).compare("true");
+    ALOGV("sending %d csd data ", numCsds);
+    int framesToDecode = numCsds;
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          framesToDecode, false));
+
+    c2_status_t err = C2_OK;
+    std::list<std::unique_ptr<C2Work>> flushedWork;
+    if (numCsds && flushCsd) {
+        // We wait for all the CSD buffers to get consumed.
+        // Once we have received all CSD work back, we call flush
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+        ASSERT_EQ(err, C2_OK);
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                               MAX_INPUT_BUFFERS - flushedWork.size());
+        ASSERT_NO_FATAL_FAILURE(
+                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+        oBufferMetaData.clear();
+    }
+
+    int offset = framesToDecode;
+    while (1) {
+        framesToDecode = c2_min(FLUSH_INTERVAL, (int)Info.size() - offset);
+        if (framesToDecode < FLUSH_INTERVAL) signalEOS = true;
+        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, &Info,
+                                              offset, framesToDecode, signalEOS));
+        offset += framesToDecode;
+        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+        ASSERT_EQ(err, C2_OK);
+        // blocking call to ensures application to Wait till remaining
+        // 'non-flushed' inputs are consumed
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                               MAX_INPUT_BUFFERS - flushedWork.size());
+        ASSERT_NO_FATAL_FAILURE(
+                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+        if (signalEOS || offset >= (int)Info.size()) {
+            break;
+        }
+    }
+    if (!signalEOS) {
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+    }
+    eleStream.close();
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+// DecodeTest with StreamIndex and EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
+                         testing::ValuesIn(kDecodeTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2AudioDecCsdInputTests,
+                         testing::ValuesIn(kCsdFlushTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        int status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
+    kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
+    for (auto params : kTestParameters) {
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "false"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "true"));
+
+        kCsdFlushTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "true"));
+        kCsdFlushTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
     }
-    return status;
+
+    // Set the resource directory based on command line args.
+    // Test will fail to set up if the argument is not set.
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+            sResourceDir = argv[i + 1];
+            break;
+        }
+    }
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
new file mode 100644
index 0000000..a22f8cf
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the"License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an"AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetAudioDecTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="vts_media_c2_v1_0_audio_dec_test" value="/data/local/tmp/vts_media_c2_v1_0_audio_dec_test" />
+
+        <!-- Files used for audio testing -->
+        <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
+        <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
+        <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz_multi_frame.info" />
+        <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
+        <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
+        <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" />
+        <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
+        <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
+        <option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
+        <option name="push-file" key="bbb_g711alaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.raw" />
+        <option name="push-file" key="bbb_g711mulaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.info" />
+        <option name="push-file" key="bbb_g711mulaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.raw" />
+        <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.info" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.info" />
+        <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
+        <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
+        <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
+        <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" />
+        <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
+        <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
+        <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
+        <option name="push-file" key="bbb_raw_1ch_8khz_s32le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.raw" />
+        <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.info" />
+        <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
+        <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
+        <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
+        <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" />
+
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_media_c2_v1_0_audio_dec_test" />
+        <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index 01baf7e..e3a4f68 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -19,73 +19,60 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <stdio.h>
-#include <fstream>
 #include <algorithm>
+#include <fstream>
 
-#include <codec2/hidl/client.h>
 #include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
 
 using android::C2AllocatorIon;
 
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_audio_hidl_test_common.h"
 #include "media_c2_hidl_test_common.h"
 
-class LinearBuffer : public C2Buffer {
-   public:
-    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
-        : C2Buffer(
-              {block->share(block->offset(), block->size(), ::C2Fence())}) {}
-};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+        kEncodeTestParameters;
 
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+static std::string sResourceDir = "";
+
+class LinearBuffer : public C2Buffer {
+  public:
+    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+};
 
 namespace {
 
-class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
-
-   public:
-    ::std::string getTestCaseInfo() const override {
-        return ::std::string() +
-                "Component: " + gEnv->getComponent().c_str() + " | " +
-                "Instance: " + gEnv->getInstance().c_str() + " | " +
-                "Res: " + gEnv->getRes().c_str();
-    }
-
+class Codec2AudioEncHidlTestBase : public ::testing::Test {
+  public:
     // google.codec2 Audio test setup
     virtual void SetUp() override {
-        Super::SetUp();
+        getParams();
         mDisableTest = false;
         ALOGV("Codec2AudioEncHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+                mInstanceName.c_str(),
+                !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener(
-            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
-                handleWorkDone(workItems);
-            }));
+        mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+            handleWorkDone(workItems);
+        }));
         ASSERT_NE(mListener, nullptr);
         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
             mWorkQueue.emplace_back(new C2Work);
         }
-        mClient->createComponent(gEnv->getComponent().c_str(), mListener,
-                                 &mComponent);
+        mClient->createComponent(mComponentName, mListener, &mComponent);
         ASSERT_NE(mComponent, nullptr);
 
-        std::shared_ptr<C2AllocatorStore> store =
-            android::GetCodec2PlatformAllocatorStore();
-        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
-                                       &mLinearAllocator),
-                 C2_OK);
-        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
-                                                          mBlockPoolId++);
+        std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
         ASSERT_NE(mLinearPool, nullptr);
 
         mCompName = unknown_comp;
@@ -94,19 +81,13 @@
             standardComp CompName;
         };
         const StringToName kStringToName[] = {
-            {"aac", aac},
-            {"flac", flac},
-            {"opus", opus},
-            {"amrnb", amrnb},
-            {"amrwb", amrwb},
+                {"aac", aac}, {"flac", flac}, {"opus", opus}, {"amrnb", amrnb}, {"amrwb", amrwb},
         };
-        const size_t kNumStringToName =
-            sizeof(kStringToName) / sizeof(kStringToName[0]);
+        const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
 
         // Find the component type
-        std::string comp = std::string(gEnv->getComponent());
         for (size_t i = 0; i < kNumStringToName; ++i) {
-            if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+            if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
                 mCompName = kStringToName[i].CompName;
                 break;
             }
@@ -114,6 +95,8 @@
         mEos = false;
         mCsd = false;
         mFramesReceived = 0;
+        mWorkResult = C2_OK;
+        mOutputSize = 0u;
         if (mCompName == unknown_comp) mDisableTest = true;
         if (mDisableTest) std::cout << "[   WARN   ] Test Disabled \n";
         getInputMaxBufSize();
@@ -125,15 +108,28 @@
             mComponent->release();
             mComponent = nullptr;
         }
-        Super::TearDown();
     }
+
+    // Get the test parameters from GetParam call.
+    virtual void getParams() {}
+
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
             if (!work->worklets.empty()) {
-                workDone(mComponent, work, mFlushedIndices, mQueueLock,
-                         mQueueCondition, mWorkQueue, mEos, mCsd,
-                         mFramesReceived);
+                mWorkResult |= work->result;
+                if (!work->worklets.front()->output.buffers.empty()) {
+                    mOutputSize += work->worklets.front()
+                                           ->output.buffers[0]
+                                           ->data()
+                                           .linearBlocks()
+                                           .front()
+                                           .map()
+                                           .get()
+                                           .capacity();
+                }
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+                         mEos, mCsd, mFramesReceived);
             }
         }
     }
@@ -146,12 +142,17 @@
         unknown_comp,
     };
 
+    std::string mInstanceName;
+    std::string mComponentName;
     bool mEos;
     bool mCsd;
     bool mDisableTest;
     standardComp mCompName;
+
+    int32_t mWorkResult;
     uint32_t mFramesReceived;
     int32_t mInputMaxBufSize;
+    uint64_t mOutputSize;
     std::list<uint64_t> mFlushedIndices;
 
     C2BlockPool::local_id_t mBlockPoolId;
@@ -166,7 +167,7 @@
     std::shared_ptr<android::Codec2Client::Listener> mListener;
     std::shared_ptr<android::Codec2Client::Component> mComponent;
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
@@ -175,9 +176,8 @@
     void getInputMaxBufSize() {
         int32_t bitStreamInfo[1] = {0};
         std::vector<std::unique_ptr<C2Param>> inParams;
-        c2_status_t status = mComponent->query(
-            {}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE}, C2_DONT_BLOCK,
-            &inParams);
+        c2_status_t status = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
+                                               C2_DONT_BLOCK, &inParams);
         if (status != C2_OK && inParams.size() == 0) {
             ALOGE("Query MaxBufferSizeInfo failed => %d", status);
             ASSERT_TRUE(false);
@@ -190,12 +190,19 @@
         }
         mInputMaxBufSize = bitStreamInfo[0];
     }
-
 };
 
-void validateComponent(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    Codec2AudioEncHidlTest::standardComp compName, bool& disableTest) {
+class Codec2AudioEncHidlTest
+    : public Codec2AudioEncHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+                       Codec2AudioEncHidlTest::standardComp compName, bool& disableTest) {
     // Validate its a C2 Component
     if (component->getName().find("c2") == std::string::npos) {
         ALOGE("Not a c2 component");
@@ -210,14 +217,12 @@
         return;
     }
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err =
-        component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
-                         C2_DONT_BLOCK, &queried);
+    c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK && queried.size() == 0) {
         ALOGE("Query media type failed => %d", c2err);
     } else {
-        std::string inputDomain =
-            ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+        std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
         if (inputDomain.find("audio/") == std::string::npos) {
             ALOGE("Expected Audio Component");
             disableTest = true;
@@ -235,20 +240,53 @@
 }
 
 // Set Default config param.
-bool setupConfigParam(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    int32_t nChannels, int32_t nSampleRate) {
+bool setupConfigParam(const std::shared_ptr<android::Codec2Client::Component>& component,
+                      int32_t nChannels, int32_t nSampleRate) {
     std::vector<std::unique_ptr<C2SettingResult>> failures;
     C2StreamSampleRateInfo::input sampleRateInfo(0u, nSampleRate);
     C2StreamChannelCountInfo::input channelCountInfo(0u, nChannels);
 
     std::vector<C2Param*> configParam{&sampleRateInfo, &channelCountInfo};
-    c2_status_t status =
-        component->config(configParam, C2_DONT_BLOCK, &failures);
+    c2_status_t status = component->config(configParam, C2_DONT_BLOCK, &failures);
     if (status == C2_OK && failures.size() == 0u) return true;
     return false;
 }
 
+// Get config params for a component
+bool getConfigParams(Codec2AudioEncHidlTest::standardComp compName, int32_t* nChannels,
+                     int32_t* nSampleRate, int32_t* samplesPerFrame) {
+    switch (compName) {
+        case Codec2AudioEncHidlTest::aac:
+            *nChannels = 2;
+            *nSampleRate = 48000;
+            *samplesPerFrame = 1024;
+            break;
+        case Codec2AudioEncHidlTest::flac:
+            *nChannels = 2;
+            *nSampleRate = 48000;
+            *samplesPerFrame = 1152;
+            break;
+        case Codec2AudioEncHidlTest::opus:
+            *nChannels = 2;
+            *nSampleRate = 48000;
+            *samplesPerFrame = 960;
+            break;
+        case Codec2AudioEncHidlTest::amrnb:
+            *nChannels = 1;
+            *nSampleRate = 8000;
+            *samplesPerFrame = 160;
+            break;
+        case Codec2AudioEncHidlTest::amrwb:
+            *nChannels = 1;
+            *nSampleRate = 16000;
+            *samplesPerFrame = 160;
+            break;
+        default:
+            return false;
+    }
+    return true;
+}
+
 // LookUpTable of clips and metadata for component testing
 void GetURLForComponent(Codec2AudioEncHidlTest::standardComp comp, char* mURL) {
     struct CompToURL {
@@ -256,16 +294,11 @@
         const char* mURL;
     };
     static const CompToURL kCompToURL[] = {
-        {Codec2AudioEncHidlTest::standardComp::aac,
-         "bbb_raw_2ch_48khz_s16le.raw"},
-        {Codec2AudioEncHidlTest::standardComp::amrnb,
-         "bbb_raw_1ch_8khz_s16le.raw"},
-        {Codec2AudioEncHidlTest::standardComp::amrwb,
-         "bbb_raw_1ch_16khz_s16le.raw"},
-        {Codec2AudioEncHidlTest::standardComp::flac,
-         "bbb_raw_2ch_48khz_s16le.raw"},
-        {Codec2AudioEncHidlTest::standardComp::opus,
-         "bbb_raw_2ch_48khz_s16le.raw"},
+            {Codec2AudioEncHidlTest::standardComp::aac, "bbb_raw_2ch_48khz_s16le.raw"},
+            {Codec2AudioEncHidlTest::standardComp::amrnb, "bbb_raw_1ch_8khz_s16le.raw"},
+            {Codec2AudioEncHidlTest::standardComp::amrwb, "bbb_raw_1ch_16khz_s16le.raw"},
+            {Codec2AudioEncHidlTest::standardComp::flac, "bbb_raw_2ch_48khz_s16le.raw"},
+            {Codec2AudioEncHidlTest::standardComp::opus, "bbb_raw_2ch_48khz_s16le.raw"},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -277,21 +310,18 @@
 }
 
 void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
-                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::mutex& queueLock, std::condition_variable& queueCondition,
                    std::list<std::unique_ptr<C2Work>>& workQueue,
-                   std::list<uint64_t>& flushedIndices,
-                   std::shared_ptr<C2BlockPool>& linearPool,
-                   std::ifstream& eleStream, uint32_t nFrames,
-                   int32_t samplesPerFrame, int32_t nChannels,
-                   int32_t nSampleRate, bool flushed = false,
+                   std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+                   std::ifstream& eleStream, uint32_t nFrames, int32_t samplesPerFrame,
+                   int32_t nChannels, int32_t nSampleRate, bool flushed = false,
                    bool signalEOS = true) {
     typedef std::unique_lock<std::mutex> ULock;
 
     uint32_t frameID = 0;
     uint32_t maxRetry = 0;
     int bytesCount = samplesPerFrame * nChannels * 2;
-    int32_t timestampIncr =
-        (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
+    int32_t timestampIncr = (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
     uint64_t timestamp = 0;
     while (1) {
         if (nFrames == 0) break;
@@ -311,8 +341,7 @@
         if (!work && (maxRetry >= MAX_RETRY)) {
             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
         }
-        if (signalEOS && (nFrames == 1))
-            flags |= C2FrameData::FLAG_END_OF_STREAM;
+        if (signalEOS && (nFrames == 1)) flags |= C2FrameData::FLAG_END_OF_STREAM;
         if (flushed) {
             flags |= SYNC_FRAME;
             flushed = false;
@@ -329,10 +358,9 @@
         eleStream.read(data, bytesCount);
         ASSERT_EQ(eleStream.gcount(), bytesCount);
         std::shared_ptr<C2LinearBlock> block;
-        ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
-                             bytesCount, {C2MemoryUsage::CPU_READ,
-                                          C2MemoryUsage::CPU_WRITE},
-                             &block));
+        ASSERT_EQ(C2_OK,
+                  linearPool->fetchLinearBlock(
+                          bytesCount, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
         ASSERT_TRUE(block);
         // Write View
         C2WriteView view = block->map().get();
@@ -364,59 +392,46 @@
     }
 }
 
-TEST_F(Codec2AudioEncHidlTest, validateCompName) {
-    if (mDisableTest) return;
+TEST_P(Codec2AudioEncHidlTest, validateCompName) {
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ALOGV("Checks if the given component is a valid audio component");
     validateComponent(mComponent, mCompName, mDisableTest);
     ASSERT_EQ(mDisableTest, false);
 }
 
 class Codec2AudioEncEncodeTest
-    : public Codec2AudioEncHidlTest,
-      public ::testing::WithParamInterface<std::pair<bool, int32_t>> {
+    : public Codec2AudioEncHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
 };
 
 TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
     ALOGV("EncodeTest");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     char mURL[512];
-    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL);
-    bool signalEOS = GetParam().first;
+    bool signalEOS = !std::get<2>(GetParam()).compare("true");
     // Ratio w.r.t to mInputMaxBufSize
-    int32_t inputMaxBufRatio = GetParam().second;
+    int32_t inputMaxBufRatio = std::stoi(std::get<3>(GetParam()));
 
-    // Setting default sampleRate
-    int32_t nChannels = 2;
-    int32_t nSampleRate = 44100;
-    switch (mCompName) {
-        case aac:
-            nChannels = 2;
-            nSampleRate = 48000;
-            break;
-        case flac:
-            nChannels = 2;
-            nSampleRate = 48000;
-            break;
-        case opus:
-            nChannels = 2;
-            nSampleRate = 48000;
-            break;
-        case amrnb:
-            nChannels = 1;
-            nSampleRate = 8000;
-            break;
-        case amrwb:
-            nChannels = 1;
-            nSampleRate = 16000;
-            break;
-        default:
-            ASSERT_TRUE(false);
+    int32_t nChannels;
+    int32_t nSampleRate;
+    int32_t samplesPerFrame;
+
+    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
+        std::cout << "Failed to get the config params for " << mCompName << " component\n";
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
     }
-    int32_t samplesPerFrame =
-        ((mInputMaxBufSize / inputMaxBufRatio) / (nChannels * 2));
-    ALOGV("signalEOS %d mInputMaxBufSize %d samplesPerFrame %d", signalEOS,
-          mInputMaxBufSize, samplesPerFrame);
+
+    samplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (nChannels * 2));
+    ALOGV("signalEOS %d mInputMaxBufSize %d samplesPerFrame %d", signalEOS, mInputMaxBufSize,
+          samplesPerFrame);
 
     if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
         std::cout << "[   WARN   ] Test Skipped \n";
@@ -428,26 +443,21 @@
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
     ALOGV("mURL : %s", mURL);
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mLinearPool, eleStream, numFrames,
-                      samplesPerFrame, nChannels, nSampleRate, false,
-                      signalEOS));
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(
+            mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices, mLinearPool,
+            eleStream, numFrames, samplesPerFrame, nChannels, nSampleRate, false, signalEOS));
 
     // If EOS is not sent, sending empty input with EOS flag
     if (!signalEOS) {
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
-        ASSERT_NO_FATAL_FAILURE(
-            testInputBuffer(mComponent, mQueueLock, mWorkQueue,
-                            C2FrameData::FLAG_END_OF_STREAM, false));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1);
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
         numFrames += 1;
     }
 
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     eleStream.close();
     if (mFramesReceived != numFrames) {
         ALOGE("Input buffer count and Output buffer count mismatch");
@@ -462,20 +472,12 @@
     }
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-// EncodeTest with EOS / No EOS and inputMaxBufRatio
-// inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
-INSTANTIATE_TEST_CASE_P(EncodeTest, Codec2AudioEncEncodeTest,
-                        ::testing::Values(std::make_pair(false, 1),
-                                          std::make_pair(false, 2),
-                                          std::make_pair(true, 1),
-                                          std::make_pair(true, 2)));
-
-
-TEST_F(Codec2AudioEncHidlTest, EOSTest) {
+TEST_P(Codec2AudioEncHidlTest, EOSTest) {
     description("Test empty input buffer with EOS flag");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ASSERT_EQ(mComponent->start(), C2_OK);
 
     typedef std::unique_lock<std::mutex> ULock;
@@ -511,50 +513,26 @@
     }
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-TEST_F(Codec2AudioEncHidlTest, FlushTest) {
+TEST_P(Codec2AudioEncHidlTest, FlushTest) {
     description("Test Request for flush");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    typedef std::unique_lock<std::mutex> ULock;
     char mURL[512];
-    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL);
 
-    // Setting default configuration
     mFlushedIndices.clear();
-    int32_t nChannels = 2;
-    int32_t nSampleRate = 44100;
-    int32_t samplesPerFrame = 1024;
-    switch (mCompName) {
-        case aac:
-            nChannels = 2;
-            nSampleRate = 48000;
-            samplesPerFrame = 1024;
-            break;
-        case flac:
-            nChannels = 2;
-            nSampleRate = 48000;
-            samplesPerFrame = 1152;
-            break;
-        case opus:
-            nChannels = 2;
-            nSampleRate = 48000;
-            samplesPerFrame = 960;
-            break;
-        case amrnb:
-            nChannels = 1;
-            nSampleRate = 8000;
-            samplesPerFrame = 160;
-            break;
-        case amrwb:
-            nChannels = 1;
-            nSampleRate = 16000;
-            samplesPerFrame = 160;
-            break;
-        default:
-            ASSERT_TRUE(false);
+    int32_t nChannels;
+    int32_t nSampleRate;
+    int32_t samplesPerFrame;
+
+    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
+        std::cout << "Failed to get the config params for " << mCompName << " component\n";
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
     }
 
     if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
@@ -568,83 +546,278 @@
     uint32_t numFrames = 128;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ALOGV("mURL : %s", mURL);
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mLinearPool, eleStream, numFramesFlushed,
-                      samplesPerFrame, nChannels, nSampleRate));
+    // flush
     std::list<std::unique_ptr<C2Work>> flushedWork;
-    c2_status_t err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    uint64_t frameIndex;
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    mFlushedIndices.clear();
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    ALOGV("mURL : %s", mURL);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, numFramesFlushed,
+                                          samplesPerFrame, nChannels, nSampleRate));
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mLinearPool, eleStream,
-                      numFrames - numFramesFlushed, samplesPerFrame,
-                      nChannels, nSampleRate, true));
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream,
+                                          numFrames - numFramesFlushed, samplesPerFrame, nChannels,
+                                          nSampleRate, true));
     eleStream.close();
-    err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    ASSERT_EQ(mFlushedIndices.empty(), true);
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    // TODO: (b/154671521)
+    // Add assert for mWorkResult
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+TEST_P(Codec2AudioEncHidlTest, MultiChannelCountTest) {
+    description("Encodes input file for different channel count");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mCompName, mURL);
+
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+    ALOGV("mURL : %s", mURL);
+
+    int32_t nSampleRate;
+    int32_t samplesPerFrame;
+    int32_t nChannels;
+    int32_t numFrames = 16;
+    int32_t maxChannelCount = 8;
+
+    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
+        std::cout << "Failed to get the config params for " << mCompName << " component\n";
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
+    }
+
+    uint64_t prevOutputSize = 0u;
+    uint32_t prevChannelCount = 0u;
+
+    // Looping through the maximum number of channel count supported by encoder
+    for (nChannels = 1; nChannels < maxChannelCount; nChannels++) {
+        ALOGV("Configuring %u encoder for channel count = %d", mCompName, nChannels);
+        if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
+            std::cout << "[   WARN   ] Test Skipped \n";
+            return;
+        }
+
+        std::vector<std::unique_ptr<C2Param>> inParams;
+        c2_status_t c2_status = mComponent->query({}, {C2StreamChannelCountInfo::input::PARAM_TYPE},
+                                                  C2_DONT_BLOCK, &inParams);
+        ASSERT_TRUE(!c2_status && inParams.size())
+                << "Query configured channelCount failed => %d" << c2_status;
+
+        size_t offset = sizeof(C2Param);
+        C2Param* param = inParams[0].get();
+        int32_t channelCount = *(int32_t*)((uint8_t*)param + offset);
+        if (channelCount != nChannels) {
+            std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels << "\n";
+            continue;
+        }
+
+        // To check if the input stream is sufficient to encode for the higher channel count
+        int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
+        if (eleStream.gcount() < bytesCount) {
+            std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels
+                      << " because of insufficient input data\n";
+            continue;
+        }
+
+        ASSERT_EQ(mComponent->start(), C2_OK);
+
+        ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, numFrames,
+                                              samplesPerFrame, nChannels, nSampleRate));
+
+        // mDisableTest will be set if buffer was not fetched properly.
+        // This may happen when config params is not proper but config succeeded
+        // In this cases, we skip encoding the input stream
+        if (mDisableTest) {
+            std::cout << "[   WARN   ] Test Disabled for ChannelCount " << nChannels << "\n";
+            ASSERT_EQ(mComponent->stop(), C2_OK);
+            return;
+        }
+
+        // blocking call to ensures application to Wait till all the inputs are consumed
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+        // Validate output size based on chosen ChannelCount
+        EXPECT_GE(mOutputSize, prevOutputSize);
+
+        prevChannelCount = nChannels;
+        prevOutputSize = mOutputSize;
+
+        if (mFramesReceived != numFrames) {
+            ALOGE("Input buffer count and Output buffer count mismatch");
+            ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
+            ASSERT_TRUE(false);
+        }
+        if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
+            ASSERT_TRUE(mCsd) << "CSD buffer missing";
+        }
+        ASSERT_TRUE(mEos);
+        ASSERT_EQ(mComponent->stop(), C2_OK);
+        mFramesReceived = 0;
+        mOutputSize = 0;
+        mEos = false;
+        mCsd = false;
+        eleStream.seekg(0, eleStream.beg);
+    }
+}
+
+TEST_P(Codec2AudioEncHidlTest, MultiSampleRateTest) {
+    description("Encodes input file for different SampleRate");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+
+    char mURL[512];
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mCompName, mURL);
+
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+    ALOGV("mURL : %s", mURL);
+
+    int32_t nSampleRate;
+    int32_t samplesPerFrame;
+    int32_t nChannels;
+    int32_t numFrames = 16;
+
+    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
+        std::cout << "Failed to get the config params for " << mCompName << " component\n";
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
+    }
+
+    int32_t sampleRateValues[] = {1000, 8000, 16000, 24000, 48000, 96000, 192000};
+
+    uint64_t prevOutputSize = 0u;
+    uint32_t prevSampleRate = 0u;
+
+    for (int32_t nSampleRate : sampleRateValues) {
+        ALOGV("Configuring %u encoder for SampleRate = %d", mCompName, nSampleRate);
+        if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
+            std::cout << "[   WARN   ] Test Skipped \n";
+            return;
+        }
+
+        std::vector<std::unique_ptr<C2Param>> inParams;
+        c2_status_t c2_status = mComponent->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
+                                                  C2_DONT_BLOCK, &inParams);
+
+        ASSERT_TRUE(!c2_status && inParams.size())
+                << "Query configured SampleRate failed => %d" << c2_status;
+        size_t offset = sizeof(C2Param);
+        C2Param* param = inParams[0].get();
+        int32_t configuredSampleRate = *(int32_t*)((uint8_t*)param + offset);
+
+        if (configuredSampleRate != nSampleRate) {
+            std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate << "\n";
+            continue;
+        }
+
+        // To check if the input stream is sufficient to encode for the higher SampleRate
+        int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
+        if (eleStream.gcount() < bytesCount) {
+            std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate
+                      << " because of insufficient input data\n";
+            continue;
+        }
+
+        ASSERT_EQ(mComponent->start(), C2_OK);
+
+        ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, numFrames,
+                                              samplesPerFrame, nChannels, nSampleRate));
+
+        // mDisableTest will be set if buffer was not fetched properly.
+        // This may happen when config params is not proper but config succeeded
+        // In this case, we skip encoding the input stream
+        if (mDisableTest) {
+            std::cout << "[   WARN   ] Test Disabled for SampleRate" << nSampleRate << "\n";
+            ASSERT_EQ(mComponent->stop(), C2_OK);
+            return;
+        }
+
+        // blocking call to ensures application to Wait till all the inputs are consumed
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+        // Validate output size based on chosen samplerate
+        if (prevSampleRate >= nSampleRate) {
+            EXPECT_LE(mOutputSize, prevOutputSize);
+        } else {
+            EXPECT_GT(mOutputSize, prevOutputSize);
+        }
+        prevSampleRate = nSampleRate;
+        prevOutputSize = mOutputSize;
+
+        if (mFramesReceived != numFrames) {
+            ALOGE("Input buffer count and Output buffer count mismatch");
+            ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
+            ASSERT_TRUE(false);
+        }
+        if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
+            ASSERT_TRUE(mCsd) << "CSD buffer missing";
+        }
+        ASSERT_TRUE(mEos);
+        ASSERT_EQ(mComponent->stop(), C2_OK);
+        mFramesReceived = 0;
+        mOutputSize = 0;
+        mEos = false;
+        mCsd = false;
+        eleStream.seekg(0, eleStream.beg);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+// EncodeTest with EOS / No EOS and inputMaxBufRatio
+// inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
+INSTANTIATE_TEST_SUITE_P(EncodeTest, Codec2AudioEncEncodeTest,
+                         testing::ValuesIn(kEncodeTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        int status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
+    kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
+    for (auto params : kTestParameters) {
+        kEncodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "false", "1"));
+        kEncodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "false", "2"));
+        kEncodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "true", "1"));
+        kEncodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "true", "2"));
     }
-    return status;
+
+    // Set the resource directory based on command line args.
+    // Test will fail to set up if the argument is not set.
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+            sResourceDir = argv[i + 1];
+            break;
+        }
+    }
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml
new file mode 100644
index 0000000..2e37111
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the"License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an"AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetAudioEncTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="vts_media_c2_v1_0_audio_enc_test" value="/data/local/tmp/vts_media_c2_v1_0_audio_enc_test" />
+
+        <!-- Files used for audio testing -->
+        <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+        <option name="push-file" key="bbb_raw_1ch_8khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s16le.raw" />
+        <option name="push-file" key="bbb_raw_1ch_16khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_16khz_s16le.raw" />
+        <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+        <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_media_c2_v1_0_audio_enc_test" />
+        <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h
deleted file mode 100644
index 4d773ce..0000000
--- a/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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 MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
-#define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
-
-
-#endif  // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/functional/common/Android.bp b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
index a011ba3..f9ec5ae 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
@@ -24,10 +24,14 @@
     ],
 
     static_libs: [
+        "libgtest",
         "VtsHalMediaC2V1_0CommonUtil",
     ],
 
     shared_libs: [
         "libcodec2_client",
     ],
+    test_suites: [
+        "vts",
+    ],
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/common/README.md b/media/codec2/hidl/1.0/vts/functional/common/README.md
index f2f579c..ac510c5 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/README.md
+++ b/media/codec2/hidl/1.0/vts/functional/common/README.md
@@ -3,34 +3,22 @@
 ## master :
 Functionality of master is to enumerate all the Codec2 components available in C2 media service.
 
-usage: `VtsHalMediaC2V1_0TargetMasterTest -I default`
+usage: `atest VtsHalMediaC2V1_0TargetMasterTest`
 
 ## component :
 Functionality of component test is to validate common functionality across all the Codec2 components available in C2 media service. For a standard C2 component, these tests are expected to pass.
 
-usage: `VtsHalMediaC2V1_0TargetComponentTest -I software -C <comp name>`
-
-example: `VtsHalMediaC2V1_0TargetComponentTest -I software -C c2.android.vorbis.decoder`
+usage: `atest VtsHalMediaC2V1_0TargetComponentTest`
 
 ## audio :
 Functionality of audio test is to validate audio specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
 
-usage: `VtsHalMediaC2V1_0TargetAudioDecTest -I default -C <comp name> -P <path to resource files>`
+usage: `atest VtsHalMediaC2V1_0TargetAudioDecTest`
 
-usage: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C <comp name> -P <path to resource files>`
-
-example: `VtsHalMediaC2V1_0TargetAudioDecTest -I software -C c2.android.flac.decoder -P /data/local/tmp/media/`
-
-example: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C c2.android.opus.encoder -P /data/local/tmp/media/`
+usage: `atest VtsHalMediaC2V1_0TargetAudioEncTest`
 
 ## video :
 Functionality of video test is to validate video specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
 
-usage: `VtsHalMediaC2V1_0TargetVideoDecTest -I default -C <comp name> -P <path to resource files>`
-
-usage: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C <comp name> -P <path to resource files>`
-
-example: `VtsHalMediaC2V1_0TargetVideoDecTest -I software -C c2.android.avc.decoder -P /data/local/tmp/media/`
-
-example: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C c2.android.vp9.encoder -P /data/local/tmp/media/`
-
+usage: `atest VtsHalMediaC2V1_0TargetVideoDecTest`
+usage: `atest VtsHalMediaC2V1_0TargetVideoEncTest`
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index d73b731..0251ec2 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -20,11 +20,12 @@
 
 #include "media_c2_hidl_test_common.h"
 
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+
 // Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
-void testInputBuffer(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
-    uint32_t flags, bool isNullBuffer) {
+void testInputBuffer(const std::shared_ptr<android::Codec2Client::Component>& component,
+                     std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+                     uint32_t flags, bool isNullBuffer) {
     std::unique_ptr<C2Work> work;
     {
         typedef std::unique_lock<std::mutex> ULock;
@@ -54,10 +55,8 @@
 }
 
 // Wait for all the inputs to be consumed by the plugin.
-void waitOnInputConsumption(std::mutex& queueLock,
-                            std::condition_variable& queueCondition,
-                            std::list<std::unique_ptr<C2Work>>& workQueue,
-                            size_t bufferCount) {
+void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition,
+                            std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount) {
     typedef std::unique_lock<std::mutex> ULock;
     uint32_t queueSize;
     uint32_t maxRetry = 0;
@@ -78,29 +77,28 @@
 }
 
 // process onWorkDone received by Listener
-void workDone(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
-    std::mutex& queueLock, std::condition_variable& queueCondition,
-    std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
-    uint32_t& framesReceived) {
+void workDone(const std::shared_ptr<android::Codec2Client::Component>& component,
+              std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+              std::mutex& queueLock, std::condition_variable& queueCondition,
+              std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+              uint32_t& framesReceived) {
     // handle configuration changes in work done
     if (work->worklets.front()->output.configUpdate.size() != 0) {
         ALOGV("Config Update");
         std::vector<std::unique_ptr<C2Param>> updates =
-            std::move(work->worklets.front()->output.configUpdate);
+                std::move(work->worklets.front()->output.configUpdate);
         std::vector<C2Param*> configParam;
         std::vector<std::unique_ptr<C2SettingResult>> failures;
         for (size_t i = 0; i < updates.size(); ++i) {
             C2Param* param = updates[i].get();
             if (param->index() == C2StreamInitDataInfo::output::PARAM_TYPE) {
-                csd = true;
-            } else if ((param->index() ==
-                        C2StreamSampleRateInfo::output::PARAM_TYPE) ||
-                       (param->index() ==
-                        C2StreamChannelCountInfo::output::PARAM_TYPE) ||
-                       (param->index() ==
-                        C2StreamPictureSizeInfo::output::PARAM_TYPE)) {
+                C2StreamInitDataInfo::output* csdBuffer =
+                        (C2StreamInitDataInfo::output*)(param);
+                size_t csdSize = csdBuffer->flexCount();
+                if (csdSize > 0) csd = true;
+            } else if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) ||
+                       (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE) ||
+                       (param->index() == C2StreamPictureSizeInfo::output::PARAM_TYPE)) {
                 configParam.push_back(param);
             }
         }
@@ -109,8 +107,7 @@
     }
     if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
         framesReceived++;
-        eos = (work->worklets.front()->output.flags &
-               C2FrameData::FLAG_END_OF_STREAM) != 0;
+        eos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
         auto frameIndexIt = std::find(flushedIndices.begin(), flushedIndices.end(),
                                       work->input.ordinal.frameIndex.peeku());
         ALOGV("WorkDone: frameID received %d",
@@ -121,7 +118,8 @@
             typedef std::unique_lock<std::mutex> ULock;
             ULock l(queueLock);
             workQueue.push_back(std::move(work));
-            if (!flushedIndices.empty()) {
+            if (!flushedIndices.empty() &&
+                (frameIndexIt != flushedIndices.end())) {
                 flushedIndices.erase(frameIndexIt);
             }
             queueCondition.notify_all();
@@ -136,3 +134,86 @@
 
     return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
 }
+
+// Return all test parameters, a list of tuple of <instance, component>
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters() {
+    return getTestParameters(C2Component::DOMAIN_OTHER, C2Component::KIND_OTHER);
+}
+
+// Return all test parameters, a list of tuple of <instance, component> with matching domain and
+// kind.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters(
+        C2Component::domain_t domain, C2Component::kind_t kind) {
+    static std::vector<std::tuple<std::string, std::string>> parameters;
+
+    auto instances = android::Codec2Client::GetServiceNames();
+    for (std::string instance : instances) {
+        std::shared_ptr<android::Codec2Client> client =
+                android::Codec2Client::CreateFromService(instance.c_str());
+        std::vector<C2Component::Traits> components = client->listComponents();
+        for (C2Component::Traits traits : components) {
+            if (instance.compare(traits.owner)) continue;
+            if (domain != C2Component::DOMAIN_OTHER &&
+                (traits.domain != domain || traits.kind != kind)) {
+                continue;
+            }
+
+            parameters.push_back(std::make_tuple(instance, traits.name));
+        }
+    }
+
+    return parameters;
+}
+
+// Populate Info vector and return number of CSDs
+int32_t populateInfoVector(std::string info, android::Vector<FrameInfo>* frameInfo,
+                           bool timestampDevTest, std::list<uint64_t>* timestampUslist) {
+    std::ifstream eleInfo;
+    eleInfo.open(info);
+    if (!eleInfo.is_open()) {
+        ALOGE("Can't open info file");
+        return -1;
+    }
+    int32_t numCsds = 0;
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) break;
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        bool codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+        if (codecConfig) numCsds++;
+        bool nonDisplayFrame = ((flags & FLAG_NON_DISPLAY_FRAME) != 0);
+        if (timestampDevTest && !codecConfig && !nonDisplayFrame) {
+            timestampUslist->push_back(timestamp);
+        }
+        frameInfo->push_back({bytesCount, flags, timestamp});
+    }
+    ALOGV("numCsds : %d", numCsds);
+    eleInfo.close();
+    return numCsds;
+}
+
+void verifyFlushOutput(std::list<std::unique_ptr<C2Work>>& flushedWork,
+                       std::list<std::unique_ptr<C2Work>>& workQueue,
+                       std::list<uint64_t>& flushedIndices, std::mutex& queueLock) {
+    // Update mFlushedIndices based on the index received from flush()
+    typedef std::unique_lock<std::mutex> ULock;
+    uint64_t frameIndex;
+    ULock l(queueLock);
+    for (std::unique_ptr<C2Work>& work : flushedWork) {
+        ASSERT_NE(work, nullptr);
+        frameIndex = work->input.ordinal.frameIndex.peeku();
+        std::list<uint64_t>::iterator frameIndexIt =
+                std::find(flushedIndices.begin(), flushedIndices.end(), frameIndex);
+        if (!flushedIndices.empty() && (frameIndexIt != flushedIndices.end())) {
+            flushedIndices.erase(frameIndexIt);
+            work->input.buffers.clear();
+            work->worklets.clear();
+            workQueue.push_back(std::move(work));
+        }
+    }
+    ASSERT_EQ(flushedIndices.empty(), true);
+    flushedWork.clear();
+}
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index db59e54..50e3ac5 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -17,45 +17,48 @@
 #ifndef MEDIA_C2_HIDL_TEST_COMMON_H
 #define MEDIA_C2_HIDL_TEST_COMMON_H
 
-#include <codec2/hidl/client.h>
-
-#include <android/hardware/media/c2/1.0/types.h>
-
 #include <C2Component.h>
 #include <C2Config.h>
+
+#include <codec2/hidl/client.h>
 #include <getopt.h>
+#include <gtest/gtest.h>
 #include <hidl/HidlSupport.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/Mutexed.h>
+#include <chrono>
+#include <fstream>
 
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
-
-using ::android::Mutexed;
-using ::android::hardware::Void;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-
-#include <VtsHalHidlTargetTestEnvBase.h>
-
+#define FLAG_NON_DISPLAY_FRAME (1 << 4)
 #define MAX_RETRY 20
 #define TIME_OUT 400ms
 #define MAX_INPUT_BUFFERS 8
+#define FLUSH_INTERVAL 30
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using namespace ::std::chrono;
+
+static std::vector<std::tuple<std::string, std::string>> kTestParameters;
+
+struct FrameInfo {
+    int bytesCount;
+    uint32_t flags;
+    int64_t timestamp;
+};
 
 /*
  * Handle Callback functions onWorkDone(), onTripped(),
  * onError(), onDeath(), onFramesRendered()
  */
 struct CodecListener : public android::Codec2Client::Listener {
-   public:
+  public:
     CodecListener(
-        const std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> fn =
-            nullptr)
+            const std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> fn = nullptr)
         : callBack(fn) {}
-    virtual void onWorkDone(
-        const std::weak_ptr<android::Codec2Client::Component>& comp,
-        std::list<std::unique_ptr<C2Work>>& workItems) override {
+    virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component>& comp,
+                            std::list<std::unique_ptr<C2Work>>& workItems) override {
         /* TODO */
         ALOGD("onWorkDone called");
         (void)comp;
@@ -63,40 +66,34 @@
     }
 
     virtual void onTripped(
-        const std::weak_ptr<android::Codec2Client::Component>& comp,
-        const std::vector<std::shared_ptr<C2SettingResult>>& settingResults)
-        override {
+            const std::weak_ptr<android::Codec2Client::Component>& comp,
+            const std::vector<std::shared_ptr<C2SettingResult>>& settingResults) override {
         /* TODO */
         (void)comp;
         (void)settingResults;
     }
 
-    virtual void onError(
-        const std::weak_ptr<android::Codec2Client::Component>& comp,
-        uint32_t errorCode) override {
+    virtual void onError(const std::weak_ptr<android::Codec2Client::Component>& comp,
+                         uint32_t errorCode) override {
         /* TODO */
         (void)comp;
         ALOGD("onError called");
         if (errorCode != 0) ALOGE("Error : %u", errorCode);
     }
 
-    virtual void onDeath(
-        const std::weak_ptr<android::Codec2Client::Component>& comp) override {
+    virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component>& comp) override {
         /* TODO */
         (void)comp;
     }
 
-    virtual void onInputBufferDone(
-        uint64_t frameIndex, size_t arrayIndex) override {
+    virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
         /* TODO */
         (void)frameIndex;
         (void)arrayIndex;
     }
 
-    virtual void onFrameRendered(
-        uint64_t bufferQueueId,
-        int32_t slotId,
-        int64_t timestampNs) override {
+    virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
+                                 int64_t timestampNs) override {
         /* TODO */
         (void)bufferQueueId;
         (void)slotId;
@@ -108,99 +105,37 @@
     std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
 };
 
-// A class for test environment setup
-class ComponentTestEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestEnvBase Super;
+// Return all test parameters, a list of tuple of <instance, component>.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters();
 
-   public:
-    virtual void registerTestServices() override {
-        registerTestService<IComponentStore>();
-    }
-
-    ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
-
-    void setComponent(const char* _component) { component = _component; }
-
-    void setInstance(const char* _instance) { instance = _instance; }
-
-    void setRes(const char* _res) { res = _res; }
-
-    const hidl_string getInstance() const { return instance; }
-
-    const hidl_string getComponent() const { return component; }
-
-    const hidl_string getRes() const { return res; }
-
-    int initFromOptions(int argc, char** argv) {
-        static struct option options[] = {
-            {"instance", required_argument, 0, 'I'},
-            {"component", required_argument, 0, 'C'},
-            {"res", required_argument, 0, 'P'},
-            {0, 0, 0, 0}};
-
-        while (true) {
-            int index = 0;
-            int c = getopt_long(argc, argv, "I:C:P:", options, &index);
-            if (c == -1) {
-                break;
-            }
-
-            switch (c) {
-                case 'I':
-                    setInstance(optarg);
-                    break;
-                case 'C':
-                    setComponent(optarg);
-                    break;
-                case 'P':
-                    setRes(optarg);
-                    break;
-                case '?':
-                    break;
-            }
-        }
-
-        if (optind < argc) {
-            fprintf(stderr,
-                    "unrecognized option: %s\n\n"
-                    "usage: %s <gtest options> <test options>\n\n"
-                    "test options are:\n\n"
-                    "-I, --instance: software for C2 components, else default\n"
-                    "-C, --component: C2 component to test\n"
-                    "-P, --res: Resource files directory location\n",
-                    argv[optind ?: 1], argv[0]);
-            return 2;
-        }
-        return 0;
-    }
-
-   private:
-    hidl_string instance;
-    hidl_string component;
-    hidl_string res;
-};
+// Return all test parameters, a list of tuple of <instance, component> with matching domain and
+// kind.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters(
+        C2Component::domain_t domain, C2Component::kind_t kind);
 
 /*
  * common functions declarations
  */
-void testInputBuffer(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
-    uint32_t flags, bool isNullBuffer);
+void testInputBuffer(const std::shared_ptr<android::Codec2Client::Component>& component,
+                     std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+                     uint32_t flags, bool isNullBuffer);
 
-void waitOnInputConsumption(std::mutex& queueLock,
-                            std::condition_variable& queueCondition,
+void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition,
                             std::list<std::unique_ptr<C2Work>>& workQueue,
                             size_t bufferCount = MAX_INPUT_BUFFERS);
 
-void workDone(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
-    std::mutex& queueLock, std::condition_variable& queueCondition,
-    std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
-    uint32_t& framesReceived);
+void workDone(const std::shared_ptr<android::Codec2Client::Component>& component,
+              std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+              std::mutex& queueLock, std::condition_variable& queueCondition,
+              std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+              uint32_t& framesReceived);
 
 int64_t getNowUs();
 
+int32_t populateInfoVector(std::string info, android::Vector<FrameInfo>* frameInfo,
+                           bool timestampDevTest, std::list<uint64_t>* timestampUslist);
+
+void verifyFlushOutput(std::list<std::unique_ptr<C2Work>>& flushedWork,
+                       std::list<std::unique_ptr<C2Work>>& workQueue,
+                       std::list<uint64_t>& flushedIndices, std::mutex& queueLock);
 #endif  // MEDIA_C2_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 9dc541c..6122225 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -19,11 +19,11 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 
 #include <C2Config.h>
 #include <codec2/hidl/client.h>
 
-#include <VtsHalHidlTargetTestBase.h>
 #include "media_c2_hidl_test_common.h"
 
 /* Time_Out for start(), stop(), reset(), release(), flush(), queue() are
@@ -31,50 +31,45 @@
  * extra in case of timeout is 500ms, 1ms extra in case timeout is 1ms/5ms. All
  * timeout is calculated in us.
  */
-#define START_TIME_OUT                  550000
-#define STOP_TIME_OUT                   550000
-#define RESET_TIME_OUT                  550000
-#define RELEASE_TIME_OUT                550000
-#define FLUSH_TIME_OUT                  6000
-#define QUEUE_TIME_OUT                  2000
+#define START_TIME_OUT 550000
+#define STOP_TIME_OUT 550000
+#define RESET_TIME_OUT 550000
+#define RELEASE_TIME_OUT 550000
+#define FLUSH_TIME_OUT 6000
+#define QUEUE_TIME_OUT 2000
 
 // Time_Out for config(), query(), querySupportedParams() are defined in
 // hardware/interfaces/media/c2/1.0/IConfigurable.hal.
-#define CONFIG_TIME_OUT                 6000
-#define QUERY_TIME_OUT                  6000
-#define QUERYSUPPORTEDPARAMS_TIME_OUT   2000
+#define CONFIG_TIME_OUT 6000
+#define QUERY_TIME_OUT 6000
+#define QUERYSUPPORTEDPARAMS_TIME_OUT 2000
 
-#define CHECK_TIMEOUT(timeConsumed, TIME_OUT, FuncName)          \
-    if (timeConsumed > TIME_OUT) {                               \
-        ALOGW(                                                   \
-            "TIMED_OUT %s  timeConsumed=%" PRId64 " us is "      \
-            "greater than threshold %d us",                      \
-            FuncName, timeConsumed, TIME_OUT);                   \
+#define CHECK_TIMEOUT(timeConsumed, TIME_OUT, FuncName) \
+    if (timeConsumed > TIME_OUT) {                      \
+        ALOGW("TIMED_OUT %s  timeConsumed=%" PRId64     \
+              " us is "                                 \
+              "greater than threshold %d us",           \
+              FuncName, timeConsumed, TIME_OUT);        \
     }
 
-static ComponentTestEnvironment* gEnv = nullptr;
-
 namespace {
 
-// google.codec2 Component test setup
-class Codec2ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+        kInputTestParameters;
 
-   public:
+// google.codec2 Component test setup
+class Codec2ComponentHidlTestBase : public ::testing::Test {
+  public:
     virtual void SetUp() override {
-        Super::SetUp();
+        getParams();
         mEos = false;
-        mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+        mClient = android::Codec2Client::CreateFromService(mInstanceName.c_str());
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener(
-            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
-                handleWorkDone(workItems);
-            }));
+        mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+            handleWorkDone(workItems);
+        }));
         ASSERT_NE(mListener, nullptr);
-        mClient->createComponent(gEnv->getComponent().c_str(), mListener,
-                                 &mComponent);
+        mClient->createComponent(mComponentName.c_str(), mListener, &mComponent);
         ASSERT_NE(mComponent, nullptr);
         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
             mWorkQueue.emplace_back(new C2Work);
@@ -90,8 +85,11 @@
             mComponent->release();
             mComponent = nullptr;
         }
-        Super::TearDown();
     }
+
+    // Get the test parameters from GetParam call.
+    virtual void getParams() {}
+
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
@@ -99,12 +97,14 @@
                 bool mCsd = false;
                 uint32_t mFramesReceived = 0;
                 std::list<uint64_t> mFlushedIndices;
-                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition,
-                         mWorkQueue, mEos, mCsd, mFramesReceived);
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+                         mEos, mCsd, mFramesReceived);
             }
         }
     }
 
+    std::string mInstanceName;
+    std::string mComponentName;
     bool mEos;
     std::mutex mQueueLock;
     std::condition_variable mQueueCondition;
@@ -114,14 +114,23 @@
     std::shared_ptr<android::Codec2Client::Listener> mListener;
     std::shared_ptr<android::Codec2Client::Component> mComponent;
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
 };
 
+class Codec2ComponentHidlTest
+    : public Codec2ComponentHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
 // Test Empty Flush
-TEST_F(Codec2ComponentHidlTest, EmptyFlush) {
+TEST_P(Codec2ComponentHidlTest, EmptyFlush) {
     ALOGV("Empty Flush Test");
     c2_status_t err = mComponent->start();
     ASSERT_EQ(err, C2_OK);
@@ -137,7 +146,7 @@
 }
 
 // Test Queue Empty Work
-TEST_F(Codec2ComponentHidlTest, QueueEmptyWork) {
+TEST_P(Codec2ComponentHidlTest, QueueEmptyWork) {
     ALOGV("Queue Empty Work Test");
     c2_status_t err = mComponent->start();
     ASSERT_EQ(err, C2_OK);
@@ -151,7 +160,7 @@
 }
 
 // Test Component Configuration
-TEST_F(Codec2ComponentHidlTest, Config) {
+TEST_P(Codec2ComponentHidlTest, Config) {
     ALOGV("Configuration Test");
 
     C2String name = mComponent->getName();
@@ -180,7 +189,7 @@
 }
 
 // Test Multiple Start Stop Reset Test
-TEST_F(Codec2ComponentHidlTest, MultipleStartStopReset) {
+TEST_P(Codec2ComponentHidlTest, MultipleStartStopReset) {
     ALOGV("Multiple Start Stop and Reset Test");
 
     for (size_t i = 0; i < MAX_RETRY; i++) {
@@ -202,21 +211,21 @@
 }
 
 // Test Component Release API
-TEST_F(Codec2ComponentHidlTest, MultipleRelease) {
+TEST_P(Codec2ComponentHidlTest, MultipleRelease) {
     ALOGV("Multiple Release Test");
     c2_status_t err = mComponent->start();
     ASSERT_EQ(err, C2_OK);
 
     // Query Component Domain Type
     std::vector<std::unique_ptr<C2Param>> queried;
-    err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
-                            C2_DONT_BLOCK, &queried);
+    err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK,
+                            &queried);
     EXPECT_NE(queried.size(), 0u);
 
     // Configure Component Domain
     std::vector<std::unique_ptr<C2SettingResult>> failures;
     C2PortMediaTypeSetting::input* portMediaType =
-        C2PortMediaTypeSetting::input::From(queried[0].get());
+            C2PortMediaTypeSetting::input::From(queried[0].get());
     err = mComponent->config({portMediaType}, C2_DONT_BLOCK, &failures);
     ASSERT_EQ(err, C2_OK);
     ASSERT_EQ(failures.size(), 0u);
@@ -226,40 +235,8 @@
     }
 }
 
-class Codec2ComponentInputTests : public Codec2ComponentHidlTest,
-        public ::testing::WithParamInterface<std::pair<uint32_t, bool> > {
-};
-
-TEST_P(Codec2ComponentInputTests, InputBufferTest) {
-    description("Tests for different inputs");
-
-    uint32_t flags = GetParam().first;
-    bool isNullBuffer = GetParam().second;
-    if (isNullBuffer) ALOGD("Testing for null input buffer with flag : %u", flags);
-    else ALOGD("Testing for empty input buffer with flag : %u", flags);
-    mEos = false;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-    ASSERT_NO_FATAL_FAILURE(testInputBuffer(
-        mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
-
-    ALOGD("Waiting for input consumption");
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
-
-    if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
-    ASSERT_EQ(mComponent->stop(), C2_OK);
-    ASSERT_EQ(mComponent->reset(), C2_OK);
-}
-
-INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests, ::testing::Values(
-    std::make_pair(0, true),
-    std::make_pair(C2FrameData::FLAG_END_OF_STREAM, true),
-    std::make_pair(0, false),
-    std::make_pair(C2FrameData::FLAG_CODEC_CONFIG, false),
-    std::make_pair(C2FrameData::FLAG_END_OF_STREAM, false)));
-
 // Test API's Timeout
-TEST_F(Codec2ComponentHidlTest, Timeout) {
+TEST_P(Codec2ComponentHidlTest, Timeout) {
     ALOGV("Timeout Test");
     c2_status_t err = C2_OK;
 
@@ -285,10 +262,8 @@
     startTime = getNowUs();
     err = mComponent->querySupportedParams(&params);
     timeConsumed = getNowUs() - startTime;
-    CHECK_TIMEOUT(timeConsumed, QUERYSUPPORTEDPARAMS_TIME_OUT,
-                  "querySupportedParams()");
-    ALOGV("mComponent->querySupportedParams() timeConsumed=%" PRId64 " us",
-          timeConsumed);
+    CHECK_TIMEOUT(timeConsumed, QUERYSUPPORTEDPARAMS_TIME_OUT, "querySupportedParams()");
+    ALOGV("mComponent->querySupportedParams() timeConsumed=%" PRId64 " us", timeConsumed);
     ASSERT_EQ(err, C2_OK);
 
     std::vector<std::unique_ptr<C2Param>> queried;
@@ -301,8 +276,8 @@
         CHECK_TIMEOUT(timeConsumed, QUERY_TIME_OUT, "query()");
         EXPECT_NE(queried.size(), 0u);
         EXPECT_EQ(err, C2_OK);
-        ALOGV("mComponent->query() for %s timeConsumed=%" PRId64 " us",
-              p->name().c_str(), timeConsumed);
+        ALOGV("mComponent->query() for %s timeConsumed=%" PRId64 " us", p->name().c_str(),
+              timeConsumed);
 
         startTime = getNowUs();
         err = mComponent->config({queried[0].get()}, C2_DONT_BLOCK, &failures);
@@ -310,8 +285,8 @@
         CHECK_TIMEOUT(timeConsumed, CONFIG_TIME_OUT, "config()");
         ASSERT_EQ(err, C2_OK);
         ASSERT_EQ(failures.size(), 0u);
-        ALOGV("mComponent->config() for %s timeConsumed=%" PRId64 " us",
-              p->name().c_str(), timeConsumed);
+        ALOGV("mComponent->config() for %s timeConsumed=%" PRId64 " us", p->name().c_str(),
+              timeConsumed);
     }
 
     std::list<std::unique_ptr<C2Work>> workList;
@@ -340,22 +315,68 @@
     ALOGV("mComponent->release() timeConsumed=%" PRId64 " us", timeConsumed);
     CHECK_TIMEOUT(timeConsumed, RELEASE_TIME_OUT, "release()");
     ASSERT_EQ(err, C2_OK);
-
 }
 
+class Codec2ComponentInputTests
+    : public Codec2ComponentHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+TEST_P(Codec2ComponentInputTests, InputBufferTest) {
+    description("Tests for different inputs");
+
+    uint32_t flags = std::stoul(std::get<2>(GetParam()));
+    bool isNullBuffer = !std::get<3>(GetParam()).compare("true");
+    if (isNullBuffer)
+        ALOGD("Testing for null input buffer with flag : %u", flags);
+    else
+        ALOGD("Testing for empty input buffer with flag : %u", flags);
+    mEos = false;
+    ASSERT_EQ(mComponent->start(), C2_OK);
+    ASSERT_NO_FATAL_FAILURE(
+            testInputBuffer(mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
+
+    ALOGD("Waiting for input consumption");
+    ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+
+    if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mComponent->reset(), C2_OK);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests,
+                        testing::ValuesIn(kInputTestParameters),
+                        android::hardware::PrintInstanceTupleNameToString<>);
 }  // anonymous namespace
 
 // TODO: Add test for Invalid work,
 // TODO: Add test for Invalid states
 int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
+    kTestParameters = getTestParameters();
+    for (auto params : kTestParameters) {
+        kInputTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+        kInputTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params),
+                                std::to_string(C2FrameData::FLAG_END_OF_STREAM), "true"));
+        kInputTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+        kInputTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params),
+                                std::to_string(C2FrameData::FLAG_CODEC_CONFIG), "false"));
+        kInputTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params),
+                                std::to_string(C2FrameData::FLAG_END_OF_STREAM), "false"));
     }
-    return status;
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index e88fbc7..fb1c291 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -19,30 +19,25 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <codec2/hidl/client.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include "media_c2_hidl_test_common.h"
 
-static ComponentTestEnvironment* gEnv = nullptr;
-
 namespace {
 
 // google.codec2 Master test setup
-class Codec2MasterHalTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
-
-   public:
+class Codec2MasterHalTest : public ::testing::TestWithParam<std::string> {
+  public:
     virtual void SetUp() override {
-        Super::SetUp();
-        mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+        mClient = android::Codec2Client::CreateFromService(GetParam().c_str());
         ASSERT_NE(mClient, nullptr);
     }
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
@@ -58,15 +53,14 @@
 }
 
 // List Components
-TEST_F(Codec2MasterHalTest, ListComponents) {
+TEST_P(Codec2MasterHalTest, ListComponents) {
     ALOGV("ListComponents Test");
 
     C2String name = mClient->getName();
     EXPECT_NE(name.empty(), true) << "Invalid Codec2Client Name";
 
     // Get List of components from all known services
-    const std::vector<C2Component::Traits> listTraits =
-        mClient->ListComponents();
+    const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
 
     if (listTraits.size() == 0)
         ALOGE("Warning, ComponentInfo list empty");
@@ -79,24 +73,16 @@
             ASSERT_NE(listener, nullptr);
 
             // Create component from all known services
-            component = mClient->CreateComponentByName(
-                listTraits[i].name.c_str(), listener, &mClient);
-            ASSERT_NE(component, nullptr) << "Create component failed for "
-                                          << listTraits[i].name.c_str();
+            component =
+                    mClient->CreateComponentByName(listTraits[i].name.c_str(), listener, &mClient);
+            ASSERT_NE(component, nullptr)
+                    << "Create component failed for " << listTraits[i].name.c_str();
         }
     }
 }
 
 }  // anonymous namespace
 
-int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
-    }
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2MasterHalTest,
+                         testing::ValuesIn(android::Codec2Client::GetServiceNames()),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_176_144_chksm.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_176_144_chksm.md5
new file mode 100644
index 0000000..cb69709
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_176_144_chksm.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_640_360_chksum.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_640_360_chksum.md5
new file mode 100644
index 0000000..2693071
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_av1_640_360_chksum.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_176x144_300kbps_60fps_chksum.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_176x144_300kbps_60fps_chksum.md5
new file mode 100644
index 0000000..5c802d9
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_176x144_300kbps_60fps_chksum.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_640x360_768kbps_30fps_chksum.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_640x360_768kbps_30fps_chksum.md5
new file mode 100644
index 0000000..073f8eb
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_avc_640x360_768kbps_30fps_chksum.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_176x144_176kbps_60fps_chksum.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_176x144_176kbps_60fps_chksum.md5
new file mode 100644
index 0000000..83f11c0
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_176x144_176kbps_60fps_chksum.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_640x360_1600kbps_30fps_chksum.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_640x360_1600kbps_30fps_chksum.md5
new file mode 100644
index 0000000..3344881
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_hevc_640x360_1600kbps_30fps_chksum.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_vp8_640x360_2mbps_30fps_chksm.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp8_640x360_2mbps_30fps_chksm.md5
new file mode 100644
index 0000000..738b1da
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp8_640x360_2mbps_30fps_chksm.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_640x360_1600kbps_30fps_chksm.md5 b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_640x360_1600kbps_30fps_chksm.md5
new file mode 100644
index 0000000..a52faf2
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_640x360_1600kbps_30fps_chksm.md5
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.info b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.info
new file mode 100644
index 0000000..9ea1ffa
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.info
@@ -0,0 +1,352 @@
+73 0 0
+159 16 41000
+103 16 41000
+34 0 41000
+30 0 83000
+30 0 125000
+30 0 166000
+1 0 208000
+105 0 250000
+54 0 291000
+65 0 333000
+1 0 375000
+239 0 416000
+1373 16 458000
+263 16 458000
+133 0 458000
+109 0 500000
+127 0 541000
+1 0 583000
+134 0 625000
+159 0 666000
+131 0 708000
+1 0 750000
+4420 16 791000
+349 16 791000
+151 0 791000
+1 0 833000
+120 0 875000
+1 0 916000
+3203 16 958000
+433 16 958000
+125 0 958000
+1 0 1000000
+107 0 1041000
+1 0 1083000
+3832 16 1125000
+541 16 1125000
+116 0 1125000
+1 0 1166000
+115 0 1208000
+1 0 1250000
+3777 16 1291000
+495 16 1291000
+109 0 1291000
+1 0 1333000
+79 0 1375000
+1 0 1416000
+3906 16 1458000
+539 16 1458000
+149 0 1458000
+1 0 1500000
+112 0 1541000
+1 0 1583000
+5495 16 1625000
+594 16 1625000
+392 0 1625000
+235 0 1666000
+170 0 1708000
+1 0 1750000
+384 0 1791000
+378 0 1833000
+120 0 1875000
+1 0 1916000
+16843 16 1958000
+1951 16 1958000
+774 0 1958000
+831 0 2000000
+560 0 2041000
+489 0 2083000
+345 0 2125000
+243 0 2166000
+260 0 2208000
+1 0 2250000
+498 0 2291000
+463 0 2333000
+414 0 2375000
+341 0 2416000
+262 0 2458000
+194 0 2500000
+85 0 2541000
+1 0 2583000
+11253 16 2625000
+1561 16 2625000
+250 0 2625000
+402 0 2666000
+454 0 2708000
+350 0 2750000
+316 0 2791000
+164 0 2833000
+108 0 2875000
+1 0 2916000
+246 0 2958000
+586 0 3000000
+493 0 3041000
+363 0 3083000
+325 0 3125000
+170 0 3166000
+78 0 3208000
+40 0 3250000
+15630 16 3291000
+2228 16 3291000
+346 0 3291000
+707 0 3333000
+685 0 3375000
+582 0 3416000
+473 0 3458000
+249 0 3500000
+177 0 3541000
+1 0 3583000
+541 0 3625000
+834 0 3666000
+614 0 3708000
+473 0 3750000
+365 0 3791000
+211 0 3833000
+91 0 3875000
+1 0 3916000
+8384 16 3958000
+1138 16 3958000
+256 0 3958000
+377 0 4000000
+316 0 4041000
+267 0 4083000
+119 0 4125000
+1 0 4166000
+319 0 4208000
+390 0 4250000
+243 0 4291000
+203 0 4333000
+110 0 4375000
+1 0 4416000
+11302 16 4458000
+1527 16 4458000
+408 0 4458000
+507 0 4500000
+350 0 4541000
+377 0 4583000
+239 0 4625000
+125 0 4666000
+1 0 4708000
+351 0 4750000
+469 0 4791000
+288 0 4833000
+244 0 4875000
+224 0 4916000
+108 0 4958000
+1 0 5000000
+6016 16 5041000
+561 16 5041000
+235 0 5041000
+213 0 5083000
+118 0 5125000
+1 0 5166000
+299 0 5208000
+213 0 5250000
+129 0 5291000
+1 0 5333000
+7029 16 5375000
+728 16 5375000
+339 0 5375000
+287 0 5416000
+225 0 5458000
+147 0 5500000
+1 0 5541000
+270 0 5583000
+217 0 5625000
+138 0 5666000
+46 0 5708000
+32861 0 5750000
+16095 16 5791000
+2033 16 5791000
+318 0 5791000
+443 0 5833000
+361 0 5875000
+313 0 5916000
+274 0 5958000
+210 0 6000000
+134 0 6041000
+1 0 6083000
+295 0 6125000
+415 0 6166000
+330 0 6208000
+264 0 6250000
+242 0 6291000
+166 0 6333000
+116 0 6375000
+1 0 6416000
+9488 16 6458000
+1466 16 6458000
+378 0 6458000
+419 0 6500000
+335 0 6541000
+290 0 6583000
+315 0 6625000
+199 0 6666000
+131 0 6708000
+1 0 6750000
+342 0 6791000
+421 0 6833000
+306 0 6875000
+320 0 6916000
+245 0 6958000
+205 0 7000000
+143 0 7041000
+1 0 7083000
+16554 16 7125000
+1744 16 7125000
+482 0 7125000
+365 0 7166000
+352 0 7208000
+308 0 7250000
+295 0 7291000
+199 0 7333000
+149 0 7375000
+1 0 7416000
+360 0 7458000
+428 0 7500000
+377 0 7541000
+347 0 7583000
+270 0 7625000
+187 0 7666000
+130 0 7708000
+39 0 7750000
+14637 16 7791000
+1832 16 7791000
+422 0 7791000
+466 0 7833000
+375 0 7875000
+405 0 7916000
+352 0 7958000
+275 0 8000000
+173 0 8041000
+1 0 8083000
+484 0 8125000
+516 0 8166000
+497 0 8208000
+452 0 8250000
+428 0 8291000
+293 0 8333000
+190 0 8375000
+1 0 8416000
+11534 16 8458000
+1655 16 8458000
+446 0 8458000
+531 0 8500000
+465 0 8541000
+495 0 8583000
+402 0 8625000
+330 0 8666000
+227 0 8708000
+1 0 8750000
+568 0 8791000
+694 0 8833000
+382 0 8875000
+422 0 8916000
+280 0 8958000
+305 0 9000000
+203 0 9041000
+1 0 9083000
+17067 16 9125000
+1521 16 9125000
+428 0 9125000
+434 0 9166000
+359 0 9208000
+368 0 9250000
+240 0 9291000
+215 0 9333000
+211 0 9375000
+1 0 9416000
+346 0 9458000
+533 0 9500000
+391 0 9541000
+313 0 9583000
+326 0 9625000
+211 0 9666000
+233 0 9708000
+35 0 9750000
+23743 16 9791000
+1968 16 9791000
+277 0 9791000
+276 0 9833000
+285 0 9875000
+232 0 9916000
+179 0 9958000
+203 0 10000000
+121 0 10041000
+1 0 10083000
+318 0 10125000
+391 0 10166000
+362 0 10208000
+291 0 10250000
+235 0 10291000
+187 0 10333000
+117 0 10375000
+43 0 10416000
+12465 16 10458000
+1607 16 10458000
+280 0 10458000
+295 0 10500000
+244 0 10541000
+211 0 10583000
+171 0 10625000
+159 0 10666000
+106 0 10708000
+1 0 10750000
+216 0 10791000
+195 0 10833000
+180 0 10875000
+164 0 10916000
+156 0 10958000
+96 0 11000000
+1 0 11041000
+54547 0 11083000
+2920 16 11125000
+153 16 11125000
+117 0 11125000
+83 0 11166000
+86 0 11208000
+1 0 11250000
+92 0 11291000
+93 0 11333000
+80 0 11375000
+1 0 11416000
+1314 16 11458000
+311 16 11458000
+79 0 11458000
+65 0 11500000
+74 0 11541000
+61 0 11583000
+1 0 11625000
+65 0 11666000
+64 0 11708000
+49 0 11750000
+51 0 11791000
+1 0 11833000
+19309 0 11875000
+3848 16 11916000
+771 16 11916000
+167 0 11916000
+202 0 11958000
+190 0 12000000
+173 0 12041000
+128 0 12083000
+79 0 12125000
+1 0 12166000
+155 0 12208000
+211 0 12250000
+192 0 12291000
+131 0 12333000
+91 0 12375000
+128 0 12416000
+1 0 12458000
diff --git a/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.vp9 b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.vp9
new file mode 100644
index 0000000..00c7dec
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/res/bbb_vp9_704x480_280kbps_24fps_altref_2.vp9
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index be35b02..c7b0c12 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -16,13 +16,28 @@
 
 cc_test {
     name: "VtsHalMediaC2V1_0TargetVideoDecTest",
+    stem: "vts_media_c2_v1_0_video_dec_test",
     defaults: ["VtsHalMediaC2V1_0Defaults"],
     srcs: ["VtsHalMediaC2V1_0TargetVideoDecTest.cpp"],
+    header_libs: [
+        "libnativewindow_headers",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libgui",
+        "libutils",
+        "libcrypto",
+    ],
+    data: [":media_c2_v1_video_decode_res"],
+    test_config: "VtsHalMediaC2V1_0TargetVideoDecTest.xml",
 }
 
 cc_test {
     name: "VtsHalMediaC2V1_0TargetVideoEncTest",
+    stem: "vts_media_c2_v1_0_video_enc_test",
     defaults: ["VtsHalMediaC2V1_0Defaults"],
     srcs: ["VtsHalMediaC2V1_0TargetVideoEncTest.cpp"],
+    data: [":media_c2_v1_video_encode_res"],
+    test_config: "VtsHalMediaC2V1_0TargetVideoEncTest.xml",
 }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 5e28750..12ed725 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -19,82 +19,70 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <stdio.h>
-#include <fstream>
 
-#include <codec2/hidl/client.h>
+#include <openssl/md5.h>
+
 #include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
+#include <gui/BufferQueue.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IProducerListener.h>
+#include <system/window.h>
 
 using android::C2AllocatorIon;
 
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_video_hidl_test_common.h"
 #include "media_c2_hidl_test_common.h"
+#include "media_c2_video_hidl_test_common.h"
 
-struct FrameInfo {
-    int bytesCount;
-    uint32_t flags;
-    int64_t timestamp;
-};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+        kDecodeTestParameters;
+
+static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;
+
+// Resource directory
+static std::string sResourceDir = "";
 
 class LinearBuffer : public C2Buffer {
-   public:
+  public:
     explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
-        : C2Buffer(
-              {block->share(block->offset(), block->size(), ::C2Fence())}) {}
+        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
 
     explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
-        : C2Buffer(
-              {block->share(block->offset(), size, ::C2Fence())}) {}
+        : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
 };
 
-static ComponentTestEnvironment* gEnv = nullptr;
-
 namespace {
 
-class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
-
-   public:
-    ::std::string getTestCaseInfo() const override {
-        return ::std::string() +
-                "Component: " + gEnv->getComponent().c_str() + " | " +
-                "Instance: " + gEnv->getInstance().c_str() + " | " +
-                "Res: " + gEnv->getRes().c_str();
-    }
-
+class Codec2VideoDecHidlTestBase : public ::testing::Test {
+  public:
     // google.codec2 Video test setup
     virtual void SetUp() override {
-        Super::SetUp();
+        getParams();
         mDisableTest = false;
         ALOGV("Codec2VideoDecHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+                mInstanceName.c_str(),
+                !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener(
-            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
-                handleWorkDone(workItems);
-            }));
+        mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+            handleWorkDone(workItems);
+        }));
         ASSERT_NE(mListener, nullptr);
         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
             mWorkQueue.emplace_back(new C2Work);
         }
-        mClient->createComponent(gEnv->getComponent().c_str(), mListener,
-                                 &mComponent);
+        mClient->createComponent(mComponentName, mListener, &mComponent);
         ASSERT_NE(mComponent, nullptr);
 
-        std::shared_ptr<C2AllocatorStore> store =
-            android::GetCodec2PlatformAllocatorStore();
-        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
-                                       &mLinearAllocator),
-                 C2_OK);
-        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
-                                                          mBlockPoolId++);
+        std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+        mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
         ASSERT_NE(mLinearPool, nullptr);
 
         mCompName = unknown_comp;
@@ -104,17 +92,15 @@
         };
 
         const StringToName kStringToName[] = {
-            {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
-            {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
+                {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
+                {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},     {"av1", av1},
         };
 
-        const size_t kNumStringToName =
-            sizeof(kStringToName) / sizeof(kStringToName[0]);
+        const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
 
         // Find the component type
-        std::string comp = std::string(gEnv->getComponent());
         for (size_t i = 0; i < kNumStringToName; ++i) {
-            if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+            if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
                 mCompName = kStringToName[i].CompName;
                 break;
             }
@@ -122,11 +108,16 @@
         mEos = false;
         mFramesReceived = 0;
         mTimestampUs = 0u;
+        mWorkResult = C2_OK;
+        mReorderDepth = -1;
         mTimestampDevTest = false;
+        mMd5Offset = 0;
+        mMd5Enable = false;
+        mRefMd5 = nullptr;
         if (mCompName == unknown_comp) mDisableTest = true;
 
         C2SecureModeTuning secureModeTuning{};
-        mComponent->query({ &secureModeTuning }, {}, C2_MAY_BLOCK, nullptr);
+        mComponent->query({&secureModeTuning}, {}, C2_MAY_BLOCK, nullptr);
         if (secureModeTuning.value == C2Config::SM_READ_PROTECTED) {
             mDisableTest = true;
         }
@@ -140,53 +131,137 @@
             mComponent->release();
             mComponent = nullptr;
         }
-        Super::TearDown();
     }
 
+    // Get the test parameters from GetParam call.
+    virtual void getParams() {}
+
+    /* Calculate the CKSUM for the data in inbuf */
+    void calc_md5_cksum(uint8_t* pu1_inbuf, uint32_t u4_stride, uint32_t u4_width,
+                        uint32_t u4_height, uint8_t* pu1_cksum_p) {
+        int32_t row;
+        MD5_CTX s_md5_context;
+        MD5_Init(&s_md5_context);
+        for (row = 0; row < u4_height; row++) {
+            MD5_Update(&s_md5_context, pu1_inbuf, u4_width);
+            pu1_inbuf += u4_stride;
+        }
+        MD5_Final(pu1_cksum_p, &s_md5_context);
+    }
+
+    void compareMd5Chksm(std::unique_ptr<C2Work>& work) {
+        uint8_t chksum[48];
+        uint8_t* au1_y_chksum = chksum;
+        uint8_t* au1_u_chksum = chksum + 16;
+        uint8_t* au1_v_chksum = chksum + 32;
+        const C2GraphicView output = work->worklets.front()
+                                             ->output.buffers[0]
+                                             ->data()
+                                             .graphicBlocks()
+                                             .front()
+                                             .map()
+                                             .get();
+        uint8_t* yPlane = const_cast<uint8_t*>(output.data()[C2PlanarLayout::PLANE_Y]);
+        uint8_t* uPlane = const_cast<uint8_t*>(output.data()[C2PlanarLayout::PLANE_U]);
+        uint8_t* vPlane = const_cast<uint8_t*>(output.data()[C2PlanarLayout::PLANE_V]);
+        C2PlanarLayout layout = output.layout();
+
+        size_t yStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+        size_t uvStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+        size_t colInc = layout.planes[C2PlanarLayout::PLANE_U].colInc;
+        size_t bitDepth = layout.planes[C2PlanarLayout::PLANE_Y].bitDepth;
+        uint32_t layoutType = layout.type;
+        size_t cropWidth = output.crop().width;
+        size_t cropHeight = output.crop().height;
+
+        if (bitDepth == 8 && layoutType == C2PlanarLayout::TYPE_YUV && colInc == 1) {
+            calc_md5_cksum(yPlane, yStride, cropWidth, cropHeight, au1_y_chksum);
+            calc_md5_cksum(uPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_u_chksum);
+            calc_md5_cksum(vPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_v_chksum);
+        } else if (bitDepth == 8 && layoutType == C2PlanarLayout::TYPE_YUV && colInc == 2) {
+            uint8_t* cbPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
+            uint8_t* crPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
+            ASSERT_NE(cbPlane, nullptr);
+            ASSERT_NE(crPlane, nullptr);
+            size_t count = 0;
+            for (size_t k = 0; k < (cropHeight / 2); k++) {
+                for (size_t l = 0; l < (cropWidth); l = l + 2) {
+                    cbPlane[count] = uPlane[k * uvStride + l];
+                    crPlane[count] = vPlane[k * uvStride + l];
+                    count++;
+                }
+            }
+            calc_md5_cksum(yPlane, yStride, cropWidth, cropHeight, au1_y_chksum);
+            calc_md5_cksum(cbPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_u_chksum);
+            calc_md5_cksum(crPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_v_chksum);
+            free(cbPlane);
+            free(crPlane);
+        } else {
+            mMd5Enable = false;
+            ALOGV("Disabling MD5 chksm flag");
+            return;
+        }
+        if (memcmp(mRefMd5 + mMd5Offset, chksum, 48)) ASSERT_TRUE(false);
+        mMd5Offset += 48;
+        return;
+    }
+    bool configPixelFormat(uint32_t format);
+
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
             if (!work->worklets.empty()) {
                 // For decoder components current timestamp always exceeds
-                // previous timestamp
+                // previous timestamp if output is in display order
                 typedef std::unique_lock<std::mutex> ULock;
+                mWorkResult |= work->result;
                 bool codecConfig = ((work->worklets.front()->output.flags &
                                      C2FrameData::FLAG_CODEC_CONFIG) != 0);
-                if (!codecConfig &&
-                    !work->worklets.front()->output.buffers.empty()) {
-                    EXPECT_GE(
-                        (work->worklets.front()->output.ordinal.timestamp.peeku()),
-                        mTimestampUs);
-                    mTimestampUs =
-                        work->worklets.front()->output.ordinal.timestamp.peeku();
-
-                    ULock l(mQueueLock);
-                    if (mTimestampDevTest) {
-                        bool tsHit = false;
-                        std::list<uint64_t>::iterator it = mTimestampUslist.begin();
-                        while (it != mTimestampUslist.end()) {
-                            if (*it == mTimestampUs) {
-                                mTimestampUslist.erase(it);
-                                tsHit = true;
-                                break;
-                            }
-                            it++;
+                if (!codecConfig && !work->worklets.front()->output.buffers.empty()) {
+                    if (mReorderDepth < 0) {
+                        C2PortReorderBufferDepthTuning::output reorderBufferDepth;
+                        mComponent->query({&reorderBufferDepth}, {}, C2_MAY_BLOCK,
+                                          nullptr);
+                        mReorderDepth = reorderBufferDepth.value;
+                        if (mReorderDepth > 0) {
+                            // TODO: Add validation for reordered output
+                            mTimestampDevTest = false;
                         }
-                        if (tsHit == false) {
-                            if (mTimestampUslist.empty() == false) {
-                                EXPECT_EQ(tsHit, true)
-                                    << "TimeStamp not recognized";
-                            } else {
-                                std::cout << "[   INFO   ] Received non-zero "
-                                             "output / TimeStamp not recognized \n";
+                    }
+                    if (mTimestampDevTest) {
+                        EXPECT_GE((work->worklets.front()->output.ordinal.timestamp.peeku()),
+                                  mTimestampUs);
+                        mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
+
+                        ULock l(mQueueLock);
+                        {
+                            bool tsHit = false;
+                            std::list<uint64_t>::iterator it = mTimestampUslist.begin();
+                            while (it != mTimestampUslist.end()) {
+                                if (*it == mTimestampUs) {
+                                    mTimestampUslist.erase(it);
+                                    tsHit = true;
+                                    break;
+                                }
+                                it++;
+                            }
+                            if (tsHit == false) {
+                                if (mTimestampUslist.empty() == false) {
+                                    EXPECT_EQ(tsHit, true) << "TimeStamp not recognized";
+                                } else {
+                                    std::cout << "[   INFO   ] Received non-zero "
+                                                 "output / TimeStamp not recognized \n";
+                                }
                             }
                         }
                     }
+                    if (mMd5Enable) {
+                        compareMd5Chksm(work);
+                    }
                 }
-                bool mCsd;
-                workDone(mComponent, work, mFlushedIndices, mQueueLock,
-                         mQueueCondition, mWorkQueue, mEos, mCsd,
-                         mFramesReceived);
+                bool mCsd = false;
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+                         mEos, mCsd, mFramesReceived);
                 (void)mCsd;
             }
         }
@@ -204,13 +279,22 @@
         unknown_comp,
     };
 
+    std::string mInstanceName;
+    std::string mComponentName;
+
     bool mEos;
     bool mDisableTest;
+    bool mMd5Enable;
     bool mTimestampDevTest;
     uint64_t mTimestampUs;
+    uint64_t mMd5Offset;
+    char* mRefMd5;
     std::list<uint64_t> mTimestampUslist;
     std::list<uint64_t> mFlushedIndices;
     standardComp mCompName;
+
+    int32_t mWorkResult;
+    int32_t mReorderDepth;
     uint32_t mFramesReceived;
     C2BlockPool::local_id_t mBlockPoolId;
     std::shared_ptr<C2BlockPool> mLinearPool;
@@ -224,15 +308,23 @@
     std::shared_ptr<android::Codec2Client::Listener> mListener;
     std::shared_ptr<android::Codec2Client::Component> mComponent;
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
 };
 
-void validateComponent(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    Codec2VideoDecHidlTest::standardComp compName, bool& disableTest) {
+class Codec2VideoDecHidlTest
+    : public Codec2VideoDecHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+                       Codec2VideoDecHidlTest::standardComp compName, bool& disableTest) {
     // Validate its a C2 Component
     if (component->getName().find("c2") == std::string::npos) {
         ALOGE("Not a c2 component");
@@ -247,14 +339,12 @@
         return;
     }
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err =
-        component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
-                         C2_DONT_BLOCK, &queried);
+    c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK && queried.size() == 0) {
         ALOGE("Query media type failed => %d", c2err);
     } else {
-        std::string inputDomain =
-            ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+        std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
         if (inputDomain.find("video/") == std::string::npos) {
             ALOGE("Expected Video Component");
             disableTest = true;
@@ -272,73 +362,80 @@
 }
 
 // number of elementary streams per component
-#define STREAM_COUNT 2
-// LookUpTable of clips and metadata for component testing
-void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL,
-                        char* info, size_t streamIndex = 1) {
+#define STREAM_COUNT 3
+// LookUpTable of clips, metadata and chksum for component testing
+void GetURLChksmForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL, char* info,
+                             char* chksum, size_t streamIndex = 1) {
     struct CompToURL {
         Codec2VideoDecHidlTest::standardComp comp;
         const char mURL[STREAM_COUNT][512];
         const char info[STREAM_COUNT][512];
+        const char chksum[STREAM_COUNT][512];
     };
     ASSERT_TRUE(streamIndex < STREAM_COUNT);
 
     static const CompToURL kCompToURL[] = {
-        {Codec2VideoDecHidlTest::standardComp::avc,
-         {"bbb_avc_176x144_300kbps_60fps.h264",
-          "bbb_avc_640x360_768kbps_30fps.h264"},
-         {"bbb_avc_176x144_300kbps_60fps.info",
-          "bbb_avc_640x360_768kbps_30fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::hevc,
-         {"bbb_hevc_176x144_176kbps_60fps.hevc",
-          "bbb_hevc_640x360_1600kbps_30fps.hevc"},
-         {"bbb_hevc_176x144_176kbps_60fps.info",
-          "bbb_hevc_640x360_1600kbps_30fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::mpeg2,
-         {"bbb_mpeg2_176x144_105kbps_25fps.m2v",
-          "bbb_mpeg2_352x288_1mbps_60fps.m2v"},
-         {"bbb_mpeg2_176x144_105kbps_25fps.info",
-          "bbb_mpeg2_352x288_1mbps_60fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::h263,
-         {"", "bbb_h263_352x288_300kbps_12fps.h263"},
-         {"", "bbb_h263_352x288_300kbps_12fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::mpeg4,
-         {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v"},
-         {"", "bbb_mpeg4_352x288_512kbps_30fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::vp8,
-         {"bbb_vp8_176x144_240kbps_60fps.vp8",
-          "bbb_vp8_640x360_2mbps_30fps.vp8"},
-         {"bbb_vp8_176x144_240kbps_60fps.info",
-          "bbb_vp8_640x360_2mbps_30fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::vp9,
-         {"bbb_vp9_176x144_285kbps_60fps.vp9",
-          "bbb_vp9_640x360_1600kbps_30fps.vp9"},
-         {"bbb_vp9_176x144_285kbps_60fps.info",
-          "bbb_vp9_640x360_1600kbps_30fps.info"}},
-        {Codec2VideoDecHidlTest::standardComp::av1,
-         {"bbb_av1_640_360.av1",
-          "bbb_av1_176_144.av1"},
-         {"bbb_av1_640_360.info",
-          "bbb_av1_176_144.info"}},
+            {Codec2VideoDecHidlTest::standardComp::avc,
+             {"bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_640x360_768kbps_30fps.h264", ""},
+             {"bbb_avc_176x144_300kbps_60fps.info", "bbb_avc_640x360_768kbps_30fps.info", ""},
+             {"bbb_avc_176x144_300kbps_60fps_chksum.md5",
+              "bbb_avc_640x360_768kbps_30fps_chksum.md5", ""}},
+            {Codec2VideoDecHidlTest::standardComp::hevc,
+             {"bbb_hevc_176x144_176kbps_60fps.hevc", "bbb_hevc_640x360_1600kbps_30fps.hevc", ""},
+             {"bbb_hevc_176x144_176kbps_60fps.info", "bbb_hevc_640x360_1600kbps_30fps.info", ""},
+             {"bbb_hevc_176x144_176kbps_60fps_chksum.md5",
+              "bbb_hevc_640x360_1600kbps_30fps_chksum.md5", ""}},
+            {Codec2VideoDecHidlTest::standardComp::mpeg2,
+             {"bbb_mpeg2_176x144_105kbps_25fps.m2v", "bbb_mpeg2_352x288_1mbps_60fps.m2v", ""},
+             {"bbb_mpeg2_176x144_105kbps_25fps.info", "bbb_mpeg2_352x288_1mbps_60fps.info", ""},
+             {"", "", ""}},
+            {Codec2VideoDecHidlTest::standardComp::h263,
+             {"", "bbb_h263_352x288_300kbps_12fps.h263", ""},
+             {"", "bbb_h263_352x288_300kbps_12fps.info", ""},
+             {"", "", ""}},
+            {Codec2VideoDecHidlTest::standardComp::mpeg4,
+             {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v", ""},
+             {"", "bbb_mpeg4_352x288_512kbps_30fps.info", ""},
+             {"", "", ""}},
+            {Codec2VideoDecHidlTest::standardComp::vp8,
+             {"bbb_vp8_176x144_240kbps_60fps.vp8", "bbb_vp8_640x360_2mbps_30fps.vp8", ""},
+             {"bbb_vp8_176x144_240kbps_60fps.info", "bbb_vp8_640x360_2mbps_30fps.info", ""},
+             {"", "bbb_vp8_640x360_2mbps_30fps_chksm.md5", ""}},
+            {Codec2VideoDecHidlTest::standardComp::vp9,
+             {"bbb_vp9_176x144_285kbps_60fps.vp9", "bbb_vp9_640x360_1600kbps_30fps.vp9",
+              "bbb_vp9_704x480_280kbps_24fps_altref_2.vp9"},
+             {"bbb_vp9_176x144_285kbps_60fps.info", "bbb_vp9_640x360_1600kbps_30fps.info",
+              "bbb_vp9_704x480_280kbps_24fps_altref_2.info"},
+             {"", "bbb_vp9_640x360_1600kbps_30fps_chksm.md5", ""}},
+            {Codec2VideoDecHidlTest::standardComp::av1,
+             {"bbb_av1_640_360.av1", "bbb_av1_176_144.av1", ""},
+             {"bbb_av1_640_360.info", "bbb_av1_176_144.info", ""},
+             {"bbb_av1_640_360_chksum.md5", "bbb_av1_176_144_chksm.md5", ""}},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
         if (kCompToURL[i].comp == comp) {
             strcat(mURL, kCompToURL[i].mURL[streamIndex]);
             strcat(info, kCompToURL[i].info[streamIndex]);
+            strcat(chksum, kCompToURL[i].chksum[streamIndex]);
             return;
         }
     }
 }
 
+void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL, char* info,
+                        size_t streamIndex = 1) {
+    char chksum[512];
+    strcpy(chksum, sResourceDir.c_str());
+    GetURLChksmForComponent(comp, mURL, info, chksum, streamIndex);
+}
+
 void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
-                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::mutex& queueLock, std::condition_variable& queueCondition,
                    std::list<std::unique_ptr<C2Work>>& workQueue,
-                   std::list<uint64_t>& flushedIndices,
-                   std::shared_ptr<C2BlockPool>& linearPool,
-                   std::ifstream& eleStream,
-                   android::Vector<FrameInfo>* Info,
-                   int offset, int range, bool signalEOS = true) {
+                   std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+                   std::ifstream& eleStream, android::Vector<FrameInfo>* Info, int offset,
+                   int range, bool signalEOS = true) {
     typedef std::unique_lock<std::mutex> ULock;
     int frameID = offset;
     int maxRetry = 0;
@@ -362,8 +459,7 @@
         }
         int64_t timestamp = (*Info)[frameID].timestamp;
         if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1));
-        if (signalEOS && ((frameID == (int)Info->size() - 1) ||
-                          (frameID == (offset + range - 1))))
+        if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
             flags |= C2FrameData::FLAG_END_OF_STREAM;
 
         work->input.flags = (C2FrameData::flags_t)flags;
@@ -385,10 +481,9 @@
         auto alignedSize = ALIGN(size, PAGE_SIZE);
         if (size) {
             std::shared_ptr<C2LinearBlock> block;
-            ASSERT_EQ(C2_OK,
-                    linearPool->fetchLinearBlock(
-                        alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
-                        &block));
+            ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
+                                     alignedSize,
+                                     {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
             ASSERT_TRUE(block);
 
             // Write View
@@ -419,105 +514,182 @@
     }
 }
 
-TEST_F(Codec2VideoDecHidlTest, validateCompName) {
-    if (mDisableTest) return;
+TEST_P(Codec2VideoDecHidlTest, validateCompName) {
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ALOGV("Checks if the given component is a valid video component");
     validateComponent(mComponent, mCompName, mDisableTest);
     ASSERT_EQ(mDisableTest, false);
 }
 
+TEST_P(Codec2VideoDecHidlTest, configureTunnel) {
+    description("Attempts to configure tunneling");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+    ALOGV("Checks if the component can be configured for tunneling");
+    native_handle_t* sidebandStream{};
+    c2_status_t err = mComponent->configureVideoTunnel(0, &sidebandStream);
+    if (err == C2_OMITTED) {
+        return;
+    }
+
+    using namespace android;
+    sp<NativeHandle> nativeHandle = NativeHandle::create(sidebandStream, true);
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    class DummyConsumerListener : public BnConsumerListener {
+      public:
+        DummyConsumerListener() : BnConsumerListener() {}
+        void onFrameAvailable(const BufferItem&) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+    consumer->consumerConnect(new DummyConsumerListener(), false);
+
+    class DummyProducerListener : public BnProducerListener {
+      public:
+        DummyProducerListener() : BnProducerListener() {}
+        virtual void onBufferReleased() override {}
+        virtual bool needsReleaseNotify() override { return false; }
+        virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
+    };
+    IGraphicBufferProducer::QueueBufferOutput qbo{};
+    producer->connect(new DummyProducerListener(), NATIVE_WINDOW_API_MEDIA, false, &qbo);
+
+    ASSERT_EQ(producer->setSidebandStream(nativeHandle), NO_ERROR);
+}
+
+// Config output pixel format
+bool Codec2VideoDecHidlTestBase::configPixelFormat(uint32_t format) {
+    std::vector<std::unique_ptr<C2SettingResult>> failures;
+    C2StreamPixelFormatInfo::output pixelformat(0u, format);
+
+    std::vector<C2Param*> configParam{&pixelformat};
+    c2_status_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+    if (status == C2_OK && failures.size() == 0u) {
+        return true;
+    }
+    return false;
+}
+
 class Codec2VideoDecDecodeTest
-    : public Codec2VideoDecHidlTest,
-      public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
+    : public Codec2VideoDecHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
 };
 
 // Bitstream Test
 TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
     description("Decodes input file");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    uint32_t streamIndex = GetParam().first;
-    bool signalEOS = GetParam().second;
-    char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
-    GetURLForComponent(mCompName, mURL, info, streamIndex);
-
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
+    uint32_t streamIndex = std::stoi(std::get<2>(GetParam()));
+    bool signalEOS = !std::get<2>(GetParam()).compare("true");
     mTimestampDevTest = true;
+
+    char mURL[512], info[512], chksum[512];
+    android::Vector<FrameInfo> Info;
+
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
+    strcpy(chksum, sResourceDir.c_str());
+
+    GetURLChksmForComponent(mCompName, mURL, info, chksum, streamIndex);
+    if (!(strcmp(mURL, sResourceDir.c_str())) || !(strcmp(info, sResourceDir.c_str()))) {
+        ALOGV("Skipping Test, Stream not available");
+        return;
+    }
+    mMd5Enable = true;
+    if (!strcmp(chksum, sResourceDir.c_str())) mMd5Enable = false;
+
+    uint32_t format = HAL_PIXEL_FORMAT_YCBCR_420_888;
+    if (!configPixelFormat(format)) {
+        std::cout << "[   WARN   ] Test Skipped PixelFormat not configured\n";
+        return;
+    }
+
     mFlushedIndices.clear();
     mTimestampUslist.clear();
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        bool codecConfig = flags ?
-            ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
-        if (mTimestampDevTest && !codecConfig)
-            mTimestampUslist.push_back(timestamp);
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
 
     ASSERT_EQ(mComponent->start(), C2_OK);
     // Reset total no of frames received
     mFramesReceived = 0;
     mTimestampUs = 0;
     ALOGV("mURL : %s", mURL);
+    std::ifstream eleStream;
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, (int)Info.size(), signalEOS));
+
+    size_t refChksmSize = 0;
+    std::ifstream refChksum;
+    if (mMd5Enable) {
+        ALOGV("chksum file name: %s", chksum);
+        refChksum.open(chksum, std::ifstream::binary | std::ifstream::ate);
+        ASSERT_EQ(refChksum.is_open(), true);
+        refChksmSize = refChksum.tellg();
+        refChksum.seekg(0, std::ifstream::beg);
+
+        ALOGV("chksum Size %zu ", refChksmSize);
+        mRefMd5 = (char*)malloc(refChksmSize);
+        ASSERT_NE(mRefMd5, nullptr);
+        refChksum.read(mRefMd5, refChksmSize);
+        ASSERT_EQ(refChksum.gcount(), refChksmSize);
+        refChksum.close();
+    }
+
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          (int)Info.size(), signalEOS));
 
     // If EOS is not sent, sending empty input with EOS flag
     size_t infoSize = Info.size();
     if (!signalEOS) {
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
-        ASSERT_NO_FATAL_FAILURE(
-            testInputBuffer(mComponent, mQueueLock, mWorkQueue,
-                            C2FrameData::FLAG_END_OF_STREAM, false));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1);
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
         infoSize += 1;
     }
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     if (!mEos) {
         ALOGV("Waiting for input consumption");
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     }
 
     eleStream.close();
     if (mFramesReceived != infoSize) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
-              infoSize);
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, infoSize);
+        ASSERT_TRUE(false);
+    }
+
+    if (mRefMd5 != nullptr) free(mRefMd5);
+    if (mMd5Enable && refChksmSize != mMd5Offset) {
+        ALOGE("refChksum size and generated chksum size mismatch refChksum size %zu generated "
+              "chksum size %" PRId64 "",
+              refChksmSize, mMd5Offset);
         ASSERT_TRUE(false);
     }
 
     if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
-// DecodeTest with StreamIndex and EOS / No EOS
-INSTANTIATE_TEST_CASE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
-                        ::testing::Values(std::make_pair(0, false),
-                                          std::make_pair(0, true),
-                                          std::make_pair(1, false),
-                                          std::make_pair(1, true)));
 
 // Adaptive Test
-TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
+TEST_P(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
     description("Adaptive Decode Test");
-    if (mDisableTest) return;
-    if (!(mCompName == avc || mCompName == hevc || mCompName == vp8 ||
-          mCompName == vp9 || mCompName == mpeg2))
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+    if (!(mCompName == avc || mCompName == hevc || mCompName == vp8 || mCompName == vp9 ||
+          mCompName == mpeg2))
         return;
 
     typedef std::unique_lock<std::mutex> ULock;
@@ -531,9 +703,13 @@
         char mURL[512], info[512];
         std::ifstream eleStream, eleInfo;
 
-        strcpy(mURL, gEnv->getRes().c_str());
-        strcpy(info, gEnv->getRes().c_str());
+        strcpy(mURL, sResourceDir.c_str());
+        strcpy(info, sResourceDir.c_str());
         GetURLForComponent(mCompName, mURL, info, i % STREAM_COUNT);
+        if (!(strcmp(mURL, sResourceDir.c_str())) || !(strcmp(info, sResourceDir.c_str()))) {
+            ALOGV("Stream not available, skipping this index");
+            continue;
+        }
 
         eleInfo.open(info);
         ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -547,12 +723,13 @@
             eleInfo >> timestamp;
             timestamp += timestampOffset;
             Info.push_back({bytesCount, flags, timestamp});
-            bool codecConfig = flags ?
-                ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            bool codecConfig =
+                    flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            bool nonDisplayFrame = ((flags & FLAG_NON_DISPLAY_FRAME) != 0);
 
             {
                 ULock l(mQueueLock);
-                if (mTimestampDevTest && !codecConfig)
+                if (mTimestampDevTest && !codecConfig && !nonDisplayFrame)
                     mTimestampUslist.push_back(timestamp);
             }
             if (timestampMax < timestamp) timestampMax = timestamp;
@@ -565,10 +742,9 @@
         ALOGV("mURL : %s", mURL);
         eleStream.open(mURL, std::ifstream::binary);
         ASSERT_EQ(eleStream.is_open(), true);
-        ASSERT_NO_FATAL_FAILURE(
-            decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                          mFlushedIndices, mLinearPool, eleStream, &Info,
-                          offset, (int)(Info.size() - offset), false));
+        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, &Info,
+                                              offset, (int)(Info.size() - offset), false));
 
         eleStream.close();
         offset = (int)Info.size();
@@ -603,45 +779,34 @@
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     ALOGV("Waiting for input consumption");
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
     if (mFramesReceived != ((Info.size()) + 1)) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
-              Info.size() + 1);
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size() + 1);
         ASSERT_TRUE(false);
     }
 
     if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
 // thumbnail test
-TEST_F(Codec2VideoDecHidlTest, ThumbnailTest) {
+TEST_P(Codec2VideoDecHidlTest, ThumbnailTest) {
     description("Test Request for thumbnail");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
+    android::Vector<FrameInfo> Info;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true);
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
 
+    uint32_t flags = 0;
     for (size_t i = 0; i < MAX_ITERATIONS; i++) {
         ASSERT_EQ(mComponent->start(), C2_OK);
 
@@ -654,24 +819,26 @@
             if (Info[j].flags) flags = 1u << (Info[j].flags - 1);
 
         } while (!(flags & SYNC_FRAME));
+
+        std::ifstream eleStream;
         eleStream.open(mURL, std::ifstream::binary);
         ASSERT_EQ(eleStream.is_open(), true);
-        ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-            mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-            mFlushedIndices, mLinearPool, eleStream, &Info, 0, j + 1));
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                              j + 1));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
         eleStream.close();
         EXPECT_GE(mFramesReceived, 1U);
         ASSERT_EQ(mEos, true);
         ASSERT_EQ(mComponent->stop(), C2_OK);
     }
     ASSERT_EQ(mComponent->release(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-TEST_F(Codec2VideoDecHidlTest, EOSTest) {
+TEST_P(Codec2VideoDecHidlTest, EOSTest) {
     description("Test empty input buffer with EOS flag");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     typedef std::unique_lock<std::mutex> ULock;
     ASSERT_EQ(mComponent->start(), C2_OK);
     std::unique_ptr<C2Work> work;
@@ -707,76 +874,59 @@
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mWorkResult, C2_OK);
 }
 
-TEST_F(Codec2VideoDecHidlTest, FlushTest) {
+TEST_P(Codec2VideoDecHidlTest, FlushTest) {
     description("Tests Flush calls");
-    if (mDisableTest) return;
-    typedef std::unique_lock<std::mutex> ULock;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-    char mURL[512], info[512];
-    std::ifstream eleStream, eleInfo;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    ASSERT_EQ(mComponent->start(), C2_OK);
+
+    char mURL[512], info[512];
+    android::Vector<FrameInfo> Info;
+
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
-    eleInfo.open(info);
-    ASSERT_EQ(eleInfo.is_open(), true);
-    android::Vector<FrameInfo> Info;
-    int bytesCount = 0;
-    uint32_t flags = 0;
-    uint32_t timestamp = 0;
     mFlushedIndices.clear();
-    while (1) {
-        if (!(eleInfo >> bytesCount)) break;
-        eleInfo >> flags;
-        eleInfo >> timestamp;
-        Info.push_back({bytesCount, flags, timestamp});
-    }
-    eleInfo.close();
+
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << info;
 
     ALOGV("mURL : %s", mURL);
-    eleStream.open(mURL, std::ifstream::binary);
-    ASSERT_EQ(eleStream.is_open(), true);
-    // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
-    // frame after this so that the below section can be covered for all
-    // components
-    uint32_t numFramesFlushed = 128;
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, numFramesFlushed, false));
+
     // flush
     std::list<std::unique_ptr<C2Work>> flushedWork;
-    c2_status_t err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-                               (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
 
-    {
-        // Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            auto frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          work->input.ordinal.frameIndex.peeku());
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+    // Decode 30 frames and flush. here 30 is chosen to ensure there is a key
+    // frame after this so that the below section can be covered for all
+    // components
+    uint32_t numFramesFlushed = FLUSH_INTERVAL;
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          numFramesFlushed, false));
+    // flush
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
+    ASSERT_NO_FATAL_FAILURE(
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
     // Seek to next key frame and start decoding till the end
-    mFlushedIndices.clear();
     int index = numFramesFlushed;
     bool keyFrame = false;
-    flags = 0;
+    uint32_t flags = 0;
     while (index < (int)Info.size()) {
         if (Info[index].flags) flags = 1u << (Info[index].flags - 1);
         if ((flags & SYNC_FRAME) == SYNC_FRAME) {
@@ -788,47 +938,32 @@
         index++;
     }
     if (keyFrame) {
-        ASSERT_NO_FATAL_FAILURE(
-            decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                          mFlushedIndices, mLinearPool, eleStream, &Info, index,
-                          (int)Info.size() - index));
+        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mLinearPool, eleStream, &Info, index,
+                                              (int)Info.size() - index));
     }
     eleStream.close();
     err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-                               (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    {
-        // Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            uint64_t frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt = std::find(
-                mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    ASSERT_EQ(mFlushedIndices.empty(), true);
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    // TODO: (b/154671521)
+    // Add assert for mWorkResult
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
+TEST_P(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
     description("Decode with multiple empty input frames");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     char mURL[512], info[512];
     std::ifstream eleStream, eleInfo;
 
-    strcpy(mURL, gEnv->getRes().c_str());
-    strcpy(info, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
     GetURLForComponent(mCompName, mURL, info);
 
     eleInfo.open(info);
@@ -843,15 +978,16 @@
     // and empty input frames at an interval of 5 frames.
     while (1) {
         if (!(frameId % 5)) {
-            if (!(frameId % 20)) flags = 32;
-            else flags = 0;
+            if (!(frameId % 20))
+                flags = 32;
+            else
+                flags = 0;
             bytesCount = 0;
         } else {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
             eleInfo >> timestamp;
-            codecConfig = flags ?
-                ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+            codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
         }
         Info.push_back({bytesCount, flags, timestamp});
         frameId++;
@@ -862,39 +998,175 @@
     ALOGV("mURL : %s", mURL);
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
-    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
-        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
-        mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          (int)Info.size()));
 
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     if (!mEos) {
         ALOGV("Waiting for input consumption");
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
     }
 
     eleStream.close();
     if (mFramesReceived != Info.size()) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
-              Info.size());
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size());
         ASSERT_TRUE(false);
     }
 }
 
+class Codec2VideoDecCsdInputTests
+    : public Codec2VideoDecHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+// Test the codecs for the following
+// start - csd - data… - (with/without)flush - data… - flush - data…
+TEST_P(Codec2VideoDecCsdInputTests, CSDFlushTest) {
+    description("Tests codecs for flush at different states");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+
+    char mURL[512], info[512];
+
+    android::Vector<FrameInfo> Info;
+
+    strcpy(mURL, sResourceDir.c_str());
+    strcpy(info, sResourceDir.c_str());
+    GetURLForComponent(mCompName, mURL, info);
+
+    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file";
+
+    ASSERT_EQ(mComponent->start(), C2_OK);
+
+    ALOGV("mURL : %s", mURL);
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+    bool flushedDecoder = false;
+    bool signalEOS = false;
+    bool keyFrame = false;
+    bool flushCsd = !std::get<2>(GetParam()).compare("true");
+
+    ALOGV("sending %d csd data ", numCsds);
+    int framesToDecode = numCsds;
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+                                          framesToDecode, false));
+    c2_status_t err = C2_OK;
+    std::list<std::unique_ptr<C2Work>> flushedWork;
+    if (numCsds && flushCsd) {
+        // We wait for all the CSD buffers to get consumed.
+        // Once we have received all CSD work back, we call flush
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+        ASSERT_EQ(err, C2_OK);
+        flushedDecoder = true;
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                               MAX_INPUT_BUFFERS - flushedWork.size());
+        ASSERT_NO_FATAL_FAILURE(
+                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    }
+
+    int offset = framesToDecode;
+    uint32_t flags = 0;
+    while (1) {
+        while (offset < (int)Info.size()) {
+            flags = 0;
+            if (Info[offset].flags) flags = 1u << (Info[offset].flags - 1);
+            if (flags & SYNC_FRAME) {
+                keyFrame = true;
+                break;
+            }
+            eleStream.ignore(Info[offset].bytesCount);
+            offset++;
+        }
+        if (keyFrame) {
+            framesToDecode = c2_min(FLUSH_INTERVAL, (int)Info.size() - offset);
+            if (framesToDecode < FLUSH_INTERVAL) signalEOS = true;
+            ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+                    mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
+                    mLinearPool, eleStream, &Info, offset, framesToDecode, signalEOS));
+            offset += framesToDecode;
+        }
+        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+        ASSERT_EQ(err, C2_OK);
+        keyFrame = false;
+        // blocking call to ensures application to Wait till remaining
+        // 'non-flushed' inputs are consumed
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                               MAX_INPUT_BUFFERS - flushedWork.size());
+        ASSERT_NO_FATAL_FAILURE(
+                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+        if (signalEOS || offset >= (int)Info.size()) {
+            break;
+        }
+    }
+    if (!signalEOS) {
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+    }
+    eleStream.close();
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+// DecodeTest with StreamIndex and EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
+                         testing::ValuesIn(kDecodeTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2VideoDecCsdInputTests,
+                         testing::ValuesIn(kCsdFlushTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // anonymous namespace
 
 // TODO : Video specific configuration Test
 int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        int status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
+    kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
+    for (auto params : kTestParameters) {
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "false"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "true"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "2", "false"));
+        kDecodeTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "2", "true"));
+
+        kCsdFlushTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "true"));
+        kCsdFlushTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
     }
-    return status;
+
+    // Set the resource directory based on command line args.
+    // Test will fail to set up if the argument is not set.
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+            sResourceDir = argv[i + 1];
+            break;
+        }
+    }
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml
new file mode 100644
index 0000000..a1049df
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the"License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an"AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetVideoDecTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="vts_media_c2_v1_0_video_dec_test" value="/data/local/tmp/vts_media_c2_v1_0_video_dec_test" />
+
+        <!-- Files used for video testing -->
+        <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.h264" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.h264" />
+        <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.h264" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.h264" />
+        <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.info" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.info" />
+        <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.info" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.info" />
+        <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.hevc" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.hevc" />
+        <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.hevc" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.hevc" />
+        <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.info" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.info" />
+        <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.info" />
+        <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.m2v" />
+        <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.m2v" />
+        <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.info" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.info" />
+        <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.info" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.info" />
+        <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.h263" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.h263" />
+        <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.info" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.info" />
+        <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.m4v" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.m4v" />
+        <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.info" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.info" />
+        <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.vp8" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.vp8" />
+        <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.vp8" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.vp8" />
+        <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.info" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.info" />
+        <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.info" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.info" />
+        <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.vp9" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.vp9" />
+        <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.vp9" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.vp9" />
+        <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.info" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.info" />
+        <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.info" />
+        <option name="push-file" key="bbb_av1_640_360.av1" value="/data/local/tmp/media/bbb_av1_640_360.av1" />
+        <option name="push-file" key="bbb_av1_176_144.av1" value="/data/local/tmp/media/bbb_av1_176_144.av1" />
+        <option name="push-file" key="bbb_av1_640_360.info" value="/data/local/tmp/media/bbb_av1_640_360.info" />
+        <option name="push-file" key="bbb_av1_176_144.info" value="/data/local/tmp/media/bbb_av1_176_144.info" />
+        <option name="push-file" key="bbb_vp9_704x480_280kbps_24fps_altref_2.vp9" value="/data/local/tmp/media/bbb_vp9_704x480_280kbps_24fps_altref_2.vp9" />
+        <option name="push-file" key="bbb_vp9_704x480_280kbps_24fps_altref_2.info" value="/data/local/tmp/media/bbb_vp9_704x480_280kbps_24fps_altref_2.info" />
+        <option name="push-file" key="bbb_avc_176x144_300kbps_60fps_chksum.md5" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps_chksum.md5" />
+        <option name="push-file" key="bbb_avc_640x360_768kbps_30fps_chksum.md5" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps_chksum.md5" />
+        <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps_chksum.md5" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps_chksum.md5" />
+        <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps_chksum.md5" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps_chksum.md5" />
+        <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps_chksm.md5" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps_chksm.md5" />
+        <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps_chksm.md5" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps_chksm.md5" />
+        <option name="push-file" key="bbb_av1_640_360_chksum.md5" value="/data/local/tmp/media/bbb_av1_640_360_chksum.md5" />
+        <option name="push-file" key="bbb_av1_176_144_chksm.md5" value="/data/local/tmp/media/bbb_av1_176_144_chksm.md5" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_media_c2_v1_0_video_dec_test" />
+        <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index c1f5a92..ecaf3a8 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -19,72 +19,63 @@
 
 #include <android-base/logging.h>
 #include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <stdio.h>
 #include <fstream>
 
-#include <codec2/hidl/client.h>
 #include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
 #include <C2Buffer.h>
 #include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
 
 using android::C2AllocatorIon;
 
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_video_hidl_test_common.h"
 #include "media_c2_hidl_test_common.h"
+#include "media_c2_video_hidl_test_common.h"
 
 class GraphicBuffer : public C2Buffer {
-public:
-  explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
-      : C2Buffer({block->share(C2Rect(block->width(), block->height()),
-                               ::C2Fence())}) {}
+  public:
+    explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock>& block)
+        : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
 };
 
-static ComponentTestEnvironment* gEnv = nullptr;
+static std::vector<std::tuple<std::string, std::string, std::string, std::string, std::string>>
+        kEncodeTestParameters;
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+        kEncodeResolutionTestParameters;
+
+// Resource directory
+static std::string sResourceDir = "";
 
 namespace {
 
-class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
-    typedef ::testing::VtsHalHidlTargetTestBase Super;
-
-   public:
-    ::std::string getTestCaseInfo() const override {
-        return ::std::string() +
-                "Component: " + gEnv->getComponent().c_str() + " | " +
-                "Instance: " + gEnv->getInstance().c_str() + " | " +
-                "Res: " + gEnv->getRes().c_str();
-    }
-
+class Codec2VideoEncHidlTestBase : public ::testing::Test {
+  public:
     // google.codec2 Video test setup
     virtual void SetUp() override {
-        Super::SetUp();
+        getParams();
         mDisableTest = false;
         ALOGV("Codec2VideoEncHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+                mInstanceName.c_str(),
+                !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener(
-            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
-                handleWorkDone(workItems);
-            }));
+        mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+            handleWorkDone(workItems);
+        }));
         ASSERT_NE(mListener, nullptr);
         for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
             mWorkQueue.emplace_back(new C2Work);
         }
-        mClient->createComponent(gEnv->getComponent().c_str(), mListener,
-                                 &mComponent);
+        mClient->createComponent(mComponentName, mListener, &mComponent);
         ASSERT_NE(mComponent, nullptr);
 
-        std::shared_ptr<C2AllocatorStore> store =
-            android::GetCodec2PlatformAllocatorStore();
-        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC,
-                                       &mGraphicAllocator),
+        std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+        CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator),
                  C2_OK);
-        mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator,
-                                                           mBlockPoolId++);
+        mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
         ASSERT_NE(mGraphicPool, nullptr);
 
         mCompName = unknown_comp;
@@ -94,26 +85,26 @@
         };
 
         const StringToName kStringToName[] = {
-            {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
-            {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
+                {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
+                {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
         };
 
-        const size_t kNumStringToName =
-            sizeof(kStringToName) / sizeof(kStringToName[0]);
+        const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
 
         // Find the component type
-        std::string comp = std::string(gEnv->getComponent());
         for (size_t i = 0; i < kNumStringToName; ++i) {
-            if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+            if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
                 mCompName = kStringToName[i].CompName;
                 break;
             }
         }
         mEos = false;
         mCsd = false;
+        mConfigBPictures = false;
         mFramesReceived = 0;
         mFailedWorkReceived = 0;
         mTimestampUs = 0u;
+        mOutputSize = 0u;
         mTimestampDevTest = false;
         if (mCompName == unknown_comp) mDisableTest = true;
         if (mDisableTest) std::cout << "[   WARN   ] Test Disabled \n";
@@ -125,10 +116,12 @@
             mComponent->release();
             mComponent = nullptr;
         }
-        Super::TearDown();
     }
 
-    bool setupConfigParam(int32_t nWidth, int32_t nHeight);
+    // Get the test parameters from GetParam call.
+    virtual void getParams() {}
+
+    bool setupConfigParam(int32_t nWidth, int32_t nHeight, int32_t nBFrame = 0);
 
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
@@ -138,11 +131,11 @@
                 // previous timestamp
                 typedef std::unique_lock<std::mutex> ULock;
                 if (!mTimestampUslist.empty()) {
-                    EXPECT_GE((work->worklets.front()
-                                   ->output.ordinal.timestamp.peeku()),
-                              mTimestampUs);
-                    mTimestampUs = work->worklets.front()
-                                       ->output.ordinal.timestamp.peeku();
+                    if (!mConfigBPictures) {
+                        EXPECT_GE((work->worklets.front()->output.ordinal.timestamp.peeku()),
+                                  mTimestampUs);
+                    }
+                    mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
                     // Currently this lock is redundant as no mTimestampUslist is only initialized
                     // before queuing any work to component. Once AdaptiveTest is added similar to
                     // the one in video decoders, this is needed.
@@ -150,8 +143,7 @@
 
                     if (mTimestampDevTest) {
                         bool tsHit = false;
-                        std::list<uint64_t>::iterator it =
-                            mTimestampUslist.begin();
+                        std::list<uint64_t>::iterator it = mTimestampUslist.begin();
                         while (it != mTimestampUslist.end()) {
                             if (*it == mTimestampUs) {
                                 mTimestampUslist.erase(it);
@@ -162,21 +154,28 @@
                         }
                         if (tsHit == false) {
                             if (mTimestampUslist.empty() == false) {
-                                EXPECT_EQ(tsHit, true)
-                                    << "TimeStamp not recognized";
+                                EXPECT_EQ(tsHit, true) << "TimeStamp not recognized";
                             } else {
-                                std::cout
-                                    << "[   INFO   ] Received non-zero "
-                                       "output / TimeStamp not recognized \n";
+                                std::cout << "[   INFO   ] Received non-zero "
+                                             "output / TimeStamp not recognized \n";
                             }
                         }
                     }
                 }
 
                 if (work->result != C2_OK) mFailedWorkReceived++;
-                workDone(mComponent, work, mFlushedIndices, mQueueLock,
-                         mQueueCondition, mWorkQueue, mEos, mCsd,
-                         mFramesReceived);
+                if (!work->worklets.front()->output.buffers.empty()) {
+                    mOutputSize += work->worklets.front()
+                                           ->output.buffers[0]
+                                           ->data()
+                                           .linearBlocks()
+                                           .front()
+                                           .map()
+                                           .get()
+                                           .capacity();
+                }
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+                         mEos, mCsd, mFramesReceived);
             }
         }
     }
@@ -191,15 +190,18 @@
         unknown_comp,
     };
 
+    std::string mInstanceName;
+    std::string mComponentName;
     bool mEos;
     bool mCsd;
     bool mDisableTest;
-    bool mConfig;
+    bool mConfigBPictures;
     bool mTimestampDevTest;
     standardComp mCompName;
     uint32_t mFramesReceived;
     uint32_t mFailedWorkReceived;
     uint64_t mTimestampUs;
+    uint64_t mOutputSize;
 
     std::list<uint64_t> mTimestampUslist;
     std::list<uint64_t> mFlushedIndices;
@@ -216,15 +218,23 @@
     std::shared_ptr<android::Codec2Client::Listener> mListener;
     std::shared_ptr<android::Codec2Client::Component> mComponent;
 
-   protected:
+  protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
     }
 };
 
-void validateComponent(
-    const std::shared_ptr<android::Codec2Client::Component>& component,
-    Codec2VideoEncHidlTest::standardComp compName, bool& disableTest) {
+class Codec2VideoEncHidlTest
+    : public Codec2VideoEncHidlTestBase,
+      public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+                       Codec2VideoEncHidlTest::standardComp compName, bool& disableTest) {
     // Validate its a C2 Component
     if (component->getName().find("c2") == std::string::npos) {
         ALOGE("Not a c2 component");
@@ -239,14 +249,12 @@
         return;
     }
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err =
-        component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
-                         C2_DONT_BLOCK, &queried);
+    c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                         C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK && queried.size() == 0) {
         ALOGE("Query media type failed => %d", c2err);
     } else {
-        std::string inputDomain =
-            ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+        std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
         if (inputDomain.find("video/") == std::string::npos) {
             ALOGE("Expected Video Component");
             disableTest = true;
@@ -264,14 +272,27 @@
 }
 
 // Set Default config param.
-bool Codec2VideoEncHidlTest::setupConfigParam(int32_t nWidth, int32_t nHeight) {
+bool Codec2VideoEncHidlTestBase::setupConfigParam(int32_t nWidth, int32_t nHeight,
+                                                  int32_t nBFrame) {
+    c2_status_t status = C2_OK;
+    std::vector<std::unique_ptr<C2Param>> configParam;
     std::vector<std::unique_ptr<C2SettingResult>> failures;
-    C2StreamPictureSizeInfo::input inputSize(0u, nWidth, nHeight);
-    std::vector<C2Param*> configParam{&inputSize};
-    c2_status_t status =
-        mComponent->config(configParam, C2_DONT_BLOCK, &failures);
-    if (status == C2_OK && failures.size() == 0u) return true;
-    return false;
+
+    configParam.push_back(std::make_unique<C2StreamPictureSizeInfo::input>(0u, nWidth, nHeight));
+
+    if (nBFrame > 0) {
+        std::unique_ptr<C2StreamGopTuning::output> gop =
+                C2StreamGopTuning::output::AllocUnique(2 /* flexCount */, 0u /* stream */);
+        gop->m.values[0] = {P_FRAME, UINT32_MAX};
+        gop->m.values[1] = {C2Config::picture_type_t(P_FRAME | B_FRAME), uint32_t(nBFrame)};
+        configParam.push_back(std::move(gop));
+    }
+
+    for (const std::unique_ptr<C2Param>& param : configParam) {
+        status = mComponent->config({param.get()}, C2_DONT_BLOCK, &failures);
+        if (status != C2_OK || failures.size() != 0u) return false;
+    }
+    return true;
 }
 
 // LookUpTable of clips for component testing
@@ -280,19 +301,16 @@
 }
 
 void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
-                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::mutex& queueLock, std::condition_variable& queueCondition,
                    std::list<std::unique_ptr<C2Work>>& workQueue,
-                   std::list<uint64_t>& flushedIndices,
-                   std::shared_ptr<C2BlockPool>& graphicPool,
-                   std::ifstream& eleStream, bool& disableTest,
-                   uint32_t frameID, uint32_t nFrames, uint32_t nWidth,
-                   int32_t nHeight, bool flushed = false, bool signalEOS = true) {
+                   std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& graphicPool,
+                   std::ifstream& eleStream, bool& disableTest, uint32_t frameID, uint32_t nFrames,
+                   uint32_t nWidth, int32_t nHeight, bool flushed = false, bool signalEOS = true) {
     typedef std::unique_lock<std::mutex> ULock;
 
     uint32_t maxRetry = 0;
     int bytesCount = nWidth * nHeight * 3 >> 1;
     int32_t timestampIncr = ENCODER_TIMESTAMP_INCREMENT;
-    uint64_t timestamp = 0;
     c2_status_t err = C2_OK;
     while (1) {
         if (nFrames == 0) break;
@@ -312,15 +330,14 @@
         if (!work && (maxRetry >= MAX_RETRY)) {
             ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
         }
-        if (signalEOS && (nFrames == 1))
-            flags |= C2FrameData::FLAG_END_OF_STREAM;
+        if (signalEOS && (nFrames == 1)) flags |= C2FrameData::FLAG_END_OF_STREAM;
         if (flushed) {
             flags |= SYNC_FRAME;
             flushed = false;
         }
 
         work->input.flags = (C2FrameData::flags_t)flags;
-        work->input.ordinal.timestamp = timestamp;
+        work->input.ordinal.timestamp = frameID * timestampIncr;
         work->input.ordinal.frameIndex = frameID;
         {
             ULock l(queueLock);
@@ -334,9 +351,9 @@
             ASSERT_EQ(eleStream.gcount(), bytesCount);
         }
         std::shared_ptr<C2GraphicBlock> block;
-        err = graphicPool->fetchGraphicBlock(
-                nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
-                {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+        err = graphicPool->fetchGraphicBlock(nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
+                                             {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+                                             &block);
         if (err != C2_OK) {
             fprintf(stderr, "fetchGraphicBlock failed : %d\n", err);
             disableTest = true;
@@ -373,33 +390,41 @@
         ASSERT_EQ(component->queue(&items), C2_OK);
         ALOGV("Frame #%d size = %d queued", frameID, bytesCount);
         nFrames--;
-        timestamp += timestampIncr;
         frameID++;
         maxRetry = 0;
     }
 }
 
-TEST_F(Codec2VideoEncHidlTest, validateCompName) {
-    if (mDisableTest) return;
+TEST_P(Codec2VideoEncHidlTest, validateCompName) {
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ALOGV("Checks if the given component is a valid video component");
     validateComponent(mComponent, mCompName, mDisableTest);
     ASSERT_EQ(mDisableTest, false);
 }
 
-class Codec2VideoEncEncodeTest : public Codec2VideoEncHidlTest,
-                                 public ::testing::WithParamInterface<bool> {
+class Codec2VideoEncEncodeTest
+    : public Codec2VideoEncHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
 };
 
 TEST_P(Codec2VideoEncEncodeTest, EncodeTest) {
     description("Encodes input file");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     char mURL[512];
     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
     int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
-    bool signalEOS = GetParam();
+    bool signalEOS = !std::get<2>(GetParam()).compare("true");
+    // Send an empty frame to receive CSD data from encoder.
+    bool sendEmptyFirstFrame = !std::get<3>(GetParam()).compare("true");
+    mConfigBPictures = !std::get<4>(GetParam()).compare("true");
 
-    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
     GetURLForComponent(mURL);
 
     std::ifstream eleStream;
@@ -411,25 +436,52 @@
     mTimestampDevTest = true;
     mFlushedIndices.clear();
     mTimestampUslist.clear();
-    uint32_t inputFrames = ENC_NUM_FRAMES;
+    int32_t inputFrames = ENC_NUM_FRAMES + (sendEmptyFirstFrame ? 1 : 0);
     uint32_t timestamp = 0;
+
     // Add input timestamp to timestampUslist
     while (inputFrames) {
         if (mTimestampDevTest) mTimestampUslist.push_back(timestamp);
         timestamp += ENCODER_TIMESTAMP_INCREMENT;
         inputFrames--;
     }
-    if (!setupConfigParam(nWidth, nHeight)) {
+
+    if (!setupConfigParam(nWidth, nHeight, mConfigBPictures ? 1 : 0)) {
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    std::vector<std::unique_ptr<C2Param>> inParams;
+    c2_status_t c2_status = mComponent->query({}, {C2StreamGopTuning::output::PARAM_TYPE},
+                                              C2_DONT_BLOCK, &inParams);
+
+    if (c2_status != C2_OK || inParams.size() == 0) {
+        std::cout << "[   WARN   ] Bframe not supported for " << mComponentName
+                  << " resetting num BFrames to 0\n";
+        mConfigBPictures = false;
+    } else {
+        size_t offset = sizeof(C2Param);
+        C2Param* param = inParams[0].get();
+        int32_t numBFrames = *(int32_t*)((uint8_t*)param + offset);
+
+        if (!numBFrames) {
+            std::cout << "[   WARN   ] Bframe not supported for " << mComponentName
+                      << " resetting num BFrames to 0\n";
+            mConfigBPictures = false;
+        }
+    }
+
     ASSERT_EQ(mComponent->start(), C2_OK);
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      0, ENC_NUM_FRAMES, nWidth, nHeight, false, signalEOS));
+
+    if (sendEmptyFirstFrame) {
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue, 0, false));
+        inputFrames += 1;
+    }
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
+                                          inputFrames, ENC_NUM_FRAMES, nWidth, nHeight, false,
+                                          signalEOS));
     // mDisableTest will be set if buffer was not fetched properly.
-    // This may happen when resolution is not proper but config suceeded
+    // This may happen when resolution is not proper but config succeeded
     // In this cases, we skip encoding the input stream
     if (mDisableTest) {
         std::cout << "[   WARN   ] Test Disabled \n";
@@ -438,49 +490,42 @@
     }
 
     // If EOS is not sent, sending empty input with EOS flag
-    inputFrames = ENC_NUM_FRAMES;
+    inputFrames += ENC_NUM_FRAMES;
     if (!signalEOS) {
-        ASSERT_NO_FATAL_FAILURE(
-            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
-        ASSERT_NO_FATAL_FAILURE(
-            testInputBuffer(mComponent, mQueueLock, mWorkQueue,
-                            C2FrameData::FLAG_END_OF_STREAM, false));
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1);
+        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                                C2FrameData::FLAG_END_OF_STREAM, false));
         inputFrames += 1;
     }
 
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     ALOGD("Waiting for input consumption");
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
     eleStream.close();
     if (mFramesReceived != inputFrames) {
         ALOGE("Input buffer count and Output buffer count mismatch");
-        ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived,
-              inputFrames);
+        ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived, inputFrames);
         ASSERT_TRUE(false);
     }
 
-    if (!mCsd && (mCompName != vp8 && mCompName != vp9)) {
-        ASSERT_TRUE(false) << "CSD Buffer not received";
-    }
-
-    if (mCsd && (mCompName == vp8 || mCompName == vp9)) {
-        ASSERT_TRUE(false) << "CSD Buffer not expected";
+    if (mCompName == vp8 || mCompName == h263) {
+        ASSERT_FALSE(mCsd) << "CSD Buffer not expected";
+    } else if (mCompName != vp9) {
+        ASSERT_TRUE(mCsd) << "CSD Buffer not received";
     }
 
     if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+
+    // TODO: (b/155534991)
+    // Add assert for mFailedWorkReceived
 }
 
-// EncodeTest with EOS / No EOS
-INSTANTIATE_TEST_CASE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
-                        ::testing::Values(true, false));
-
-TEST_F(Codec2VideoEncHidlTest, EOSTest) {
+TEST_P(Codec2VideoEncHidlTest, EOSTest) {
     description("Test empty input buffer with EOS flag");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     ASSERT_EQ(mComponent->start(), C2_OK);
 
     typedef std::unique_lock<std::mutex> ULock;
@@ -516,17 +561,17 @@
     }
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mFailedWorkReceived, 0);
 }
 
-TEST_F(Codec2VideoEncHidlTest, FlushTest) {
+TEST_P(Codec2VideoEncHidlTest, FlushTest) {
     description("Test Request for flush");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
-    typedef std::unique_lock<std::mutex> ULock;
     char mURL[512];
     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
     int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
-    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(mURL, sResourceDir.c_str());
     GetURLForComponent(mURL);
 
     if (!setupConfigParam(nWidth, nHeight)) {
@@ -543,12 +588,19 @@
     eleStream.open(mURL, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
     ALOGV("mURL : %s", mURL);
+    // flush
+    std::list<std::unique_ptr<C2Work>> flushedWork;
+    c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    ASSERT_EQ(err, C2_OK);
     ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      0, numFramesFlushed, nWidth, nHeight));
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+                                          numFramesFlushed, nWidth, nHeight, false, false));
     // mDisableTest will be set if buffer was not fetched properly.
-    // This may happen when resolution is not proper but config suceeded
+    // This may happen when resolution is not proper but config succeeded
     // In this cases, we skip encoding the input stream
     if (mDisableTest) {
         std::cout << "[   WARN   ] Test Disabled \n";
@@ -556,40 +608,21 @@
         return;
     }
 
-    std::list<std::unique_ptr<C2Work>> flushedWork;
-    c2_status_t err =
-        mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+    // flush
+    err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    uint64_t frameIndex;
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt = std::find(
-                mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    mFlushedIndices.clear();
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      numFramesFlushed, numFrames - numFramesFlushed,
-                      nWidth, nHeight, true));
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
+                                          numFramesFlushed, numFrames - numFramesFlushed, nWidth,
+                                          nHeight, true));
     eleStream.close();
     // mDisableTest will be set if buffer was not fetched properly.
-    // This may happen when resolution is not proper but config suceeded
+    // This may happen when resolution is not proper but config succeeded
     // In this cases, we skip encoding the input stream
     if (mDisableTest) {
         std::cout << "[   WARN   ] Test Disabled \n";
@@ -599,33 +632,19 @@
 
     err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
     ASSERT_EQ(err, C2_OK);
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+                           (size_t)MAX_INPUT_BUFFERS - flushedWork.size());
     ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
-            (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
-    {
-        //Update mFlushedIndices based on the index received from flush()
-        ULock l(mQueueLock);
-        for (std::unique_ptr<C2Work>& work : flushedWork) {
-            ASSERT_NE(work, nullptr);
-            frameIndex = work->input.ordinal.frameIndex.peeku();
-            std::list<uint64_t>::iterator frameIndexIt = std::find(
-                mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
-            if (!mFlushedIndices.empty() &&
-                (frameIndexIt != mFlushedIndices.end())) {
-                mFlushedIndices.erase(frameIndexIt);
-                work->input.buffers.clear();
-                work->worklets.clear();
-                mWorkQueue.push_back(std::move(work));
-            }
-        }
-    }
-    ASSERT_EQ(mFlushedIndices.empty(), true);
+            verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
+    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
+    // TODO: (b/154671521)
+    // Add assert for mFailedWorkReceived
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2VideoEncHidlTest, InvalidBufferTest) {
+TEST_P(Codec2VideoEncHidlTest, InvalidBufferTest) {
     description("Tests feeding larger/smaller input buffer");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     std::ifstream eleStream;
     int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH / 2;
@@ -637,28 +656,24 @@
     }
     ASSERT_EQ(mComponent->start(), C2_OK);
 
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      0, 1, nWidth, nHeight, false, false));
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+                                          1, nWidth, nHeight, false, false));
 
     // Feed larger input buffer.
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      1, 1, nWidth*2, nHeight*2, false, false));
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 1,
+                                          1, nWidth * 2, nHeight * 2, false, false));
 
     // Feed smaller input buffer.
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      2, 1, nWidth/2, nHeight/2, false, true));
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 2,
+                                          1, nWidth / 2, nHeight / 2, false, true));
 
     // blocking call to ensures application to Wait till all the inputs are
     // consumed
     ALOGD("Waiting for input consumption");
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
     if (mFramesReceived != 3) {
         std::cout << "[   WARN   ] Component didn't receive all buffers back \n";
@@ -673,17 +688,23 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-class Codec2VideoEncResolutionTest : public Codec2VideoEncHidlTest,
-        public ::testing::WithParamInterface<std::pair<int32_t, int32_t> > {
+class Codec2VideoEncResolutionTest
+    : public Codec2VideoEncHidlTestBase,
+      public ::testing::WithParamInterface<
+              std::tuple<std::string, std::string, std::string, std::string>> {
+    void getParams() {
+        mInstanceName = std::get<0>(GetParam());
+        mComponentName = std::get<1>(GetParam());
+    }
 };
 
 TEST_P(Codec2VideoEncResolutionTest, ResolutionTest) {
     description("Tests encoding at different resolutions");
-    if (mDisableTest) return;
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
 
     std::ifstream eleStream;
-    int32_t nWidth = GetParam().first;
-    int32_t nHeight = GetParam().second;
+    int32_t nWidth = std::stoi(std::get<2>(GetParam()));
+    int32_t nHeight = std::stoi(std::get<3>(GetParam()));
     ALOGD("Trying encode for width %d height %d", nWidth, nHeight);
     mEos = false;
 
@@ -693,13 +714,12 @@
     }
     ASSERT_EQ(mComponent->start(), C2_OK);
 
-    ASSERT_NO_FATAL_FAILURE(
-        encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
-                      mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
-                      0, MAX_INPUT_BUFFERS, nWidth, nHeight, false, true));
+    ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                          mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+                                          MAX_INPUT_BUFFERS, nWidth, nHeight, false, true));
 
     // mDisableTest will be set if buffer was not fetched properly.
-    // This may happen when resolution is not proper but config suceeded
+    // This may happen when resolution is not proper but config succeeded
     // In this cases, we skip encoding the input stream
     if (mDisableTest) {
         std::cout << "[   WARN   ] Test Disabled \n";
@@ -708,31 +728,146 @@
     }
 
     ALOGD("Waiting for input consumption");
-    ASSERT_NO_FATAL_FAILURE(
-        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
 
     ASSERT_EQ(mEos, true);
     ASSERT_EQ(mComponent->stop(), C2_OK);
     ASSERT_EQ(mComponent->reset(), C2_OK);
 }
 
-INSTANTIATE_TEST_CASE_P(NonStdSizes, Codec2VideoEncResolutionTest, ::testing::Values(
-    std::make_pair(52, 18),
-    std::make_pair(365, 365),
-    std::make_pair(484, 362),
-    std::make_pair(244, 488)));
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(NonStdSizes, Codec2VideoEncResolutionTest,
+                         ::testing::ValuesIn(kEncodeResolutionTestParameters));
+
+// EncodeTest with EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
+                         ::testing::ValuesIn(kEncodeTestParameters));
+
+TEST_P(Codec2VideoEncHidlTest, AdaptiveBitrateTest) {
+    description("Encodes input file for different bitrates");
+    if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+
+    char mURL[512];
+
+    strcpy(mURL, sResourceDir.c_str());
+    GetURLForComponent(mURL);
+
+    std::ifstream eleStream;
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
+    ALOGV("mURL : %s", mURL);
+
+    mFlushedIndices.clear();
+
+    int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
+    int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
+    if (!setupConfigParam(nWidth, nHeight)) {
+        std::cout << "[   WARN   ] Test Skipped \n";
+        return;
+    }
+    ASSERT_EQ(mComponent->start(), C2_OK);
+
+    uint64_t prevOutputSize = 0u;
+    uint32_t bitrateValues[] = {100000, 64000, 200000};
+    uint32_t prevBitrate = 0;
+    int32_t inputFrameId = 0;
+
+    for (uint32_t curBitrate : bitrateValues) {
+        // Configuring bitrate
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        C2StreamBitrateInfo::output bitrate(0u, curBitrate);
+        std::vector<C2Param*> configParam{&bitrate};
+        c2_status_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+        if (status != C2_OK && failures.size() != 0u) {
+            ALOGW("BitRate Config failed, using previous bitrate");
+        }
+
+        ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+                                              mFlushedIndices, mGraphicPool, eleStream,
+                                              mDisableTest, inputFrameId, ENC_NUM_FRAMES, nWidth,
+                                              nHeight, false, false));
+        // mDisableTest will be set if buffer was not fetched properly.
+        // This may happen when resolution is not proper but config succeeded
+        // In this cases, we skip encoding the input stream
+        if (mDisableTest) {
+            std::cout << "[   WARN   ] Test Disabled \n";
+            ASSERT_EQ(mComponent->stop(), C2_OK);
+            return;
+        }
+        inputFrameId += ENC_NUM_FRAMES;
+        // blocking call to ensures application to Wait till all the inputs are
+        // consumed
+        ALOGD("Waiting for input consumption");
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+        // Change in bitrate may result in different outputSize
+        if (prevBitrate >= curBitrate) {
+            EXPECT_LE(mOutputSize, prevOutputSize);
+        } else {
+            EXPECT_GE(mOutputSize, prevOutputSize);
+        }
+        prevBitrate = curBitrate;
+        prevOutputSize = mOutputSize;
+        // Reset the file pointer and output size
+        mOutputSize = 0;
+        eleStream.seekg(0, eleStream.beg);
+    }
+
+    // Sending empty input with EOS flag
+    ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+                                            C2FrameData::FLAG_END_OF_STREAM, false));
+    inputFrameId += 1;
+    waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
+
+    eleStream.close();
+    if (mFramesReceived != inputFrameId) {
+        ALOGE("Input buffer count and Output buffer count mismatch");
+        ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived, inputFrameId);
+        ASSERT_TRUE(false);
+    }
+
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+}
 
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
-    gEnv = new ComponentTestEnvironment();
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        int status = RUN_ALL_TESTS();
-        LOG(INFO) << "C2 Test result = " << status;
+    kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
+    for (auto params : kTestParameters) {
+        constexpr char const* kBoolString[] = { "false", "true" };
+        for (size_t i = 0; i < 1 << 3; ++i) {
+            kEncodeTestParameters.push_back(std::make_tuple(
+                    std::get<0>(params), std::get<1>(params),
+                    kBoolString[i & 1],
+                    kBoolString[(i >> 1) & 1],
+                    kBoolString[(i >> 2) & 1]));
+        }
+
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "52", "18"));
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "365", "365"));
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "484", "362"));
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "244", "488"));
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "852", "608"));
+        kEncodeResolutionTestParameters.push_back(
+                std::make_tuple(std::get<0>(params), std::get<1>(params), "1400", "442"));
     }
-    return status;
+
+    // Set the resource directory based on command line args.
+    // Test will fail to set up if the argument is not set.
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+            sResourceDir = argv[i + 1];
+            break;
+        }
+    }
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml
new file mode 100644
index 0000000..260a616
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the"License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an"AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetVideoEncTest.">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="vts_media_c2_v1_0_video_enc_test" value="/data/local/tmp/vts_media_c2_v1_0_video_enc_test" />
+
+        <!-- Files used for video testing -->
+        <option name="push-file" key="bbb_352x288_420p_30fps_32frames.yuv" value="/data/local/tmp/media/bbb_352x288_420p_30fps_32frames.yuv" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_media_c2_v1_0_video_enc_test" />
+        <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
index e37ca38..d3a693b 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
@@ -29,5 +29,4 @@
  * Common video utils
  */
 
-
 #endif  // MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
new file mode 100644
index 0000000..386f6e2
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -0,0 +1,165 @@
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-client-defaults instead
+cc_library {
+    name: "libcodec2_hidl_client@1.1",
+
+    defaults: ["hidl_defaults"],
+
+    srcs: [
+        "OutputBufferQueue.cpp",
+        "types.cpp",
+    ],
+
+    header_libs: [
+        "libcodec2_internal", // private
+    ],
+
+    shared_libs: [
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libbase",
+        "libcodec2",
+        "libcodec2_hidl_client@1.0",
+        "libcodec2_vndk",
+        "libcutils",
+        "libgui",
+        "libhidlbase",
+        "liblog",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+        "libutils",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2",
+        "libcodec2_hidl_client@1.0",
+        "libgui",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+    ],
+}
+
+
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-defaults instead
+cc_library {
+    name: "libcodec2_hidl@1.1",
+    vendor_available: true,
+    min_sdk_version: "29",
+
+    defaults: ["hidl_defaults"],
+
+    srcs: [
+        "Component.cpp",
+        "ComponentInterface.cpp",
+        "ComponentStore.cpp",
+        "Configurable.cpp",
+        "InputBufferManager.cpp",
+        "InputSurface.cpp",
+        "InputSurfaceConnection.cpp",
+        "types.cpp",
+    ],
+
+    header_libs: [
+        "libbinder_headers",
+        "libsystem_headers",
+        "libcodec2_internal", // private
+    ],
+
+    shared_libs: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media@1.0",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "android.hardware.media.omx@1.0",
+        "libbase",
+        "libcodec2",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libstagefright_bufferpool@2.0.1",
+        "libstagefright_bufferqueue_helper_novndk",
+        "libui",
+        "libutils",
+    ],
+
+    target: {
+        vendor: {
+            exclude_shared_libs: [
+                "libstagefright_bufferqueue_helper_novndk",
+            ],
+            shared_libs: [
+                "libstagefright_bufferqueue_helper",
+            ],
+        },
+    },
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libhidlbase",
+        "libstagefright_bufferpool@2.0.1",
+        "libui",
+    ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+    name: "libcodec2-hidl-defaults@1.1",
+    defaults: ["libcodec2-impl-defaults"],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2_hidl@1.0",
+        "libcodec2_hidl@1.1",
+        "libcodec2_vndk",
+        "libhidlbase",
+    ],
+}
+
+// public dependency for Codec 2.0 HAL client
+cc_defaults {
+    name: "libcodec2-hidl-client-defaults@1.1",
+    defaults: ["libcodec2-impl-defaults"],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
+        "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
+        "libcodec2_vndk",
+        "libhidlbase",
+    ],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL service implementations
+cc_defaults {
+    name: "libcodec2-hidl-defaults",
+    defaults: ["libcodec2-hidl-defaults@1.1"],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL client
+cc_defaults {
+    name: "libcodec2-hidl-client-defaults",
+    defaults: ["libcodec2-hidl-client-defaults@1.1"],
+}
diff --git a/media/codec2/hidl/1.1/utils/Component.cpp b/media/codec2/hidl/1.1/utils/Component.cpp
new file mode 100644
index 0000000..ed281e6
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Component.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2019 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.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputBufferManager.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_1 {
+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;
+    c2_status_t status = CreateCodec2BlockPool(
+            static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+            mComponent,
+            &blockPool);
+    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();
+}
+
+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;
+    }
+}
+
+Component::~Component() {
+    InputBufferManager::unregisterFrameData(mListener);
+    mStore->reportComponentDeath(this);
+}
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/ComponentInterface.cpp b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
new file mode 100644
index 0000000..ccc30fe
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/ComponentInterface.h>
diff --git a/media/codec2/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
new file mode 100644
index 0000000..225cd09
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2019 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.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputSurface.h>
+#include <codec2/hidl/1.1/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>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+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;
+}
+
+// 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) {
+        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) {
+        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) {
+        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_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/Configurable.cpp b/media/codec2/hidl/1.1/utils/Configurable.cpp
new file mode 100644
index 0000000..1f3b2c7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Configurable.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/Configurable.h>
diff --git a/media/codec2/hidl/1.1/utils/InputBufferManager.cpp b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
new file mode 100644
index 0000000..45bfc86
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/InputBufferManager.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurface.cpp b/media/codec2/hidl/1.1/utils/InputSurface.cpp
new file mode 100644
index 0000000..ce40494
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/InputSurface.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
new file mode 100644
index 0000000..32154a7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/InputSurfaceConnection.h>
diff --git a/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
new file mode 100644
index 0000000..65756e8
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/OutputBufferQueue.h>
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
new file mode 100644
index 0000000..16c81d4
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2019 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_1_UTILS_COMPONENT_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/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.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.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_1 {
+
+using ::android::hardware::media::c2::V1_1::IComponent;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+
+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;
+    virtual Return<void> configureVideoTunnel(
+            uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) 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_1::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;
+};
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
new file mode 100644
index 0000000..723c5bd
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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_1_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ComponentInterface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
new file mode 100644
index 0000000..1f04391
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019 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_1_UTILS_COMPONENT_STORE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/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 {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+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;
+
+    // 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;
+
+    // Methods from ::android::hardware::media::c2::V1_1::IComponentStore.
+    virtual Return<void> createComponent_1_1(
+            const hidl_string& name,
+            const sp<IComponentListener>& listener,
+            const sp<IClientManager>& pool,
+            createComponent_1_1_cb _hidl_cb) 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_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
new file mode 100644
index 0000000..fd9091b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 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_1_UTILS_CONFIGURABLE_H
+#define CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ConfigurableC2Intf;
+using ::android::hardware::media::c2::V1_0::utils::ParameterCache;
+using ::android::hardware::media::c2::V1_0::utils::CachedConfigurable;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
new file mode 100644
index 0000000..8e7a91b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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_1_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputBufferManager;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
new file mode 100644
index 0000000..59223b7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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_1_UTILS_INPUT_SURFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
+
+#include <codec2/hidl/1.0/InputSurface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
new file mode 100644
index 0000000..7f695ef
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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_1_UTILS_INPUT_SURFACE_CONNECTION_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
+
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurfaceConnection;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
new file mode 100644
index 0000000..f77852d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 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_1_UTILS_OUTPUT_BUFFER_QUEUE
+#define CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
+
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
new file mode 100644
index 0000000..d0ba93d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019 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_1_UTILS_TYPES_H
+#define CODEC2_HIDL_V1_1_UTILS_TYPES_H
+
+#include <android/hardware/media/c2/1.1/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.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
+#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
+
+#include <codec2/hidl/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+
+using ::android::hardware::media::c2::V1_0::BaseBlock;
+using ::android::hardware::media::c2::V1_0::Block;
+using ::android::hardware::media::c2::V1_0::Buffer;
+using ::android::hardware::media::c2::V1_0::FieldDescriptor;
+using ::android::hardware::media::c2::V1_0::FieldId;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValues;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQuery;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQueryResult;
+using ::android::hardware::media::c2::V1_0::FrameData;
+using ::android::hardware::media::c2::V1_0::InfoBuffer;
+using ::android::hardware::media::c2::V1_0::ParamDescriptor;
+using ::android::hardware::media::c2::V1_0::ParamField;
+using ::android::hardware::media::c2::V1_0::ParamFieldValues;
+using ::android::hardware::media::c2::V1_0::ParamIndex;
+using ::android::hardware::media::c2::V1_0::Params;
+using ::android::hardware::media::c2::V1_0::PrimitiveValue;
+using ::android::hardware::media::c2::V1_0::SettingResult;
+using ::android::hardware::media::c2::V1_0::Status;
+using ::android::hardware::media::c2::V1_0::StructDescriptor;
+using ::android::hardware::media::c2::V1_0::ValueRange;
+using ::android::hardware::media::c2::V1_0::Work;
+using ::android::hardware::media::c2::V1_0::WorkBundle;
+using ::android::hardware::media::c2::V1_0::WorkOrdinal;
+using ::android::hardware::media::c2::V1_0::Worklet;
+
+using ::android::hardware::media::c2::V1_0::IComponentInterface;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+using ::android::hardware::media::c2::V1_0::IConfigurable;
+using ::android::hardware::media::c2::V1_0::IInputSink;
+using ::android::hardware::media::c2::V1_0::IInputSurface;
+using ::android::hardware::media::c2::V1_0::IInputSurfaceConnection;
+
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::toC2Status;
+
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Range;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RangeInfo;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Rect;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RectInfo;
+
+using ::android::hardware::media::c2::V1_0::utils::objcpy;
+using ::android::hardware::media::c2::V1_0::utils::parseParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::createParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::copyParamsFromBlob;
+using ::android::hardware::media::c2::V1_0::utils::updateParamsFromBlob;
+
+using ::android::hardware::media::c2::V1_0::utils::BufferPoolSender;
+using ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender;
+
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::displayBufferQueueBlock;
+
+using ::android::hardware::media::c2::V1_0::utils::operator<<;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_TYPES_H
diff --git a/media/codec2/hidl/1.1/utils/types.cpp b/media/codec2/hidl/1.1/utils/types.cpp
new file mode 100644
index 0000000..8c09023
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/types.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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 <codec2/hidl/1.1/types.h>
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index e184223..3c37990 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -9,15 +9,16 @@
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hardware.media.bufferpool@2.0",
         "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
         "libbase",
         "libbinder",
         "libcodec2",
         "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
         "libcodec2_vndk",
         "libcutils",
         "libgui",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libstagefright_bufferpool@2.0.1",
         "libui",
@@ -29,8 +30,11 @@
     ],
 
     export_shared_lib_headers: [
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.c2@1.1",
         "libcodec2",
         "libcodec2_hidl_client@1.0",
+        "libcodec2_hidl_client@1.1",
         "libcodec2_vndk",
     ],
 
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index c747190..7e4352d 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -19,6 +19,29 @@
 #include <android-base/logging.h>
 
 #include <codec2/hidl/client.h>
+#include <C2Debug.h>
+#include <C2BufferPriv.h>
+#include <C2PlatformSupport.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/IConfigurable.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+
+#include <android-base/properties.h>
+#include <bufferpool/ClientManager.h>
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.1/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <cutils/native_handle.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
+#include <hidl/HidlSupport.h>
 
 #include <deque>
 #include <iterator>
@@ -30,25 +53,6 @@
 #include <type_traits>
 #include <vector>
 
-#include <android-base/properties.h>
-#include <bufferpool/ClientManager.h>
-#include <cutils/native_handle.h>
-#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
-#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
-#include <hidl/HidlSupport.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/IConfigurable.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-
-#include <C2Debug.h>
-#include <C2BufferPriv.h>
-#include <C2PlatformSupport.h>
-
 namespace android {
 
 using ::android::hardware::hidl_vec;
@@ -56,8 +60,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
+using namespace ::android::hardware::media::c2::V1_1;
+using namespace ::android::hardware::media::c2::V1_1::utils;
 using namespace ::android::hardware::media::bufferpool::V2_0;
 using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
 
@@ -89,6 +93,69 @@
     return i;
 }
 
+class Client2Store : public C2ComponentStore {
+    std::shared_ptr<Codec2Client> mClient;
+
+public:
+    Client2Store(std::shared_ptr<Codec2Client> const& client)
+        : mClient(client) { }
+
+    virtual ~Client2Store() = default;
+
+    virtual c2_status_t config_sm(
+            std::vector<C2Param*> const &params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+        return mClient->config(params, C2_MAY_BLOCK, failures);
+    };
+
+    virtual c2_status_t copyBuffer(
+            std::shared_ptr<C2GraphicBuffer>,
+            std::shared_ptr<C2GraphicBuffer>) {
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createComponent(
+            C2String, std::shared_ptr<C2Component>* const component) {
+        component->reset();
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createInterface(
+            C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
+        interface->reset();
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t query_sm(
+            std::vector<C2Param*> const& stackParams,
+            std::vector<C2Param::Index> const& heapParamIndices,
+            std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
+        return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
+    }
+
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
+        return mClient->querySupportedParams(params);
+    }
+
+    virtual c2_status_t querySupportedValues_sm(
+            std::vector<C2FieldSupportedValuesQuery>& fields) const {
+        return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
+    }
+
+    virtual C2String getName() const {
+        return mClient->getName();
+    }
+
+    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
+        return mClient->getParamReflector();
+    }
+
+    virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
+        return std::vector<std::shared_ptr<C2Component::Traits const>>();
+    }
+};
+
 }  // unnamed namespace
 
 // This class caches a Codec2Client object and its component traits. The client
@@ -152,6 +219,7 @@
                 if (success) {
                     break;
                 }
+                invalidate();
                 using namespace std::chrono_literals;
                 static constexpr auto kServiceRetryPeriod = 5s;
                 LOG(INFO) << "Failed to retrieve component traits from service "
@@ -514,8 +582,24 @@
 
 };
 
+// Codec2Client::Component::BufferPoolSender
+struct Codec2Client::Component::BufferPoolSender :
+        hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
+    BufferPoolSender()
+          : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
+    }
+};
+
+// Codec2Client::Component::OutputBufferQueue
+struct Codec2Client::Component::OutputBufferQueue :
+        hardware::media::c2::V1_1::utils::OutputBufferQueue {
+    OutputBufferQueue()
+          : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
+    }
+};
+
 // Codec2Client
-Codec2Client::Codec2Client(const sp<IComponentStore>& base,
+Codec2Client::Codec2Client(sp<Base> const& base,
                            size_t serviceIndex)
       : Configurable{
             [base]() -> sp<IConfigurable> {
@@ -526,7 +610,8 @@
                         nullptr;
             }()
         },
-        mBase{base},
+        mBase1_0{base},
+        mBase1_1{Base1_1::castFrom(base)},
         mServiceIndex{serviceIndex} {
     Return<sp<IClientManager>> transResult = base->getPoolClientManager();
     if (!transResult.isOk()) {
@@ -537,7 +622,15 @@
 }
 
 sp<Codec2Client::Base> const& Codec2Client::getBase() const {
-    return mBase;
+    return mBase1_0;
+}
+
+sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
+    return mBase1_0;
+}
+
+sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
+    return mBase1_1;
 }
 
 std::string const& Codec2Client::getServiceName() const {
@@ -552,7 +645,8 @@
     c2_status_t status;
     sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
     hidlListener->base = listener;
-    Return<void> transStatus = mBase->createComponent(
+    Return<void> transStatus = mBase1_1 ?
+        mBase1_1->createComponent_1_1(
             name,
             hidlListener,
             ClientManager::getInstance(),
@@ -565,14 +659,33 @@
                 }
                 *component = std::make_shared<Codec2Client::Component>(c);
                 hidlListener->component = *component;
+            }) :
+        mBase1_0->createComponent(
+            name,
+            hidlListener,
+            ClientManager::getInstance(),
+            [&status, component, hidlListener](
+                    Status s,
+                    const sp<hardware::media::c2::V1_0::IComponent>& c) {
+                status = static_cast<c2_status_t>(s);
+                if (status != C2_OK) {
+                    return;
+                }
+                *component = std::make_shared<Codec2Client::Component>(c);
+                hidlListener->component = *component;
             });
     if (!transStatus.isOk()) {
         LOG(ERROR) << "createComponent(" << name.c_str()
                    << ") -- transaction failed.";
         return C2_TRANSACTION_FAILED;
     } else if (status != C2_OK) {
-        LOG(ERROR) << "createComponent(" << name.c_str()
-                   << ") -- call failed: " << status << ".";
+        if (status == C2_NOT_FOUND) {
+            LOG(VERBOSE) << "createComponent(" << name.c_str()
+                         << ") -- component not found.";
+        } else {
+            LOG(ERROR) << "createComponent(" << name.c_str()
+                       << ") -- call failed: " << status << ".";
+        }
         return status;
     } else if (!*component) {
         LOG(ERROR) << "createComponent(" << name.c_str()
@@ -587,7 +700,7 @@
                    << status << ".";
     }
 
-    (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
+    (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
     return status;
 }
 
@@ -595,7 +708,7 @@
         const C2String& name,
         std::shared_ptr<Codec2Client::Interface>* const interface) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createInterface(
+    Return<void> transStatus = mBase1_0->createInterface(
             name,
             [&status, interface](
                     Status s,
@@ -611,8 +724,13 @@
                    << ") -- transaction failed.";
         return C2_TRANSACTION_FAILED;
     } else if (status != C2_OK) {
-        LOG(ERROR) << "createComponent(" << name.c_str()
-                   << ") -- call failed: " << status << ".";
+        if (status == C2_NOT_FOUND) {
+            LOG(VERBOSE) << "createInterface(" << name.c_str()
+                         << ") -- component not found.";
+        } else {
+            LOG(ERROR) << "createInterface(" << name.c_str()
+                       << ") -- call failed: " << status << ".";
+        }
         return status;
     }
 
@@ -622,7 +740,7 @@
 c2_status_t Codec2Client::createInputSurface(
         std::shared_ptr<InputSurface>* const inputSurface) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createInputSurface(
+    Return<void> transStatus = mBase1_0->createInputSurface(
             [&status, inputSurface](
                     Status s,
                     const sp<IInputSurface>& i) {
@@ -650,7 +768,7 @@
         bool* success) const {
     std::vector<C2Component::Traits> traits;
     std::string const& serviceName = getServiceName();
-    Return<void> transStatus = mBase->listComponents(
+    Return<void> transStatus = mBase1_0->listComponents(
             [&traits, &serviceName](Status s,
                    const hidl_vec<IComponentStore::ComponentTraits>& t) {
                 if (s != Status::OK) {
@@ -734,7 +852,7 @@
         sp<Base> mBase;
     };
 
-    return std::make_shared<SimpleParamReflector>(mBase);
+    return std::make_shared<SimpleParamReflector>(mBase1_0);
 };
 
 std::vector<std::string> const& Codec2Client::GetServiceNames() {
@@ -806,10 +924,24 @@
 }
 
 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
-        const char* name) {
+        const char* name,
+        bool setAsPreferredCodec2ComponentStore) {
     size_t index = getServiceIndex(name);
-    return index == GetServiceNames().size() ?
-            nullptr : _CreateFromIndex(index);
+    if (index == GetServiceNames().size()) {
+        if (setAsPreferredCodec2ComponentStore) {
+            LOG(WARNING) << "CreateFromService(" << name
+                         << ") -- preferred C2ComponentStore not set.";
+        }
+        return nullptr;
+    }
+    std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
+    if (setAsPreferredCodec2ComponentStore) {
+        SetPreferredCodec2ComponentStore(
+                std::make_shared<Client2Store>(client));
+        LOG(INFO) << "CreateFromService(" << name
+                  << ") -- service set as preferred C2ComponentStore.";
+    }
+    return client;
 }
 
 std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
@@ -825,11 +957,11 @@
 
 std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
     std::string const& name = GetServiceNames()[index];
-    LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
+    LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
     sp<Base> baseStore = Base::getService(name);
     CHECK(baseStore) << "Codec2 service \"" << name << "\""
                         " inaccessible for unknown reasons.";
-    LOG(INFO) << "Client to Codec2 service \"" << name << "\" created";
+    LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
     return std::make_shared<Codec2Client>(baseStore, index);
 }
 
@@ -1053,8 +1185,32 @@
                         nullptr;
             }()
         },
-        mBase{base},
-        mBufferPoolSender{nullptr} {
+        mBase1_0{base},
+        mBase1_1{Base1_1::castFrom(base)},
+        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const sp<Base1_1>& base)
+      : Configurable{
+            [base]() -> sp<IConfigurable> {
+                Return<sp<IComponentInterface>> transResult1 =
+                        base->getInterface();
+                if (!transResult1.isOk()) {
+                    return nullptr;
+                }
+                Return<sp<IConfigurable>> transResult2 =
+                        static_cast<sp<IComponentInterface>>(transResult1)->
+                        getConfigurable();
+                return transResult2.isOk() ?
+                        static_cast<sp<IConfigurable>>(transResult2) :
+                        nullptr;
+            }()
+        },
+        mBase1_0{base},
+        mBase1_1{base},
+        mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+        mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
 }
 
 Codec2Client::Component::~Component() {
@@ -1065,7 +1221,7 @@
         C2BlockPool::local_id_t* blockPoolId,
         std::shared_ptr<Codec2Client::Configurable>* configurable) {
     c2_status_t status;
-    Return<void> transStatus = mBase->createBlockPool(
+    Return<void> transStatus = mBase1_0->createBlockPool(
             static_cast<uint32_t>(id),
             [&status, blockPoolId, configurable](
                     Status s,
@@ -1090,7 +1246,7 @@
 
 c2_status_t Codec2Client::Component::destroyBlockPool(
         C2BlockPool::local_id_t localId) {
-    Return<Status> transResult = mBase->destroyBlockPool(
+    Return<Status> transResult = mBase1_0->destroyBlockPool(
             static_cast<uint64_t>(localId));
     if (!transResult.isOk()) {
         LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1102,17 +1258,17 @@
 void Codec2Client::Component::handleOnWorkDone(
         const std::list<std::unique_ptr<C2Work>> &workItems) {
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueue.holdBufferQueueBlocks(workItems);
+    mOutputBufferQueue->holdBufferQueueBlocks(workItems);
 }
 
 c2_status_t Codec2Client::Component::queue(
         std::list<std::unique_ptr<C2Work>>* const items) {
     WorkBundle workBundle;
-    if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
+    if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
         LOG(ERROR) << "queue -- bad input.";
         return C2_TRANSACTION_FAILED;
     }
-    Return<Status> transStatus = mBase->queue(workBundle);
+    Return<Status> transStatus = mBase1_0->queue(workBundle);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "queue -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1130,7 +1286,7 @@
         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 = mBase->flush(
+    Return<void> transStatus = mBase1_0->flush(
             [&status, flushedWork](
                     Status s, const WorkBundle& wb) {
                 status = static_cast<c2_status_t>(s);
@@ -1165,13 +1321,13 @@
     }
 
     // Output bufferqueue-based blocks' lifetime management
-    mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
+    mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
 
     return status;
 }
 
 c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
-    Return<Status> transStatus = mBase->drain(
+    Return<Status> transStatus = mBase1_0->drain(
             mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
     if (!transStatus.isOk()) {
         LOG(ERROR) << "drain -- transaction failed.";
@@ -1186,7 +1342,7 @@
 }
 
 c2_status_t Codec2Client::Component::start() {
-    Return<Status> transStatus = mBase->start();
+    Return<Status> transStatus = mBase1_0->start();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "start -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1200,7 +1356,7 @@
 }
 
 c2_status_t Codec2Client::Component::stop() {
-    Return<Status> transStatus = mBase->stop();
+    Return<Status> transStatus = mBase1_0->stop();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "stop -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1214,7 +1370,7 @@
 }
 
 c2_status_t Codec2Client::Component::reset() {
-    Return<Status> transStatus = mBase->reset();
+    Return<Status> transStatus = mBase1_0->reset();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "reset -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1228,7 +1384,7 @@
 }
 
 c2_status_t Codec2Client::Component::release() {
-    Return<Status> transStatus = mBase->release();
+    Return<Status> transStatus = mBase1_0->release();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "release -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1241,6 +1397,29 @@
     return status;
 }
 
+c2_status_t Codec2Client::Component::configureVideoTunnel(
+        uint32_t avSyncHwId,
+        native_handle_t** sidebandHandle) {
+    *sidebandHandle = nullptr;
+    if (!mBase1_1) {
+        return C2_OMITTED;
+    }
+    c2_status_t status{};
+    Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+            [&status, sidebandHandle](
+                    Status s, hardware::hidl_handle const& h) {
+                status = static_cast<c2_status_t>(s);
+                if (h.getNativeHandle()) {
+                    *sidebandHandle = native_handle_clone(h.getNativeHandle());
+                }
+            });
+    if (!transStatus.isOk()) {
+        LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
+        return C2_TRANSACTION_FAILED;
+    }
+    return status;
+}
+
 c2_status_t Codec2Client::Component::setOutputSurface(
         C2BlockPool::local_id_t blockPoolId,
         const sp<IGraphicBufferProducer>& surface,
@@ -1256,18 +1435,18 @@
     }
 
     if (!surface) {
-        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+        mOutputBufferQueue->configure(nullIgbp, generation, 0);
     } else if (surface->getUniqueId(&bqId) != OK) {
         LOG(ERROR) << "setOutputSurface -- "
                    "cannot obtain bufferqueue id.";
         bqId = 0;
-        mOutputBufferQueue.configure(nullIgbp, generation, 0);
+        mOutputBufferQueue->configure(nullIgbp, generation, 0);
     } else {
-        mOutputBufferQueue.configure(surface, generation, bqId);
+        mOutputBufferQueue->configure(surface, generation, bqId);
     }
     ALOGD("generation remote change %u", generation);
 
-    Return<Status> transStatus = mBase->setOutputSurface(
+    Return<Status> transStatus = mBase1_0->setOutputSurface(
             static_cast<uint64_t>(blockPoolId),
             bqId == 0 ? nullHgbp : igbp);
     if (!transStatus.isOk()) {
@@ -1286,14 +1465,14 @@
         const C2ConstGraphicBlock& block,
         const QueueBufferInput& input,
         QueueBufferOutput* output) {
-    return mOutputBufferQueue.outputBuffer(block, input, output);
+    return mOutputBufferQueue->outputBuffer(block, input, output);
 }
 
 c2_status_t Codec2Client::Component::connectToInputSurface(
         const std::shared_ptr<InputSurface>& inputSurface,
         std::shared_ptr<InputSurfaceConnection>* connection) {
     c2_status_t status;
-    Return<void> transStatus = mBase->connectToInputSurface(
+    Return<void> transStatus = mBase1_0->connectToInputSurface(
             inputSurface->mBase,
             [&status, connection](
                     Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1317,7 +1496,7 @@
         const sp<HGraphicBufferSource>& source,
         std::shared_ptr<InputSurfaceConnection>* connection) {
     c2_status_t status;
-    Return<void> transStatus = mBase->connectToOmxInputSurface(
+    Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
             producer, source,
             [&status, connection](
                     Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1337,7 +1516,7 @@
 }
 
 c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
-    Return<Status> transStatus = mBase->disconnectFromInputSurface();
+    Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
     if (!transStatus.isOk()) {
         LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
         return C2_TRANSACTION_FAILED;
@@ -1376,7 +1555,7 @@
     deathRecipient->component = component;
 
     component->mDeathRecipient = deathRecipient;
-    Return<bool> transResult = component->mBase->linkToDeath(
+    Return<bool> transResult = component->mBase1_0->linkToDeath(
             component->mDeathRecipient, 0);
     if (!transResult.isOk()) {
         LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index c37407f..ffd194a 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -17,14 +17,13 @@
 #ifndef CODEC2_HIDL_CLIENT_H
 #define CODEC2_HIDL_CLIENT_H
 
-#include <gui/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/ClientBlockHelper.h>
 #include <C2PlatformSupport.h>
 #include <C2Component.h>
 #include <C2Buffer.h>
 #include <C2Param.h>
 #include <C2.h>
 
+#include <gui/IGraphicBufferProducer.h>
 #include <hidl/HidlSupport.h>
 #include <utils/StrongPointer.h>
 
@@ -74,6 +73,11 @@
 struct IInputSurfaceConnection;
 }  // namespace android::hardware::media::c2::V1_0
 
+namespace android::hardware::media::c2::V1_1 {
+struct IComponent;
+struct IComponentStore;
+}  // namespace android::hardware::media::c2::V1_1
+
 namespace android::hardware::media::bufferpool::V2_0 {
 struct IClientManager;
 }  // namespace android::hardware::media::bufferpool::V2_0
@@ -82,6 +86,10 @@
 struct IGraphicBufferProducer;
 }  // android::hardware::graphics::bufferqueue::V1_0
 
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}  // android::hardware::graphics::bufferqueue::V2_0
+
 namespace android::hardware::media::omx::V1_0 {
 struct IGraphicBufferSource;
 }  // namespace android::hardware::media::omx::V1_0
@@ -127,7 +135,9 @@
 
 struct Codec2Client : public Codec2ConfigurableClient {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
+    typedef Base1_0 Base;
 
     struct Listener;
 
@@ -144,6 +154,8 @@
     typedef Codec2Client Store;
 
     sp<Base> const& getBase() const;
+    sp<Base1_0> const& getBase1_0() const;
+    sp<Base1_1> const& getBase1_1() const;
 
     std::string const& getServiceName() const;
 
@@ -172,8 +184,15 @@
     // Note: A software service will have "_software" as a suffix.
     static std::vector<std::string> const& GetServiceNames();
 
-    // Create a service with a given service name.
-    static std::shared_ptr<Codec2Client> CreateFromService(char const* name);
+    // Create a client to a service with a given name.
+    //
+    // After a client to the service is successfully created, if
+    // setAsPreferredCodec2ComponentStore is true, the component store that the
+    // service hosts will be set as the preferred C2ComponentStore for this
+    // process. (See SetPreferredCodec2ComponentStore() for more information.)
+    static std::shared_ptr<Codec2Client> CreateFromService(
+            char const* name,
+            bool setAsPreferredCodec2ComponentStore = false);
 
     // Get clients to all services.
     static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();
@@ -206,7 +225,8 @@
     Codec2Client(sp<Base> const& base, size_t serviceIndex);
 
 protected:
-    sp<Base> mBase;
+    sp<Base1_0> mBase1_0;
+    sp<Base1_1> mBase1_1;
 
     // 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
@@ -295,7 +315,9 @@
 
 struct Codec2Client::Component : public Codec2Client::Configurable {
 
-    typedef ::android::hardware::media::c2::V1_0::IComponent Base;
+    typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
+    typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
+    typedef Base1_0 Base;
 
     c2_status_t createBlockPool(
             C2Allocator::id_t id,
@@ -322,6 +344,17 @@
 
     c2_status_t release();
 
+    /**
+     * Use tunneling.
+     *
+     * On success, @p sidebandHandle will be a newly allocated native handle.
+     * File descriptors in @p sidebandHandle must be closed and
+     * @p sidebandHandle itself must be deleted afterwards.
+     */
+    c2_status_t configureVideoTunnel(
+            uint32_t avSyncHwId,
+            native_handle_t** sidebandHandle);
+
     typedef ::android::
             IGraphicBufferProducer IGraphicBufferProducer;
     typedef IGraphicBufferProducer::
@@ -378,17 +411,19 @@
 
     // base cannot be null.
     Component(const sp<Base>& base);
+    Component(const sp<Base1_1>& base);
 
     ~Component();
 
 protected:
-    sp<Base> mBase;
+    sp<Base1_0> mBase1_0;
+    sp<Base1_1> mBase1_1;
 
-    ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
-            mBufferPoolSender;
+    struct BufferPoolSender;
+    std::unique_ptr<BufferPoolSender> mBufferPoolSender;
 
-    ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue
-            mOutputBufferQueue;
+    struct OutputBufferQueue;
+    std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
 
     static c2_status_t setDeathListener(
             const std::shared_ptr<Component>& component,
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 216525e..a16b106 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -1,39 +1,87 @@
+/*
+ * Copyright 2019 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.
+ */
+
+// This is an example of an empty Codec2.0 service.
+//
+// To use this, make a copy of this whole directory and rename modules
+// accordingly. The contents of "vendor.cpp" and files in the subdirectory
+// "seccomp_policy" may also need to be modified.
+
+// Binary file for the service.
+//
+// The init_rc file contains the absolute path to this binary on the device.
+// If the name of this module is modified, the content of the init_rc file has
+// to be modified accordingly.
+//
+// The seccomp_policy file name and its content can be modified, but note that
+// vendor.cpp also needs to be updated because it needs the absolute path to the
+// seccomp policy file on the device.
 cc_binary {
-    name: "android.hardware.media.c2@1.0-service",
-    defaults: ["hidl_defaults"],
-    soc_specific: true,
+    name: "android.hardware.media.c2@1.1-default-service",
+    vendor: true,
     relative_install_path: "hw",
+
+    init_rc: ["android.hardware.media.c2@1.1-default-service.rc"],
+
+    defaults: ["libcodec2-hidl-defaults"],
     srcs: [
         "vendor.cpp",
     ],
 
-    init_rc: ["android.hardware.media.c2@1.0-service.rc"],
-
+    // minijail is used to protect against unexpected system calls.
     shared_libs: [
-        "android.hardware.media.c2@1.0",
-        "android.hardware.media.omx@1.0",
         "libavservices_minijail_vendor",
         "libbinder",
-        "libcodec2_hidl@1.0",
-        "libcodec2_vndk",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libstagefright_omx",
-        "libstagefright_xmlparser",
-        "libutils",
     ],
+    required: ["android.hardware.media.c2@1.1-default-seccomp_policy"],
 
+    // The content in manifest_media_c2_V1_1_default.xml can be included
+    // directly in the main device manifest.xml file or via vintf_fragments.
+    // (Remove the line below if the entry is already in the main manifest.)
+    vintf_fragments: ["manifest_media_c2_V1_1_default.xml"],
+}
+
+// seccomp policy file.
+//
+// This should be modified to suit the target device and architecture.
+//
+// Files in the "seccomp_policy" subdirectory are only provided as examples.
+// They may not work on some devices and/or architectures without modification.
+prebuilt_etc {
+    name: "android.hardware.media.c2@1.1-default-seccomp_policy",
+    vendor: true,
+    sub_dir: "seccomp_policy",
+
+    // If a specific architecture is targeted, multiple choices are not needed.
     arch: {
         arm: {
-            required: ["codec2.vendor.base.policy"],
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy",
+        },
+        arm64: {
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy",
         },
         x86: {
-            required: ["codec2.vendor.base.policy"],
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy",
+        },
+        x86_64: {
+            src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy",
         },
     },
 
-    compile_multilib: "32",
+    // This may be removed.
+    required: ["crash_dump.policy"],
 }
 
diff --git a/media/codec2/hidl/services/Android.mk b/media/codec2/hidl/services/Android.mk
deleted file mode 100644
index d9b28e7..0000000
--- a/media/codec2/hidl/services/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# vendor service seccomp policy
-ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH), x86 x86_64 arm arm64))
-include $(CLEAR_VARS)
-LOCAL_MODULE := codec2.vendor.base.policy
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_REQUIRED_MODULES := crash_dump.policy
-ifdef TARGET_2ND_ARCH
-    ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-        LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_2ND_ARCH).policy
-    else
-        LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
-    endif
-else
-    LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
-endif
-include $(BUILD_PREBUILT)
-endif
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
deleted file mode 100644
index 8806bd1..0000000
--- a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service
-    class hal
-    user mediacodec
-    group camera mediadrm drmrpc
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
new file mode 100644
index 0000000..44f2d8e
--- /dev/null
+++ b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal-1-1 /vendor/bin/hw/android.hardware.media.c2@1.1-default-service
+    class hal
+    user mediacodec
+    group camera mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
+
diff --git a/media/codec2/hidl/services/manifest_media_c2_V1_0_default.xml b/media/codec2/hidl/services/manifest_media_c2_V1_0_default.xml
new file mode 100644
index 0000000..e97c3ce
--- /dev/null
+++ b/media/codec2/hidl/services/manifest_media_c2_V1_0_default.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal>
+        <name>android.hardware.media.c2</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IComponentStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/media/codec2/hidl/services/manifest_media_c2_V1_1_default.xml b/media/codec2/hidl/services/manifest_media_c2_V1_1_default.xml
new file mode 100644
index 0000000..bf0d72f
--- /dev/null
+++ b/media/codec2/hidl/services/manifest_media_c2_V1_1_default.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal>
+        <name>android.hardware.media.c2</name>
+        <transport>hwbinder</transport>
+        <version>1.1</version>
+        <interface>
+            <name>IComponentStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
new file mode 100644
index 0000000..9042cd7
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
@@ -0,0 +1,86 @@
+# Copyright (C) 2019 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.
+
+futex: 1
+# ioctl calls are filtered via the selinux policy.
+ioctl: 1
+sched_yield: 1
+close: 1
+dup: 1
+ppoll: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap2: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
+# parser support for '<' is in this needs to be modified to also prevent
+# |old_address| and |new_address| from touching the exception vector page, which
+# on ARM is statically loaded at 0xffff 0000. See
+# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
+# for more details.
+mremap: arg3 == 3
+munmap: 1
+prctl: 1
+getuid32: 1
+writev: 1
+sigaltstack: 1
+clone: 1
+exit: 1
+lseek: 1
+rt_sigprocmask: 1
+openat: 1
+open: 1
+fstat64: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+readlink: 1
+read: 1
+pread64: 1
+fstatfs64: 1
+gettimeofday: 1
+faccessat: 1
+_llseek: 1
+fstatat64: 1
+ugetrlimit: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
+getrandom: 1
+madvise: 1
+
+# crash dump policy additions
+sigreturn: 1
+clock_gettime: 1
+futex: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
+#mprotect: arg2 in 0x1|0x2
+#mmap2: arg2 in 0x1|0x2
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
new file mode 100644
index 0000000..4faf8b2
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
@@ -0,0 +1,81 @@
+# Copyright (C) 2019 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.
+
+futex: 1
+# ioctl calls are filtered via the selinux policy.
+ioctl: 1
+sched_yield: 1
+close: 1
+dup: 1
+ppoll: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+getuid: 1
+getrlimit: 1
+fstat: 1
+newfstatat: 1
+fstatfs: 1
+memfd_create: 1
+ftruncate: 1
+
+# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
+# parser support for '<' is in this needs to be modified to also prevent
+# |old_address| and |new_address| from touching the exception vector page, which
+# on ARM is statically loaded at 0xffff 0000. See
+# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
+# for more details.
+mremap: arg3 == 3
+munmap: 1
+prctl: 1
+writev: 1
+sigaltstack: 1
+clone: 1
+exit: 1
+lseek: 1
+rt_sigprocmask: 1
+openat: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+read: 1
+pread64: 1
+gettimeofday: 1
+faccessat: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
+getrandom: 1
+madvise: 1
+
+# crash dump policy additions
+clock_gettime: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#mprotect: arg2 in 0x1|0x2
+munmap: 1
+#mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
new file mode 100644
index 0000000..d9c4045
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
@@ -0,0 +1,71 @@
+# Copyright (C) 2017 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+open: 1
+getuid32: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap2: 1
+mmap: 1
+fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
+madvise: 1
+fstatat64: 1
+newfstatat: 1
+futex: 1
+munmap: 1
+faccessat: 1
+_llseek: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+ugetrlimit: 1
+readlink: 1
+readlinkat: 1
+_llseek: 1
+fstatfs64: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+gettid: 1
+
+@include /system/etc/seccomp_policy/crash_dump.x86.policy
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
new file mode 100644
index 0000000..d9c4045
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
@@ -0,0 +1,71 @@
+# Copyright (C) 2017 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+open: 1
+getuid32: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap2: 1
+mmap: 1
+fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
+madvise: 1
+fstatat64: 1
+newfstatat: 1
+futex: 1
+munmap: 1
+faccessat: 1
+_llseek: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+ugetrlimit: 1
+readlink: 1
+readlinkat: 1
+_llseek: 1
+fstatfs64: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+gettid: 1
+
+@include /system/etc/seccomp_policy/crash_dump.x86.policy
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
deleted file mode 100644
index d5871d1..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 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.
-
-# Organized by frequency of systemcall - in descending order for
-# best performance.
-futex: 1
-ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
-close: 1
-writev: 1
-dup: 1
-ppoll: 1
-mmap2: 1
-getrandom: 1
-
-# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
-# parser support for '<' is in this needs to be modified to also prevent
-# |old_address| and |new_address| from touching the exception vector page, which
-# on ARM is statically loaded at 0xffff 0000. See
-# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
-# for more details.
-mremap: arg3 == 3
-munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
-sigaltstack: 1
-clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
-exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
-lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
-getdents64: 1
-getrandom: 1
-
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
deleted file mode 100644
index 20c7625..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 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.
-
-read: 1
-mprotect: 1
-prctl: 1
-openat: 1
-getuid32: 1
-writev: 1
-ioctl: 1
-close: 1
-mmap2: 1
-fstat64: 1
-madvise: 1
-fstatat64: 1
-futex: 1
-munmap: 1
-faccessat: 1
-_llseek: 1
-lseek: 1
-clone: 1
-sigaltstack: 1
-setpriority: 1
-restart_syscall: 1
-exit: 1
-exit_group: 1
-rt_sigreturn: 1
-ugetrlimit: 1
-readlinkat: 1
-_llseek: 1
-fstatfs64: 1
-pread64: 1
-mremap: 1
-dup: 1
-set_tid_address: 1
-write: 1
-nanosleep: 1
-
-# Required by AddressSanitizer
-gettid: 1
-sched_yield: 1
-getpid: 1
-gettid: 1
-
-@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
deleted file mode 100644
index d5871d1..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 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.
-
-# Organized by frequency of systemcall - in descending order for
-# best performance.
-futex: 1
-ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
-close: 1
-writev: 1
-dup: 1
-ppoll: 1
-mmap2: 1
-getrandom: 1
-
-# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
-# parser support for '<' is in this needs to be modified to also prevent
-# |old_address| and |new_address| from touching the exception vector page, which
-# on ARM is statically loaded at 0xffff 0000. See
-# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
-# for more details.
-mremap: arg3 == 3
-munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
-sigaltstack: 1
-clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
-exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
-lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
-getdents64: 1
-getrandom: 1
-
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
deleted file mode 100644
index 20c7625..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 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.
-
-read: 1
-mprotect: 1
-prctl: 1
-openat: 1
-getuid32: 1
-writev: 1
-ioctl: 1
-close: 1
-mmap2: 1
-fstat64: 1
-madvise: 1
-fstatat64: 1
-futex: 1
-munmap: 1
-faccessat: 1
-_llseek: 1
-lseek: 1
-clone: 1
-sigaltstack: 1
-setpriority: 1
-restart_syscall: 1
-exit: 1
-exit_group: 1
-rt_sigreturn: 1
-ugetrlimit: 1
-readlinkat: 1
-_llseek: 1
-fstatfs64: 1
-pread64: 1
-mremap: 1
-dup: 1
-set_tid_address: 1
-write: 1
-nanosleep: 1
-
-# Required by AddressSanitizer
-gettid: 1
-sched_yield: 1
-getpid: 1
-gettid: 1
-
-@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/vendor.cpp b/media/codec2/hidl/services/vendor.cpp
index ef2f98e..81bffeb 100644
--- a/media/codec2/hidl/services/vendor.cpp
+++ b/media/codec2/hidl/services/vendor.cpp
@@ -15,31 +15,38 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.0-service"
+#define LOG_TAG "android.hardware.media.c2@1.1-service"
 
-#include <codec2/hidl/1.0/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
+#include <android-base/logging.h>
 #include <binder/ProcessState.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
 #include <minijail.h>
 
+#include <util/C2InterfaceHelper.h>
 #include <C2Component.h>
+#include <C2Config.h>
 
-// OmxStore is added for visibility by dumpstate.
-#include <media/stagefright/omx/1.0/OmxStore.h>
-
-// This is created by module "codec2.vendor.base.policy". This can be modified.
+// This is the absolute on-device path of the prebuild_etc module
+// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
 static constexpr char kBaseSeccompPolicyPath[] =
-        "/vendor/etc/seccomp_policy/codec2.vendor.base.policy";
+        "/vendor/etc/seccomp_policy/"
+        "android.hardware.media.c2@1.1-default-seccomp-policy";
 
-// Additional device-specific seccomp permissions can be added in this file.
+// Additional seccomp permissions can be added in this file.
+// This file does not exist by default.
 static constexpr char kExtSeccompPolicyPath[] =
-        "/vendor/etc/seccomp_policy/codec2.vendor.ext.policy";
+        "/vendor/etc/seccomp_policy/"
+        "android.hardware.media.c2@1.1-extended-seccomp-policy";
 
-class DummyC2Store : public C2ComponentStore {
+class StoreImpl : public C2ComponentStore {
 public:
-    DummyC2Store() = default;
+    StoreImpl()
+        : mReflectorHelper(std::make_shared<C2ReflectorHelper>()),
+          mInterface(mReflectorHelper) {
+    }
 
-    virtual ~DummyC2Store() override = default;
+    virtual ~StoreImpl() override = default;
 
     virtual C2String getName() const override {
         return "default";
@@ -69,82 +76,114 @@
     }
 
     virtual c2_status_t query_sm(
-        const std::vector<C2Param*>& /* stackParams */,
-        const std::vector<C2Param::Index>& /* heapParamIndices */,
-        std::vector<std::unique_ptr<C2Param>>* const /* heapParams */) const override {
-        return C2_OMITTED;
+        const std::vector<C2Param*>& stackParams,
+        const std::vector<C2Param::Index>& heapParamIndices,
+        std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
+        return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
     }
 
     virtual c2_status_t config_sm(
-            const std::vector<C2Param*>& /* params */,
-            std::vector<std::unique_ptr<C2SettingResult>>* const /* failures */) override {
-        return C2_OMITTED;
+            const std::vector<C2Param*>& params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
+        return mInterface.config(params, C2_MAY_BLOCK, failures);
     }
 
     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override {
-        return nullptr;
+        return mReflectorHelper;
     }
 
     virtual c2_status_t querySupportedParams_nb(
-            std::vector<std::shared_ptr<C2ParamDescriptor>>* const /* params */) const override {
-        return C2_OMITTED;
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
+        return mInterface.querySupportedParams(params);
     }
 
     virtual c2_status_t querySupportedValues_sm(
-            std::vector<C2FieldSupportedValuesQuery>& /* fields */) const override {
-        return C2_OMITTED;
+            std::vector<C2FieldSupportedValuesQuery>& fields) const override {
+        return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
     }
+
+private:
+    class Interface : public C2InterfaceHelper {
+    public:
+        Interface(const std::shared_ptr<C2ReflectorHelper> &helper)
+            : C2InterfaceHelper(helper) {
+            setDerivedInstance(this);
+
+            addParameter(
+                DefineParam(mIonUsageInfo, "ion-usage")
+                .withDefault(new C2StoreIonUsageInfo())
+                .withFields({
+                    C2F(mIonUsageInfo, usage).flags(
+                            {C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
+                    C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
+                    C2F(mIonUsageInfo, heapMask).any(),
+                    C2F(mIonUsageInfo, allocFlags).flags({}),
+                    C2F(mIonUsageInfo, minAlignment).equalTo(0)
+                })
+                .withSetter(SetIonUsage)
+                .build());
+        }
+
+        virtual ~Interface() = default;
+
+    private:
+        static C2R SetIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
+            // Vendor's TODO: put appropriate mapping logic
+            me.set().heapMask = ~0;
+            me.set().allocFlags = 0;
+            me.set().minAlignment = 0;
+            return C2R::Ok();
+        }
+
+        std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
+    };
+    std::shared_ptr<C2ReflectorHelper> mReflectorHelper;
+    Interface mInterface;
 };
 
 int main(int /* argc */, char** /* argv */) {
-    ALOGD("android.hardware.media.c2@1.0-service starting...");
+    using namespace ::android;
+    LOG(DEBUG) << "android.hardware.media.c2@1.1-service starting...";
 
+    // Set up minijail to limit system calls.
     signal(SIGPIPE, SIG_IGN);
-    android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+    SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
 
-    // vndbinder is needed by BufferQueue.
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-    android::ProcessState::self()->startThreadPool();
+    // Enable vndbinder to allow vendor-to-vendor binder calls.
+    ProcessState::initWithDriver("/dev/vndbinder");
 
+    ProcessState::self()->startThreadPool();
     // Extra threads may be needed to handle a stacked IPC sequence that
     // contains alternating binder and hwbinder calls. (See b/35283480.)
-    android::hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+    hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
 
     // Create IComponentStore service.
     {
-        using namespace ::android::hardware::media::c2::V1_0;
-        android::sp<IComponentStore> store;
+        using namespace ::android::hardware::media::c2::V1_1;
+        sp<IComponentStore> store;
 
-        // Vendor's TODO: Replace this with
+        // TODO: Replace this with
         // store = new utils::ComponentStore(
         //         /* implementation of C2ComponentStore */);
-        ALOGD("Instantiating Codec2's dummy IComponentStore service...");
+        LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
         store = new utils::ComponentStore(
-                std::make_shared<DummyC2Store>());
+                std::make_shared<StoreImpl>());
 
         if (store == nullptr) {
-            ALOGE("Cannot create Codec2's IComponentStore service.");
+            LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
         } else {
-            if (store->registerAsService("default") != android::OK) {
-                ALOGE("Cannot register Codec2's "
-                        "IComponentStore service.");
+            constexpr char const* serviceName = "default";
+            if (store->registerAsService(serviceName) != OK) {
+                LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+                              " with instance name << \""
+                           << serviceName << "\".";
             } else {
-                ALOGI("Codec2's IComponentStore service created.");
+                LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+                              "Instance name: \"" << serviceName << "\".";
             }
         }
     }
 
-    // Register IOmxStore service.
-    {
-        using namespace ::android::hardware::media::omx::V1_0;
-        android::sp<IOmxStore> omxStore = new implementation::OmxStore();
-        if (omxStore == nullptr) {
-            ALOGE("Cannot create IOmxStore HAL service.");
-        } else if (omxStore->registerAsService() != android::OK) {
-            ALOGE("Cannot register IOmxStore HAL service.");
-        }
-    }
-
-    android::hardware::joinRpcThreadpool();
+    hardware::joinRpcThreadpool();
     return 0;
 }
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 9c84c71..94034b5 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -1,6 +1,8 @@
 cc_library_shared {
     name: "libsfplugin_ccodec",
 
+    export_include_dirs: ["include"],
+
     srcs: [
         "C2OMXNode.cpp",
         "CCodec.cpp",
@@ -9,10 +11,8 @@
         "CCodecConfig.cpp",
         "Codec2Buffer.cpp",
         "Codec2InfoBuilder.cpp",
-        "Omx2IGraphicBufferSource.cpp",
         "PipelineWatcher.cpp",
         "ReflectedParamUpdater.cpp",
-        "SkipCutBuffer.cpp",
     ],
 
     cflags: [
@@ -22,11 +22,14 @@
 
     header_libs: [
         "libcodec2_internal",
+        "libmediadrm_headers",
+        "libmediametrics_headers",
+        "media_ndk_headers",
     ],
 
     shared_libs: [
         "android.hardware.cas.native@1.0",
-        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.drm@1.0",
         "android.hardware.media.c2@1.0",
         "android.hardware.media.omx@1.0",
         "libbase",
@@ -39,19 +42,23 @@
         "libhidlallocatorutils",
         "libhidlbase",
         "liblog",
-        "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libsfplugin_ccodec_utils",
         "libstagefright_bufferqueue_helper",
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx",
-        "libstagefright_omx_utils",
         "libstagefright_xmlparser",
         "libui",
         "libutils",
     ],
 
+    export_shared_lib_headers: [
+        "libcodec2",
+        "libcodec2_client",
+    ],
+
     sanitize: {
         cfi: true,
         misc_undefined: [
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 78ddd6d..1972d3f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -26,8 +26,8 @@
 #include <C2ParamInternal.h>
 #include <C2PlatformSupport.h>
 
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android-base/stringprintf.h>
@@ -35,17 +35,21 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
-#include <media/omx/1.0/WGraphicBufferSource.h>
+#include <media/omx/1.0/WOmxNode.h>
+#include <media/openmax/OMX_Core.h>
 #include <media/openmax/OMX_IndexExt.h>
+#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
+#include <media/stagefright/omx/OmxGraphicBufferSource.h>
+#include <media/stagefright/CCodec.h>
 #include <media/stagefright/BufferProducerWrapper.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/PersistentSurface.h>
 
 #include "C2OMXNode.h"
-#include "CCodec.h"
 #include "CCodecBufferChannel.h"
+#include "CCodecConfig.h"
+#include "Codec2Mapper.h"
 #include "InputSurfaceWrapper.h"
-#include "Omx2IGraphicBufferSource.h"
 
 extern "C" android::PersistentSurface *CreateInputSurface();
 
@@ -54,9 +58,11 @@
 using namespace std::chrono_literals;
 using ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
 using android::base::StringPrintf;
-using BGraphicBufferSource = ::android::IGraphicBufferSource;
 using ::android::hardware::media::c2::V1_0::IInputSurface;
 
+typedef hardware::media::omx::V1_0::IGraphicBufferSource HGraphicBufferSource;
+typedef CCodecConfig Config;
+
 namespace {
 
 class CCodecWatchdog : public AHandler {
@@ -180,9 +186,10 @@
 
 class GraphicBufferSourceWrapper : public InputSurfaceWrapper {
 public:
-//    explicit GraphicBufferSourceWrapper(const sp<BGraphicBufferSource> &source) : mSource(source) {}
+    typedef hardware::media::omx::V1_0::Status OmxStatus;
+
     GraphicBufferSourceWrapper(
-            const sp<BGraphicBufferSource> &source,
+            const sp<HGraphicBufferSource> &source,
             uint32_t width,
             uint32_t height,
             uint64_t usage)
@@ -194,6 +201,7 @@
 
     status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
         mNode = new C2OMXNode(comp);
+        mOmxNode = new hardware::media::omx::V1_0::utils::TWOmxNode(mNode);
         mNode->setFrameSize(mWidth, mHeight);
 
         // Usage is queried during configure(), so setting it beforehand.
@@ -204,7 +212,8 @@
 
         // NOTE: we do not use/pass through color aspects from GraphicBufferSource as we
         // communicate that directly to the component.
-        mSource->configure(mNode, mDataSpace);
+        mSource->configure(
+                mOmxNode, static_cast<hardware::graphics::common::V1_0::Dataspace>(mDataSpace));
         return OK;
     }
 
@@ -220,21 +229,16 @@
         source->onOmxIdle();
         source->onOmxLoaded();
         mNode.clear();
+        mOmxNode.clear();
     }
 
-    status_t GetStatus(const binder::Status &status) {
-        status_t err = OK;
-        if (!status.isOk()) {
-            err = status.serviceSpecificErrorCode();
-            if (err == OK) {
-                err = status.transactionError();
-                if (err == OK) {
-                    // binder status failed, but there is no servie or transaction error
-                    err = UNKNOWN_ERROR;
-                }
-            }
+    status_t GetStatus(hardware::Return<OmxStatus> &&status) {
+        if (status.isOk()) {
+            return static_cast<status_t>(status.withDefault(OmxStatus::UNKNOWN_ERROR));
+        } else if (status.isDeadObject()) {
+            return DEAD_OBJECT;
         }
-        return err;
+        return UNKNOWN_ERROR;
     }
 
     status_t start() override {
@@ -359,7 +363,15 @@
                 err = res;
             } else {
                 status << " delayUs";
-                res = GetStatus(mSource->getStopTimeOffsetUs(&config.mInputDelayUs));
+                hardware::Return<void> trans = mSource->getStopTimeOffsetUs(
+                        [&res, &delayUs = config.mInputDelayUs](
+                                auto status, auto stopTimeOffsetUs) {
+                            res = static_cast<status_t>(status);
+                            delayUs = stopTimeOffsetUs;
+                        });
+                if (!trans.isOk()) {
+                    res = trans.isDeadObject() ? DEAD_OBJECT : UNKNOWN_ERROR;
+                }
                 if (res != OK) {
                     status << " (=> " << asString(res) << ")";
                 } else {
@@ -388,8 +400,9 @@
     }
 
 private:
-    sp<BGraphicBufferSource> mSource;
+    sp<HGraphicBufferSource> mSource;
     sp<C2OMXNode> mNode;
+    sp<hardware::media::omx::V1_0::IOmxNode> mOmxNode;
     uint32_t mWidth;
     uint32_t mHeight;
     Config mConfig;
@@ -561,7 +574,8 @@
 // CCodec
 
 CCodec::CCodec()
-    : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))) {
+    : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))),
+      mConfig(new CCodecConfig) {
 }
 
 CCodec::~CCodec() {
@@ -652,8 +666,9 @@
     }
 
     // initialize config here in case setParameters is called prior to configure
-    Mutexed<Config>::Locked config(mConfig);
-    status_t err = config->initialize(mClient, comp);
+    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+    const std::unique_ptr<Config> &config = *configLocked;
+    status_t err = config->initialize(mClient->getParamReflector(), comp);
     if (err != OK) {
         ALOGW("Failed to initialize configuration support");
         // TODO: report error once we complete implementation.
@@ -703,6 +718,11 @@
             encoder = false;
         }
 
+        int32_t flags;
+        if (!msg->findInt32("flags", &flags)) {
+            return BAD_VALUE;
+        }
+
         // TODO: read from intf()
         if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
             return UNKNOWN_ERROR;
@@ -726,8 +746,12 @@
             setSurface(surface);
         }
 
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         config->mUsingSurface = surface != nullptr;
+        config->mBuffersBoundToCodec = ((flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) == 0);
+        ALOGD("[%s] buffers are %sbound to CCodec for this session",
+              comp->getName().c_str(), config->mBuffersBoundToCodec ? "" : "not ");
 
         // Enforce required parameters
         int32_t i32;
@@ -860,6 +884,13 @@
             }
         }
 
+        int32_t subscribeToAllVendorParams;
+        if (msg->findInt32("x-*", &subscribeToAllVendorParams) && subscribeToAllVendorParams) {
+            if (config->subscribeToAllVendorParams(comp, C2_MAY_BLOCK) != OK) {
+                ALOGD("[%s] Failed to subscribe to all vendor params", comp->getName().c_str());
+            }
+        }
+
         std::vector<std::unique_ptr<C2Param>> configUpdate;
         // NOTE: We used to ignore "video-bitrate" at configure; replicate
         //       the behavior here.
@@ -1042,7 +1073,8 @@
         return;
     }
 
-    Mutexed<Config>::Locked config(mConfig);
+    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+    const std::unique_ptr<Config> &config = *configLocked;
 
     mCallback->onComponentConfigured(config->mInputFormat, config->mOutputFormat);
 }
@@ -1092,9 +1124,7 @@
                 gbs = source;
             });
     if (transStatus.isOk() && s == OmxStatus::OK) {
-        return new PersistentSurface(
-                new H2BGraphicBufferProducer(gbp),
-                sp<::android::IGraphicBufferSource>(new LWGraphicBufferSource(gbs)));
+        return new PersistentSurface(new H2BGraphicBufferProducer(gbp), gbs);
     }
 
     return nullptr;
@@ -1118,35 +1148,36 @@
     sp<AMessage> outputFormat;
     uint64_t usage = 0;
     {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         inputFormat = config->mInputFormat;
         outputFormat = config->mOutputFormat;
         usage = config->mISConfig ? config->mISConfig->mUsage : 0;
     }
 
     sp<PersistentSurface> persistentSurface = CreateCompatibleInputSurface();
+    sp<hidl::base::V1_0::IBase> hidlTarget = persistentSurface->getHidlTarget();
+    sp<IInputSurface> hidlInputSurface = IInputSurface::castFrom(hidlTarget);
+    sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
 
-    if (persistentSurface->getHidlTarget()) {
-        sp<IInputSurface> hidlInputSurface = IInputSurface::castFrom(
-                persistentSurface->getHidlTarget());
-        if (!hidlInputSurface) {
-            ALOGE("Corrupted input surface");
-            mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
-            return;
-        }
+    if (hidlInputSurface) {
         std::shared_ptr<Codec2Client::InputSurface> inputSurface =
                 std::make_shared<Codec2Client::InputSurface>(hidlInputSurface);
         err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
                 inputSurface));
         bufferProducer = inputSurface->getGraphicBufferProducer();
-    } else {
+    } else if (gbs) {
         int32_t width = 0;
         (void)outputFormat->findInt32("width", &width);
         int32_t height = 0;
         (void)outputFormat->findInt32("height", &height);
         err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
-                persistentSurface->getBufferSource(), width, height, usage));
+                gbs, width, height, usage));
         bufferProducer = persistentSurface->getBufferProducer();
+    } else {
+        ALOGE("Corrupted input surface");
+        mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
+        return;
     }
 
     if (err != OK) {
@@ -1162,12 +1193,13 @@
 }
 
 status_t CCodec::setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface) {
-    Mutexed<Config>::Locked config(mConfig);
+    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+    const std::unique_ptr<Config> &config = *configLocked;
     config->mUsingSurface = true;
 
     // we are now using surface - apply default color aspects to input format - as well as
     // get dataspace
-    bool inputFormatChanged = config->updateFormats(config->IS_INPUT);
+    bool inputFormatChanged = config->updateFormats(Config::IS_INPUT);
     ALOGD("input format %s to %s",
             inputFormatChanged ? "changed" : "unchanged",
             config->mInputFormat->debugString().c_str());
@@ -1182,7 +1214,7 @@
     if (err != OK) {
         // undo input format update
         config->mUsingSurface = false;
-        (void)config->updateFormats(config->IS_INPUT);
+        (void)config->updateFormats(Config::IS_INPUT);
         return err;
     }
     config->mInputSurface = surface;
@@ -1207,20 +1239,16 @@
     sp<AMessage> outputFormat;
     uint64_t usage = 0;
     {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         inputFormat = config->mInputFormat;
         outputFormat = config->mOutputFormat;
         usage = config->mISConfig ? config->mISConfig->mUsage : 0;
     }
-    auto hidlTarget = surface->getHidlTarget();
-    if (hidlTarget) {
-        sp<IInputSurface> inputSurface =
-                IInputSurface::castFrom(hidlTarget);
-        if (!inputSurface) {
-            ALOGE("Failed to set input surface: Corrupted surface.");
-            mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR);
-            return;
-        }
+    sp<hidl::base::V1_0::IBase> hidlTarget = surface->getHidlTarget();
+    sp<IInputSurface> inputSurface = IInputSurface::castFrom(hidlTarget);
+    sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
+    if (inputSurface) {
         status_t err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
                 std::make_shared<Codec2Client::InputSurface>(inputSurface)));
         if (err != OK) {
@@ -1228,18 +1256,22 @@
             mCallback->onInputSurfaceDeclined(err);
             return;
         }
-    } else {
+    } else if (gbs) {
         int32_t width = 0;
         (void)outputFormat->findInt32("width", &width);
         int32_t height = 0;
         (void)outputFormat->findInt32("height", &height);
         status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
-                surface->getBufferSource(), width, height, usage));
+                gbs, width, height, usage));
         if (err != OK) {
             ALOGE("Failed to set up input surface: %d", err);
             mCallback->onInputSurfaceDeclined(err);
             return;
         }
+    } else {
+        ALOGE("Failed to set input surface: Corrupted surface.");
+        mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR);
+        return;
     }
     mCallback->onInputSurfaceAccepted(inputFormat, outputFormat);
 }
@@ -1283,14 +1315,17 @@
     sp<AMessage> inputFormat;
     sp<AMessage> outputFormat;
     status_t err2 = OK;
+    bool buffersBoundToCodec = false;
     {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         inputFormat = config->mInputFormat;
         // start triggers format dup
         outputFormat = config->mOutputFormat = config->mOutputFormat->dup();
         if (config->mInputSurface) {
             err2 = config->mInputSurface->start();
         }
+        buffersBoundToCodec = config->mBuffersBoundToCodec;
     }
     if (err2 != OK) {
         mCallback->onError(err2, ACTION_CODE_FATAL);
@@ -1298,7 +1333,7 @@
     }
     // We're not starting after flush.
     (void)mSentConfigAfterResume.test_and_set();
-    err2 = mChannel->start(inputFormat, outputFormat);
+    err2 = mChannel->start(inputFormat, outputFormat, buffersBoundToCodec);
     if (err2 != OK) {
         mCallback->onError(err2, ACTION_CODE_FATAL);
         return;
@@ -1344,7 +1379,7 @@
         state->set(STOPPING);
     }
 
-    mChannel->stop();
+    mChannel->reset();
     (new AMessage(kWhatStop, this))->post();
 }
 
@@ -1373,7 +1408,8 @@
     }
 
     {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         if (config->mInputSurface) {
             config->mInputSurface->disconnect();
             config->mInputSurface = nullptr;
@@ -1421,14 +1457,15 @@
     }
 
     if (clearInputSurfaceIfNeeded) {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         if (config->mInputSurface) {
             config->mInputSurface->disconnect();
             config->mInputSurface = nullptr;
         }
     }
 
-    mChannel->stop();
+    mChannel->reset();
     // thiz holds strong ref to this while the thread is running.
     sp<CCodec> thiz(this);
     std::thread([thiz, sendCallback] { thiz->release(sendCallback); }).detach();
@@ -1455,6 +1492,7 @@
         state->set(RELEASED);
         state->comp.reset();
     }
+    (new AMessage(kWhatRelease, this))->post();
     if (sendCallback) {
         mCallback->onReleaseCompleted();
     }
@@ -1520,7 +1558,9 @@
 
     {
         Mutexed<State>::Locked state(mState);
-        state->set(FLUSHED);
+        if (state->get() == FLUSHING) {
+            state->set(FLUSHED);
+        }
     }
     mCallback->onFlushCompleted();
 }
@@ -1542,11 +1582,16 @@
 
     mSentConfigAfterResume.clear();
     {
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         config->queryConfiguration(comp);
     }
 
-    (void)mChannel->start(nullptr, nullptr);
+    (void)mChannel->start(nullptr, nullptr, [&]{
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
+        return config->mBuffersBoundToCodec;
+    }());
 
     {
         Mutexed<State>::Locked state(mState);
@@ -1585,13 +1630,15 @@
         params->removeEntryAt(params->findEntryByName(KEY_BIT_RATE));
     }
 
-    Mutexed<Config>::Locked config(mConfig);
+    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+    const std::unique_ptr<Config> &config = *configLocked;
 
     /**
      * Handle input surface parameters
      */
     if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))
-            && (config->mDomain & Config::IS_ENCODER) && config->mInputSurface && config->mISConfig) {
+            && (config->mDomain & Config::IS_ENCODER)
+            && config->mInputSurface && config->mISConfig) {
         (void)params->findInt64(PARAMETER_KEY_OFFSET_TIME, &config->mISConfig->mTimeOffsetUs);
 
         if (params->findInt64("skip-frames-before", &config->mISConfig->mStartAtUs)) {
@@ -1644,7 +1691,8 @@
         comp = state->comp;
     }
     ALOGV("request IDR");
-    Mutexed<Config>::Locked config(mConfig);
+    Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+    const std::unique_ptr<Config> &config = *configLocked;
     std::vector<std::unique_ptr<C2Param>> params;
     params.push_back(
             std::make_unique<C2StreamRequestSyncFrameTuning::output>(0u, true));
@@ -1663,7 +1711,8 @@
     mChannel->onInputBufferDone(frameIndex, arrayIndex);
     if (arrayIndex == 0) {
         // We always put no more than one buffer per work, if we use an input surface.
-        Mutexed<Config>::Locked config(mConfig);
+        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+        const std::unique_ptr<Config> &config = *configLocked;
         if (config->mInputSurface) {
             config->mInputSurface->onInputBufferDone(frameIndex);
         }
@@ -1708,6 +1757,12 @@
             flush();
             break;
         }
+        case kWhatRelease: {
+            mChannel->release();
+            mClient.reset();
+            mClientListener.reset();
+            break;
+        }
         case kWhatCreateInputSurface: {
             // Surface operations may be briefly blocking.
             setDeadline(now, 1500ms, "createInputSurface");
@@ -1740,7 +1795,8 @@
             }
 
             // handle configuration changes in work done
-            Mutexed<Config>::Locked config(mConfig);
+            Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+            const std::unique_ptr<Config> &config = *configLocked;
             bool changed = !mSentConfigAfterResume.test_and_set();
             Config::Watcher<C2StreamInitDataInfo::output> initData =
                 config->watch<C2StreamInitDataInfo::output>();
@@ -1809,7 +1865,7 @@
                 config->mInputSurface->onInputBufferDone(work->input.ordinal.frameIndex);
             }
             mChannel->onWorkDone(
-                    std::move(work), changed ? config->mOutputFormat : nullptr,
+                    std::move(work), changed ? config->mOutputFormat->dup() : nullptr,
                     initData.hasChanged() ? initData.update().get() : nullptr);
             break;
         }
@@ -1871,15 +1927,10 @@
     mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
 }
 
-}  // namespace android
-
-extern "C" android::CodecBase *CreateCodec() {
-    return new android::CCodec;
-}
-
-// Create Codec 2.0 input surface
-extern "C" android::PersistentSurface *CreateInputSurface() {
+// static
+PersistentSurface *CCodec::CreateInputSurface() {
     using namespace android;
+    using ::android::hardware::media::omx::V1_0::implementation::TWGraphicBufferSource;
     // Attempt to create a Codec2's input surface.
     std::shared_ptr<Codec2Client::InputSurface> inputSurface =
             Codec2Client::CreateInputSurface();
@@ -1893,9 +1944,7 @@
                 return nullptr;
             }
             return new PersistentSurface(
-                    gbs->getIGraphicBufferProducer(),
-                    sp<IGraphicBufferSource>(
-                        new Omx2IGraphicBufferSource(gbs)));
+                    gbs->getIGraphicBufferProducer(), new TWGraphicBufferSource(gbs));
         } else {
             return nullptr;
         }
@@ -1906,3 +1955,340 @@
             inputSurface->getHalInterface()));
 }
 
+class IntfCache {
+public:
+    IntfCache() = default;
+
+    status_t init(const std::string &name) {
+        std::shared_ptr<Codec2Client::Interface> intf{
+            Codec2Client::CreateInterfaceByName(name.c_str())};
+        if (!intf) {
+            ALOGW("IntfCache [%s]: Unrecognized interface name", name.c_str());
+            mInitStatus = NO_INIT;
+            return NO_INIT;
+        }
+        const static C2StreamUsageTuning::input sUsage{0u /* stream id */};
+        mFields.push_back(C2FieldSupportedValuesQuery::Possible(
+                C2ParamField{&sUsage, &sUsage.value}));
+        c2_status_t err = intf->querySupportedValues(mFields, C2_MAY_BLOCK);
+        if (err != C2_OK) {
+            ALOGW("IntfCache [%s]: failed to query usage supported value (err=%d)",
+                    name.c_str(), err);
+            mFields[0].status = err;
+        }
+        std::vector<std::unique_ptr<C2Param>> params;
+        err = intf->query(
+                {&mApiFeatures},
+                {C2PortAllocatorsTuning::input::PARAM_TYPE},
+                C2_MAY_BLOCK,
+                &params);
+        if (err != C2_OK && err != C2_BAD_INDEX) {
+            ALOGW("IntfCache [%s]: failed to query api features (err=%d)",
+                    name.c_str(), err);
+        }
+        while (!params.empty()) {
+            C2Param *param = params.back().release();
+            params.pop_back();
+            if (!param) {
+                continue;
+            }
+            if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
+                mInputAllocators.reset(
+                        C2PortAllocatorsTuning::input::From(params[0].get()));
+            }
+        }
+        mInitStatus = OK;
+        return OK;
+    }
+
+    status_t initCheck() const { return mInitStatus; }
+
+    const C2FieldSupportedValuesQuery &getUsageSupportedValues() const {
+        CHECK_EQ(1u, mFields.size());
+        return mFields[0];
+    }
+
+    const C2ApiFeaturesSetting &getApiFeatures() const {
+        return mApiFeatures;
+    }
+
+    const C2PortAllocatorsTuning::input &getInputAllocators() const {
+        static std::unique_ptr<C2PortAllocatorsTuning::input> sInvalidated = []{
+            std::unique_ptr<C2PortAllocatorsTuning::input> param =
+                C2PortAllocatorsTuning::input::AllocUnique(0);
+            param->invalidate();
+            return param;
+        }();
+        return mInputAllocators ? *mInputAllocators : *sInvalidated;
+    }
+
+private:
+    status_t mInitStatus{NO_INIT};
+
+    std::vector<C2FieldSupportedValuesQuery> mFields;
+    C2ApiFeaturesSetting mApiFeatures;
+    std::unique_ptr<C2PortAllocatorsTuning::input> mInputAllocators;
+};
+
+static const IntfCache &GetIntfCache(const std::string &name) {
+    static IntfCache sNullIntfCache;
+    static std::mutex sMutex;
+    static std::map<std::string, IntfCache> sCache;
+    std::unique_lock<std::mutex> lock{sMutex};
+    auto it = sCache.find(name);
+    if (it == sCache.end()) {
+        lock.unlock();
+        IntfCache intfCache;
+        status_t err = intfCache.init(name);
+        if (err != OK) {
+            return sNullIntfCache;
+        }
+        lock.lock();
+        it = sCache.insert({name, std::move(intfCache)}).first;
+    }
+    return it->second;
+}
+
+static status_t GetCommonAllocatorIds(
+        const std::vector<std::string> &names,
+        C2Allocator::type_t type,
+        std::set<C2Allocator::id_t> *ids) {
+    int poolMask = GetCodec2PoolMask();
+    C2PlatformAllocatorStore::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
+    C2Allocator::id_t defaultAllocatorId =
+        (type == C2Allocator::LINEAR) ? preferredLinearId : C2PlatformAllocatorStore::GRALLOC;
+
+    ids->clear();
+    if (names.empty()) {
+        return OK;
+    }
+    bool firstIteration = true;
+    for (const std::string &name : names) {
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
+            continue;
+        }
+        const C2PortAllocatorsTuning::input &allocators = intfCache.getInputAllocators();
+        if (firstIteration) {
+            firstIteration = false;
+            if (allocators && allocators.flexCount() > 0) {
+                ids->insert(allocators.m.values,
+                            allocators.m.values + allocators.flexCount());
+            }
+            if (ids->empty()) {
+                // The component does not advertise allocators. Use default.
+                ids->insert(defaultAllocatorId);
+            }
+            continue;
+        }
+        bool filtered = false;
+        if (allocators && allocators.flexCount() > 0) {
+            filtered = true;
+            for (auto it = ids->begin(); it != ids->end(); ) {
+                bool found = false;
+                for (size_t j = 0; j < allocators.flexCount(); ++j) {
+                    if (allocators.m.values[j] == *it) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (found) {
+                    ++it;
+                } else {
+                    it = ids->erase(it);
+                }
+            }
+        }
+        if (!filtered) {
+            // The component does not advertise supported allocators. Use default.
+            bool containsDefault = (ids->count(defaultAllocatorId) > 0u);
+            if (ids->size() != (containsDefault ? 1 : 0)) {
+                ids->clear();
+                if (containsDefault) {
+                    ids->insert(defaultAllocatorId);
+                }
+            }
+        }
+    }
+    // Finally, filter with pool masks
+    for (auto it = ids->begin(); it != ids->end(); ) {
+        if ((poolMask >> *it) & 1) {
+            ++it;
+        } else {
+            it = ids->erase(it);
+        }
+    }
+    return OK;
+}
+
+static status_t CalculateMinMaxUsage(
+        const std::vector<std::string> &names, uint64_t *minUsage, uint64_t *maxUsage) {
+    static C2StreamUsageTuning::input sUsage{0u /* stream id */};
+    *minUsage = 0;
+    *maxUsage = ~0ull;
+    for (const std::string &name : names) {
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
+            continue;
+        }
+        const C2FieldSupportedValuesQuery &usageSupportedValues =
+            intfCache.getUsageSupportedValues();
+        if (usageSupportedValues.status != C2_OK) {
+            continue;
+        }
+        const C2FieldSupportedValues &supported = usageSupportedValues.values;
+        if (supported.type != C2FieldSupportedValues::FLAGS) {
+            continue;
+        }
+        if (supported.values.empty()) {
+            *maxUsage = 0;
+            continue;
+        }
+        *minUsage |= supported.values[0].u64;
+        int64_t currentMaxUsage = 0;
+        for (const C2Value::Primitive &flags : supported.values) {
+            currentMaxUsage |= flags.u64;
+        }
+        *maxUsage &= currentMaxUsage;
+    }
+    return OK;
+}
+
+// static
+status_t CCodec::CanFetchLinearBlock(
+        const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible) {
+    for (const std::string &name : names) {
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
+            continue;
+        }
+        const C2ApiFeaturesSetting &features = intfCache.getApiFeatures();
+        if (features && !(features.value & API_SAME_INPUT_BUFFER)) {
+            *isCompatible = false;
+            return OK;
+        }
+    }
+    uint64_t minUsage = usage.expected;
+    uint64_t maxUsage = ~0ull;
+    std::set<C2Allocator::id_t> allocators;
+    GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
+    if (allocators.empty()) {
+        *isCompatible = false;
+        return OK;
+    }
+    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+    *isCompatible = ((maxUsage & minUsage) == minUsage);
+    return OK;
+}
+
+static std::shared_ptr<C2BlockPool> GetPool(C2Allocator::id_t allocId) {
+    static std::mutex sMutex{};
+    static std::map<C2Allocator::id_t, std::shared_ptr<C2BlockPool>> sPools;
+    std::unique_lock<std::mutex> lock{sMutex};
+    std::shared_ptr<C2BlockPool> pool;
+    auto it = sPools.find(allocId);
+    if (it == sPools.end()) {
+        c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
+        if (err == OK) {
+            sPools.emplace(allocId, pool);
+        } else {
+            pool.reset();
+        }
+    } else {
+        pool = it->second;
+    }
+    return pool;
+}
+
+// static
+std::shared_ptr<C2LinearBlock> CCodec::FetchLinearBlock(
+        size_t capacity, const C2MemoryUsage &usage, const std::vector<std::string> &names) {
+    uint64_t minUsage = usage.expected;
+    uint64_t maxUsage = ~0ull;
+    std::set<C2Allocator::id_t> allocators;
+    GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
+    if (allocators.empty()) {
+        allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
+    }
+    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+    if ((maxUsage & minUsage) != minUsage) {
+        allocators.clear();
+        allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
+    }
+    std::shared_ptr<C2LinearBlock> block;
+    for (C2Allocator::id_t allocId : allocators) {
+        std::shared_ptr<C2BlockPool> pool = GetPool(allocId);
+        if (!pool) {
+            continue;
+        }
+        c2_status_t err = pool->fetchLinearBlock(capacity, C2MemoryUsage{minUsage}, &block);
+        if (err != C2_OK || !block) {
+            block.reset();
+            continue;
+        }
+        break;
+    }
+    return block;
+}
+
+// static
+status_t CCodec::CanFetchGraphicBlock(
+        const std::vector<std::string> &names, bool *isCompatible) {
+    uint64_t minUsage = 0;
+    uint64_t maxUsage = ~0ull;
+    std::set<C2Allocator::id_t> allocators;
+    GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
+    if (allocators.empty()) {
+        *isCompatible = false;
+        return OK;
+    }
+    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+    *isCompatible = ((maxUsage & minUsage) == minUsage);
+    return OK;
+}
+
+// static
+std::shared_ptr<C2GraphicBlock> CCodec::FetchGraphicBlock(
+        int32_t width,
+        int32_t height,
+        int32_t format,
+        uint64_t usage,
+        const std::vector<std::string> &names) {
+    uint32_t halPixelFormat = HAL_PIXEL_FORMAT_YCBCR_420_888;
+    if (!C2Mapper::mapPixelFormatFrameworkToCodec(format, &halPixelFormat)) {
+        ALOGD("Unrecognized pixel format: %d", format);
+        return nullptr;
+    }
+    uint64_t minUsage = 0;
+    uint64_t maxUsage = ~0ull;
+    std::set<C2Allocator::id_t> allocators;
+    GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
+    if (allocators.empty()) {
+        allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
+    }
+    CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+    minUsage |= usage;
+    if ((maxUsage & minUsage) != minUsage) {
+        allocators.clear();
+        allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
+    }
+    std::shared_ptr<C2GraphicBlock> block;
+    for (C2Allocator::id_t allocId : allocators) {
+        std::shared_ptr<C2BlockPool> pool;
+        c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
+        if (err != C2_OK || !pool) {
+            continue;
+        }
+        err = pool->fetchGraphicBlock(
+                width, height, halPixelFormat, C2MemoryUsage{minUsage}, &block);
+        if (err != C2_OK || !block) {
+            block.reset();
+            continue;
+        }
+        break;
+    }
+    return block;
+}
+
+}  // namespace android
+
diff --git a/media/codec2/sfplugin/CCodec.h b/media/codec2/sfplugin/CCodec.h
deleted file mode 100644
index a580d1d..0000000
--- a/media/codec2/sfplugin/CCodec.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2017 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 C_CODEC_H_
-#define C_CODEC_H_
-
-#include <atomic>
-#include <chrono>
-#include <list>
-#include <memory>
-#include <set>
-
-#include <C2Component.h>
-#include <codec2/hidl/client.h>
-
-#include <android/native_window.h>
-#include <media/hardware/MetadataBufferType.h>
-#include <media/stagefright/foundation/Mutexed.h>
-#include <media/stagefright/CodecBase.h>
-#include <media/stagefright/FrameRenderTracker.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/SkipCutBuffer.h>
-#include <utils/NativeHandle.h>
-#include <hardware/gralloc.h>
-#include <nativebase/nativebase.h>
-
-#include "CCodecConfig.h"
-
-namespace android {
-
-class CCodecBufferChannel;
-class InputSurfaceWrapper;
-struct MediaCodecInfo;
-
-class CCodec : public CodecBase {
-public:
-    CCodec();
-
-    virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
-    virtual void initiateAllocateComponent(const sp<AMessage> &msg) override;
-    virtual void initiateConfigureComponent(const sp<AMessage> &msg) override;
-    virtual void initiateCreateInputSurface() override;
-    virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface) override;
-    virtual void initiateStart() override;
-    virtual void initiateShutdown(bool keepComponentAllocated = false) override;
-
-    virtual status_t setSurface(const sp<Surface> &surface) override;
-
-    virtual void signalFlush() override;
-    virtual void signalResume() override;
-
-    virtual void signalSetParameters(const sp<AMessage> &params) override;
-    virtual void signalEndOfInputStream() override;
-    virtual void signalRequestIDRFrame() override;
-
-    void initiateReleaseIfStuck();
-    void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
-    void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex);
-
-protected:
-    virtual ~CCodec();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg) override;
-
-private:
-    typedef std::chrono::steady_clock::time_point TimePoint;
-
-    status_t tryAndReportOnError(std::function<status_t()> job);
-
-    void initiateStop();
-    void initiateRelease(bool sendCallback = true);
-
-    void allocate(const sp<MediaCodecInfo> &codecInfo);
-    void configure(const sp<AMessage> &msg);
-    void start();
-    void stop();
-    void flush();
-    void release(bool sendCallback);
-
-    /**
-     * Creates an input surface for the current device configuration compatible with CCodec.
-     * This could be backed by the C2 HAL or the OMX HAL.
-     */
-    static sp<PersistentSurface> CreateCompatibleInputSurface();
-
-    /// Creates an input surface to the OMX HAL
-    static sp<PersistentSurface> CreateOmxInputSurface();
-
-    /// handle a create input surface call
-    void createInputSurface();
-    void setInputSurface(const sp<PersistentSurface> &surface);
-    status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
-
-    void setDeadline(
-            const TimePoint &now,
-            const std::chrono::milliseconds &timeout,
-            const char *name);
-
-    enum {
-        kWhatAllocate,
-        kWhatConfigure,
-        kWhatStart,
-        kWhatFlush,
-        kWhatStop,
-        kWhatRelease,
-        kWhatCreateInputSurface,
-        kWhatSetInputSurface,
-        kWhatSetParameters,
-
-        kWhatWorkDone,
-        kWhatWatch,
-    };
-
-    enum {
-        RELEASED,
-        ALLOCATED,
-        FLUSHED,
-        RUNNING,
-
-        ALLOCATING,  // RELEASED -> ALLOCATED
-        STARTING,    // ALLOCATED -> RUNNING
-        STOPPING,    // RUNNING -> ALLOCATED
-        FLUSHING,    // RUNNING -> FLUSHED
-        RESUMING,    // FLUSHED -> RUNNING
-        RELEASING,   // {ANY EXCEPT RELEASED} -> RELEASED
-    };
-
-    struct State {
-        inline State() : mState(RELEASED) {}
-        inline int get() const { return mState; }
-        inline void set(int newState) { mState = newState; }
-
-        std::shared_ptr<Codec2Client::Component> comp;
-    private:
-        int mState;
-    };
-
-    struct NamedTimePoint {
-        NamedTimePoint() : mTimePoint(TimePoint::max()), mName("") {}
-
-        inline void set(
-                const TimePoint &timePoint,
-                const char *name) {
-            mTimePoint = timePoint;
-            mName = name;
-        }
-
-        inline TimePoint get() const { return mTimePoint; }
-        inline const char *getName() const { return mName; }
-    private:
-        TimePoint mTimePoint;
-        const char *mName;
-    };
-
-    Mutexed<State> mState;
-    std::shared_ptr<CCodecBufferChannel> mChannel;
-
-    std::shared_ptr<Codec2Client> mClient;
-    std::shared_ptr<Codec2Client::Listener> mClientListener;
-    struct ClientListener;
-
-    Mutexed<NamedTimePoint> mDeadline;
-    typedef CCodecConfig Config;
-    Mutexed<Config> mConfig;
-    Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
-    std::atomic_flag mSentConfigAfterResume;
-
-    friend class CCodecCallbackImpl;
-
-    DISALLOW_EVIL_CONSTRUCTORS(CCodec);
-};
-
-}  // namespace android
-
-#endif  // C_CODEC_H_
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 4ee6c1c..0626c8d 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "CCodecBufferChannel"
 #include <utils/Log.h>
 
+#include <algorithm>
+#include <list>
 #include <numeric>
 
 #include <C2AllocatorGralloc.h>
@@ -27,9 +29,13 @@
 #include <C2Debug.h>
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <android-base/stringprintf.h>
+#include <binder/MemoryBase.h>
 #include <binder/MemoryDealer.h>
+#include <cutils/properties.h>
 #include <gui/Surface.h>
+#include <hidlmemory/FrameworkUtils.h>
 #include <media/openmax/OMX_Core.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALookup.h>
@@ -38,12 +44,13 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/SkipCutBuffer.h>
 #include <media/MediaCodecBuffer.h>
+#include <mediadrm/ICrypto.h>
 #include <system/window.h>
 
 #include "CCodecBufferChannel.h"
 #include "Codec2Buffer.h"
-#include "SkipCutBuffer.h"
 
 namespace android {
 
@@ -51,10 +58,14 @@
 using hardware::hidl_handle;
 using hardware::hidl_string;
 using hardware::hidl_vec;
+using hardware::fromHeap;
+using hardware::HidlMemory;
+
 using namespace hardware::cas::V1_0;
 using namespace hardware::cas::native::V1_0;
 
 using CasStatus = hardware::cas::V1_0::Status;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
 
 namespace {
 
@@ -119,97 +130,6 @@
     count->value = -1;
 }
 
-// CCodecBufferChannel::ReorderStash
-
-CCodecBufferChannel::ReorderStash::ReorderStash() {
-    clear();
-}
-
-void CCodecBufferChannel::ReorderStash::clear() {
-    mPending.clear();
-    mStash.clear();
-    mDepth = 0;
-    mKey = C2Config::ORDINAL;
-}
-
-void CCodecBufferChannel::ReorderStash::flush() {
-    mPending.clear();
-    mStash.clear();
-}
-
-void CCodecBufferChannel::ReorderStash::setDepth(uint32_t depth) {
-    mPending.splice(mPending.end(), mStash);
-    mDepth = depth;
-}
-
-void CCodecBufferChannel::ReorderStash::setKey(C2Config::ordinal_key_t key) {
-    mPending.splice(mPending.end(), mStash);
-    mKey = key;
-}
-
-bool CCodecBufferChannel::ReorderStash::pop(Entry *entry) {
-    if (mPending.empty()) {
-        return false;
-    }
-    entry->buffer     = mPending.front().buffer;
-    entry->timestamp  = mPending.front().timestamp;
-    entry->flags      = mPending.front().flags;
-    entry->ordinal    = mPending.front().ordinal;
-    mPending.pop_front();
-    return true;
-}
-
-void CCodecBufferChannel::ReorderStash::emplace(
-        const std::shared_ptr<C2Buffer> &buffer,
-        int64_t timestamp,
-        int32_t flags,
-        const C2WorkOrdinalStruct &ordinal) {
-    bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
-    if (!buffer && eos) {
-        // TRICKY: we may be violating ordering of the stash here. Because we
-        // don't expect any more emplace() calls after this, the ordering should
-        // not matter.
-        mStash.emplace_back(buffer, timestamp, flags, ordinal);
-    } else {
-        flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
-        auto it = mStash.begin();
-        for (; it != mStash.end(); ++it) {
-            if (less(ordinal, it->ordinal)) {
-                break;
-            }
-        }
-        mStash.emplace(it, buffer, timestamp, flags, ordinal);
-        if (eos) {
-            mStash.back().flags = mStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
-        }
-    }
-    while (!mStash.empty() && mStash.size() > mDepth) {
-        mPending.push_back(mStash.front());
-        mStash.pop_front();
-    }
-}
-
-void CCodecBufferChannel::ReorderStash::defer(
-        const CCodecBufferChannel::ReorderStash::Entry &entry) {
-    mPending.push_front(entry);
-}
-
-bool CCodecBufferChannel::ReorderStash::hasPending() const {
-    return !mPending.empty();
-}
-
-bool CCodecBufferChannel::ReorderStash::less(
-        const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) {
-    switch (mKey) {
-        case C2Config::ORDINAL:   return o1.frameIndex < o2.frameIndex;
-        case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
-        case C2Config::CUSTOM:    return o1.customOrdinal < o2.customOrdinal;
-        default:
-            ALOGD("Unrecognized key; default to timestamp");
-            return o1.frameIndex < o2.frameIndex;
-    }
-}
-
 // Input
 
 CCodecBufferChannel::Input::Input() : extraBuffers("extra") {}
@@ -242,7 +162,7 @@
 }
 
 CCodecBufferChannel::~CCodecBufferChannel() {
-    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
+    if (mCrypto != nullptr && mHeapSeqNum >= 0) {
         mCrypto->unsetHeap(mHeapSeqNum);
     }
 }
@@ -402,6 +322,173 @@
     return OK;
 }
 
+status_t CCodecBufferChannel::attachBuffer(
+        const std::shared_ptr<C2Buffer> &c2Buffer,
+        const sp<MediaCodecBuffer> &buffer) {
+    if (!buffer->copy(c2Buffer)) {
+        return -ENOSYS;
+    }
+    return OK;
+}
+
+void CCodecBufferChannel::ensureDecryptDestination(size_t size) {
+    if (!mDecryptDestination || mDecryptDestination->size() < size) {
+        sp<IMemoryHeap> heap{new MemoryHeapBase(size * 2)};
+        if (mDecryptDestination && mCrypto && mHeapSeqNum >= 0) {
+            mCrypto->unsetHeap(mHeapSeqNum);
+        }
+        mDecryptDestination = new MemoryBase(heap, 0, size * 2);
+        if (mCrypto) {
+            mHeapSeqNum = mCrypto->setHeap(hardware::fromHeap(heap));
+        }
+    }
+}
+
+int32_t CCodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) {
+    CHECK(mCrypto);
+    auto it = mHeapSeqNumMap.find(memory);
+    int32_t heapSeqNum = -1;
+    if (it == mHeapSeqNumMap.end()) {
+        heapSeqNum = mCrypto->setHeap(memory);
+        mHeapSeqNumMap.emplace(memory, heapSeqNum);
+    } else {
+        heapSeqNum = it->second;
+    }
+    return heapSeqNum;
+}
+
+status_t CCodecBufferChannel::attachEncryptedBuffer(
+        const sp<hardware::HidlMemory> &memory,
+        bool secure,
+        const uint8_t *key,
+        const uint8_t *iv,
+        CryptoPlugin::Mode mode,
+        CryptoPlugin::Pattern pattern,
+        size_t offset,
+        const CryptoPlugin::SubSample *subSamples,
+        size_t numSubSamples,
+        const sp<MediaCodecBuffer> &buffer) {
+    static const C2MemoryUsage kSecureUsage{C2MemoryUsage::READ_PROTECTED, 0};
+    static const C2MemoryUsage kDefaultReadWriteUsage{
+        C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+    size_t size = 0;
+    for (size_t i = 0; i < numSubSamples; ++i) {
+        size += subSamples[i].mNumBytesOfClearData + subSamples[i].mNumBytesOfEncryptedData;
+    }
+    std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool;
+    std::shared_ptr<C2LinearBlock> block;
+    c2_status_t err = pool->fetchLinearBlock(
+            size,
+            secure ? kSecureUsage : kDefaultReadWriteUsage,
+            &block);
+    if (err != C2_OK) {
+        return NO_MEMORY;
+    }
+    if (!secure) {
+        ensureDecryptDestination(size);
+    }
+    ssize_t result = -1;
+    ssize_t codecDataOffset = 0;
+    if (mCrypto) {
+        AString errorDetailMsg;
+        int32_t heapSeqNum = getHeapSeqNum(memory);
+        hardware::drm::V1_0::SharedBuffer src{(uint32_t)heapSeqNum, offset, size};
+        hardware::drm::V1_0::DestinationBuffer dst;
+        if (secure) {
+            dst.type = DrmBufferType::NATIVE_HANDLE;
+            dst.secureMemory = hardware::hidl_handle(block->handle());
+        } else {
+            dst.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &dst.nonsecureMemory);
+        }
+        result = mCrypto->decrypt(
+                key, iv, mode, pattern, src, 0, subSamples, numSubSamples,
+                dst, &errorDetailMsg);
+        if (result < 0) {
+            return result;
+        }
+        if (dst.type == DrmBufferType::SHARED_MEMORY) {
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                return false;
+            }
+            if (view.size() < result) {
+                return false;
+            }
+            memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
+        }
+    } else {
+        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
+        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
+        hidl_vec<SubSample> hidlSubSamples;
+        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
+
+        hardware::cas::native::V1_0::SharedBuffer src{*memory, offset, size};
+        hardware::cas::native::V1_0::DestinationBuffer dst;
+        if (secure) {
+            dst.type = BufferType::NATIVE_HANDLE;
+            dst.secureMemory = hardware::hidl_handle(block->handle());
+        } else {
+            dst.type = BufferType::SHARED_MEMORY;
+            dst.nonsecureMemory = src;
+        }
+
+        CasStatus status = CasStatus::OK;
+        hidl_string detailedError;
+        ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;
+
+        if (key != nullptr) {
+            sctrl = (ScramblingControl)key[0];
+            // Adjust for the PES offset
+            codecDataOffset = key[2] | (key[3] << 8);
+        }
+
+        auto returnVoid = mDescrambler->descramble(
+                sctrl,
+                hidlSubSamples,
+                src,
+                0,
+                dst,
+                0,
+                [&status, &result, &detailedError] (
+                        CasStatus _status, uint32_t _bytesWritten,
+                        const hidl_string& _detailedError) {
+                    status = _status;
+                    result = (ssize_t)_bytesWritten;
+                    detailedError = _detailedError;
+                });
+
+        if (!returnVoid.isOk() || status != CasStatus::OK || result < 0) {
+            ALOGI("[%s] descramble failed, trans=%s, status=%d, result=%zd",
+                    mName, returnVoid.description().c_str(), status, result);
+            return UNKNOWN_ERROR;
+        }
+
+        if (result < codecDataOffset) {
+            ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
+            return BAD_VALUE;
+        }
+    }
+    if (!secure) {
+        C2WriteView view = block->map().get();
+        if (view.error() != C2_OK) {
+            return UNKNOWN_ERROR;
+        }
+        if (view.size() < result) {
+            return UNKNOWN_ERROR;
+        }
+        memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
+    }
+    std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer(
+            block->share(codecDataOffset, result - codecDataOffset, C2Fence{}))};
+    if (!buffer->copy(c2Buffer)) {
+        return -ENOSYS;
+    }
+    return OK;
+}
+
 status_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
     QueueGuard guard(mSync);
     if (!guard.isRunning()) {
@@ -429,24 +516,31 @@
 
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
-    if (mCrypto != nullptr) {
-        ICrypto::DestinationBuffer destination;
+    if (numSubSamples == 1
+            && subSamples[0].mNumBytesOfClearData == 0
+            && subSamples[0].mNumBytesOfEncryptedData == 0) {
+        // We don't need to go through crypto or descrambler if the input is empty.
+        result = 0;
+    } else if (mCrypto != nullptr) {
+        hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
-            destination.mType = ICrypto::kDestinationTypeNativeHandle;
-            destination.mHandle = encryptedBuffer->handle();
+            destination.type = DrmBufferType::NATIVE_HANDLE;
+            destination.secureMemory = hidl_handle(encryptedBuffer->handle());
         } else {
-            destination.mType = ICrypto::kDestinationTypeSharedMemory;
-            destination.mSharedMemory = mDecryptDestination;
+            destination.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
         }
-        ICrypto::SourceBuffer source;
+        hardware::drm::V1_0::SharedBuffer source;
         encryptedBuffer->fillSourceBuffer(&source);
         result = mCrypto->decrypt(
                 key, iv, mode, pattern, source, buffer->offset(),
                 subSamples, numSubSamples, destination, errorDetailMsg);
         if (result < 0) {
+            ALOGI("[%s] decrypt failed: result=%zd", mName, result);
             return result;
         }
-        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+        if (destination.type == DrmBufferType::SHARED_MEMORY) {
             encryptedBuffer->copyDecryptedContent(mDecryptDestination, result);
         }
     } else {
@@ -524,13 +618,14 @@
 }
 
 void CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
-    if (mInputMetEos ||
-           mReorderStash.lock()->hasPending() ||
-           mPipelineWatcher.lock()->pipelineFull()) {
+    if (mInputMetEos || mPipelineWatcher.lock()->pipelineFull()) {
         return;
-    } else {
+    }
+    {
         Mutexed<Output>::Locked output(mOutput);
-        if (output->buffers->numClientBuffers() >= output->numSlots) {
+        if (!output->buffers ||
+                output->buffers->hasPending() ||
+                output->buffers->numClientBuffers() >= output->numSlots) {
             return;
         }
     }
@@ -637,6 +732,9 @@
     std::shared_ptr<const C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
         std::static_pointer_cast<const C2StreamHdr10PlusInfo::output>(
                 c2Buffer->getInfo(C2StreamHdr10PlusInfo::output::PARAM_TYPE));
+    if (hdr10PlusInfo && hdr10PlusInfo->flexCount() == 0) {
+        hdr10PlusInfo.reset();
+    }
 
     {
         Mutexed<OutputSurface>::Locked output(mOutputSurface);
@@ -668,31 +766,39 @@
     if (hdrStaticInfo || hdr10PlusInfo) {
         HdrMetadata hdr;
         if (hdrStaticInfo) {
-            struct android_smpte2086_metadata smpte2086_meta = {
-                .displayPrimaryRed = {
-                    hdrStaticInfo->mastering.red.x, hdrStaticInfo->mastering.red.y
-                },
-                .displayPrimaryGreen = {
-                    hdrStaticInfo->mastering.green.x, hdrStaticInfo->mastering.green.y
-                },
-                .displayPrimaryBlue = {
-                    hdrStaticInfo->mastering.blue.x, hdrStaticInfo->mastering.blue.y
-                },
-                .whitePoint = {
-                    hdrStaticInfo->mastering.white.x, hdrStaticInfo->mastering.white.y
-                },
-                .maxLuminance = hdrStaticInfo->mastering.maxLuminance,
-                .minLuminance = hdrStaticInfo->mastering.minLuminance,
-            };
-
-            struct android_cta861_3_metadata cta861_meta = {
-                .maxContentLightLevel = hdrStaticInfo->maxCll,
-                .maxFrameAverageLightLevel = hdrStaticInfo->maxFall,
-            };
-
-            hdr.validTypes = HdrMetadata::SMPTE2086 | HdrMetadata::CTA861_3;
-            hdr.smpte2086 = smpte2086_meta;
-            hdr.cta8613 = cta861_meta;
+            // If mastering max and min luminance fields are 0, do not use them.
+            // It indicates the value may not be present in the stream.
+            if (hdrStaticInfo->mastering.maxLuminance > 0.0f &&
+                hdrStaticInfo->mastering.minLuminance > 0.0f) {
+                struct android_smpte2086_metadata smpte2086_meta = {
+                    .displayPrimaryRed = {
+                        hdrStaticInfo->mastering.red.x, hdrStaticInfo->mastering.red.y
+                    },
+                    .displayPrimaryGreen = {
+                        hdrStaticInfo->mastering.green.x, hdrStaticInfo->mastering.green.y
+                    },
+                    .displayPrimaryBlue = {
+                        hdrStaticInfo->mastering.blue.x, hdrStaticInfo->mastering.blue.y
+                    },
+                    .whitePoint = {
+                        hdrStaticInfo->mastering.white.x, hdrStaticInfo->mastering.white.y
+                    },
+                    .maxLuminance = hdrStaticInfo->mastering.maxLuminance,
+                    .minLuminance = hdrStaticInfo->mastering.minLuminance,
+                };
+                hdr.validTypes |= HdrMetadata::SMPTE2086;
+                hdr.smpte2086 = smpte2086_meta;
+            }
+            // If the content light level fields are 0, do not use them, it
+            // indicates the value may not be present in the stream.
+            if (hdrStaticInfo->maxCll > 0.0f && hdrStaticInfo->maxFall > 0.0f) {
+                struct android_cta861_3_metadata cta861_meta = {
+                    .maxContentLightLevel = hdrStaticInfo->maxCll,
+                    .maxFrameAverageLightLevel = hdrStaticInfo->maxFall,
+                };
+                hdr.validTypes |= HdrMetadata::CTA861_3;
+                hdr.cta8613 = cta861_meta;
+            }
         }
         if (hdr10PlusInfo) {
             hdr.validTypes |= HdrMetadata::HDR10PLUS;
@@ -766,7 +872,9 @@
 }
 
 status_t CCodecBufferChannel::start(
-        const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
+        const sp<AMessage> &inputFormat,
+        const sp<AMessage> &outputFormat,
+        bool buffersBoundToCodec) {
     C2StreamBufferTypeSetting::input iStreamFormat(0u);
     C2StreamBufferTypeSetting::output oStreamFormat(0u);
     C2PortReorderBufferDepthTuning::output reorderDepth;
@@ -796,17 +904,6 @@
         return UNKNOWN_ERROR;
     }
 
-    {
-        Mutexed<ReorderStash>::Locked reorder(mReorderStash);
-        reorder->clear();
-        if (reorderDepth) {
-            reorder->setDepth(reorderDepth.value);
-        }
-        if (reorderKey) {
-            reorder->setKey(reorderKey.value);
-        }
-    }
-
     uint32_t inputDelayValue = inputDelay ? inputDelay.value : 0;
     uint32_t pipelineDelayValue = pipelineDelay ? pipelineDelay.value : 0;
     uint32_t outputDelayValue = outputDelay ? outputDelay.value : 0;
@@ -818,32 +915,37 @@
     bool secure = mComponent->getName().find(".secure") != std::string::npos;
 
     std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
-    int poolMask = property_get_int32(
-            "debug.stagefright.c2-poolmask",
-            1 << C2PlatformAllocatorStore::ION |
-            1 << C2PlatformAllocatorStore::BUFFERQUEUE);
+    int poolMask = GetCodec2PoolMask();
+    C2PlatformAllocatorStore::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
 
     if (inputFormat != nullptr) {
         bool graphic = (iStreamFormat.value == C2BufferData::GRAPHIC);
+        C2Config::api_feature_t apiFeatures = C2Config::api_feature_t(
+                API_REFLECTION |
+                API_VALUES |
+                API_CURRENT_VALUES |
+                API_DEPENDENCY |
+                API_SAME_INPUT_BUFFER);
         std::shared_ptr<C2BlockPool> pool;
         {
             Mutexed<BlockPools>::Locked pools(mBlockPools);
 
             // set default allocator ID.
             pools->inputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
-                                                : C2PlatformAllocatorStore::ION;
+                                                : preferredLinearId;
 
             // query C2PortAllocatorsTuning::input from component. If an allocator ID is obtained
             // from component, create the input block pool with given ID. Otherwise, use default IDs.
             std::vector<std::unique_ptr<C2Param>> params;
-            err = mComponent->query({ },
+            C2ApiFeaturesSetting featuresSetting{apiFeatures};
+            err = mComponent->query({ &featuresSetting },
                                     { C2PortAllocatorsTuning::input::PARAM_TYPE },
                                     C2_DONT_BLOCK,
                                     &params);
             if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {
                 ALOGD("[%s] Query input allocators returned %zu params => %s (%u)",
                         mName, params.size(), asString(err), err);
-            } else if (err == C2_OK && params.size() == 1) {
+            } else if (params.size() == 1) {
                 C2PortAllocatorsTuning::input *inputAllocators =
                     C2PortAllocatorsTuning::input::From(params[0].get());
                 if (inputAllocators && inputAllocators->flexCount() > 0) {
@@ -858,6 +960,9 @@
                     }
                 }
             }
+            if (featuresSetting) {
+                apiFeatures = featuresSetting.value;
+            }
 
             // TODO: use C2Component wrapper to associate this pool with ourselves
             if ((poolMask >> pools->inputAllocatorId) & 1) {
@@ -891,7 +996,12 @@
         input->numSlots = numInputSlots;
         input->extraBuffers.flush();
         input->numExtraSlots = 0u;
-        if (graphic) {
+        bool conforming = (apiFeatures & API_SAME_INPUT_BUFFER);
+        // For encrypted content, framework decrypts source buffer (ashmem) into
+        // C2Buffers. Thus non-conforming codecs can process these.
+        if (!buffersBoundToCodec && (hasCryptoOrDescrambler() || conforming)) {
+            input->buffers.reset(new SlotInputBuffers(mName));
+        } else if (graphic) {
             if (mInputSurface) {
                 input->buffers.reset(new DummyInputBuffers(mName));
             } else if (mMetaMode == MODE_ANW) {
@@ -900,7 +1010,7 @@
                 // TODO: handle this without going into array mode
                 forceArrayMode = true;
             } else {
-                input->buffers.reset(new GraphicInputBuffers(numInputSlots, mName));
+                input->buffers.reset(new GraphicInputBuffers(mName));
             }
         } else {
             if (hasCryptoOrDescrambler()) {
@@ -918,7 +1028,8 @@
                     mDecryptDestination = mDealer->allocate((size_t)capacity);
                 }
                 if (mCrypto != nullptr && mHeapSeqNum < 0) {
-                    mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap());
+                    sp<HidlMemory> heap = fromHeap(mDealer->getMemoryHeap());
+                    mHeapSeqNum = mCrypto->setHeap(heap);
                 } else {
                     mHeapSeqNum = -1;
                 }
@@ -969,7 +1080,7 @@
 
             // set default allocator ID.
             pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
-                                                 : C2PlatformAllocatorStore::ION;
+                                                 : preferredLinearId;
 
             // query C2PortAllocatorsTuning::output from component, or use default allocator if
             // unsuccessful.
@@ -1064,16 +1175,23 @@
         output->outputDelay = outputDelayValue;
         output->numSlots = numOutputSlots;
         if (graphic) {
-            if (outputSurface) {
+            if (outputSurface || !buffersBoundToCodec) {
                 output->buffers.reset(new GraphicOutputBuffers(mName));
             } else {
-                output->buffers.reset(new RawGraphicOutputBuffers(numOutputSlots, mName));
+                output->buffers.reset(new RawGraphicOutputBuffers(mName));
             }
         } else {
             output->buffers.reset(new LinearOutputBuffers(mName));
         }
         output->buffers->setFormat(outputFormat);
 
+        output->buffers->clearStash();
+        if (reorderDepth) {
+            output->buffers->setReorderDepth(reorderDepth.value);
+        }
+        if (reorderKey) {
+            output->buffers->setReorderKey(reorderKey.value);
+        }
 
         // Try to set output surface to created block pool if given.
         if (outputSurface) {
@@ -1083,12 +1201,13 @@
                     outputGeneration);
         }
 
-        if (oStreamFormat.value == C2BufferData::LINEAR
-                && mComponentName.find("c2.qti.") == std::string::npos) {
-            // WORKAROUND: if we're using early CSD workaround we convert to
-            //             array mode, to appease apps assuming the output
-            //             buffers to be of the same size.
-            output->buffers = output->buffers->toArrayMode(numOutputSlots);
+        if (oStreamFormat.value == C2BufferData::LINEAR) {
+            if (buffersBoundToCodec) {
+                // WORKAROUND: if we're using early CSD workaround we convert to
+                //             array mode, to appease apps assuming the output
+                //             buffers to be of the same size.
+                output->buffers = output->buffers->toArrayMode(numOutputSlots);
+            }
 
             int32_t channelCount;
             int32_t sampleRate;
@@ -1136,67 +1255,104 @@
     }
 
     C2StreamBufferTypeSetting::output oStreamFormat(0u);
-    c2_status_t err = mComponent->query({ &oStreamFormat }, {}, C2_DONT_BLOCK, nullptr);
-    if (err != C2_OK) {
+    C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
+    c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
+    if (err != C2_OK && err != C2_BAD_INDEX) {
         return UNKNOWN_ERROR;
     }
     size_t numInputSlots = mInput.lock()->numSlots;
-    std::vector<sp<MediaCodecBuffer>> toBeQueued;
-    for (size_t i = 0; i < numInputSlots; ++i) {
+
+    struct ClientInputBuffer {
         size_t index;
         sp<MediaCodecBuffer> buffer;
-        {
-            Mutexed<Input>::Locked input(mInput);
-            if (!input->buffers->requestNewBuffer(&index, &buffer)) {
-                if (i == 0) {
-                    ALOGW("[%s] start: cannot allocate memory at all", mName);
-                    return NO_MEMORY;
-                } else {
-                    ALOGV("[%s] start: cannot allocate memory, only %zu buffers allocated",
-                            mName, i);
-                }
+        size_t capacity;
+    };
+    std::list<ClientInputBuffer> clientInputBuffers;
+
+    {
+        Mutexed<Input>::Locked input(mInput);
+        while (clientInputBuffers.size() < numInputSlots) {
+            ClientInputBuffer clientInputBuffer;
+            if (!input->buffers->requestNewBuffer(&clientInputBuffer.index,
+                                                  &clientInputBuffer.buffer)) {
                 break;
             }
+            clientInputBuffer.capacity = clientInputBuffer.buffer->capacity();
+            clientInputBuffers.emplace_back(std::move(clientInputBuffer));
         }
-        if (buffer) {
-            Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
-            ALOGV("[%s] input buffer %zu available", mName, index);
-            bool post = true;
-            if (!configs->empty()) {
+    }
+    if (clientInputBuffers.empty()) {
+        ALOGW("[%s] start: cannot allocate memory at all", mName);
+        return NO_MEMORY;
+    } else if (clientInputBuffers.size() < numInputSlots) {
+        ALOGD("[%s] start: cannot allocate memory for all slots, "
+              "only %zu buffers allocated",
+              mName, clientInputBuffers.size());
+    } else {
+        ALOGV("[%s] %zu initial input buffers available",
+              mName, clientInputBuffers.size());
+    }
+    // Sort input buffers by their capacities in increasing order.
+    clientInputBuffers.sort(
+            [](const ClientInputBuffer& a, const ClientInputBuffer& b) {
+                return a.capacity < b.capacity;
+            });
+
+    {
+        Mutexed<std::list<sp<ABuffer>>>::Locked configs(mFlushedConfigs);
+        if (!configs->empty()) {
+            while (!configs->empty()) {
                 sp<ABuffer> config = configs->front();
                 configs->pop_front();
-                if (buffer->capacity() >= config->size()) {
-                    memcpy(buffer->base(), config->data(), config->size());
-                    buffer->setRange(0, config->size());
-                    buffer->meta()->clear();
-                    buffer->meta()->setInt64("timeUs", 0);
-                    buffer->meta()->setInt32("csd", 1);
-                    post = false;
-                } else {
-                    ALOGD("[%s] buffer capacity too small for the config (%zu < %zu)",
-                            mName, buffer->capacity(), config->size());
+                // Find the smallest input buffer that can fit the config.
+                auto i = std::find_if(
+                        clientInputBuffers.begin(),
+                        clientInputBuffers.end(),
+                        [cfgSize = config->size()](const ClientInputBuffer& b) {
+                            return b.capacity >= cfgSize;
+                        });
+                if (i == clientInputBuffers.end()) {
+                    ALOGW("[%s] no input buffer large enough for the config "
+                          "(%zu bytes)",
+                          mName, config->size());
+                    return NO_MEMORY;
                 }
-            } else if (oStreamFormat.value == C2BufferData::LINEAR && i == 0
-                    && mComponentName.find("c2.qti.") == std::string::npos) {
-                // WORKAROUND: Some apps expect CSD available without queueing
-                //             any input. Queue an empty buffer to get the CSD.
-                buffer->setRange(0, 0);
+                sp<MediaCodecBuffer> buffer = i->buffer;
+                memcpy(buffer->base(), config->data(), config->size());
+                buffer->setRange(0, config->size());
                 buffer->meta()->clear();
                 buffer->meta()->setInt64("timeUs", 0);
-                post = false;
+                buffer->meta()->setInt32("csd", 1);
+                if (queueInputBufferInternal(buffer) != OK) {
+                    ALOGW("[%s] Error while queueing a flushed config",
+                          mName);
+                    return UNKNOWN_ERROR;
+                }
+                clientInputBuffers.erase(i);
             }
-            if (post) {
-                mCallback->onInputBufferAvailable(index, buffer);
-            } else {
-                toBeQueued.emplace_back(buffer);
+        } else if (oStreamFormat.value == C2BufferData::LINEAR &&
+                   (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
+            sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
+            // WORKAROUND: Some apps expect CSD available without queueing
+            //             any input. Queue an empty buffer to get the CSD.
+            buffer->setRange(0, 0);
+            buffer->meta()->clear();
+            buffer->meta()->setInt64("timeUs", 0);
+            if (queueInputBufferInternal(buffer) != OK) {
+                ALOGW("[%s] Error while queueing an empty buffer to get CSD",
+                      mName);
+                return UNKNOWN_ERROR;
             }
+            clientInputBuffers.pop_front();
         }
     }
-    for (const sp<MediaCodecBuffer> &buffer : toBeQueued) {
-        if (queueInputBufferInternal(buffer) != OK) {
-            ALOGV("[%s] Error while queueing initial buffers", mName);
-        }
+
+    for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
+        mCallback->onInputBufferAvailable(
+                clientInputBuffer.index,
+                clientInputBuffer.buffer);
     }
+
     return OK;
 }
 
@@ -1206,8 +1362,36 @@
     if (mInputSurface != nullptr) {
         mInputSurface.reset();
     }
+    mPipelineWatcher.lock()->flush();
 }
 
+void CCodecBufferChannel::reset() {
+    stop();
+    {
+        Mutexed<Input>::Locked input(mInput);
+        input->buffers.reset(new DummyInputBuffers(""));
+        input->extraBuffers.flush();
+    }
+    {
+        Mutexed<Output>::Locked output(mOutput);
+        output->buffers.reset();
+    }
+}
+
+void CCodecBufferChannel::release() {
+    mComponent.reset();
+    mInputAllocator.reset();
+    mOutputSurface.lock()->surface.clear();
+    {
+        Mutexed<BlockPools>::Locked blockPools{mBlockPools};
+        blockPools->inputPool.reset();
+        blockPools->outputPoolIntf.reset();
+    }
+    setCrypto(nullptr);
+    setDescrambler(nullptr);
+}
+
+
 void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
     ALOGV("[%s] flush", mName);
     {
@@ -1238,9 +1422,11 @@
     }
     {
         Mutexed<Output>::Locked output(mOutput);
-        output->buffers->flush(flushedWork);
+        if (output->buffers) {
+            output->buffers->flush(flushedWork);
+            output->buffers->flushStash();
+        }
     }
-    mReorderStash.lock()->flush();
     mPipelineWatcher.lock()->flush();
 }
 
@@ -1276,45 +1462,41 @@
         std::unique_ptr<C2Work> work,
         const sp<AMessage> &outputFormat,
         const C2StreamInitDataInfo::output *initData) {
-    if (outputFormat != nullptr) {
+    {
         Mutexed<Output>::Locked output(mOutput);
-        ALOGD("[%s] onWorkDone: output format changed to %s",
-                mName, outputFormat->debugString().c_str());
-        output->buffers->setFormat(outputFormat);
-
-        AString mediaType;
-        if (outputFormat->findString(KEY_MIME, &mediaType)
-                && mediaType == MIMETYPE_AUDIO_RAW) {
-            int32_t channelCount;
-            int32_t sampleRate;
-            if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
-                    && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
-                output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
-            }
+        if (!output->buffers) {
+            return false;
         }
     }
 
-    if ((work->input.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) {
+    // Whether the output buffer should be reported to the client or not.
+    bool notifyClient = false;
+
+    if (work->result == C2_OK){
+        notifyClient = true;
+    } else if (work->result == C2_NOT_FOUND) {
+        ALOGD("[%s] flushed work; ignored.", mName);
+    } else {
+        // C2_OK and C2_NOT_FOUND are the only results that we accept for processing
+        // the config update.
+        ALOGD("[%s] work failed to complete: %d", mName, work->result);
+        mCCodecCallback->onError(work->result, ACTION_CODE_FATAL);
+        return false;
+    }
+
+    if ((work->input.ordinal.frameIndex -
+            mFirstValidFrameIndex.load()).peek() < 0) {
         // Discard frames from previous generation.
         ALOGD("[%s] Discard frames from previous generation.", mName);
-        return false;
+        notifyClient = false;
     }
 
     if (mInputSurface == nullptr && (work->worklets.size() != 1u
             || !work->worklets.front()
-            || !(work->worklets.front()->output.flags & C2FrameData::FLAG_INCOMPLETE))) {
-        mPipelineWatcher.lock()->onWorkDone(work->input.ordinal.frameIndex.peeku());
-    }
-
-    if (work->result == C2_NOT_FOUND) {
-        ALOGD("[%s] flushed work; ignored.", mName);
-        return true;
-    }
-
-    if (work->result != C2_OK) {
-        ALOGD("[%s] work failed to complete: %d", mName, work->result);
-        mCCodecCallback->onError(work->result, ACTION_CODE_FATAL);
-        return false;
+            || !(work->worklets.front()->output.flags &
+                 C2FrameData::FLAG_INCOMPLETE))) {
+        mPipelineWatcher.lock()->onWorkDone(
+                work->input.ordinal.frameIndex.peeku());
     }
 
     // NOTE: MediaCodec usage supposedly have only one worklet
@@ -1350,8 +1532,10 @@
             case C2PortReorderBufferDepthTuning::CORE_INDEX: {
                 C2PortReorderBufferDepthTuning::output reorderDepth;
                 if (reorderDepth.updateFrom(*param)) {
-                    bool secure = mComponent->getName().find(".secure") != std::string::npos;
-                    mReorderStash.lock()->setDepth(reorderDepth.value);
+                    bool secure = mComponent->getName().find(".secure") !=
+                                  std::string::npos;
+                    mOutput.lock()->buffers->setReorderDepth(
+                            reorderDepth.value);
                     ALOGV("[%s] onWorkDone: updated reorder depth to %u",
                           mName, reorderDepth.value);
                     size_t numOutputSlots = mOutput.lock()->numSlots;
@@ -1363,17 +1547,19 @@
                         output->maxDequeueBuffers += numInputSlots;
                     }
                     if (output->surface) {
-                        output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
+                        output->surface->setMaxDequeuedBufferCount(
+                                output->maxDequeueBuffers);
                     }
                 } else {
-                    ALOGD("[%s] onWorkDone: failed to read reorder depth", mName);
+                    ALOGD("[%s] onWorkDone: failed to read reorder depth",
+                          mName);
                 }
                 break;
             }
             case C2PortReorderKeySetting::CORE_INDEX: {
                 C2PortReorderKeySetting::output reorderKey;
                 if (reorderKey.updateFrom(*param)) {
-                    mReorderStash.lock()->setKey(reorderKey.value);
+                    mOutput.lock()->buffers->setReorderKey(reorderKey.value);
                     ALOGV("[%s] onWorkDone: updated reorder key to %u",
                           mName, reorderKey.value);
                 } else {
@@ -1388,7 +1574,8 @@
                         ALOGV("[%s] onWorkDone: updating pipeline delay %u",
                               mName, pipelineDelay.value);
                         newPipelineDelay = pipelineDelay.value;
-                        (void)mPipelineWatcher.lock()->pipelineDelay(pipelineDelay.value);
+                        (void)mPipelineWatcher.lock()->pipelineDelay(
+                                pipelineDelay.value);
                     }
                 }
                 if (param->forInput()) {
@@ -1397,7 +1584,8 @@
                         ALOGV("[%s] onWorkDone: updating input delay %u",
                               mName, inputDelay.value);
                         newInputDelay = inputDelay.value;
-                        (void)mPipelineWatcher.lock()->inputDelay(inputDelay.value);
+                        (void)mPipelineWatcher.lock()->inputDelay(
+                                inputDelay.value);
                     }
                 }
                 if (param->forOutput()) {
@@ -1405,16 +1593,22 @@
                     if (outputDelay.updateFrom(*param)) {
                         ALOGV("[%s] onWorkDone: updating output delay %u",
                               mName, outputDelay.value);
-                        bool secure = mComponent->getName().find(".secure") != std::string::npos;
-                        (void)mPipelineWatcher.lock()->outputDelay(outputDelay.value);
+                        bool secure = mComponent->getName().find(".secure") !=
+                                      std::string::npos;
+                        (void)mPipelineWatcher.lock()->outputDelay(
+                                outputDelay.value);
 
                         bool outputBuffersChanged = false;
                         size_t numOutputSlots = 0;
                         size_t numInputSlots = mInput.lock()->numSlots;
                         {
                             Mutexed<Output>::Locked output(mOutput);
+                            if (!output->buffers) {
+                                return false;
+                            }
                             output->outputDelay = outputDelay.value;
-                            numOutputSlots = outputDelay.value + kSmoothnessFactor;
+                            numOutputSlots = outputDelay.value +
+                                             kSmoothnessFactor;
                             if (output->numSlots < numOutputSlots) {
                                 output->numSlots = numOutputSlots;
                                 if (output->buffers->isArrayMode()) {
@@ -1433,7 +1627,7 @@
                             mCCodecCallback->onOutputBuffersChanged();
                         }
 
-                        uint32_t depth = mReorderStash.lock()->depth();
+                        uint32_t depth = mOutput.lock()->buffers->getReorderDepth();
                         Mutexed<OutputSurface>::Locked output(mOutputSurface);
                         output->maxDequeueBuffers = numOutputSlots + depth + kRenderingDepth;
                         if (!secure) {
@@ -1477,9 +1671,6 @@
         ALOGV("[%s] onWorkDone: output EOS", mName);
     }
 
-    sp<MediaCodecBuffer> outBuffer;
-    size_t index;
-
     // WORKAROUND: adjust output timestamp based on client input timestamp and codec
     // input timestamp. Codec output timestamp (in the timestamp field) shall correspond to
     // the codec input timestamp, but client output timestamp should (reported in timeUs)
@@ -1500,9 +1691,19 @@
           worklet->output.ordinal.timestamp.peekll(),
           timestamp.peekll());
 
+    // csd cannot be re-ordered and will always arrive first.
     if (initData != nullptr) {
         Mutexed<Output>::Locked output(mOutput);
-        if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
+        if (output->buffers && outputFormat) {
+            output->buffers->updateSkipCutBuffer(outputFormat);
+            output->buffers->setFormat(outputFormat);
+        }
+        if (!notifyClient) {
+            return false;
+        }
+        size_t index;
+        sp<MediaCodecBuffer> outBuffer;
+        if (output->buffers && output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
             outBuffer->meta()->setInt64("timeUs", timestamp.peek());
             outBuffer->meta()->setInt32("flags", MediaCodec::BUFFER_FLAG_CODECCONFIG);
             ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get());
@@ -1517,10 +1718,10 @@
         }
     }
 
-    if (!buffer && !flags) {
+    if (notifyClient && !buffer && !flags) {
         ALOGV("[%s] onWorkDone: Not reporting output buffer (%lld)",
               mName, work->input.ordinal.frameIndex.peekull());
-        return true;
+        notifyClient = false;
     }
 
     if (buffer) {
@@ -1539,63 +1740,65 @@
     }
 
     {
-        Mutexed<ReorderStash>::Locked reorder(mReorderStash);
-        reorder->emplace(buffer, timestamp.peek(), flags, worklet->output.ordinal);
-        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
-            // Flush reorder stash
-            reorder->setDepth(0);
+        Mutexed<Output>::Locked output(mOutput);
+        if (!output->buffers) {
+            return false;
         }
+        output->buffers->pushToStash(
+                buffer,
+                notifyClient,
+                timestamp.peek(),
+                flags,
+                outputFormat,
+                worklet->output.ordinal);
     }
     sendOutputBuffers();
     return true;
 }
 
 void CCodecBufferChannel::sendOutputBuffers() {
-    ReorderStash::Entry entry;
-    sp<MediaCodecBuffer> outBuffer;
+    OutputBuffers::BufferAction action;
     size_t index;
+    sp<MediaCodecBuffer> outBuffer;
+    std::shared_ptr<C2Buffer> c2Buffer;
 
     while (true) {
-        Mutexed<ReorderStash>::Locked reorder(mReorderStash);
-        if (!reorder->hasPending()) {
-            break;
-        }
-        if (!reorder->pop(&entry)) {
-            break;
-        }
-
         Mutexed<Output>::Locked output(mOutput);
-        status_t err = output->buffers->registerBuffer(entry.buffer, &index, &outBuffer);
-        if (err != OK) {
-            bool outputBuffersChanged = false;
-            if (err != WOULD_BLOCK) {
-                if (!output->buffers->isArrayMode()) {
-                    output->buffers = output->buffers->toArrayMode(output->numSlots);
-                }
-                OutputBuffersArray *array = (OutputBuffersArray *)output->buffers.get();
-                array->realloc(entry.buffer);
-                outputBuffersChanged = true;
-            }
-            ALOGV("[%s] sendOutputBuffers: unable to register output buffer", mName);
-            reorder->defer(entry);
-
-            output.unlock();
-            reorder.unlock();
-
-            if (outputBuffersChanged) {
-                mCCodecCallback->onOutputBuffersChanged();
-            }
+        if (!output->buffers) {
             return;
         }
-        output.unlock();
-        reorder.unlock();
-
-        outBuffer->meta()->setInt64("timeUs", entry.timestamp);
-        outBuffer->meta()->setInt32("flags", entry.flags);
-        ALOGV("[%s] sendOutputBuffers: out buffer index = %zu [%p] => %p + %zu (%lld)",
-                mName, index, outBuffer.get(), outBuffer->data(), outBuffer->size(),
-                (long long)entry.timestamp);
-        mCallback->onOutputBufferAvailable(index, outBuffer);
+        action = output->buffers->popFromStashAndRegister(
+                &c2Buffer, &index, &outBuffer);
+        switch (action) {
+        case OutputBuffers::SKIP:
+            return;
+        case OutputBuffers::DISCARD:
+            break;
+        case OutputBuffers::NOTIFY_CLIENT:
+            output.unlock();
+            mCallback->onOutputBufferAvailable(index, outBuffer);
+            break;
+        case OutputBuffers::REALLOCATE:
+            if (!output->buffers->isArrayMode()) {
+                output->buffers =
+                    output->buffers->toArrayMode(output->numSlots);
+            }
+            static_cast<OutputBuffersArray*>(output->buffers.get())->
+                    realloc(c2Buffer);
+            output.unlock();
+            mCCodecCallback->onOutputBuffersChanged();
+            break;
+        case OutputBuffers::RETRY:
+            ALOGV("[%s] sendOutputBuffers: unable to register output buffer",
+                  mName);
+            return;
+        default:
+            LOG_ALWAYS_FATAL("[%s] sendOutputBuffers: "
+                    "corrupted BufferAction value (%d) "
+                    "returned from popFromStashAndRegister.",
+                    mName, int(action));
+            return;
+        }
     }
 }
 
@@ -1661,6 +1864,24 @@
     mMetaMode = mode;
 }
 
+void CCodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
+    if (mCrypto != nullptr) {
+        for (std::pair<wp<HidlMemory>, int32_t> entry : mHeapSeqNumMap) {
+            mCrypto->unsetHeap(entry.second);
+        }
+        mHeapSeqNumMap.clear();
+        if (mHeapSeqNum >= 0) {
+            mCrypto->unsetHeap(mHeapSeqNum);
+            mHeapSeqNum = -1;
+        }
+    }
+    mCrypto = crypto;
+}
+
+void CCodecBufferChannel::setDescrambler(const sp<IDescrambler> &descrambler) {
+    mDescrambler = descrambler;
+}
+
 status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) {
     // C2_OK is always translated to OK.
     if (c2s == C2_OK) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index ee3455d..046c5c3 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -29,7 +29,6 @@
 #include <codec2/hidl/client.h>
 #include <media/stagefright/foundation/Mutexed.h>
 #include <media/stagefright/CodecBase.h>
-#include <media/ICrypto.h>
 
 #include "CCodecBuffers.h"
 #include "InputSurfaceWrapper.h"
@@ -57,6 +56,9 @@
     virtual ~CCodecBufferChannel();
 
     // BufferChannelBase interface
+    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(
             const sp<MediaCodecBuffer> &buffer,
@@ -68,6 +70,20 @@
             const CryptoPlugin::SubSample *subSamples,
             size_t numSubSamples,
             AString *errorDetailMsg) override;
+    virtual status_t attachBuffer(
+            const std::shared_ptr<C2Buffer> &c2Buffer,
+            const sp<MediaCodecBuffer> &buffer) override;
+    virtual status_t attachEncryptedBuffer(
+            const sp<hardware::HidlMemory> &memory,
+            bool secure,
+            const uint8_t *key,
+            const uint8_t *iv,
+            CryptoPlugin::Mode mode,
+            CryptoPlugin::Pattern pattern,
+            size_t offset,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
     virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -106,7 +122,10 @@
      * Start queueing buffers to the component. This object should never queue
      * buffers before this call has completed.
      */
-    status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
+    status_t start(
+            const sp<AMessage> &inputFormat,
+            const sp<AMessage> &outputFormat,
+            bool buffersBoundToCodec);
 
     /**
      * Request initial input buffers to be filled by client.
@@ -119,6 +138,16 @@
      */
     void stop();
 
+    /**
+     * Stop queueing buffers to the component and release all buffers.
+     */
+    void reset();
+
+    /**
+     * Release all resources.
+     */
+    void release();
+
     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
 
     /**
@@ -214,11 +243,14 @@
             std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
             const C2StreamInitDataInfo::output *initData);
     void sendOutputBuffers();
+    void ensureDecryptDestination(size_t size);
+    int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);
 
     QueueSync mSync;
     sp<MemoryDealer> mDealer;
     sp<IMemory> mDecryptDestination;
     int32_t mHeapSeqNum;
+    std::map<wp<hardware::HidlMemory>, int32_t> mHeapSeqNumMap;
 
     std::shared_ptr<Codec2Client::Component> mComponent;
     std::string mComponentName; ///< component name for debugging
@@ -274,51 +306,12 @@
 
     Mutexed<PipelineWatcher> mPipelineWatcher;
 
-    class ReorderStash {
-    public:
-        struct Entry {
-            inline Entry() : buffer(nullptr), timestamp(0), flags(0), ordinal({0, 0, 0}) {}
-            inline Entry(
-                    const std::shared_ptr<C2Buffer> &b,
-                    int64_t t,
-                    int32_t f,
-                    const C2WorkOrdinalStruct &o)
-                : buffer(b), timestamp(t), flags(f), ordinal(o) {}
-            std::shared_ptr<C2Buffer> buffer;
-            int64_t timestamp;
-            int32_t flags;
-            C2WorkOrdinalStruct ordinal;
-        };
-
-        ReorderStash();
-
-        void clear();
-        void flush();
-        void setDepth(uint32_t depth);
-        void setKey(C2Config::ordinal_key_t key);
-        bool pop(Entry *entry);
-        void emplace(
-                const std::shared_ptr<C2Buffer> &buffer,
-                int64_t timestamp,
-                int32_t flags,
-                const C2WorkOrdinalStruct &ordinal);
-        void defer(const Entry &entry);
-        bool hasPending() const;
-        uint32_t depth() const { return mDepth; }
-
-    private:
-        std::list<Entry> mPending;
-        std::list<Entry> mStash;
-        uint32_t mDepth;
-        C2Config::ordinal_key_t mKey;
-
-        bool less(const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2);
-    };
-    Mutexed<ReorderStash> mReorderStash;
-
     std::atomic_bool mInputMetEos;
     std::once_flag mRenderWarningFlag;
 
+    sp<ICrypto> mCrypto;
+    sp<IDescrambler> mDescrambler;
+
     inline bool hasCryptoOrDescrambler() {
         return mCrypto != nullptr || mDescrambler != nullptr;
     }
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index ed8b832..e58a1e4 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -21,7 +21,10 @@
 #include <C2PlatformSupport.h>
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/SkipCutBuffer.h>
+#include <mediadrm/ICrypto.h>
 
 #include "CCodecBuffers.h"
 
@@ -120,26 +123,54 @@
 
 // OutputBuffers
 
+OutputBuffers::OutputBuffers(const char *componentName, const char *name)
+    : CCodecBuffers(componentName, name) { }
+
+OutputBuffers::~OutputBuffers() = default;
+
 void OutputBuffers::initSkipCutBuffer(
         int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
     CHECK(mSkipCutBuffer == nullptr);
     mDelay = delay;
     mPadding = padding;
     mSampleRate = sampleRate;
-    setSkipCutBuffer(delay, padding, channelCount);
+    mChannelCount = channelCount;
+    setSkipCutBuffer(delay, padding);
 }
 
 void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
     if (mSkipCutBuffer == nullptr) {
         return;
     }
+    if (mSampleRate == sampleRate && mChannelCount == channelCount) {
+        return;
+    }
     int32_t delay = mDelay;
     int32_t padding = mPadding;
     if (sampleRate != mSampleRate) {
         delay = ((int64_t)delay * sampleRate) / mSampleRate;
         padding = ((int64_t)padding * sampleRate) / mSampleRate;
     }
-    setSkipCutBuffer(delay, padding, channelCount);
+    mSampleRate = sampleRate;
+    mChannelCount = channelCount;
+    setSkipCutBuffer(delay, padding);
+}
+
+void OutputBuffers::updateSkipCutBuffer(
+        const sp<AMessage> &format, bool notify) {
+    AString mediaType;
+    if (format->findString(KEY_MIME, &mediaType)
+            && mediaType == MIMETYPE_AUDIO_RAW) {
+        int32_t channelCount;
+        int32_t sampleRate;
+        if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
+                && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
+            updateSkipCutBuffer(sampleRate, channelCount);
+        }
+    }
+    if (notify) {
+        mUnreportedFormat = nullptr;
+    }
 }
 
 void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
@@ -148,24 +179,192 @@
     }
 }
 
-void OutputBuffers::transferSkipCutBuffer(const sp<SkipCutBuffer> &scb) {
-    mSkipCutBuffer = scb;
-}
-
-void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount) {
+void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
     if (mSkipCutBuffer != nullptr) {
         size_t prevSize = mSkipCutBuffer->size();
         if (prevSize != 0u) {
             ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
         }
     }
-    mSkipCutBuffer = new SkipCutBuffer(skip, cut, channelCount);
+    mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
+}
+
+void OutputBuffers::clearStash() {
+    mPending.clear();
+    mReorderStash.clear();
+    mDepth = 0;
+    mKey = C2Config::ORDINAL;
+    mUnreportedFormat = nullptr;
+}
+
+void OutputBuffers::flushStash() {
+    for (StashEntry& e : mPending) {
+        e.notify = false;
+    }
+    for (StashEntry& e : mReorderStash) {
+        e.notify = false;
+    }
+}
+
+uint32_t OutputBuffers::getReorderDepth() const {
+    return mDepth;
+}
+
+void OutputBuffers::setReorderDepth(uint32_t depth) {
+    mPending.splice(mPending.end(), mReorderStash);
+    mDepth = depth;
+}
+
+void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
+    mPending.splice(mPending.end(), mReorderStash);
+    mKey = key;
+}
+
+void OutputBuffers::pushToStash(
+        const std::shared_ptr<C2Buffer>& buffer,
+        bool notify,
+        int64_t timestamp,
+        int32_t flags,
+        const sp<AMessage>& format,
+        const C2WorkOrdinalStruct& ordinal) {
+    bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
+    if (!buffer && eos) {
+        // TRICKY: we may be violating ordering of the stash here. Because we
+        // don't expect any more emplace() calls after this, the ordering should
+        // not matter.
+        mReorderStash.emplace_back(
+                buffer, notify, timestamp, flags, format, ordinal);
+    } else {
+        flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
+        auto it = mReorderStash.begin();
+        for (; it != mReorderStash.end(); ++it) {
+            if (less(ordinal, it->ordinal)) {
+                break;
+            }
+        }
+        mReorderStash.emplace(it,
+                buffer, notify, timestamp, flags, format, ordinal);
+        if (eos) {
+            mReorderStash.back().flags =
+                mReorderStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
+        }
+    }
+    while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
+        mPending.push_back(mReorderStash.front());
+        mReorderStash.pop_front();
+    }
+    ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
+}
+
+OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
+        std::shared_ptr<C2Buffer>* c2Buffer,
+        size_t* index,
+        sp<MediaCodecBuffer>* outBuffer) {
+    if (mPending.empty()) {
+        return SKIP;
+    }
+
+    // Retrieve the first entry.
+    StashEntry &entry = mPending.front();
+
+    *c2Buffer = entry.buffer;
+    sp<AMessage> outputFormat = entry.format;
+
+    // The output format can be processed without a registered slot.
+    if (outputFormat) {
+        ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
+                mName, outputFormat->debugString().c_str());
+        updateSkipCutBuffer(outputFormat, entry.notify);
+    }
+
+    if (entry.notify) {
+        if (outputFormat) {
+            setFormat(outputFormat);
+        } else if (mUnreportedFormat) {
+            outputFormat = mUnreportedFormat;
+            setFormat(outputFormat);
+        }
+        mUnreportedFormat = nullptr;
+    } else {
+        if (outputFormat) {
+            mUnreportedFormat = outputFormat;
+        } else if (!mUnreportedFormat) {
+            mUnreportedFormat = mFormat;
+        }
+    }
+
+    // Flushing mReorderStash because no other buffers should come after output
+    // EOS.
+    if (entry.flags & MediaCodec::BUFFER_FLAG_EOS) {
+        // Flush reorder stash
+        setReorderDepth(0);
+    }
+
+    if (!entry.notify) {
+        mPending.pop_front();
+        return DISCARD;
+    }
+
+    // Try to register the buffer.
+    status_t err = registerBuffer(*c2Buffer, index, outBuffer);
+    if (err != OK) {
+        if (err != WOULD_BLOCK) {
+            return REALLOCATE;
+        }
+        return RETRY;
+    }
+
+    // Append information from the front stash entry to outBuffer.
+    (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
+    (*outBuffer)->meta()->setInt32("flags", entry.flags);
+    ALOGV("[%s] popFromStashAndRegister: "
+          "out buffer index = %zu [%p] => %p + %zu (%lld)",
+          mName, *index, outBuffer->get(),
+          (*outBuffer)->data(), (*outBuffer)->size(),
+          (long long)entry.timestamp);
+
+    // The front entry of mPending will be removed now that the registration
+    // succeeded.
+    mPending.pop_front();
+    return NOTIFY_CLIENT;
+}
+
+bool OutputBuffers::popPending(StashEntry *entry) {
+    if (mPending.empty()) {
+        return false;
+    }
+    *entry = mPending.front();
+    mPending.pop_front();
+    return true;
+}
+
+void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
+    mPending.push_front(entry);
+}
+
+bool OutputBuffers::hasPending() const {
+    return !mPending.empty();
+}
+
+bool OutputBuffers::less(
+        const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
+    switch (mKey) {
+        case C2Config::ORDINAL:   return o1.frameIndex < o2.frameIndex;
+        case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
+        case C2Config::CUSTOM:    return o1.customOrdinal < o2.customOrdinal;
+        default:
+            ALOGD("Unrecognized key; default to timestamp");
+            return o1.frameIndex < o2.frameIndex;
+    }
 }
 
 // LocalBufferPool
 
-std::shared_ptr<LocalBufferPool> LocalBufferPool::Create(size_t poolCapacity) {
-    return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(poolCapacity));
+constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
+constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
+
+std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
+    return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
 }
 
 sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
@@ -185,6 +384,11 @@
             mUsedSize -= mPool.back().capacity();
             mPool.pop_back();
         }
+        while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
+            ALOGD("Increasing local buffer pool capacity from %zu to %zu",
+                  mPoolCapacity, mPoolCapacity * 2);
+            mPoolCapacity *= 2;
+        }
         if (mUsedSize + capacity > mPoolCapacity) {
             ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
                     mUsedSize, capacity, mPoolCapacity);
@@ -254,6 +458,7 @@
     std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
     if (!result) {
         result = clientBuffer->asC2Buffer();
+        clientBuffer->clearC2BufferRefs();
         mBuffers[index].compBuffer = result;
     }
     if (c2buffer) {
@@ -372,6 +577,7 @@
     std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
     if (!result) {
         result = clientBuffer->asC2Buffer();
+        clientBuffer->clearC2BufferRefs();
         mBuffers[index].compBuffer = result;
     }
     if (c2buffer) {
@@ -493,6 +699,44 @@
     return mAllocate();
 }
 
+// SlotInputBuffers
+
+bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
+    sp<Codec2Buffer> newBuffer = createNewBuffer();
+    *index = mImpl.assignSlot(newBuffer);
+    *buffer = newBuffer;
+    return true;
+}
+
+bool SlotInputBuffers::releaseBuffer(
+        const sp<MediaCodecBuffer> &buffer,
+        std::shared_ptr<C2Buffer> *c2buffer,
+        bool release) {
+    return mImpl.releaseSlot(buffer, c2buffer, release);
+}
+
+bool SlotInputBuffers::expireComponentBuffer(
+        const std::shared_ptr<C2Buffer> &c2buffer) {
+    return mImpl.expireComponentBuffer(c2buffer);
+}
+
+void SlotInputBuffers::flush() {
+    mImpl.flush();
+}
+
+std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
+    TRESPASS("Array mode should not be called at non-legacy mode");
+    return nullptr;
+}
+
+size_t SlotInputBuffers::numClientBuffers() const {
+    return mImpl.numClientBuffers();
+}
+
+sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
+    return new DummyContainerBuffer{mFormat, nullptr};
+}
+
 // LinearInputBuffers
 
 bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
@@ -730,11 +974,10 @@
 // GraphicInputBuffers
 
 GraphicInputBuffers::GraphicInputBuffers(
-        size_t numInputSlots, const char *componentName, const char *name)
+        const char *componentName, const char *name)
     : InputBuffers(componentName, name),
       mImpl(mName),
-      mLocalBufferPool(LocalBufferPool::Create(
-              kMaxLinearBufferSize * numInputSlots)) { }
+      mLocalBufferPool(LocalBufferPool::Create()) { }
 
 bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
     sp<Codec2Buffer> newBuffer = createNewBuffer();
@@ -895,7 +1138,7 @@
         case C2BufferData::GRAPHIC: {
             // This is only called for RawGraphicOutputBuffers.
             mAlloc = [format = mFormat,
-                      lbp = LocalBufferPool::Create(kMaxLinearBufferSize * mImpl.arraySize())] {
+                      lbp = LocalBufferPool::Create()] {
                 return ConstGraphicBlockBuffer::AllocateEmpty(
                         format,
                         [lbp](size_t capacity) {
@@ -921,6 +1164,16 @@
     mImpl.grow(newSize, mAlloc);
 }
 
+void OutputBuffersArray::transferFrom(OutputBuffers* source) {
+    mFormat = source->mFormat;
+    mSkipCutBuffer = source->mSkipCutBuffer;
+    mUnreportedFormat = source->mUnreportedFormat;
+    mPending = std::move(source->mPending);
+    mReorderStash = std::move(source->mReorderStash);
+    mDepth = source->mDepth;
+    mKey = source->mKey;
+}
+
 // FlexOutputBuffers
 
 status_t FlexOutputBuffers::registerBuffer(
@@ -963,13 +1216,12 @@
     // track of the flushed work.
 }
 
-std::unique_ptr<OutputBuffers> FlexOutputBuffers::toArrayMode(size_t size) {
+std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
     std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
-    array->setFormat(mFormat);
-    array->transferSkipCutBuffer(mSkipCutBuffer);
+    array->transferFrom(this);
     std::function<sp<Codec2Buffer>()> alloc = getAlloc();
     array->initialize(mImpl, size, alloc);
-    return std::move(array);
+    return array;
 }
 
 size_t FlexOutputBuffers::numClientBuffers() const {
@@ -1032,10 +1284,9 @@
 // RawGraphicOutputBuffers
 
 RawGraphicOutputBuffers::RawGraphicOutputBuffers(
-        size_t numOutputSlots, const char *componentName, const char *name)
+        const char *componentName, const char *name)
     : FlexOutputBuffers(componentName, name),
-      mLocalBufferPool(LocalBufferPool::Create(
-              kMaxLinearBufferSize * numOutputSlots)) { }
+      mLocalBufferPool(LocalBufferPool::Create()) { }
 
 sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
     if (buffer == nullptr) {
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 2cb6b81..0d4fa81 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -25,10 +25,13 @@
 #include <media/MediaCodecBuffer.h>
 
 #include "Codec2Buffer.h"
-#include "SkipCutBuffer.h"
 
 namespace android {
 
+struct ICrypto;
+class MemoryDealer;
+class SkipCutBuffer;
+
 constexpr size_t kLinearBufferSize = 1048576;
 // This can fit 4K RGBA frame, and most likely client won't need more than this.
 constexpr size_t kMaxLinearBufferSize = 4096 * 2304 * 4;
@@ -153,16 +156,21 @@
     DISALLOW_EVIL_CONSTRUCTORS(InputBuffers);
 };
 
+class OutputBuffersArray;
+
 class OutputBuffers : public CCodecBuffers {
 public:
-    OutputBuffers(const char *componentName, const char *name = "Output")
-        : CCodecBuffers(componentName, name) { }
-    virtual ~OutputBuffers() = default;
+    OutputBuffers(const char *componentName, const char *name = "Output");
+    virtual ~OutputBuffers();
 
     /**
      * Register output C2Buffer from the component and obtain corresponding
-     * index and MediaCodecBuffer object. Returns false if registration
-     * fails.
+     * index and MediaCodecBuffer object.
+     *
+     * Returns:
+     *   OK if registration succeeds.
+     *   NO_MEMORY if all buffers are available but not compatible.
+     *   WOULD_BLOCK if there are compatible buffers, but they are all in use.
      */
     virtual status_t registerBuffer(
             const std::shared_ptr<C2Buffer> &buffer,
@@ -197,7 +205,7 @@
      * shall retain the internal state so that it will honor index and
      * buffer from previous calls of registerBuffer().
      */
-    virtual std::unique_ptr<OutputBuffers> toArrayMode(size_t size) = 0;
+    virtual std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) = 0;
 
     /**
      * Initialize SkipCutBuffer object.
@@ -206,6 +214,164 @@
             int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount);
 
     /**
+     * Update SkipCutBuffer from format. The @p format must not be null.
+     * @p notify determines whether the format comes with a buffer that should
+     * be reported to the client or not.
+     */
+    void updateSkipCutBuffer(const sp<AMessage> &format, bool notify = true);
+
+    /**
+     * Output Stash
+     * ============
+     *
+     * The output stash is a place to hold output buffers temporarily before
+     * they are registered to output slots. It has 2 main functions:
+     * 1. Allow reordering of output frames as the codec may produce frames in a
+     *    different order.
+     * 2. Act as a "buffer" between the codec and the client because the codec
+     *    may produce more buffers than available slots. This excess of codec's
+     *    output buffers should be registered to slots later, after the client
+     *    has released some slots.
+     *
+     * The stash consists of 2 lists of buffers: mPending and mReorderStash.
+     * mPending is a normal FIFO queue with not size limit, while mReorderStash
+     * is a sorted list with size limit mDepth.
+     *
+     * The normal flow of a non-csd output buffer is as follows:
+     *
+     *           |----------------OutputBuffers---------------|
+     *           |----------Output stash----------|           |
+     *   Codec --|-> mReorderStash --> mPending --|-> slots --|-> client
+     *           |                                |           |
+     *     pushToStash()                    popFromStashAndRegister()
+     *
+     * The buffer that comes from the codec first enters mReorderStash. The
+     * first buffer in mReorderStash gets moved to mPending when mReorderStash
+     * overflows. Buffers in mPending are registered to slots and given to the
+     * client as soon as slots are available.
+     *
+     * Every output buffer that is not a csd buffer should be put on the stash
+     * by calling pushToStash(), then later registered to a slot by calling
+     * popFromStashAndRegister() before notifying the client with
+     * onOutputBufferAvailable().
+     *
+     * Reordering
+     * ==========
+     *
+     * mReorderStash is a sorted list with a specified size limit. The size
+     * limit can be set by calling setReorderDepth().
+     *
+     * Every buffer in mReorderStash has a C2WorkOrdinalStruct, which contains 3
+     * members, all of which are comparable. Which member of C2WorkOrdinalStruct
+     * should be used for reordering can be chosen by calling setReorderKey().
+     */
+
+    /**
+     * Return the reorder depth---the size of mReorderStash.
+     */
+    uint32_t getReorderDepth() const;
+
+    /**
+     * Set the reorder depth.
+     */
+    void setReorderDepth(uint32_t depth);
+
+    /**
+     * Set the type of "key" to use in comparisons.
+     */
+    void setReorderKey(C2Config::ordinal_key_t key);
+
+    /**
+     * Return whether the output stash has any pending buffers.
+     */
+    bool hasPending() const;
+
+    /**
+     * Flush the stash and reset the depth and the key to their default values.
+     */
+    void clearStash();
+
+    /**
+     * Flush the stash.
+     */
+    void flushStash();
+
+    /**
+     * Push a buffer to the reorder stash.
+     *
+     * @param buffer    C2Buffer object from the returned work.
+     * @param notify    Whether the returned work contains a buffer that should
+     *                  be reported to the client. This may be false if the
+     *                  caller wants to process the buffer without notifying the
+     *                  client.
+     * @param timestamp Buffer timestamp to report to the client.
+     * @param flags     Buffer flags to report to the client.
+     * @param format    Buffer format to report to the client.
+     * @param ordinal   Ordinal used in reordering. This determines when the
+     *                  buffer will be popped from the output stash by
+     *                  `popFromStashAndRegister()`.
+     */
+    void pushToStash(
+            const std::shared_ptr<C2Buffer>& buffer,
+            bool notify,
+            int64_t timestamp,
+            int32_t flags,
+            const sp<AMessage>& format,
+            const C2WorkOrdinalStruct& ordinal);
+
+    enum BufferAction : int {
+        SKIP,
+        DISCARD,
+        NOTIFY_CLIENT,
+        REALLOCATE,
+        RETRY,
+    };
+
+    /**
+     * Try to atomically pop the first buffer from the reorder stash and
+     * register it to an output slot. The function returns a value that
+     * indicates a recommended course of action for the caller.
+     *
+     * If the stash is empty, the function will return `SKIP`.
+     *
+     * If the stash is not empty, the function will peek at the first (oldest)
+     * entry in mPending process the buffer in the entry as follows:
+     * - If the buffer should not be sent to the client, the function will
+     *   return `DISCARD`. The stash entry will be removed.
+     * - If the buffer should be sent to the client, the function will attempt
+     *   to register the buffer to a slot. The registration may have 3 outcomes
+     *   corresponding to the following return values:
+     *   - `NOTIFY_CLIENT`: The buffer is successfully registered to a slot. The
+     *     output arguments @p index and @p outBuffer will contain valid values
+     *     that the caller can use to call onOutputBufferAvailable(). The stash
+     *     entry will be removed.
+     *   - `REALLOCATE`: The buffer is not registered because it is not
+     *     compatible with the current slots (which are available). The caller
+     *     should reallocate the OutputBuffers with slots that can fit the
+     *     returned @p c2Buffer. The stash entry will not be removed
+     *   - `RETRY`: All slots are currently occupied by the client. The caller
+     *     should try to call this function again after the client has released
+     *     some slots.
+     *
+     * @return What the caller should do afterwards.
+     *
+     * @param[out] c2Buffer   Underlying C2Buffer associated to the first buffer
+     *                        on the stash. This value is guaranteed to be valid
+     *                        unless the return value is `SKIP`.
+     * @param[out] index      Slot index. This value is valid only if the return
+     *                        value is `NOTIFY_CLIENT`.
+     * @param[out] outBuffer  Registered buffer. This value is valid only if the
+     *                        return valu is `NOTIFY_CLIENT`.
+     */
+    BufferAction popFromStashAndRegister(
+            std::shared_ptr<C2Buffer>* c2Buffer,
+            size_t* index,
+            sp<MediaCodecBuffer>* outBuffer);
+
+protected:
+    sp<SkipCutBuffer> mSkipCutBuffer;
+
+    /**
      * Update the SkipCutBuffer object. No-op if it's never initialized.
      */
     void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount);
@@ -215,22 +381,87 @@
      */
     void submit(const sp<MediaCodecBuffer> &buffer);
 
-    /**
-     * Transfer SkipCutBuffer object to the other Buffers object.
-     */
-    void transferSkipCutBuffer(const sp<SkipCutBuffer> &scb);
-
-protected:
-    sp<SkipCutBuffer> mSkipCutBuffer;
-
 private:
+    // SkipCutBuffer
     int32_t mDelay;
     int32_t mPadding;
     int32_t mSampleRate;
+    int32_t mChannelCount;
 
-    void setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount);
+    void setSkipCutBuffer(int32_t skip, int32_t cut);
+
+    // Output stash
+
+    // Output format that has not been made available to the client.
+    sp<AMessage> mUnreportedFormat;
+
+    // Struct for an entry in the output stash (mPending and mReorderStash)
+    struct StashEntry {
+        inline StashEntry()
+            : buffer(nullptr),
+              notify(false),
+              timestamp(0),
+              flags(0),
+              format(),
+              ordinal({0, 0, 0}) {}
+        inline StashEntry(
+                const std::shared_ptr<C2Buffer> &b,
+                bool n,
+                int64_t t,
+                int32_t f,
+                const sp<AMessage> &fmt,
+                const C2WorkOrdinalStruct &o)
+            : buffer(b),
+              notify(n),
+              timestamp(t),
+              flags(f),
+              format(fmt),
+              ordinal(o) {}
+        std::shared_ptr<C2Buffer> buffer;
+        bool notify;
+        int64_t timestamp;
+        int32_t flags;
+        sp<AMessage> format;
+        C2WorkOrdinalStruct ordinal;
+    };
+
+    /**
+     * FIFO queue of stash entries.
+     */
+    std::list<StashEntry> mPending;
+    /**
+     * Sorted list of stash entries.
+     */
+    std::list<StashEntry> mReorderStash;
+    /**
+     * Size limit of mReorderStash.
+     */
+    uint32_t mDepth{0};
+    /**
+     * Choice of key to use in ordering of stash entries in mReorderStash.
+     */
+    C2Config::ordinal_key_t mKey{C2Config::ORDINAL};
+
+    /**
+     * Return false if mPending is empty; otherwise, pop the first entry from
+     * mPending and return true.
+     */
+    bool popPending(StashEntry *entry);
+
+    /**
+     * Push an entry as the first entry of mPending.
+     */
+    void deferPending(const StashEntry &entry);
+
+    /**
+     * Comparison of C2WorkOrdinalStruct based on mKey.
+     */
+    bool less(const C2WorkOrdinalStruct &o1,
+              const C2WorkOrdinalStruct &o2) const;
 
     DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
+
+    friend OutputBuffersArray;
 };
 
 /**
@@ -241,11 +472,9 @@
     /**
      * Create a new LocalBufferPool object.
      *
-     * \param poolCapacity  max total size of buffers managed by this pool.
-     *
      * \return  a newly created pool object.
      */
-    static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity);
+    static std::shared_ptr<LocalBufferPool> Create();
 
     /**
      * Return an ABuffer object whose size is at least |capacity|.
@@ -415,7 +644,7 @@
             size_t *index,
             sp<Codec2Buffer> *buffer,
             std::function<bool(const sp<Codec2Buffer> &)> match =
-                [](const sp<Codec2Buffer> &) { return true; });
+                [](const sp<Codec2Buffer> &buffer) { return (buffer != nullptr); });
 
     /**
      * Return the buffer from the client, and get the C2Buffer object back from
@@ -546,6 +775,36 @@
     std::function<sp<Codec2Buffer>()> mAllocate;
 };
 
+class SlotInputBuffers : public InputBuffers {
+public:
+    SlotInputBuffers(const char *componentName, const char *name = "Slot-Input")
+        : InputBuffers(componentName, name),
+          mImpl(mName) { }
+    ~SlotInputBuffers() override = default;
+
+    bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) final;
+
+    bool releaseBuffer(
+            const sp<MediaCodecBuffer> &buffer,
+            std::shared_ptr<C2Buffer> *c2buffer,
+            bool release) final;
+
+    bool expireComponentBuffer(
+            const std::shared_ptr<C2Buffer> &c2buffer) final;
+
+    void flush() final;
+
+    std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
+
+    size_t numClientBuffers() const final;
+
+protected:
+    sp<Codec2Buffer> createNewBuffer() final;
+
+private:
+    FlexBuffersImpl mImpl;
+};
+
 class LinearInputBuffers : public InputBuffers {
 public:
     LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
@@ -647,8 +906,7 @@
 
 class GraphicInputBuffers : public InputBuffers {
 public:
-    GraphicInputBuffers(
-            size_t numInputSlots, const char *componentName, const char *name = "2D-BB-Input");
+    GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input");
     ~GraphicInputBuffers() override = default;
 
     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
@@ -740,7 +998,7 @@
 
     bool isArrayMode() const final { return true; }
 
-    std::unique_ptr<OutputBuffers> toArrayMode(size_t) final {
+    std::unique_ptr<OutputBuffersArray> toArrayMode(size_t) final {
         return nullptr;
     }
 
@@ -779,6 +1037,12 @@
      */
     void grow(size_t newSize);
 
+    /**
+     * Transfer the SkipCutBuffer and the output stash from another
+     * OutputBuffers.
+     */
+    void transferFrom(OutputBuffers* source);
+
 private:
     BuffersArrayImpl mImpl;
     std::function<sp<Codec2Buffer>()> mAlloc;
@@ -807,7 +1071,7 @@
     void flush(
             const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
 
-    std::unique_ptr<OutputBuffers> toArrayMode(size_t size) override;
+    std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override;
 
     size_t numClientBuffers() const final;
 
@@ -860,8 +1124,7 @@
 
 class RawGraphicOutputBuffers : public FlexOutputBuffers {
 public:
-    RawGraphicOutputBuffers(
-            size_t numOutputSlots, const char *componentName, const char *name = "2D-BB-Output");
+    RawGraphicOutputBuffers(const char *componentName, const char *name = "2D-BB-Output");
     ~RawGraphicOutputBuffers() override = default;
 
     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5adcd94..96f86e8 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -20,7 +20,6 @@
 #include <log/log.h>
 
 #include <C2Component.h>
-#include <C2Debug.h>
 #include <C2Param.h>
 #include <util/C2InterfaceHelper.h>
 
@@ -34,6 +33,8 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0   /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS -1 /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 // names of properties that can be used to override the default DRC settings
 #define PROP_DRC_OVERRIDE_REF_LEVEL  "aac_drc_reference_level"
@@ -49,6 +50,27 @@
 
 namespace {
 
+void C2ValueToMessageItem(const C2Value &value, AMessage::ItemData &item) {
+    int32_t int32Value;
+    uint32_t uint32Value;
+    int64_t int64Value;
+    uint64_t uint64Value;
+    float floatValue;
+    if (value.get(&int32Value)) {
+        item.set(int32Value);
+    } else if (value.get(&uint32Value) && uint32Value <= uint32_t(INT32_MAX)) {
+        // SDK does not support unsigned values
+        item.set((int32_t)uint32Value);
+    } else if (value.get(&int64Value)) {
+        item.set(int64Value);
+    } else if (value.get(&uint64Value) && uint64Value <= uint64_t(INT64_MAX)) {
+        // SDK does not support unsigned values
+        item.set((int64_t)uint64Value);
+    } else if (value.get(&floatValue)) {
+        item.set(floatValue);
+    }
+}
+
 /**
  * mapping between SDK and Codec 2.0 configurations.
  */
@@ -138,27 +160,10 @@
     /// Maps from a C2Value to an SDK value in an AMessage.
     AMessage::ItemData mapToMessage(C2Value value) const {
         AMessage::ItemData item;
-        int32_t int32Value;
-        uint32_t uint32Value;
-        int64_t int64Value;
-        uint64_t uint64Value;
-        float floatValue;
         if (value.type() != C2Value::NO_INIT && mReverse) {
             value = mReverse(value);
         }
-        if (value.get(&int32Value)) {
-            item.set(int32Value);
-        } else if (value.get(&uint32Value) && uint32Value <= uint32_t(INT32_MAX)) {
-            // SDK does not support unsigned values
-            item.set((int32_t)uint32Value);
-        } else if (value.get(&int64Value)) {
-            item.set(int64Value);
-        } else if (value.get(&uint64Value) && uint64Value <= uint64_t(INT64_MAX)) {
-            // SDK does not support unsigned values
-            item.set((int64_t)uint64Value);
-        } else if (value.get(&floatValue)) {
-            item.set(floatValue);
-        }
+        C2ValueToMessageItem(value, item);
         return item;
     }
 
@@ -179,10 +184,10 @@
 
 template <typename PORT, typename STREAM>
 AString QueryMediaTypeImpl(
-        const std::shared_ptr<Codec2Client::Component> &component) {
+        const std::shared_ptr<Codec2Client::Configurable> &configurable) {
     AString mediaType;
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err = component->query(
+    c2_status_t c2err = configurable->query(
             {}, { PORT::PARAM_TYPE, STREAM::PARAM_TYPE }, C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK && queried.size() == 0) {
         ALOGD("Query media type failed => %s", asString(c2err));
@@ -207,13 +212,13 @@
 }
 
 AString QueryMediaType(
-        bool input, const std::shared_ptr<Codec2Client::Component> &component) {
+        bool input, const std::shared_ptr<Codec2Client::Configurable> &configurable) {
     typedef C2PortMediaTypeSetting P;
     typedef C2StreamMediaTypeSetting S;
     if (input) {
-        return QueryMediaTypeImpl<P::input, S::input>(component);
+        return QueryMediaTypeImpl<P::input, S::input>(configurable);
     } else {
-        return QueryMediaTypeImpl<P::output, S::output>(component);
+        return QueryMediaTypeImpl<P::output, S::output>(configurable);
     }
 }
 
@@ -595,39 +600,28 @@
         .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (v.get(&value)) {
-                switch (value) {
-                    case COLOR_FormatSurface:
-                        return (uint32_t)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-                    case COLOR_FormatYUV420Flexible:
-                        return (uint32_t)HAL_PIXEL_FORMAT_YCBCR_420_888;
-                    case COLOR_FormatYUV420Planar:
-                    case COLOR_FormatYUV420SemiPlanar:
-                    case COLOR_FormatYUV420PackedPlanar:
-                    case COLOR_FormatYUV420PackedSemiPlanar:
-                        return (uint32_t)HAL_PIXEL_FORMAT_YV12;
-                    default:
-                        // TODO: support some sort of passthrough
-                        break;
+                uint32_t result;
+                if (C2Mapper::mapPixelFormatFrameworkToCodec(value, &result)) {
+                    return result;
                 }
             }
             return C2Value();
         }, [](C2Value v) -> C2Value {
             uint32_t value;
             if (v.get(&value)) {
-                switch (value) {
-                    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-                        return COLOR_FormatSurface;
-                    case HAL_PIXEL_FORMAT_YV12:
-                    case HAL_PIXEL_FORMAT_YCBCR_420_888:
-                        return COLOR_FormatYUV420Flexible;
-                    default:
-                        // TODO: support some sort of passthrough
-                        break;
+                int32_t result;
+                if (C2Mapper::mapPixelFormatCodecToFramework(value, &result)) {
+                    return result;
                 }
             }
             return C2Value();
         }));
 
+    add(ConfigMapper(KEY_PIXEL_ASPECT_RATIO_WIDTH,  C2_PARAMKEY_PIXEL_ASPECT_RATIO, "width")
+        .limitTo((D::VIDEO | D::IMAGE) & D::RAW));
+    add(ConfigMapper(KEY_PIXEL_ASPECT_RATIO_HEIGHT, C2_PARAMKEY_PIXEL_ASPECT_RATIO, "height")
+        .limitTo((D::VIDEO | D::IMAGE) & D::RAW));
+
     add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CHANNEL_COUNT,       "value")
         .limitTo(D::AUDIO)); // read back to both formats
     add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CODED_CHANNEL_COUNT, "value")
@@ -716,63 +710,101 @@
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
-            if (!v.get(&value) || value < 0) {
+            if (!v.get(&value) || value < -1) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_REF_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
             }
             return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+                return (int32_t) (-4. * value);
+            }
+            return C2Value();
         }));
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_CUT, DRC_DEFAULT_MOBILE_DRC_CUT);
             }
             return float(c2_min(value, 127) / 127.);
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (value * 127. + 0.5);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_BOOST, DRC_DEFAULT_MOBILE_DRC_BOOST);
             }
             return float(c2_min(value, 127) / 127.);
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (value * 127. + 0.5);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to compression type and add default
     add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
             }
             return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return value;
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_ENC_LEVEL, DRC_DEFAULT_MOBILE_ENC_LEVEL);
             }
             return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+              return (int32_t) (-4. * value);
+            }
+            else {
+              return C2Value();
+            }
         }));
 
     // convert to effect type (these map to SDK values) and add default
     add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value")
-        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
-        .withMapper([](C2Value v) -> C2Value {
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < -1 || value > 8) {
                 value = property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT);
@@ -782,13 +814,60 @@
                 }
             }
             return value;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return  value;
+            }
+            else {
+              return C2Value();
+            }
+        }));
+
+    // convert to album mode and add default
+    add(ConfigMapper(KEY_AAC_DRC_ALBUM_MODE, C2_PARAMKEY_DRC_ALBUM_MODE, "value")
+        .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+        .withMappers([](C2Value v) -> C2Value {
+            int32_t value;
+            if (!v.get(&value) || value < 0 || value > 1) {
+                value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+                // ensure value is within range
+                if (value < 0 || value > 1) {
+                    value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+                }
+            }
+            return value;
+        },[](C2Value v) -> C2Value {
+            int32_t value;
+            if (v.get(&value)) {
+              return value;
+            }
+            else {
+              return C2Value();
+            }
+        }));
+
+    add(ConfigMapper(KEY_AAC_DRC_OUTPUT_LOUDNESS, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS, "value")
+        .limitTo(D::OUTPUT & D::DECODER & D::READ)
+        .withMappers([](C2Value v) -> C2Value {
+            int32_t value;
+            if (!v.get(&value) || value < -1) {
+                value = DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS;
+            }
+            return float(-0.25 * c2_min(value, 127));
+        },[](C2Value v) -> C2Value {
+            float value;
+            if (v.get(&value)) {
+                return (int32_t) (-4. * value);
+            }
+            return C2Value();
         }));
 
     add(ConfigMapper(KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value")
-        .limitTo(D::AUDIO));
+        .limitTo(D::AUDIO & (D::CONFIG | D::PARAM | D::READ)));
 
     add(ConfigMapper(KEY_AAC_SBR_MODE, C2_PARAMKEY_AAC_SBR_MODE, "value")
-        .limitTo(D::AUDIO & D::ENCODER & D::CONFIG)
+        .limitTo(D::AUDIO & D::ENCODER & (D::CONFIG | D::PARAM | D::READ))
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -823,6 +902,14 @@
 
     add(ConfigMapper(C2_PARAMKEY_INPUT_TIME_STRETCH, C2_PARAMKEY_INPUT_TIME_STRETCH, "value"));
 
+    add(ConfigMapper(KEY_LOW_LATENCY, C2_PARAMKEY_LOW_LATENCY_MODE, "value")
+        .limitTo(D::DECODER & (D::CONFIG | D::PARAM))
+        .withMapper([](C2Value v) -> C2Value {
+            int32_t value = 0;
+            (void)v.get(&value);
+            return value == 0 ? C2_FALSE : C2_TRUE;
+        }));
+
     /* still to do
     constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
 
@@ -833,27 +920,27 @@
 }
 
 status_t CCodecConfig::initialize(
-        const std::shared_ptr<Codec2Client> &client,
-        const std::shared_ptr<Codec2Client::Component> &component) {
+        const std::shared_ptr<C2ParamReflector> &reflector,
+        const std::shared_ptr<Codec2Client::Configurable> &configurable) {
     C2ComponentDomainSetting domain(C2Component::DOMAIN_OTHER);
     C2ComponentKindSetting kind(C2Component::KIND_OTHER);
 
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err = component->query({ &domain, &kind }, {}, C2_DONT_BLOCK, &queried);
+    c2_status_t c2err = configurable->query({ &domain, &kind }, {}, C2_DONT_BLOCK, &queried);
     if (c2err != C2_OK) {
         ALOGD("Query domain & kind failed => %s", asString(c2err));
         // TEMP: determine kind from component name
         if (kind.value == C2Component::KIND_OTHER) {
-            if (component->getName().find("encoder") != std::string::npos) {
+            if (configurable->getName().find("encoder") != std::string::npos) {
                 kind.value = C2Component::KIND_ENCODER;
-            } else if (component->getName().find("decoder") != std::string::npos) {
+            } else if (configurable->getName().find("decoder") != std::string::npos) {
                 kind.value = C2Component::KIND_DECODER;
             }
         }
 
         // TEMP: determine domain from media type (port (preferred) or stream #0)
         if (domain.value == C2Component::DOMAIN_OTHER) {
-            AString mediaType = QueryMediaType(true /* input */, component);
+            AString mediaType = QueryMediaType(true /* input */, configurable);
             if (mediaType.startsWith("audio/")) {
                 domain.value = C2Component::DOMAIN_AUDIO;
             } else if (mediaType.startsWith("video/")) {
@@ -878,16 +965,16 @@
     std::vector<C2Param::Index> paramIndices;
     switch (kind.value) {
     case C2Component::KIND_DECODER:
-        mCodingMediaType = QueryMediaType(true /* input */, component).c_str();
+        mCodingMediaType = QueryMediaType(true /* input */, configurable).c_str();
         break;
     case C2Component::KIND_ENCODER:
-        mCodingMediaType = QueryMediaType(false /* input */, component).c_str();
+        mCodingMediaType = QueryMediaType(false /* input */, configurable).c_str();
         break;
     default:
         mCodingMediaType = "";
     }
 
-    c2err = component->querySupportedParams(&mParamDescs);
+    c2err = configurable->querySupportedParams(&mParamDescs);
     if (c2err != C2_OK) {
         ALOGD("Query supported params failed after returning %zu values => %s",
                 mParamDescs.size(), asString(c2err));
@@ -897,9 +984,9 @@
         mSupportedIndices.emplace(desc->index());
     }
 
-    mReflector = client->getParamReflector();
+    mReflector = reflector;
     if (mReflector == nullptr) {
-        ALOGE("Failed to get param reflector");
+        ALOGE("Null param reflector");
         return UNKNOWN_ERROR;
     }
 
@@ -953,11 +1040,21 @@
     // init data (CSD)
     mSubscribedIndices.emplace(C2StreamInitDataInfo::output::PARAM_TYPE);
 
+    for (const std::shared_ptr<C2ParamDescriptor> &desc : mParamDescs) {
+        if (desc->index().isVendor()) {
+            std::vector<std::string> keys;
+            mParamUpdater->getKeysForParamIndex(desc->index(), &keys);
+            for (const std::string &key : keys) {
+                mVendorParamIndices.insert_or_assign(key, desc->index());
+            }
+        }
+    }
+
     return OK;
 }
 
 status_t CCodecConfig::subscribeToConfigUpdate(
-        const std::shared_ptr<Codec2Client::Component> &component,
+        const std::shared_ptr<Codec2Client::Configurable> &configurable,
         const std::vector<C2Param::Index> &indices,
         c2_blocking_t blocking) {
     mSubscribedIndices.insert(indices.begin(), indices.end());
@@ -970,7 +1067,7 @@
         std::unique_ptr<C2SubscribedParamIndicesTuning> subscribeTuning =
             C2SubscribedParamIndicesTuning::AllocUnique(indices);
         std::vector<std::unique_ptr<C2SettingResult>> results;
-        c2_status_t c2Err = component->config({ subscribeTuning.get() }, blocking, &results);
+        c2_status_t c2Err = configurable->config({ subscribeTuning.get() }, blocking, &results);
         if (c2Err != C2_OK && c2Err != C2_BAD_INDEX) {
             ALOGD("Failed to subscribe to parameters => %s", asString(c2Err));
             // TODO: error
@@ -982,11 +1079,11 @@
 }
 
 status_t CCodecConfig::queryConfiguration(
-        const std::shared_ptr<Codec2Client::Component> &component) {
+        const std::shared_ptr<Codec2Client::Configurable> &configurable) {
     // query all subscribed parameters
     std::vector<C2Param::Index> indices(mSubscribedIndices.begin(), mSubscribedIndices.end());
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2Err = component->query({}, indices, C2_MAY_BLOCK, &queried);
+    c2_status_t c2Err = configurable->query({}, indices, C2_MAY_BLOCK, &queried);
     if (c2Err != OK) {
         ALOGI("query failed after returning %zu values (%s)", queried.size(), asString(c2Err));
         // TODO: error
@@ -1056,7 +1153,7 @@
     if (domain & mInputDomain) {
         sp<AMessage> oldFormat = mInputFormat;
         mInputFormat = mInputFormat->dup(); // trigger format changed
-        mInputFormat->extend(getSdkFormatForDomain(reflected, mInputDomain));
+        mInputFormat->extend(getFormatForDomain(reflected, mInputDomain));
         if (mInputFormat->countEntries() != oldFormat->countEntries()
                 || mInputFormat->changesFrom(oldFormat)->countEntries() > 0) {
             changed = true;
@@ -1067,7 +1164,7 @@
     if (domain & mOutputDomain) {
         sp<AMessage> oldFormat = mOutputFormat;
         mOutputFormat = mOutputFormat->dup(); // trigger output format changed
-        mOutputFormat->extend(getSdkFormatForDomain(reflected, mOutputDomain));
+        mOutputFormat->extend(getFormatForDomain(reflected, mOutputDomain));
         if (mOutputFormat->countEntries() != oldFormat->countEntries()
                 || mOutputFormat->changesFrom(oldFormat)->countEntries() > 0) {
             changed = true;
@@ -1079,8 +1176,9 @@
     return changed;
 }
 
-sp<AMessage> CCodecConfig::getSdkFormatForDomain(
-        const ReflectedParamUpdater::Dict &reflected, Domain portDomain) const {
+sp<AMessage> CCodecConfig::getFormatForDomain(
+        const ReflectedParamUpdater::Dict &reflected,
+        Domain portDomain) const {
     sp<AMessage> msg = new AMessage;
     for (const std::pair<std::string, std::vector<ConfigMapper>> &el : mStandardParams->getKeys()) {
         for (const ConfigMapper &cm : el.second) {
@@ -1111,6 +1209,39 @@
         }
     }
 
+    bool input = (portDomain & Domain::IS_INPUT);
+    std::vector<std::string> vendorKeys;
+    for (const std::pair<std::string, ReflectedParamUpdater::Value> &entry : reflected) {
+        auto it = mVendorParamIndices.find(entry.first);
+        if (it == mVendorParamIndices.end()) {
+            continue;
+        }
+        if (mSubscribedIndices.count(it->second) == 0) {
+            continue;
+        }
+        // For vendor parameters, we only care about direction
+        if ((input && !it->second.forInput())
+                || (!input && !it->second.forOutput())) {
+            continue;
+        }
+        const ReflectedParamUpdater::Value &value = entry.second;
+        C2Value c2Value;
+        sp<ABuffer> bufValue;
+        AString strValue;
+        AMessage::ItemData item;
+        if (value.find(&c2Value)) {
+            C2ValueToMessageItem(c2Value, item);
+        } else if (value.find(&bufValue)) {
+            item.set(bufValue);
+        } else if (value.find(&strValue)) {
+            item.set(strValue);
+        } else {
+            ALOGD("unexpected untyped query value for key: %s", entry.first.c_str());
+            continue;
+        }
+        msg->setItem(entry.first.c_str(), item);
+    }
+
     { // convert from Codec 2.0 rect to MediaFormat rect and add crop rect if not present
         int32_t left, top, width, height;
         if (msg->findInt32("crop-left", &left) && msg->findInt32("crop-width", &width)
@@ -1518,7 +1649,7 @@
 }
 
 status_t CCodecConfig::getConfigUpdateFromSdkParams(
-        std::shared_ptr<Codec2Client::Component> component,
+        std::shared_ptr<Codec2Client::Configurable> configurable,
         const sp<AMessage> &sdkParams, Domain configDomain,
         c2_blocking_t blocking,
         std::vector<std::unique_ptr<C2Param>> *configUpdate) const {
@@ -1545,7 +1676,7 @@
         }
     }
 
-    c2_status_t err = component->query({ }, supportedIndices, blocking, configUpdate);
+    c2_status_t err = configurable->query({ }, supportedIndices, blocking, configUpdate);
     if (err != C2_OK) {
         ALOGD("query failed after returning %zu params => %s", configUpdate->size(), asString(err));
     }
@@ -1557,7 +1688,7 @@
 }
 
 status_t CCodecConfig::setParameters(
-        std::shared_ptr<Codec2Client::Component> component,
+        std::shared_ptr<Codec2Client::Configurable> configurable,
         std::vector<std::unique_ptr<C2Param>> &configUpdate,
         c2_blocking_t blocking) {
     status_t result = OK;
@@ -1593,10 +1724,10 @@
         }
     }
     // update subscribed param indices
-    subscribeToConfigUpdate(component, indices, blocking);
+    subscribeToConfigUpdate(configurable, indices, blocking);
 
     std::vector<std::unique_ptr<C2SettingResult>> failures;
-    c2_status_t err = component->config(paramVector, blocking, &failures);
+    c2_status_t err = configurable->config(paramVector, blocking, &failures);
     if (err != C2_OK) {
         ALOGD("config failed => %s", asString(err));
         // This is non-fatal.
@@ -1616,7 +1747,7 @@
     // Re-query parameter values in case config could not update them and update the current
     // configuration.
     configUpdate.clear();
-    err = component->query({}, indices, blocking, &configUpdate);
+    err = configurable->query({}, indices, blocking, &configUpdate);
     if (err != C2_OK) {
         ALOGD("query failed after returning %zu params => %s", configUpdate.size(), asString(err));
     }
@@ -1635,4 +1766,13 @@
     }
 }
 
+status_t CCodecConfig::subscribeToAllVendorParams(
+        const std::shared_ptr<Codec2Client::Configurable> &configurable,
+        c2_blocking_t blocking) {
+    for (const std::pair<std::string, C2Param::Index> &entry : mVendorParamIndices) {
+        mSubscribedIndices.insert(entry.second);
+    }
+    return subscribeToConfigUpdate(configurable, {}, blocking);
+}
+
 }  // namespace android
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index a61c8b7..2895746 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -23,8 +23,10 @@
 #include <vector>
 
 #include <C2Component.h>
-#include <codec2/hidl/client.h>
+#include <C2Config.h>
+#include <C2Debug.h>
 
+#include <codec2/hidl/client.h>
 #include <utils/RefBase.h>
 
 #include "InputSurfaceWrapper.h"
@@ -39,7 +41,6 @@
  * Struct managing the codec configuration for CCodec.
  */
 struct CCodecConfig {
-
     /**
      * Domain consists of a bitmask divided into fields, and specifiers work by excluding other
      * values in those domains.
@@ -118,6 +119,7 @@
     sp<AMessage> mOutputFormat;
 
     bool mUsingSurface; ///< using input or output surface
+    bool mBuffersBoundToCodec; ///< whether buffers are bound to codecs or not.
 
     std::shared_ptr<InputSurfaceWrapper> mInputSurface;
     std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
@@ -134,6 +136,9 @@
     /// For now support a validation function.
     std::map<C2Param::Index, LocalParamValidator> mLocalParams;
 
+    /// Vendor field name -> index map.
+    std::map<std::string, C2Param::Index> mVendorParamIndices;
+
     std::set<std::string> mLastConfig;
 
     CCodecConfig();
@@ -142,9 +147,8 @@
     /// reflected param helper, domain, standard params, and subscribes to standard
     /// indices.
     status_t initialize(
-            const std::shared_ptr<Codec2Client> &client,
-            const std::shared_ptr<Codec2Client::Component> &component);
-
+            const std::shared_ptr<C2ParamReflector> &client,
+            const std::shared_ptr<Codec2Client::Configurable> &configurable);
 
     /**
      * Adds a locally maintained parameter. This is used for output configuration that can be
@@ -237,7 +241,7 @@
      * \param blocking blocking mode to use with the component
      */
     status_t getConfigUpdateFromSdkParams(
-            std::shared_ptr<Codec2Client::Component> component,
+            std::shared_ptr<Codec2Client::Configurable> configurable,
             const sp<AMessage> &sdkParams, Domain domain,
             c2_blocking_t blocking,
             std::vector<std::unique_ptr<C2Param>> *configUpdate) const;
@@ -249,19 +253,24 @@
      * \param blocking blocking mode to use with the component
      */
     status_t setParameters(
-            std::shared_ptr<Codec2Client::Component> component,
+            std::shared_ptr<Codec2Client::Configurable> configurable,
             std::vector<std::unique_ptr<C2Param>> &configUpdate,
             c2_blocking_t blocking);
 
     /// Queries subscribed indices (which contains all SDK-exposed values) and updates
     /// input/output formats.
     status_t queryConfiguration(
-            const std::shared_ptr<Codec2Client::Component> &component);
+            const std::shared_ptr<Codec2Client::Configurable> &configurable);
 
     /// Queries a configuration parameter value. Returns nullptr if the parameter is not
     /// part of the current configuration
     const C2Param *getConfigParameterValue(C2Param::Index index) const;
 
+    /// Subscribe to all vendor parameters.
+    status_t subscribeToAllVendorParams(
+            const std::shared_ptr<Codec2Client::Configurable> &configurable,
+            c2_blocking_t blocking);
+
     /**
      * Object that can be used to access configuration parameters and if they change.
      */
@@ -320,14 +329,15 @@
     /// Adds indices to the subscribed indices, and updated subscription to component
     /// \param blocking blocking mode to use with the component
     status_t subscribeToConfigUpdate(
-            const std::shared_ptr<Codec2Client::Component> &component,
+            const std::shared_ptr<Codec2Client::Configurable> &configurable,
             const std::vector<C2Param::Index> &indices,
             c2_blocking_t blocking = C2_DONT_BLOCK);
 
     /// Gets SDK format from codec 2.0 reflected configuration
     /// \param domain input/output bitmask
-    sp<AMessage> getSdkFormatForDomain(
-            const ReflectedParamUpdater::Dict &reflected, Domain domain) const;
+    sp<AMessage> getFormatForDomain(
+            const ReflectedParamUpdater::Dict &reflected,
+            Domain domain) const;
 
     /**
      * Converts a set of configuration parameters in an AMessage to a list of path-based Codec
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 5c8ad56..25e7da9 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,12 +18,16 @@
 #define LOG_TAG "Codec2Buffer"
 #include <utils/Log.h>
 
+#include <android/hardware/cas/native/1.0/types.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/CodecBase.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
+#include <mediadrm/ICrypto.h>
 #include <nativebase/nativebase.h>
 #include <ui/Fence.h>
 
@@ -110,7 +114,11 @@
 }
 
 std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
-    return std::move(mBufferRef);
+    return mBufferRef;
+}
+
+void DummyContainerBuffer::clearC2BufferRefs() {
+    mBufferRef.reset();
 }
 
 bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
@@ -186,7 +194,11 @@
 }
 
 std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
-    return std::move(mBufferRef);
+    return mBufferRef;
+}
+
+void ConstLinearBlockBuffer::clearC2BufferRefs() {
+    mBufferRef.reset();
 }
 
 // GraphicView2MediaImageConverter
@@ -688,8 +700,12 @@
 }
 
 std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
+    return mBufferRef;
+}
+
+void ConstGraphicBlockBuffer::clearC2BufferRefs() {
     mView.reset();
-    return std::move(mBufferRef);
+    mBufferRef.reset();
 }
 
 bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
@@ -764,7 +780,11 @@
         const std::shared_ptr<C2LinearBlock> &block,
         const sp<IMemory> &memory,
         int32_t heapSeqNum)
-    : Codec2Buffer(format, new ABuffer(memory->pointer(), memory->size())),
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
       mBlock(block),
       mMemory(memory),
       mHeapSeqNum(heapSeqNum) {
@@ -775,9 +795,8 @@
 }
 
 void EncryptedLinearBlockBuffer::fillSourceBuffer(
-        ICrypto::SourceBuffer *source) {
-    source->mSharedMemory = mMemory;
-    source->mHeapSeqNum = mHeapSeqNum;
+        hardware::drm::V1_0::SharedBuffer *source) {
+    BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
 }
 
 void EncryptedLinearBlockBuffer::fillSourceBuffer(
@@ -800,7 +819,7 @@
     if (view.size() < length) {
         return false;
     }
-    memcpy(view.data(), decrypted->pointer(), length);
+    memcpy(view.data(), decrypted->unsecurePointer(), length);
     return true;
 }
 
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 36dcab9..dc788cd 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -20,15 +20,29 @@
 
 #include <C2Buffer.h>
 
-#include <android/hardware/cas/native/1.0/types.h>
 #include <binder/IMemory.h>
 #include <media/hardware/VideoAPI.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/MediaCodecBuffer.h>
-#include <media/ICrypto.h>
 
 namespace android {
 
+namespace hardware {
+class HidlMemory;
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct SharedBuffer;
+}  // namespace V1_0
+}  // namespace native
+}  // namespace cas
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+
 /**
  * Copies a graphic view into a media image.
  *
@@ -56,38 +70,10 @@
     using MediaCodecBuffer::MediaCodecBuffer;
     ~Codec2Buffer() override = default;
 
-    /**
-     * \return  C2Buffer object represents this buffer.
-     */
-    virtual std::shared_ptr<C2Buffer> asC2Buffer() = 0;
-
-    /**
-     * Test if we can copy the content of |buffer| into this object.
-     *
-     * \param   buffer  C2Buffer object to copy.
-     * \return  true    if the content of buffer can be copied over to this buffer
-     *          false   otherwise.
-     */
-    virtual bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
-        (void)buffer;
-        return false;
-    }
-
-    /**
-     * Copy the content of |buffer| into this object. This method assumes that
-     * canCopy() check already passed.
-     *
-     * \param   buffer  C2Buffer object to copy.
-     * \return  true    if successful
-     *          false   otherwise.
-     */
-    virtual bool copy(const std::shared_ptr<C2Buffer> &buffer) {
-        (void)buffer;
-        return false;
-    }
-
     sp<ABuffer> getImageData() const { return mImageData; }
 
+    virtual void clearC2BufferRefs() {}
+
 protected:
     /**
      * canCopy() implementation for linear buffers.
@@ -131,6 +117,7 @@
             const std::shared_ptr<C2Buffer> &buffer = nullptr);
 
     std::shared_ptr<C2Buffer> asC2Buffer() override;
+    void clearC2BufferRefs() override;
     bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
     bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
 
@@ -190,6 +177,7 @@
     virtual ~ConstLinearBlockBuffer() = default;
 
     std::shared_ptr<C2Buffer> asC2Buffer() override;
+    void clearC2BufferRefs() override;
 
 private:
     ConstLinearBlockBuffer(
@@ -309,6 +297,7 @@
     virtual ~ConstGraphicBlockBuffer() = default;
 
     std::shared_ptr<C2Buffer> asC2Buffer() override;
+    void clearC2BufferRefs() override;
     bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
     bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
 
@@ -361,7 +350,8 @@
      *
      * \param source  source buffer structure to fill.
      */
-    void fillSourceBuffer(ICrypto::SourceBuffer *source);
+    void fillSourceBuffer(
+            hardware::drm::V1_0::SharedBuffer *source);
     void fillSourceBuffer(
             hardware::cas::native::V1_0::SharedBuffer *source);
 
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 6b75eba..b112249 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -43,13 +43,12 @@
 #include <codec2/hidl/client.h>
 #include <cutils/native_handle.h>
 #include <media/omx/1.0/WOmxNode.h>
-#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/foundation/ALookup.h>
 #include <media/stagefright/foundation/MediaDefs.h>
 #include <media/stagefright/omx/OMXUtils.h>
 #include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-
-#include "Codec2InfoBuilder.h"
+#include <media/stagefright/Codec2InfoBuilder.h>
+#include <media/stagefright/MediaCodecConstants.h>
 
 namespace android {
 
@@ -117,8 +116,9 @@
         }
     }
 
-    // For VP9, the static info is always propagated by framework.
+    // For VP9/AV1, the static info is always propagated by framework.
     supportsHdr |= (mediaType == MIMETYPE_VIDEO_VP9);
+    supportsHdr |= (mediaType == MIMETYPE_VIDEO_AV1);
 
     for (C2Value::Primitive profile : profileQuery[0].values.values) {
         pl.profile = (C2Config::profile_t)profile.ref<uint32_t>();
@@ -319,10 +319,11 @@
     // Obtain Codec2Client
     std::vector<Traits> traits = Codec2Client::ListComponents();
 
-    // parse APEX XML first, followed by vendor XML
+    // parse APEX XML first, followed by vendor XML.
+    // Note: APEX XML names do not depend on ro.media.xml_variant.* properties.
     MediaCodecsXmlParser parser;
     parser.parseXmlFilesInSearchDirs(
-            parser.getDefaultXmlNames(),
+            { "media_codecs.xml", "media_codecs_performance.xml" },
             { "/apex/com.android.media.swcodec/etc" });
 
     // TODO: remove these c2-specific files once product moved to default file names
diff --git a/media/codec2/sfplugin/ReflectedParamUpdater.cpp b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
index 55b0ec9..f39051b 100644
--- a/media/codec2/sfplugin/ReflectedParamUpdater.cpp
+++ b/media/codec2/sfplugin/ReflectedParamUpdater.cpp
@@ -125,18 +125,6 @@
         }
         addParamDesc(desc, *structDesc, reflector, true /* markVendor */);
     }
-
-    // TEMP: also add vendor parameters as non-vendor
-    for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) {
-        if (!desc->index().isVendor()) {
-            continue;
-        }
-        std::unique_ptr<C2StructDescriptor> structDesc = reflector->describe(
-                desc->index().coreIndex());
-        if (structDesc) {
-            addParamDesc(desc, *structDesc, reflector, false /* markVendor */);
-        }
-    }
 }
 
 void ReflectedParamUpdater::addParamStructDesc(
@@ -286,6 +274,20 @@
     }
 }
 
+void ReflectedParamUpdater::getKeysForParamIndex(
+        const C2Param::Index &index,
+        std::vector<std::string> *keys /* nonnull */) const {
+    CHECK(keys != nullptr);
+    keys->clear();
+    for (const std::pair<const std::string, FieldDesc> &kv : mMap) {
+        const std::string &name = kv.first;
+        const FieldDesc &desc = kv.second;
+        if (desc.paramDesc->index() == index) {
+            keys->push_back(name);
+        }
+    }
+}
+
 void ReflectedParamUpdater::updateParamsFromMessage(
         const Dict &params,
         std::vector<std::unique_ptr<C2Param>> *vec /* nonnull */) const {
diff --git a/media/codec2/sfplugin/ReflectedParamUpdater.h b/media/codec2/sfplugin/ReflectedParamUpdater.h
index 5436ba5..752c7e4 100644
--- a/media/codec2/sfplugin/ReflectedParamUpdater.h
+++ b/media/codec2/sfplugin/ReflectedParamUpdater.h
@@ -166,6 +166,16 @@
             std::vector<C2Param::Index> *vec /* nonnull */) const;
 
     /**
+     * Get list of field names for the given param index.
+     *
+     * \param index[in]   param index
+     * \param keys[out]   vector to store the field names
+     */
+    void getKeysForParamIndex(
+            const C2Param::Index &index,
+            std::vector<std::string> *keys /* nonnull */) const;
+
+    /**
      * Update C2Param objects from field name and value in AMessage object.
      *
      * \param params[in]    Dict object with field name to value pairs.
diff --git a/media/codec2/sfplugin/SkipCutBuffer.cpp b/media/codec2/sfplugin/SkipCutBuffer.cpp
deleted file mode 100644
index 8d1de65..0000000
--- a/media/codec2/sfplugin/SkipCutBuffer.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2012 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 "SkipCutBuffer"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBuffer.h>
-#include "SkipCutBuffer.h"
-
-namespace android {
-
-SkipCutBuffer::SkipCutBuffer(size_t skip, size_t cut, size_t num16BitChannels) {
-
-    mWriteHead = 0;
-    mReadHead = 0;
-    mCapacity = 0;
-    mCutBuffer = nullptr;
-
-    if (num16BitChannels == 0 || num16BitChannels > INT32_MAX / 2) {
-        ALOGW("# channels out of range: %zu, using passthrough instead", num16BitChannels);
-        return;
-    }
-    size_t frameSize = num16BitChannels * 2;
-    if (skip > INT32_MAX / frameSize || cut > INT32_MAX / frameSize
-            || cut * frameSize > INT32_MAX - 4096) {
-        ALOGW("out of range skip/cut: %zu/%zu, using passthrough instead",
-                skip, cut);
-        return;
-    }
-    skip *= frameSize;
-    cut *= frameSize;
-
-    mFrontPadding = mSkip = skip;
-    mBackPadding = cut;
-    mCapacity = cut + 4096;
-    mCutBuffer = new (std::nothrow) char[mCapacity];
-    ALOGV("skipcutbuffer %zu %zu %d", skip, cut, mCapacity);
-}
-
-SkipCutBuffer::~SkipCutBuffer() {
-    delete[] mCutBuffer;
-}
-
-void SkipCutBuffer::submit(MediaBuffer *buffer) {
-    if (mCutBuffer == nullptr) {
-        // passthrough mode
-        return;
-    }
-
-    int32_t offset = buffer->range_offset();
-    int32_t buflen = buffer->range_length();
-
-    // drop the initial data from the buffer if needed
-    if (mFrontPadding > 0) {
-        // still data left to drop
-        int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
-        offset += to_drop;
-        buflen -= to_drop;
-        buffer->set_range(offset, buflen);
-        mFrontPadding -= to_drop;
-    }
-
-
-    // append data to cutbuffer
-    char *src = ((char*) buffer->data()) + offset;
-    write(src, buflen);
-
-
-    // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
-    // at least mBackPadding bytes in the cutbuffer
-    char *dst = (char*) buffer->data();
-    size_t copied = read(dst, buffer->size());
-    buffer->set_range(0, copied);
-}
-
-template <typename T>
-void SkipCutBuffer::submitInternal(const sp<T>& buffer) {
-    if (mCutBuffer == nullptr) {
-        // passthrough mode
-        return;
-    }
-
-    int32_t offset = buffer->offset();
-    int32_t buflen = buffer->size();
-
-    // drop the initial data from the buffer if needed
-    if (mFrontPadding > 0) {
-        // still data left to drop
-        int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
-        offset += to_drop;
-        buflen -= to_drop;
-        buffer->setRange(offset, buflen);
-        mFrontPadding -= to_drop;
-    }
-
-
-    // append data to cutbuffer
-    char *src = (char*) buffer->data();
-    write(src, buflen);
-
-
-    // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
-    // at least mBackPadding bytes in the cutbuffer
-    char *dst = (char*) buffer->base();
-    size_t copied = read(dst, buffer->capacity());
-    buffer->setRange(0, copied);
-}
-
-void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
-    submitInternal(buffer);
-}
-
-void SkipCutBuffer::submit(const sp<MediaCodecBuffer>& buffer) {
-    submitInternal(buffer);
-}
-
-void SkipCutBuffer::clear() {
-    mWriteHead = mReadHead = 0;
-    mFrontPadding = mSkip;
-}
-
-void SkipCutBuffer::write(const char *src, size_t num) {
-    int32_t sizeused = (mWriteHead - mReadHead);
-    if (sizeused < 0) sizeused += mCapacity;
-
-    // Everything must fit. Make sure the buffer is a little larger than needed,
-    // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer
-    // full or empty
-    size_t available = mCapacity - sizeused - 32;
-    if (available < num) {
-        int32_t newcapacity = mCapacity + (num - available);
-        char * newbuffer = new char[newcapacity];
-        memcpy(newbuffer, mCutBuffer, mCapacity);
-        delete [] mCutBuffer;
-        mCapacity = newcapacity;
-        mCutBuffer = newbuffer;
-        ALOGV("reallocated buffer at size %d", newcapacity);
-    }
-
-    size_t copyfirst = (mCapacity - mWriteHead);
-    if (copyfirst > num) copyfirst = num;
-    if (copyfirst) {
-        memcpy(mCutBuffer + mWriteHead, src, copyfirst);
-        num -= copyfirst;
-        src += copyfirst;
-        mWriteHead += copyfirst;
-        CHECK_LE(mWriteHead, mCapacity);
-        if (mWriteHead == mCapacity) mWriteHead = 0;
-        if (num) {
-            memcpy(mCutBuffer, src, num);
-            mWriteHead += num;
-        }
-    }
-}
-
-size_t SkipCutBuffer::read(char *dst, size_t num) {
-    int32_t available = (mWriteHead - mReadHead);
-    if (available < 0) available += mCapacity;
-
-    available -= mBackPadding;
-    if (available <=0) {
-        return 0;
-    }
-    if (available < int32_t(num)) {
-        num = available;
-    }
-
-    size_t copyfirst = (mCapacity - mReadHead);
-    if (copyfirst > num) copyfirst = num;
-    if (copyfirst) {
-        memcpy(dst, mCutBuffer + mReadHead, copyfirst);
-        num -= copyfirst;
-        dst += copyfirst;
-        mReadHead += copyfirst;
-        CHECK_LE(mReadHead, mCapacity);
-        if (mReadHead == mCapacity) mReadHead = 0;
-        if (num) {
-            memcpy(dst, mCutBuffer, num);
-            mReadHead += num;
-        }
-    }
-    return available;
-}
-
-size_t SkipCutBuffer::size() {
-    int32_t available = (mWriteHead - mReadHead);
-    if (available < 0) available += mCapacity;
-    return available;
-}
-
-}  // namespace android
diff --git a/media/codec2/sfplugin/SkipCutBuffer.h b/media/codec2/sfplugin/SkipCutBuffer.h
deleted file mode 100644
index 0fb5690..0000000
--- a/media/codec2/sfplugin/SkipCutBuffer.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 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 SKIP_CUT_BUFFER_H_
-
-#define SKIP_CUT_BUFFER_H_
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/foundation/ABuffer.h>
-
-namespace android {
-
-/**
- * utility class to cut the start and end off a stream of data in MediaBuffers
- *
- */
-class SkipCutBuffer: public RefBase {
- public:
-    // 'skip' is the number of frames to skip from the beginning
-    // 'cut' is the number of frames to cut from the end
-    // 'num16BitChannels' is the number of channels, which are assumed to be 16 bit wide each
-    SkipCutBuffer(size_t skip, size_t cut, size_t num16Channels);
-
-    // Submit one MediaBuffer for skipping and cutting. This may consume all or
-    // some of the data in the buffer, or it may add data to it.
-    // After this, the caller should continue processing the buffer as usual.
-    void submit(MediaBuffer *buffer);
-    void submit(const sp<ABuffer>& buffer);    // same as above, but with an ABuffer
-    void submit(const sp<MediaCodecBuffer>& buffer);    // same as above, but with an ABuffer
-    void clear();
-    size_t size(); // how many bytes are currently stored in the buffer
-
- protected:
-    virtual ~SkipCutBuffer();
-
- private:
-    void write(const char *src, size_t num);
-    size_t read(char *dst, size_t num);
-    template <typename T>
-    void submitInternal(const sp<T>& buffer);
-    int32_t mSkip;
-    int32_t mFrontPadding;
-    int32_t mBackPadding;
-    int32_t mWriteHead;
-    int32_t mReadHead;
-    int32_t mCapacity;
-    char* mCutBuffer;
-    DISALLOW_EVIL_CONSTRUCTORS(SkipCutBuffer);
-};
-
-}  // namespace android
-
-#endif  // OMX_CODEC_H_
diff --git a/media/codec2/sfplugin/include/media/stagefright/CCodec.h b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
new file mode 100644
index 0000000..ecb2506
--- /dev/null
+++ b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 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 C_CODEC_H_
+#define C_CODEC_H_
+
+#include <atomic>
+#include <chrono>
+#include <list>
+#include <memory>
+#include <set>
+
+#include <C2Component.h>
+#include <codec2/hidl/client.h>
+
+#include <android/native_window.h>
+#include <media/hardware/MetadataBufferType.h>
+#include <media/stagefright/foundation/Mutexed.h>
+#include <media/stagefright/CodecBase.h>
+#include <media/stagefright/FrameRenderTracker.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/SkipCutBuffer.h>
+#include <utils/NativeHandle.h>
+#include <hardware/gralloc.h>
+#include <nativebase/nativebase.h>
+
+namespace android {
+
+class CCodecBufferChannel;
+class InputSurfaceWrapper;
+struct CCodecConfig;
+struct MediaCodecInfo;
+
+class CCodec : public CodecBase {
+public:
+    CCodec();
+
+    virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
+    virtual void initiateAllocateComponent(const sp<AMessage> &msg) override;
+    virtual void initiateConfigureComponent(const sp<AMessage> &msg) override;
+    virtual void initiateCreateInputSurface() override;
+    virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface) override;
+    virtual void initiateStart() override;
+    virtual void initiateShutdown(bool keepComponentAllocated = false) override;
+
+    virtual status_t setSurface(const sp<Surface> &surface) override;
+
+    virtual void signalFlush() override;
+    virtual void signalResume() override;
+
+    virtual void signalSetParameters(const sp<AMessage> &params) override;
+    virtual void signalEndOfInputStream() override;
+    virtual void signalRequestIDRFrame() override;
+
+    void initiateReleaseIfStuck();
+    void onWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
+    void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex);
+
+    static PersistentSurface *CreateInputSurface();
+
+    static status_t CanFetchLinearBlock(
+            const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible);
+
+    static std::shared_ptr<C2LinearBlock> FetchLinearBlock(
+            size_t capacity, const C2MemoryUsage &usage, const std::vector<std::string> &names);
+
+    static status_t CanFetchGraphicBlock(
+            const std::vector<std::string> &names, bool *isCompatible);
+
+    static std::shared_ptr<C2GraphicBlock> FetchGraphicBlock(
+            int32_t width,
+            int32_t height,
+            int32_t format,
+            uint64_t usage,
+            const std::vector<std::string> &names);
+
+protected:
+    virtual ~CCodec();
+
+    virtual void onMessageReceived(const sp<AMessage> &msg) override;
+
+private:
+    typedef std::chrono::steady_clock::time_point TimePoint;
+
+    status_t tryAndReportOnError(std::function<status_t()> job);
+
+    void initiateStop();
+    void initiateRelease(bool sendCallback = true);
+
+    void allocate(const sp<MediaCodecInfo> &codecInfo);
+    void configure(const sp<AMessage> &msg);
+    void start();
+    void stop();
+    void flush();
+    void release(bool sendCallback);
+
+    /**
+     * Creates an input surface for the current device configuration compatible with CCodec.
+     * This could be backed by the C2 HAL or the OMX HAL.
+     */
+    static sp<PersistentSurface> CreateCompatibleInputSurface();
+
+    /// Creates an input surface to the OMX HAL
+    static sp<PersistentSurface> CreateOmxInputSurface();
+
+    /// handle a create input surface call
+    void createInputSurface();
+    void setInputSurface(const sp<PersistentSurface> &surface);
+    status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
+
+    void setDeadline(
+            const TimePoint &now,
+            const std::chrono::milliseconds &timeout,
+            const char *name);
+
+    enum {
+        kWhatAllocate,
+        kWhatConfigure,
+        kWhatStart,
+        kWhatFlush,
+        kWhatStop,
+        kWhatRelease,
+        kWhatCreateInputSurface,
+        kWhatSetInputSurface,
+        kWhatSetParameters,
+
+        kWhatWorkDone,
+        kWhatWatch,
+    };
+
+    enum {
+        RELEASED,
+        ALLOCATED,
+        FLUSHED,
+        RUNNING,
+
+        ALLOCATING,  // RELEASED -> ALLOCATED
+        STARTING,    // ALLOCATED -> RUNNING
+        STOPPING,    // RUNNING -> ALLOCATED
+        FLUSHING,    // RUNNING -> FLUSHED
+        RESUMING,    // FLUSHED -> RUNNING
+        RELEASING,   // {ANY EXCEPT RELEASED} -> RELEASED
+    };
+
+    struct State {
+        inline State() : mState(RELEASED) {}
+        inline int get() const { return mState; }
+        inline void set(int newState) { mState = newState; }
+
+        std::shared_ptr<Codec2Client::Component> comp;
+    private:
+        int mState;
+    };
+
+    struct NamedTimePoint {
+        NamedTimePoint() : mTimePoint(TimePoint::max()), mName("") {}
+
+        inline void set(
+                const TimePoint &timePoint,
+                const char *name) {
+            mTimePoint = timePoint;
+            mName = name;
+        }
+
+        inline TimePoint get() const { return mTimePoint; }
+        inline const char *getName() const { return mName; }
+    private:
+        TimePoint mTimePoint;
+        const char *mName;
+    };
+
+    Mutexed<State> mState;
+    std::shared_ptr<CCodecBufferChannel> mChannel;
+
+    std::shared_ptr<Codec2Client> mClient;
+    std::shared_ptr<Codec2Client::Listener> mClientListener;
+    struct ClientListener;
+
+    Mutexed<NamedTimePoint> mDeadline;
+
+    Mutexed<std::unique_ptr<CCodecConfig>> mConfig;
+    Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
+    std::atomic_flag mSentConfigAfterResume;
+
+    friend class CCodecCallbackImpl;
+
+    DISALLOW_EVIL_CONSTRUCTORS(CCodec);
+};
+
+}  // namespace android
+
+#endif  // C_CODEC_H_
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.h b/media/codec2/sfplugin/include/media/stagefright/Codec2InfoBuilder.h
similarity index 100%
rename from media/codec2/sfplugin/Codec2InfoBuilder.h
rename to media/codec2/sfplugin/include/media/stagefright/Codec2InfoBuilder.h
diff --git a/media/codec2/sfplugin/tests/Android.bp b/media/codec2/sfplugin/tests/Android.bp
index be7f55c..8d1a9c3 100644
--- a/media/codec2/sfplugin/tests/Android.bp
+++ b/media/codec2/sfplugin/tests/Android.bp
@@ -2,20 +2,39 @@
     name: "ccodec_unit_test",
 
     srcs: [
+        "CCodecBuffers_test.cpp",
+        "CCodecConfig_test.cpp",
         "ReflectedParamUpdater_test.cpp",
     ],
 
+    defaults: [
+        "libcodec2-impl-defaults",
+        "libcodec2-internal-defaults",
+    ],
+
     include_dirs: [
         "frameworks/av/media/codec2/sfplugin",
     ],
 
     shared_libs: [
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
         "libcodec2",
+        "libcodec2_client",
+        "libhidlbase",
+        "libfmq",
+        "libmedia_omx",
         "libsfplugin_ccodec",
+        "libsfplugin_ccodec_utils",
         "libstagefright_foundation",
         "libutils",
     ],
 
+    static_libs: [
+        "libcodec2_hidl@1.0",
+        "libstagefright_bufferpool@2.0",
+    ],
+
     cflags: [
         "-Werror",
         "-Wall",
@@ -33,6 +52,11 @@
         "frameworks/av/media/codec2/sfplugin",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+        "libmediametrics_headers",
+    ],
+
     shared_libs: [
         "libbinder",
         "libcodec2",
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
new file mode 100644
index 0000000..5bee605
--- /dev/null
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CCodecBuffers.h"
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/MediaCodecConstants.h>
+
+#include <C2PlatformSupport.h>
+
+namespace android {
+
+TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
+    constexpr int32_t kWidth = 3840;
+    constexpr int32_t kHeight = 2160;
+
+    std::shared_ptr<RawGraphicOutputBuffers> buffers =
+        std::make_shared<RawGraphicOutputBuffers>("test");
+    sp<AMessage> format{new AMessage};
+    format->setInt32("width", kWidth);
+    format->setInt32("height", kHeight);
+    buffers->setFormat(format);
+
+    std::shared_ptr<C2BlockPool> pool;
+    ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
+
+    // Register 4 buffers
+    std::vector<sp<MediaCodecBuffer>> clientBuffers;
+    auto registerBuffer = [&buffers, &clientBuffers, &pool] {
+        std::shared_ptr<C2GraphicBlock> block;
+        ASSERT_EQ(OK, pool->fetchGraphicBlock(
+                kWidth, kHeight, HAL_PIXEL_FORMAT_YCbCr_420_888,
+                C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
+        std::shared_ptr<C2Buffer> c2Buffer = C2Buffer::CreateGraphicBuffer(block->share(
+                block->crop(), C2Fence{}));
+        size_t index;
+        sp<MediaCodecBuffer> clientBuffer;
+        ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
+        ASSERT_NE(nullptr, clientBuffer);
+        while (clientBuffers.size() <= index) {
+            clientBuffers.emplace_back();
+        }
+        ASSERT_EQ(nullptr, clientBuffers[index]) << "index = " << index;
+        clientBuffers[index] = clientBuffer;
+    };
+    for (int i = 0; i < 4; ++i) {
+        registerBuffer();
+    }
+
+    // Release 2 buffers
+    auto releaseBuffer = [&buffers, &clientBuffers, kWidth, kHeight](int index) {
+        std::shared_ptr<C2Buffer> c2Buffer;
+        ASSERT_TRUE(buffers->releaseBuffer(clientBuffers[index], &c2Buffer))
+                << "index = " << index;
+        clientBuffers[index] = nullptr;
+        // Sanity checks
+        ASSERT_TRUE(c2Buffer->data().linearBlocks().empty());
+        ASSERT_EQ(1u, c2Buffer->data().graphicBlocks().size());
+        C2ConstGraphicBlock block = c2Buffer->data().graphicBlocks().front();
+        ASSERT_EQ(kWidth, block.width());
+        ASSERT_EQ(kHeight, block.height());
+    };
+    for (int i = 0, index = 0; i < 2 && index < clientBuffers.size(); ++index) {
+        if (clientBuffers[index] == nullptr) {
+            continue;
+        }
+        releaseBuffer(index);
+        ++i;
+    }
+
+    // Simulate # of slots 4->16
+    for (int i = 2; i < 16; ++i) {
+        registerBuffer();
+    }
+
+    // Release everything
+    for (int index = 0; index < clientBuffers.size(); ++index) {
+        if (clientBuffers[index] == nullptr) {
+            continue;
+        }
+        releaseBuffer(index);
+    }
+}
+
+} // namespace android
diff --git a/media/codec2/sfplugin/tests/CCodecConfig_test.cpp b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp
new file mode 100644
index 0000000..c9caa01
--- /dev/null
+++ b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp
@@ -0,0 +1,460 @@
+/*
+ * Copyright 2019 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 "CCodecConfig.h"
+
+#include <set>
+
+#include <gtest/gtest.h>
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/client.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <media/stagefright/MediaCodecConstants.h>
+
+namespace {
+
+enum ExtendedC2ParamIndexKind : C2Param::type_index_t {
+    kParamIndexVendorInt32 = C2Param::TYPE_INDEX_VENDOR_START,
+    kParamIndexVendorInt64,
+    kParamIndexVendorString,
+};
+
+typedef C2PortParam<C2Info, C2Int32Value, kParamIndexVendorInt32> C2PortVendorInt32Info;
+constexpr char C2_PARAMKEY_VENDOR_INT32[] = "example.int32";
+constexpr char KEY_VENDOR_INT32[] = "vendor.example.int32.value";
+
+typedef C2StreamParam<C2Info, C2Int64Value, kParamIndexVendorInt64> C2StreamVendorInt64Info;
+constexpr char C2_PARAMKEY_VENDOR_INT64[] = "example.int64";
+constexpr char KEY_VENDOR_INT64[] = "vendor.example.int64.value";
+
+typedef C2PortParam<C2Info, C2StringValue, kParamIndexVendorString> C2PortVendorStringInfo;
+constexpr char C2_PARAMKEY_VENDOR_STRING[] = "example.string";
+constexpr char KEY_VENDOR_STRING[] = "vendor.example.string.value";
+
+}  // namespace
+
+namespace android {
+
+class CCodecConfigTest : public ::testing::Test {
+public:
+    constexpr static int32_t kCodec2Int32 = 0xC0DEC2;
+    constexpr static int64_t kCodec2Int64 = 0xC0DEC2C0DEC2ll;
+    constexpr static char kCodec2Str[] = "codec2";
+
+    CCodecConfigTest()
+        : mReflector{std::make_shared<C2ReflectorHelper>()} {
+    }
+
+    void init(
+            C2Component::domain_t domain,
+            C2Component::kind_t kind,
+            const char *mediaType) {
+        sp<hardware::media::c2::V1_0::utils::CachedConfigurable> cachedConfigurable =
+            new hardware::media::c2::V1_0::utils::CachedConfigurable(
+                    std::make_unique<Configurable>(mReflector, domain, kind, mediaType));
+        cachedConfigurable->init(std::make_shared<Cache>());
+        mConfigurable = std::make_shared<Codec2Client::Configurable>(cachedConfigurable);
+    }
+
+    struct Cache : public hardware::media::c2::V1_0::utils::ParameterCache {
+        c2_status_t validate(const std::vector<std::shared_ptr<C2ParamDescriptor>>&) override {
+            return C2_OK;
+        }
+    };
+
+    class Configurable : public hardware::media::c2::V1_0::utils::ConfigurableC2Intf {
+    public:
+        Configurable(
+                const std::shared_ptr<C2ReflectorHelper> &reflector,
+                C2Component::domain_t domain,
+                C2Component::kind_t kind,
+                const char *mediaType)
+            : ConfigurableC2Intf("name", 0u),
+              mImpl(reflector, domain, kind, mediaType) {
+        }
+
+        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 mImpl.query({}, indices, mayBlock, params);
+        }
+
+        c2_status_t config(
+                const std::vector<C2Param*> &params,
+                c2_blocking_t mayBlock,
+                std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
+            return mImpl.config(params, mayBlock, failures);
+        }
+
+        c2_status_t querySupportedParams(
+                std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
+            return mImpl.querySupportedParams(params);
+        }
+
+        c2_status_t querySupportedValues(
+                std::vector<C2FieldSupportedValuesQuery>& fields,
+                c2_blocking_t mayBlock) const override {
+            return mImpl.querySupportedValues(fields, mayBlock);
+        }
+
+    private:
+        class Impl : public C2InterfaceHelper {
+        public:
+            Impl(const std::shared_ptr<C2ReflectorHelper> &reflector,
+                    C2Component::domain_t domain,
+                    C2Component::kind_t kind,
+                    const char *mediaType)
+                : C2InterfaceHelper{reflector} {
+
+                setDerivedInstance(this);
+
+                addParameter(
+                        DefineParam(mDomain, C2_PARAMKEY_COMPONENT_DOMAIN)
+                        .withConstValue(new C2ComponentDomainSetting(domain))
+                        .build());
+
+                addParameter(
+                        DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND)
+                        .withConstValue(new C2ComponentKindSetting(kind))
+                        .build());
+
+                addParameter(
+                        DefineParam(mInputStreamCount, C2_PARAMKEY_INPUT_STREAM_COUNT)
+                        .withConstValue(new C2PortStreamCountTuning::input(1))
+                        .build());
+
+                addParameter(
+                        DefineParam(mOutputStreamCount, C2_PARAMKEY_OUTPUT_STREAM_COUNT)
+                        .withConstValue(new C2PortStreamCountTuning::output(1))
+                        .build());
+
+                const char *rawMediaType = "";
+                switch (domain) {
+                    case C2Component::DOMAIN_IMAGE: [[fallthrough]];
+                    case C2Component::DOMAIN_VIDEO:
+                        rawMediaType = MIMETYPE_VIDEO_RAW;
+                        break;
+                    case C2Component::DOMAIN_AUDIO:
+                        rawMediaType = MIMETYPE_AUDIO_RAW;
+                        break;
+                    default:
+                        break;
+                }
+                bool isEncoder = kind == C2Component::KIND_ENCODER;
+                std::string inputMediaType{isEncoder ? rawMediaType : mediaType};
+                std::string outputMediaType{isEncoder ? mediaType : rawMediaType};
+
+                auto allocSharedString = [](const auto &param, const std::string &str) {
+                    typedef typename std::remove_reference<decltype(param)>::type::element_type T;
+                    std::shared_ptr<T> ret = T::AllocShared(str.length() + 1);
+                    strcpy(ret->m.value, str.c_str());
+                    return ret;
+                };
+
+                addParameter(
+                        DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
+                        .withConstValue(allocSharedString(mInputMediaType, inputMediaType))
+                        .build());
+
+                addParameter(
+                        DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
+                        .withConstValue(allocSharedString(mOutputMediaType, outputMediaType))
+                        .build());
+
+                addParameter(
+                        DefineParam(mInt32Input, C2_PARAMKEY_VENDOR_INT32)
+                        .withDefault(new C2PortVendorInt32Info::input(0))
+                        .withFields({C2F(mInt32Input, value).any()})
+                        .withSetter(Setter<decltype(mInt32Input)::element_type>)
+                        .build());
+
+                addParameter(
+                        DefineParam(mInt64Output, C2_PARAMKEY_VENDOR_INT64)
+                        .withDefault(new C2StreamVendorInt64Info::output(0u, 0))
+                        .withFields({C2F(mInt64Output, value).any()})
+                        .withSetter(Setter<decltype(mInt64Output)::element_type>)
+                        .build());
+
+                addParameter(
+                        DefineParam(mStringInput, C2_PARAMKEY_VENDOR_STRING)
+                        .withDefault(decltype(mStringInput)::element_type::AllocShared(1, ""))
+                        .withFields({C2F(mStringInput, m.value).any()})
+                        .withSetter(Setter<decltype(mStringInput)::element_type>)
+                        .build());
+
+                addParameter(
+                        DefineParam(mPixelAspectRatio, C2_PARAMKEY_PIXEL_ASPECT_RATIO)
+                        .withDefault(new C2StreamPixelAspectRatioInfo::output(0u, 1, 1))
+                        .withFields({
+                            C2F(mPixelAspectRatio, width).any(),
+                            C2F(mPixelAspectRatio, height).any(),
+                        })
+                        .withSetter(Setter<C2StreamPixelAspectRatioInfo::output>)
+                        .build());
+
+                // TODO: more SDK params
+            }
+        private:
+            std::shared_ptr<C2ComponentDomainSetting> mDomain;
+            std::shared_ptr<C2ComponentKindSetting> mKind;
+            std::shared_ptr<C2PortStreamCountTuning::input> mInputStreamCount;
+            std::shared_ptr<C2PortStreamCountTuning::output> mOutputStreamCount;
+            std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
+            std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
+            std::shared_ptr<C2PortVendorInt32Info::input> mInt32Input;
+            std::shared_ptr<C2StreamVendorInt64Info::output> mInt64Output;
+            std::shared_ptr<C2PortVendorStringInfo::input> mStringInput;
+            std::shared_ptr<C2StreamPixelAspectRatioInfo::output> mPixelAspectRatio;
+
+            template<typename T>
+            static C2R Setter(bool, C2P<T> &) {
+                return C2R::Ok();
+            }
+        };
+
+        Impl mImpl;
+    };
+
+    std::shared_ptr<C2ReflectorHelper> mReflector;
+    std::shared_ptr<Codec2Client::Configurable> mConfigurable;
+    CCodecConfig mConfig;
+};
+
+using D = CCodecConfig::Domain;
+
+template<typename T>
+T *FindParam(const std::vector<std::unique_ptr<C2Param>> &vec) {
+    for (const std::unique_ptr<C2Param> &param : vec) {
+        if (param->coreIndex() == T::CORE_INDEX) {
+            return static_cast<T *>(param.get());
+        }
+    }
+    return nullptr;
+}
+
+TEST_F(CCodecConfigTest, SetVendorParam) {
+    // Test at audio domain, as video domain has a few local parameters that
+    // interfere with the testing.
+    init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    sp<AMessage> format{new AMessage};
+    format->setInt32(KEY_VENDOR_INT32, kCodec2Int32);
+    format->setInt64(KEY_VENDOR_INT64, kCodec2Int64);
+    format->setString(KEY_VENDOR_STRING, kCodec2Str);
+
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
+            mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
+
+    ASSERT_EQ(3u, configUpdate.size());
+    C2PortVendorInt32Info::input *i32 =
+        FindParam<std::remove_pointer<decltype(i32)>::type>(configUpdate);
+    ASSERT_NE(nullptr, i32);
+    ASSERT_EQ(kCodec2Int32, i32->value);
+
+    C2StreamVendorInt64Info::output *i64 =
+        FindParam<std::remove_pointer<decltype(i64)>::type>(configUpdate);
+    ASSERT_NE(nullptr, i64);
+    ASSERT_EQ(kCodec2Int64, i64->value);
+
+    C2PortVendorStringInfo::input *str =
+        FindParam<std::remove_pointer<decltype(str)>::type>(configUpdate);
+    ASSERT_NE(nullptr, str);
+    ASSERT_STREQ(kCodec2Str, str->m.value);
+}
+
+TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) {
+    // Test at audio domain, as video domain has a few local parameters that
+    // interfere with the testing.
+    init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    C2PortVendorInt32Info::input i32(kCodec2Int32);
+    C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
+    std::unique_ptr<C2PortVendorStringInfo::input> str =
+        C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
+    configUpdate.push_back(C2Param::Copy(i32));
+    configUpdate.push_back(C2Param::Copy(i64));
+    configUpdate.push_back(std::move(str));
+
+    // The vendor parameters are not yet subscribed
+    ASSERT_FALSE(mConfig.updateConfiguration(configUpdate, D::ALL));
+
+    int32_t vendorInt32{0};
+    ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+    int64_t vendorInt64{0};
+    ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+    AString vendorString;
+    ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+}
+
+TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) {
+    // Test at audio domain, as video domain has a few local parameters that
+    // interfere with the testing.
+    init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    // Force subscribe to all vendor params
+    ASSERT_EQ(OK, mConfig.subscribeToAllVendorParams(mConfigurable, C2_MAY_BLOCK));
+
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    C2PortVendorInt32Info::input i32(kCodec2Int32);
+    C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
+    std::unique_ptr<C2PortVendorStringInfo::input> str =
+        C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
+    configUpdate.push_back(C2Param::Copy(i32));
+    configUpdate.push_back(C2Param::Copy(i64));
+    configUpdate.push_back(std::move(str));
+
+    ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
+
+    int32_t vendorInt32{0};
+    ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_EQ(kCodec2Int32, vendorInt32);
+    ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+    int64_t vendorInt64{0};
+    ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_TRUE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+    ASSERT_EQ(kCodec2Int64, vendorInt64);
+
+    AString vendorString;
+    ASSERT_TRUE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_STREQ(kCodec2Str, vendorString.c_str());
+    ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+}
+
+TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) {
+    // Test at audio domain, as video domain has a few local parameters that
+    // interfere with the testing.
+    init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    // Subscribe to example.int32 only
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    sp<AMessage> format{new AMessage};
+    format->setInt32(KEY_VENDOR_INT32, 0);
+    configUpdate.clear();
+    ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
+            mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
+    ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK));
+
+    C2PortVendorInt32Info::input i32(kCodec2Int32);
+    C2StreamVendorInt64Info::output i64(0u, kCodec2Int64);
+    std::unique_ptr<C2PortVendorStringInfo::input> str =
+        C2PortVendorStringInfo::input::AllocUnique(strlen(kCodec2Str) + 1, kCodec2Str);
+    configUpdate.clear();
+    configUpdate.push_back(C2Param::Copy(i32));
+    configUpdate.push_back(C2Param::Copy(i64));
+    configUpdate.push_back(std::move(str));
+
+    // Only example.i32 should be updated
+    ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
+
+    int32_t vendorInt32{0};
+    ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_EQ(kCodec2Int32, vendorInt32);
+    ASSERT_FALSE(mConfig.mOutputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+    int64_t vendorInt64{0};
+    ASSERT_FALSE(mConfig.mInputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_FALSE(mConfig.mOutputFormat->findInt64(KEY_VENDOR_INT64, &vendorInt64))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+
+    AString vendorString;
+    ASSERT_FALSE(mConfig.mInputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+    ASSERT_FALSE(mConfig.mOutputFormat->findString(KEY_VENDOR_STRING, &vendorString))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+}
+
+TEST_F(CCodecConfigTest, SetPixelAspectRatio) {
+    init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    sp<AMessage> format{new AMessage};
+    format->setInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, 12);
+    format->setInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, 11);
+
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams(
+            mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate));
+
+    ASSERT_EQ(1u, configUpdate.size());
+    C2StreamPixelAspectRatioInfo::output *par =
+        FindParam<std::remove_pointer<decltype(par)>::type>(configUpdate);
+    ASSERT_NE(nullptr, par);
+    ASSERT_EQ(12, par->width);
+    ASSERT_EQ(11, par->height);
+}
+
+TEST_F(CCodecConfigTest, PixelAspectRatioUpdate) {
+    init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC);
+
+    ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable));
+
+    std::vector<std::unique_ptr<C2Param>> configUpdate;
+    C2StreamPixelAspectRatioInfo::output par(0u, 12, 11);
+    configUpdate.push_back(C2Param::Copy(par));
+
+    ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL));
+
+    int32_t parWidth{0};
+    ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+    ASSERT_EQ(12, parWidth);
+    ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+
+    int32_t parHeight{0};
+    ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
+            << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str();
+    ASSERT_EQ(11, parHeight);
+    ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight))
+            << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str();
+}
+
+} // namespace android
diff --git a/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp b/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
index ba3687b..6deede0 100644
--- a/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
+++ b/media/codec2/sfplugin/tests/MediaCodec_sanity_test.cpp
@@ -21,7 +21,7 @@
 #include <binder/ProcessState.h>
 #include <gtest/gtest.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/hardware/VideoAPI.h>
 #include <media/stagefright/MediaCodec.h>
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 8c8f025..6287221 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -1,6 +1,8 @@
 cc_library_shared {
     name: "libsfplugin_ccodec_utils",
     vendor_available: true,
+    min_sdk_version: "29",
+    double_loadable: true,
 
     srcs: [
         "Codec2BufferUtils.cpp",
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 40160c7..903db6c 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -190,6 +190,7 @@
     { C2Config::PROFILE_DV_HE_07, DolbyVisionProfileDvheDtb },
     { C2Config::PROFILE_DV_HE_08, DolbyVisionProfileDvheSt },
     { C2Config::PROFILE_DV_AV_09, DolbyVisionProfileDvavSe },
+    { C2Config::PROFILE_DV_AV1_10, DolbyVisionProfileDvav110 },
 };
 
 ALookup<C2Config::level_t, int32_t> sH263Levels = {
@@ -382,10 +383,11 @@
     // TODO: will need to disambiguate between Main8 and Main10
     { C2Config::PROFILE_AV1_0, AV1ProfileMain8 },
     { C2Config::PROFILE_AV1_0, AV1ProfileMain10 },
+    { C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10 },
+    { C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10Plus },
 };
 
 ALookup<C2Config::profile_t, int32_t> sAv1HdrProfiles = {
-    { C2Config::PROFILE_AV1_0, AV1ProfileMain10 },
     { C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10 },
 };
 
@@ -629,7 +631,7 @@
 // static
 std::shared_ptr<C2Mapper::ProfileLevelMapper>
 C2Mapper::GetProfileLevelMapper(std::string mediaType) {
-    std::transform(mediaType.begin(), mediaType.begin(), mediaType.end(), ::tolower);
+    std::transform(mediaType.begin(), mediaType.end(), mediaType.begin(), ::tolower);
     if (mediaType == MIMETYPE_AUDIO_AAC) {
         return std::make_shared<AacProfileLevelMapper>();
     } else if (mediaType == MIMETYPE_VIDEO_AVC) {
@@ -657,11 +659,13 @@
 // static
 std::shared_ptr<C2Mapper::ProfileLevelMapper>
 C2Mapper::GetHdrProfileLevelMapper(std::string mediaType, bool isHdr10Plus) {
-    std::transform(mediaType.begin(), mediaType.begin(), mediaType.end(), ::tolower);
+    std::transform(mediaType.begin(), mediaType.end(), mediaType.begin(), ::tolower);
     if (mediaType == MIMETYPE_VIDEO_HEVC) {
         return std::make_shared<HevcProfileLevelMapper>(true, isHdr10Plus);
     } else if (mediaType == MIMETYPE_VIDEO_VP9) {
         return std::make_shared<Vp9ProfileLevelMapper>(true, isHdr10Plus);
+    } else if (mediaType == MIMETYPE_VIDEO_AV1) {
+        return std::make_shared<Av1ProfileLevelMapper>(true, isHdr10Plus);
     }
     return nullptr;
 }
@@ -945,3 +949,41 @@
 bool C2Mapper::map(ColorAspects::Transfer from, C2Color::transfer_t *to) {
     return sColorTransfersSf.map(from, to);
 }
+
+// static
+bool C2Mapper::mapPixelFormatFrameworkToCodec(
+        int32_t frameworkValue, uint32_t *c2Value) {
+    switch (frameworkValue) {
+        case COLOR_FormatSurface:
+            *c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+            return true;
+        case COLOR_FormatYUV420Flexible:
+            *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
+            return true;
+        case COLOR_FormatYUV420Planar:
+        case COLOR_FormatYUV420SemiPlanar:
+        case COLOR_FormatYUV420PackedPlanar:
+        case COLOR_FormatYUV420PackedSemiPlanar:
+            *c2Value = HAL_PIXEL_FORMAT_YV12;
+            return true;
+        default:
+            // TODO: support some sort of passthrough
+            return false;
+    }
+}
+
+// static
+bool C2Mapper::mapPixelFormatCodecToFramework(
+        uint32_t c2Value, int32_t *frameworkValue) {
+    switch (c2Value) {
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+            *frameworkValue = COLOR_FormatSurface;
+            return true;
+        case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCBCR_420_888:
+            *frameworkValue = COLOR_FormatYUV420Flexible;
+            return true;
+        default:
+            return false;
+    }
+}
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.h b/media/codec2/sfplugin/utils/Codec2Mapper.h
index cec6f07..797c8a8 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.h
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.h
@@ -75,6 +75,11 @@
         static bool map(ColorAspects::MatrixCoeffs, C2Color::matrix_t*);
         static bool map(C2Color::transfer_t, ColorAspects::Transfer*);
         static bool map(ColorAspects::Transfer, C2Color::transfer_t*);
+
+        static bool mapPixelFormatFrameworkToCodec(
+                int32_t frameworkValue, uint32_t *c2Value);
+        static bool mapPixelFormatCodecToFramework(
+                uint32_t c2Value, int32_t *frameworkValue);
     };
 }
 
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 52cc7ad..6f7acce 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -7,6 +7,8 @@
 
     // TODO: Remove this when this module is moved back to frameworks/av.
     vendor_available: true,
+
+    min_sdk_version: "29",
 }
 
 // !!!DO NOT DEPEND ON THIS SHARED LIBRARY DIRECTLY!!!
@@ -14,8 +16,12 @@
 cc_library_shared {
     name: "libcodec2_vndk",
     vendor_available: true,
+    min_sdk_version: "29",
+    // TODO: b/147147883
+    double_loadable: true,
 
     srcs: [
+        "C2AllocatorBlob.cpp",
         "C2AllocatorIon.cpp",
         "C2AllocatorGralloc.cpp",
         "C2Buffer.cpp",
@@ -49,14 +55,10 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.bufferqueue@2.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.common@1.2",
         "android.hardware.media.bufferpool@2.0",
         "libbase",
-        "libbinder",
         "libcutils",
         "libdl",
         "libhardware",
@@ -88,6 +90,8 @@
         "libcodec2_vndk",
         "libutils",
     ],
+
+    min_sdk_version: "29",
 }
 
 // public dependency for implementing Codec 2 framework utilities
@@ -96,6 +100,10 @@
     name: "libcodec2-internal-defaults",
     defaults: ["libcodec2-impl-defaults"],
 
+    header_libs: [
+        "libcodec2_internal",
+    ],
+
     shared_libs: [
         "libcutils", // for properties
     ],
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
new file mode 100644
index 0000000..50c9e59
--- /dev/null
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 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 "C2AllocatorBlob"
+
+#include <C2AllocatorBlob.h>
+#include <C2PlatformSupport.h>
+
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+
+constexpr uint32_t kLinearBufferHeight = 1u;
+constexpr uint32_t kLinearBufferFormat = static_cast<uint32_t>(PixelFormat::BLOB);
+
+namespace {
+
+c2_status_t GetCapacityFromHandle(const C2Handle* const grallocHandle, size_t* capacity) {
+    uint32_t width, height, format, stride, generation, igbp_slot;
+    uint64_t usage, igbp_id;
+    _UnwrapNativeCodec2GrallocMetadata(grallocHandle, &width, &height, &format, &usage, &stride,
+                                       &generation, &igbp_id, &igbp_slot);
+
+    if (height != kLinearBufferHeight || format != kLinearBufferFormat) {
+        return C2_BAD_VALUE;
+    }
+    *capacity = width;
+    return C2_OK;
+}
+
+}  // namespace
+
+// C2AllocationBlob is a wrapper for C2AllocationGralloc allocated by C2AllocatorGralloc.
+// C2AllocationBlob::handle() delegates to the backed C2AllocationGralloc::handle().
+class C2AllocationBlob : public C2LinearAllocation {
+public:
+    C2AllocationBlob(std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+                     C2Allocator::id_t allocatorId);
+    ~C2AllocationBlob() override;
+    c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence* fence,
+                    void** addr /* nonnull */) override;
+    c2_status_t unmap(void* addr, size_t size, C2Fence* fenceFd) override;
+
+    id_t getAllocatorId() const override { return mAllocatorId; }
+    const C2Handle* handle() const override { return mGraphicAllocation->handle(); }
+    bool equals(const std::shared_ptr<C2LinearAllocation>& other) const override {
+        return other && other->handle() == handle();
+    }
+
+private:
+    const std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
+    const C2Allocator::id_t mAllocatorId;
+};
+
+C2AllocationBlob::C2AllocationBlob(
+        std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+        C2Allocator::id_t allocatorId)
+      : C2LinearAllocation(capacity),
+        mGraphicAllocation(std::move(graphicAllocation)),
+        mAllocatorId(allocatorId) {}
+
+C2AllocationBlob::~C2AllocationBlob() {}
+
+c2_status_t C2AllocationBlob::map(size_t offset, size_t size, C2MemoryUsage usage,
+                                  C2Fence* fence, void** addr /* nonnull */) {
+    C2PlanarLayout layout;
+    C2Rect rect = C2Rect(size, kLinearBufferHeight).at(offset, 0u);
+    return mGraphicAllocation->map(rect, usage, fence, &layout, reinterpret_cast<uint8_t**>(addr));
+}
+
+c2_status_t C2AllocationBlob::unmap(void* addr, size_t size, C2Fence* fenceFd) {
+    C2Rect rect(size, kLinearBufferHeight);
+    return mGraphicAllocation->unmap(reinterpret_cast<uint8_t**>(&addr), rect, fenceFd);
+}
+
+/* ====================================== BLOB ALLOCATOR ====================================== */
+C2AllocatorBlob::C2AllocatorBlob(id_t id) {
+    C2MemoryUsage minUsage = {0, 0};
+    C2MemoryUsage maxUsage = {C2MemoryUsage::CPU_READ | C2MemoryUsage::READ_PROTECTED,
+                              C2MemoryUsage::CPU_WRITE};
+    Traits traits = {"android.allocator.blob", id, LINEAR, minUsage, maxUsage};
+    mTraits = std::make_shared<C2Allocator::Traits>(traits);
+    auto allocatorStore = GetCodec2PlatformAllocatorStore();
+    allocatorStore->fetchAllocator(C2PlatformAllocatorStore::GRALLOC, &mC2AllocatorGralloc);
+    if (!mC2AllocatorGralloc) {
+        ALOGE("Failed to obtain C2AllocatorGralloc as backed allocator");
+    }
+}
+
+C2AllocatorBlob::~C2AllocatorBlob() {}
+
+c2_status_t C2AllocatorBlob::newLinearAllocation(
+        uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation>* allocation) {
+    if (allocation == nullptr) {
+        return C2_BAD_VALUE;
+    }
+
+    allocation->reset();
+
+    if (!mC2AllocatorGralloc) {
+        return C2_CORRUPTED;
+    }
+
+    std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+    c2_status_t status = mC2AllocatorGralloc->newGraphicAllocation(
+            capacity, kLinearBufferHeight, kLinearBufferFormat, usage, &graphicAllocation);
+    if (status != C2_OK) {
+        ALOGE("Failed newGraphicAllocation");
+        return status;
+    }
+
+    allocation->reset(new C2AllocationBlob(std::move(graphicAllocation),
+                                           static_cast<size_t>(capacity), mTraits->id));
+    return C2_OK;
+}
+
+c2_status_t C2AllocatorBlob::priorLinearAllocation(
+        const C2Handle* handle, std::shared_ptr<C2LinearAllocation>* allocation) {
+    if (allocation == nullptr) {
+        return C2_BAD_VALUE;
+    }
+
+    allocation->reset();
+
+    if (!mC2AllocatorGralloc) {
+        return C2_CORRUPTED;
+    }
+
+    std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+    c2_status_t status = mC2AllocatorGralloc->priorGraphicAllocation(handle, &graphicAllocation);
+    if (status != C2_OK) {
+        ALOGE("Failed priorGraphicAllocation");
+        return status;
+    }
+
+    const C2Handle* const grallocHandle = graphicAllocation->handle();
+    size_t capacity = 0;
+    status = GetCapacityFromHandle(grallocHandle, &capacity);
+    if (status != C2_OK) {
+        ALOGE("Failed to extract capacity from Handle");
+        return status;
+    }
+
+    allocation->reset(new C2AllocationBlob(std::move(graphicAllocation), capacity, mTraits->id));
+    return C2_OK;
+}
+
+id_t C2AllocatorBlob::getId() const {
+    return mTraits->id;
+}
+
+C2String C2AllocatorBlob::getName() const {
+    return mTraits->name;
+}
+
+std::shared_ptr<const C2Allocator::Traits> C2AllocatorBlob::getTraits() const {
+    return mTraits;
+}
+
+// static
+bool C2AllocatorBlob::isValid(const C2Handle* const o) {
+    size_t capacity;
+    // Distinguish C2Handle purely allocated by C2AllocatorGralloc, or one allocated through
+    // C2AllocatorBlob, by checking the handle's height is 1, and its format is
+    // PixelFormat::BLOB by GetCapacityFromHandle().
+    return C2AllocatorGralloc::isValid(o) && GetCapacityFromHandle(o, &capacity) == C2_OK;
+}
+
+}  // namespace android
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index af97e61..e1e1377 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -18,17 +18,21 @@
 #define LOG_TAG "C2AllocatorGralloc"
 #include <utils/Log.h>
 
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <mutex>
+
+#include <android/hardware/graphics/common/1.2/types.h>
 #include <cutils/native_handle.h>
 #include <hardware/gralloc.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
 
 #include <C2AllocatorGralloc.h>
 #include <C2Buffer.h>
 #include <C2PlatformSupport.h>
 
+using ::android::hardware::hidl_handle;
+using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
+
 namespace android {
 
 namespace /* unnamed */ {
@@ -61,59 +65,9 @@
             (expected & PASSTHROUGH_USAGE_MASK));
 }
 
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
-using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
-
-using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
-using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
-using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
-
-using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
-using BufferDescriptor3 = ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
-using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
-using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
-
 namespace /* unnamed */ {
 
-struct BufferDescriptorInfo2 {
-    IMapper2::BufferDescriptorInfo mapperInfo;
-    uint32_t stride;
-};
-
-struct BufferDescriptorInfo3 {
-    IMapper3::BufferDescriptorInfo mapperInfo;
-    uint32_t stride;
-};
-
 /* ===================================== GRALLOC ALLOCATION ==================================== */
-c2_status_t maperr2error(Error2 maperr) {
-    switch (maperr) {
-        case Error2::NONE:           return C2_OK;
-        case Error2::BAD_DESCRIPTOR: return C2_BAD_VALUE;
-        case Error2::BAD_BUFFER:     return C2_BAD_VALUE;
-        case Error2::BAD_VALUE:      return C2_BAD_VALUE;
-        case Error2::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error2::UNSUPPORTED:    return C2_CANNOT_DO;
-    }
-    return C2_CORRUPTED;
-}
-
-c2_status_t maperr2error(Error3 maperr) {
-    switch (maperr) {
-        case Error3::NONE:           return C2_OK;
-        case Error3::BAD_DESCRIPTOR: return C2_BAD_VALUE;
-        case Error3::BAD_BUFFER:     return C2_BAD_VALUE;
-        case Error3::BAD_VALUE:      return C2_BAD_VALUE;
-        case Error3::NO_RESOURCES:   return C2_NO_MEMORY;
-        case Error3::UNSUPPORTED:    return C2_CANNOT_DO;
-    }
-    return C2_CORRUPTED;
-}
-
 bool native_handle_is_invalid(const native_handle_t *const handle) {
     // perform basic validation of a native handle
     if (handle == nullptr) {
@@ -309,15 +263,11 @@
 
     // internal methods
     // |handle| will be moved.
+
     C2AllocationGralloc(
-              const BufferDescriptorInfo2 &info,
-              const sp<IMapper2> &mapper,
-              hidl_handle &hidlHandle,
-              const C2HandleGralloc *const handle,
-              C2Allocator::id_t allocatorId);
-    C2AllocationGralloc(
-              const BufferDescriptorInfo3 &info,
-              const sp<IMapper3> &mapper,
+              uint32_t width, uint32_t height,
+              uint32_t format, uint32_t layerCount,
+              uint64_t grallocUsage, uint32_t stride,
               hidl_handle &hidlHandle,
               const C2HandleGralloc *const handle,
               C2Allocator::id_t allocatorId);
@@ -325,10 +275,12 @@
     c2_status_t status() const;
 
 private:
-    const BufferDescriptorInfo2 mInfo2{};
-    const sp<IMapper2> mMapper2{nullptr};
-    const BufferDescriptorInfo3 mInfo3{};
-    const sp<IMapper3> mMapper3{nullptr};
+    const uint32_t mWidth;
+    const uint32_t mHeight;
+    const uint32_t mFormat;
+    const uint32_t mLayerCount;
+    const uint64_t mGrallocUsage;
+    const uint32_t mStride;
     const hidl_handle mHidlHandle;
     const C2HandleGralloc *mHandle;
     buffer_handle_t mBuffer;
@@ -339,31 +291,19 @@
 };
 
 C2AllocationGralloc::C2AllocationGralloc(
-          const BufferDescriptorInfo2 &info,
-          const sp<IMapper2> &mapper,
+          uint32_t width, uint32_t height,
+          uint32_t format, uint32_t layerCount,
+          uint64_t grallocUsage, uint32_t stride,
           hidl_handle &hidlHandle,
           const C2HandleGralloc *const handle,
           C2Allocator::id_t allocatorId)
-    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
-      mInfo2(info),
-      mMapper2(mapper),
-      mHidlHandle(std::move(hidlHandle)),
-      mHandle(handle),
-      mBuffer(nullptr),
-      mLockedHandle(nullptr),
-      mLocked(false),
-      mAllocatorId(allocatorId) {
-}
-
-C2AllocationGralloc::C2AllocationGralloc(
-          const BufferDescriptorInfo3 &info,
-          const sp<IMapper3> &mapper,
-          hidl_handle &hidlHandle,
-          const C2HandleGralloc *const handle,
-          C2Allocator::id_t allocatorId)
-    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
-      mInfo3(info),
-      mMapper3(mapper),
+    : C2GraphicAllocation(width, height),
+      mWidth(width),
+      mHeight(height),
+      mFormat(format),
+      mLayerCount(layerCount),
+      mGrallocUsage(grallocUsage),
+      mStride(stride),
       mHidlHandle(std::move(hidlHandle)),
       mHandle(handle),
       mBuffer(nullptr),
@@ -379,16 +319,9 @@
         unmap(addr, C2Rect(), nullptr);
     }
     if (mBuffer) {
-        if (mMapper2) {
-            if (!mMapper2->freeBuffer(const_cast<native_handle_t *>(
-                    mBuffer)).isOk()) {
-                ALOGE("failed transaction: freeBuffer");
-            }
-        } else {
-            if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
-                    mBuffer)).isOk()) {
-                ALOGE("failed transaction: freeBuffer");
-            }
+        status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
+        if (err) {
+            ALOGE("failed transaction: freeBuffer");
         }
     }
     if (mHandle) {
@@ -410,7 +343,7 @@
           (long long)usage.expected, (long long)grallocUsage);
 
     // TODO
-    (void) fence;
+    (void)fence;
 
     std::lock_guard<std::mutex> lock(mMappedLock);
     if (mBuffer && mLocked) {
@@ -422,34 +355,13 @@
         return C2_BAD_VALUE;
     }
 
-    c2_status_t err = C2_OK;
     if (!mBuffer) {
-        if (mMapper2) {
-            if (!mMapper2->importBuffer(
-                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
-                        err = maperr2error(maperr);
-                        if (err == C2_OK) {
-                            mBuffer = static_cast<buffer_handle_t>(buffer);
-                        }
-                    }).isOk()) {
-                ALOGE("failed transaction: importBuffer");
-                return C2_CORRUPTED;
-            }
-        } else {
-            if (!mMapper3->importBuffer(
-                    mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
-                        err = maperr2error(maperr);
-                        if (err == C2_OK) {
-                            mBuffer = static_cast<buffer_handle_t>(buffer);
-                        }
-                    }).isOk()) {
-                ALOGE("failed transaction: importBuffer (@3.0)");
-                return C2_CORRUPTED;
-            }
-        }
-        if (err != C2_OK) {
-            ALOGD("importBuffer failed: %d", err);
-            return err;
+        status_t err = GraphicBufferMapper::get().importBuffer(
+                            mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
+                            mFormat, mGrallocUsage, mStride, &mBuffer);
+        if (err) {
+            ALOGE("failed transaction: importBuffer");
+            return C2_CORRUPTED;
         }
         if (mBuffer == nullptr) {
             ALOGD("importBuffer returned null buffer");
@@ -461,69 +373,26 @@
         if (mHandle) {
             mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
         }
-        if (mMapper2) {
-            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
-                    mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
-                    (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
-                    mInfo2.stride, generation, igbp_id, igbp_slot);
-        } else {
-            mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
-                    mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
-                    (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
-                    mInfo3.stride, generation, igbp_id, igbp_slot);
-        }
-    }
 
-    PixelFormat3 format = mMapper2 ?
-            PixelFormat3(mInfo2.mapperInfo.format) :
-            PixelFormat3(mInfo3.mapperInfo.format);
-    switch (format) {
-        case PixelFormat3::RGBA_1010102: {
+        mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
+                mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
+                mStride, generation, igbp_id, igbp_slot);
+    }
+    switch (mFormat) {
+        case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
             // default to YUV for now.
             void *pointer = nullptr;
-            if (mMapper2) {
-                if (!mMapper2->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_1010102)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper3->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            }
-            if (err != C2_OK) {
-                ALOGD("lock failed: %d", err);
-                return err;
+            // TODO: fence
+            status_t err = GraphicBufferMapper::get().lock(
+                                const_cast<native_handle_t *>(mBuffer), grallocUsage,
+                                { (int32_t)rect.left, (int32_t)rect.top,
+                                  (int32_t)rect.width, (int32_t)rect.height },
+                                &pointer);
+            if (err) {
+                ALOGE("failed transaction: lock(RGBA_1010102)");
+                return C2_CORRUPTED;
             }
             // treat as 32-bit values
             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
@@ -533,13 +402,10 @@
             layout->type = C2PlanarLayout::TYPE_YUVA;
             layout->numPlanes = 4;
             layout->rootPlanes = 1;
-            int32_t stride = mMapper2 ?
-                    int32_t(mInfo2.stride) :
-                    int32_t(mInfo3.stride);
             layout->planes[C2PlanarLayout::PLANE_Y] = {
                 C2PlaneInfo::CHANNEL_Y,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -552,7 +418,7 @@
             layout->planes[C2PlanarLayout::PLANE_U] = {
                 C2PlaneInfo::CHANNEL_CB,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -565,7 +431,7 @@
             layout->planes[C2PlanarLayout::PLANE_V] = {
                 C2PlaneInfo::CHANNEL_CR,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -578,7 +444,7 @@
             layout->planes[C2PlanarLayout::PLANE_A] = {
                 C2PlaneInfo::CHANNEL_A,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 32,                             // allocatedDepth
@@ -591,52 +457,20 @@
             break;
         }
 
-        case PixelFormat3::RGBA_8888:
+        case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
             // TODO: alpha channel
             // fall-through
-        case PixelFormat3::RGBX_8888: {
+        case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
             void *pointer = nullptr;
-            if (mMapper2) {
-                if (!mMapper2->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_8888)");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper3->lock(
-                        const_cast<native_handle_t *>(mBuffer),
-                        grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &pointer](const auto &maperr, const auto &mapPointer,
-                                         int32_t bytesPerPixel, int32_t bytesPerStride) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                pointer = mapPointer;
-                            }
-                            (void)bytesPerPixel;
-                            (void)bytesPerStride;
-                        }).isOk()) {
-                    ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
-                    return C2_CORRUPTED;
-                }
-            }
-            if (err != C2_OK) {
-                ALOGD("lock failed: %d", err);
-                return err;
+            // TODO: fence
+            status_t err = GraphicBufferMapper::get().lock(
+                                const_cast<native_handle_t*>(mBuffer), grallocUsage,
+                                { (int32_t)rect.left, (int32_t)rect.top,
+                                  (int32_t)rect.width, (int32_t)rect.height },
+                                &pointer);
+            if (err) {
+                ALOGE("failed transaction: lock(RGBA_8888)");
+                return C2_CORRUPTED;
             }
             addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
             addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
@@ -644,13 +478,10 @@
             layout->type = C2PlanarLayout::TYPE_RGB;
             layout->numPlanes = 3;
             layout->rootPlanes = 1;
-            int32_t stride = mMapper2 ?
-                    int32_t(mInfo2.stride) :
-                    int32_t(mInfo3.stride);
             layout->planes[C2PlanarLayout::PLANE_R] = {
                 C2PlaneInfo::CHANNEL_R,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -663,7 +494,7 @@
             layout->planes[C2PlanarLayout::PLANE_G] = {
                 C2PlaneInfo::CHANNEL_G,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -676,7 +507,7 @@
             layout->planes[C2PlanarLayout::PLANE_B] = {
                 C2PlaneInfo::CHANNEL_B,         // channel
                 4,                              // colInc
-                4 * stride,                     // rowInc
+                static_cast<int32_t>(4 * mStride), // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -689,69 +520,39 @@
             break;
         }
 
-        case PixelFormat3::YCBCR_420_888:
+        case static_cast<uint32_t>(PixelFormat4::BLOB): {
+            void *pointer = nullptr;
+            // TODO: fence
+            status_t err = GraphicBufferMapper::get().lock(
+                                const_cast<native_handle_t*>(mBuffer), grallocUsage,
+                                { (int32_t)rect.left, (int32_t)rect.top,
+                                  (int32_t)rect.width, (int32_t)rect.height },
+                                &pointer);
+            if (err) {
+                ALOGE("failed transaction: lock(BLOB)");
+                return C2_CORRUPTED;
+            }
+            *addr = (uint8_t *)pointer;
+            break;
+        }
+
+        case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
             // fall-through
-        case PixelFormat3::YV12:
+        case static_cast<uint32_t>(PixelFormat4::YV12):
             // fall-through
         default: {
-            struct YCbCrLayout {
-                void* y;
-                void* cb;
-                void* cr;
-                uint32_t yStride;
-                uint32_t cStride;
-                uint32_t chromaStep;
-            };
-            YCbCrLayout ycbcrLayout;
-            if (mMapper2) {
-                if (!mMapper2->lockYCbCr(
-                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
+            android_ycbcr ycbcrLayout;
+
+            status_t err = GraphicBufferMapper::get().lockYCbCr(
+                        const_cast<native_handle_t*>(mBuffer), grallocUsage,
                         { (int32_t)rect.left, (int32_t)rect.top,
                           (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                ycbcrLayout = YCbCrLayout{
-                                        mapLayout.y,
-                                        mapLayout.cb,
-                                        mapLayout.cr,
-                                        mapLayout.yStride,
-                                        mapLayout.cStride,
-                                        mapLayout.chromaStep};
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lockYCbCr");
-                    return C2_CORRUPTED;
-                }
-            } else {
-                if (!mMapper3->lockYCbCr(
-                        const_cast<native_handle_t *>(mBuffer), grallocUsage,
-                        { (int32_t)rect.left, (int32_t)rect.top,
-                          (int32_t)rect.width, (int32_t)rect.height },
-                        // TODO: fence
-                        hidl_handle(),
-                        [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
-                            err = maperr2error(maperr);
-                            if (err == C2_OK) {
-                                ycbcrLayout = YCbCrLayout{
-                                        mapLayout.y,
-                                        mapLayout.cb,
-                                        mapLayout.cr,
-                                        mapLayout.yStride,
-                                        mapLayout.cStride,
-                                        mapLayout.chromaStep};
-                            }
-                        }).isOk()) {
-                    ALOGE("failed transaction: lockYCbCr (@3.0)");
-                    return C2_CORRUPTED;
-                }
+                        &ycbcrLayout);
+            if (err) {
+                ALOGE("failed transaction: lockYCbCr");
+                return C2_CORRUPTED;
             }
-            if (err != C2_OK) {
-                ALOGD("lockYCbCr failed: %d", err);
-                return err;
-            }
+
             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
@@ -761,7 +562,7 @@
             layout->planes[C2PlanarLayout::PLANE_Y] = {
                 C2PlaneInfo::CHANNEL_Y,         // channel
                 1,                              // colInc
-                (int32_t)ycbcrLayout.yStride,   // rowInc
+                (int32_t)ycbcrLayout.ystride,   // rowInc
                 1,                              // mColSampling
                 1,                              // mRowSampling
                 8,                              // allocatedDepth
@@ -773,8 +574,8 @@
             };
             layout->planes[C2PlanarLayout::PLANE_U] = {
                 C2PlaneInfo::CHANNEL_CB,          // channel
-                (int32_t)ycbcrLayout.chromaStep,  // colInc
-                (int32_t)ycbcrLayout.cStride,     // rowInc
+                (int32_t)ycbcrLayout.chroma_step, // colInc
+                (int32_t)ycbcrLayout.cstride,     // rowInc
                 2,                                // mColSampling
                 2,                                // mRowSampling
                 8,                                // allocatedDepth
@@ -786,8 +587,8 @@
             };
             layout->planes[C2PlanarLayout::PLANE_V] = {
                 C2PlaneInfo::CHANNEL_CR,          // channel
-                (int32_t)ycbcrLayout.chromaStep,  // colInc
-                (int32_t)ycbcrLayout.cStride,     // rowInc
+                (int32_t)ycbcrLayout.chroma_step, // colInc
+                (int32_t)ycbcrLayout.cstride,     // rowInc
                 2,                                // mColSampling
                 2,                                // mRowSampling
                 8,                                // allocatedDepth
@@ -799,11 +600,11 @@
             };
             // handle interleaved formats
             intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
-            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
+            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
                 layout->rootPlanes = 2;
                 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
                 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
-            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
+            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
                 layout->rootPlanes = 2;
                 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
                 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
@@ -821,44 +622,18 @@
     // TODO: check addr and size, use fence
     (void)addr;
     (void)rect;
+    (void)fence;
 
     std::lock_guard<std::mutex> lock(mMappedLock);
-    c2_status_t err = C2_OK;
-    if (mMapper2) {
-        if (!mMapper2->unlock(
-                const_cast<native_handle_t *>(mBuffer),
-                [&err, &fence](const auto &maperr, const auto &releaseFence) {
-                    // TODO
-                    (void) fence;
-                    (void) releaseFence;
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        // TODO: fence
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: unlock");
-            return C2_CORRUPTED;
-        }
-    } else {
-        if (!mMapper3->unlock(
-                const_cast<native_handle_t *>(mBuffer),
-                [&err, &fence](const auto &maperr, const auto &releaseFence) {
-                    // TODO
-                    (void) fence;
-                    (void) releaseFence;
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        // TODO: fence
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: unlock (@3.0)");
-            return C2_CORRUPTED;
-        }
+    // TODO: fence
+    status_t err = GraphicBufferMapper::get().unlock(mBuffer);
+    if (err) {
+        ALOGE("failed transaction: unlock");
+        return C2_CORRUPTED;
     }
-    if (err == C2_OK) {
-        mLocked = false;
-    }
-    return err;
+
+    mLocked = false;
+    return C2_OK;
 }
 
 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
@@ -895,10 +670,6 @@
 private:
     std::shared_ptr<C2Allocator::Traits> mTraits;
     c2_status_t mInit;
-    sp<IAllocator2> mAllocator2;
-    sp<IMapper2> mMapper2;
-    sp<IAllocator3> mAllocator3;
-    sp<IMapper3> mMapper3;
     const bool mBufferQueue;
 };
 
@@ -916,21 +687,6 @@
     C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
     Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
     mTraits = std::make_shared<C2Allocator::Traits>(traits);
-
-    // gralloc allocator is a singleton, so all objects share a global service
-    mAllocator3 = IAllocator3::getService();
-    mMapper3 = IMapper3::getService();
-    if (!mAllocator3 || !mMapper3) {
-        mAllocator3 = nullptr;
-        mMapper3 = nullptr;
-        mAllocator2 = IAllocator2::getService();
-        mMapper2 = IMapper2::getService();
-        if (!mAllocator2 || !mMapper2) {
-            mAllocator2 = nullptr;
-            mMapper2 = nullptr;
-            mInit = C2_CORRUPTED;
-        }
-    }
 }
 
 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
@@ -940,176 +696,59 @@
     ALOGV("allocating buffer with usage %#llx => %#llx",
           (long long)usage.expected, (long long)grallocUsage);
 
-    c2_status_t err = C2_OK;
-    hidl_handle buffer{};
+    buffer_handle_t buffer;
 
-    if (mMapper2) {
-        BufferDescriptorInfo2 info = {
-            {
-                width,
-                height,
-                1u,  // layerCount
-                PixelFormat2(format),
-                grallocUsage,
-            },
-            0u,  // stride placeholder
-        };
-        BufferDescriptor2 desc;
-        if (!mMapper2->createDescriptor(
-                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        desc = descriptor;
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: createDescriptor");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
+    uint32_t stride = 0;
 
-        // IAllocator shares IMapper error codes.
-        if (!mAllocator2->allocate(
-                desc,
-                1u,
-                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
-                    err = maperr2error(maperr);
-                    if (err != C2_OK) {
-                        return;
-                    }
-                    if (buffers.size() != 1u) {
-                        err = C2_CORRUPTED;
-                        return;
-                    }
-                    info.stride = stride;
-                    buffer = buffers[0];
-                }).isOk()) {
-            ALOGE("failed transaction: allocate");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper2, buffer,
-                C2HandleGralloc::WrapAndMoveNativeHandle(
-                        buffer.getNativeHandle(),
-                        width, height,
-                        format, grallocUsage, info.stride,
-                        0, 0, mBufferQueue ? ~0 : 0),
-                mTraits->id));
-        return C2_OK;
-    } else {
-        BufferDescriptorInfo3 info = {
-            {
-                width,
-                height,
-                1u,  // layerCount
-                PixelFormat3(format),
-                grallocUsage,
-            },
-            0u,  // stride placeholder
-        };
-        BufferDescriptor3 desc;
-        if (!mMapper3->createDescriptor(
-                info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
-                    err = maperr2error(maperr);
-                    if (err == C2_OK) {
-                        desc = descriptor;
-                    }
-                }).isOk()) {
-            ALOGE("failed transaction: createDescriptor");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-
-        // IAllocator shares IMapper error codes.
-        if (!mAllocator3->allocate(
-                desc,
-                1u,
-                [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
-                    err = maperr2error(maperr);
-                    if (err != C2_OK) {
-                        return;
-                    }
-                    if (buffers.size() != 1u) {
-                        err = C2_CORRUPTED;
-                        return;
-                    }
-                    info.stride = stride;
-                    buffer = buffers[0];
-                }).isOk()) {
-            ALOGE("failed transaction: allocate");
-            return C2_CORRUPTED;
-        }
-        if (err != C2_OK) {
-            return err;
-        }
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper3, buffer,
-                C2HandleGralloc::WrapAndMoveNativeHandle(
-                        buffer.getNativeHandle(),
-                        width, height,
-                        format, grallocUsage, info.stride,
-                        0, 0, mBufferQueue ? ~0 : 0),
-                mTraits->id));
-        return C2_OK;
+    status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
+            1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
+    if (err) {
+        ALOGE("failed transaction: allocate");
+        return C2_CORRUPTED;
     }
+
+    hidl_handle hidlHandle;
+    hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
+
+    allocation->reset(new C2AllocationGralloc(
+            width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
+            C2HandleGralloc::WrapAndMoveNativeHandle(
+                    hidlHandle, width, height,
+                    format, grallocUsage, stride,
+                    0, 0, mBufferQueue ? ~0 : 0),
+            mTraits->id));
+    return C2_OK;
 }
 
 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
         const C2Handle *handle,
         std::shared_ptr<C2GraphicAllocation> *allocation) {
-    if (mMapper2) {
-        BufferDescriptorInfo2 info;
-        info.mapperInfo.layerCount = 1u;
-        uint32_t generation;
-        uint64_t igbp_id;
-        uint32_t igbp_slot;
-        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
-                handle,
-                &info.mapperInfo.width, &info.mapperInfo.height,
-                (uint32_t *)&info.mapperInfo.format,
-                (uint64_t *)&info.mapperInfo.usage,
-                &info.stride,
-                &generation, &igbp_id, &igbp_slot);
-        if (grallocHandle == nullptr) {
-            return C2_BAD_VALUE;
-        }
 
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+    uint32_t generation;
+    uint64_t igbp_id;
+    uint32_t igbp_slot;
 
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
-        return C2_OK;
-    } else {
-        BufferDescriptorInfo3 info;
-        info.mapperInfo.layerCount = 1u;
-        uint32_t generation;
-        uint64_t igbp_id;
-        uint32_t igbp_slot;
-        const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
-                handle,
-                &info.mapperInfo.width, &info.mapperInfo.height,
-                (uint32_t *)&info.mapperInfo.format,
-                (uint64_t *)&info.mapperInfo.usage,
-                &info.stride,
-                &generation, &igbp_id, &igbp_slot);
-        if (grallocHandle == nullptr) {
-            return C2_BAD_VALUE;
-        }
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    uint32_t layerCount = 1;
+    uint64_t grallocUsage;
+    uint32_t stride;
 
-        hidl_handle hidlHandle;
-        hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
-
-        allocation->reset(new C2AllocationGralloc(
-                info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
-        return C2_OK;
+    const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
+            handle, &width, &height, &format, &grallocUsage, &stride,
+            &generation, &igbp_id, &igbp_slot);
+    if (grallocHandle == nullptr) {
+        return C2_BAD_VALUE;
     }
+
+    hidl_handle hidlHandle;
+    hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
+
+    allocation->reset(new C2AllocationGralloc(
+            width, height, format, layerCount,
+            grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
+    return C2_OK;
 }
 
 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 752bc46..6d27a02 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -28,6 +28,7 @@
 #include <C2Buffer.h>
 #include <C2Debug.h>
 #include <C2ErrnoUtils.h>
+#include <C2HandleIonInternal.h>
 
 namespace android {
 
@@ -64,43 +65,6 @@
  * This handle will not capture mapped fd-s as updating that would require a global mutex.
  */
 
-struct C2HandleIon : public C2Handle {
-    // ion handle owns ionFd(!) and bufferFd
-    C2HandleIon(int bufferFd, size_t size)
-        : C2Handle(cHeader),
-          mFds{ bufferFd },
-          mInts{ int(size & 0xFFFFFFFF), int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic } { }
-
-    static bool isValid(const C2Handle * const o);
-
-    int bufferFd() const { return mFds.mBuffer; }
-    size_t size() const {
-        return size_t(unsigned(mInts.mSizeLo))
-                | size_t(uint64_t(unsigned(mInts.mSizeHi)) << 32);
-    }
-
-protected:
-    struct {
-        int mBuffer; // shared ion buffer
-    } mFds;
-    struct {
-        int mSizeLo; // low 32-bits of size
-        int mSizeHi; // high 32-bits of size
-        int mMagic;
-    } mInts;
-
-private:
-    typedef C2HandleIon _type;
-    enum {
-        kMagic = '\xc2io\x00',
-        numFds = sizeof(mFds) / sizeof(int),
-        numInts = sizeof(mInts) / sizeof(int),
-        version = sizeof(C2Handle)
-    };
-    //constexpr static C2Handle cHeader = { version, numFds, numInts, {} };
-    const static C2Handle cHeader;
-};
-
 const C2Handle C2HandleIon::cHeader = {
     C2HandleIon::version,
     C2HandleIon::numFds,
@@ -262,7 +226,7 @@
                 *fence = C2Fence(); // not using fences
             }
             (void)mMappings.erase(it);
-            ALOGV("successfully unmapped: %d", mHandle.bufferFd());
+            ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size, mHandle.bufferFd());
             return C2_OK;
         }
         ALOGD("unmap failed to find specified map");
@@ -600,7 +564,7 @@
     }
 
     std::shared_ptr<C2AllocationIon> alloc
-        = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags, mTraits->id);
+        = std::make_shared<C2AllocationIon>(dup(mIonFd), capacity, align, heapMask, flags, getId());
     ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
@@ -622,7 +586,7 @@
     // TODO: get capacity and validate it
     const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
     std::shared_ptr<C2AllocationIon> alloc
-        = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd(), mTraits->id);
+        = std::make_shared<C2AllocationIon>(dup(mIonFd), h->size(), h->bufferFd(), getId());
     c2_status_t ret = alloc->status();
     if (ret == C2_OK) {
         *allocation = alloc;
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 2d99b53..0b08f31 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -22,14 +22,17 @@
 #include <map>
 #include <mutex>
 
-#include <C2AllocatorIon.h>
+#include <C2AllocatorBlob.h>
 #include <C2AllocatorGralloc.h>
+#include <C2AllocatorIon.h>
 #include <C2BufferPriv.h>
 #include <C2BlockInternal.h>
+#include <C2PlatformSupport.h>
 #include <bufferpool/ClientManager.h>
 
 namespace {
 
+using android::C2AllocatorBlob;
 using android::C2AllocatorGralloc;
 using android::C2AllocatorIon;
 using android::hardware::media::bufferpool::BufferPoolData;
@@ -393,10 +396,29 @@
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
         const C2Handle *handle) {
     // TODO: get proper allocator? and mutex?
-    static std::unique_ptr<C2AllocatorIon> sAllocator = std::make_unique<C2AllocatorIon>(0);
+    static std::unique_ptr<C2Allocator> sAllocator = []{
+        std::unique_ptr<C2Allocator> allocator;
+        if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
+                android::C2PlatformAllocatorStore::BLOB) {
+            allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
+        } else {
+            allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
+        }
+        return allocator;
+    }();
+
+    if (sAllocator == nullptr)
+        return nullptr;
+
+    bool isValidHandle = false;
+    if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
+        isValidHandle = C2AllocatorBlob::isValid(handle);
+    } else {
+        isValidHandle = C2AllocatorIon::isValid(handle);
+    }
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    if (C2AllocatorIon::isValid(handle)) {
+    if (isValidHandle) {
         c2_status_t err = sAllocator->priorLinearAllocation(handle, &alloc);
         if (err == C2_OK) {
             std::shared_ptr<C2LinearBlock> block = _C2BlockFactory::CreateLinearBlock(alloc);
@@ -409,10 +431,29 @@
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
         const C2Handle *cHandle, const std::shared_ptr<BufferPoolData> &data) {
     // TODO: get proper allocator? and mutex?
-    static std::unique_ptr<C2AllocatorIon> sAllocator = std::make_unique<C2AllocatorIon>(0);
+    static std::unique_ptr<C2Allocator> sAllocator = []{
+        std::unique_ptr<C2Allocator> allocator;
+        if (android::GetPreferredLinearAllocatorId(android::GetCodec2PoolMask()) ==
+                android::C2PlatformAllocatorStore::BLOB) {
+            allocator = std::make_unique<C2AllocatorBlob>(android::C2PlatformAllocatorStore::BLOB);
+        } else {
+            allocator = std::make_unique<C2AllocatorIon>(android::C2PlatformAllocatorStore::ION);
+        }
+        return allocator;
+    }();
+
+    if (sAllocator == nullptr)
+        return nullptr;
+
+    bool isValidHandle = false;
+    if (sAllocator->getId() == android::C2PlatformAllocatorStore::BLOB) {
+        isValidHandle = C2AllocatorBlob::isValid(cHandle);
+    } else {
+        isValidHandle = C2AllocatorIon::isValid(cHandle);
+    }
 
     std::shared_ptr<C2LinearAllocation> alloc;
-    if (C2AllocatorIon::isValid(cHandle)) {
+    if (isValidHandle) {
         c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
         const std::shared_ptr<C2PooledBlockPoolData> poolData =
                 std::make_shared<C2PooledBlockPoolData>(data);
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 5b2bd7b..d16527e 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -18,6 +18,7 @@
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <C2AllocatorBlob.h>
 #include <C2AllocatorGralloc.h>
 #include <C2AllocatorIon.h>
 #include <C2BufferPriv.h>
@@ -26,6 +27,7 @@
 #include <C2Config.h>
 #include <C2PlatformStorePluginLoader.h>
 #include <C2PlatformSupport.h>
+#include <cutils/properties.h>
 #include <util/C2InterfaceHelper.h>
 
 #include <dlfcn.h>
@@ -35,6 +37,10 @@
 #include <memory>
 #include <mutex>
 
+#ifdef __ANDROID_APEX__
+#include <android-base/properties.h>
+#endif
+
 namespace android {
 
 /**
@@ -71,6 +77,9 @@
     ~C2PlatformAllocatorStoreImpl() override = default;
 
 private:
+    /// returns a shared-singleton blob allocator (gralloc-backed)
+    std::shared_ptr<C2Allocator> fetchBlobAllocator();
+
     /// returns a shared-singleton ion allocator
     std::shared_ptr<C2Allocator> fetchIonAllocator();
 
@@ -93,10 +102,12 @@
 c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
         id_t id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
+    if (id == C2AllocatorStore::DEFAULT_LINEAR) {
+        id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
+    }
     switch (id) {
     // TODO: should we implement a generic registry for all, and use that?
     case C2PlatformAllocatorStore::ION:
-    case C2AllocatorStore::DEFAULT_LINEAR:
         *allocator = fetchIonAllocator();
         break;
 
@@ -109,6 +120,10 @@
         *allocator = fetchBufferQueueAllocator();
         break;
 
+    case C2PlatformAllocatorStore::BLOB:
+        *allocator = fetchBlobAllocator();
+        break;
+
     default:
         // Try to create allocator from platform store plugins.
         c2_status_t res =
@@ -218,6 +233,18 @@
     return allocator;
 }
 
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
+    static std::mutex mutex;
+    static std::weak_ptr<C2Allocator> blobAllocator;
+    std::lock_guard<std::mutex> lock(mutex);
+    std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
+    if (allocator == nullptr) {
+        allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
+        blobAllocator = allocator;
+    }
+    return allocator;
+}
+
 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
     static std::mutex mutex;
     static std::weak_ptr<C2Allocator> grallocAllocator;
@@ -288,6 +315,18 @@
     return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
 }
 
+int GetCodec2PoolMask() {
+    return property_get_int32(
+            "debug.stagefright.c2-poolmask",
+            1 << C2PlatformAllocatorStore::ION |
+            1 << C2PlatformAllocatorStore::BUFFERQUEUE);
+}
+
+C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
+    return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
+                                                              : C2PlatformAllocatorStore::ION;
+}
+
 namespace {
 
 class _C2BlockPoolCache {
@@ -304,11 +343,25 @@
         std::shared_ptr<C2Allocator> allocator;
         c2_status_t res = C2_NOT_FOUND;
 
+        if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
+            allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
+        }
         switch(allocatorId) {
             case C2PlatformAllocatorStore::ION:
-            case C2AllocatorStore::DEFAULT_LINEAR:
                 res = allocatorStore->fetchAllocator(
-                        C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+                        C2PlatformAllocatorStore::ION, &allocator);
+                if (res == C2_OK) {
+                    std::shared_ptr<C2BlockPool> ptr =
+                            std::make_shared<C2PooledBlockPool>(
+                                    allocator, poolId);
+                    *pool = ptr;
+                    mBlockPools[poolId] = ptr;
+                    mComponents[poolId] = component;
+                }
+                break;
+            case C2PlatformAllocatorStore::BLOB:
+                res = allocatorStore->fetchAllocator(
+                        C2PlatformAllocatorStore::BLOB, &allocator);
                 if (res == C2_OK) {
                     std::shared_ptr<C2BlockPool> ptr =
                             std::make_shared<C2PooledBlockPool>(
@@ -599,9 +652,33 @@
 
             struct Setter {
                 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
+#ifdef __ANDROID_APEX__
+                    static int32_t defaultHeapMask = [] {
+                        int32_t heapmask = base::GetIntProperty(
+                                "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
+                        ALOGD("Default ION heapmask = %d", heapmask);
+                        return heapmask;
+                    }();
+                    static int32_t defaultFlags = [] {
+                        int32_t flags = base::GetIntProperty(
+                                "ro.com.android.media.swcodec.ion.flags", 0);
+                        ALOGD("Default ION flags = %d", flags);
+                        return flags;
+                    }();
+                    static uint32_t defaultAlign = [] {
+                        uint32_t align = base::GetUintProperty(
+                                "ro.com.android.media.swcodec.ion.align", 0u);
+                        ALOGD("Default ION align = %d", align);
+                        return align;
+                    }();
+                    me.set().heapMask = defaultHeapMask;
+                    me.set().allocFlags = defaultFlags;
+                    me.set().minAlignment = defaultAlign;
+#else
                     me.set().heapMask = ~0;
                     me.set().allocFlags = 0;
                     me.set().minAlignment = 0;
+#endif
                     return C2R::Ok();
                 }
             };
diff --git a/media/codec2/vndk/include/C2AllocatorBlob.h b/media/codec2/vndk/include/C2AllocatorBlob.h
new file mode 100644
index 0000000..89ce949
--- /dev/null
+++ b/media/codec2/vndk/include/C2AllocatorBlob.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 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 STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+
+#include <functional>
+
+#include <C2AllocatorGralloc.h>
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorBlob : public C2Allocator {
+public:
+    virtual id_t getId() const override;
+
+    virtual C2String getName() const override;
+
+    virtual std::shared_ptr<const Traits> getTraits() const override;
+
+    virtual c2_status_t newLinearAllocation(
+            uint32_t capacity, C2MemoryUsage usage,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    virtual c2_status_t priorLinearAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+    C2AllocatorBlob(id_t id);
+
+    virtual ~C2AllocatorBlob() override;
+
+    static bool isValid(const C2Handle* const o);
+
+private:
+    std::shared_ptr<const Traits> mTraits;
+    // Design as C2AllocatorGralloc-backed to unify Gralloc implementations.
+    std::shared_ptr<C2Allocator> mC2AllocatorGralloc;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index f31282c..a14e0d3 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -66,6 +66,15 @@
         BUFFERQUEUE,
 
         /**
+         * ID of the gralloc backed platform allocator for linear blob buffer.
+         *
+         * C2Handle layout is not public. Use C2AllocatorGralloc::UnwrapNativeCodec2GrallocHandle
+         * to get the underlying gralloc handle from a C2Handle, and WrapNativeCodec2GrallocHandle
+         * to create a C2Handle from a gralloc handle - for C2Allocator::priorAllocation.
+         */
+        BLOB,
+
+        /**
          * ID of indicating the end of platform allocator definition.
          *
          * \note always put this macro in the last place.
@@ -131,6 +140,20 @@
  */
 void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> store);
 
+/**
+ * Returns the pool mask.
+ * \retval the default pool mask should be adopted if it could not be obtained from property
+ *         "debug.stagefright.c2-poolmask"
+ */
+int GetCodec2PoolMask();
+
+/**
+ * Returns the preferred linear buffer allocator id from param poolMask.
+ * C2PlatformAllocatorStore::ION should be chosen as fallback allocator if BLOB is not enabled from
+ * param poolMask.
+ */
+C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask);
+
 } // namespace android
 
 #endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/codec2/vndk/internal/C2HandleIonInternal.h b/media/codec2/vndk/internal/C2HandleIonInternal.h
new file mode 100644
index 0000000..c0e1d83
--- /dev/null
+++ b/media/codec2/vndk/internal/C2HandleIonInternal.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STAGEFRIGHT_CODEC2_ALLOCATION_ION_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATION_ION_H_
+
+#include <C2Buffer.h>
+
+namespace android {
+
+struct C2HandleIon : public C2Handle {
+    // ion handle owns ionFd(!) and bufferFd
+    C2HandleIon(int bufferFd, size_t size)
+        : C2Handle(cHeader),
+          mFds{ bufferFd },
+          mInts{ int(size & 0xFFFFFFFF), int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic } { }
+
+    static bool isValid(const C2Handle * const o);
+
+    int bufferFd() const { return mFds.mBuffer; }
+    size_t size() const {
+        return size_t(unsigned(mInts.mSizeLo))
+                | size_t(uint64_t(unsigned(mInts.mSizeHi)) << 32);
+    }
+
+protected:
+    struct {
+        int mBuffer; // shared ion buffer
+    } mFds;
+    struct {
+        int mSizeLo; // low 32-bits of size
+        int mSizeHi; // high 32-bits of size
+        int mMagic;
+    } mInts;
+
+private:
+    typedef C2HandleIon _type;
+    enum {
+        kMagic = '\xc2io\x00',
+        numFds = sizeof(mFds) / sizeof(int),
+        numInts = sizeof(mInts) / sizeof(int),
+        version = sizeof(C2Handle)
+    };
+    //constexpr static C2Handle cHeader = { version, numFds, numInts, {} };
+    const static C2Handle cHeader;
+};
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATION_ION_H_
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 8304f74..62936f6 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -576,10 +576,11 @@
             }
         }
         int migrated = 0;
+        // poolDatas dtor should not be called during lock is held.
+        std::shared_ptr<C2BufferQueueBlockPoolData>
+                poolDatas[NUM_BUFFER_SLOTS];
         {
             sp<GraphicBuffer> buffers[NUM_BUFFER_SLOTS];
-            std::weak_ptr<C2BufferQueueBlockPoolData>
-                    poolDatas[NUM_BUFFER_SLOTS];
             std::scoped_lock<std::mutex> lock(mMutex);
             bool noInit = false;
             for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
diff --git a/media/codec2/vndk/util/C2InterfaceUtils.cpp b/media/codec2/vndk/util/C2InterfaceUtils.cpp
index 61ec911..0c1729b 100644
--- a/media/codec2/vndk/util/C2InterfaceUtils.cpp
+++ b/media/codec2/vndk/util/C2InterfaceUtils.cpp
@@ -216,9 +216,14 @@
     if (limit.contains(minMask) && contains(minMask)) {
         values[0] = minMask;
         // keep only flags that are covered by limit
-        std::remove_if(values.begin(), values.end(), [&limit, minMask](const C2Value::Primitive &v) -> bool {
-            T value = v.ref<ValueType>() | minMask;
-            return value == minMask || !limit.contains(value); });
+        values.erase(std::remove_if(values.begin(), values.end(),
+                                    [&limit, minMask](
+                                        const C2Value::Primitive &v) -> bool {
+                                      T value = v.ref<ValueType>() | minMask;
+                                      return value == minMask ||
+                                             !limit.contains(value);
+                                    }),
+                     values.end());
         // we also need to do it vice versa
         for (const C2Value::Primitive &v : _mValues) {
             T value = v.ref<ValueType>() | minMask;
@@ -264,24 +269,33 @@
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedValueSet<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedRange<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
 template<typename T>
 C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedFlags<T> &limit) const {
     std::vector<C2Value::Primitive> values = _mValues; // make a copy
-    std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
-        return !limit.contains(v.ref<ValueType>()); });
+    values.erase(std::remove_if(values.begin(), values.end(),
+                                [&limit](const C2Value::Primitive &v) -> bool {
+                                  return !limit.contains(v.ref<ValueType>());
+                                }),
+                 values.end());
     return C2SupportedValueSet(std::move(values));
 }
 
diff --git a/media/extractors/Android.bp b/media/extractors/Android.bp
new file mode 100644
index 0000000..7c4e62f
--- /dev/null
+++ b/media/extractors/Android.bp
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+    name: "extractor-defaults",
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright/include",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libmediandk#29",
+    ],
+
+    // extractors are supposed to work on Q(29)
+    min_sdk_version: "29",
+
+    relative_install_path: "extractors",
+
+    compile_multilib: "first",
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-fvisibility=hidden",
+    ],
+
+    version_script: "exports.lds",
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
\ No newline at end of file
diff --git a/media/extractors/TEST_MAPPING b/media/extractors/TEST_MAPPING
new file mode 100644
index 0000000..abefb0f
--- /dev/null
+++ b/media/extractors/TEST_MAPPING
@@ -0,0 +1,17 @@
+{
+  "presubmit": [
+    // TODO(b/153661591) enable test once the bug is fixed
+    // This tests the extractor path
+    // {
+    //    "name": "GtsYouTubeTestCases",
+    //    "options" : [
+    //      {
+    //        "include-annotation": "android.platform.test.annotations.Presubmit"
+    //      },
+    //      {
+    //        "include-filter": "com.google.android.youtube.gts.SimultaneousClearAndProtectedDecodeTest#testSimultaneousClearAndProtectedDecode"
+    //      }
+    //    ]
+    //  }
+  ]
+}
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 5d00d94..8f60f6b 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -181,6 +181,8 @@
 }
 
 AACExtractor::~AACExtractor() {
+    mOffsetVector.clear();
+    delete mDataSource;
     if (mMeta != nullptr) {
         AMediaFormat_delete(mMeta);
     }
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index a58167a..60d3ae1 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -1,40 +1,13 @@
-cc_library_shared {
+cc_library {
+    name: "libaacextractor",
+    defaults: ["extractor-defaults"],
 
     srcs: ["AACExtractor.cpp"],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libmediandk",
-    ],
-
     static_libs: [
         "libstagefright_foundation",
         "libstagefright_metadatautils",
         "libutils",
     ],
 
-    name: "libaacextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index ffeff42..26431a4 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -144,6 +144,7 @@
 
 AMRExtractor::AMRExtractor(DataSourceHelper *source)
     : mDataSource(source),
+      mMeta(NULL),
       mInitCheck(NO_INIT),
       mOffsetTableLength(0) {
     float confidence;
@@ -191,7 +192,9 @@
 
 AMRExtractor::~AMRExtractor() {
     delete mDataSource;
-    AMediaFormat_delete(mMeta);
+    if (mMeta) {
+        AMediaFormat_delete(mMeta);
+    }
 }
 
 media_status_t AMRExtractor::getMetaData(AMediaFormat *meta) {
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 4bd933d..49c9567 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -1,38 +1,11 @@
-cc_library_shared {
+cc_library {
+    name: "libamrextractor",
+    defaults: ["extractor-defaults"],
 
     srcs: ["AMRExtractor.cpp"],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/include",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libmediandk",
-    ],
-
     static_libs: [
         "libstagefright_foundation",
     ],
 
-    name: "libamrextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 3a3d051..826c1a0 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -1,16 +1,16 @@
-cc_library_shared {
+cc_library {
+    name: "libflacextractor",
+    defaults: ["extractor-defaults"],
 
     srcs: ["FLACExtractor.cpp"],
 
     include_dirs: [
-        "frameworks/av/media/libstagefright/include",
         "external/flac/include",
     ],
 
     shared_libs: [
+        "libbase",
         "libbinder_ndk",
-        "liblog",
-        "libmediandk",
     ],
 
     static_libs: [
@@ -21,24 +21,4 @@
         "libutils",
     ],
 
-    name: "libflacextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 5329bd1..0617e88 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -24,6 +24,7 @@
 // libFLAC parser
 #include "FLAC/stream_decoder.h"
 
+#include <android-base/properties.h>
 #include <android/binder_ibinder.h> // for AIBinder_getCallingUid
 #include <audio_utils/primitives.h>
 #include <media/MediaExtractorPluginApi.h>
@@ -47,7 +48,8 @@
 // (Note: duplicated with WAVExtractor.cpp)
 static inline bool shouldExtractorOutputFloat(int bitsPerSample)
 {
-    return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA;
+    return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA
+                              && android::base::GetBoolProperty("media.extractor.float", true);
 }
 
 class FLACParser;
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 5a73d20..223d359 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -17,7 +17,6 @@
 #ifndef FLAC_EXTRACTOR_H_
 #define FLAC_EXTRACTOR_H_
 
-#include <media/DataSourceBase.h>
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
 #include <media/NdkMediaFormat.h>
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 91ce78e..b8255fc 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -1,40 +1,21 @@
-cc_library_shared {
+cc_library {
+    name: "libmidiextractor",
+    defaults: ["extractor-defaults"],
 
     srcs: ["MidiExtractor.cpp"],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/include",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libmediandk",
+    header_libs: [
+        "libmedia_headers",
     ],
 
     static_libs: [
         "libmedia_midiiowrapper",
-        "libsonivox",
+        "libsonivoxwithoutjet",
         "libstagefright_foundation",
         "libwatchdog",
+    ],
+
+    shared_libs: [
         "libbase",
     ],
-    name: "libmidiextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
 }
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 2e78086..b486fc6 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -17,7 +17,6 @@
 #ifndef MIDI_EXTRACTOR_H_
 #define MIDI_EXTRACTOR_H_
 
-#include <media/DataSourceBase.h>
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MediaBufferBase.h>
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 1744d3d..7ad8cc1 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -1,4 +1,6 @@
-cc_library_shared {
+cc_library {
+    name: "libmkvextractor",
+    defaults: ["extractor-defaults"],
 
     srcs: ["MatroskaExtractor.cpp"],
 
@@ -6,40 +8,17 @@
         "external/flac/include",
         "external/libvpx/libwebm",
         "frameworks/av/media/libstagefright/flac/dec",
-        "frameworks/av/media/libstagefright/include",
     ],
 
     shared_libs: [
-        "liblog",
-        "libmediandk",
+        "libstagefright_flacdec",
     ],
 
     static_libs: [
-        "libstagefright_flacdec",
         "libstagefright_foundation",
         "libstagefright_metadatautils",
         "libwebm",
         "libutils",
     ],
 
-    name: "libmkvextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 23022e4..b88e4e8 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -22,7 +22,7 @@
 #include "MatroskaExtractor.h"
 #include "common/webmids.h"
 
-#include <media/DataSourceBase.h>
+#include <media/stagefright/DataSourceBase.h>
 #include <media/ExtractorUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -339,7 +339,12 @@
 }
 
 void BlockIterator::advance_l() {
-    for (;;) {
+    for (int i = 0;; i++) {
+        if (i == 1000) {
+            ALOGE("no block found after %d iterations, stopping", i);
+            mCluster = NULL;
+            break;
+        }
         long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
         ALOGV("GetEntry returned %ld", res);
 
@@ -809,11 +814,13 @@
             int32_t sampleRate;
             if (!AMediaFormat_getInt32(trackInfo->mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE,
                                        &sampleRate)) {
+                mbuf->release();
                 return AMEDIA_ERROR_MALFORMED;
             }
             int64_t durationUs;
             if (!AMediaFormat_getInt64(trackInfo->mMeta, AMEDIAFORMAT_KEY_DURATION,
                                        &durationUs)) {
+                mbuf->release();
                 return AMEDIA_ERROR_MALFORMED;
             }
             // TODO: Explore if this can be handled similar to MPEG4 extractor where padding is
@@ -976,6 +983,7 @@
         while (mPendingFrames.empty()) {
             media_status_t err = readBlock();
             if (err != OK) {
+                buffer->release();
                 clearPendingFrames();
                 return err;
             }
@@ -995,6 +1003,7 @@
             while (mPendingFrames.empty()) {
                 media_status_t err = readBlock();
                 if (err != OK) {
+                    buffer->release();
                     clearPendingFrames();
                     return err;
                 }
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 4e2f248..102ac81 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -1,44 +1,16 @@
-cc_library_shared {
-
+cc_library {
+    name: "libmp3extractor",
+    defaults: ["extractor-defaults"],
     srcs: [
             "MP3Extractor.cpp",
             "VBRISeeker.cpp",
             "XINGSeeker.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/include",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libmediandk",
-    ],
-
     static_libs: [
         "libutils",
         "libstagefright_id3",
         "libstagefright_foundation",
     ],
 
-    name: "libmp3extractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index a838ae6..5165822 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -227,17 +227,17 @@
 
 private:
     static const size_t kMaxFrameSize;
-    AMediaFormat *mMeta;
-    DataSourceHelper *mDataSource;
-    off64_t mFirstFramePos;
-    uint32_t mFixedHeader;
-    off64_t mCurrentPos;
-    int64_t mCurrentTimeUs;
-    bool mStarted;
-    MP3Seeker *mSeeker;
+    AMediaFormat *mMeta = NULL;
+    DataSourceHelper *mDataSource = NULL;
+    off64_t mFirstFramePos = 0;
+    uint32_t mFixedHeader = 0;
+    off64_t mCurrentPos = 0;
+    int64_t mCurrentTimeUs = 0;
+    bool mStarted = false;
+    MP3Seeker *mSeeker = NULL;
 
-    int64_t mBasisTimeUs;
-    int64_t mSamplesRead;
+    int64_t mBasisTimeUs = 0;
+    int64_t mSamplesRead = 0;
 
     MP3Source(const MP3Source &);
     MP3Source &operator=(const MP3Source &);
@@ -251,11 +251,7 @@
 
 MP3Extractor::MP3Extractor(
         DataSourceHelper *source, Mp3Meta *meta)
-    : mInitCheck(NO_INIT),
-      mDataSource(source),
-      mFirstFramePos(-1),
-      mFixedHeader(0),
-      mSeeker(NULL) {
+    : mDataSource(source) {
 
     off64_t pos = 0;
     off64_t post_id3_pos;
@@ -442,6 +438,7 @@
 //  (8000 samples/sec * 8 bits/byte)) + 1 padding byte/frame = 2881 bytes/frame.
 // Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
 const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
+
 MP3Source::MP3Source(
         AMediaFormat *meta, DataSourceHelper *source,
         off64_t first_frame_pos, uint32_t fixed_header,
@@ -450,12 +447,7 @@
       mDataSource(source),
       mFirstFramePos(first_frame_pos),
       mFixedHeader(fixed_header),
-      mCurrentPos(0),
-      mCurrentTimeUs(0),
-      mStarted(false),
-      mSeeker(seeker),
-      mBasisTimeUs(0),
-      mSamplesRead(0) {
+      mSeeker(seeker) {
 }
 
 MP3Source::~MP3Source() {
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 1e38ab7..a2345da 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -45,13 +45,13 @@
     virtual const char * name() { return "MP3Extractor"; }
 
 private:
-    status_t mInitCheck;
+    status_t mInitCheck = NO_INIT;
 
-    DataSourceHelper *mDataSource;
-    off64_t mFirstFramePos;
-    AMediaFormat *mMeta;
-    uint32_t mFixedHeader;
-    MP3Seeker *mSeeker;
+    DataSourceHelper *mDataSource = NULL;
+    off64_t mFirstFramePos = -1;
+    AMediaFormat *mMeta = NULL;
+    uint32_t mFixedHeader = 0;
+    MP3Seeker *mSeeker = NULL;
 
     MP3Extractor(const MP3Extractor &);
     MP3Extractor &operator=(const MP3Extractor &);
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/extractors/mp4/AC4Parser.cpp
index 13d60c8..25fc4cd 100644
--- a/media/extractors/mp4/AC4Parser.cpp
+++ b/media/extractors/mp4/AC4Parser.cpp
@@ -600,6 +600,10 @@
         if (ac4_dsi_version == 1) {
             uint64_t end = (mDSISize - mBitReader.numBitsLeft()) / 8;
             uint64_t presentation_bytes = end - start;
+            if (pres_bytes < presentation_bytes) {
+                ALOGE("pres_bytes is smaller than presentation_bytes.");
+                return false;
+            }
             uint64_t skip_bytes = pres_bytes - presentation_bytes;
             ALOGV("skipping = %" PRIu64 " bytes", skip_bytes);
             CHECK_BITS_LEFT(skip_bytes * 8);
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 1b308aa..e48e1b7 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -1,5 +1,6 @@
-cc_defaults {
-    name: "libmp4extractor_defaults",
+cc_library {
+    name: "libmp4extractor",
+    defaults: ["extractor-defaults"],
 
     srcs: [
         "AC4Parser.cpp",
@@ -9,50 +10,10 @@
         "SampleTable.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libmediandk"
-    ],
-
     static_libs: [
         "libstagefright_esds",
         "libstagefright_foundation",
         "libstagefright_id3",
         "libutils",
     ],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-    relative_install_path: "extractors",
-    compile_multilib: "first",
-}
-
-cc_library_shared {
-
-
-    name: "libmp4extractor",
-    defaults: ["libmp4extractor_defaults"],
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
-}
-
-cc_library_static {
-    name: "libmp4extractor_fuzzing",
-
-    defaults: ["libmp4extractor_defaults"],
 }
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index 8c8e6d1..0773387 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -700,8 +700,8 @@
     }
 
 private:
-    uint32_t mWidth;
-    uint32_t mHeight;
+    int32_t mWidth;
+    int32_t mHeight;
 };
 
 status_t IspeBox::parse(off64_t offset, size_t size) {
@@ -715,12 +715,19 @@
     if (size < 8) {
         return ERROR_MALFORMED;
     }
-    if (!source()->getUInt32(offset, &mWidth)
-            || !source()->getUInt32(offset + 4, &mHeight)) {
+    if (!source()->getUInt32(offset, (uint32_t *)&mWidth)
+            || !source()->getUInt32(offset + 4, (uint32_t *)&mHeight)) {
         return ERROR_IO;
     }
-    ALOGV("property ispe: %dx%d", mWidth, mHeight);
 
+    // Validate that the dimension doesn't cause overflow on calculated max input size.
+    // Max input size is width*height*1.5, restrict width*height to 1<<29 so that
+    // we don't need to cast to int64_t when doing mults.
+    if (mWidth <= 0 || mHeight <= 0 || mWidth > (1 << 29) / mHeight) {
+        return ERROR_MALFORMED;
+    }
+
+    ALOGV("property ispe: %dx%d", mWidth, mHeight);
     return OK;
 }
 
@@ -1524,8 +1531,9 @@
             default: break; // don't set if invalid
         }
     }
+    // we validated no overflow in IspeBox::parse()
     AMediaFormat_setInt32(meta,
-            AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 1.5);
+            AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 3 / 2);
 
     if (!image->thumbnails.empty()) {
         ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(image->thumbnails[0]);
@@ -1561,8 +1569,9 @@
                 AMEDIAFORMAT_KEY_TILE_WIDTH, image->width);
         AMediaFormat_setInt32(meta,
                 AMEDIAFORMAT_KEY_TILE_HEIGHT, image->height);
+        // we validated no overflow in IspeBox::parse()
         AMediaFormat_setInt32(meta,
-                AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 1.5);
+                AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 3 / 2);
     }
 
     if (image->hvcc == NULL) {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 485c0cc..a976a2b 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -19,6 +19,8 @@
 
 #include <ctype.h>
 #include <inttypes.h>
+#include <algorithm>
+#include <map>
 #include <memory>
 #include <stdint.h>
 #include <stdlib.h>
@@ -31,9 +33,10 @@
 #include "MPEG4Extractor.h"
 #include "SampleTable.h"
 #include "ItemTable.h"
-#include "include/ESDS.h"
 
-#include <media/DataSourceBase.h>
+#include <ESDS.h>
+#include <ID3.h>
+#include <media/stagefright/DataSourceBase.h>
 #include <media/ExtractorUtils.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -52,7 +55,6 @@
 #include <utils/String8.h>
 
 #include <byteswap.h>
-#include "include/ID3.h"
 
 #ifndef UINT32_MAX
 #define UINT32_MAX       (4294967295U)
@@ -83,7 +85,8 @@
                 const Trex *trex,
                 off64_t firstMoofOffset,
                 const sp<ItemTable> &itemTable,
-                uint64_t elstShiftStartTicks);
+                uint64_t elstShiftStartTicks,
+                uint64_t elstInitialEmptyEditTicks);
     virtual status_t init();
 
     virtual media_status_t start();
@@ -111,6 +114,7 @@
     const Trex *mTrex;
     off64_t mFirstMoofOffset;
     off64_t mCurrentMoofOffset;
+    off64_t mCurrentMoofSize;
     off64_t mNextMoofOffset;
     uint32_t mCurrentTime; // in media timescale ticks
     int32_t mLastParsedTrackId;
@@ -133,6 +137,7 @@
 
     bool mIsAVC;
     bool mIsHEVC;
+    bool mIsDolbyVision;
     bool mIsAC4;
     bool mIsPcm;
     size_t mNALLengthSize;
@@ -145,11 +150,17 @@
 
     bool mIsHeif;
     bool mIsAudio;
+    bool mIsUsac = false;
     sp<ItemTable> mItemTable;
 
-    // Start offset from composition time to presentation time.
-    // Support shift only for video tracks through mElstShiftStartTicks for now.
+    /* Shift start offset (move to earlier time) when media_time > 0,
+     * in media time scale.
+     */
     uint64_t mElstShiftStartTicks;
+    /* Initial start offset (move to later time), empty edit list entry
+     * in media time scale.
+     */
+    uint64_t mElstInitialEmptyEditTicks;
 
     size_t parseNALSize(const uint8_t *data) const;
     status_t parseChunk(off64_t *offset);
@@ -157,8 +168,9 @@
     status_t parseTrackFragmentRun(off64_t offset, off64_t size);
     status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
     status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
-    status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags);
-    status_t parseSampleEncryption(off64_t offset);
+    status_t parseClearEncryptedSizes(off64_t offset, bool isSampleEncryption,
+            uint32_t flags, off64_t size);
+    status_t parseSampleEncryption(off64_t offset, off64_t size);
     // returns -1 for invalid layer ID
     int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
 
@@ -194,6 +206,7 @@
         Vector<size_t> encryptedsizes;
     };
     Vector<Sample> mCurrentSamples;
+    std::map<off64_t, uint32_t> mDrmOffsets;
 
     MPEG4Source(const MPEG4Source &);
     MPEG4Source &operator=(const MPEG4Source &);
@@ -337,6 +350,14 @@
         case FOURCC("hvc1"):
         case FOURCC("hev1"):
             return MEDIA_MIMETYPE_VIDEO_HEVC;
+
+        case FOURCC("dvav"):
+        case FOURCC("dva1"):
+        case FOURCC("dvhe"):
+        case FOURCC("dvh1"):
+        case FOURCC("dav1"):
+            return MEDIA_MIMETYPE_VIDEO_DOLBY_VISION;
+
         case FOURCC("ac-4"):
             return MEDIA_MIMETYPE_AUDIO_AC4;
         case FOURCC("Opus"):
@@ -475,12 +496,11 @@
         int64_t duration;
         int32_t samplerate;
         // Only for audio track.
-        if (track->has_elst && mHeaderTimescale != 0 &&
-                AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
-                AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
-
+        if (track->elst_needs_processing && mHeaderTimescale != 0 &&
+            AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
+            AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
             // Elst has to be processed only the first time this function is called.
-            track->has_elst = false;
+            track->elst_needs_processing = false;
 
             if (track->elst_segment_duration > INT64_MAX) {
                 return;
@@ -1064,6 +1084,68 @@
                     mLastTrack->mTx3gSize = 0;
                 }
 
+                const char *mime;
+                AMediaFormat_getString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, &mime);
+
+                if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+                    void *data;
+                    size_t size;
+
+                    if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+                        const uint8_t *ptr = (const uint8_t *)data;
+                        const uint8_t profile = ptr[2] >> 1;
+                        const uint8_t bl_compatibility_id = (ptr[4]) >> 4;
+                        bool create_two_tracks = false;
+
+                        if (bl_compatibility_id && bl_compatibility_id != 15) {
+                            create_two_tracks = true;
+                        }
+
+                        if (4 == profile || 7 == profile ||
+                                (profile >= 8 && profile < 11 && create_two_tracks)) {
+                            // we need a backward compatible track
+                            ALOGV("Adding new backward compatible track");
+                            Track *track_b = new Track;
+
+                            track_b->timescale = mLastTrack->timescale;
+                            track_b->sampleTable = mLastTrack->sampleTable;
+                            track_b->includes_expensive_metadata = mLastTrack->includes_expensive_metadata;
+                            track_b->skipTrack = mLastTrack->skipTrack;
+                            track_b->elst_needs_processing = mLastTrack->elst_needs_processing;
+                            track_b->elst_media_time = mLastTrack->elst_media_time;
+                            track_b->elst_segment_duration = mLastTrack->elst_segment_duration;
+                            track_b->elst_shift_start_ticks = mLastTrack->elst_shift_start_ticks;
+                            track_b->elst_initial_empty_edit_ticks = mLastTrack->elst_initial_empty_edit_ticks;
+                            track_b->subsample_encryption = mLastTrack->subsample_encryption;
+
+                            track_b->mTx3gBuffer = mLastTrack->mTx3gBuffer;
+                            track_b->mTx3gSize = mLastTrack->mTx3gSize;
+                            track_b->mTx3gFilled = mLastTrack->mTx3gFilled;
+
+                            track_b->meta = AMediaFormat_new();
+                            AMediaFormat_copy(track_b->meta, mLastTrack->meta);
+
+                            mLastTrack->next = track_b;
+                            track_b->next = NULL;
+
+                            auto id = track_b->meta->mFormat->findEntryByName(AMEDIAFORMAT_KEY_CSD_2);
+                            track_b->meta->mFormat->removeEntryAt(id);
+
+                            if (4 == profile || 7 == profile || 8 == profile ) {
+                                AMediaFormat_setString(track_b->meta,
+                                        AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_HEVC);
+                            } else if (9 == profile) {
+                                AMediaFormat_setString(track_b->meta,
+                                        AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
+                            } else if (10 == profile) {
+                                AMediaFormat_setString(track_b->meta,
+                                        AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
+                            } // Should never get to else part
+
+                            mLastTrack = track_b;
+                        }
+                    }
+                }
             } else if (chunk_type == FOURCC("moov")) {
                 mInitCheck = OK;
 
@@ -1136,39 +1218,73 @@
                 return ERROR_IO;
             }
 
-            if (entry_count != 1) {
-                // we only support a single entry at the moment, for gapless playback
-                // or start offset
+            if (entry_count > 2) {
+                /* We support a single entry for gapless playback or negating offset for
+                 * reordering B frames, two entries (empty edit) for start offset at the moment.
+                 */
                 ALOGW("ignoring edit list with %d entries", entry_count);
             } else {
                 off64_t entriesoffset = data_offset + 8;
                 uint64_t segment_duration;
                 int64_t media_time;
-
-                if (version == 1) {
-                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
-                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
-                        return ERROR_IO;
-                    }
-                } else if (version == 0) {
-                    uint32_t sd;
-                    int32_t mt;
-                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
+                bool empty_edit_present = false;
+                for (int i = 0; i < entry_count; ++i) {
+                    switch (version) {
+                    case 0: {
+                        uint32_t sd;
+                        int32_t mt;
+                        if (!mDataSource->getUInt32(entriesoffset, &sd) ||
                             !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
-                        return ERROR_IO;
+                            return ERROR_IO;
+                        }
+                        segment_duration = sd;
+                        media_time = mt;
+                        // 4(segment duration) + 4(media time) + 4(media rate)
+                        entriesoffset += 12;
+                        break;
                     }
-                    segment_duration = sd;
-                    media_time = mt;
-                } else {
-                    return ERROR_IO;
+                    case 1: {
+                        if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
+                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
+                            return ERROR_IO;
+                        }
+                        // 8(segment duration) + 8(media time) + 4(media rate)
+                        entriesoffset += 20;
+                        break;
+                    }
+                    default:
+                        return ERROR_IO;
+                        break;
+                    }
+                    // Empty edit entry would have to be first entry.
+                    if (media_time == -1 && i == 0) {
+                        empty_edit_present = true;
+                        ALOGV("initial empty edit ticks: %" PRIu64, segment_duration);
+                        /* In movie header timescale, and needs to be converted to media timescale
+                         * after we get that from a track's 'mdhd' atom,
+                         * which at times come after 'elst'.
+                         */
+                        mLastTrack->elst_initial_empty_edit_ticks = segment_duration;
+                    } else if (media_time >= 0 && i == 0) {
+                        ALOGV("first edit list entry - from gapless playback files");
+                        mLastTrack->elst_media_time = media_time;
+                        mLastTrack->elst_segment_duration = segment_duration;
+                        ALOGV("segment_duration: %" PRIu64 " media_time: %" PRId64,
+                              segment_duration, media_time);
+                        // media_time is in media timescale as are STTS/CTTS entries.
+                        mLastTrack->elst_shift_start_ticks = media_time;
+                    } else if (empty_edit_present && i == 1) {
+                        // Process second entry only when the first entry was an empty edit entry.
+                        ALOGV("second edit list entry");
+                        mLastTrack->elst_shift_start_ticks = media_time;
+                    } else {
+                        ALOGW("for now, unsupported entry in edit list %" PRIu32, entry_count);
+                    }
                 }
-
                 // save these for later, because the elst atom might precede
                 // the atoms that actually gives us the duration and sample rate
                 // needed to calculate the padding and delay values
-                mLastTrack->has_elst = true;
-                mLastTrack->elst_media_time = media_time;
-                mLastTrack->elst_segment_duration = segment_duration;
+                mLastTrack->elst_needs_processing = true;
             }
             break;
         }
@@ -1563,8 +1679,12 @@
         {
             *offset += chunk_size;
 
-            if (mLastTrack == NULL)
+            // the absolute minimum size of a compliant mett box is 11 bytes:
+            // 6 byte reserved, 2 byte index, null byte, one char mime_format, null byte
+            // The resulting mime_format would be invalid at that size though.
+            if (mLastTrack == NULL || chunk_data_size < 11) {
                 return ERROR_MALFORMED;
+            }
 
             auto buffer = heapbuffer<uint8_t>(chunk_data_size);
             if (buffer.get() == NULL) {
@@ -1576,10 +1696,24 @@
                 return ERROR_IO;
             }
 
+            // ISO-14496-12:
+            // int8 reserved[6];               // should be all zeroes
+            // int16_t data_reference_index;
+            // char content_encoding[];        // null terminated, optional (= just the null byte)
+            // char mime_format[];             // null terminated, mandatory
+            // optional other boxes
+            //
+            // API < 29:
+            // char mime_format[];             // null terminated
+            //
+            // API >= 29
+            // char mime_format[];             // null terminated
+            // char mime_format[];             // null terminated
+
             // Prior to API 29, the metadata track was not compliant with ISO/IEC
             // 14496-12-2015. This led to some ISO-compliant parsers failing to read the
             // metatrack. As of API 29 and onwards, a change was made to metadata track to
-            // make it compliant with the standard. The workaround is to write the
+            // make it somewhat compatible with the standard. The workaround is to write the
             // null-terminated mime_format string twice. This allows compliant parsers to
             // read the missing reserved, data_reference_index, and content_encoding fields
             // from the first mime_type string. The actual mime_format field would then be
@@ -1588,27 +1722,27 @@
             // as it would only read the first null-terminated mime_format string. To enable
             // reading metadata tracks generated from both the non-compliant and compliant
             // formats, a check needs to be done to see which format is used.
-            int null_pos = 0;
-            const unsigned char *str = buffer.get();
-            while (null_pos < chunk_data_size) {
-              if (*(str + null_pos) == '\0') {
-                break;
-              }
-              ++null_pos;
-            }
+            const char *str = (const char*) buffer.get();
+            size_t string_length = strnlen(str, chunk_data_size);
 
-            if (null_pos == chunk_data_size - 1) {
-              // This is not a standard ompliant metadata track.
-              String8 mimeFormat((const char *)(buffer.get()), chunk_data_size);
-              AMediaFormat_setString(mLastTrack->meta,
-                  AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+            if (string_length == chunk_data_size - 1) {
+                // This is likely a pre API 29 file, since it's a single null terminated
+                // string filling the entire box.
+                AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, str);
             } else {
-              // This is a standard compliant metadata track.
-              String8 contentEncoding((const char *)(buffer.get() + 8));
-              String8 mimeFormat((const char *)(buffer.get() + 8 + contentEncoding.size() + 1),
-                  chunk_data_size - 8 - contentEncoding.size() - 1);
-              AMediaFormat_setString(mLastTrack->meta,
-                  AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+                // This might be a fully compliant metadata track, a "double mime" compatibility
+                // track, or anything else, including a single non-terminated string, so we need
+                // to determine the length of each string we want to parse out of the box.
+                size_t encoding_length = strnlen(str + 8, chunk_data_size - 8);
+                if (encoding_length + 8 >= chunk_data_size - 2) {
+                    // the encoding extends to the end of the box, so there's no mime_format
+                    return ERROR_MALFORMED;
+                }
+                String8 contentEncoding(str + 8, encoding_length);
+                String8 mimeFormat(str + 8 + encoding_length + 1,
+                        chunk_data_size - 8 - encoding_length - 1);
+                AMediaFormat_setString(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
             }
             break;
         }
@@ -1832,6 +1966,11 @@
         case FOURCC("avc1"):
         case FOURCC("hvc1"):
         case FOURCC("hev1"):
+        case FOURCC("dvav"):
+        case FOURCC("dva1"):
+        case FOURCC("dvhe"):
+        case FOURCC("dvh1"):
+        case FOURCC("dav1"):
         case FOURCC("av01"):
         {
             uint8_t buffer[78];
@@ -1986,7 +2125,8 @@
                     // for audio, use 128KB
                     max_size = 1024 * 128;
                 } else if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
-                        || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+                        || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)
+                        || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
                     // AVC & HEVC requires compression ratio of at least 2, and uses
                     // macroblocks
                     max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
@@ -2317,6 +2457,33 @@
             *offset += chunk_size;
             break;
         }
+        case FOURCC("dvcC"):
+        case FOURCC("dvvC"): {
+
+            CHECK_EQ(chunk_data_size, 24);
+
+            auto buffer = heapbuffer<uint8_t>(chunk_data_size);
+
+            if (buffer.get() == NULL) {
+                ALOGE("b/28471206");
+                return NO_MEMORY;
+            }
+
+            if (mDataSource->readAt(data_offset, buffer.get(), chunk_data_size) < chunk_data_size) {
+                return ERROR_IO;
+            }
+
+            if (mLastTrack == NULL)
+                return ERROR_MALFORMED;
+
+            AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
+                                   buffer.get(), chunk_data_size);
+            AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME,
+                                   MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
+
+            *offset += chunk_size;
+            break;
+        }
         case FOURCC("d263"):
         {
             *offset += chunk_size;
@@ -2734,7 +2901,7 @@
                 return ERROR_MALFORMED;
             }
 
-            parseID3v2MetaData(data_offset + 6);
+            parseID3v2MetaData(data_offset + 6, chunk_data_size - 6);
 
             break;
         }
@@ -3650,43 +3817,44 @@
     switch ((int32_t)mPath[4]) {
         case FOURCC("\251alb"):
         {
-            metadataKey = "album";
+            metadataKey = AMEDIAFORMAT_KEY_ALBUM;
             break;
         }
         case FOURCC("\251ART"):
         {
-            metadataKey = "artist";
+            metadataKey = AMEDIAFORMAT_KEY_ARTIST;
             break;
         }
         case FOURCC("aART"):
         {
-            metadataKey = "albumartist";
+            metadataKey = AMEDIAFORMAT_KEY_ALBUMARTIST;
             break;
         }
         case FOURCC("\251day"):
         {
-            metadataKey = "year";
+            metadataKey = AMEDIAFORMAT_KEY_YEAR;
             break;
         }
         case FOURCC("\251nam"):
         {
-            metadataKey = "title";
+            metadataKey = AMEDIAFORMAT_KEY_TITLE;
             break;
         }
         case FOURCC("\251wrt"):
         {
-            metadataKey = "writer";
+            // various open source taggers agree that the "©wrt" tag is for composer, not writer
+            metadataKey = AMEDIAFORMAT_KEY_COMPOSER;
             break;
         }
         case FOURCC("covr"):
         {
-            metadataKey = "albumart";
+            metadataKey = AMEDIAFORMAT_KEY_ALBUMART;
             break;
         }
         case FOURCC("gnre"):
         case FOURCC("\251gen"):
         {
-            metadataKey = "genre";
+            metadataKey = AMEDIAFORMAT_KEY_GENRE;
             break;
         }
         case FOURCC("cpil"):
@@ -3791,7 +3959,7 @@
         if (!strcmp(metadataKey, "albumart")) {
             AMediaFormat_setBuffer(mFileMetaData, metadataKey,
                     buffer + 8, size - 8);
-        } else if (!strcmp(metadataKey, "genre")) {
+        } else if (!strcmp(metadataKey, AMEDIAFORMAT_KEY_GENRE)) {
             if (flags == 0) {
                 // uint8_t genre code, iTunes genre codes are
                 // the standard id3 codes, except they start
@@ -4005,8 +4173,19 @@
     return OK;
 }
 
-void MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
-    ID3 id3(mDataSource, true /* ignorev1 */, offset);
+void MPEG4Extractor::parseID3v2MetaData(off64_t offset, uint64_t size) {
+    uint8_t *buffer = new (std::nothrow) uint8_t[size];
+    if (buffer == NULL) {
+        return;
+    }
+    if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
+        delete[] buffer;
+        buffer = NULL;
+        return;
+    }
+
+    ID3 id3(buffer, size, true /* ignorev1 */);
+    delete[] buffer;
 
     if (id3.isValid()) {
         struct Map {
@@ -4133,7 +4312,20 @@
         if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
             itemTable = mItemTable;
         }
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+        void *data;
+        size_t size;
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+            return NULL;
+        }
+
+        const uint8_t *ptr = (const uint8_t *)data;
+
+        // dv_major.dv_minor Should be 1.0 or 2.1
+        if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+            return NULL;
+        }
+   } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
         void *data;
         size_t size;
         if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
@@ -4147,15 +4339,28 @@
         }
     }
 
-    if (track->has_elst and !strncasecmp("video/", mime, 6) and track->elst_media_time > 0) {
-        track->elstShiftStartTicks = track->elst_media_time;
-        ALOGV("video track->elstShiftStartTicks :%" PRIu64, track->elstShiftStartTicks);
-    }
+    ALOGV("track->elst_shift_start_ticks :%" PRIu64, track->elst_shift_start_ticks);
 
-    MPEG4Source *source =  new MPEG4Source(
-            track->meta, mDataSource, track->timescale, track->sampleTable,
-            mSidxEntries, trex, mMoofOffset, itemTable,
-            track->elstShiftStartTicks);
+    uint64_t elst_initial_empty_edit_ticks = 0;
+    if (mHeaderTimescale != 0) {
+        // Convert empty_edit_ticks from movie timescale to media timescale.
+        uint64_t elst_initial_empty_edit_ticks_mul = 0, elst_initial_empty_edit_ticks_add = 0;
+        if (__builtin_mul_overflow(track->elst_initial_empty_edit_ticks, track->timescale,
+                                   &elst_initial_empty_edit_ticks_mul) ||
+            __builtin_add_overflow(elst_initial_empty_edit_ticks_mul, (mHeaderTimescale / 2),
+                                   &elst_initial_empty_edit_ticks_add)) {
+            ALOGE("track->elst_initial_empty_edit_ticks overflow");
+            return nullptr;
+        }
+        elst_initial_empty_edit_ticks = elst_initial_empty_edit_ticks_add / mHeaderTimescale;
+    }
+    ALOGV("elst_initial_empty_edit_ticks in MediaTimeScale :%" PRIu64,
+          elst_initial_empty_edit_ticks);
+
+    MPEG4Source* source =
+            new MPEG4Source(track->meta, mDataSource, track->timescale, track->sampleTable,
+                            mSidxEntries, trex, mMoofOffset, itemTable,
+                            track->elst_shift_start_ticks, elst_initial_empty_edit_ticks);
     if (source->init() != OK) {
         delete source;
         return NULL;
@@ -4178,6 +4383,10 @@
         if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size)) {
             return ERROR_MALFORMED;
         }
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+            return ERROR_MALFORMED;
+        }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
         if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
             return ERROR_MALFORMED;
@@ -4249,7 +4458,7 @@
     //AOT_SLS              = 38, /**< SLS                                       */
     //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
 
-    //AOT_USAC             = 42, /**< USAC                                      */
+    AOT_USAC               = 42, /**< USAC                                      */
     //AOT_SAOC             = 43, /**< SAOC                                      */
     //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
 
@@ -4397,7 +4606,7 @@
     ABitReader br(csd, csd_size);
     uint32_t objectType = br.getBits(5);
 
-    if (objectType == 31) {  // AAC-ELD => additional 6 bits
+    if (objectType == AOT_ESCAPE) {  // AAC-ELD => additional 6 bits
         objectType = 32 + br.getBits(6);
     }
 
@@ -4644,7 +4853,8 @@
         const Trex *trex,
         off64_t firstMoofOffset,
         const sp<ItemTable> &itemTable,
-        uint64_t elstShiftStartTicks)
+        uint64_t elstShiftStartTicks,
+        uint64_t elstInitialEmptyEditTicks)
     : mFormat(format),
       mDataSource(dataSource),
       mTimescale(timeScale),
@@ -4655,6 +4865,7 @@
       mTrex(trex),
       mFirstMoofOffset(firstMoofOffset),
       mCurrentMoofOffset(firstMoofOffset),
+      mCurrentMoofSize(0),
       mNextMoofOffset(-1),
       mCurrentTime(0),
       mDefaultEncryptedByteBlock(0),
@@ -4665,6 +4876,7 @@
       mCurrentSampleInfoOffsets(NULL),
       mIsAVC(false),
       mIsHEVC(false),
+      mIsDolbyVision(false),
       mIsAC4(false),
       mIsPcm(false),
       mNALLengthSize(0),
@@ -4673,7 +4885,8 @@
       mSrcBuffer(NULL),
       mIsHeif(itemTable != NULL),
       mItemTable(itemTable),
-      mElstShiftStartTicks(elstShiftStartTicks) {
+      mElstShiftStartTicks(elstShiftStartTicks),
+      mElstInitialEmptyEditTicks(elstInitialEmptyEditTicks) {
 
     memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
 
@@ -4704,6 +4917,7 @@
     mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
               !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
     mIsAC4 = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC4);
+    mIsDolbyVision = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
 
     if (mIsAVC) {
         void *data;
@@ -4728,11 +4942,53 @@
         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
 
         mNALLengthSize = 1 + (ptr[14 + 7] & 3);
+    } else if (mIsDolbyVision) {
+        ALOGV("%s DolbyVision stream detected", __FUNCTION__);
+        void *data;
+        size_t size;
+        CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_2, &data, &size));
+
+        const uint8_t *ptr = (const uint8_t *)data;
+
+        CHECK(size == 24);
+
+        // dv_major.dv_minor Should be 1.0 or 2.1
+        CHECK(!((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)));
+
+        const uint8_t profile = ptr[2] >> 1;
+        // profile == (unknown,1,9) --> AVC; profile = (2,3,4,5,6,7,8) --> HEVC;
+        // profile == (10) --> AV1
+        if (profile > 1 && profile < 9) {
+            CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size));
+
+            const uint8_t *ptr = (const uint8_t *)data;
+
+            CHECK(size >= 22);
+            CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
+
+            mNALLengthSize = 1 + (ptr[14 + 7] & 3);
+        } else if (10 == profile) {
+            /* AV1 profile nothing to do */
+        } else {
+            CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_AVC, &data, &size));
+            const uint8_t *ptr = (const uint8_t *)data;
+
+            CHECK(size >= 7);
+            CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
+            // The number of bytes used to encode the length of a NAL unit.
+            mNALLengthSize = 1 + (ptr[4] & 3);
+        }
     }
 
     mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
     mIsAudio = !strncasecmp(mime, "audio/", 6);
 
+    int32_t aacObjectType = -1;
+
+    if (AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_AAC_PROFILE, &aacObjectType)) {
+        mIsUsac = (aacObjectType == AOT_USAC);
+    }
+
     if (mIsPcm) {
         int32_t numChannels = 0;
         int32_t bitsPerSample = 0;
@@ -4755,35 +5011,14 @@
     }
 
     CHECK(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_TRACK_ID, &mTrackId));
-
 }
 
 status_t MPEG4Source::init() {
-    status_t err = OK;
-    const char *mime;
-    CHECK(AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime));
     if (mFirstMoofOffset != 0) {
         off64_t offset = mFirstMoofOffset;
-        err = parseChunk(&offset);
-        if(err == OK && !strncasecmp("video/", mime, 6)
-            && !mCurrentSamples.isEmpty()) {
-            // Start offset should be less or equal to composition time of first sample.
-            // ISO : sample_composition_time_offset, version 0 (unsigned) for major brands.
-            mElstShiftStartTicks = std::min(mElstShiftStartTicks,
-                                            (uint64_t)(*mCurrentSamples.begin()).compositionOffset);
-        }
-        return err;
+        return parseChunk(&offset);
     }
-
-    if (!strncasecmp("video/", mime, 6)) {
-        uint64_t firstSampleCTS = 0;
-        err = mSampleTable->getMetaDataForSample(0, NULL, NULL, &firstSampleCTS);
-        // Start offset should be less or equal to composition time of first sample.
-        // Composition time stamp of first sample cannot be negative.
-        mElstShiftStartTicks = std::min(mElstShiftStartTicks, firstSampleCTS);
-    }
-
-    return err;
+    return OK;
 }
 
 MPEG4Source::~MPEG4Source() {
@@ -4887,6 +5122,9 @@
         case FOURCC("moof"): {
             off64_t stop_offset = *offset + chunk_size;
             *offset = data_offset;
+            if (chunk_type == FOURCC("moof")) {
+                mCurrentMoofSize = chunk_data_size;
+            }
             while (*offset < stop_offset) {
                 status_t err = parseChunk(offset);
                 if (err != OK) {
@@ -4925,6 +5163,9 @@
                     if (chunk_type == FOURCC("moof")) {
                         mNextMoofOffset = *offset;
                         break;
+                    } else if (chunk_type == FOURCC("mdat")) {
+                        parseChunk(offset);
+                        continue;
                     } else if (chunk_size == 0) {
                         break;
                     }
@@ -4975,7 +5216,7 @@
 
         case FOURCC("senc"): {
             status_t err;
-            if ((err = parseSampleEncryption(data_offset)) != OK) {
+            if ((err = parseSampleEncryption(data_offset, chunk_data_size)) != OK) {
                 return err;
             }
             *offset += chunk_size;
@@ -4986,6 +5227,22 @@
             // parse DRM info if present
             ALOGV("MPEG4Source::parseChunk mdat");
             // if saiz/saoi was previously observed, do something with the sampleinfos
+            status_t err = OK;
+            auto kv = mDrmOffsets.lower_bound(*offset);
+            if (kv != mDrmOffsets.end()) {
+                auto drmoffset = kv->first;
+                auto flags = kv->second;
+                mDrmOffsets.erase(kv);
+                ALOGV("mdat chunk_size %" PRIu64 " drmoffset %" PRId64 " offset %" PRId64,
+                        chunk_size, drmoffset, *offset);
+                if (chunk_size >= drmoffset - *offset) {
+                    err = parseClearEncryptedSizes(drmoffset, false, flags,
+                        chunk_size - (drmoffset - *offset));
+                }
+            }
+            if (err != OK) {
+                return err;
+            }
             *offset += chunk_size;
             break;
         }
@@ -5167,12 +5424,14 @@
     off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
 
     drmoffset += mCurrentMoofOffset;
+    mDrmOffsets[drmoffset] = flags;
+    ALOGV("saio drmoffset %" PRId64 " flags %u", drmoffset, flags);
 
-    return parseClearEncryptedSizes(drmoffset, false, 0);
+    return OK;
 }
 
 status_t MPEG4Source::parseClearEncryptedSizes(
-        off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
+        off64_t offset, bool isSampleEncryption, uint32_t flags, off64_t size) {
 
     int32_t ivlength;
     if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
@@ -5186,11 +5445,15 @@
     }
 
     uint32_t sampleCount = mCurrentSampleInfoCount;
-    if (isSubsampleEncryption) {
+    if (isSampleEncryption) {
+        if (size < 4) {
+            return ERROR_MALFORMED;
+        }
         if (!mDataSource->getUInt32(offset, &sampleCount)) {
             return ERROR_IO;
         }
         offset += 4;
+        size -= 4;
     }
 
     // read CencSampleAuxiliaryDataFormats
@@ -5205,14 +5468,18 @@
         }
 
         memset(smpl->iv, 0, 16);
+        if (size < ivlength) {
+            return ERROR_MALFORMED;
+        }
         if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
             return ERROR_IO;
         }
 
         offset += ivlength;
+        size -= ivlength;
 
         bool readSubsamples;
-        if (isSubsampleEncryption) {
+        if (isSampleEncryption) {
             readSubsamples = flags & 2;
         } else {
             int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
@@ -5224,13 +5491,20 @@
 
         if (readSubsamples) {
             uint16_t numsubsamples;
+            if (size < 2) {
+                return ERROR_MALFORMED;
+            }
             if (!mDataSource->getUInt16(offset, &numsubsamples)) {
                 return ERROR_IO;
             }
             offset += 2;
+            size -= 2;
             for (size_t j = 0; j < numsubsamples; j++) {
                 uint16_t numclear;
                 uint32_t numencrypted;
+                if (size < 6) {
+                    return ERROR_MALFORMED;
+                }
                 if (!mDataSource->getUInt16(offset, &numclear)) {
                     return ERROR_IO;
                 }
@@ -5239,6 +5513,7 @@
                     return ERROR_IO;
                 }
                 offset += 4;
+                size -= 6;
                 smpl->clearsizes.add(numclear);
                 smpl->encryptedsizes.add(numencrypted);
             }
@@ -5251,12 +5526,15 @@
     return OK;
 }
 
-status_t MPEG4Source::parseSampleEncryption(off64_t offset) {
+status_t MPEG4Source::parseSampleEncryption(off64_t offset, off64_t chunk_data_size) {
     uint32_t flags;
+    if (chunk_data_size < 4) {
+        return ERROR_MALFORMED;
+    }
     if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
         return ERROR_MALFORMED;
     }
-    return parseClearEncryptedSizes(offset + 4, true, flags);
+    return parseClearEncryptedSizes(offset + 4, true, flags, chunk_data_size - 4);
 }
 
 status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
@@ -5445,20 +5723,30 @@
 
     if (flags & kSampleSizePresent) {
         bytesPerSample += 4;
-    } else if (mTrackFragmentHeaderInfo.mFlags
-            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
-        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
     } else {
         sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
+#ifdef VERY_VERY_VERBOSE_LOGGING
+        // We don't expect this, but also want to avoid spamming the log if
+        // we hit this case.
+        if (!(mTrackFragmentHeaderInfo.mFlags
+              & TrackFragmentHeaderInfo::kDefaultSampleSizePresent)) {
+            ALOGW("No sample size specified");
+        }
+#endif
     }
 
     if (flags & kSampleFlagsPresent) {
         bytesPerSample += 4;
-    } else if (mTrackFragmentHeaderInfo.mFlags
-            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
-        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
     } else {
         sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
+#ifdef VERY_VERY_VERBOSE_LOGGING
+        // We don't expect this, but also want to avoid spamming the log if
+        // we hit this case.
+        if (!(mTrackFragmentHeaderInfo.mFlags
+              & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent)) {
+            ALOGW("No sample flags specified");
+        }
+#endif
     }
 
     if (flags & kSampleCompositionTimeOffsetPresent) {
@@ -5621,8 +5909,9 @@
 
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
 
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        ALOGV("seekTimeUs:%" PRId64, seekTimeUs);
         if (mIsHeif) {
             CHECK(mSampleTable == NULL);
             CHECK(mItemTable != NULL);
@@ -5661,7 +5950,22 @@
                     break;
             }
             if( mode != ReadOptions::SEEK_FRAME_INDEX) {
-                seekTimeUs += ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
+                int64_t elstInitialEmptyEditUs = 0, elstShiftStartUs = 0;
+                if (mElstInitialEmptyEditTicks > 0) {
+                    elstInitialEmptyEditUs = ((long double)mElstInitialEmptyEditTicks * 1000000) /
+                                             mTimescale;
+                    /* Sample's composition time from ctts/stts entries are non-negative(>=0).
+                     * Hence, lower bound on seekTimeUs is 0.
+                     */
+                    seekTimeUs = std::max(seekTimeUs - elstInitialEmptyEditUs, (int64_t)0);
+                }
+                if (mElstShiftStartTicks > 0) {
+                    elstShiftStartUs = ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
+                    seekTimeUs += elstShiftStartUs;
+                }
+                ALOGV("shifted seekTimeUs:%" PRId64 ", elstInitialEmptyEditUs:%" PRIu64
+                      ", elstShiftStartUs:%" PRIu64, seekTimeUs, elstInitialEmptyEditUs,
+                      elstShiftStartUs);
             }
 
             uint32_t sampleIndex;
@@ -5678,10 +5982,10 @@
             }
 
             uint32_t syncSampleIndex = sampleIndex;
-            // assume every audio sample is a sync sample. This works around
+            // assume every non-USAC audio sample is a sync sample. This works around
             // seek issues with files that were incorrectly written with an
             // empty or single-sample stss block for the audio track
-            if (err == OK && !mIsAudio) {
+            if (err == OK && (!mIsAudio || mIsUsac)) {
                 err = mSampleTable->findSyncSampleNear(
                         sampleIndex, &syncSampleIndex, findFlags);
             }
@@ -5707,7 +6011,16 @@
 
             if (mode == ReadOptions::SEEK_CLOSEST
                 || mode == ReadOptions::SEEK_FRAME_INDEX) {
-                sampleTime -= mElstShiftStartTicks;
+                if (mElstInitialEmptyEditTicks > 0) {
+                    sampleTime += mElstInitialEmptyEditTicks;
+                }
+                if (mElstShiftStartTicks > 0){
+                    if (sampleTime > mElstShiftStartTicks) {
+                        sampleTime -= mElstShiftStartTicks;
+                    } else {
+                        sampleTime = 0;
+                    }
+                }
                 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
             }
 
@@ -5736,7 +6049,8 @@
 
     off64_t offset = 0;
     size_t size = 0;
-    uint64_t cts, stts;
+    int64_t cts;
+    uint64_t stts;
     bool isSyncSample;
     bool newBuffer = false;
     if (mBuffer == NULL) {
@@ -5744,16 +6058,17 @@
 
         status_t err;
         if (!mIsHeif) {
-            err = mSampleTable->getMetaDataForSample(
-                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
+            err = mSampleTable->getMetaDataForSample(mCurrentSampleIndex, &offset, &size,
+                                                    (uint64_t*)&cts, &isSyncSample, &stts);
             if(err == OK) {
-                /* Composition Time Stamp cannot be negative. Some files have video Sample
-                * Time(STTS)delta with zero value(b/117402420).  Hence subtract only
-                * min(cts, mElstShiftStartTicks), so that audio tracks can be played.
-                */
-                cts -= std::min(cts, mElstShiftStartTicks);
+                if (mElstInitialEmptyEditTicks > 0) {
+                    cts += mElstInitialEmptyEditTicks;
+                }
+                if (mElstShiftStartTicks > 0) {
+                    // cts can be negative. for example, initial audio samples for gapless playback.
+                    cts -= (int64_t)mElstShiftStartTicks;
+                }
             }
-
         } else {
             err = mItemTable->getImageOffsetAndSize(
                     options && options->getSeekTo(&seekTimeUs, &mode) ?
@@ -5785,7 +6100,7 @@
         }
     }
 
-    if (!mIsAVC && !mIsHEVC && !mIsAC4) {
+    if (!mIsAVC && !mIsHEVC && !(mIsDolbyVision && mNALLengthSize) && !mIsAC4) {
         if (newBuffer) {
             if (mIsPcm) {
                 // The twos' PCM block reader assumes that all samples has the same size.
@@ -5816,11 +6131,11 @@
                       meta, AMEDIAFORMAT_KEY_TIME_US, ((long double)cts * 1000000) / mTimescale);
                 AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
-                int32_t byteOrder;
-                AMediaFormat_getInt32(mFormat,
+                int32_t byteOrder = 0;
+                bool isGetBigEndian = AMediaFormat_getInt32(mFormat,
                         AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &byteOrder);
 
-                if (byteOrder == 1) {
+                if (isGetBigEndian && byteOrder == 1) {
                     // Big-endian -> little-endian
                     uint16_t *dstData = (uint16_t *)buf;
                     uint16_t *srcData = (uint16_t *)buf;
@@ -6033,10 +6348,23 @@
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-
-        seekTimeUs += ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
-        ALOGV("shifted seekTimeUs :%" PRId64 ", mElstShiftStartTicks:%" PRIu64, seekTimeUs,
-              mElstShiftStartTicks);
+        ALOGV("seekTimeUs:%" PRId64, seekTimeUs);
+        int64_t elstInitialEmptyEditUs = 0, elstShiftStartUs = 0;
+        if (mElstInitialEmptyEditTicks > 0) {
+            elstInitialEmptyEditUs = ((long double)mElstInitialEmptyEditTicks * 1000000) /
+                                     mTimescale;
+            /* Sample's composition time from ctts/stts entries are non-negative(>=0).
+             * Hence, lower bound on seekTimeUs is 0.
+             */
+            seekTimeUs = std::max(seekTimeUs - elstInitialEmptyEditUs, (int64_t)0);
+        }
+        if (mElstShiftStartTicks > 0){
+            elstShiftStartUs = ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
+            seekTimeUs += elstShiftStartUs;
+        }
+        ALOGV("shifted seekTimeUs:%" PRId64 ", elstInitialEmptyEditUs:%" PRIu64
+              ", elstShiftStartUs:%" PRIu64, seekTimeUs, elstInitialEmptyEditUs,
+              elstShiftStartUs);
 
         int numSidxEntries = mSegments.size();
         if (numSidxEntries != 0) {
@@ -6092,7 +6420,7 @@
 
     off64_t offset = 0;
     size_t size = 0;
-    uint64_t cts = 0;
+    int64_t cts = 0;
     bool isSyncSample = false;
     bool newBuffer = false;
     if (mBuffer == NULL || mCurrentSampleIndex >= mCurrentSamples.size()) {
@@ -6124,11 +6452,14 @@
         offset = smpl->offset;
         size = smpl->size;
         cts = mCurrentTime + smpl->compositionOffset;
-        /* Composition Time Stamp cannot be negative. Some files have video Sample
-        * Time(STTS)delta with zero value(b/117402420).  Hence subtract only
-        * min(cts, mElstShiftStartTicks), so that audio tracks can be played.
-        */
-        cts -= std::min(cts, mElstShiftStartTicks);
+
+        if (mElstInitialEmptyEditTicks > 0) {
+            cts += mElstInitialEmptyEditTicks;
+        }
+        if (mElstShiftStartTicks > 0) {
+            // cts can be negative. for example, initial audio samples for gapless playback.
+            cts -= (int64_t)mElstShiftStartTicks;
+        }
 
         mCurrentTime += smpl->duration;
         isSyncSample = (mCurrentSampleIndex == 0);
@@ -6175,7 +6506,7 @@
         AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_IV, iv, ivlength);
     }
 
-    if (!mIsAVC && !mIsHEVC) {
+    if (!mIsAVC && !mIsHEVC && !(mIsDolbyVision && mNALLengthSize)) {
         if (newBuffer) {
             if (!isInRange((size_t)0u, mBuffer->size(), size)) {
                 mBuffer->release();
@@ -6449,6 +6780,12 @@
                 // The smallest valid chunk is 16 bytes long in this case.
                 return false;
             }
+            if (chunkSize > INT64_MAX) {
+                // reject overly large chunk sizes that could
+                // be interpreted as negative
+                ALOGE("chunk size too large");
+                return false;
+            }
 
         } else if (chunkSize < 8) {
             // The smallest valid chunk is 8 bytes long.
@@ -6504,7 +6841,10 @@
 
             case FOURCC("moov"):
             {
-                moovAtomEndOffset = offset + chunkSize;
+                if (__builtin_add_overflow(offset, chunkSize, &moovAtomEndOffset)) {
+                    ALOGE("chunk size + offset would overflow");
+                    return false;
+                }
 
                 done = true;
                 break;
@@ -6514,7 +6854,10 @@
                 break;
         }
 
-        offset += chunkSize;
+        if (__builtin_add_overflow(offset, chunkSize, &offset)) {
+            ALOGE("chunk size + offset would overflow");
+            return false;
+        }
     }
 
     if (!foundGoodFileType) {
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index fcddbb8..1e49d50 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -82,14 +82,16 @@
         sp<SampleTable> sampleTable;
         bool includes_expensive_metadata;
         bool skipTrack;
-        bool has_elst;
+        bool elst_needs_processing;
         /* signed int, ISO Spec allows media_time = -1 for other use cases.
          * but we don't support empty edits for now.
          */
         int64_t elst_media_time;
         uint64_t elst_segment_duration;
-        // unsigned int, shift start offset only when media_time > 0.
-        uint64_t elstShiftStartTicks;
+        // Shift start offset (move to earlier time) when media_time > 0.
+        uint64_t elst_shift_start_ticks;
+        // Initial start offset (move to later time), from empty edit list entry.
+        uint64_t elst_initial_empty_edit_ticks;
         bool subsample_encryption;
 
         uint8_t *mTx3gBuffer;
@@ -102,9 +104,11 @@
             timescale = 0;
             includes_expensive_metadata = false;
             skipTrack = false;
-            has_elst = false;
+            elst_needs_processing = false;
             elst_media_time = 0;
-            elstShiftStartTicks = 0;
+            elst_segment_duration = 0;
+            elst_shift_start_ticks = 0;
+            elst_initial_empty_edit_ticks = 0;
             subsample_encryption = false;
             mTx3gBuffer = NULL;
             mTx3gSize = mTx3gFilled = 0;
@@ -157,7 +161,7 @@
     status_t parseITunesMetaData(off64_t offset, size_t size);
     status_t parseColorInfo(off64_t offset, size_t size);
     status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
-    void parseID3v2MetaData(off64_t offset);
+    void parseID3v2MetaData(off64_t offset, uint64_t size);
     status_t parseQTMetaKey(off64_t data_offset, size_t data_size);
     status_t parseQTMetaVal(int32_t keyId, off64_t data_offset, size_t data_size);
 
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/extractors/mp4/SampleIterator.cpp
index 2890b26..85fbf97 100644
--- a/media/extractors/mp4/SampleIterator.cpp
+++ b/media/extractors/mp4/SampleIterator.cpp
@@ -22,7 +22,6 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 
@@ -355,7 +354,7 @@
     if (offset > 0) {
         *time += offset;
     } else {
-        *time -= (offset == INT64_MIN ? INT64_MAX : (-offset));
+        *time -= (offset == INT32_MIN ? INT64_MAX : (-offset));
     }
 
     *duration = mTTSDuration;
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index e7e8901..a00812b 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -652,11 +652,13 @@
     }
 
     mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
+
     if (!mSampleTimeEntries) {
         ALOGE("Cannot allocate sample entry table with %llu entries.",
                 (unsigned long long)mNumSampleSizes);
         return;
     }
+    memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
 
     uint32_t sampleIndex = 0;
     uint64_t sampleTime = 0;
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 0f0c72c..bc8632c 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -1,4 +1,7 @@
-cc_library_shared {
+cc_library {
+    name: "libmpeg2extractor",
+
+    defaults: ["extractor-defaults"],
 
     srcs: [
         "ExtractorBundle.cpp",
@@ -6,55 +9,47 @@
         "MPEG2TSExtractor.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-        "frameworks/av/media/libstagefright/include",
-    ],
-
     shared_libs: [
-        "android.hardware.cas@1.0",
-        "android.hardware.cas.native@1.0",
-        "android.hidl.token@1.0-utils",
-        "android.hidl.allocator@1.0",
-        "libhidlmemory",
-        "libhidlbase",
-        "liblog",
-        "libmediandk",
+        "libbase",
+        "libcgrouprc#29",
+        "libvndksupport#29",
     ],
 
     header_libs: [
+        "libaudioclient_headers",
         "libbase_headers",
         "libstagefright_headers",
         "libmedia_headers",
     ],
 
     static_libs: [
-        "libcrypto",
+        "android.hardware.cas@1.0",
+        "android.hardware.cas.native@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "android.hidl.token@1.0",
+        "android.hidl.token@1.0-utils",
+        "libcutils",
+        "libhidlbase",
+        "libhidlmemory",
+        "libjsoncpp",
+        "libprocessgroup",
+        "libstagefright_esds",
         "libstagefright_foundation_without_imemory",
+        "libstagefright_mpeg2extractor",
         "libstagefright_mpeg2support",
         "libutils",
-        "libstagefright_mpeg2extractor",
-        "libstagefright_esds",
     ],
 
-    name: "libmpeg2extractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
+    apex_available: [
+        "com.android.media",
+        "test_com.android.media",
     ],
-    version_script: "exports.lds",
 
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
+    static: {
+        apex_available: [
+            // Needed for unit tests
+            "//apex_available:platform",
         ],
     },
-
 }
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 731584d..d431b05 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -20,10 +20,9 @@
 
 #include "MPEG2PSExtractor.h"
 
-#include "mpeg2ts/AnotherPacketSource.h"
-#include "mpeg2ts/ESQueue.h"
+#include <AnotherPacketSource.h>
+#include <ESQueue.h>
 
-#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -111,8 +110,10 @@
     AMediaFormat *meta = AMediaFormat_new();
     for (size_t i = mTracks.size(); i > 0;) {
         i--;
-        if (mTracks.valueAt(i)->getFormat(meta) != AMEDIA_OK) {
+        Track *track = mTracks.valueAt(i);
+        if (track->getFormat(meta) != AMEDIA_OK) {
             mTracks.removeItemsAt(i);
+            delete track;
         }
     }
     AMediaFormat_delete(meta);
@@ -122,6 +123,10 @@
 
 MPEG2PSExtractor::~MPEG2PSExtractor() {
     delete mDataSource;
+    for (size_t i = mTracks.size(); i > 0;) {
+        i--;
+        delete mTracks.valueAt(i);
+    }
 }
 
 size_t MPEG2PSExtractor::countTracks() {
@@ -793,7 +798,9 @@
 }
 
 media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+    delete mTrack->mBufferGroup;
     mTrack->mBufferGroup = mBufferGroup;
+    mBufferGroup = nullptr;
     return mTrack->start();
 }
 
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 50ce657..9e093eb 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -24,21 +24,20 @@
 
 #include "MPEG2TSExtractor.h"
 
-#include <media/DataSourceBase.h>
 #include <media/IStreamSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/foundation/MediaKeys.h>
+#include <media/stagefright/DataSourceBase.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
 #include <utils/String8.h>
 
-#include "mpeg2ts/AnotherPacketSource.h"
-#include "mpeg2ts/ATSParser.h"
+#include <AnotherPacketSource.h>
 
 #include <hidl/HybridInterface.h>
 #include <android/hardware/cas/1.0/ICas.h>
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index dcd1e7b..fd77b08 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -27,7 +27,7 @@
 #include <utils/KeyedVector.h>
 #include <utils/Vector.h>
 
-#include "mpeg2ts/ATSParser.h"
+#include <ATSParser.h>
 
 namespace android {
 
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 604ec59..7aed683 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -1,9 +1,11 @@
-cc_library_shared {
+cc_library {
+    name: "liboggextractor",
+
+    defaults: ["extractor-defaults"],
 
     srcs: ["OggExtractor.cpp"],
 
     include_dirs: [
-        "frameworks/av/media/libstagefright/include",
         "external/tremolo",
     ],
 
@@ -11,11 +13,6 @@
         "libaudio_system_headers",
     ],
 
-    shared_libs: [
-        "liblog",
-        "libmediandk",
-    ],
-
     static_libs: [
         "libstagefright_foundation",
         "libstagefright_metadatautils",
@@ -23,24 +20,4 @@
         "libvorbisidec",
     ],
 
-    name: "liboggextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 72b94bb..828bcd6 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -22,7 +22,7 @@
 
 #include <cutils/properties.h>
 #include <utils/Vector.h>
-#include <media/DataSourceBase.h>
+#include <media/stagefright/DataSourceBase.h>
 #include <media/ExtractorUtils.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -635,7 +635,8 @@
             currentPageSamples -= mStartGranulePosition;
             AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, currentPageSamples);
         }
-        mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
+        (void) __builtin_sub_overflow(mCurrentPage.mGranulePosition, currentPageSamples,
+                                      &mCurGranulePosition);
     }
 
     int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
@@ -1062,8 +1063,15 @@
     size_t size = buffer->range_length();
 
     if (size < kOpusHeaderSize
-            || memcmp(data, "OpusHead", 8)
-            || /* version = */ data[8] != 1) {
+            || memcmp(data, "OpusHead", 8)) {
+        return AMEDIA_ERROR_MALFORMED;
+    }
+    // allow both version 0 and 1. Per the opus specification:
+    // An earlier draft of the specification described a version 0, but the only difference
+    // between version 1 and version 0 is that version 0 did not specify the semantics for
+    // handling the version field
+    if ( /* version = */ data[8] > 1) {
+        ALOGW("no support for opus version %d", data[8]);
         return AMEDIA_ERROR_MALFORMED;
     }
 
@@ -1384,7 +1392,7 @@
         return NULL;
     }
 
-    *confidence = 0.2f;
+    *confidence = 0.5f;
 
     return CreateExtractor;
 }
diff --git a/media/extractors/tests/Android.bp b/media/extractors/tests/Android.bp
new file mode 100644
index 0000000..b3afe2f
--- /dev/null
+++ b/media/extractors/tests/Android.bp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "ExtractorUnitTest",
+    gtest: true,
+
+    srcs: ["ExtractorUnitTest.cpp"],
+
+    static_libs: [
+        "libaacextractor",
+        "libamrextractor",
+        "libmp3extractor",
+        "libwavextractor",
+        "liboggextractor",
+        "libflacextractor",
+        "libmidiextractor",
+        "libmkvextractor",
+        "libmpeg2extractor",
+        "libmp4extractor",
+        "libaudioutils",
+        "libdatasource",
+        "libwatchdog",
+
+        "libstagefright",
+        "libstagefright_id3",
+        "libstagefright_flacdec",
+        "libstagefright_esds",
+        "libstagefright_mpeg2support",
+        "libstagefright_mpeg2extractor",
+        "libstagefright_foundation",
+        "libstagefright_metadatautils",
+
+        "libmedia_midiiowrapper",
+        "libsonivoxwithoutjet",
+        "libvorbisidec",
+        "libwebm",
+        "libFLAC",
+    ],
+
+    shared_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas.native@1.0",
+        "android.hidl.token@1.0-utils",
+        "android.hidl.allocator@1.0",
+        "libbinder",
+        "libbinder_ndk",
+        "libutils",
+        "liblog",
+        "libcutils",
+        "libmediandk",
+        "libmedia",
+        "libcrypto",
+        "libhidlmemory",
+        "libhidlbase",
+        "libbase",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/extractors/",
+        "frameworks/av/media/libstagefright/",
+    ],
+
+    compile_multilib: "first",
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    ldflags: [
+        "-Wl",
+        "-Bsymbolic",
+        // to ignore duplicate symbol: GETEXTRACTORDEF
+        "-z muldefs",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/extractors/tests/AndroidTest.xml b/media/extractors/tests/AndroidTest.xml
new file mode 100644
index 0000000..6bb2c8a
--- /dev/null
+++ b/media/extractors/tests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for extractor unit tests">
+    <option name="test-suite-tag" value="ExtractorUnitTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="ExtractorUnitTest->/data/local/tmp/ExtractorUnitTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
+            value="/data/local/tmp/ExtractorUnitTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="ExtractorUnitTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/ExtractorUnitTestRes/" />
+    </test>
+</configuration>
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/extractors/tests/ExtractorUnitTest.cpp
new file mode 100644
index 0000000..518166e
--- /dev/null
+++ b/media/extractors/tests/ExtractorUnitTest.cpp
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2019 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 "ExtractorUnitTest"
+#include <utils/Log.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaDataUtils.h>
+
+#include "aac/AACExtractor.h"
+#include "amr/AMRExtractor.h"
+#include "flac/FLACExtractor.h"
+#include "midi/MidiExtractor.h"
+#include "mkv/MatroskaExtractor.h"
+#include "mp3/MP3Extractor.h"
+#include "mp4/MPEG4Extractor.h"
+#include "mp4/SampleTable.h"
+#include "mpeg2/MPEG2PSExtractor.h"
+#include "mpeg2/MPEG2TSExtractor.h"
+#include "ogg/OggExtractor.h"
+#include "wav/WAVExtractor.h"
+
+#include "ExtractorUnitTestEnvironment.h"
+
+using namespace android;
+
+#define OUTPUT_DUMP_FILE "/data/local/tmp/extractorOutput"
+
+constexpr int32_t kMaxCount = 10;
+constexpr int32_t kOpusSeekPreRollUs = 80000;  // 80 ms;
+
+static ExtractorUnitTestEnvironment *gEnv = nullptr;
+
+class ExtractorUnitTest : public ::testing::TestWithParam<pair<string, string>> {
+  public:
+    ExtractorUnitTest() : mInputFp(nullptr), mDataSource(nullptr), mExtractor(nullptr) {}
+
+    ~ExtractorUnitTest() {
+        if (mInputFp) {
+            fclose(mInputFp);
+            mInputFp = nullptr;
+        }
+        if (mDataSource) {
+            mDataSource.clear();
+            mDataSource = nullptr;
+        }
+        if (mExtractor) {
+            delete mExtractor;
+            mExtractor = nullptr;
+        }
+    }
+
+    virtual void SetUp() override {
+        mExtractorName = unknown_comp;
+        mDisableTest = false;
+
+        static const std::map<std::string, standardExtractors> mapExtractor = {
+                {"aac", AAC},     {"amr", AMR},         {"mp3", MP3},        {"ogg", OGG},
+                {"wav", WAV},     {"mkv", MKV},         {"flac", FLAC},      {"midi", MIDI},
+                {"mpeg4", MPEG4}, {"mpeg2ts", MPEG2TS}, {"mpeg2ps", MPEG2PS}};
+        // Find the component type
+        string writerFormat = GetParam().first;
+        if (mapExtractor.find(writerFormat) != mapExtractor.end()) {
+            mExtractorName = mapExtractor.at(writerFormat);
+        }
+        if (mExtractorName == standardExtractors::unknown_comp) {
+            cout << "[   WARN   ] Test Skipped. Invalid extractor\n";
+            mDisableTest = true;
+        }
+    }
+
+    int32_t setDataSource(string inputFileName);
+
+    int32_t createExtractor();
+
+    enum standardExtractors {
+        AAC,
+        AMR,
+        FLAC,
+        MIDI,
+        MKV,
+        MP3,
+        MPEG4,
+        MPEG2PS,
+        MPEG2TS,
+        OGG,
+        WAV,
+        unknown_comp,
+    };
+
+    bool mDisableTest;
+    standardExtractors mExtractorName;
+
+    FILE *mInputFp;
+    sp<DataSource> mDataSource;
+    MediaExtractorPluginHelper *mExtractor;
+};
+
+int32_t ExtractorUnitTest::setDataSource(string inputFileName) {
+    mInputFp = fopen(inputFileName.c_str(), "rb");
+    if (!mInputFp) {
+        ALOGE("Unable to open input file for reading");
+        return -1;
+    }
+    struct stat buf;
+    stat(inputFileName.c_str(), &buf);
+    int32_t fd = fileno(mInputFp);
+    mDataSource = new FileSource(dup(fd), 0, buf.st_size);
+    if (!mDataSource) return -1;
+    return 0;
+}
+
+int32_t ExtractorUnitTest::createExtractor() {
+    switch (mExtractorName) {
+        case AAC:
+            mExtractor = new AACExtractor(new DataSourceHelper(mDataSource->wrap()), 0);
+            break;
+        case AMR:
+            mExtractor = new AMRExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MP3:
+            mExtractor = new MP3Extractor(new DataSourceHelper(mDataSource->wrap()), nullptr);
+            break;
+        case OGG:
+            mExtractor = new OggExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case WAV:
+            mExtractor = new WAVExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MKV:
+            mExtractor = new MatroskaExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case FLAC:
+            mExtractor = new FLACExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MPEG4:
+            mExtractor = new MPEG4Extractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MPEG2TS:
+            mExtractor = new MPEG2TSExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MPEG2PS:
+            mExtractor = new MPEG2PSExtractor(new DataSourceHelper(mDataSource->wrap()));
+            break;
+        case MIDI:
+            mExtractor = new MidiExtractor(mDataSource->wrap());
+            break;
+        default:
+            return -1;
+    }
+    if (!mExtractor) return -1;
+    return 0;
+}
+
+void getSeekablePoints(vector<int64_t> &seekablePoints, MediaTrackHelper *track) {
+    int32_t status = 0;
+    if (!seekablePoints.empty()) {
+        seekablePoints.clear();
+    }
+    int64_t timeStamp;
+    while (status != AMEDIA_ERROR_END_OF_STREAM) {
+        MediaBufferHelper *buffer = nullptr;
+        status = track->read(&buffer);
+        if (buffer) {
+            AMediaFormat *metaData = buffer->meta_data();
+            int32_t isSync = 0;
+            AMediaFormat_getInt32(metaData, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, &isSync);
+            if (isSync) {
+                AMediaFormat_getInt64(metaData, AMEDIAFORMAT_KEY_TIME_US, &timeStamp);
+                seekablePoints.push_back(timeStamp);
+            }
+            buffer->release();
+        }
+    }
+}
+
+TEST_P(ExtractorUnitTest, CreateExtractorTest) {
+    if (mDisableTest) return;
+
+    ALOGV("Checks if a valid extractor is created for a given input file");
+    string inputFileName = gEnv->getRes() + GetParam().second;
+
+    ASSERT_EQ(setDataSource(inputFileName), 0)
+            << "SetDataSource failed for" << GetParam().first << "extractor";
+
+    ASSERT_EQ(createExtractor(), 0)
+            << "Extractor creation failed for" << GetParam().first << "extractor";
+
+    // A valid extractor instace should return success for following calls
+    ASSERT_GT(mExtractor->countTracks(), 0);
+
+    AMediaFormat *format = AMediaFormat_new();
+    ASSERT_NE(format, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+    ASSERT_EQ(mExtractor->getMetaData(format), AMEDIA_OK);
+    AMediaFormat_delete(format);
+}
+
+TEST_P(ExtractorUnitTest, ExtractorTest) {
+    if (mDisableTest) return;
+
+    ALOGV("Validates %s Extractor for a given input file", GetParam().first.c_str());
+    string inputFileName = gEnv->getRes() + GetParam().second;
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+    for (int32_t idx = 0; idx < numTracks; idx++) {
+        MediaTrackHelper *track = mExtractor->getTrack(idx);
+        ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+        CMediaTrack *cTrack = wrap(track);
+        ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+        MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+        status = cTrack->start(track, bufferGroup->wrap());
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+
+        FILE *outFp = fopen((OUTPUT_DUMP_FILE + to_string(idx)).c_str(), "wb");
+        if (!outFp) {
+            ALOGW("Unable to open output file for dumping extracted stream");
+        }
+
+        while (status != AMEDIA_ERROR_END_OF_STREAM) {
+            MediaBufferHelper *buffer = nullptr;
+            status = track->read(&buffer);
+            ALOGV("track->read Status = %d buffer %p", status, buffer);
+            if (buffer) {
+                ALOGV("buffer->data %p buffer->size() %zu buffer->range_length() %zu",
+                      buffer->data(), buffer->size(), buffer->range_length());
+                if (outFp) fwrite(buffer->data(), 1, buffer->range_length(), outFp);
+                buffer->release();
+            }
+        }
+        if (outFp) fclose(outFp);
+        status = cTrack->stop(track);
+        ASSERT_EQ(OK, status) << "Failed to stop the track";
+        delete bufferGroup;
+        delete track;
+    }
+}
+
+TEST_P(ExtractorUnitTest, MetaDataComparisonTest) {
+    if (mDisableTest) return;
+
+    ALOGV("Validates Extractor's meta data for a given input file");
+    string inputFileName = gEnv->getRes() + GetParam().second;
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+    AMediaFormat *extractorFormat = AMediaFormat_new();
+    ASSERT_NE(extractorFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
+    AMediaFormat *trackFormat = AMediaFormat_new();
+    ASSERT_NE(trackFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+    for (int32_t idx = 0; idx < numTracks; idx++) {
+        MediaTrackHelper *track = mExtractor->getTrack(idx);
+        ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+        CMediaTrack *cTrack = wrap(track);
+        ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+        MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+        status = cTrack->start(track, bufferGroup->wrap());
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+
+        status = mExtractor->getTrackMetaData(extractorFormat, idx, 1);
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to get trackMetaData";
+
+        status = track->getFormat(trackFormat);
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to get track meta data";
+
+        const char *extractorMime, *trackMime;
+        AMediaFormat_getString(extractorFormat, AMEDIAFORMAT_KEY_MIME, &extractorMime);
+        AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &trackMime);
+        ASSERT_TRUE(!strcmp(extractorMime, trackMime))
+                << "Extractor's format doesn't match track format";
+
+        if (!strncmp(extractorMime, "audio/", 6)) {
+            int32_t exSampleRate, exChannelCount;
+            int32_t trackSampleRate, trackChannelCount;
+            ASSERT_TRUE(AMediaFormat_getInt32(extractorFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
+                                              &exChannelCount));
+            ASSERT_TRUE(AMediaFormat_getInt32(extractorFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE,
+                                              &exSampleRate));
+            ASSERT_TRUE(AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
+                                              &trackChannelCount));
+            ASSERT_TRUE(AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE,
+                                              &trackSampleRate));
+            ASSERT_EQ(exChannelCount, trackChannelCount) << "ChannelCount not as expected";
+            ASSERT_EQ(exSampleRate, trackSampleRate) << "SampleRate not as expected";
+        } else {
+            int32_t exWidth, exHeight;
+            int32_t trackWidth, trackHeight;
+            ASSERT_TRUE(AMediaFormat_getInt32(extractorFormat, AMEDIAFORMAT_KEY_WIDTH, &exWidth));
+            ASSERT_TRUE(AMediaFormat_getInt32(extractorFormat, AMEDIAFORMAT_KEY_HEIGHT, &exHeight));
+            ASSERT_TRUE(AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_WIDTH, &trackWidth));
+            ASSERT_TRUE(AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_HEIGHT, &trackHeight));
+            ASSERT_EQ(exWidth, trackWidth) << "Width not as expected";
+            ASSERT_EQ(exHeight, trackHeight) << "Height not as expected";
+        }
+        status = cTrack->stop(track);
+        ASSERT_EQ(OK, status) << "Failed to stop the track";
+        delete bufferGroup;
+        delete track;
+    }
+    AMediaFormat_delete(trackFormat);
+    AMediaFormat_delete(extractorFormat);
+}
+
+TEST_P(ExtractorUnitTest, MultipleStartStopTest) {
+    if (mDisableTest) return;
+
+    ALOGV("Test %s extractor for multiple start and stop calls", GetParam().first.c_str());
+    string inputFileName = gEnv->getRes() + GetParam().second;
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+    // start/stop the tracks multiple times
+    for (int32_t count = 0; count < kMaxCount; count++) {
+        for (int32_t idx = 0; idx < numTracks; idx++) {
+            MediaTrackHelper *track = mExtractor->getTrack(idx);
+            ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+            CMediaTrack *cTrack = wrap(track);
+            ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+            MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+            status = cTrack->start(track, bufferGroup->wrap());
+            ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+            MediaBufferHelper *buffer = nullptr;
+            status = track->read(&buffer);
+            if (buffer) {
+                ALOGV("buffer->data %p buffer->size() %zu buffer->range_length() %zu",
+                      buffer->data(), buffer->size(), buffer->range_length());
+                buffer->release();
+            }
+            status = cTrack->stop(track);
+            ASSERT_EQ(OK, status) << "Failed to stop the track";
+            delete bufferGroup;
+            delete track;
+        }
+    }
+}
+
+TEST_P(ExtractorUnitTest, SeekTest) {
+    // Both Flac and Wav extractor can give samples from any pts and mark the given sample as
+    // sync frame. So, this seek test is not applicable to FLAC and WAV extractors
+    if (mDisableTest || mExtractorName == FLAC || mExtractorName == WAV) return;
+
+    ALOGV("Validates %s Extractor behaviour for different seek modes", GetParam().first.c_str());
+    string inputFileName = gEnv->getRes() + GetParam().second;
+
+    int32_t status = setDataSource(inputFileName);
+    ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+
+    status = createExtractor();
+    ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+
+    int32_t numTracks = mExtractor->countTracks();
+    ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+    uint32_t seekFlag = mExtractor->flags();
+    if (!(seekFlag & MediaExtractorPluginHelper::CAN_SEEK)) {
+        cout << "[   WARN   ] Test Skipped. " << GetParam().first
+             << " Extractor doesn't support seek\n";
+        return;
+    }
+
+    vector<int64_t> seekablePoints;
+    for (int32_t idx = 0; idx < numTracks; idx++) {
+        MediaTrackHelper *track = mExtractor->getTrack(idx);
+        ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+        CMediaTrack *cTrack = wrap(track);
+        ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+        // Get all the seekable points of a given input
+        MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+        status = cTrack->start(track, bufferGroup->wrap());
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+        getSeekablePoints(seekablePoints, track);
+        ASSERT_GT(seekablePoints.size(), 0)
+                << "Failed to get seekable points for " << GetParam().first << " extractor";
+
+        AMediaFormat *trackFormat = AMediaFormat_new();
+        ASSERT_NE(trackFormat, nullptr) << "AMediaFormat_new returned null format";
+        status = track->getFormat(trackFormat);
+        ASSERT_EQ(OK, (media_status_t)status) << "Failed to get track meta data";
+
+        bool isOpus = false;
+        const char *mime;
+        AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+        if (!strcmp(mime, "audio/opus")) isOpus = true;
+        AMediaFormat_delete(trackFormat);
+
+        int32_t seekIdx = 0;
+        size_t seekablePointsSize = seekablePoints.size();
+        for (int32_t mode = CMediaTrackReadOptions::SEEK_PREVIOUS_SYNC;
+             mode <= CMediaTrackReadOptions::SEEK_CLOSEST; mode++) {
+            for (int32_t seekCount = 0; seekCount < kMaxCount; seekCount++) {
+                seekIdx = rand() % seekablePointsSize + 1;
+                if (seekIdx >= seekablePointsSize) seekIdx = seekablePointsSize - 1;
+
+                int64_t seekToTimeStamp = seekablePoints[seekIdx];
+                if (seekablePointsSize > 1) {
+                    int64_t prevTimeStamp = seekablePoints[seekIdx - 1];
+                    seekToTimeStamp = seekToTimeStamp - ((seekToTimeStamp - prevTimeStamp) >> 3);
+                }
+
+                // Opus has a seekPreRollUs. TimeStamp returned by the
+                // extractor is calculated based on (seekPts - seekPreRollUs).
+                // So we add the preRoll value to the timeStamp we want to seek to.
+                if (isOpus) {
+                    seekToTimeStamp += kOpusSeekPreRollUs;
+                }
+
+                MediaTrackHelper::ReadOptions *options = new MediaTrackHelper::ReadOptions(
+                        mode | CMediaTrackReadOptions::SEEK, seekToTimeStamp);
+                ASSERT_NE(options, nullptr) << "Cannot create read option";
+
+                MediaBufferHelper *buffer = nullptr;
+                status = track->read(&buffer, options);
+                if (status == AMEDIA_ERROR_END_OF_STREAM) {
+                    delete options;
+                    continue;
+                }
+                if (buffer) {
+                    AMediaFormat *metaData = buffer->meta_data();
+                    int64_t timeStamp;
+                    AMediaFormat_getInt64(metaData, AMEDIAFORMAT_KEY_TIME_US, &timeStamp);
+                    buffer->release();
+
+                    // CMediaTrackReadOptions::SEEK is 8. Using mask 0111b to get true modes
+                    switch (mode & 0x7) {
+                        case CMediaTrackReadOptions::SEEK_PREVIOUS_SYNC:
+                            if (seekablePointsSize == 1) {
+                                EXPECT_EQ(timeStamp, seekablePoints[seekIdx]);
+                            } else {
+                                EXPECT_EQ(timeStamp, seekablePoints[seekIdx - 1]);
+                            }
+                            break;
+                        case CMediaTrackReadOptions::SEEK_NEXT_SYNC:
+                        case CMediaTrackReadOptions::SEEK_CLOSEST_SYNC:
+                        case CMediaTrackReadOptions::SEEK_CLOSEST:
+                            EXPECT_EQ(timeStamp, seekablePoints[seekIdx]);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                delete options;
+            }
+        }
+        status = cTrack->stop(track);
+        ASSERT_EQ(OK, status) << "Failed to stop the track";
+        delete bufferGroup;
+        delete track;
+    }
+    seekablePoints.clear();
+}
+
+// TODO: (b/145332185)
+// Add MIDI inputs
+INSTANTIATE_TEST_SUITE_P(ExtractorUnitTestAll, ExtractorUnitTest,
+                         ::testing::Values(make_pair("aac", "loudsoftaac.aac"),
+                                           make_pair("amr", "testamr.amr"),
+                                           make_pair("amr", "amrwb.wav"),
+                                           make_pair("ogg", "john_cage.ogg"),
+                                           make_pair("wav", "monotestgsm.wav"),
+                                           make_pair("mpeg2ts", "segment000001.ts"),
+                                           make_pair("flac", "sinesweepflac.flac"),
+                                           make_pair("ogg", "testopus.opus"),
+                                           make_pair("mkv", "sinesweepvorbis.mkv"),
+                                           make_pair("mpeg4", "sinesweepoggmp4.mp4"),
+                                           make_pair("mp3", "sinesweepmp3lame.mp3"),
+                                           make_pair("mkv", "swirl_144x136_vp9.webm"),
+                                           make_pair("mkv", "swirl_144x136_vp8.webm"),
+                                           make_pair("mpeg2ps", "swirl_144x136_mpeg2.mpg"),
+                                           make_pair("mpeg4", "swirl_132x130_mpeg4.mp4")));
+
+int main(int argc, char **argv) {
+    gEnv = new ExtractorUnitTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/extractors/tests/ExtractorUnitTestEnvironment.h b/media/extractors/tests/ExtractorUnitTestEnvironment.h
new file mode 100644
index 0000000..fce8fc2
--- /dev/null
+++ b/media/extractors/tests/ExtractorUnitTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __EXTRACTOR_UNIT_TEST_ENVIRONMENT_H__
+#define __EXTRACTOR_UNIT_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class ExtractorUnitTestEnvironment : public ::testing::Environment {
+  public:
+    ExtractorUnitTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int ExtractorUnitTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __EXTRACTOR_UNIT_TEST_ENVIRONMENT_H__
diff --git a/media/extractors/tests/README.md b/media/extractors/tests/README.md
new file mode 100644
index 0000000..69538b6
--- /dev/null
+++ b/media/extractors/tests/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### Extractor :
+The Extractor Test Suite validates the extractors available in the device.
+
+Run the following steps to build the test suite:
+```
+m ExtractorUnitTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/ExtractorUnitTest/ExtractorUnitTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/ExtractorUnitTest/ExtractorUnitTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push extractor /data/local/tmp/
+```
+
+usage: ExtractorUnitTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/ExtractorUnitTest -P /data/local/tmp/extractor/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ExtractorUnitTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 7e89271..5d38a81 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -1,4 +1,7 @@
-cc_library_shared {
+cc_library {
+    name: "libwavextractor",
+
+    defaults: ["extractor-defaults"],
 
     srcs: ["WAVExtractor.cpp"],
 
@@ -7,9 +10,8 @@
     ],
 
     shared_libs: [
+        "libbase",
         "libbinder_ndk",
-        "liblog",
-        "libmediandk",
     ],
 
     static_libs: [
@@ -17,25 +19,4 @@
         "libfifo",
         "libstagefright_foundation",
     ],
-
-    name: "libwavextractor",
-    relative_install_path: "extractors",
-
-    compile_multilib: "first",
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-fvisibility=hidden",
-    ],
-    version_script: "exports.lds",
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-
 }
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 976b7d9..901b29d 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -20,6 +20,7 @@
 
 #include "WAVExtractor.h"
 
+#include <android-base/properties.h>
 #include <android/binder_ibinder.h> // for AIBinder_getCallingUid
 #include <audio_utils/primitives.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -43,7 +44,8 @@
 // (Note: duplicated with FLACExtractor.cpp)
 static inline bool shouldExtractorOutputFloat(int bitsPerSample)
 {
-    return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA;
+    return bitsPerSample > 16 && AIBinder_getCallingUid() == AID_MEDIA
+                              && android::base::GetBoolProperty("media.extractor.float", true);
 }
 
 enum {
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 16958f9..140052f 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -24,7 +24,7 @@
 ndk_library {
     name: "libaaudio",
     // deliberately includes symbols from AAudioTesting.h
-    symbol_file: "libaaudio.map.txt",
+    symbol_file: "src/libaaudio.map.txt",
     first_version: "26",
     unversioned_until: "current",
 }
@@ -32,6 +32,5 @@
 cc_library_headers {
     name: "libaaudio_headers",
     export_include_dirs: ["include"],
-    version_script: "libaaudio.map.txt",
 }
 
diff --git a/media/libaaudio/examples/input_monitor/Android.bp b/media/libaaudio/examples/input_monitor/Android.bp
index 5d399b5..d8c5843 100644
--- a/media/libaaudio/examples/input_monitor/Android.bp
+++ b/media/libaaudio/examples/input_monitor/Android.bp
@@ -5,7 +5,6 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: ["libaaudio"],
     header_libs: ["libaaudio_example_utils"],
-    pack_relocations: false,
 }
 
 cc_test {
@@ -15,5 +14,4 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: ["libaaudio"],
     header_libs: ["libaaudio_example_utils"],
-    pack_relocations: false,
 }
diff --git a/media/libaaudio/examples/loopback/Android.bp b/media/libaaudio/examples/loopback/Android.bp
index 53e5020..5b7d956 100644
--- a/media/libaaudio/examples/loopback/Android.bp
+++ b/media/libaaudio/examples/loopback/Android.bp
@@ -9,5 +9,4 @@
         "libaudioutils",
         ],
     header_libs: ["libaaudio_example_utils"],
-    pack_relocations: false,
 }
diff --git a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
deleted file mode 100644
index 8eb70b1..0000000
--- a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
+++ /dev/null
@@ -1,1114 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-/**
- * Tools for measuring latency and for detecting glitches.
- * These classes are pure math and can be used with any audio system.
- */
-
-#ifndef AAUDIO_EXAMPLES_LOOPBACK_ANALYSER_H
-#define AAUDIO_EXAMPLES_LOOPBACK_ANALYSER_H
-
-#include <algorithm>
-#include <assert.h>
-#include <cctype>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <audio_utils/sndfile.h>
-
-// Tag for machine readable results as property = value pairs
-#define LOOPBACK_RESULT_TAG      "RESULT: "
-
-constexpr int32_t kDefaultSampleRate = 48000;
-constexpr int32_t kMillisPerSecond   = 1000;
-constexpr int32_t kMinLatencyMillis  = 4;    // arbitrary and very low
-constexpr int32_t kMaxLatencyMillis  = 400;  // arbitrary and generous
-constexpr double  kMaxEchoGain       = 10.0; // based on experiments, otherwise too noisy
-constexpr double  kMinimumConfidence = 0.5;
-
-static void printAudioScope(float sample) {
-    const int maxStars = 80; // arbitrary, fits on one line
-    char c = '*';
-    if (sample < -1.0) {
-        sample = -1.0;
-        c = '$';
-    } else if (sample > 1.0) {
-        sample = 1.0;
-        c = '$';
-    }
-    int numSpaces = (int) (((sample + 1.0) * 0.5) * maxStars);
-    for (int i = 0; i < numSpaces; i++) {
-        putchar(' ');
-    }
-    printf("%c\n", c);
-}
-
-/*
-
-FIR filter designed with
-http://t-filter.appspot.com
-
-sampling frequency: 48000 Hz
-
-* 0 Hz - 8000 Hz
-  gain = 1.2
-  desired ripple = 5 dB
-  actual ripple = 5.595266169703693 dB
-
-* 12000 Hz - 20000 Hz
-  gain = 0
-  desired attenuation = -40 dB
-  actual attenuation = -37.58691566571914 dB
-
-*/
-
-#define FILTER_TAP_NUM 11
-
-static const float sFilterTaps8000[FILTER_TAP_NUM] = {
-        -0.05944219353343189f,
-        -0.07303434839503208f,
-        -0.037690487672689066f,
-        0.1870480506596512f,
-        0.3910337357836833f,
-        0.5333672385425637f,
-        0.3910337357836833f,
-        0.1870480506596512f,
-        -0.037690487672689066f,
-        -0.07303434839503208f,
-        -0.05944219353343189f
-};
-
-class LowPassFilter {
-public:
-
-    /*
-     * Filter one input sample.
-     * @return filtered output
-     */
-    float filter(float input) {
-        float output = 0.0f;
-        mX[mCursor] = input;
-        // Index backwards over x.
-        int xIndex = mCursor + FILTER_TAP_NUM;
-        // Write twice so we avoid having to wrap in the middle of the convolution.
-        mX[xIndex] = input;
-        for (int i = 0; i < FILTER_TAP_NUM; i++) {
-            output += sFilterTaps8000[i] * mX[xIndex--];
-        }
-        if (++mCursor >= FILTER_TAP_NUM) {
-            mCursor = 0;
-        }
-        return output;
-    }
-
-    /**
-     * @return true if PASSED
-     */
-    bool test() {
-        // Measure the impulse of the filter at different phases so we exercise
-        // all the wraparound cases in the FIR.
-        for (int offset = 0; offset < (FILTER_TAP_NUM * 2); offset++ ) {
-            // printf("LowPassFilter: cursor = %d\n", mCursor);
-            // Offset by one each time.
-            if (filter(0.0f) != 0.0f) {
-                printf("ERROR: filter should return 0.0 before impulse response\n");
-                return false;
-            }
-            for (int i = 0; i < FILTER_TAP_NUM; i++) {
-                float output = filter((i == 0) ? 1.0f : 0.0f); // impulse
-                if (output != sFilterTaps8000[i]) {
-                    printf("ERROR: filter should return impulse response\n");
-                    return false;
-                }
-            }
-            for (int i = 0; i < FILTER_TAP_NUM; i++) {
-                if (filter(0.0f) != 0.0f) {
-                    printf("ERROR: filter should return 0.0 after impulse response\n");
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-private:
-    float   mX[FILTER_TAP_NUM * 2]{}; // twice as big as needed to avoid wrapping
-    int32_t mCursor = 0;
-};
-
-// A narrow impulse seems to have better immunity against over estimating the
-// latency due to detecting subharmonics by the auto-correlator.
-static const float s_Impulse[] = {
-        0.0f, 0.0f, 0.0f, 0.0f, 0.3f, // silence on each side of the impulse
-        0.99f, 0.0f, -0.99f, // bipolar with one zero crossing in middle
-        -0.3f, 0.0f, 0.0f, 0.0f, 0.0f
-};
-
-constexpr int32_t kImpulseSizeInFrames = (int32_t)(sizeof(s_Impulse) / sizeof(s_Impulse[0]));
-
-class PseudoRandom {
-public:
-    PseudoRandom() {}
-    PseudoRandom(int64_t seed)
-            :    mSeed(seed)
-    {}
-
-    /**
-     * Returns the next random double from -1.0 to 1.0
-     *
-     * @return value from -1.0 to 1.0
-     */
-     double nextRandomDouble() {
-        return nextRandomInteger() * (0.5 / (((int32_t)1) << 30));
-    }
-
-    /** Calculate random 32 bit number using linear-congruential method. */
-    int32_t nextRandomInteger() {
-        // Use values for 64-bit sequence from MMIX by Donald Knuth.
-        mSeed = (mSeed * (int64_t)6364136223846793005) + (int64_t)1442695040888963407;
-        return (int32_t) (mSeed >> 32); // The higher bits have a longer sequence.
-    }
-
-private:
-    int64_t mSeed = 99887766;
-};
-
-
-typedef struct LatencyReport_s {
-    double latencyInFrames;
-    double confidence;
-} LatencyReport;
-
-static double calculateCorrelation(const float *a,
-                                   const float *b,
-                                   int windowSize)
-{
-    double correlation = 0.0;
-    double sumProducts = 0.0;
-    double sumSquares = 0.0;
-
-    // Correlate a against b.
-    for (int i = 0; i < windowSize; i++) {
-        float s1 = a[i];
-        float s2 = b[i];
-        // Use a normalized cross-correlation.
-        sumProducts += s1 * s2;
-        sumSquares += ((s1 * s1) + (s2 * s2));
-    }
-
-    if (sumSquares >= 0.00000001) {
-        correlation = (float) (2.0 * sumProducts / sumSquares);
-    }
-    return correlation;
-}
-
-static int measureLatencyFromEchos(const float *data,
-                                   int32_t numFloats,
-                                   int32_t sampleRate,
-                                   LatencyReport *report) {
-    // Allocate results array
-    const int minReasonableLatencyFrames = sampleRate * kMinLatencyMillis / kMillisPerSecond;
-    const int maxReasonableLatencyFrames = sampleRate * kMaxLatencyMillis / kMillisPerSecond;
-    int32_t maxCorrelationSize = maxReasonableLatencyFrames * 3;
-    int numCorrelations = std::min(numFloats, maxCorrelationSize);
-    float *correlations = new float[numCorrelations]{};
-    float *harmonicSums = new float[numCorrelations]{};
-
-    // Perform sliding auto-correlation.
-    // Skip first frames to avoid huge peak at zero offset.
-    for (int i = minReasonableLatencyFrames; i < numCorrelations; i++) {
-        int32_t remaining = numFloats - i;
-        float correlation = (float) calculateCorrelation(&data[i], data, remaining);
-        correlations[i] = correlation;
-        // printf("correlation[%d] = %f\n", ic, correlation);
-    }
-
-    // Apply a technique similar to Harmonic Product Spectrum Analysis to find echo fundamental.
-    // Add higher harmonics mapped onto lower harmonics. This reinforces the "fundamental" echo.
-    const int numEchoes = 8;
-    for (int partial = 1; partial < numEchoes; partial++) {
-        for (int i = minReasonableLatencyFrames; i < numCorrelations; i++) {
-            harmonicSums[i / partial] += correlations[i] / partial;
-        }
-    }
-
-    // Find highest peak in correlation array.
-    float maxCorrelation = 0.0;
-    int peakIndex = 0;
-    for (int i = 0; i < numCorrelations; i++) {
-        if (harmonicSums[i] > maxCorrelation) {
-            maxCorrelation = harmonicSums[i];
-            peakIndex = i;
-            // printf("maxCorrelation = %f at %d\n", maxCorrelation, peakIndex);
-        }
-    }
-    report->latencyInFrames = peakIndex;
-/*
-    {
-        int32_t topPeak = peakIndex * 7 / 2;
-        for (int i = 0; i < topPeak; i++) {
-            float sample = harmonicSums[i];
-            printf("%4d: %7.5f ", i, sample);
-            printAudioScope(sample);
-        }
-    }
-*/
-
-    // Calculate confidence.
-    if (maxCorrelation < 0.001) {
-        report->confidence = 0.0;
-    } else {
-        // Compare peak to average value around peak.
-        int32_t numSamples = std::min(numCorrelations, peakIndex * 2);
-        if (numSamples <= 0) {
-            report->confidence = 0.0;
-        } else {
-            double sum = 0.0;
-            for (int i = 0; i < numSamples; i++) {
-                sum += harmonicSums[i];
-            }
-            const double average = sum / numSamples;
-            const double ratio = average / maxCorrelation; // will be < 1.0
-            report->confidence = 1.0 - sqrt(ratio);
-        }
-    }
-
-    delete[] correlations;
-    delete[] harmonicSums;
-    return 0;
-}
-
-class AudioRecording
-{
-public:
-    AudioRecording() {
-    }
-    ~AudioRecording() {
-        delete[] mData;
-    }
-
-    void allocate(int maxFrames) {
-        delete[] mData;
-        mData = new float[maxFrames];
-        mMaxFrames = maxFrames;
-    }
-
-    // Write SHORT data from the first channel.
-    int32_t write(int16_t *inputData, int32_t inputChannelCount, int32_t numFrames) {
-        // stop at end of buffer
-        if ((mFrameCounter + numFrames) > mMaxFrames) {
-            numFrames = mMaxFrames - mFrameCounter;
-        }
-        for (int i = 0; i < numFrames; i++) {
-            mData[mFrameCounter++] = inputData[i * inputChannelCount] * (1.0f / 32768);
-        }
-        return numFrames;
-    }
-
-    // Write FLOAT data from the first channel.
-    int32_t write(float *inputData, int32_t inputChannelCount, int32_t numFrames) {
-        // stop at end of buffer
-        if ((mFrameCounter + numFrames) > mMaxFrames) {
-            numFrames = mMaxFrames - mFrameCounter;
-        }
-        for (int i = 0; i < numFrames; i++) {
-            mData[mFrameCounter++] = inputData[i * inputChannelCount];
-        }
-        return numFrames;
-    }
-
-    int32_t size() {
-        return mFrameCounter;
-    }
-
-    float *getData() {
-        return mData;
-    }
-
-    void setSampleRate(int32_t sampleRate) {
-        mSampleRate = sampleRate;
-    }
-
-    int32_t getSampleRate() {
-        return mSampleRate;
-    }
-
-    int save(const char *fileName, bool writeShorts = true) {
-        SNDFILE *sndFile = nullptr;
-        int written = 0;
-        SF_INFO info = {
-                .frames = mFrameCounter,
-                .samplerate = mSampleRate,
-                .channels = 1,
-                .format = SF_FORMAT_WAV | (writeShorts ? SF_FORMAT_PCM_16 : SF_FORMAT_FLOAT)
-        };
-
-        sndFile = sf_open(fileName, SFM_WRITE, &info);
-        if (sndFile == nullptr) {
-            printf("AudioRecording::save(%s) failed to open file\n", fileName);
-            return -errno;
-        }
-
-        written = sf_writef_float(sndFile, mData, mFrameCounter);
-
-        sf_close(sndFile);
-        return written;
-    }
-
-    int load(const char *fileName) {
-        SNDFILE *sndFile = nullptr;
-        SF_INFO info;
-
-        sndFile = sf_open(fileName, SFM_READ, &info);
-        if (sndFile == nullptr) {
-            printf("AudioRecording::load(%s) failed to open file\n", fileName);
-            return -errno;
-        }
-
-        assert(info.channels == 1);
-        assert(info.format == SF_FORMAT_FLOAT);
-
-        setSampleRate(info.samplerate);
-        allocate(info.frames);
-        mFrameCounter = sf_readf_float(sndFile, mData, info.frames);
-
-        sf_close(sndFile);
-        return mFrameCounter;
-    }
-
-    /**
-     * Square the samples so they are all positive and so the peaks are emphasized.
-     */
-    void square() {
-        for (int i = 0; i < mFrameCounter; i++) {
-            const float sample = mData[i];
-            mData[i] = sample * sample;
-        }
-    }
-
-    /**
-     * Low pass filter the recording using a simple FIR filter.
-     * Note that the lowpass filter cutoff tracks the sample rate.
-     * That is OK because the impulse width is a fixed number of samples.
-     */
-    void lowPassFilter() {
-        for (int i = 0; i < mFrameCounter; i++) {
-            mData[i] = mLowPassFilter.filter(mData[i]);
-        }
-    }
-
-    /**
-     * Remove DC offset using a one-pole one-zero IIR filter.
-     */
-    void dcBlocker() {
-        const float R = 0.996; // narrow notch at zero Hz
-        float x1 = 0.0;
-        float y1 = 0.0;
-        for (int i = 0; i < mFrameCounter; i++) {
-            const float x = mData[i];
-            const float y = x - x1 + (R * y1);
-            mData[i] = y;
-            y1 = y;
-            x1 = x;
-        }
-    }
-
-private:
-    float        *mData = nullptr;
-    int32_t       mFrameCounter = 0;
-    int32_t       mMaxFrames = 0;
-    int32_t       mSampleRate = kDefaultSampleRate; // common default
-    LowPassFilter mLowPassFilter;
-};
-
-// ====================================================================================
-class LoopbackProcessor {
-public:
-    virtual ~LoopbackProcessor() = default;
-
-
-    enum process_result {
-        PROCESS_RESULT_OK,
-        PROCESS_RESULT_GLITCH
-    };
-
-    virtual void reset() {}
-
-    virtual process_result process(float *inputData, int inputChannelCount,
-                 float *outputData, int outputChannelCount,
-                 int numFrames) = 0;
-
-
-    virtual void report() = 0;
-
-    virtual void printStatus() {};
-
-    int32_t getResult() {
-        return mResult;
-    }
-
-    void setResult(int32_t result) {
-        mResult = result;
-    }
-
-    virtual bool isDone() {
-        return false;
-    }
-
-    virtual int save(const char *fileName) {
-        (void) fileName;
-        return AAUDIO_ERROR_UNIMPLEMENTED;
-    }
-
-    virtual int load(const char *fileName) {
-        (void) fileName;
-        return AAUDIO_ERROR_UNIMPLEMENTED;
-    }
-
-    virtual void setSampleRate(int32_t sampleRate) {
-        mSampleRate = sampleRate;
-    }
-
-    int32_t getSampleRate() {
-        return mSampleRate;
-    }
-
-    // Measure peak amplitude of buffer.
-    static float measurePeakAmplitude(float *inputData, int inputChannelCount, int numFrames) {
-        float peak = 0.0f;
-        for (int i = 0; i < numFrames; i++) {
-            const float pos = fabs(*inputData);
-            if (pos > peak) {
-                peak = pos;
-            }
-            inputData += inputChannelCount;
-        }
-        return peak;
-    }
-
-
-private:
-    int32_t mSampleRate = kDefaultSampleRate;
-    int32_t mResult = 0;
-};
-
-class PeakDetector {
-public:
-    float process(float input) {
-        float output = mPrevious * mDecay;
-        if (input > output) {
-            output = input;
-        }
-        mPrevious = output;
-        return output;
-    }
-
-private:
-    float  mDecay = 0.99f;
-    float  mPrevious = 0.0f;
-};
-
-// ====================================================================================
-/**
- * Measure latency given a loopback stream data.
- * Uses a state machine to cycle through various stages including:
- *
- */
-class EchoAnalyzer : public LoopbackProcessor {
-public:
-
-    EchoAnalyzer() : LoopbackProcessor() {
-        mAudioRecording.allocate(2 * getSampleRate());
-        mAudioRecording.setSampleRate(getSampleRate());
-    }
-
-    void setSampleRate(int32_t sampleRate) override {
-        LoopbackProcessor::setSampleRate(sampleRate);
-        mAudioRecording.setSampleRate(sampleRate);
-    }
-
-    void reset() override {
-        mDownCounter = getSampleRate() / 2;
-        mLoopCounter = 0;
-        mMeasuredLoopGain = 0.0f;
-        mEchoGain = 1.0f;
-        mState = STATE_INITIAL_SILENCE;
-    }
-
-    virtual bool isDone() {
-        return mState == STATE_DONE || mState == STATE_FAILED;
-    }
-
-    void setGain(float gain) {
-        mEchoGain = gain;
-    }
-
-    float getGain() {
-        return mEchoGain;
-    }
-
-    bool testLowPassFilter() {
-        LowPassFilter filter;
-        return filter.test();
-    }
-
-    void report() override {
-        printf("EchoAnalyzer ---------------\n");
-        if (getResult() != 0) {
-            printf(LOOPBACK_RESULT_TAG "result          = %d\n", getResult());
-            return;
-        }
-
-        // printf("LowPassFilter test %s\n", testLowPassFilter() ? "PASSED" : "FAILED");
-
-        printf(LOOPBACK_RESULT_TAG "measured.gain          = %8f\n", mMeasuredLoopGain);
-        printf(LOOPBACK_RESULT_TAG "echo.gain              = %8f\n", mEchoGain);
-        printf(LOOPBACK_RESULT_TAG "test.state             = %8d\n", mState);
-        printf(LOOPBACK_RESULT_TAG "test.state.name        = %8s\n", convertStateToText(mState));
-
-        if (mState == STATE_WAITING_FOR_SILENCE) {
-            printf("WARNING - Stuck waiting for silence. Input may be too noisy!\n");
-            setResult(ERROR_NOISY);
-        } else if (mMeasuredLoopGain >= 0.9999) {
-            printf("   ERROR - clipping, turn down volume slightly\n");
-            setResult(ERROR_CLIPPING);
-        } else if (mState != STATE_DONE && mState != STATE_GATHERING_ECHOS) {
-            printf("WARNING - Bad state. Check volume on device.\n");
-            setResult(ERROR_INVALID_STATE);
-        } else {
-            // Cleanup the signal to improve the auto-correlation.
-            mAudioRecording.dcBlocker();
-            mAudioRecording.square();
-            mAudioRecording.lowPassFilter();
-
-            printf("Please wait several seconds for auto-correlation to complete.\n");
-            measureLatencyFromEchos(mAudioRecording.getData(),
-                                    mAudioRecording.size(),
-                                    getSampleRate(),
-                                    &mLatencyReport);
-
-            double latencyMillis = kMillisPerSecond * (double) mLatencyReport.latencyInFrames
-                                   / getSampleRate();
-            printf(LOOPBACK_RESULT_TAG "latency.frames         = %8.2f\n",
-                   mLatencyReport.latencyInFrames);
-            printf(LOOPBACK_RESULT_TAG "latency.msec           = %8.2f\n",
-                   latencyMillis);
-            printf(LOOPBACK_RESULT_TAG "latency.confidence     = %8.6f\n",
-                   mLatencyReport.confidence);
-            if (mLatencyReport.confidence < kMinimumConfidence) {
-                printf("   ERROR - confidence too low!\n");
-                setResult(ERROR_CONFIDENCE);
-            }
-        }
-    }
-
-    void printStatus() override {
-        printf("st = %d, echo gain = %f ", mState, mEchoGain);
-    }
-
-    void sendImpulses(float *outputData, int outputChannelCount, int numFrames) {
-        while (numFrames-- > 0) {
-            float sample = s_Impulse[mSampleIndex++];
-            if (mSampleIndex >= kImpulseSizeInFrames) {
-                mSampleIndex = 0;
-            }
-
-            *outputData = sample;
-            outputData += outputChannelCount;
-        }
-    }
-
-    void sendOneImpulse(float *outputData, int outputChannelCount) {
-        mSampleIndex = 0;
-        sendImpulses(outputData, outputChannelCount, kImpulseSizeInFrames);
-    }
-
-    // @return number of frames for a typical block of processing
-    int32_t getBlockFrames() {
-        return getSampleRate() / 8;
-    }
-
-    process_result process(float *inputData, int inputChannelCount,
-                 float *outputData, int outputChannelCount,
-                 int numFrames) override {
-        int channelsValid = std::min(inputChannelCount, outputChannelCount);
-        float peak = 0.0f;
-        int numWritten;
-        int numSamples;
-
-        echo_state nextState = mState;
-
-        switch (mState) {
-            case STATE_INITIAL_SILENCE:
-                // Output silence at the beginning.
-                numSamples = numFrames * outputChannelCount;
-                for (int i = 0; i < numSamples; i++) {
-                    outputData[i] = 0;
-                }
-                mDownCounter -= numFrames;
-                if (mDownCounter <= 0) {
-                    nextState = STATE_MEASURING_GAIN;
-                    //printf("%5d: switch to STATE_MEASURING_GAIN\n", mLoopCounter);
-                    mDownCounter = getBlockFrames() * 2;
-                }
-                break;
-
-            case STATE_MEASURING_GAIN:
-                sendImpulses(outputData, outputChannelCount, numFrames);
-                peak = measurePeakAmplitude(inputData, inputChannelCount, numFrames);
-                // If we get several in a row then go to next state.
-                if (peak > mPulseThreshold) {
-                    mDownCounter -= numFrames;
-                    if (mDownCounter <= 0) {
-                        //printf("%5d: switch to STATE_WAITING_FOR_SILENCE, measured peak = %f\n",
-                        //       mLoopCounter, peak);
-                        mDownCounter = getBlockFrames();
-                        mMeasuredLoopGain = peak;  // assumes original pulse amplitude is one
-                        mSilenceThreshold = peak * 0.1; // scale silence to measured pulse
-                        // Calculate gain that will give us a nice decaying echo.
-                        mEchoGain = mDesiredEchoGain / mMeasuredLoopGain;
-                        if (mEchoGain > kMaxEchoGain) {
-                            printf("ERROR - loop gain too low. Increase the volume.\n");
-                            nextState = STATE_FAILED;
-                        } else {
-                            nextState = STATE_WAITING_FOR_SILENCE;
-                        }
-                    }
-                } else if (numFrames > kImpulseSizeInFrames){ // ignore short callbacks
-                    mDownCounter = getBlockFrames();
-                }
-                break;
-
-            case STATE_WAITING_FOR_SILENCE:
-                // Output silence and wait for the echos to die down.
-                numSamples = numFrames * outputChannelCount;
-                for (int i = 0; i < numSamples; i++) {
-                    outputData[i] = 0;
-                }
-                peak = measurePeakAmplitude(inputData, inputChannelCount, numFrames);
-                // If we get several in a row then go to next state.
-                if (peak < mSilenceThreshold) {
-                    mDownCounter -= numFrames;
-                    if (mDownCounter <= 0) {
-                        nextState = STATE_SENDING_PULSE;
-                        //printf("%5d: switch to STATE_SENDING_PULSE\n", mLoopCounter);
-                        mDownCounter = getBlockFrames();
-                    }
-                } else {
-                    mDownCounter = getBlockFrames();
-                }
-                break;
-
-            case STATE_SENDING_PULSE:
-                mAudioRecording.write(inputData, inputChannelCount, numFrames);
-                sendOneImpulse(outputData, outputChannelCount);
-                nextState = STATE_GATHERING_ECHOS;
-                //printf("%5d: switch to STATE_GATHERING_ECHOS\n", mLoopCounter);
-                break;
-
-            case STATE_GATHERING_ECHOS:
-                numWritten = mAudioRecording.write(inputData, inputChannelCount, numFrames);
-                peak = measurePeakAmplitude(inputData, inputChannelCount, numFrames);
-                if (peak > mMeasuredLoopGain) {
-                    mMeasuredLoopGain = peak;  // AGC might be raising gain so adjust it on the fly.
-                    // Recalculate gain that will give us a nice decaying echo.
-                    mEchoGain = mDesiredEchoGain / mMeasuredLoopGain;
-                }
-                // Echo input to output.
-                for (int i = 0; i < numFrames; i++) {
-                    int ic;
-                    for (ic = 0; ic < channelsValid; ic++) {
-                        outputData[ic] = inputData[ic] * mEchoGain;
-                    }
-                    for (; ic < outputChannelCount; ic++) {
-                        outputData[ic] = 0;
-                    }
-                    inputData += inputChannelCount;
-                    outputData += outputChannelCount;
-                }
-                if (numWritten  < numFrames) {
-                    nextState = STATE_DONE;
-                }
-                break;
-
-            case STATE_DONE:
-            case STATE_FAILED:
-            default:
-                break;
-        }
-
-        mState = nextState;
-        mLoopCounter++;
-        return PROCESS_RESULT_OK;
-    }
-
-    int save(const char *fileName) override {
-        return mAudioRecording.save(fileName);
-    }
-
-    int load(const char *fileName) override {
-        int result = mAudioRecording.load(fileName);
-        setSampleRate(mAudioRecording.getSampleRate());
-        mState = STATE_DONE;
-        return result;
-    }
-
-private:
-
-    enum error_code {
-        ERROR_OK = 0,
-        ERROR_NOISY = -99,
-        ERROR_CLIPPING,
-        ERROR_CONFIDENCE,
-        ERROR_INVALID_STATE
-    };
-
-    enum echo_state {
-        STATE_INITIAL_SILENCE,
-        STATE_MEASURING_GAIN,
-        STATE_WAITING_FOR_SILENCE,
-        STATE_SENDING_PULSE,
-        STATE_GATHERING_ECHOS,
-        STATE_DONE,
-        STATE_FAILED
-    };
-
-    const char *convertStateToText(echo_state state) {
-        const char *result = "Unknown";
-        switch(state) {
-            case STATE_INITIAL_SILENCE:
-                result = "INIT";
-                break;
-            case STATE_MEASURING_GAIN:
-                result = "GAIN";
-                break;
-            case STATE_WAITING_FOR_SILENCE:
-                result = "SILENCE";
-                break;
-            case STATE_SENDING_PULSE:
-                result = "PULSE";
-                break;
-            case STATE_GATHERING_ECHOS:
-                result = "ECHOS";
-                break;
-            case STATE_DONE:
-                result = "DONE";
-                break;
-            case STATE_FAILED:
-                result = "FAILED";
-                break;
-        }
-        return result;
-    }
-
-
-    int32_t         mDownCounter = 500;
-    int32_t         mLoopCounter = 0;
-    int32_t         mSampleIndex = 0;
-    float           mPulseThreshold = 0.02f;
-    float           mSilenceThreshold = 0.002f;
-    float           mMeasuredLoopGain = 0.0f;
-    float           mDesiredEchoGain = 0.95f;
-    float           mEchoGain = 1.0f;
-    echo_state      mState = STATE_INITIAL_SILENCE;
-
-    AudioRecording  mAudioRecording; // contains only the input after the gain detection burst
-    LatencyReport   mLatencyReport;
-    // PeakDetector    mPeakDetector;
-};
-
-
-// ====================================================================================
-/**
- * Output a steady sinewave and analyze the return signal.
- *
- * Use a cosine transform to measure the predicted magnitude and relative phase of the
- * looped back sine wave. Then generate a predicted signal and compare with the actual signal.
- */
-class SineAnalyzer : public LoopbackProcessor {
-public:
-
-    void report() override {
-        printf("SineAnalyzer ------------------\n");
-        printf(LOOPBACK_RESULT_TAG "peak.amplitude     = %8f\n", mPeakAmplitude);
-        printf(LOOPBACK_RESULT_TAG "sine.magnitude     = %8f\n", mMagnitude);
-        printf(LOOPBACK_RESULT_TAG "peak.noise         = %8f\n", mPeakNoise);
-        printf(LOOPBACK_RESULT_TAG "rms.noise          = %8f\n", mRootMeanSquareNoise);
-        float amplitudeRatio = mMagnitude / mPeakNoise;
-        float signalToNoise = amplitudeRatio * amplitudeRatio;
-        printf(LOOPBACK_RESULT_TAG "signal.to.noise    = %8.2f\n", signalToNoise);
-        float signalToNoiseDB = 10.0 * log(signalToNoise);
-        printf(LOOPBACK_RESULT_TAG "signal.to.noise.db = %8.2f\n", signalToNoiseDB);
-        if (signalToNoiseDB < MIN_SNRATIO_DB) {
-            printf("ERROR - signal to noise ratio is too low! < %d dB. Adjust volume.\n", MIN_SNRATIO_DB);
-            setResult(ERROR_NOISY);
-        }
-        printf(LOOPBACK_RESULT_TAG "frames.accumulated = %8d\n", mFramesAccumulated);
-        printf(LOOPBACK_RESULT_TAG "sine.period        = %8d\n", mSinePeriod);
-        printf(LOOPBACK_RESULT_TAG "test.state         = %8d\n", mState);
-        printf(LOOPBACK_RESULT_TAG "frame.count        = %8d\n", mFrameCounter);
-        // Did we ever get a lock?
-        bool gotLock = (mState == STATE_LOCKED) || (mGlitchCount > 0);
-        if (!gotLock) {
-            printf("ERROR - failed to lock on reference sine tone\n");
-            setResult(ERROR_NO_LOCK);
-        } else {
-            // Only print if meaningful.
-            printf(LOOPBACK_RESULT_TAG "glitch.count       = %8d\n", mGlitchCount);
-            printf(LOOPBACK_RESULT_TAG "max.glitch         = %8f\n", mMaxGlitchDelta);
-            if (mGlitchCount > 0) {
-                printf("ERROR - number of glitches > 0\n");
-                setResult(ERROR_GLITCHES);
-            }
-        }
-    }
-
-    void printStatus() override {
-        printf("st = %d, #gl = %3d,", mState, mGlitchCount);
-    }
-
-    double calculateMagnitude(double *phasePtr = NULL) {
-        if (mFramesAccumulated == 0) {
-            return 0.0;
-        }
-        double sinMean = mSinAccumulator / mFramesAccumulated;
-        double cosMean = mCosAccumulator / mFramesAccumulated;
-        double magnitude = 2.0 * sqrt( (sinMean * sinMean) + (cosMean * cosMean ));
-        if( phasePtr != NULL )
-        {
-            double phase = M_PI_2 - atan2( sinMean, cosMean );
-            *phasePtr = phase;
-        }
-        return magnitude;
-    }
-
-    /**
-     * @param inputData contains microphone data with sine signal feedback
-     * @param outputData contains the reference sine wave
-     */
-    process_result process(float *inputData, int inputChannelCount,
-                 float *outputData, int outputChannelCount,
-                 int numFrames) override {
-        process_result result = PROCESS_RESULT_OK;
-        mProcessCount++;
-
-        float peak = measurePeakAmplitude(inputData, inputChannelCount, numFrames);
-        if (peak > mPeakAmplitude) {
-            mPeakAmplitude = peak;
-        }
-
-        for (int i = 0; i < numFrames; i++) {
-            bool sineEnabled = true;
-            float sample = inputData[i * inputChannelCount];
-
-            float sinOut = sinf(mPhase);
-
-            switch (mState) {
-                case STATE_IDLE:
-                    sineEnabled = false;
-                    mDownCounter--;
-                    if (mDownCounter <= 0) {
-                        mState = STATE_MEASURE_NOISE;
-                        mDownCounter = NOISE_FRAME_COUNT;
-                    }
-                    break;
-                case STATE_MEASURE_NOISE:
-                    sineEnabled = false;
-                    mPeakNoise = std::max(abs(sample), mPeakNoise);
-                    mNoiseSumSquared += sample * sample;
-                    mDownCounter--;
-                    if (mDownCounter <= 0) {
-                        mState = STATE_WAITING_FOR_SIGNAL;
-                        mRootMeanSquareNoise = sqrt(mNoiseSumSquared / NOISE_FRAME_COUNT);
-                        mTolerance = std::max(MIN_TOLERANCE, mPeakNoise * 2.0f);
-                        mPhase = 0.0; // prevent spike at start
-                    }
-                    break;
-
-                case STATE_IMMUNE:
-                    mDownCounter--;
-                    if (mDownCounter <= 0) {
-                        mState = STATE_WAITING_FOR_SIGNAL;
-                    }
-                    break;
-
-                case STATE_WAITING_FOR_SIGNAL:
-                    if (peak > mThreshold) {
-                        mState = STATE_WAITING_FOR_LOCK;
-                        //printf("%5d: switch to STATE_WAITING_FOR_LOCK\n", mFrameCounter);
-                        resetAccumulator();
-                    }
-                    break;
-
-                case STATE_WAITING_FOR_LOCK:
-                    mSinAccumulator += sample * sinOut;
-                    mCosAccumulator += sample * cosf(mPhase);
-                    mFramesAccumulated++;
-                    // Must be a multiple of the period or the calculation will not be accurate.
-                    if (mFramesAccumulated == mSinePeriod * PERIODS_NEEDED_FOR_LOCK) {
-                        mPhaseOffset = 0.0;
-                        mMagnitude = calculateMagnitude(&mPhaseOffset);
-                        if (mMagnitude > mThreshold) {
-                            if (fabs(mPreviousPhaseOffset - mPhaseOffset) < 0.001) {
-                                mState = STATE_LOCKED;
-                                //printf("%5d: switch to STATE_LOCKED\n", mFrameCounter);
-                            }
-                            mPreviousPhaseOffset = mPhaseOffset;
-                        }
-                        resetAccumulator();
-                    }
-                    break;
-
-                case STATE_LOCKED: {
-                    // Predict next sine value
-                    float predicted = sinf(mPhase + mPhaseOffset) * mMagnitude;
-                    // printf("    predicted = %f, actual = %f\n", predicted, sample);
-
-                    float diff = predicted - sample;
-                    float absDiff = fabs(diff);
-                    mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
-                    if (absDiff > mTolerance) {
-                        mGlitchCount++;
-                        result = PROCESS_RESULT_GLITCH;
-                        //printf("%5d: Got a glitch # %d, predicted = %f, actual = %f\n",
-                        //       mFrameCounter, mGlitchCount, predicted, sample);
-                        mState = STATE_IMMUNE;
-                        mDownCounter = mSinePeriod * PERIODS_IMMUNE;
-                    }
-
-                    // Track incoming signal and slowly adjust magnitude to account
-                    // for drift in the DRC or AGC.
-                    mSinAccumulator += sample * sinOut;
-                    mCosAccumulator += sample * cosf(mPhase);
-                    mFramesAccumulated++;
-                    // Must be a multiple of the period or the calculation will not be accurate.
-                    if (mFramesAccumulated == mSinePeriod) {
-                        const double coefficient = 0.1;
-                        double phaseOffset = 0.0;
-                        double magnitude = calculateMagnitude(&phaseOffset);
-                        // One pole averaging filter.
-                        mMagnitude = (mMagnitude * (1.0 - coefficient)) + (magnitude * coefficient);
-                        resetAccumulator();
-                    }
-                } break;
-            }
-
-            float output = 0.0f;
-            // Output sine wave so we can measure it.
-            if (sineEnabled) {
-                output = (sinOut * mOutputAmplitude)
-                         + (mWhiteNoise.nextRandomDouble() * mNoiseAmplitude);
-                // printf("%5d: sin(%f) = %f, %f\n", i, mPhase, sinOut,  mPhaseIncrement);
-                // advance and wrap phase
-                mPhase += mPhaseIncrement;
-                if (mPhase > M_PI) {
-                    mPhase -= (2.0 * M_PI);
-                }
-            }
-            outputData[i * outputChannelCount] = output;
-
-
-            mFrameCounter++;
-        }
-        return result;
-    }
-
-    void resetAccumulator() {
-        mFramesAccumulated = 0;
-        mSinAccumulator = 0.0;
-        mCosAccumulator = 0.0;
-    }
-
-    void reset() override {
-        mGlitchCount = 0;
-        mState = STATE_IDLE;
-        mDownCounter = IDLE_FRAME_COUNT;
-        mPhaseIncrement = 2.0 * M_PI / mSinePeriod;
-        printf("phaseInc = %f for period %d\n", mPhaseIncrement, mSinePeriod);
-        resetAccumulator();
-        mProcessCount = 0;
-        mPeakNoise = 0.0f;
-        mNoiseSumSquared = 0.0;
-        mRootMeanSquareNoise = 0.0;
-        mPhase = 0.0f;
-        mMaxGlitchDelta = 0.0;
-    }
-
-private:
-
-    enum error_code {
-        OK,
-        ERROR_NO_LOCK = -80,
-        ERROR_GLITCHES,
-        ERROR_NOISY
-    };
-
-    enum sine_state_t {
-        STATE_IDLE,
-        STATE_MEASURE_NOISE,
-        STATE_IMMUNE,
-        STATE_WAITING_FOR_SIGNAL,
-        STATE_WAITING_FOR_LOCK,
-        STATE_LOCKED
-    };
-
-    enum constants {
-        // Arbitrary durations, assuming 48000 Hz
-        IDLE_FRAME_COUNT = 48 * 100,
-        NOISE_FRAME_COUNT = 48 * 600,
-        PERIODS_NEEDED_FOR_LOCK = 8,
-        PERIODS_IMMUNE = 2,
-        MIN_SNRATIO_DB = 65
-    };
-
-    static constexpr float MIN_TOLERANCE = 0.01;
-
-    int     mSinePeriod = 79;
-    double  mPhaseIncrement = 0.0;
-    double  mPhase = 0.0;
-    double  mPhaseOffset = 0.0;
-    double  mPreviousPhaseOffset = 0.0;
-    double  mMagnitude = 0.0;
-    double  mThreshold = 0.005;
-    double  mTolerance = MIN_TOLERANCE;
-    int32_t mFramesAccumulated = 0;
-    int32_t mProcessCount = 0;
-    double  mSinAccumulator = 0.0;
-    double  mCosAccumulator = 0.0;
-    float   mMaxGlitchDelta = 0.0f;
-    int32_t mGlitchCount = 0;
-    double  mPeakAmplitude = 0.0;
-    int     mDownCounter = IDLE_FRAME_COUNT;
-    int32_t mFrameCounter = 0;
-    float   mOutputAmplitude = 0.75;
-
-    // measure background noise
-    float   mPeakNoise = 0.0f;
-    double  mNoiseSumSquared = 0.0;
-    double  mRootMeanSquareNoise = 0.0;
-
-    PseudoRandom  mWhiteNoise;
-    float   mNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.
-
-    sine_state_t  mState = STATE_IDLE;
-};
-
-#undef LOOPBACK_RESULT_TAG
-
-#endif /* AAUDIO_EXAMPLES_LOOPBACK_ANALYSER_H */
diff --git a/media/libaaudio/examples/loopback/src/analyzer/GlitchAnalyzer.h b/media/libaaudio/examples/loopback/src/analyzer/GlitchAnalyzer.h
new file mode 100644
index 0000000..04435d1
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/GlitchAnalyzer.h
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2017 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 ANALYZER_GLITCH_ANALYZER_H
+#define ANALYZER_GLITCH_ANALYZER_H
+
+#include <algorithm>
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+
+#include "LatencyAnalyzer.h"
+#include "PseudoRandom.h"
+
+/**
+ * Output a steady sine wave and analyze the return signal.
+ *
+ * Use a cosine transform to measure the predicted magnitude and relative phase of the
+ * looped back sine wave. Then generate a predicted signal and compare with the actual signal.
+ */
+class GlitchAnalyzer : public LoopbackProcessor {
+public:
+
+    int32_t getState() const {
+        return mState;
+    }
+
+    double getPeakAmplitude() const {
+        return mPeakFollower.getLevel();
+    }
+
+    double getTolerance() {
+        return mTolerance;
+    }
+
+    void setTolerance(double tolerance) {
+        mTolerance = tolerance;
+        mScaledTolerance = mMagnitude * mTolerance;
+    }
+
+    void setMagnitude(double magnitude) {
+        mMagnitude = magnitude;
+        mScaledTolerance = mMagnitude * mTolerance;
+    }
+
+    int32_t getGlitchCount() const {
+        return mGlitchCount;
+    }
+
+    int32_t getStateFrameCount(int state) const {
+        return mStateFrameCounters[state];
+    }
+
+    double getSignalToNoiseDB() {
+        static const double threshold = 1.0e-14;
+        if (mMeanSquareSignal < threshold || mMeanSquareNoise < threshold) {
+            return 0.0;
+        } else {
+            double signalToNoise = mMeanSquareSignal / mMeanSquareNoise; // power ratio
+            double signalToNoiseDB = 10.0 * log(signalToNoise);
+            if (signalToNoiseDB < MIN_SNR_DB) {
+                ALOGD("ERROR - signal to noise ratio is too low! < %d dB. Adjust volume.",
+                     MIN_SNR_DB);
+                setResult(ERROR_VOLUME_TOO_LOW);
+            }
+            return signalToNoiseDB;
+        }
+    }
+
+    std::string analyze() override {
+        std::stringstream report;
+        report << "GlitchAnalyzer ------------------\n";
+        report << LOOPBACK_RESULT_TAG "peak.amplitude     = " << std::setw(8)
+               << getPeakAmplitude() << "\n";
+        report << LOOPBACK_RESULT_TAG "sine.magnitude     = " << std::setw(8)
+               << mMagnitude << "\n";
+        report << LOOPBACK_RESULT_TAG "rms.noise          = " << std::setw(8)
+               << mMeanSquareNoise << "\n";
+        report << LOOPBACK_RESULT_TAG "signal.to.noise.db = " << std::setw(8)
+               << getSignalToNoiseDB() << "\n";
+        report << LOOPBACK_RESULT_TAG "frames.accumulated = " << std::setw(8)
+               << mFramesAccumulated << "\n";
+        report << LOOPBACK_RESULT_TAG "sine.period        = " << std::setw(8)
+               << mSinePeriod << "\n";
+        report << LOOPBACK_RESULT_TAG "test.state         = " << std::setw(8)
+               << mState << "\n";
+        report << LOOPBACK_RESULT_TAG "frame.count        = " << std::setw(8)
+               << mFrameCounter << "\n";
+        // Did we ever get a lock?
+        bool gotLock = (mState == STATE_LOCKED) || (mGlitchCount > 0);
+        if (!gotLock) {
+            report << "ERROR - failed to lock on reference sine tone.\n";
+            setResult(ERROR_NO_LOCK);
+        } else {
+            // Only print if meaningful.
+            report << LOOPBACK_RESULT_TAG "glitch.count       = " << std::setw(8)
+                   << mGlitchCount << "\n";
+            report << LOOPBACK_RESULT_TAG "max.glitch         = " << std::setw(8)
+                   << mMaxGlitchDelta << "\n";
+            if (mGlitchCount > 0) {
+                report << "ERROR - number of glitches > 0\n";
+                setResult(ERROR_GLITCHES);
+            }
+        }
+        return report.str();
+    }
+
+    void printStatus() override {
+        ALOGD("st = %d, #gl = %3d,", mState, mGlitchCount);
+    }
+    /**
+     * Calculate the magnitude of the component of the input signal
+     * that matches the analysis frequency.
+     * Also calculate the phase that we can use to create a
+     * signal that matches that component.
+     * The phase will be between -PI and +PI.
+     */
+    double calculateMagnitude(double *phasePtr = nullptr) {
+        if (mFramesAccumulated == 0) {
+            return 0.0;
+        }
+        double sinMean = mSinAccumulator / mFramesAccumulated;
+        double cosMean = mCosAccumulator / mFramesAccumulated;
+        double magnitude = 2.0 * sqrt((sinMean * sinMean) + (cosMean * cosMean));
+        if (phasePtr != nullptr) {
+            double phase = M_PI_2 - atan2(sinMean, cosMean);
+            *phasePtr = phase;
+        }
+        return magnitude;
+    }
+
+    /**
+     * @param frameData contains microphone data with sine signal feedback
+     * @param channelCount
+     */
+    result_code processInputFrame(float *frameData, int /* channelCount */) override {
+        result_code result = RESULT_OK;
+
+        float sample = frameData[0];
+        float peak = mPeakFollower.process(sample);
+
+        // Force a periodic glitch to test the detector!
+        if (mForceGlitchDuration > 0) {
+            if (mForceGlitchCounter == 0) {
+                ALOGE("%s: force a glitch!!", __func__);
+                mForceGlitchCounter = getSampleRate();
+            } else if (mForceGlitchCounter <= mForceGlitchDuration) {
+                // Force an abrupt offset.
+                sample += (sample > 0.0) ? -0.5f : 0.5f;
+            }
+            --mForceGlitchCounter;
+        }
+
+        mStateFrameCounters[mState]++; // count how many frames we are in each state
+
+        switch (mState) {
+            case STATE_IDLE:
+                mDownCounter--;
+                if (mDownCounter <= 0) {
+                    mState = STATE_IMMUNE;
+                    mDownCounter = IMMUNE_FRAME_COUNT;
+                    mInputPhase = 0.0; // prevent spike at start
+                    mOutputPhase = 0.0;
+                }
+                break;
+
+            case STATE_IMMUNE:
+                mDownCounter--;
+                if (mDownCounter <= 0) {
+                    mState = STATE_WAITING_FOR_SIGNAL;
+                }
+                break;
+
+            case STATE_WAITING_FOR_SIGNAL:
+                if (peak > mThreshold) {
+                    mState = STATE_WAITING_FOR_LOCK;
+                    //ALOGD("%5d: switch to STATE_WAITING_FOR_LOCK", mFrameCounter);
+                    resetAccumulator();
+                }
+                break;
+
+            case STATE_WAITING_FOR_LOCK:
+                mSinAccumulator += sample * sinf(mInputPhase);
+                mCosAccumulator += sample * cosf(mInputPhase);
+                mFramesAccumulated++;
+                // Must be a multiple of the period or the calculation will not be accurate.
+                if (mFramesAccumulated == mSinePeriod * PERIODS_NEEDED_FOR_LOCK) {
+                    double phaseOffset = 0.0;
+                    setMagnitude(calculateMagnitude(&phaseOffset));
+//                    ALOGD("%s() mag = %f, offset = %f, prev = %f",
+//                            __func__, mMagnitude, mPhaseOffset, mPreviousPhaseOffset);
+                    if (mMagnitude > mThreshold) {
+                        if (abs(phaseOffset) < kMaxPhaseError) {
+                            mState = STATE_LOCKED;
+//                            ALOGD("%5d: switch to STATE_LOCKED", mFrameCounter);
+                        }
+                        // Adjust mInputPhase to match measured phase
+                        mInputPhase += phaseOffset;
+                    }
+                    resetAccumulator();
+                }
+                incrementInputPhase();
+                break;
+
+            case STATE_LOCKED: {
+                // Predict next sine value
+                double predicted = sinf(mInputPhase) * mMagnitude;
+                double diff = predicted - sample;
+                double absDiff = fabs(diff);
+                mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
+                if (absDiff > mScaledTolerance) {
+                    result = ERROR_GLITCHES;
+                    onGlitchStart();
+//                    LOGI("diff glitch detected, absDiff = %g", absDiff);
+                } else {
+                    mSumSquareSignal += predicted * predicted;
+                    mSumSquareNoise += diff * diff;
+                    // Track incoming signal and slowly adjust magnitude to account
+                    // for drift in the DRC or AGC.
+                    mSinAccumulator += sample * sinf(mInputPhase);
+                    mCosAccumulator += sample * cosf(mInputPhase);
+                    mFramesAccumulated++;
+                    // Must be a multiple of the period or the calculation will not be accurate.
+                    if (mFramesAccumulated == mSinePeriod) {
+                        const double coefficient = 0.1;
+                        double phaseOffset = 0.0;
+                        double magnitude = calculateMagnitude(&phaseOffset);
+                        // One pole averaging filter.
+                        setMagnitude((mMagnitude * (1.0 - coefficient)) + (magnitude * coefficient));
+
+                        mMeanSquareNoise = mSumSquareNoise * mInverseSinePeriod;
+                        mMeanSquareSignal = mSumSquareSignal * mInverseSinePeriod;
+                        resetAccumulator();
+
+                        if (abs(phaseOffset) > kMaxPhaseError) {
+                            result = ERROR_GLITCHES;
+                            onGlitchStart();
+                            ALOGD("phase glitch detected, phaseOffset = %g", phaseOffset);
+                        } else if (mMagnitude < mThreshold) {
+                            result = ERROR_GLITCHES;
+                            onGlitchStart();
+                            ALOGD("magnitude glitch detected, mMagnitude = %g", mMagnitude);
+                        }
+                    }
+                }
+                incrementInputPhase();
+            } break;
+
+            case STATE_GLITCHING: {
+                // Predict next sine value
+                mGlitchLength++;
+                double predicted = sinf(mInputPhase) * mMagnitude;
+                double diff = predicted - sample;
+                double absDiff = fabs(diff);
+                mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
+                if (absDiff < mScaledTolerance) { // close enough?
+                    // If we get a full sine period of non-glitch samples in a row then consider the glitch over.
+                    // We don't want to just consider a zero crossing the end of a glitch.
+                    if (mNonGlitchCount++ > mSinePeriod) {
+                        onGlitchEnd();
+                    }
+                } else {
+                    mNonGlitchCount = 0;
+                    if (mGlitchLength > (4 * mSinePeriod)) {
+                        relock();
+                    }
+                }
+                incrementInputPhase();
+            } break;
+
+            case NUM_STATES: // not a real state
+                break;
+        }
+
+        mFrameCounter++;
+
+        return result;
+    }
+
+    // advance and wrap phase
+    void incrementInputPhase() {
+        mInputPhase += mPhaseIncrement;
+        if (mInputPhase > M_PI) {
+            mInputPhase -= (2.0 * M_PI);
+        }
+    }
+
+    // advance and wrap phase
+    void incrementOutputPhase() {
+        mOutputPhase += mPhaseIncrement;
+        if (mOutputPhase > M_PI) {
+            mOutputPhase -= (2.0 * M_PI);
+        }
+    }
+
+    /**
+     * @param frameData upon return, contains the reference sine wave
+     * @param channelCount
+     */
+    result_code processOutputFrame(float *frameData, int channelCount) override {
+        float output = 0.0f;
+        // Output sine wave so we can measure it.
+        if (mState != STATE_IDLE) {
+            float sinOut = sinf(mOutputPhase);
+            incrementOutputPhase();
+            output = (sinOut * mOutputAmplitude)
+                     + (mWhiteNoise.nextRandomDouble() * kNoiseAmplitude);
+            // ALOGD("sin(%f) = %f, %f\n", mOutputPhase, sinOut,  mPhaseIncrement);
+        }
+        frameData[0] = output;
+        for (int i = 1; i < channelCount; i++) {
+            frameData[i] = 0.0f;
+        }
+        return RESULT_OK;
+    }
+
+    void onGlitchStart() {
+        mGlitchCount++;
+//        ALOGD("%5d: STARTED a glitch # %d", mFrameCounter, mGlitchCount);
+        mState = STATE_GLITCHING;
+        mGlitchLength = 1;
+        mNonGlitchCount = 0;
+    }
+
+    void onGlitchEnd() {
+//        ALOGD("%5d: ENDED a glitch # %d, length = %d", mFrameCounter, mGlitchCount, mGlitchLength);
+        mState = STATE_LOCKED;
+        resetAccumulator();
+    }
+
+    // reset the sine wave detector
+    void resetAccumulator() {
+        mFramesAccumulated = 0;
+        mSinAccumulator = 0.0;
+        mCosAccumulator = 0.0;
+        mSumSquareSignal = 0.0;
+        mSumSquareNoise = 0.0;
+    }
+
+    void relock() {
+//        ALOGD("relock: %d because of a very long %d glitch", mFrameCounter, mGlitchLength);
+        mState = STATE_WAITING_FOR_LOCK;
+        resetAccumulator();
+    }
+
+    void reset() override {
+        LoopbackProcessor::reset();
+        mState = STATE_IDLE;
+        mDownCounter = IDLE_FRAME_COUNT;
+        resetAccumulator();
+    }
+
+    void prepareToTest() override {
+        LoopbackProcessor::prepareToTest();
+        mSinePeriod = getSampleRate() / kTargetGlitchFrequency;
+        mOutputPhase = 0.0f;
+        mInverseSinePeriod = 1.0 / mSinePeriod;
+        mPhaseIncrement = 2.0 * M_PI * mInverseSinePeriod;
+        mGlitchCount = 0;
+        mMaxGlitchDelta = 0.0;
+        for (int i = 0; i < NUM_STATES; i++) {
+            mStateFrameCounters[i] = 0;
+        }
+    }
+
+private:
+
+    // These must match the values in GlitchActivity.java
+    enum sine_state_t {
+        STATE_IDLE,               // beginning
+        STATE_IMMUNE,             // ignoring input, waiting fo HW to settle
+        STATE_WAITING_FOR_SIGNAL, // looking for a loud signal
+        STATE_WAITING_FOR_LOCK,   // trying to lock onto the phase of the sine
+        STATE_LOCKED,             // locked on the sine wave, looking for glitches
+        STATE_GLITCHING,           // locked on the sine wave but glitching
+        NUM_STATES
+    };
+
+    enum constants {
+        // Arbitrary durations, assuming 48000 Hz
+        IDLE_FRAME_COUNT = 48 * 100,
+        IMMUNE_FRAME_COUNT = 48 * 100,
+        PERIODS_NEEDED_FOR_LOCK = 8,
+        MIN_SNR_DB = 65
+    };
+
+    static constexpr float kNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.
+    static constexpr int kTargetGlitchFrequency = 607;
+    static constexpr double kMaxPhaseError = M_PI * 0.05;
+
+    float   mTolerance = 0.10; // scaled from 0.0 to 1.0
+    double  mThreshold = 0.005;
+    int     mSinePeriod = 1; // this will be set before use
+    double  mInverseSinePeriod = 1.0;
+
+    int32_t mStateFrameCounters[NUM_STATES];
+
+    double  mPhaseIncrement = 0.0;
+    double  mInputPhase = 0.0;
+    double  mOutputPhase = 0.0;
+    double  mMagnitude = 0.0;
+    int32_t mFramesAccumulated = 0;
+    double  mSinAccumulator = 0.0;
+    double  mCosAccumulator = 0.0;
+    double  mMaxGlitchDelta = 0.0;
+    int32_t mGlitchCount = 0;
+    int32_t mNonGlitchCount = 0;
+    int32_t mGlitchLength = 0;
+    // This is used for processing every frame so we cache it here.
+    double  mScaledTolerance = 0.0;
+    int     mDownCounter = IDLE_FRAME_COUNT;
+    int32_t mFrameCounter = 0;
+    double  mOutputAmplitude = 0.75;
+
+    int32_t mForceGlitchDuration = 0; // if > 0 then force a glitch for debugging
+    int32_t mForceGlitchCounter = 4 * 48000; // count down and trigger at zero
+
+    // measure background noise continuously as a deviation from the expected signal
+    double  mSumSquareSignal = 0.0;
+    double  mSumSquareNoise = 0.0;
+    double  mMeanSquareSignal = 0.0;
+    double  mMeanSquareNoise = 0.0;
+
+    PeakDetector  mPeakFollower;
+
+    PseudoRandom  mWhiteNoise;
+
+    sine_state_t  mState = STATE_IDLE;
+};
+
+
+#endif //ANALYZER_GLITCH_ANALYZER_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/LatencyAnalyzer.h b/media/libaaudio/examples/loopback/src/analyzer/LatencyAnalyzer.h
new file mode 100644
index 0000000..e506791
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/LatencyAnalyzer.h
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/**
+ * Tools for measuring latency and for detecting glitches.
+ * These classes are pure math and can be used with any audio system.
+ */
+
+#ifndef ANALYZER_LATENCY_ANALYZER_H
+#define ANALYZER_LATENCY_ANALYZER_H
+
+#include <algorithm>
+#include <assert.h>
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+#include <math.h>
+#include <memory>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vector>
+
+#include "PeakDetector.h"
+#include "PseudoRandom.h"
+#include "RandomPulseGenerator.h"
+
+// This is used when the code is in Oboe.
+#ifndef ALOGD
+#define ALOGD printf
+#define ALOGE printf
+#define ALOGW printf
+#endif
+
+#define LOOPBACK_RESULT_TAG  "RESULT: "
+
+static constexpr int32_t kDefaultSampleRate = 48000;
+static constexpr int32_t kMillisPerSecond   = 1000;
+static constexpr int32_t kMaxLatencyMillis  = 700;  // arbitrary and generous
+static constexpr double  kMinimumConfidence = 0.2;
+
+struct LatencyReport {
+    int32_t latencyInFrames = 0.0;
+    double confidence = 0.0;
+
+    void reset() {
+        latencyInFrames = 0;
+        confidence = 0.0;
+    }
+};
+
+// Calculate a normalized cross correlation.
+static double calculateNormalizedCorrelation(const float *a,
+                                             const float *b,
+                                             int windowSize) {
+    double correlation = 0.0;
+    double sumProducts = 0.0;
+    double sumSquares = 0.0;
+
+    // Correlate a against b.
+    for (int i = 0; i < windowSize; i++) {
+        float s1 = a[i];
+        float s2 = b[i];
+        // Use a normalized cross-correlation.
+        sumProducts += s1 * s2;
+        sumSquares += ((s1 * s1) + (s2 * s2));
+    }
+
+    if (sumSquares >= 1.0e-9) {
+        correlation = 2.0 * sumProducts / sumSquares;
+    }
+    return correlation;
+}
+
+static double calculateRootMeanSquare(float *data, int32_t numSamples) {
+    double sum = 0.0;
+    for (int32_t i = 0; i < numSamples; i++) {
+        float sample = data[i];
+        sum += sample * sample;
+    }
+    return sqrt(sum / numSamples);
+}
+
+/**
+ * Monophonic recording with processing.
+ */
+class AudioRecording
+{
+public:
+
+    void allocate(int maxFrames) {
+        mData = std::make_unique<float[]>(maxFrames);
+        mMaxFrames = maxFrames;
+    }
+
+    // Write SHORT data from the first channel.
+    int32_t write(int16_t *inputData, int32_t inputChannelCount, int32_t numFrames) {
+        // stop at end of buffer
+        if ((mFrameCounter + numFrames) > mMaxFrames) {
+            numFrames = mMaxFrames - mFrameCounter;
+        }
+        for (int i = 0; i < numFrames; i++) {
+            mData[mFrameCounter++] = inputData[i * inputChannelCount] * (1.0f / 32768);
+        }
+        return numFrames;
+    }
+
+    // Write FLOAT data from the first channel.
+    int32_t write(float *inputData, int32_t inputChannelCount, int32_t numFrames) {
+        // stop at end of buffer
+        if ((mFrameCounter + numFrames) > mMaxFrames) {
+            numFrames = mMaxFrames - mFrameCounter;
+        }
+        for (int i = 0; i < numFrames; i++) {
+            mData[mFrameCounter++] = inputData[i * inputChannelCount];
+        }
+        return numFrames;
+    }
+
+    // Write FLOAT data from the first channel.
+    int32_t write(float sample) {
+        // stop at end of buffer
+        if (mFrameCounter < mMaxFrames) {
+            mData[mFrameCounter++] = sample;
+            return 1;
+        }
+        return 0;
+    }
+
+    void clear() {
+        mFrameCounter = 0;
+    }
+    int32_t size() const {
+        return mFrameCounter;
+    }
+
+    bool isFull() const {
+        return mFrameCounter >= mMaxFrames;
+    }
+
+    float *getData() const {
+        return mData.get();
+    }
+
+    void setSampleRate(int32_t sampleRate) {
+        mSampleRate = sampleRate;
+    }
+
+    int32_t getSampleRate() const {
+        return mSampleRate;
+    }
+
+    /**
+     * Square the samples so they are all positive and so the peaks are emphasized.
+     */
+    void square() {
+        float *x = mData.get();
+        for (int i = 0; i < mFrameCounter; i++) {
+            x[i] *= x[i];
+        }
+    }
+
+    /**
+     * Amplify a signal so that the peak matches the specified target.
+     *
+     * @param target final max value
+     * @return gain applied to signal
+     */
+    float normalize(float target) {
+        float maxValue = 1.0e-9f;
+        for (int i = 0; i < mFrameCounter; i++) {
+            maxValue = std::max(maxValue, abs(mData[i]));
+        }
+        float gain = target / maxValue;
+        for (int i = 0; i < mFrameCounter; i++) {
+            mData[i] *= gain;
+        }
+        return gain;
+    }
+
+private:
+    std::unique_ptr<float[]> mData;
+    int32_t       mFrameCounter = 0;
+    int32_t       mMaxFrames = 0;
+    int32_t       mSampleRate = kDefaultSampleRate; // common default
+};
+
+static int measureLatencyFromPulse(AudioRecording &recorded,
+                                   AudioRecording &pulse,
+                                   LatencyReport *report) {
+
+    report->latencyInFrames = 0;
+    report->confidence = 0.0;
+
+    int numCorrelations = recorded.size() - pulse.size();
+    if (numCorrelations < 10) {
+        ALOGE("%s() recording too small = %d frames\n", __func__, recorded.size());
+        return -1;
+    }
+    std::unique_ptr<float[]> correlations= std::make_unique<float[]>(numCorrelations);
+
+    // Correlate pulse against the recorded data.
+    for (int i = 0; i < numCorrelations; i++) {
+        float correlation = (float) calculateNormalizedCorrelation(&recorded.getData()[i],
+                                                                   &pulse.getData()[0],
+                                                                   pulse.size());
+        correlations[i] = correlation;
+    }
+
+    // Find highest peak in correlation array.
+    float peakCorrelation = 0.0;
+    int peakIndex = -1;
+    for (int i = 0; i < numCorrelations; i++) {
+        float value = abs(correlations[i]);
+        if (value > peakCorrelation) {
+            peakCorrelation = value;
+            peakIndex = i;
+        }
+    }
+    if (peakIndex < 0) {
+        ALOGE("%s() no signal for correlation\n", __func__);
+        return -2;
+    }
+
+    report->latencyInFrames = peakIndex;
+    report->confidence = peakCorrelation;
+
+    return 0;
+}
+
+// ====================================================================================
+class LoopbackProcessor {
+public:
+    virtual ~LoopbackProcessor() = default;
+
+    enum result_code {
+        RESULT_OK = 0,
+        ERROR_NOISY = -99,
+        ERROR_VOLUME_TOO_LOW,
+        ERROR_VOLUME_TOO_HIGH,
+        ERROR_CONFIDENCE,
+        ERROR_INVALID_STATE,
+        ERROR_GLITCHES,
+        ERROR_NO_LOCK
+    };
+
+    virtual void prepareToTest() {
+        reset();
+    }
+
+    virtual void reset() {
+        mResult = 0;
+        mResetCount++;
+    }
+
+    virtual result_code processInputFrame(float *frameData, int channelCount) = 0;
+    virtual result_code processOutputFrame(float *frameData, int channelCount) = 0;
+
+    void process(float *inputData, int inputChannelCount, int numInputFrames,
+                 float *outputData, int outputChannelCount, int numOutputFrames) {
+        int numBoth = std::min(numInputFrames, numOutputFrames);
+        // Process one frame at a time.
+        for (int i = 0; i < numBoth; i++) {
+            processInputFrame(inputData, inputChannelCount);
+            inputData += inputChannelCount;
+            processOutputFrame(outputData, outputChannelCount);
+            outputData += outputChannelCount;
+        }
+        // If there is more input than output.
+        for (int i = numBoth; i < numInputFrames; i++) {
+            processInputFrame(inputData, inputChannelCount);
+            inputData += inputChannelCount;
+        }
+        // If there is more output than input.
+        for (int i = numBoth; i < numOutputFrames; i++) {
+            processOutputFrame(outputData, outputChannelCount);
+            outputData += outputChannelCount;
+        }
+    }
+
+    virtual std::string analyze() = 0;
+
+    virtual void printStatus() {};
+
+    int32_t getResult() {
+        return mResult;
+    }
+
+    void setResult(int32_t result) {
+        mResult = result;
+    }
+
+    virtual bool isDone() {
+        return false;
+    }
+
+    virtual int save(const char *fileName) {
+        (void) fileName;
+        return -1;
+    }
+
+    virtual int load(const char *fileName) {
+        (void) fileName;
+        return -1;
+    }
+
+    virtual void setSampleRate(int32_t sampleRate) {
+        mSampleRate = sampleRate;
+    }
+
+    int32_t getSampleRate() const {
+        return mSampleRate;
+    }
+
+    int32_t getResetCount() const {
+        return mResetCount;
+    }
+
+    /** Called when not enough input frames could be read after synchronization.
+     */
+    virtual void onInsufficientRead() {
+        reset();
+    }
+
+protected:
+    int32_t   mResetCount = 0;
+
+private:
+    int32_t mSampleRate = kDefaultSampleRate;
+    int32_t mResult = 0;
+};
+
+class LatencyAnalyzer : public LoopbackProcessor {
+public:
+
+    LatencyAnalyzer() : LoopbackProcessor() {}
+    virtual ~LatencyAnalyzer() = default;
+
+    virtual int32_t getProgress() const = 0;
+
+    virtual int getState() = 0;
+
+    // @return latency in frames
+    virtual int32_t getMeasuredLatency() = 0;
+
+    virtual double getMeasuredConfidence() = 0;
+
+    virtual double getBackgroundRMS() = 0;
+
+    virtual double getSignalRMS() = 0;
+
+};
+
+// ====================================================================================
+/**
+ * Measure latency given a loopback stream data.
+ * Use an encoded bit train as the sound source because it
+ * has an unambiguous correlation value.
+ * Uses a state machine to cycle through various stages.
+ *
+ */
+class PulseLatencyAnalyzer : public LatencyAnalyzer {
+public:
+
+    PulseLatencyAnalyzer() : LatencyAnalyzer() {
+        int32_t maxLatencyFrames = getSampleRate() * kMaxLatencyMillis / kMillisPerSecond;
+        int32_t numPulseBits = getSampleRate() * kPulseLengthMillis
+                / (kFramesPerEncodedBit * kMillisPerSecond);
+        int32_t  pulseLength = numPulseBits * kFramesPerEncodedBit;
+        mFramesToRecord = pulseLength + maxLatencyFrames;
+        mAudioRecording.allocate(mFramesToRecord);
+        mAudioRecording.setSampleRate(getSampleRate());
+        generateRandomPulse(pulseLength);
+    }
+
+    void generateRandomPulse(int32_t pulseLength) {
+        mPulse.allocate(pulseLength);
+        RandomPulseGenerator pulser(kFramesPerEncodedBit);
+        for (int i = 0; i < pulseLength; i++) {
+            mPulse.write(pulser.nextFloat());
+        }
+    }
+
+    int getState() override {
+        return mState;
+    }
+
+    void setSampleRate(int32_t sampleRate) override {
+        LoopbackProcessor::setSampleRate(sampleRate);
+        mAudioRecording.setSampleRate(sampleRate);
+    }
+
+    void reset() override {
+        LoopbackProcessor::reset();
+        mDownCounter = getSampleRate() / 2;
+        mLoopCounter = 0;
+
+        mPulseCursor = 0;
+        mBackgroundSumSquare = 0.0f;
+        mBackgroundSumCount = 0;
+        mBackgroundRMS = 0.0f;
+        mSignalRMS = 0.0f;
+
+        mState = STATE_MEASURE_BACKGROUND;
+        mAudioRecording.clear();
+        mLatencyReport.reset();
+    }
+
+    bool hasEnoughData() {
+        return mAudioRecording.isFull();
+    }
+
+    bool isDone() override {
+        return mState == STATE_DONE;
+    }
+
+    int32_t getProgress() const override {
+        return mAudioRecording.size();
+    }
+
+    std::string analyze() override {
+        std::stringstream report;
+        report << "PulseLatencyAnalyzer ---------------\n";
+        report << LOOPBACK_RESULT_TAG "test.state             = "
+                << std::setw(8) << mState << "\n";
+        report << LOOPBACK_RESULT_TAG "test.state.name        = "
+                << convertStateToText(mState) << "\n";
+        report << LOOPBACK_RESULT_TAG "background.rms         = "
+                << std::setw(8) << mBackgroundRMS << "\n";
+
+        int32_t newResult = RESULT_OK;
+        if (mState != STATE_GOT_DATA) {
+            report << "WARNING - Bad state. Check volume on device.\n";
+            // setResult(ERROR_INVALID_STATE);
+        } else {
+            float gain = mAudioRecording.normalize(1.0f);
+            measureLatencyFromPulse(mAudioRecording,
+                                    mPulse,
+                                    &mLatencyReport);
+
+            if (mLatencyReport.confidence < kMinimumConfidence) {
+                report << "   ERROR - confidence too low!";
+                newResult = ERROR_CONFIDENCE;
+            } else {
+                mSignalRMS = calculateRootMeanSquare(
+                        &mAudioRecording.getData()[mLatencyReport.latencyInFrames], mPulse.size())
+                                / gain;
+            }
+            double latencyMillis = kMillisPerSecond * (double) mLatencyReport.latencyInFrames
+                                   / getSampleRate();
+            report << LOOPBACK_RESULT_TAG "latency.frames         = " << std::setw(8)
+                   << mLatencyReport.latencyInFrames << "\n";
+            report << LOOPBACK_RESULT_TAG "latency.msec           = " << std::setw(8)
+                   << latencyMillis << "\n";
+            report << LOOPBACK_RESULT_TAG "latency.confidence     = " << std::setw(8)
+                   << mLatencyReport.confidence << "\n";
+        }
+        mState = STATE_DONE;
+        if (getResult() == RESULT_OK) {
+            setResult(newResult);
+        }
+
+        return report.str();
+    }
+
+    int32_t getMeasuredLatency() override {
+        return mLatencyReport.latencyInFrames;
+    }
+
+    double getMeasuredConfidence() override {
+        return mLatencyReport.confidence;
+    }
+
+    double getBackgroundRMS() override {
+        return mBackgroundRMS;
+    }
+
+    double getSignalRMS() override {
+        return mSignalRMS;
+    }
+
+    void printStatus() override {
+        ALOGD("st = %d", mState);
+    }
+
+    result_code processInputFrame(float *frameData, int channelCount) override {
+        echo_state nextState = mState;
+        mLoopCounter++;
+
+        switch (mState) {
+            case STATE_MEASURE_BACKGROUND:
+                // Measure background RMS on channel 0
+                mBackgroundSumSquare += frameData[0] * frameData[0];
+                mBackgroundSumCount++;
+                mDownCounter--;
+                if (mDownCounter <= 0) {
+                    mBackgroundRMS = sqrtf(mBackgroundSumSquare / mBackgroundSumCount);
+                    nextState = STATE_IN_PULSE;
+                    mPulseCursor = 0;
+                }
+                break;
+
+            case STATE_IN_PULSE:
+                // Record input until the mAudioRecording is full.
+                mAudioRecording.write(frameData, channelCount, 1);
+                if (hasEnoughData()) {
+                    nextState = STATE_GOT_DATA;
+                }
+                break;
+
+            case STATE_GOT_DATA:
+            case STATE_DONE:
+            default:
+                break;
+        }
+
+        mState = nextState;
+        return RESULT_OK;
+    }
+
+    result_code processOutputFrame(float *frameData, int channelCount) override {
+        switch (mState) {
+            case STATE_IN_PULSE:
+                if (mPulseCursor < mPulse.size()) {
+                    float pulseSample = mPulse.getData()[mPulseCursor++];
+                    for (int i = 0; i < channelCount; i++) {
+                        frameData[i] = pulseSample;
+                    }
+                } else {
+                    for (int i = 0; i < channelCount; i++) {
+                        frameData[i] = 0;
+                    }
+                }
+                break;
+
+            case STATE_MEASURE_BACKGROUND:
+            case STATE_GOT_DATA:
+            case STATE_DONE:
+            default:
+                for (int i = 0; i < channelCount; i++) {
+                    frameData[i] = 0.0f; // silence
+                }
+                break;
+        }
+
+        return RESULT_OK;
+    }
+
+private:
+
+    enum echo_state {
+        STATE_MEASURE_BACKGROUND,
+        STATE_IN_PULSE,
+        STATE_GOT_DATA, // must match RoundTripLatencyActivity.java
+        STATE_DONE,
+    };
+
+    const char *convertStateToText(echo_state state) {
+        switch (state) {
+            case STATE_MEASURE_BACKGROUND:
+                return "INIT";
+            case STATE_IN_PULSE:
+                return "PULSE";
+            case STATE_GOT_DATA:
+                return "GOT_DATA";
+            case STATE_DONE:
+                return "DONE";
+        }
+        return "UNKNOWN";
+    }
+
+    int32_t         mDownCounter = 500;
+    int32_t         mLoopCounter = 0;
+    echo_state      mState = STATE_MEASURE_BACKGROUND;
+
+    static constexpr int32_t kFramesPerEncodedBit = 8; // multiple of 2
+    static constexpr int32_t kPulseLengthMillis = 500;
+
+    AudioRecording     mPulse;
+    int32_t            mPulseCursor = 0;
+
+    double             mBackgroundSumSquare = 0.0;
+    int32_t            mBackgroundSumCount = 0;
+    double             mBackgroundRMS = 0.0;
+    double             mSignalRMS = 0.0;
+    int32_t            mFramesToRecord = 0;
+
+    AudioRecording     mAudioRecording; // contains only the input after starting the pulse
+    LatencyReport      mLatencyReport;
+};
+
+#endif // ANALYZER_LATENCY_ANALYZER_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/ManchesterEncoder.h b/media/libaaudio/examples/loopback/src/analyzer/ManchesterEncoder.h
new file mode 100644
index 0000000..0a4bd5b
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/ManchesterEncoder.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 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 ANALYZER_MANCHESTER_ENCODER_H
+#define ANALYZER_MANCHESTER_ENCODER_H
+
+#include <cstdint>
+
+/**
+ * Encode bytes using Manchester Coding scheme.
+ *
+ * Manchester Code is self clocking.
+ * There is a transition in the middle of every bit.
+ * Zero is high then low.
+ * One is low then high.
+ *
+ * This avoids having long DC sections that would droop when
+ * passed though analog circuits with AC coupling.
+ *
+ * IEEE 802.3 compatible.
+ */
+
+class ManchesterEncoder {
+public:
+    ManchesterEncoder(int samplesPerPulse)
+            : mSamplesPerPulse(samplesPerPulse)
+            , mSamplesPerPulseHalf(samplesPerPulse / 2)
+            , mCursor(samplesPerPulse) {
+    }
+
+    virtual ~ManchesterEncoder() = default;
+
+    /**
+     * This will be called when the next byte is needed.
+     * @return
+     */
+    virtual uint8_t onNextByte() = 0;
+
+    /**
+     * Generate the next floating point sample.
+     * @return
+     */
+    virtual float nextFloat() {
+        advanceSample();
+        if (mCurrentBit) {
+            return (mCursor < mSamplesPerPulseHalf) ? -1.0f : 1.0f; // one
+        } else {
+            return (mCursor < mSamplesPerPulseHalf) ? 1.0f : -1.0f; // zero
+        }
+    }
+
+protected:
+    /**
+     * This will be called when a new bit is ready to be encoded.
+     * It can be used to prepare the encoded samples.
+     * @param current
+     */
+    virtual void onNextBit(bool /* current */) {};
+
+    void advanceSample() {
+        // Are we ready for a new bit?
+        if (++mCursor >= mSamplesPerPulse) {
+            mCursor = 0;
+            if (mBitsLeft == 0) {
+                mCurrentByte = onNextByte();
+                mBitsLeft = 8;
+            }
+            --mBitsLeft;
+            mCurrentBit = (mCurrentByte >> mBitsLeft) & 1;
+            onNextBit(mCurrentBit);
+        }
+    }
+
+    bool getCurrentBit() {
+        return mCurrentBit;
+    }
+
+    const int mSamplesPerPulse;
+    const int mSamplesPerPulseHalf;
+    int       mCursor;
+    int       mBitsLeft = 0;
+    uint8_t   mCurrentByte = 0;
+    bool      mCurrentBit = false;
+};
+#endif //ANALYZER_MANCHESTER_ENCODER_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/PeakDetector.h b/media/libaaudio/examples/loopback/src/analyzer/PeakDetector.h
new file mode 100644
index 0000000..4b3b4e7
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/PeakDetector.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 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 ANALYZER_PEAK_DETECTOR_H
+#define ANALYZER_PEAK_DETECTOR_H
+
+#include <math.h>
+
+/**
+ * Measure a peak envelope by rising with the peaks,
+ * and decaying exponentially after each peak.
+ * The absolute value of the input signal is used.
+ */
+class PeakDetector {
+public:
+
+    void reset() {
+        mLevel = 0.0;
+    }
+
+    double process(double input) {
+        mLevel *= mDecay; // exponential decay
+        input = fabs(input);
+        // never fall below the input signal
+        if (input > mLevel) {
+            mLevel = input;
+        }
+        return mLevel;
+    }
+
+    double getLevel() const {
+        return mLevel;
+    }
+
+    double getDecay() const {
+        return mDecay;
+    }
+
+    /**
+     * Multiply the level by this amount on every iteration.
+     * This provides an exponential decay curve.
+     * A value just under 1.0 is best, for example, 0.99;
+     * @param decay scale level for each input
+     */
+    void setDecay(double decay) {
+        mDecay = decay;
+    }
+
+private:
+    static constexpr double kDefaultDecay = 0.99f;
+
+    double mLevel = 0.0;
+    double mDecay = kDefaultDecay;
+};
+#endif //ANALYZER_PEAK_DETECTOR_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/PseudoRandom.h b/media/libaaudio/examples/loopback/src/analyzer/PseudoRandom.h
new file mode 100644
index 0000000..1c4938c
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/PseudoRandom.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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 ANALYZER_PSEUDORANDOM_H
+#define ANALYZER_PSEUDORANDOM_H
+
+#include <cctype>
+
+class PseudoRandom {
+public:
+    PseudoRandom(int64_t seed = 99887766)
+            :    mSeed(seed)
+    {}
+
+    /**
+     * Returns the next random double from -1.0 to 1.0
+     *
+     * @return value from -1.0 to 1.0
+     */
+    double nextRandomDouble() {
+        return nextRandomInteger() * (0.5 / (((int32_t)1) << 30));
+    }
+
+    /** Calculate random 32 bit number using linear-congruential method
+     * with known real-time performance.
+     */
+    int32_t nextRandomInteger() {
+#if __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_add_overflow)
+        int64_t prod;
+        // Use values for 64-bit sequence from MMIX by Donald Knuth.
+        __builtin_mul_overflow(mSeed, (int64_t)6364136223846793005, &prod);
+        __builtin_add_overflow(prod, (int64_t)1442695040888963407, &mSeed);
+#else
+        mSeed = (mSeed * (int64_t)6364136223846793005) + (int64_t)1442695040888963407;
+#endif
+        return (int32_t) (mSeed >> 32); // The higher bits have a longer sequence.
+    }
+
+private:
+    int64_t mSeed;
+};
+
+#endif //ANALYZER_PSEUDORANDOM_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/RandomPulseGenerator.h b/media/libaaudio/examples/loopback/src/analyzer/RandomPulseGenerator.h
new file mode 100644
index 0000000..030050b
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/RandomPulseGenerator.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 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 ANALYZER_RANDOM_PULSE_GENERATOR_H
+#define ANALYZER_RANDOM_PULSE_GENERATOR_H
+
+#include <stdlib.h>
+#include "RoundedManchesterEncoder.h"
+
+/**
+ * Encode random ones and zeros using Manchester Code per IEEE 802.3.
+ */
+class RandomPulseGenerator : public RoundedManchesterEncoder {
+public:
+    RandomPulseGenerator(int samplesPerPulse)
+    : RoundedManchesterEncoder(samplesPerPulse) {
+    }
+
+    virtual ~RandomPulseGenerator() = default;
+
+    /**
+     * This will be called when the next byte is needed.
+     * @return random byte
+     */
+    uint8_t onNextByte() override {
+        return static_cast<uint8_t>(rand());
+    }
+};
+
+#endif //ANALYZER_RANDOM_PULSE_GENERATOR_H
diff --git a/media/libaaudio/examples/loopback/src/analyzer/RoundedManchesterEncoder.h b/media/libaaudio/examples/loopback/src/analyzer/RoundedManchesterEncoder.h
new file mode 100644
index 0000000..f2eba84
--- /dev/null
+++ b/media/libaaudio/examples/loopback/src/analyzer/RoundedManchesterEncoder.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019 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 ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
+#define ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
+
+#include <math.h>
+#include <memory.h>
+#include <stdlib.h>
+#include "ManchesterEncoder.h"
+
+/**
+ * Encode bytes using Manchester Code.
+ * Round the edges using a half cosine to reduce ringing caused by a hard edge.
+ */
+
+class RoundedManchesterEncoder : public ManchesterEncoder {
+public:
+    RoundedManchesterEncoder(int samplesPerPulse)
+            : ManchesterEncoder(samplesPerPulse) {
+        int rampSize = samplesPerPulse / 4;
+        mZeroAfterZero = std::make_unique<float[]>(samplesPerPulse);
+        mZeroAfterOne = std::make_unique<float[]>(samplesPerPulse);
+
+        int sampleIndex = 0;
+        for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+            float phase = (rampIndex + 1) * M_PI / rampSize;
+            float sample = -cosf(phase);
+            mZeroAfterZero[sampleIndex] = sample;
+            mZeroAfterOne[sampleIndex] = 1.0f;
+            sampleIndex++;
+        }
+        for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+            mZeroAfterZero[sampleIndex] = 1.0f;
+            mZeroAfterOne[sampleIndex] = 1.0f;
+            sampleIndex++;
+        }
+        for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+            float phase = (rampIndex + 1) * M_PI / rampSize;
+            float sample = cosf(phase);
+            mZeroAfterZero[sampleIndex] = sample;
+            mZeroAfterOne[sampleIndex] = sample;
+            sampleIndex++;
+        }
+        for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+            mZeroAfterZero[sampleIndex] = -1.0f;
+            mZeroAfterOne[sampleIndex] = -1.0f;
+            sampleIndex++;
+        }
+    }
+
+    void onNextBit(bool current) override {
+        // Do we need to use the rounded edge?
+        mCurrentSamples = (current ^ mPreviousBit)
+                          ? mZeroAfterOne.get()
+                          : mZeroAfterZero.get();
+        mPreviousBit = current;
+    }
+
+    float nextFloat() override {
+        advanceSample();
+        float output = mCurrentSamples[mCursor];
+        if (getCurrentBit()) output = -output;
+        return output;
+    }
+
+private:
+
+    bool mPreviousBit = false;
+    float *mCurrentSamples = nullptr;
+    std::unique_ptr<float[]> mZeroAfterZero;
+    std::unique_ptr<float[]> mZeroAfterOne;
+};
+
+#endif //ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 49d921f..0d2ec70 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -20,6 +20,8 @@
 #include <assert.h>
 #include <cctype>
 #include <errno.h>
+#include <iomanip>
+#include <iostream>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,7 +35,9 @@
 #include "AAudioSimplePlayer.h"
 #include "AAudioSimpleRecorder.h"
 #include "AAudioExampleUtils.h"
-#include "LoopbackAnalyzer.h"
+
+#include "analyzer/GlitchAnalyzer.h"
+#include "analyzer/LatencyAnalyzer.h"
 #include "../../utils/AAudioExampleUtils.h"
 
 // V0.4.00 = rectify and low-pass filter the echos, auto-correlate entire echo
@@ -41,7 +45,8 @@
 //           fix -n option to set output buffer for -tm
 //           plot first glitch
 // V0.4.02 = allow -n0 for minimal buffer size
-#define APP_VERSION             "0.4.02"
+// V0.5.00 = use latency analyzer from OboeTester, uses random noise for latency
+#define APP_VERSION             "0.5.00"
 
 // Tag for machine readable results as property = value pairs
 #define RESULT_TAG              "RESULT: "
@@ -57,6 +62,20 @@
 constexpr int kDefaultHangTimeMillis = 50;
 constexpr int kMaxGlitchEventsToSave = 32;
 
+static void printAudioScope(float sample) {
+    const int maxStars = 80; // arbitrary, fits on one line
+    char c = '*';
+    if (sample < -1.0) {
+        sample = -1.0;
+        c = '$';
+    } else if (sample > 1.0) {
+        sample = 1.0;
+        c = '$';
+    }
+    int numSpaces = (int) (((sample + 1.0) * 0.5) * maxStars);
+    printf("%*c%c\n", numSpaces, ' ', c);
+}
+
 struct LoopbackData {
     AAudioStream      *inputStream = nullptr;
     AAudioStream      *outputStream = nullptr;
@@ -83,8 +102,8 @@
     aaudio_result_t    inputError = AAUDIO_OK;
     aaudio_result_t    outputError = AAUDIO_OK;
 
-    SineAnalyzer       sineAnalyzer;
-    EchoAnalyzer       echoAnalyzer;
+    GlitchAnalyzer     sineAnalyzer;
+    PulseLatencyAnalyzer echoAnalyzer;
     AudioRecording     audioRecording;
     LoopbackProcessor *loopbackProcessor;
 
@@ -254,17 +273,18 @@
             }
 
             // Analyze the data.
-            LoopbackProcessor::process_result procResult = myData->loopbackProcessor->process(myData->inputFloatData,
+            myData->loopbackProcessor->process(myData->inputFloatData,
                                                myData->actualInputChannelCount,
+                                               numFrames,
                                                outputData,
                                                myData->actualOutputChannelCount,
                                                numFrames);
-
-            if (procResult == LoopbackProcessor::PROCESS_RESULT_GLITCH) {
-                if (myData->numGlitchEvents < kMaxGlitchEventsToSave) {
-                    myData->glitchFrames[myData->numGlitchEvents++] = myData->audioRecording.size();
-                }
-            }
+//
+//            if (procResult == LoopbackProcessor::PROCESS_RESULT_GLITCH) {
+//                if (myData->numGlitchEvents < kMaxGlitchEventsToSave) {
+//                    myData->glitchFrames[myData->numGlitchEvents++] = myData->audioRecording.size();
+//                }
+//            }
 
             // Save for later.
             myData->audioRecording.write(myData->inputFloatData,
@@ -283,8 +303,8 @@
 }
 
 static void MyErrorCallbackProc(
-        AAudioStream *stream __unused,
-        void *userData __unused,
+        AAudioStream * /* stream */,
+        void * userData,
         aaudio_result_t error) {
     printf("Error Callback, error: %d\n",(int)error);
     LoopbackData *myData = (LoopbackData *) userData;
@@ -305,8 +325,8 @@
     printf("          l for _LATENCY\n");
     printf("          p for _POWER_SAVING\n");
     printf("      -t{test}          select test mode\n");
-    printf("          m for sine magnitude\n");
-    printf("          e for echo latency (default)\n");
+    printf("          g for Glitch detection\n");
+    printf("          l for round trip Latency (default)\n");
     printf("          f for file latency, analyzes %s\n\n", FILENAME_ECHOS);
     printf("      -X  use EXCLUSIVE mode for input\n");
     printf("Example:  aaudio_loopback -n2 -pl -Pl -x\n");
@@ -333,20 +353,22 @@
 }
 
 enum {
-    TEST_SINE_MAGNITUDE = 0,
-    TEST_ECHO_LATENCY,
+    TEST_GLITCHES = 0,
+    TEST_LATENCY,
     TEST_FILE_LATENCY,
 };
 
 static int parseTestMode(char c) {
-    int testMode = TEST_ECHO_LATENCY;
+    int testMode = TEST_LATENCY;
     c = tolower(c);
     switch (c) {
-        case 'm':
-            testMode = TEST_SINE_MAGNITUDE;
+        case 'm': // deprecated
+        case 'g':
+            testMode = TEST_GLITCHES;
             break;
-        case 'e':
-            testMode = TEST_ECHO_LATENCY;
+        case 'e': // deprecated
+        case 'l':
+            testMode = TEST_LATENCY;
             break;
         case 'f':
             testMode = TEST_FILE_LATENCY;
@@ -408,9 +430,10 @@
     int32_t               actualSampleRate           = 0;
     int                   written                    = 0;
 
-    int                   testMode                   = TEST_ECHO_LATENCY;
+    int                   testMode                   = TEST_LATENCY;
     double                gain                       = 1.0;
     int                   hangTimeMillis             = 0;
+    std::string           report;
 
     // Make printf print immediately so that debug info is not stuck
     // in a buffer if we hang or crash.
@@ -488,22 +511,21 @@
     int32_t requestedOutputBursts = argParser.getNumberOfBursts();
 
     switch(testMode) {
-        case TEST_SINE_MAGNITUDE:
+        case TEST_GLITCHES:
             loopbackData.loopbackProcessor = &loopbackData.sineAnalyzer;
             break;
-        case TEST_ECHO_LATENCY:
-            loopbackData.echoAnalyzer.setGain(gain);
+        case TEST_LATENCY:
+            // TODO loopbackData.echoAnalyzer.setGain(gain);
             loopbackData.loopbackProcessor = &loopbackData.echoAnalyzer;
             break;
         case TEST_FILE_LATENCY: {
-            loopbackData.echoAnalyzer.setGain(gain);
-
+            // TODO loopbackData.echoAnalyzer.setGain(gain);
             loopbackData.loopbackProcessor = &loopbackData.echoAnalyzer;
             int read = loopbackData.loopbackProcessor->load(FILENAME_ECHOS);
             printf("main() read %d mono samples from %s on Android device, rate = %d\n",
                    read, FILENAME_ECHOS,
                    loopbackData.loopbackProcessor->getSampleRate());
-            loopbackData.loopbackProcessor->report();
+            std::cout << loopbackData.loopbackProcessor->analyze();
             goto report_result;
         }
             break;
@@ -557,7 +579,7 @@
         int32_t actualCapacity = AAudioStream_getBufferCapacityInFrames(inputStream);
         (void) AAudioStream_setBufferSizeInFrames(inputStream, actualCapacity);
 
-        if (testMode == TEST_SINE_MAGNITUDE
+        if (testMode == TEST_GLITCHES
                 && requestedOutputBursts == AAUDIO_UNSPECIFIED) {
             result = AAudioStream_setBufferSizeInFrames(outputStream, actualCapacity);
             if (result < 0) {
@@ -594,10 +616,10 @@
     loopbackData.inputFloatData = new float[loopbackData.inputFramesMaximum *
                                               loopbackData.actualInputChannelCount]{};
 
-    loopbackData.loopbackProcessor->reset();
-
     loopbackData.hangTimeMillis = hangTimeMillis;
 
+    loopbackData.loopbackProcessor->prepareToTest();
+
     // Start OUTPUT first so INPUT does not overflow.
     result = player.start();
     if (result != AAUDIO_OK) {
@@ -669,7 +691,8 @@
 
     printf("input error = %d = %s\n",
            loopbackData.inputError, AAudio_convertResultToText(loopbackData.inputError));
-
+/*
+    // TODO Restore this code some day if we want to save files.
     written = loopbackData.loopbackProcessor->save(FILENAME_ECHOS);
     if (written > 0) {
         printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
@@ -681,9 +704,9 @@
         printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
                written, FILENAME_ALL);
     }
-
+*/
     if (loopbackData.inputError == AAUDIO_OK) {
-        if (testMode == TEST_SINE_MAGNITUDE) {
+        if (testMode == TEST_GLITCHES) {
             if (loopbackData.numGlitchEvents > 0) {
                 // Graph around the first glitch if there is one.
                 const int32_t start = loopbackData.glitchFrames[0] - 8;
@@ -697,7 +720,8 @@
             }
         }
 
-        loopbackData.loopbackProcessor->report();
+        std::cout << "Please wait several seconds for analysis to complete.\n";
+        std::cout << loopbackData.loopbackProcessor->analyze();
     }
 
     {
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
index 9115778..4bba436 100644
--- a/media/libaaudio/examples/utils/AAudioArgsParser.h
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -38,12 +38,15 @@
                                 aaudio_input_preset_t inputPreset) = nullptr;
 static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder,
                                           aaudio_allowed_capture_policy_t usage) = nullptr;
+static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder,
+                                          bool privacySensitive) = nullptr;
 
 static bool s_loadAttempted = false;
 static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
 static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
 static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
 static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr;
+static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr;
 
 // Link to test functions in shared library.
 static void loadFutureFunctions() {
@@ -68,6 +71,10 @@
                 dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy");
         if (s_setAllowedCapturePolicy == nullptr) goto error;
 
+        s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool))
+                dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive");
+        if (s_setPrivacySensitive == nullptr) goto error;
+
         s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
                 dlsym(handle, "AAudioStream_getUsage");
         if (s_getUsage == nullptr) goto error;
@@ -83,6 +90,10 @@
         s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *))
                 dlsym(handle, "AAudioStream_getAllowedCapturePolicy");
         if (s_getAllowedCapturePolicy == nullptr) goto error;
+
+        s_isPrivacySensitive = (bool (*)(AAudioStream *))
+                dlsym(handle, "AAudioStream_isPrivacySensitive");
+        if (s_isPrivacySensitive == nullptr) goto error;
     }
     return;
 
@@ -91,9 +102,11 @@
     s_setUsage = nullptr;
     s_setContentType = nullptr;
     s_setInputPreset = nullptr;
+    s_setPrivacySensitive = nullptr;
     s_getUsage = nullptr;
     s_getContentType = nullptr;
     s_getInputPreset = nullptr;
+    s_isPrivacySensitive = nullptr;
     dlclose(handle);
     return;
 }
@@ -211,6 +224,14 @@
         mFramesPerCallback = size;
     }
 
+    int32_t isPrivacySensitive() const {
+        return mPrivacySensitive;
+    }
+
+    void setPrivacySensitive(int32_t privacySensitive) {
+        mPrivacySensitive = privacySensitive;
+    }
+
     /**
      * Apply these parameters to a stream builder.
      * @param builder
@@ -234,12 +255,12 @@
         }
         if (s_setContentType != nullptr) {
             s_setContentType(builder, mContentType);
-        } else if (mUsage != AAUDIO_UNSPECIFIED){
+        } else if (mContentType != AAUDIO_UNSPECIFIED){
             printf("WARNING: setContentType not supported");
         }
         if (s_setInputPreset != nullptr) {
             s_setInputPreset(builder, mInputPreset);
-        } else if (mUsage != AAUDIO_UNSPECIFIED){
+        } else if (mInputPreset != AAUDIO_UNSPECIFIED){
             printf("WARNING: setInputPreset not supported");
         }
 
@@ -249,6 +270,15 @@
         } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){
             printf("WARNING: setAllowedCapturePolicy not supported");
         }
+
+        if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) {
+            if (s_setPrivacySensitive != nullptr) {
+                s_setPrivacySensitive(builder,
+                    mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED);
+            } else {
+                printf("WARNING: setPrivacySensitive not supported");
+            }
+        }
     }
 
     static constexpr int32_t   kDefaultNumberOfBursts = 2;
@@ -270,6 +300,13 @@
 
     int32_t                    mNumberOfBursts  = kDefaultNumberOfBursts;
     int32_t                    mFramesPerCallback = AAUDIO_UNSPECIFIED;
+
+    enum {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+    int32_t                    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
 };
 
 class AAudioArgsParser : public AAudioParameters {
@@ -341,6 +378,9 @@
                 case 'z':
                     setFramesPerCallback(atoi(&arg[2]));
                     break;
+                case 'S':
+                    setPrivacySensitive(atoi(&arg[2]));
+                    break;
                 default:
                     unrecognized = true;
                     break;
@@ -399,6 +439,9 @@
         printf("      -x to use EXCLUSIVE mode\n");
         printf("      -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
         printf("      -z{callbackSize} or block size, in frames, default = 0\n");
+        printf("      -S{0|1} set privacy Sensitive enabled or disabled\n");
+        printf("          0 = disabled\n");
+        printf("          1 = enabled\n");
     }
 
     static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) {
@@ -506,10 +549,15 @@
                    getContentType(), s_getContentType(stream));
         }
 
-        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT
-            && s_getInputPreset != nullptr) {
+        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) {
+            if (s_getInputPreset != nullptr) {
                 printf("  InputPreset:  requested = %d, actual = %d\n",
                        getInputPreset(), s_getInputPreset(stream));
+            }
+            if (s_isPrivacySensitive != nullptr) {
+                printf("  Privacy Sensitive:  requested = %d, actual = %d\n",
+                       isPrivacySensitive(), s_isPrivacySensitive(stream));
+            }
         }
 
         printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
diff --git a/media/libaaudio/examples/write_sine/Android.bp b/media/libaaudio/examples/write_sine/Android.bp
index cc80861..aa25e67 100644
--- a/media/libaaudio/examples/write_sine/Android.bp
+++ b/media/libaaudio/examples/write_sine/Android.bp
@@ -4,7 +4,6 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: ["libaaudio"],
     header_libs: ["libaaudio_example_utils"],
-    pack_relocations: false,
 }
 
 cc_test {
@@ -13,5 +12,4 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: ["libaaudio"],
     header_libs: ["libaaudio_example_utils"],
-    pack_relocations: false,
 }
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index ee5d089..a47f189 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -227,6 +227,8 @@
 };
 typedef int32_t aaudio_performance_mode_t;
 
+#define AAUDIO_SYSTEM_USAGE_OFFSET 1000
+
 /**
  * The USAGE attribute expresses "why" you are playing a sound, what is this sound used for.
  * This information is used by certain platforms or routing policies
@@ -297,7 +299,31 @@
     /**
      * Use this for audio responses to user queries, audio instructions or help utterances.
      */
-    AAUDIO_USAGE_ASSISTANT = 16
+    AAUDIO_USAGE_ASSISTANT = 16,
+
+    /**
+     * Use this in case of playing sounds in an emergency.
+     * Privileged MODIFY_AUDIO_ROUTING permission required.
+     */
+    AAUDIO_SYSTEM_USAGE_EMERGENCY = AAUDIO_SYSTEM_USAGE_OFFSET,
+
+    /**
+     * Use this for safety sounds and alerts, for example backup camera obstacle detection.
+     * Privileged MODIFY_AUDIO_ROUTING permission required.
+     */
+    AAUDIO_SYSTEM_USAGE_SAFETY = AAUDIO_SYSTEM_USAGE_OFFSET + 1,
+
+    /**
+     * Use this for vehicle status alerts and information, for example the check engine light.
+     * Privileged MODIFY_AUDIO_ROUTING permission required.
+     */
+    AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS = AAUDIO_SYSTEM_USAGE_OFFSET + 2,
+
+    /**
+     * Use this for traffic announcements, etc.
+     * Privileged MODIFY_AUDIO_ROUTING permission required.
+     */
+    AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT = AAUDIO_SYSTEM_USAGE_OFFSET + 3,
 };
 typedef int32_t aaudio_usage_t;
 
@@ -380,6 +406,7 @@
      * Use this preset for capturing audio meant to be processed in real time
      * and played back for live performance (e.g karaoke).
      * The capture path will minimize latency and coupling with playback path.
+     * Available since API level 29.
      */
     AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
 };
@@ -472,6 +499,8 @@
  * This is intended for developers to use when debugging.
  * It is not for display to users.
  *
+ * Available since API level 26.
+ *
  * @return pointer to a text representation of an AAudio result code.
  */
 AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) __INTRODUCED_IN(26);
@@ -482,6 +511,8 @@
  * This is intended for developers to use when debugging.
  * It is not for display to users.
  *
+ * Available since API level 26.
+ *
  * @return pointer to a text representation of an AAudio state.
  */
 AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state)
@@ -502,6 +533,8 @@
  * chosen by the device when it is opened.
  *
  * AAudioStreamBuilder_delete() must be called when you are done using the builder.
+ *
+ * Available since API level 26.
  */
 AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder)
         __INTRODUCED_IN(26);
@@ -513,6 +546,8 @@
  * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED},
  * in which case the primary device will be used.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param deviceId device identifier or {@link #AAUDIO_UNSPECIFIED}
  */
@@ -530,6 +565,8 @@
  * If an exact value is specified then an opened stream will use that value.
  * If a stream cannot be opened with the specified value then the open will fail.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param sampleRate frames per second. Common rates include 44100 and 48000 Hz.
  */
@@ -547,6 +584,8 @@
  * If an exact value is specified then an opened stream will use that value.
  * If a stream cannot be opened with the specified value then the open will fail.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param channelCount Number of channels desired.
  */
@@ -556,6 +595,8 @@
 /**
  * Identical to AAudioStreamBuilder_setChannelCount().
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param samplesPerFrame Number of samples in a frame.
  */
@@ -573,6 +614,8 @@
  * If an exact value is specified then an opened stream will use that value.
  * If a stream cannot be opened with the specified value then the open will fail.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param format common formats are {@link #AAUDIO_FORMAT_PCM_FLOAT} and
  *               {@link #AAUDIO_FORMAT_PCM_I16}.
@@ -588,6 +631,8 @@
  * The requested sharing mode may not be available.
  * The application can query for the actual mode after the stream is opened.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param sharingMode {@link #AAUDIO_SHARING_MODE_SHARED} or {@link #AAUDIO_SHARING_MODE_EXCLUSIVE}
  */
@@ -599,6 +644,8 @@
  *
  * The default, if you do not call this function, is {@link #AAUDIO_DIRECTION_OUTPUT}.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param direction {@link #AAUDIO_DIRECTION_OUTPUT} or {@link #AAUDIO_DIRECTION_INPUT}
  */
@@ -611,6 +658,8 @@
  *
  * The default, if you do not call this function, is {@link #AAUDIO_UNSPECIFIED}.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param numFrames the desired buffer capacity in frames or {@link #AAUDIO_UNSPECIFIED}
  */
@@ -629,6 +678,8 @@
  * You can call AAudioStream_getPerformanceMode()
  * to find out the final mode for the stream.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param mode the desired performance mode, eg. {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}
  */
@@ -644,7 +695,7 @@
  *
  * The default, if you do not call this function, is {@link #AAUDIO_USAGE_MEDIA}.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param usage the desired usage, eg. {@link #AAUDIO_USAGE_GAME}
@@ -661,7 +712,7 @@
  *
  * The default, if you do not call this function, is {@link #AAUDIO_CONTENT_TYPE_MUSIC}.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param contentType the type of audio data, eg. {@link #AAUDIO_CONTENT_TYPE_SPEECH}
@@ -681,7 +732,7 @@
  * That is because VOICE_RECOGNITION is the preset with the lowest latency
  * on many platforms.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param inputPreset the desired configuration for recording
@@ -697,10 +748,10 @@
  * Note that an application can also set its global policy, in which case the most restrictive
  * policy is always applied. See {@link android.media.AudioAttributes#setAllowedCapturePolicy(int)}
  *
- * Added in API level 29.
+ * Available since API level 29.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
- * @param inputPreset the desired level of opt-out from being captured.
+ * @param capturePolicy the desired level of opt-out from being captured.
  */
 AAUDIO_API void AAudioStreamBuilder_setAllowedCapturePolicy(AAudioStreamBuilder* builder,
         aaudio_allowed_capture_policy_t capturePolicy) __INTRODUCED_IN(29);
@@ -727,7 +778,7 @@
  *
  * Allocated session IDs will always be positive and nonzero.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param sessionId an allocated sessionID or {@link #AAUDIO_SESSION_ID_ALLOCATE}
@@ -735,6 +786,28 @@
 AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
         aaudio_session_id_t sessionId) __INTRODUCED_IN(28);
 
+
+/** Indicates whether this input stream must be marked as privacy sensitive or not.
+ *
+ * When true, this input stream is privacy sensitive and any concurrent capture
+ * is not permitted.
+ *
+ * This is off (false) by default except when the input preset is {@link #AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION}
+ * or {@link #AAUDIO_INPUT_PRESET_CAMCORDER}.
+ *
+ * Always takes precedence over default from input preset when set explicitly.
+ *
+ * Only relevant if the stream direction is {@link #AAUDIO_DIRECTION_INPUT}.
+ *
+ * Added in API level 30.
+ *
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param privacySensitive true if capture from this stream must be marked as privacy sensitive,
+ * false otherwise.
+ */
+AAUDIO_API void AAudioStreamBuilder_setPrivacySensitive(AAudioStreamBuilder* builder,
+        bool privacySensitive) __INTRODUCED_IN(30);
+
 /**
  * Return one of these values from the data callback function.
  */
@@ -826,6 +899,8 @@
  *
  * Note that the AAudio callbacks will never be called simultaneously from multiple threads.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param callback pointer to a function that will process audio data.
  * @param userData pointer to an application data structure that will be passed
@@ -854,6 +929,8 @@
  * If you do call this function then the requested size should be less than
  * half the buffer capacity, to allow double buffering.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param numFrames the desired buffer size in frames or {@link #AAUDIO_UNSPECIFIED}
  */
@@ -905,6 +982,8 @@
  *
  * Note that the AAudio callbacks will never be called simultaneously from multiple threads.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param callback pointer to a function that will be called if an error occurs.
  * @param userData pointer to an application data structure that will be passed
@@ -919,6 +998,8 @@
  * AAudioStream_close() must be called when finished with the stream to recover
  * the memory and to free the associated resources.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param stream pointer to a variable to receive the new stream reference
  * @return {@link #AAUDIO_OK} or a negative error.
@@ -929,6 +1010,8 @@
 /**
  * Delete the resources associated with the StreamBuilder.
  *
+ * Available since API level 26.
+ *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
@@ -939,8 +1022,30 @@
 // Stream Control
 // ============================================================
 
+#if __ANDROID_API__ >= 30
 /**
- * Free the resources associated with a stream created by AAudioStreamBuilder_openStream()
+ * Free the audio resources associated with a stream created by
+ * AAudioStreamBuilder_openStream().
+ * AAudioStream_close() should be called at some point after calling
+ * this function.
+ *
+ * After this call, the stream will be in {@link #AAUDIO_STREAM_STATE_CLOSING}
+ *
+ * This function is useful if you want to release the audio resources immediately,
+ * but still allow queries to the stream to occur from other threads. This often
+ * happens if you are monitoring stream progress from a UI thread.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return {@link #AAUDIO_OK} or a negative error.
+ */
+AAUDIO_API aaudio_result_t  AAudioStream_release(AAudioStream* stream) __INTRODUCED_IN(30);
+#endif // __ANDROID_API__
+
+/**
+ * Delete the internal data structures associated with the stream created
+ * by AAudioStreamBuilder_openStream().
+ *
+ * If AAudioStream_release() has not been called then it will be called automatically.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
@@ -954,6 +1059,8 @@
  * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STARTING} or
  * {@link #AAUDIO_STREAM_STATE_STARTED}.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
@@ -969,6 +1076,8 @@
  * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams.
  * For input streams use AAudioStream_requestStop().
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
@@ -984,6 +1093,8 @@
  *
  * This will return {@link #AAUDIO_ERROR_UNIMPLEMENTED} for input streams.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
@@ -995,6 +1106,8 @@
  * After this call the state will be in {@link #AAUDIO_STREAM_STATE_STOPPING} or
  * {@link #AAUDIO_STREAM_STATE_STOPPED}.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return {@link #AAUDIO_OK} or a negative error.
  */
@@ -1008,6 +1121,8 @@
  * call AAudioStream_waitForStateChange() with currentState
  * set to {@link #AAUDIO_STREAM_STATE_UNKNOWN} and a zero timeout.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  */
 AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream) __INTRODUCED_IN(26);
@@ -1028,6 +1143,8 @@
  * }
  * </code></pre>
  *
+ * Available since API level 26.
+ *
  * @param stream A reference provided by AAudioStreamBuilder_openStream()
  * @param inputState The state we want to avoid.
  * @param nextState Pointer to a variable that will be set to the new state.
@@ -1056,6 +1173,8 @@
  *
  * If the call times out then zero or a partial frame count will be returned.
  *
+ * Available since API level 26.
+ *
  * @param stream A stream created using AAudioStreamBuilder_openStream().
  * @param buffer The address of the first sample.
  * @param numFrames Number of frames to read. Only complete frames will be written.
@@ -1079,6 +1198,8 @@
  *
  * If the call times out then zero or a partial frame count will be returned.
  *
+ * Available since API level 26.
+ *
  * @param stream A stream created using AAudioStreamBuilder_openStream().
  * @param buffer The address of the first sample.
  * @param numFrames Number of frames to write. Only complete frames will be written.
@@ -1104,6 +1225,8 @@
  * You can check the return value or call AAudioStream_getBufferSizeInFrames()
  * to see what the actual final size is.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @param numFrames requested number of frames that can be filled without blocking
  * @return actual buffer size in frames or a negative error
@@ -1114,6 +1237,8 @@
 /**
  * Query the maximum number of frames that can be filled without blocking.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return buffer size in frames.
  */
@@ -1129,6 +1254,8 @@
  * For some endpoints, the burst size can vary dynamically.
  * But these tend to be devices with high latency.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return burst size
  */
@@ -1137,6 +1264,8 @@
 /**
  * Query maximum buffer capacity in frames.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return  buffer capacity in frames
  */
@@ -1158,6 +1287,8 @@
  * {@link #AAUDIO_UNSPECIFIED} indicates that the callback buffer size for this stream
  * may vary from one dataProc callback to the next.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return callback buffer size in frames or {@link #AAUDIO_UNSPECIFIED}
  */
@@ -1175,12 +1306,16 @@
  * Note that some INPUT devices may not support this function.
  * In that case a 0 will always be returned.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return the underrun or overrun count
  */
 AAUDIO_API int32_t AAudioStream_getXRunCount(AAudioStream* stream) __INTRODUCED_IN(26);
 
 /**
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return actual sample rate
  */
@@ -1190,6 +1325,8 @@
  * A stream has one or more channels of data.
  * A frame will contain one sample for each channel.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return actual number of channels
  */
@@ -1198,18 +1335,24 @@
 /**
  * Identical to AAudioStream_getChannelCount().
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return actual number of samples frame
  */
 AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream) __INTRODUCED_IN(26);
 
 /**
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return actual device ID
  */
 AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream) __INTRODUCED_IN(26);
 
 /**
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return actual data format
  */
@@ -1217,6 +1360,9 @@
 
 /**
  * Provide actual sharing mode.
+ *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return  actual sharing mode
  */
@@ -1226,12 +1372,16 @@
 /**
  * Get the performance mode used by the stream.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  */
 AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream)
         __INTRODUCED_IN(26);
 
 /**
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return direction
  */
@@ -1245,6 +1395,8 @@
  *
  * The frame position is monotonically increasing.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return frames written
  */
@@ -1258,6 +1410,8 @@
  *
  * The frame position is monotonically increasing.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return frames read
  */
@@ -1281,7 +1435,7 @@
  *
  * The sessionID for a stream should not change once the stream has been opened.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return session ID or {@link #AAUDIO_SESSION_ID_NONE}
@@ -1304,6 +1458,8 @@
  *
  * The position and time passed back are monotonically increasing.
  *
+ * Available since API level 26.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @param clockid CLOCK_MONOTONIC or CLOCK_BOOTTIME
  * @param framePosition pointer to a variable to receive the position
@@ -1316,7 +1472,7 @@
 /**
  * Return the use case for the stream.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return frames read
@@ -1326,7 +1482,7 @@
 /**
  * Return the content type for the stream.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return content type, for example {@link #AAUDIO_CONTENT_TYPE_MUSIC}
@@ -1337,7 +1493,7 @@
 /**
  * Return the input preset for the stream.
  *
- * Added in API level 28.
+ * Available since API level 28.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return input preset, for example {@link #AAUDIO_INPUT_PRESET_CAMCORDER}
@@ -1349,7 +1505,7 @@
  * Return the policy that determines whether the audio may or may not be captured
  * by other apps or the system.
  *
- * Added in API level 29.
+ * Available since API level 29.
  *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return the allowed capture policy, for example {@link #AAUDIO_ALLOW_CAPTURE_BY_ALL}
@@ -1357,6 +1513,20 @@
 AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
         AAudioStream* stream) __INTRODUCED_IN(29);
 
+
+/**
+ * Return whether this input stream is marked as privacy sensitive or not.
+ *
+ * See {@link #AAudioStreamBuilder_setPrivacySensitive()}.
+ *
+ * Added in API level 30.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return true if privacy sensitive, false otherwise
+ */
+AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* stream)
+        __INTRODUCED_IN(30);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/media/libaaudio/libaaudio.map.txt b/media/libaaudio/libaaudio.map.txt
deleted file mode 100644
index a87ede3..0000000
--- a/media/libaaudio/libaaudio.map.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-LIBAAUDIO {
-  global:
-    AAudio_convertResultToText;
-    AAudio_convertStreamStateToText;
-    AAudio_createStreamBuilder;
-    AAudio_getMMapPolicy;
-    AAudio_setMMapPolicy;
-    AAudioStreamBuilder_setPerformanceMode;
-    AAudioStreamBuilder_setDeviceId;
-    AAudioStreamBuilder_setDataCallback;
-    AAudioStreamBuilder_setErrorCallback;
-    AAudioStreamBuilder_setFramesPerDataCallback;
-    AAudioStreamBuilder_setSampleRate;
-    AAudioStreamBuilder_setSamplesPerFrame;
-    AAudioStreamBuilder_setChannelCount;
-    AAudioStreamBuilder_setFormat;
-    AAudioStreamBuilder_setSharingMode;
-    AAudioStreamBuilder_setDirection;
-    AAudioStreamBuilder_setBufferCapacityInFrames;
-    AAudioStreamBuilder_setUsage;       # introduced=28
-    AAudioStreamBuilder_setContentType; # introduced=28
-    AAudioStreamBuilder_setInputPreset; # introduced=28
-    AAudioStreamBuilder_setAllowedCapturePolicy; # introduced=29
-    AAudioStreamBuilder_setSessionId;   # introduced=28
-    AAudioStreamBuilder_openStream;
-    AAudioStreamBuilder_delete;
-    AAudioStream_close;
-    AAudioStream_requestStart;
-    AAudioStream_requestPause;
-    AAudioStream_requestFlush;
-    AAudioStream_requestStop;
-    AAudioStream_getState;
-    AAudioStream_waitForStateChange;
-    AAudioStream_read;
-    AAudioStream_write;
-    AAudioStream_setBufferSizeInFrames;
-    AAudioStream_getBufferSizeInFrames;
-    AAudioStream_getFramesPerDataCallback;
-    AAudioStream_getFramesPerBurst;
-    AAudioStream_getBufferCapacityInFrames;
-    AAudioStream_getXRunCount;
-    AAudioStream_getSampleRate;
-    AAudioStream_getSamplesPerFrame;
-    AAudioStream_getChannelCount;
-    AAudioStream_getPerformanceMode;
-    AAudioStream_getDeviceId;
-    AAudioStream_getFormat;
-    AAudioStream_getSharingMode;
-    AAudioStream_getDirection;
-    AAudioStream_getUsage;       # introduced=28
-    AAudioStream_getContentType; # introduced=28
-    AAudioStream_getInputPreset; # introduced=28
-    AAudioStream_getAllowedCapturePolicy; # introduced=29
-    AAudioStream_getFramesWritten;
-    AAudioStream_getFramesRead;
-    AAudioStream_getSessionId;   # introduced=28
-    AAudioStream_getTimestamp;
-    AAudioStream_isMMapUsed;
-  local:
-    *;
-};
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 4090286..717f31a 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -10,14 +10,93 @@
         "legacy",
         "utility",
     ],
-    export_include_dirs: ["."],
-    header_libs: ["libaaudio_headers"],
+    header_libs: [
+        "libaaudio_headers",
+    ],
     export_header_lib_headers: ["libaaudio_headers"],
+    version_script: "libaaudio.map.txt",
 
     srcs: [
+        "core/AAudioAudio.cpp",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wall",
+        "-Werror",
+
+        // By default, all symbols are hidden.
+        // "-fvisibility=hidden",
+        // AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
+        "-DAAUDIO_API=__attribute__((visibility(\"default\")))",
+    ],
+
+    shared_libs: [
+        "libaaudio_internal",
+        "libaudioclient",
+        "libaudioutils",
+        "libmedia_helper",
+        "libmediametrics",
+        "libmediautils",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libbinder",
+    ],
+
+    sanitize: {
+        integer_overflow: true,
+        misc_undefined: ["bounds"],
+    },
+
+    stubs: {
+        symbol_file: "libaaudio.map.txt",
+        versions: ["28"],
+    },
+}
+
+cc_library {
+    name: "libaaudio_internal",
+
+    local_include_dirs: [
+        "binding",
+        "client",
+        "core",
+        "fifo",
+        "legacy",
+        "utility",
+    ],
+
+    export_include_dirs: ["."],
+    header_libs: [
+        "libaaudio_headers",
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
+    export_header_lib_headers: ["libaaudio_headers"],
+
+    shared_libs: [
+        "libaudioclient",
+        "libaudioutils",
+        "libmedia_helper",
+        "libmediametrics",
+        "libmediautils",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libbinder",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wall",
+        "-Werror",
+    ],
+
+    srcs: [
+        "core/AudioGlobal.cpp",
         "core/AudioStream.cpp",
         "core/AudioStreamBuilder.cpp",
-        "core/AAudioAudio.cpp",
         "core/AAudioStreamParameters.cpp",
         "legacy/AudioStreamLegacy.cpp",
         "legacy/AudioStreamRecord.cpp",
@@ -54,25 +133,8 @@
         "flowgraph/SourceI16.cpp",
         "flowgraph/SourceI24.cpp",
     ],
-
-    cflags: [
-        "-Wno-unused-parameter",
-        "-Wall",
-        "-Werror",
-
-        // By default, all symbols are hidden.
-        // "-fvisibility=hidden",
-        // AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
-        "-DAAUDIO_API=__attribute__((visibility(\"default\")))",
-    ],
-
-    shared_libs: [
-        "libaudioclient",
-        "libaudioutils",
-        "liblog",
-        "libcutils",
-        "libutils",
-        "libbinder",
-        "libaudiomanager",
-    ],
+    sanitize: {
+        integer_overflow: true,
+        misc_undefined: ["bounds"],
+    },
 }
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index f9da8b4..e8c91fc 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -98,8 +98,9 @@
                                                   pid_t clientThreadId) override;
 
     aaudio_result_t startClient(aaudio_handle_t streamHandle __unused,
-                                      const android::AudioClient& client __unused,
-                                      audio_port_handle_t *clientHandle) override {
+                                const android::AudioClient& client __unused,
+                                const audio_attributes_t *attr __unused,
+                                audio_port_handle_t *clientHandle __unused) override {
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index a64405b..9c28cc7 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -89,8 +89,9 @@
                                                   pid_t clientThreadId) = 0;
 
     virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
-                                      const android::AudioClient& client,
-                                      audio_port_handle_t *clientHandle) = 0;
+                                        const android::AudioClient& client,
+                                        const audio_attributes_t *attr,
+                                        audio_port_handle_t *clientHandle) = 0;
 
     virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
                                        audio_port_handle_t clientHandle) = 0;
diff --git a/media/libaaudio/src/binding/AAudioServiceMessage.h b/media/libaaudio/src/binding/AAudioServiceMessage.h
index 3981454..62927a0 100644
--- a/media/libaaudio/src/binding/AAudioServiceMessage.h
+++ b/media/libaaudio/src/binding/AAudioServiceMessage.h
@@ -44,6 +44,8 @@
 struct AAudioMessageEvent {
     aaudio_service_event_t event;
     union {
+        // Align so that 32 and 64-bit code can exchange messages through shared memory.
+        alignas(8)
         double  dataDouble;
         int64_t dataLong;
     };
@@ -57,8 +59,10 @@
         EVENT,
     };
 
-    code what;
+    code      what;
     union {
+        // Align so that 32 and 64-bit code can exchange messages through shared memory.
+        alignas(8)
         AAudioMessageTimestamp timestamp; // what == TIMESTAMP
         AAudioMessageEvent event;         // what == EVENT
     };
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index a987fab..b785f88 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -66,6 +66,8 @@
     if (status != NO_ERROR) goto error;
     status = parcel->writeInt32(getSessionId());
     if (status != NO_ERROR) goto error;
+    status = parcel->writeInt32(isPrivacySensitive() ? 1 : 0);
+    if (status != NO_ERROR) goto error;
     return NO_ERROR;
 error:
     ALOGE("%s(): write failed = %d", __func__, status);
@@ -111,7 +113,9 @@
     status = parcel->readInt32(&value);
     if (status != NO_ERROR) goto error;
     setSessionId(value);
-
+    status = parcel->readInt32(&value);
+    if (status != NO_ERROR) goto error;
+    setPrivacySensitive(value == 1);
     return NO_ERROR;
 error:
     ALOGE("%s(): read failed = %d", __func__, status);
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 214f888..06f66d3 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -32,19 +32,12 @@
 #define RIDICULOUSLY_LARGE_FRAME_SIZE        4096
 
 AudioEndpoint::AudioEndpoint()
-    : mUpCommandQueue(nullptr)
-    , mDataQueue(nullptr)
-    , mFreeRunning(false)
+    : mFreeRunning(false)
     , mDataReadCounter(0)
     , mDataWriteCounter(0)
 {
 }
 
-AudioEndpoint::~AudioEndpoint() {
-    delete mDataQueue;
-    delete mUpCommandQueue;
-}
-
 // TODO Consider moving to a method in RingBufferDescriptor
 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
                                                   const RingBufferDescriptor *descriptor) {
@@ -144,7 +137,7 @@
         return AAUDIO_ERROR_INTERNAL;
     }
 
-    mUpCommandQueue = new FifoBuffer(
+    mUpCommandQueue = std::make_unique<FifoBuffer>(
             descriptor->bytesPerFrame,
             descriptor->capacityInFrames,
             descriptor->readCounterAddress,
@@ -173,7 +166,7 @@
                                   ? &mDataWriteCounter
                                   : descriptor->writeCounterAddress;
 
-    mDataQueue = new FifoBuffer(
+    mDataQueue = std::make_unique<FifoBuffer>(
             descriptor->bytesPerFrame,
             descriptor->capacityInFrames,
             readCounterAddress,
@@ -194,18 +187,15 @@
     return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
 }
 
-int32_t AudioEndpoint::getEmptyFramesAvailable()
-{
+int32_t AudioEndpoint::getEmptyFramesAvailable() {
     return mDataQueue->getEmptyFramesAvailable();
 }
 
-int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
-{
+int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) {
     return mDataQueue->getFullDataAvailable(wrappingBuffer);
 }
 
-int32_t AudioEndpoint::getFullFramesAvailable()
-{
+int32_t AudioEndpoint::getFullFramesAvailable() {
     return mDataQueue->getFullFramesAvailable();
 }
 
@@ -217,29 +207,24 @@
     mDataQueue->advanceReadIndex(deltaFrames);
 }
 
-void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
-{
+void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) {
     mDataQueue->setReadCounter(framesRead);
 }
 
-fifo_counter_t AudioEndpoint::getDataReadCounter()
-{
+fifo_counter_t AudioEndpoint::getDataReadCounter() const {
     return mDataQueue->getReadCounter();
 }
 
-void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
-{
+void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) {
     mDataQueue->setWriteCounter(framesRead);
 }
 
-fifo_counter_t AudioEndpoint::getDataWriteCounter()
-{
+fifo_counter_t AudioEndpoint::getDataWriteCounter() const {
     return mDataQueue->getWriteCounter();
 }
 
 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
-                                            int32_t *actualFrames)
-{
+                                            int32_t *actualFrames) {
     if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
         requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
     }
@@ -248,19 +233,17 @@
     return AAUDIO_OK;
 }
 
-int32_t AudioEndpoint::getBufferSizeInFrames() const
-{
+int32_t AudioEndpoint::getBufferSizeInFrames() const {
     return mDataQueue->getThreshold();
 }
 
-int32_t AudioEndpoint::getBufferCapacityInFrames() const
-{
+int32_t AudioEndpoint::getBufferCapacityInFrames() const {
     return (int32_t)mDataQueue->getBufferCapacityInFrames();
 }
 
 void AudioEndpoint::dump() const {
-    ALOGD("data readCounter  = %lld", (long long) mDataQueue->getReadCounter());
-    ALOGD("data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
+    ALOGD("data readCounter  = %lld", (long long) getDataReadCounter());
+    ALOGD("data writeCounter = %lld", (long long) getDataWriteCounter());
 }
 
 void AudioEndpoint::eraseDataMemory() {
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index f5b67e8..484d917 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -35,7 +35,6 @@
 
 public:
     AudioEndpoint();
-    virtual ~AudioEndpoint();
 
     /**
      * Configure based on the EndPointDescriptor_t.
@@ -67,11 +66,11 @@
      */
     void setDataReadCounter(android::fifo_counter_t framesRead);
 
-    android::fifo_counter_t getDataReadCounter();
+    android::fifo_counter_t getDataReadCounter() const;
 
     void setDataWriteCounter(android::fifo_counter_t framesWritten);
 
-    android::fifo_counter_t getDataWriteCounter();
+    android::fifo_counter_t getDataWriteCounter() const;
 
     /**
      * The result is not valid until after configure() is called.
@@ -94,8 +93,8 @@
     void dump() const;
 
 private:
-    android::FifoBuffer    *mUpCommandQueue;
-    android::FifoBuffer    *mDataQueue;
+    std::unique_ptr<android::FifoBuffer> mUpCommandQueue;
+    std::unique_ptr<android::FifoBuffer> mDataQueue;
     bool                    mFreeRunning;
     android::fifo_counter_t mDataReadCounter; // only used if free-running
     android::fifo_counter_t mDataWriteCounter; // only used if free-running
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 52eadd4..4520823 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-// This file is used in both client and server processes.
-// This is needed to make sense of the logs more easily.
-#define LOG_TAG (mInService ? "AudioStreamInternal_Service" : "AudioStreamInternal_Client")
+#define LOG_TAG "AudioStreamInternal"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
@@ -28,6 +26,8 @@
 
 #include <aaudio/AAudio.h>
 #include <cutils/properties.h>
+
+#include <media/MediaMetricsItem.h>
 #include <utils/String16.h>
 #include <utils/Trace.h>
 
@@ -36,12 +36,20 @@
 #include "binding/AAudioStreamConfiguration.h"
 #include "binding/IAAudioService.h"
 #include "binding/AAudioServiceMessage.h"
+#include "core/AudioGlobal.h"
 #include "core/AudioStreamBuilder.h"
 #include "fifo/FifoBuffer.h"
 #include "utility/AudioClock.h"
 
 #include "AudioStreamInternal.h"
 
+// We do this after the #includes because if a header uses ALOG.
+// it would fail on the reference to mInService.
+#undef LOG_TAG
+// This file is used in both client and server processes.
+// This is needed to make sense of the logs more easily.
+#define LOG_TAG (mInService ? "AudioStreamInternal_Service" : "AudioStreamInternal_Client")
+
 using android::String16;
 using android::Mutex;
 using android::WrappingBuffer;
@@ -58,7 +66,6 @@
 AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface  &serviceInterface, bool inService)
         : AudioStream()
         , mClockModel()
-        , mAudioEndpoint()
         , mServiceStreamHandle(AAUDIO_HANDLE_INVALID)
         , mInService(inService)
         , mServiceInterface(serviceInterface)
@@ -74,7 +81,6 @@
 aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
 
     aaudio_result_t result = AAUDIO_OK;
-    int32_t capacity;
     int32_t framesPerBurst;
     int32_t framesPerHardwareBurst;
     AAudioStreamRequest request;
@@ -116,6 +122,7 @@
     request.getConfiguration().setUsage(getUsage());
     request.getConfiguration().setContentType(getContentType());
     request.getConfiguration().setInputPreset(getInputPreset());
+    request.getConfiguration().setPrivacySensitive(isPrivacySensitive());
 
     request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
 
@@ -138,6 +145,11 @@
         return mServiceStreamHandle;
     }
 
+    // This must match the key generated in oboeservice/AAudioServiceStreamBase.cpp
+    // so the client can have permission to log.
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM)
+            + std::to_string(mServiceStreamHandle);
+
     result = configurationOutput.validate();
     if (result != AAUDIO_OK) {
         goto error;
@@ -172,7 +184,8 @@
     }
 
     // Configure endpoint based on descriptor.
-    result = mAudioEndpoint.configure(&mEndpointDescriptor, getDirection());
+    mAudioEndpoint = std::make_unique<AudioEndpoint>();
+    result = mAudioEndpoint->configure(&mEndpointDescriptor, getDirection());
     if (result != AAUDIO_OK) {
         goto error;
     }
@@ -200,9 +213,10 @@
     }
     mFramesPerBurst = framesPerBurst; // only save good value
 
-    capacity = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
-    if (capacity < mFramesPerBurst || capacity > MAX_BUFFER_CAPACITY_IN_FRAMES) {
-        ALOGE("%s - bufferCapacity out of range = %d", __func__, capacity);
+    mBufferCapacityInFrames = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
+    if (mBufferCapacityInFrames < mFramesPerBurst
+            || mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) {
+        ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames);
         result = AAUDIO_ERROR_OUT_OF_RANGE;
         goto error;
     }
@@ -229,42 +243,66 @@
         }
 
         const int32_t callbackBufferSize = mCallbackFrames * getBytesPerFrame();
-        mCallbackBuffer = new uint8_t[callbackBufferSize];
+        mCallbackBuffer = std::make_unique<uint8_t[]>(callbackBufferSize);
     }
 
+    // For debugging and analyzing the distribution of MMAP timestamps.
+    // For OUTPUT, use a NEGATIVE offset to move the CPU writes further BEFORE the HW reads.
+    // For INPUT, use a POSITIVE offset to move the CPU reads further AFTER the HW writes.
+    // You can use this offset to reduce glitching.
+    // You can also use this offset to force glitching. By iterating over multiple
+    // values you can reveal the distribution of the hardware timing jitter.
+    if (mAudioEndpoint->isFreeRunning()) { // MMAP?
+        int32_t offsetMicros = (getDirection() == AAUDIO_DIRECTION_OUTPUT)
+                ? AAudioProperty_getOutputMMapOffsetMicros()
+                : AAudioProperty_getInputMMapOffsetMicros();
+        // This log is used to debug some tricky glitch issues. Please leave.
+        ALOGD_IF(offsetMicros, "%s() - %s mmap offset = %d micros",
+                __func__,
+                (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? "output" : "input",
+                offsetMicros);
+        mTimeOffsetNanos = offsetMicros * AAUDIO_NANOS_PER_MICROSECOND;
+    }
+
+    setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q
+
     setState(AAUDIO_STREAM_STATE_OPEN);
 
     return result;
 
 error:
-    close();
+    releaseCloseFinal();
     return result;
 }
 
 // This must be called under mStreamLock.
-aaudio_result_t AudioStreamInternal::close() {
+aaudio_result_t AudioStreamInternal::release_l() {
     aaudio_result_t result = AAUDIO_OK;
     ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
     if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
-        // Don't close a stream while it is running.
         aaudio_stream_state_t currentState = getState();
-        // Don't close a stream while it is running. Stop it first.
+        // Don't release a stream while it is running. Stop it first.
         // If DISCONNECTED then we should still try to stop in case the
         // error callback is still running.
         if (isActive() || currentState == AAUDIO_STREAM_STATE_DISCONNECTED) {
             requestStop();
         }
+
+        logReleaseBufferState();
+
         setState(AAUDIO_STREAM_STATE_CLOSING);
         aaudio_handle_t serviceStreamHandle = mServiceStreamHandle;
         mServiceStreamHandle = AAUDIO_HANDLE_INVALID;
 
         mServiceInterface.closeStream(serviceStreamHandle);
-        delete[] mCallbackBuffer;
-        mCallbackBuffer = nullptr;
+        mCallbackBuffer.reset();
 
-        setState(AAUDIO_STREAM_STATE_CLOSED);
+        // Update local frame counters so we can query them after releasing the endpoint.
+        getFramesRead();
+        getFramesWritten();
+        mAudioEndpoint.reset();
         result = mEndPointParcelable.close();
-        aaudio_result_t result2 = AudioStream::close();
+        aaudio_result_t result2 = AudioStream::release_l();
         return (result != AAUDIO_OK) ? result : result2;
     } else {
         return AAUDIO_ERROR_INVALID_HANDLE;
@@ -316,6 +354,12 @@
     drainTimestampsFromService();
 
     aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);
+    if (result == AAUDIO_ERROR_INVALID_HANDLE) {
+        ALOGD("%s() INVALID_HANDLE, stream was probably stolen", __func__);
+        // Stealing was added in R. Coerce result to improve backward compatibility.
+        result = AAUDIO_ERROR_DISCONNECTED;
+        setState(AAUDIO_STREAM_STATE_DISCONNECTED);
+    }
 
     startTime = AudioClock::getNanoseconds();
     mClockModel.start(startTime);
@@ -359,7 +403,12 @@
     if (isDataCallbackSet()
             && (isActive() || getState() == AAUDIO_STREAM_STATE_DISCONNECTED)) {
         mCallbackEnabled.store(false);
-        return joinThread(NULL); // may temporarily unlock mStreamLock
+        aaudio_result_t result = joinThread(NULL); // may temporarily unlock mStreamLock
+        if (result == AAUDIO_ERROR_INVALID_HANDLE) {
+            ALOGD("%s() INVALID_HANDLE, stream was probably stolen", __func__);
+            result = AAUDIO_OK;
+        }
+        return result;
     } else {
         return AAUDIO_OK;
     }
@@ -389,7 +438,12 @@
     setState(AAUDIO_STREAM_STATE_STOPPING);
     mAtomicInternalTimestamp.clear();
 
-    return mServiceInterface.stopStream(mServiceStreamHandle);
+    result = mServiceInterface.stopStream(mServiceStreamHandle);
+    if (result == AAUDIO_ERROR_INVALID_HANDLE) {
+        ALOGD("%s() INVALID_HANDLE, stream was probably stolen", __func__);
+        result = AAUDIO_OK;
+    }
+    return result;
 }
 
 aaudio_result_t AudioStreamInternal::registerThread() {
@@ -411,13 +465,14 @@
 }
 
 aaudio_result_t AudioStreamInternal::startClient(const android::AudioClient& client,
+                                                 const audio_attributes_t *attr,
                                                  audio_port_handle_t *portHandle) {
     ALOGV("%s() called", __func__);
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
         return AAUDIO_ERROR_INVALID_STATE;
     }
     aaudio_result_t result =  mServiceInterface.startClient(mServiceStreamHandle,
-                                                            client, portHandle);
+                                                            client, attr, portHandle);
     ALOGV("%s(%d) returning %d", __func__, *portHandle, result);
     return result;
 }
@@ -478,7 +533,8 @@
 #if LOG_TIMESTAMPS
     logTimestamp(*message);
 #endif
-    processTimestamp(message->timestamp.position, message->timestamp.timestamp);
+    processTimestamp(message->timestamp.position,
+            message->timestamp.timestamp + mTimeOffsetNanos);
     return AAUDIO_OK;
 }
 
@@ -519,7 +575,7 @@
         case AAUDIO_SERVICE_EVENT_DISCONNECTED:
             // Prevent hardware from looping on old data and making buzzing sounds.
             if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
-                mAudioEndpoint.eraseDataMemory();
+                mAudioEndpoint->eraseDataMemory();
             }
             result = AAUDIO_ERROR_DISCONNECTED;
             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
@@ -545,7 +601,10 @@
 
     while (result == AAUDIO_OK) {
         AAudioServiceMessage message;
-        if (mAudioEndpoint.readUpCommand(&message) != 1) {
+        if (!mAudioEndpoint) {
+            break;
+        }
+        if (mAudioEndpoint->readUpCommand(&message) != 1) {
             break; // no command this time, no problem
         }
         switch (message.what) {
@@ -573,7 +632,10 @@
 
     while (result == AAUDIO_OK) {
         AAudioServiceMessage message;
-        if (mAudioEndpoint.readUpCommand(&message) != 1) {
+        if (!mAudioEndpoint) {
+            break;
+        }
+        if (mAudioEndpoint->readUpCommand(&message) != 1) {
             break; // no command this time, no problem
         }
         switch (message.what) {
@@ -606,7 +668,7 @@
     const char * fifoName = "aaRdy";
     ATRACE_BEGIN(traceName);
     if (ATRACE_ENABLED()) {
-        int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable();
+        int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable();
         ATRACE_INT(fifoName, fullFrames);
     }
 
@@ -634,8 +696,8 @@
         // Should we block?
         if (timeoutNanoseconds == 0) {
             break; // don't block
-        } else if (framesLeft > 0) {
-            if (!mAudioEndpoint.isFreeRunning()) {
+        } else if (wakeTimeNanos != 0) {
+            if (!mAudioEndpoint->isFreeRunning()) {
                 // If there is software on the other end of the FIFO then it may get delayed.
                 // So wake up just a little after we expect it to be ready.
                 wakeTimeNanos += mWakeupDelayNanos;
@@ -660,12 +722,12 @@
                 ALOGW("processData(): past deadline by %d micros",
                       (int)((wakeTimeNanos - deadlineNanos) / AAUDIO_NANOS_PER_MICROSECOND));
                 mClockModel.dump();
-                mAudioEndpoint.dump();
+                mAudioEndpoint->dump();
                 break;
             }
 
             if (ATRACE_ENABLED()) {
-                int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable();
+                int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable();
                 ATRACE_INT(fifoName, fullFrames);
                 int64_t sleepForNanos = wakeTimeNanos - currentTimeNanos;
                 ATRACE_INT("aaSlpNs", (int32_t)sleepForNanos);
@@ -677,7 +739,7 @@
     }
 
     if (ATRACE_ENABLED()) {
-        int32_t fullFrames = mAudioEndpoint.getFullFramesAvailable();
+        int32_t fullFrames = mAudioEndpoint->getFullFramesAvailable();
         ATRACE_INT(fifoName, fullFrames);
     }
 
@@ -693,41 +755,53 @@
 
 aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
     int32_t adjustedFrames = requestedFrames;
-    int32_t actualFrames = 0;
-    int32_t maximumSize = getBufferCapacity();
+    const int32_t maximumSize = getBufferCapacity() - mFramesPerBurst;
+    // Minimum size should be a multiple number of bursts.
+    const int32_t minimumSize = 1 * mFramesPerBurst;
 
     // Clip to minimum size so that rounding up will work better.
-    if (adjustedFrames < 1) {
-        adjustedFrames = 1;
-    }
+    adjustedFrames = std::max(minimumSize, adjustedFrames);
 
-    if (adjustedFrames > maximumSize) {
-        // Clip to maximum size.
+    // Prevent arithmetic overflow by clipping before we round.
+    if (adjustedFrames >= maximumSize) {
         adjustedFrames = maximumSize;
     } else {
         // Round to the next highest burst size.
         int32_t numBursts = (adjustedFrames + mFramesPerBurst - 1) / mFramesPerBurst;
         adjustedFrames = numBursts * mFramesPerBurst;
-        // Rounding may have gone above maximum.
-        if (adjustedFrames > maximumSize) {
-            adjustedFrames = maximumSize;
-        }
+        // Clip just in case maximumSize is not a multiple of mFramesPerBurst.
+        adjustedFrames = std::min(maximumSize, adjustedFrames);
     }
 
-    aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(adjustedFrames, &actualFrames);
-    if (result < 0) {
-        return result;
-    } else {
-        return (aaudio_result_t) actualFrames;
+    if (mAudioEndpoint) {
+        // Clip against the actual size from the endpoint.
+        int32_t actualFrames = 0;
+        // Set to maximum size so we can write extra data when ready in order to reduce glitches.
+        // The amount we keep in the buffer is controlled by mBufferSizeInFrames.
+        mAudioEndpoint->setBufferSizeInFrames(maximumSize, &actualFrames);
+        // actualFrames should be <= actual maximum size of endpoint
+        adjustedFrames = std::min(actualFrames, adjustedFrames);
     }
+
+    if (adjustedFrames != mBufferSizeInFrames) {
+        android::mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETBUFFERSIZE)
+                .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, adjustedFrames)
+                .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
+                .record();
+    }
+
+    mBufferSizeInFrames = adjustedFrames;
+    ALOGV("%s(%d) returns %d", __func__, requestedFrames, adjustedFrames);
+    return (aaudio_result_t) adjustedFrames;
 }
 
 int32_t AudioStreamInternal::getBufferSize() const {
-    return mAudioEndpoint.getBufferSizeInFrames();
+    return mBufferSizeInFrames;
 }
 
 int32_t AudioStreamInternal::getBufferCapacity() const {
-    return mAudioEndpoint.getBufferCapacityInFrames();
+    return mBufferCapacityInFrames;
 }
 
 int32_t AudioStreamInternal::getFramesPerBurst() const {
@@ -740,5 +814,5 @@
 }
 
 bool AudioStreamInternal::isClockModelInControl() const {
-    return isActive() && mAudioEndpoint.isFreeRunning() && mClockModel.isRunning();
+    return isActive() && mAudioEndpoint->isFreeRunning() && mClockModel.isRunning();
 }
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 86c4698..61591b3 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -58,7 +58,7 @@
 
     aaudio_result_t open(const AudioStreamBuilder &builder) override;
 
-    aaudio_result_t close() override;
+    aaudio_result_t release_l() override;
 
     aaudio_result_t setBufferSize(int32_t requestedFrames) override;
 
@@ -90,6 +90,7 @@
     int64_t calculateReasonableTimeout();
 
     aaudio_result_t startClient(const android::AudioClient& client,
+                                const audio_attributes_t *attr,
                                 audio_port_handle_t *clientHandle);
 
     aaudio_result_t stopClient(audio_port_handle_t clientHandle);
@@ -154,7 +155,8 @@
 
     IsochronousClockModel    mClockModel;      // timing model for chasing the HAL
 
-    AudioEndpoint            mAudioEndpoint;   // source for reads or sink for writes
+    std::unique_ptr<AudioEndpoint> mAudioEndpoint;   // source for reads or sink for writes
+
     aaudio_handle_t          mServiceStreamHandle; // opaque handle returned from service
 
     int32_t                  mFramesPerBurst = MIN_FRAMES_PER_BURST; // frames per HAL transfer
@@ -163,7 +165,7 @@
     // Offset from underlying frame position.
     int64_t                  mFramesOffsetFromService = 0; // offset for timestamps
 
-    uint8_t                 *mCallbackBuffer = nullptr;
+    std::unique_ptr<uint8_t[]> mCallbackBuffer;
     int32_t                  mCallbackFrames = 0;
 
     // The service uses this for SHARED mode.
@@ -177,6 +179,9 @@
 
     float                    mStreamVolume = 1.0f;
 
+    int64_t                  mLastFramesWritten = 0;
+    int64_t                  mLastFramesRead = 0;
+
 private:
     /*
      * Asynchronous write with data conversion.
@@ -194,6 +199,7 @@
     // By delaying slightly we can avoid waking up before other side is ready.
     const int32_t            mWakeupDelayNanos; // delay past typical wakeup jitter
     const int32_t            mMinimumSleepNanos; // minimum sleep while polling
+    int32_t                  mTimeOffsetNanos = 0; // add to time part of an MMAP timestamp
 
     AudioEndpointParcelable  mEndPointParcelable; // description of the buffers filled by service
     EndpointDescriptor       mEndpointDescriptor; // buffer description with resolved addresses
@@ -203,6 +209,11 @@
     // Sometimes the hardware is operating with a different channel count from the app.
     // Then we require conversion in AAudio.
     int32_t                  mDeviceChannelCount = 0;
+
+    int32_t                  mBufferSizeInFrames = 0; // local threshold to control latency
+    int32_t                  mBufferCapacityInFrames = 0;
+
+
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 366cc87..9fa2e40 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -42,8 +42,8 @@
 AudioStreamInternalCapture::~AudioStreamInternalCapture() {}
 
 void AudioStreamInternalCapture::advanceClientToMatchServerPosition() {
-    int64_t readCounter = mAudioEndpoint.getDataReadCounter();
-    int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
+    int64_t readCounter = mAudioEndpoint->getDataReadCounter();
+    int64_t writeCounter = mAudioEndpoint->getDataWriteCounter();
 
     // Bump offset so caller does not see the retrograde motion in getFramesRead().
     int64_t offset = readCounter - writeCounter;
@@ -53,7 +53,7 @@
 
     // Force readCounter to match writeCounter.
     // This is because we cannot change the write counter in the hardware.
-    mAudioEndpoint.setDataReadCounter(writeCounter);
+    mAudioEndpoint->setDataReadCounter(writeCounter);
 }
 
 // Write the data, block if needed and timeoutMillis > 0
@@ -86,7 +86,7 @@
     }
     // If we have gotten this far then we have at least one timestamp from server.
 
-    if (mAudioEndpoint.isFreeRunning()) {
+    if (mAudioEndpoint->isFreeRunning()) {
         //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
         // Update data queue based on the timing model.
         // Jitter in the DSP can cause late writes to the FIFO.
@@ -95,7 +95,7 @@
         // that the DSP could have written the data.
         int64_t estimatedRemoteCounter = mClockModel.convertLatestTimeToPosition(currentNanoTime);
         // TODO refactor, maybe use setRemoteCounter()
-        mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter);
+        mAudioEndpoint->setDataWriteCounter(estimatedRemoteCounter);
     }
 
     // This code assumes that we have already received valid timestamps.
@@ -106,9 +106,10 @@
         mNeedCatchUp.acknowledge();
     }
 
-    // If the write index passed the read index then consider it an overrun.
+    // If the capture buffer is full beyond capacity then consider it an overrun.
     // For shared streams, the xRunCount is passed up from the service.
-    if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getEmptyFramesAvailable() < 0) {
+    if (mAudioEndpoint->isFreeRunning()
+        && mAudioEndpoint->getFullFramesAvailable() > mAudioEndpoint->getBufferCapacityInFrames()) {
         mXRunCount++;
         if (ATRACE_ENABLED()) {
             ATRACE_INT("aaOverRuns", mXRunCount);
@@ -142,7 +143,7 @@
                 // Calculate frame position based off of the readCounter because
                 // the writeCounter might have just advanced in the background,
                 // causing us to sleep until a later burst.
-                int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
+                int64_t nextPosition = mAudioEndpoint->getDataReadCounter() + mFramesPerBurst;
                 wakeTime = mClockModel.convertPositionToLatestTime(nextPosition);
             }
                 break;
@@ -165,7 +166,7 @@
     uint8_t *destination = (uint8_t *) buffer;
     int32_t framesLeft = numFrames;
 
-    mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer);
+    mAudioEndpoint->getFullFramesAvailable(&wrappingBuffer);
 
     // Read data in one or two parts.
     for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) {
@@ -207,26 +208,29 @@
     }
 
     int32_t framesProcessed = numFrames - framesLeft;
-    mAudioEndpoint.advanceReadIndex(framesProcessed);
+    mAudioEndpoint->advanceReadIndex(framesProcessed);
 
     //ALOGD("readNowWithConversion() returns %d", framesProcessed);
     return framesProcessed;
 }
 
 int64_t AudioStreamInternalCapture::getFramesWritten() {
-    const int64_t framesWrittenHardware = isClockModelInControl()
-            ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
-            : mAudioEndpoint.getDataWriteCounter();
-    // Add service offset and prevent retrograde motion.
-    mLastFramesWritten = std::max(mLastFramesWritten,
-                                  framesWrittenHardware + mFramesOffsetFromService);
+    if (mAudioEndpoint) {
+        const int64_t framesWrittenHardware = isClockModelInControl()
+                ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
+                : mAudioEndpoint->getDataWriteCounter();
+        // Add service offset and prevent retrograde motion.
+        mLastFramesWritten = std::max(mLastFramesWritten,
+                                      framesWrittenHardware + mFramesOffsetFromService);
+    }
     return mLastFramesWritten;
 }
 
 int64_t AudioStreamInternalCapture::getFramesRead() {
-    int64_t frames = mAudioEndpoint.getDataReadCounter() + mFramesOffsetFromService;
-    //ALOGD("getFramesRead() returns %lld", (long long)frames);
-    return frames;
+    if (mAudioEndpoint) {
+        mLastFramesRead = mAudioEndpoint->getDataReadCounter() + mFramesOffsetFromService;
+    }
+    return mLastFramesRead;
 }
 
 // Read data from the stream and pass it to the callback for processing.
@@ -242,7 +246,7 @@
         int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames);
 
         // This is a BLOCKING READ!
-        result = read(mCallbackBuffer, mCallbackFrames, timeoutNanos);
+        result = read(mCallbackBuffer.get(), mCallbackFrames, timeoutNanos);
         if ((result != mCallbackFrames)) {
             ALOGE("callbackLoop: read() returned %d", result);
             if (result >= 0) {
@@ -254,7 +258,7 @@
         }
 
         // Call application using the AAudio callback interface.
-        callbackResult = maybeCallDataCallback(mCallbackBuffer, mCallbackFrames);
+        callbackResult = maybeCallDataCallback(mCallbackBuffer.get(), mCallbackFrames);
 
         if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
             ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.h b/media/libaaudio/src/client/AudioStreamInternalCapture.h
index 294dbaf..6436a53 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.h
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.h
@@ -68,8 +68,6 @@
      * @return frames written or negative error
      */
     aaudio_result_t readNowWithConversion(void *buffer, int32_t numFrames);
-
-    int64_t       mLastFramesWritten = 0; // used to prevent retrograde motion
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index b8ef247..1303daf 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -49,7 +49,7 @@
                              getDeviceChannelCount());
 
         if (result != AAUDIO_OK) {
-            close();
+            releaseCloseFinal();
         }
         // Sample rate is constrained to common values by now and should not overflow.
         int32_t numFrames = kRampMSec * getSampleRate() / AAUDIO_MILLIS_PER_SECOND;
@@ -87,8 +87,8 @@
 }
 
 void AudioStreamInternalPlay::advanceClientToMatchServerPosition() {
-    int64_t readCounter = mAudioEndpoint.getDataReadCounter();
-    int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
+    int64_t readCounter = mAudioEndpoint->getDataReadCounter();
+    int64_t writeCounter = mAudioEndpoint->getDataWriteCounter();
 
     // Bump offset so caller does not see the retrograde motion in getFramesRead().
     int64_t offset = writeCounter - readCounter;
@@ -98,7 +98,7 @@
 
     // Force writeCounter to match readCounter.
     // This is because we cannot change the read counter in the hardware.
-    mAudioEndpoint.setDataWriteCounter(readCounter);
+    mAudioEndpoint->setDataWriteCounter(readCounter);
 }
 
 void AudioStreamInternalPlay::onFlushFromServer() {
@@ -135,11 +135,11 @@
     // If we have gotten this far then we have at least one timestamp from server.
 
     // If a DMA channel or DSP is reading the other end then we have to update the readCounter.
-    if (mAudioEndpoint.isFreeRunning()) {
+    if (mAudioEndpoint->isFreeRunning()) {
         // Update data queue based on the timing model.
         int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
         // ALOGD("AudioStreamInternal::processDataNow() - estimatedReadCounter = %d", (int)estimatedReadCounter);
-        mAudioEndpoint.setDataReadCounter(estimatedReadCounter);
+        mAudioEndpoint->setDataReadCounter(estimatedReadCounter);
     }
 
     if (mNeedCatchUp.isRequested()) {
@@ -151,7 +151,7 @@
 
     // If the read index passed the write index then consider it an underrun.
     // For shared streams, the xRunCount is passed up from the service.
-    if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getFullFramesAvailable() < 0) {
+    if (mAudioEndpoint->isFreeRunning() && mAudioEndpoint->getFullFramesAvailable() < 0) {
         mXRunCount++;
         if (ATRACE_ENABLED()) {
             ATRACE_INT("aaUnderRuns", mXRunCount);
@@ -167,8 +167,10 @@
         ATRACE_INT("aaWrote", framesWritten);
     }
 
+    // Sleep if there is too much data in the buffer.
     // Calculate an ideal time to wake up.
-    if (wakeTimePtr != nullptr && framesWritten >= 0) {
+    if (wakeTimePtr != nullptr
+            && (mAudioEndpoint->getFullFramesAvailable() >= getBufferSize())) {
         // By default wake up a few milliseconds from now.  // TODO review
         int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
         aaudio_stream_state_t state = getState();
@@ -184,14 +186,10 @@
                 break;
             case AAUDIO_STREAM_STATE_STARTED:
             {
-                // When do we expect the next read burst to occur?
-
-                // Calculate frame position based off of the writeCounter because
-                // the readCounter might have just advanced in the background,
-                // causing us to sleep until a later burst.
-                int64_t nextPosition = mAudioEndpoint.getDataWriteCounter() + mFramesPerBurst
-                        - mAudioEndpoint.getBufferSizeInFrames();
-                wakeTime = mClockModel.convertPositionToTime(nextPosition);
+                // Sleep until the readCounter catches up and we only have
+                // the getBufferSize() frames of data sitting in the buffer.
+                int64_t nextReadPosition = mAudioEndpoint->getDataWriteCounter() - getBufferSize();
+                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
             }
                 break;
             default:
@@ -212,7 +210,7 @@
     uint8_t *byteBuffer = (uint8_t *) buffer;
     int32_t framesLeft = numFrames;
 
-    mAudioEndpoint.getEmptyFramesAvailable(&wrappingBuffer);
+    mAudioEndpoint->getEmptyFramesAvailable(&wrappingBuffer);
 
     // Write data in one or two parts.
     int partIndex = 0;
@@ -238,24 +236,28 @@
         partIndex++;
     }
     int32_t framesWritten = numFrames - framesLeft;
-    mAudioEndpoint.advanceWriteIndex(framesWritten);
+    mAudioEndpoint->advanceWriteIndex(framesWritten);
 
     return framesWritten;
 }
 
 int64_t AudioStreamInternalPlay::getFramesRead() {
-    const int64_t framesReadHardware = isClockModelInControl()
-            ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
-            : mAudioEndpoint.getDataReadCounter();
-    // Add service offset and prevent retrograde motion.
-    mLastFramesRead = std::max(mLastFramesRead, framesReadHardware + mFramesOffsetFromService);
+    if (mAudioEndpoint) {
+        const int64_t framesReadHardware = isClockModelInControl()
+                ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
+                : mAudioEndpoint->getDataReadCounter();
+        // Add service offset and prevent retrograde motion.
+        mLastFramesRead = std::max(mLastFramesRead, framesReadHardware + mFramesOffsetFromService);
+    }
     return mLastFramesRead;
 }
 
 int64_t AudioStreamInternalPlay::getFramesWritten() {
-    const int64_t framesWritten = mAudioEndpoint.getDataWriteCounter()
-                               + mFramesOffsetFromService;
-    return framesWritten;
+    if (mAudioEndpoint) {
+        mLastFramesWritten = mAudioEndpoint->getDataWriteCounter()
+                             + mFramesOffsetFromService;
+    }
+    return mLastFramesWritten;
 }
 
 
@@ -270,11 +272,11 @@
     // result might be a frame count
     while (mCallbackEnabled.load() && isActive() && (result >= 0)) {
         // Call application using the AAudio callback interface.
-        callbackResult = maybeCallDataCallback(mCallbackBuffer, mCallbackFrames);
+        callbackResult = maybeCallDataCallback(mCallbackBuffer.get(), mCallbackFrames);
 
         if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
             // Write audio data to stream. This is a BLOCKING WRITE!
-            result = write(mCallbackBuffer, mCallbackFrames, timeoutNanos);
+            result = write(mCallbackBuffer.get(), mCallbackFrames, timeoutNanos);
             if ((result != mCallbackFrames)) {
                 if (result >= 0) {
                     // Only wrote some of the frames requested. Must have timed out.
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.h b/media/libaaudio/src/client/AudioStreamInternalPlay.h
index cab2942..2e93157 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.h
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.h
@@ -92,8 +92,6 @@
     aaudio_result_t writeNowWithConversion(const void *buffer,
                                            int32_t numFrames);
 
-    int64_t                  mLastFramesRead = 0; // used to prevent retrograde motion
-
     AAudioFlowGraph          mFlowGraph;
 
 };
diff --git a/media/libaaudio/src/client/IsochronousClockModel.cpp b/media/libaaudio/src/client/IsochronousClockModel.cpp
index 9abdf53..f0dcd44 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.cpp
+++ b/media/libaaudio/src/client/IsochronousClockModel.cpp
@@ -18,25 +18,44 @@
 //#define LOG_NDEBUG 0
 #include <log/log.h>
 
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
 #include <stdint.h>
 #include <algorithm>
 
 #include "utility/AudioClock.h"
+#include "utility/AAudioUtilities.h"
 #include "IsochronousClockModel.h"
 
 using namespace aaudio;
 
+using namespace android::audio_utils;
+
+#ifndef ICM_LOG_DRIFT
+#define ICM_LOG_DRIFT   0
+#endif // ICM_LOG_DRIFT
+
+// To enable the timestamp histogram, enter this before opening the stream:
+//    adb root
+//    adb shell setprop aaudio.log_mask 1
+// A histogram of the lateness of the timestamps will be cleared when the stream is started.
+// It will be updated when the model is stable and receives a timestamp,
+// and dumped to the log when the stream is stopped.
+
 IsochronousClockModel::IsochronousClockModel()
         : mMarkerFramePosition(0)
         , mMarkerNanoTime(0)
         , mSampleRate(48000)
-        , mFramesPerBurst(64)
+        , mFramesPerBurst(48)
+        , mBurstPeriodNanos(0) // this will be updated before use
         , mMaxMeasuredLatenessNanos(0)
+        , mLatenessForDriftNanos(kInitialLatenessForDriftNanos)
         , mState(STATE_STOPPED)
 {
-}
-
-IsochronousClockModel::~IsochronousClockModel() {
+    if ((AAudioProperty_getLogMask() & AAUDIO_LOG_CLOCK_MODEL_HISTOGRAM) != 0) {
+        mHistogramMicros = std::make_unique<Histogram>(kHistogramBinCount,
+                kHistogramBinWidthMicros);
+    }
 }
 
 void IsochronousClockModel::setPositionAndTime(int64_t framePosition, int64_t nanoTime) {
@@ -49,6 +68,9 @@
     ALOGV("start(nanos = %lld)\n", (long long) nanoTime);
     mMarkerNanoTime = nanoTime;
     mState = STATE_STARTING;
+    if (mHistogramMicros) {
+        mHistogramMicros->clear();
+    }
 }
 
 void IsochronousClockModel::stop(int64_t nanoTime) {
@@ -58,6 +80,9 @@
     setPositionAndTime(convertTimeToPosition(nanoTime), nanoTime);
     // TODO should we set position?
     mState = STATE_STOPPED;
+    if (mHistogramMicros) {
+        dumpHistogram();
+    }
 }
 
 bool IsochronousClockModel::isStarting() const {
@@ -90,6 +115,7 @@
 
 //    ALOGD("processTimestamp() - mSampleRate = %d", mSampleRate);
 //    ALOGD("processTimestamp() - mState = %d", mState);
+    int64_t latenessNanos = nanosDelta - expectedNanosDelta;
     switch (mState) {
     case STATE_STOPPED:
         break;
@@ -99,7 +125,7 @@
         break;
     case STATE_SYNCING:
         // This will handle a burst of rapid transfer at the beginning.
-        if (nanosDelta < expectedNanosDelta) {
+        if (latenessNanos < 0) {
             setPositionAndTime(framePosition, nanoTime);
         } else {
 //            ALOGD("processTimestamp() - advance to STATE_RUNNING");
@@ -107,65 +133,67 @@
         }
         break;
     case STATE_RUNNING:
-        if (nanosDelta < expectedNanosDelta) {
+        if (mHistogramMicros) {
+            mHistogramMicros->add(latenessNanos / AAUDIO_NANOS_PER_MICROSECOND);
+        }
+        // Modify estimated position based on lateness.
+        // This affects the "early" side of the window, which controls output glitches.
+        if (latenessNanos < 0) {
             // Earlier than expected timestamp.
             // This data is probably more accurate, so use it.
             // Or we may be drifting due to a fast HW clock.
-            //int microsDelta = (int) (nanosDelta / 1000);
-            //int expectedMicrosDelta = (int) (expectedNanosDelta / 1000);
-            //ALOGD("%s() - STATE_RUNNING - #%d, %4d micros EARLY",
-                //__func__, mTimestampCount, expectedMicrosDelta - microsDelta);
-
             setPositionAndTime(framePosition, nanoTime);
-        } else if (nanosDelta > (expectedNanosDelta + (2 * mBurstPeriodNanos))) {
-            // In this case we do not update mMaxMeasuredLatenessNanos because it
-            // would force it too high.
-            // mMaxMeasuredLatenessNanos should range from 1 to 2 * mBurstPeriodNanos
-            //int32_t measuredLatenessNanos = (int32_t)(nanosDelta - expectedNanosDelta);
-            //ALOGD("%s() - STATE_RUNNING - #%d, lateness %d - max %d = %4d micros VERY LATE",
-                  //__func__,
-                  //mTimestampCount,
-                  //measuredLatenessNanos / 1000,
-                  //mMaxMeasuredLatenessNanos / 1000,
-                  //(measuredLatenessNanos - mMaxMeasuredLatenessNanos) / 1000
-                  //);
-
-            // This typically happens when we are modelling a service instead of a DSP.
-            setPositionAndTime(framePosition,  nanoTime - (2 * mBurstPeriodNanos));
-        } else if (nanosDelta > (expectedNanosDelta + mMaxMeasuredLatenessNanos)) {
-            //int32_t previousLatenessNanos = mMaxMeasuredLatenessNanos;
-            mMaxMeasuredLatenessNanos = (int32_t)(nanosDelta - expectedNanosDelta);
-
-            //ALOGD("%s() - STATE_RUNNING - #%d, newmax %d - oldmax %d = %4d micros LATE",
-                  //__func__,
-                  //mTimestampCount,
-                  //mMaxMeasuredLatenessNanos / 1000,
-                  //previousLatenessNanos / 1000,
-                  //(mMaxMeasuredLatenessNanos - previousLatenessNanos) / 1000
-                  //);
-
-            // When we are late, it may be because of preemption in the kernel,
+#if ICM_LOG_DRIFT
+            int earlyDeltaMicros = (int) ((expectedNanosDelta - nanosDelta)/ 1000);
+            ALOGD("%s() - STATE_RUNNING - #%d, %4d micros EARLY",
+                __func__, mTimestampCount, earlyDeltaMicros);
+#endif
+        } else if (latenessNanos > mLatenessForDriftNanos) {
+            // When we are on the late side, it may be because of preemption in the kernel,
             // or timing jitter caused by resampling in the DSP,
             // or we may be drifting due to a slow HW clock.
             // We add slight drift value just in case there is actual long term drift
             // forward caused by a slower clock.
             // If the clock is faster than the model will get pushed earlier
-            // by the code in the preceding branch.
+            // by the code in the earlier branch.
             // The two opposing forces should allow the model to track the real clock
             // over a long time.
             int64_t driftingTime = mMarkerNanoTime + expectedNanosDelta + kDriftNanos;
             setPositionAndTime(framePosition,  driftingTime);
-            //ALOGD("%s() - #%d, max lateness = %d micros",
-                  //__func__,
-                  //mTimestampCount,
-                  //(int) (mMaxMeasuredLatenessNanos / 1000));
+#if ICM_LOG_DRIFT
+            ALOGD("%s() - STATE_RUNNING - #%d, DRIFT, lateness = %d micros",
+                  __func__,
+                  mTimestampCount,
+                  (int) (latenessNanos / 1000));
+#endif
+        }
+
+        // Modify mMaxMeasuredLatenessNanos.
+        // This affects the "late" side of the window, which controls input glitches.
+        if (latenessNanos > mMaxMeasuredLatenessNanos) { // increase
+#if ICM_LOG_DRIFT
+            ALOGD("%s() - STATE_RUNNING - #%d, newmax %d - oldmax %d = %4d micros LATE",
+                    __func__,
+                    mTimestampCount,
+                    (int) (latenessNanos / 1000),
+                    mMaxMeasuredLatenessNanos / 1000,
+                    (int) ((latenessNanos - mMaxMeasuredLatenessNanos) / 1000)
+                    );
+#endif
+            mMaxMeasuredLatenessNanos = (int32_t) latenessNanos;
+            // Calculate upper region that will trigger a drift forwards.
+            mLatenessForDriftNanos = mMaxMeasuredLatenessNanos - (mMaxMeasuredLatenessNanos >> 4);
+        } else { // decrease
+            // If this is an outlier in lateness then mMaxMeasuredLatenessNanos can go high
+            // and stay there. So we slowly reduce mMaxMeasuredLatenessNanos for better
+            // long term stability. The two opposing forces will keep mMaxMeasuredLatenessNanos
+            // within a reasonable range.
+            mMaxMeasuredLatenessNanos -= kDriftNanos;
         }
         break;
     default:
         break;
     }
-
-//    ALOGD("processTimestamp() - mState = %d", mState);
 }
 
 void IsochronousClockModel::setSampleRate(int32_t sampleRate) {
@@ -181,9 +209,6 @@
 // Update expected lateness based on sampleRate and framesPerBurst
 void IsochronousClockModel::update() {
     mBurstPeriodNanos = convertDeltaPositionToTime(mFramesPerBurst); // uses mSampleRate
-    // Timestamps may be late by up to a burst because we are randomly sampling the time period
-    // after the DSP position is actually updated.
-    mMaxMeasuredLatenessNanos = mBurstPeriodNanos;
 }
 
 int64_t IsochronousClockModel::convertDeltaPositionToTime(int64_t framesDelta) const {
@@ -227,9 +252,7 @@
 }
 
 int32_t IsochronousClockModel::getLateTimeOffsetNanos() const {
-    // This will never be < 0 because mMaxLatenessNanos starts at
-    // mBurstPeriodNanos and only gets bigger.
-    return (mMaxMeasuredLatenessNanos - mBurstPeriodNanos) + kExtraLatenessNanos;
+    return mMaxMeasuredLatenessNanos + kExtraLatenessNanos;
 }
 
 int64_t IsochronousClockModel::convertPositionToLatestTime(int64_t framePosition) const {
@@ -241,10 +264,19 @@
 }
 
 void IsochronousClockModel::dump() const {
-    ALOGD("mMarkerFramePosition = %lld", (long long) mMarkerFramePosition);
-    ALOGD("mMarkerNanoTime      = %lld", (long long) mMarkerNanoTime);
+    ALOGD("mMarkerFramePosition = %" PRIu64, mMarkerFramePosition);
+    ALOGD("mMarkerNanoTime      = %" PRIu64, mMarkerNanoTime);
     ALOGD("mSampleRate          = %6d", mSampleRate);
     ALOGD("mFramesPerBurst      = %6d", mFramesPerBurst);
     ALOGD("mMaxMeasuredLatenessNanos = %6d", mMaxMeasuredLatenessNanos);
     ALOGD("mState               = %6d", mState);
 }
+
+void IsochronousClockModel::dumpHistogram() const {
+    if (!mHistogramMicros) return;
+    std::istringstream istr(mHistogramMicros->dump());
+    std::string line;
+    while (std::getline(istr, line)) {
+        ALOGD("lateness, %s", line.c_str());
+    }
+}
diff --git a/media/libaaudio/src/client/IsochronousClockModel.h b/media/libaaudio/src/client/IsochronousClockModel.h
index 582bf4e..6280013 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.h
+++ b/media/libaaudio/src/client/IsochronousClockModel.h
@@ -18,6 +18,9 @@
 #define ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
 
 #include <stdint.h>
+
+#include <audio_utils/Histogram.h>
+
 #include "utility/AudioClock.h"
 
 namespace aaudio {
@@ -32,7 +35,7 @@
 
 public:
     IsochronousClockModel();
-    virtual ~IsochronousClockModel();
+    virtual ~IsochronousClockModel() = default;
 
     void start(int64_t nanoTime);
     void stop(int64_t nanoTime);
@@ -122,9 +125,12 @@
 
     void dump() const;
 
+    void dumpHistogram() const;
+
 private:
 
     int32_t getLateTimeOffsetNanos() const;
+    void update();
 
     enum clock_model_state_t {
         STATE_STOPPED,
@@ -134,23 +140,31 @@
     };
 
     // Amount of time to drift forward when we get a late timestamp.
-    // This value was calculated to allow tracking of a clock with 50 ppm error.
-    static constexpr int32_t   kDriftNanos         =  10 * 1000;
-    // TODO review value of kExtraLatenessNanos
+    static constexpr int32_t   kDriftNanos         =   1 * 1000;
+    // Safety margin to add to the late edge of the timestamp window.
     static constexpr int32_t   kExtraLatenessNanos = 100 * 1000;
+    // Initial small threshold for causing a drift later in time.
+    static constexpr int32_t   kInitialLatenessForDriftNanos = 10 * 1000;
 
-    int64_t             mMarkerFramePosition;
-    int64_t             mMarkerNanoTime;
+    static constexpr int32_t   kHistogramBinWidthMicros = 50;
+    static constexpr int32_t   kHistogramBinCount = 128;
+
+    int64_t             mMarkerFramePosition; // Estimated HW position.
+    int64_t             mMarkerNanoTime;      // Estimated HW time.
     int32_t             mSampleRate;
-    int32_t             mFramesPerBurst;
-    int32_t             mBurstPeriodNanos;
+    int32_t             mFramesPerBurst;      // number of frames transferred at one time.
+    int32_t             mBurstPeriodNanos;    // Time between HW bursts.
     // Includes mBurstPeriodNanos because we sample randomly over time.
     int32_t             mMaxMeasuredLatenessNanos;
-    clock_model_state_t mState;
+    // Threshold for lateness that triggers a drift later in time.
+    int32_t             mLatenessForDriftNanos;
+    clock_model_state_t mState;               // State machine handles startup sequence.
 
-    int32_t             mTimestampCount = 0;
+    int32_t             mTimestampCount = 0;  // For logging.
 
-    void update();
+    // distribution of timestamps relative to earliest
+    std::unique_ptr<android::audio_utils::Histogram>   mHistogramMicros;
+
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 44d5122..8965875 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -25,8 +25,8 @@
 
 #include <aaudio/AAudio.h>
 #include <aaudio/AAudioTesting.h>
-
 #include "AudioClock.h"
+#include "AudioGlobal.h"
 #include "AudioStreamBuilder.h"
 #include "AudioStream.h"
 #include "binding/AAudioCommon.h"
@@ -45,63 +45,14 @@
         return AAUDIO_ERROR_NULL; \
     }
 
-#define AAUDIO_CASE_ENUM(name) case name: return #name
-
 AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) {
-    switch (returnCode) {
-        AAUDIO_CASE_ENUM(AAUDIO_OK);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
-        // reserved
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
-        // reserved
-        // reserved
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
-         // reserved
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
-        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
-    }
-    return "Unrecognized AAudio error.";
+    return AudioGlobal_convertResultToText(returnCode);
 }
 
 AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) {
-    switch (state) {
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
-        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
-    }
-    return "Unrecognized AAudio state.";
+    return AudioGlobal_convertStreamStateToText(state);
 }
 
-#undef AAUDIO_CASE_ENUM
-
-
-/******************************************
- * Static globals.
- */
-static aaudio_policy_t s_MMapPolicy = AAUDIO_UNSPECIFIED;
-
 static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream)
 {
     return (AudioStream*) stream;
@@ -197,6 +148,12 @@
     streamBuilder->setInputPreset(inputPreset);
 }
 
+AAUDIO_API void AAudioStreamBuilder_setPrivacySensitive(AAudioStreamBuilder* builder,
+                                                   bool privacySensitive) {
+    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+    streamBuilder->setPrivacySensitiveRequest(privacySensitive);
+}
+
 AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
                                                               int32_t frames)
 {
@@ -273,21 +230,42 @@
     return AAUDIO_ERROR_NULL;
 }
 
-AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
-{
+AAUDIO_API aaudio_result_t  AAudioStream_release(AAudioStream* stream) {
     aaudio_result_t result = AAUDIO_ERROR_NULL;
-    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+    AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
     if (audioStream != nullptr) {
         aaudio_stream_id_t id = audioStream->getId();
         ALOGD("%s(s#%u) called ---------------", __func__, id);
-        result = audioStream->safeClose();
-        // Close will only fail if called illegally, for example, from a callback.
+        result = audioStream->safeRelease();
+        // safeRelease() will only fail if called illegally, for example, from a callback.
+        // That would result in the release of an active stream, which would cause a crash.
+        if (result != AAUDIO_OK) {
+            ALOGW("%s(s#%u) failed. Release it from another thread.",
+                  __func__, id);
+        }
+        ALOGD("%s(s#%u) returned %d %s ---------", __func__,
+                id, result, AAudio_convertResultToText(result));
+    }
+    return result;
+}
+
+AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream) {
+    aaudio_result_t result = AAUDIO_ERROR_NULL;
+    AudioStream* audioStream = convertAAudioStreamToAudioStream(stream);
+    if (audioStream != nullptr) {
+        aaudio_stream_id_t id = audioStream->getId();
+        ALOGD("%s(s#%u) called ---------------", __func__, id);
+        result = audioStream->safeRelease();
+        // safeRelease will only fail if called illegally, for example, from a callback.
         // That would result in deleting an active stream, which would cause a crash.
-        if (result == AAUDIO_OK) {
-            audioStream->unregisterPlayerBase();
-            delete audioStream;
+        if (result != AAUDIO_OK) {
+            ALOGW("%s(s#%u) failed. Close it from another thread.",
+                  __func__, id);
         } else {
-            ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
+            audioStream->unregisterPlayerBase();
+             // Mark CLOSED to keep destructors from asserting.
+            audioStream->closeFinal();
+            delete audioStream;
         }
         ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
     }
@@ -543,23 +521,11 @@
 }
 
 AAUDIO_API aaudio_policy_t AAudio_getMMapPolicy() {
-    return s_MMapPolicy;
+    return AudioGlobal_getMMapPolicy();
 }
 
 AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) {
-    aaudio_result_t result = AAUDIO_OK;
-    switch(policy) {
-        case AAUDIO_UNSPECIFIED:
-        case AAUDIO_POLICY_NEVER:
-        case AAUDIO_POLICY_AUTO:
-        case AAUDIO_POLICY_ALWAYS:
-            s_MMapPolicy = policy;
-            break;
-        default:
-            result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-            break;
-    }
-    return result;
+    return AudioGlobal_setMMapPolicy(policy);
 }
 
 AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream)
@@ -567,3 +533,9 @@
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
     return audioStream->isMMap();
 }
+
+AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* stream)
+{
+    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+    return audioStream->isPrivacySensitive();
+}
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index c9711da..5f45261 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -47,6 +47,7 @@
     mContentType          = other.mContentType;
     mInputPreset          = other.mInputPreset;
     mAllowedCapturePolicy = other.mAllowedCapturePolicy;
+    mIsPrivacySensitive   = other.mIsPrivacySensitive;
 }
 
 static aaudio_result_t isFormatValid(audio_format_t format) {
@@ -132,6 +133,10 @@
         case AAUDIO_USAGE_ASSISTANCE_SONIFICATION:
         case AAUDIO_USAGE_GAME:
         case AAUDIO_USAGE_ASSISTANT:
+        case AAUDIO_SYSTEM_USAGE_EMERGENCY:
+        case AAUDIO_SYSTEM_USAGE_SAFETY:
+        case AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS:
+        case AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT:
             break; // valid
         default:
             ALOGD("usage not valid = %d", mUsage);
@@ -195,4 +200,5 @@
     ALOGD("mContentType          = %6d", mContentType);
     ALOGD("mInputPreset          = %6d", mInputPreset);
     ALOGD("mAllowedCapturePolicy = %6d", mAllowedCapturePolicy);
+    ALOGD("mIsPrivacySensitive   = %s", mIsPrivacySensitive ? "true" : "false");
 }
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 2e21a8d..3e65b37 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -128,6 +128,14 @@
         mSessionId = sessionId;
     }
 
+    bool isPrivacySensitive() const {
+        return mIsPrivacySensitive;
+    }
+
+    void setPrivacySensitive(bool privacySensitive) {
+        mIsPrivacySensitive = privacySensitive;
+    }
+
     /**
      * @return bytes per frame of getFormat()
      */
@@ -158,6 +166,7 @@
     int32_t                         mBufferCapacity       = AAUDIO_UNSPECIFIED;
     aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_UNSPECIFIED;
     aaudio_session_id_t             mSessionId            = AAUDIO_SESSION_ID_NONE;
+    bool                            mIsPrivacySensitive   = false;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioGlobal.cpp b/media/libaaudio/src/core/AudioGlobal.cpp
new file mode 100644
index 0000000..7f5d8d5
--- /dev/null
+++ b/media/libaaudio/src/core/AudioGlobal.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2019 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 <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+#include "AudioGlobal.h"
+
+/******************************************
+ * Static globals.
+ */
+namespace aaudio {
+
+static aaudio_policy_t g_MMapPolicy = AAUDIO_UNSPECIFIED;
+
+aaudio_policy_t AudioGlobal_getMMapPolicy() {
+  return g_MMapPolicy;
+}
+
+aaudio_result_t AudioGlobal_setMMapPolicy(aaudio_policy_t policy) {
+    aaudio_result_t result = AAUDIO_OK;
+    switch(policy) {
+        case AAUDIO_UNSPECIFIED:
+        case AAUDIO_POLICY_NEVER:
+        case AAUDIO_POLICY_AUTO:
+        case AAUDIO_POLICY_ALWAYS:
+            g_MMapPolicy = policy;
+            break;
+        default:
+            result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+            break;
+    }
+    return result;
+}
+
+#define AAUDIO_CASE_ENUM(name) case name: return #name
+
+const char* AudioGlobal_convertResultToText(aaudio_result_t returnCode) {
+    switch (returnCode) {
+        AAUDIO_CASE_ENUM(AAUDIO_OK);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
+        // reserved
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
+        // reserved
+        // reserved
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
+         // reserved
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
+        AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
+    }
+    return "Unrecognized";
+}
+
+const char* AudioGlobal_convertFormatToText(aaudio_format_t format) {
+      switch (format) {
+        AAUDIO_CASE_ENUM(AAUDIO_FORMAT_UNSPECIFIED);
+        AAUDIO_CASE_ENUM(AAUDIO_FORMAT_INVALID);
+        AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_I16);
+        AAUDIO_CASE_ENUM(AAUDIO_FORMAT_PCM_FLOAT);
+    }
+    return "Unrecognized";
+}
+
+const char* AudioGlobal_convertDirectionToText(aaudio_direction_t direction) {
+      switch (direction) {
+        AAUDIO_CASE_ENUM(AAUDIO_DIRECTION_INPUT);
+        AAUDIO_CASE_ENUM(AAUDIO_DIRECTION_OUTPUT);
+    }
+    return "Unrecognized";
+}
+
+const char* AudioGlobal_convertPerformanceModeToText(aaudio_performance_mode_t mode) {
+      switch (mode) {
+        AAUDIO_CASE_ENUM(AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
+        AAUDIO_CASE_ENUM(AAUDIO_PERFORMANCE_MODE_NONE);
+        AAUDIO_CASE_ENUM(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+    }
+    return "Unrecognized";
+}
+
+const char* AudioGlobal_convertSharingModeToText(aaudio_sharing_mode_t mode) {
+      switch (mode) {
+        AAUDIO_CASE_ENUM(AAUDIO_SHARING_MODE_SHARED);
+        AAUDIO_CASE_ENUM(AAUDIO_SHARING_MODE_EXCLUSIVE);
+    }
+    return "Unrecognized";
+}
+
+const char* AudioGlobal_convertStreamStateToText(aaudio_stream_state_t state) {
+      switch (state) {
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
+        AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
+    }
+    return "Unrecognized";
+}
+
+#undef AAUDIO_CASE_ENUM
+
+}  // namespace aaudio
diff --git a/media/libaaudio/src/core/AudioGlobal.h b/media/libaaudio/src/core/AudioGlobal.h
new file mode 100644
index 0000000..1e88d15
--- /dev/null
+++ b/media/libaaudio/src/core/AudioGlobal.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 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 AAUDIO_AUDIOGLOBAL_H
+#define AAUDIO_AUDIOGLOBAL_H
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+
+namespace aaudio {
+
+aaudio_policy_t AudioGlobal_getMMapPolicy();
+aaudio_result_t AudioGlobal_setMMapPolicy(aaudio_policy_t policy);
+
+const char* AudioGlobal_convertFormatToText(aaudio_format_t format);
+const char* AudioGlobal_convertDirectionToText(aaudio_direction_t direction);
+const char* AudioGlobal_convertPerformanceModeToText(aaudio_performance_mode_t mode);
+const char* AudioGlobal_convertResultToText(aaudio_result_t returnCode);
+const char* AudioGlobal_convertSharingModeToText(aaudio_sharing_mode_t mode);
+const char* AudioGlobal_convertStreamStateToText(aaudio_stream_state_t state);
+}
+
+#endif  // AAUDIO_AUDIOGLOBAL_H
+
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index f5c97d8..f5c75ca 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -20,14 +20,17 @@
 
 #include <atomic>
 #include <stdint.h>
+
+#include <media/MediaMetricsItem.h>
+
 #include <aaudio/AAudio.h>
 
 #include "AudioStreamBuilder.h"
 #include "AudioStream.h"
 #include "AudioClock.h"
+#include "AudioGlobal.h"
 
-using namespace aaudio;
-
+namespace aaudio {
 
 // Sequential number assigned to streams solely for debugging purposes.
 static aaudio_stream_id_t AAudio_getNextStreamId() {
@@ -51,7 +54,7 @@
                           || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
                           || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
                         "~AudioStream() - still in use, state = %s",
-                        AAudio_convertStreamStateToText(getState()));
+                        AudioGlobal_convertStreamStateToText(getState()));
 
     mPlayerBase->clearParentReference(); // remove reference to this AudioStream
 }
@@ -90,6 +93,7 @@
     if (mAllowedCapturePolicy == AAUDIO_UNSPECIFIED) {
         mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
     }
+    mIsPrivacySensitive = builder.isPrivacySensitive();
 
     // callbacks
     mFramesPerDataCallback = builder.getFramesPerDataCallback();
@@ -101,6 +105,27 @@
     return AAUDIO_OK;
 }
 
+void AudioStream::logOpen() {
+    if (mMetricsId.size() > 0) {
+        android::mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+                     AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
+                .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+                     AudioGlobal_convertSharingModeToText(getSharingMode()))
+                .record();
+    }
+}
+
+void AudioStream::logReleaseBufferState() {
+    if (mMetricsId.size() > 0) {
+        android::mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RELEASE)
+                .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t) getBufferSize())
+                .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
+                .record();
+    }
+}
+
 aaudio_result_t AudioStream::systemStart() {
     std::lock_guard<std::mutex> lock(mStreamLock);
 
@@ -109,6 +134,34 @@
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
+    switch (getState()) {
+        // Is this a good time to start?
+        case AAUDIO_STREAM_STATE_OPEN:
+        case AAUDIO_STREAM_STATE_PAUSING:
+        case AAUDIO_STREAM_STATE_PAUSED:
+        case AAUDIO_STREAM_STATE_STOPPING:
+        case AAUDIO_STREAM_STATE_STOPPED:
+        case AAUDIO_STREAM_STATE_FLUSHING:
+        case AAUDIO_STREAM_STATE_FLUSHED:
+            break; // Proceed with starting.
+
+        // Already started?
+        case AAUDIO_STREAM_STATE_STARTING:
+        case AAUDIO_STREAM_STATE_STARTED:
+            ALOGW("%s() stream was already started, state = %s", __func__,
+                  AudioGlobal_convertStreamStateToText(getState()));
+            return AAUDIO_ERROR_INVALID_STATE;
+
+        // Don't start when the stream is dead!
+        case AAUDIO_STREAM_STATE_DISCONNECTED:
+        case AAUDIO_STREAM_STATE_CLOSING:
+        case AAUDIO_STREAM_STATE_CLOSED:
+        default:
+            ALOGW("%s() stream is dead, state = %s", __func__,
+                  AudioGlobal_convertStreamStateToText(getState()));
+            return AAUDIO_ERROR_INVALID_STATE;
+    }
+
     aaudio_result_t result = requestStart();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
@@ -154,8 +207,8 @@
         case AAUDIO_STREAM_STATE_CLOSING:
         case AAUDIO_STREAM_STATE_CLOSED:
         default:
-            ALOGW("safePause() stream not running, state = %s",
-                  AAudio_convertStreamStateToText(getState()));
+            ALOGW("%s() stream not running, state = %s",
+                  __func__, AudioGlobal_convertStreamStateToText(getState()));
             return AAUDIO_ERROR_INVALID_STATE;
     }
 
@@ -240,32 +293,48 @@
         case AAUDIO_STREAM_STATE_CLOSED:
         default:
             ALOGW("%s() stream not running, state = %s", __func__,
-                  AAudio_convertStreamStateToText(getState()));
+                  AudioGlobal_convertStreamStateToText(getState()));
             return AAUDIO_ERROR_INVALID_STATE;
     }
 
     return requestStop();
 }
 
-aaudio_result_t AudioStream::safeClose() {
-    // This get temporarily unlocked in the close when joining callback threads.
+aaudio_result_t AudioStream::safeRelease() {
+    // This get temporarily unlocked in the release() when joining callback threads.
     std::lock_guard<std::mutex> lock(mStreamLock);
     if (collidesWithCallback()) {
         ALOGE("%s cannot be called from a callback!", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    return close();
+    if (getState() == AAUDIO_STREAM_STATE_CLOSING) {
+        return AAUDIO_OK;
+    }
+    return release_l();
 }
 
 void AudioStream::setState(aaudio_stream_state_t state) {
-    ALOGV("%s(%d) from %d to %d", __func__, getId(), mState, state);
+    ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
+    // Track transition to DISCONNECTED state.
+    if (state == AAUDIO_STREAM_STATE_DISCONNECTED && mState != state) {
+        android::mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
+                .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+                .record();
+    }
     // CLOSED is a final state
     if (mState == AAUDIO_STREAM_STATE_CLOSED) {
         ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
 
-    // Once DISCONNECTED, we can only move to CLOSED state.
-    } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
+    // Once CLOSING, we can only move to CLOSED state.
+    } else if (mState == AAUDIO_STREAM_STATE_CLOSING
                && state != AAUDIO_STREAM_STATE_CLOSED) {
+        ALOGE("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
+
+    // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
+    } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
+               && !(state == AAUDIO_STREAM_STATE_CLOSING
+                   || state == AAUDIO_STREAM_STATE_CLOSED)) {
         ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
 
     } else {
@@ -488,3 +557,5 @@
 void AudioStream::MyPlayerBase::destroy() {
     unregisterWithAudioManager();
 }
+
+}  // namespace aaudio
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 044c979..fb71c36 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -95,7 +95,6 @@
                                        int64_t *framePosition,
                                        int64_t *timeNanoseconds) = 0;
 
-
     /**
      * Update state machine.()
      * @return
@@ -114,14 +113,37 @@
      */
     virtual aaudio_result_t open(const AudioStreamBuilder& builder);
 
+    // log to MediaMetrics
+    virtual void logOpen();
+    void logReleaseBufferState();
+
     /**
-     * Close the stream and deallocate any resources from the open() call.
-     * It is safe to call close() multiple times.
+     * Free any hardware or system resources from the open() call.
+     * It is safe to call release_l() multiple times.
      */
-    virtual aaudio_result_t close() {
+    virtual aaudio_result_t release_l() {
+        setState(AAUDIO_STREAM_STATE_CLOSING);
         return AAUDIO_OK;
     }
 
+    aaudio_result_t closeFinal() {
+        // State is checked by destructor.
+        setState(AAUDIO_STREAM_STATE_CLOSED);
+        return AAUDIO_OK;
+    }
+
+    /**
+     * Release then close the stream.
+     * @return AAUDIO_OK or negative error.
+     */
+    aaudio_result_t releaseCloseFinal() {
+        aaudio_result_t result = release_l(); // TODO review locking
+        if (result == AAUDIO_OK) {
+          result = closeFinal();
+        }
+        return result;
+    }
+
     // This is only used to identify a stream in the logs without
     // revealing any pointers.
     aaudio_stream_id_t getId() {
@@ -234,6 +256,10 @@
         return mSessionId;
     }
 
+    bool isPrivacySensitive() const {
+        return mIsPrivacySensitive;
+    }
+
     /**
      * This is only valid after setSamplesPerFrame() and setFormat() have been called.
      */
@@ -369,7 +395,7 @@
      */
     aaudio_result_t systemStopFromCallback();
 
-    aaudio_result_t safeClose();
+    aaudio_result_t safeRelease();
 
 protected:
 
@@ -543,6 +569,15 @@
         mAllowedCapturePolicy = policy;
     }
 
+    /**
+     * This should not be called after the open() call.
+     */
+    void setPrivacySensitive(bool privacySensitive) {
+        mIsPrivacySensitive = privacySensitive;
+    }
+
+    std::string mMetricsId; // set once during open()
+
 private:
 
     aaudio_result_t safeStop();
@@ -565,6 +600,7 @@
     aaudio_content_type_t       mContentType     = AAUDIO_UNSPECIFIED;
     aaudio_input_preset_t       mInputPreset     = AAUDIO_UNSPECIFIED;
     aaudio_allowed_capture_policy_t mAllowedCapturePolicy = AAUDIO_ALLOW_CAPTURE_BY_ALL;
+    bool                        mIsPrivacySensitive = false;
 
     int32_t                     mSessionId = AAUDIO_UNSPECIFIED;
 
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 08f4958..60dad84 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -27,6 +27,7 @@
 #include "binding/AAudioBinderClient.h"
 #include "client/AudioStreamInternalCapture.h"
 #include "client/AudioStreamInternalPlay.h"
+#include "core/AudioGlobal.h"
 #include "core/AudioStream.h"
 #include "core/AudioStreamBuilder.h"
 #include "legacy/AudioStreamRecord.h"
@@ -112,7 +113,7 @@
     }
 
     // The API setting is the highest priority.
-    aaudio_policy_t mmapPolicy = AAudio_getMMapPolicy();
+    aaudio_policy_t mmapPolicy = AudioGlobal_getMMapPolicy();
     // If not specified then get from a system property.
     if (mmapPolicy == AAUDIO_UNSPECIFIED) {
         mmapPolicy = AAudioProperty_getMMapPolicy();
@@ -141,14 +142,14 @@
     // TODO Support other performance settings in MMAP mode.
     // Disable MMAP if low latency not requested.
     if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_LOW_LATENCY) {
-        ALOGD("%s() MMAP not available because AAUDIO_PERFORMANCE_MODE_LOW_LATENCY not used.",
+        ALOGD("%s() MMAP not used because AAUDIO_PERFORMANCE_MODE_LOW_LATENCY not requested.",
               __func__);
         allowMMap = false;
     }
 
     // SessionID and Effects are only supported in Legacy mode.
     if (getSessionId() != AAUDIO_SESSION_ID_NONE) {
-        ALOGD("%s() MMAP not available because sessionId used.", __func__);
+        ALOGD("%s() MMAP not used because sessionId specified.", __func__);
         allowMMap = false;
     }
 
@@ -157,6 +158,19 @@
         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     }
 
+    setPrivacySensitive(false);
+    if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_DEFAULT) {
+        // When not explicitly requested, set privacy sensitive mode according to input preset:
+        // communication and camcorder captures are considered privacy sensitive by default.
+        aaudio_input_preset_t preset = getInputPreset();
+        if (preset == AAUDIO_INPUT_PRESET_CAMCORDER
+                || preset == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION) {
+            setPrivacySensitive(true);
+        }
+    } else if (mPrivacySensitiveReq == PRIVACY_SENSITIVE_ENABLED) {
+        setPrivacySensitive(true);
+    }
+
     result = builder_createStream(getDirection(), sharingMode, allowMMap, &audioStream);
     if (result == AAUDIO_OK) {
         // Open the stream using the parameters from the builder.
@@ -179,10 +193,14 @@
                         *streamPtr = audioStream;
                     } else {
                         delete audioStream;
+                        audioStream = nullptr;
                     }
                 }
             }
         }
+        if (audioStream != nullptr) {
+            audioStream->logOpen();
+        }
     }
 
     return result;
@@ -256,4 +274,5 @@
           mFramesPerDataCallback);
     ALOGI("usage  = %6d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
           getUsage(), getContentType(), getInputPreset(), getAllowedCapturePolicy());
+    ALOGI("privacy sensitive = %s", isPrivacySensitive() ? "true" : "false");
 }
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index 8149af2..d5fb80d 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -98,6 +98,12 @@
         return this;
     }
 
+    AudioStreamBuilder* setPrivacySensitiveRequest(bool privacySensitive) {
+        mPrivacySensitiveReq =
+            privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
+        return this;
+    }
+
     aaudio_result_t build(AudioStream **streamPtr);
 
     virtual aaudio_result_t validate() const override;
@@ -114,6 +120,14 @@
 
     AAudioStream_errorCallback mErrorCallbackProc = nullptr;
     void                      *mErrorCallbackUserData = nullptr;
+
+    enum {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+    typedef int32_t privacy_sensitive_t;
+    privacy_sensitive_t        mPrivacySensitiveReq = PRIVACY_SENSITIVE_DEFAULT;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/fifo/FifoControllerBase.cpp b/media/libaaudio/src/fifo/FifoControllerBase.cpp
index 66e247f..1dece0e 100644
--- a/media/libaaudio/src/fifo/FifoControllerBase.cpp
+++ b/media/libaaudio/src/fifo/FifoControllerBase.cpp
@@ -33,7 +33,9 @@
 }
 
 fifo_frames_t FifoControllerBase::getFullFramesAvailable() {
-    return (fifo_frames_t) (getWriteCounter() - getReadCounter());
+    fifo_frames_t temp = 0;
+    __builtin_sub_overflow(getWriteCounter(), getReadCounter(), &temp);
+    return temp;
 }
 
 fifo_frames_t FifoControllerBase::getReadIndex() {
@@ -42,7 +44,9 @@
 }
 
 void FifoControllerBase::advanceReadIndex(fifo_frames_t numFrames) {
-    setReadCounter(getReadCounter() + numFrames);
+   fifo_counter_t temp = 0;
+    __builtin_add_overflow(getReadCounter(), numFrames, &temp);
+    setReadCounter(temp);
 }
 
 fifo_frames_t FifoControllerBase::getEmptyFramesAvailable() {
@@ -55,7 +59,9 @@
 }
 
 void FifoControllerBase::advanceWriteIndex(fifo_frames_t numFrames) {
-    setWriteCounter(getWriteCounter() + numFrames);
+    fifo_counter_t temp = 0;
+    __builtin_add_overflow(getWriteCounter(), numFrames, &temp);
+    setWriteCounter(temp);
 }
 
 void FifoControllerBase::setThreshold(fifo_frames_t threshold) {
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 91d2eff..c062882 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -26,6 +26,7 @@
 #include <media/AudioTimestamp.h>
 #include <utils/String16.h>
 
+#include "core/AudioGlobal.h"
 #include "core/AudioStream.h"
 #include "legacy/AudioStreamLegacy.h"
 
@@ -72,7 +73,7 @@
 
 // Implement FixedBlockProcessor
 int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
-    int32_t numFrames = numBytes / getBytesPerDeviceFrame();
+    int32_t numFrames = numBytes / mBlockAdapterBytesPerFrame;
     return (int32_t) callDataCallbackFrames(buffer, numFrames);
 }
 
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 8e78554..9c24b2b 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -128,16 +128,22 @@
         return mFramesRead.increment(frames);
     }
 
+    // This is used for exact matching by MediaMetrics. So do not change it.
+    // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_AAUDIO
+    static constexpr char     kCallerName[] = "aaudio";
+
     MonotonicCounter           mFramesWritten;
     MonotonicCounter           mFramesRead;
     MonotonicCounter           mTimestampPosition;
 
     FixedBlockAdapter         *mBlockAdapter = nullptr;
+    int32_t                    mBlockAdapterBytesPerFrame = 0;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
     int32_t                    mCallbackBufferSize = 0;
     const android::sp<StreamDeviceCallback>   mDeviceCallback;
 
     AtomicRequestor            mRequestDisconnect;
+
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 71efc30..b0dc59e 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -142,11 +142,13 @@
     const audio_source_t source =
             AAudioConvert_inputPresetToAudioSource(builder.getInputPreset());
 
+    const audio_flags_mask_t attrFlags =
+            AAudioConvert_privacySensitiveToAudioFlagsMask(builder.isPrivacySensitive());
     const audio_attributes_t attributes = {
             .content_type = contentType,
             .usage = AUDIO_USAGE_UNKNOWN, // only used for output
             .source = source,
-            .flags = AUDIO_FLAG_NONE, // Different than the AUDIO_INPUT_FLAGS
+            .flags = attrFlags, // Different than the AUDIO_INPUT_FLAGS
             .tags = ""
     };
 
@@ -177,10 +179,13 @@
                 selectedDeviceId
         );
 
+        // Set it here so it can be logged by the destructor if the open failed.
+        mAudioRecord->setCallerName(kCallerName);
+
         // Did we get a valid track?
         status_t status = mAudioRecord->initCheck();
         if (status != OK) {
-            close();
+            releaseCloseFinal();
             ALOGE("open(), initCheck() returned %d", status);
             return AAudioConvert_androidToAAudioResult(status);
         }
@@ -200,6 +205,9 @@
         }
     }
 
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD)
+            + std::to_string(mAudioRecord->getPortId());
+
     // Get the actual values from the AudioRecord.
     setSamplesPerFrame(mAudioRecord->channelCount());
 
@@ -211,7 +219,10 @@
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
-        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+        // The block adapter runs before the format conversion.
+        // So we need to use the device frame size.
+        mBlockAdapterBytesPerFrame = getBytesPerDeviceFrame();
+        int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
         mFixedBlockWriter.open(callbackSizeBytes);
         mBlockAdapter = &mFixedBlockWriter;
     } else {
@@ -276,16 +287,18 @@
     return AAUDIO_OK;
 }
 
-aaudio_result_t AudioStreamRecord::close()
-{
-    // TODO add close() or release() to AudioRecord API then call it from here
-    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
+aaudio_result_t AudioStreamRecord::release_l() {
+    // TODO add close() or release() to AudioFlinger's AudioRecord API.
+    //  Then call it from here
+    if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
         mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
+        logReleaseBufferState();
         mAudioRecord.clear();
-        setState(AAUDIO_STREAM_STATE_CLOSED);
+        mFixedBlockWriter.close();
+        return AudioStream::release_l();
+    } else {
+        return AAUDIO_OK; // already released
     }
-    mFixedBlockWriter.close();
-    return AudioStream::close();
 }
 
 const void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
@@ -332,13 +345,17 @@
     // Enable callback before starting AudioRecord to avoid shutting
     // down because of a race condition.
     mCallbackEnabled.store(true);
+    aaudio_stream_state_t originalState = getState();
+    // Set before starting the callback so that we are in the correct state
+    // before updateStateMachine() can be called by the callback.
+    setState(AAUDIO_STREAM_STATE_STARTING);
     mFramesWritten.reset32(); // service writes frames
     mTimestampPosition.reset32();
     status_t err = mAudioRecord->start(); // resets position to zero
     if (err != OK) {
+        mCallbackEnabled.store(false);
+        setState(originalState);
         return AAudioConvert_androidToAAudioResult(err);
-    } else {
-        setState(AAUDIO_STREAM_STATE_STARTING);
     }
     return AAUDIO_OK;
 }
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 2f41d34..c5944c7 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -38,7 +38,7 @@
     virtual ~AudioStreamRecord();
 
     aaudio_result_t open(const AudioStreamBuilder & builder) override;
-    aaudio_result_t close() override;
+    aaudio_result_t release_l() override;
 
     aaudio_result_t requestStart() override;
     aaudio_result_t requestStop() override;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 094cdd1..4869480 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -173,14 +173,20 @@
             selectedDeviceId
     );
 
+    // Set it here so it can be logged by the destructor if the open failed.
+    mAudioTrack->setCallerName(kCallerName);
+
     // Did we get a valid track?
     status_t status = mAudioTrack->initCheck();
     if (status != NO_ERROR) {
-        close();
+        releaseCloseFinal();
         ALOGE("open(), initCheck() returned %d", status);
         return AAudioConvert_androidToAAudioResult(status);
     }
 
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
+            + std::to_string(mAudioTrack->getPortId());
+
     doSetVolume();
 
     // Get the actual values from the AudioTrack.
@@ -196,7 +202,10 @@
 
     // We may need to pass the data through a block size adapter to guarantee constant size.
     if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
-        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+        // This may need to change if we add format conversion before
+        // the block size adaptation.
+        mBlockAdapterBytesPerFrame = getBytesPerFrame();
+        int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
         mFixedBlockReader.open(callbackSizeBytes);
         mBlockAdapter = &mFixedBlockReader;
     } else {
@@ -212,6 +221,9 @@
             : (aaudio_session_id_t) mAudioTrack->getSessionId();
     setSessionId(actualSessionId);
 
+    mInitialBufferCapacity = getBufferCapacity();
+    mInitialFramesPerBurst = getFramesPerBurst();
+
     mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
 
     // Update performance mode based on the actual stream flags.
@@ -239,14 +251,19 @@
     return AAUDIO_OK;
 }
 
-aaudio_result_t AudioStreamTrack::close()
-{
-    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
+aaudio_result_t AudioStreamTrack::release_l() {
+    if (getState() != AAUDIO_STREAM_STATE_CLOSING) {
         mAudioTrack->removeAudioDeviceCallback(mDeviceCallback);
-        setState(AAUDIO_STREAM_STATE_CLOSED);
+        logReleaseBufferState();
+        // TODO Investigate why clear() causes a hang in test_various.cpp
+        // if I call close() from a data callback.
+        // But the same thing in AudioRecord is OK!
+        // mAudioTrack.clear();
+        mFixedBlockReader.close();
+        return AudioStream::release_l();
+    } else {
+        return AAUDIO_OK; // already released
     }
-    mFixedBlockReader.close();
-    return AAUDIO_OK;
 }
 
 void AudioStreamTrack::processCallback(int event, void *info) {
@@ -258,7 +275,16 @@
 
             // Stream got rerouted so we disconnect.
         case AudioTrack::EVENT_NEW_IAUDIOTRACK:
-            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+            // request stream disconnect if the restored AudioTrack has properties not matching
+            // what was requested initially
+            if (mAudioTrack->channelCount() != getSamplesPerFrame()
+                    || mAudioTrack->format() != getFormat()
+                    || mAudioTrack->getSampleRate() != getSampleRate()
+                    || mAudioTrack->getRoutedDeviceId() != getDeviceId()
+                    || getBufferCapacity() != mInitialBufferCapacity
+                    || getFramesPerBurst() != mInitialFramesPerBurst) {
+                processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+            }
             break;
 
         default:
@@ -281,11 +307,15 @@
     // Enable callback before starting AudioTrack to avoid shutting
     // down because of a race condition.
     mCallbackEnabled.store(true);
+    aaudio_stream_state_t originalState = getState();
+    // Set before starting the callback so that we are in the correct state
+    // before updateStateMachine() can be called by the callback.
+    setState(AAUDIO_STREAM_STATE_STARTING);
     err = mAudioTrack->start();
     if (err != OK) {
+        mCallbackEnabled.store(false);
+        setState(originalState);
         return AAudioConvert_androidToAAudioResult(err);
-    } else {
-        setState(AAUDIO_STREAM_STATE_STARTING);
     }
     return AAUDIO_OK;
 }
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 68608de..93a1ff4 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -41,7 +41,7 @@
 
 
     aaudio_result_t open(const AudioStreamBuilder & builder) override;
-    aaudio_result_t close() override;
+    aaudio_result_t release_l() override;
 
     aaudio_result_t requestStart() override;
     aaudio_result_t requestPause() override;
@@ -104,6 +104,10 @@
 
     // TODO add 64-bit position reporting to AudioTrack and use it.
     aaudio_wrapping_frames_t         mPositionWhenPausing = 0;
+
+    // initial AudioTrack frame count and notification period
+    int32_t mInitialBufferCapacity = 0;
+    int32_t mInitialFramesPerBurst = 0;
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/libaaudio.map.txt b/media/libaaudio/src/libaaudio.map.txt
new file mode 100644
index 0000000..2e00aa5
--- /dev/null
+++ b/media/libaaudio/src/libaaudio.map.txt
@@ -0,0 +1,64 @@
+LIBAAUDIO {
+  global:
+    AAudio_convertResultToText;
+    AAudio_convertStreamStateToText;
+    AAudio_createStreamBuilder;
+    AAudio_getMMapPolicy;
+    AAudio_setMMapPolicy;
+    AAudioStreamBuilder_setPerformanceMode;
+    AAudioStreamBuilder_setDeviceId;
+    AAudioStreamBuilder_setDataCallback;
+    AAudioStreamBuilder_setErrorCallback;
+    AAudioStreamBuilder_setFramesPerDataCallback;
+    AAudioStreamBuilder_setSampleRate;
+    AAudioStreamBuilder_setSamplesPerFrame;
+    AAudioStreamBuilder_setChannelCount;
+    AAudioStreamBuilder_setFormat;
+    AAudioStreamBuilder_setSharingMode;
+    AAudioStreamBuilder_setDirection;
+    AAudioStreamBuilder_setBufferCapacityInFrames;
+    AAudioStreamBuilder_setUsage;       # introduced=28
+    AAudioStreamBuilder_setContentType; # introduced=28
+    AAudioStreamBuilder_setInputPreset; # introduced=28
+    AAudioStreamBuilder_setAllowedCapturePolicy; # introduced=29
+    AAudioStreamBuilder_setSessionId;   # introduced=28
+    AAudioStreamBuilder_setPrivacySensitive;   # introduced=30
+    AAudioStreamBuilder_openStream;
+    AAudioStreamBuilder_delete;
+    AAudioStream_close;
+    AAudioStream_requestStart;
+    AAudioStream_requestPause;
+    AAudioStream_requestFlush;
+    AAudioStream_requestStop;
+    AAudioStream_getState;
+    AAudioStream_waitForStateChange;
+    AAudioStream_read;
+    AAudioStream_write;
+    AAudioStream_setBufferSizeInFrames;
+    AAudioStream_getBufferSizeInFrames;
+    AAudioStream_getFramesPerDataCallback;
+    AAudioStream_getFramesPerBurst;
+    AAudioStream_getBufferCapacityInFrames;
+    AAudioStream_getXRunCount;
+    AAudioStream_getSampleRate;
+    AAudioStream_getSamplesPerFrame;
+    AAudioStream_getChannelCount;
+    AAudioStream_getPerformanceMode;
+    AAudioStream_getDeviceId;
+    AAudioStream_getFormat;
+    AAudioStream_getSharingMode;
+    AAudioStream_getDirection;
+    AAudioStream_getUsage;       # introduced=28
+    AAudioStream_getContentType; # introduced=28
+    AAudioStream_getInputPreset; # introduced=28
+    AAudioStream_getAllowedCapturePolicy; # introduced=29
+    AAudioStream_getFramesWritten;
+    AAudioStream_getFramesRead;
+    AAudioStream_getSessionId;   # introduced=28
+    AAudioStream_getTimestamp;
+    AAudioStream_isMMapUsed;
+    AAudioStream_isPrivacySensitive;   # introduced=30
+    AAudioStream_release;        # introduced=30
+  local:
+    *;
+};
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 96ed56a..9007b10 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -24,6 +24,7 @@
 #include <utils/Errors.h>
 
 #include "aaudio/AAudio.h"
+#include "core/AudioGlobal.h"
 #include <aaudio/AAudioTesting.h>
 #include <math.h>
 #include <system/audio-base.h>
@@ -182,6 +183,10 @@
     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
     STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
+    STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_EMERGENCY == AUDIO_USAGE_EMERGENCY);
+    STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_SAFETY == AUDIO_USAGE_SAFETY);
+    STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS == AUDIO_USAGE_VEHICLE_STATUS);
+    STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT == AUDIO_USAGE_ANNOUNCEMENT);
     if (usage == AAUDIO_UNSPECIFIED) {
         usage = AAUDIO_USAGE_MEDIA;
     }
@@ -233,6 +238,11 @@
     }
 }
 
+audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
+        bool privacySensitive) {
+    return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE;
+}
+
 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
                                     int32_t bytesPerFrame,
                                     int32_t *sizeInBytes) {
@@ -334,6 +344,34 @@
     return prop;
 }
 
+static int32_t AAudioProperty_getMMapOffsetMicros(const char *functionName,
+        const char *propertyName) {
+    const int32_t minMicros = -20000; // arbitrary
+    const int32_t defaultMicros = 0;  // arbitrary
+    const int32_t maxMicros =  20000; // arbitrary
+    int32_t prop = property_get_int32(propertyName, defaultMicros);
+    if (prop < minMicros) {
+        ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
+        prop = minMicros;
+    } else if (prop > maxMicros) {
+        ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
+        prop = maxMicros;
+    }
+    return prop;
+}
+
+int32_t AAudioProperty_getInputMMapOffsetMicros() {
+    return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC);
+}
+
+int32_t AAudioProperty_getOutputMMapOffsetMicros() {
+    return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC);
+}
+
+int32_t AAudioProperty_getLogMask() {
+    return property_get_int32(AAUDIO_PROP_LOG_MASK, 0);
+}
+
 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
     aaudio_result_t result = AAUDIO_OK;
     switch (state) {
@@ -355,7 +393,7 @@
         case AAUDIO_STREAM_STATE_DISCONNECTED:
         default:
             ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
-                  AAudio_convertStreamStateToText(state));
+                  aaudio::AudioGlobal_convertStreamStateToText(state));
             result =  AAUDIO_ERROR_INVALID_STATE;
             break;
     }
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index 76d0457..d2e4805 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -92,33 +92,31 @@
 audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
         aaudio_allowed_capture_policy_t policy);
 
-// Note that this code may be replaced by Settings or by some other system configuration tool.
+audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
+        bool privacySensitive);
 
-#define AAUDIO_PROP_MMAP_POLICY           "aaudio.mmap_policy"
+// Note that this code may be replaced by Settings or by some other system configuration tool.
 
 /**
  * Read system property.
  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
  */
 int32_t AAudioProperty_getMMapPolicy();
-
-#define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
+#define AAUDIO_PROP_MMAP_POLICY           "aaudio.mmap_policy"
 
 /**
  * Read system property.
  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
  */
 int32_t AAudioProperty_getMMapExclusivePolicy();
-
-#define AAUDIO_PROP_MIXER_BURSTS           "aaudio.mixer_bursts"
+#define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy"
 
 /**
  * Read system property.
  * @return number of bursts per AAudio service mixer cycle
  */
 int32_t AAudioProperty_getMixerBursts();
-
-#define AAUDIO_PROP_HW_BURST_MIN_USEC      "aaudio.hw_burst_min_usec"
+#define AAUDIO_PROP_MIXER_BURSTS           "aaudio.mixer_bursts"
 
 /**
  * Read a system property that specifies the number of extra microseconds that a thread
@@ -130,7 +128,6 @@
  * @return number of microseconds to delay the wakeup.
  */
 int32_t AAudioProperty_getWakeupDelayMicros();
-
 #define AAUDIO_PROP_WAKEUP_DELAY_USEC      "aaudio.wakeup_delay_usec"
 
 /**
@@ -139,7 +136,6 @@
  * @return minimum number of microseconds to sleep.
  */
 int32_t AAudioProperty_getMinimumSleepMicros();
-
 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC      "aaudio.minimum_sleep_usec"
 
 /**
@@ -153,7 +149,35 @@
  * @return minimum number of microseconds for a MMAP HW burst
  */
 int32_t AAudioProperty_getHardwareBurstMinMicros();
+#define AAUDIO_PROP_HW_BURST_MIN_USEC      "aaudio.hw_burst_min_usec"
 
+/**
+ * Read a system property that specifies an offset that will be added to MMAP timestamps.
+ * This can be used to correct bias in the timestamp.
+ * It can also be used to analyze the time distribution of the timestamp
+ * by progressively modifying the offset and listening for glitches.
+ *
+ * @return number of microseconds to offset the time part of an MMAP timestamp
+ */
+int32_t AAudioProperty_getInputMMapOffsetMicros();
+#define AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC    "aaudio.in_mmap_offset_usec"
+
+int32_t AAudioProperty_getOutputMMapOffsetMicros();
+#define AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC   "aaudio.out_mmap_offset_usec"
+
+// These are powers of two that can be combined as a bit mask.
+// AAUDIO_LOG_CLOCK_MODEL_HISTOGRAM must be enabled before the stream is opened.
+#define AAUDIO_LOG_CLOCK_MODEL_HISTOGRAM   1
+#define AAUDIO_LOG_RESERVED_2              2
+#define AAUDIO_LOG_RESERVED_4              4
+#define AAUDIO_LOG_RESERVED_8              8
+
+/**
+ * Use a mask to enable various logs in AAudio.
+ * @return mask that enables various AAudio logs, such as AAUDIO_LOG_CLOCK_MODEL_HISTOGRAM
+ */
+int32_t AAudioProperty_getLogMask();
+#define AAUDIO_PROP_LOG_MASK   "aaudio.log_mask"
 
 /**
  * Is flush allowed for the given state?
diff --git a/media/libaaudio/src/utility/FixedBlockAdapter.cpp b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
index 63495f0..b55f827 100644
--- a/media/libaaudio/src/utility/FixedBlockAdapter.cpp
+++ b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
@@ -18,22 +18,17 @@
 
 #include "FixedBlockAdapter.h"
 
-FixedBlockAdapter::~FixedBlockAdapter() {
-    close();
-}
-
 int32_t FixedBlockAdapter::open(int32_t bytesPerFixedBlock)
 {
     mSize = bytesPerFixedBlock;
-    mStorage = new uint8_t[bytesPerFixedBlock];
+    mStorage = std::make_unique<uint8_t[]>(bytesPerFixedBlock);
     mPosition = 0;
     return 0;
 }
 
 int32_t FixedBlockAdapter::close()
 {
-    delete[] mStorage;
-    mStorage = nullptr;
+    mStorage.reset();
     mSize = 0;
     mPosition = 0;
     return 0;
diff --git a/media/libaaudio/src/utility/FixedBlockAdapter.h b/media/libaaudio/src/utility/FixedBlockAdapter.h
index 7008b25..4dc7e68 100644
--- a/media/libaaudio/src/utility/FixedBlockAdapter.h
+++ b/media/libaaudio/src/utility/FixedBlockAdapter.h
@@ -17,6 +17,7 @@
 #ifndef AAUDIO_FIXED_BLOCK_ADAPTER_H
 #define AAUDIO_FIXED_BLOCK_ADAPTER_H
 
+#include <memory>
 #include <stdio.h>
 
 /**
@@ -37,7 +38,7 @@
     FixedBlockAdapter(FixedBlockProcessor &fixedBlockProcessor)
     : mFixedBlockProcessor(fixedBlockProcessor) {}
 
-    virtual ~FixedBlockAdapter();
+    virtual ~FixedBlockAdapter() = default;
 
     /**
      * Allocate internal resources needed for buffering data.
@@ -63,7 +64,7 @@
 
 protected:
     FixedBlockProcessor  &mFixedBlockProcessor;
-    uint8_t              *mStorage = nullptr;    // Store data here while assembling buffers.
+    std::unique_ptr<uint8_t[]> mStorage;         // Store data here while assembling buffers.
     int32_t               mSize = 0;             // Size in bytes of the fixed size buffer.
     int32_t               mPosition = 0;         // Offset of the last byte read or written.
 };
diff --git a/media/libaaudio/src/utility/FixedBlockReader.cpp b/media/libaaudio/src/utility/FixedBlockReader.cpp
index 21ea70e..7931fa0 100644
--- a/media/libaaudio/src/utility/FixedBlockReader.cpp
+++ b/media/libaaudio/src/utility/FixedBlockReader.cpp
@@ -39,7 +39,7 @@
     if (bytesToRead > dataAvailable) {
         bytesToRead = dataAvailable;
     }
-    memcpy(buffer, mStorage + mPosition, bytesToRead);
+    memcpy(buffer, &mStorage[mPosition], bytesToRead);
     mPosition += bytesToRead;
     return bytesToRead;
 }
@@ -60,7 +60,7 @@
             bytesLeft -= mSize;
         } else {
             // Just need a partial block so we have to use storage.
-            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage, mSize);
+            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize);
             mPosition = 0;
         }
     }
diff --git a/media/libaaudio/src/utility/FixedBlockWriter.cpp b/media/libaaudio/src/utility/FixedBlockWriter.cpp
index 2ce8046..afb83c1 100644
--- a/media/libaaudio/src/utility/FixedBlockWriter.cpp
+++ b/media/libaaudio/src/utility/FixedBlockWriter.cpp
@@ -30,7 +30,7 @@
     if (bytesToStore > roomAvailable) {
         bytesToStore = roomAvailable;
     }
-    memcpy(mStorage + mPosition, buffer, bytesToStore);
+    memcpy(&mStorage[mPosition], buffer, bytesToStore);
     mPosition += bytesToStore;
     return bytesToStore;
 }
@@ -46,7 +46,7 @@
         bytesLeft -= bytesWritten;
         // If storage full then flush it out
         if (mPosition == mSize) {
-            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage, mSize);
+            result = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize);
             mPosition = 0;
         }
     }
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 6101e99..8935d57 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -11,7 +11,7 @@
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_marshalling.cpp"],
     shared_libs: [
-        "libaaudio",
+        "libaaudio_internal",
         "libbinder",
         "libcutils",
         "libutils",
@@ -23,7 +23,7 @@
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_clock_model.cpp"],
     shared_libs: [
-        "libaaudio",
+        "libaaudio_internal",
         "libaudioutils",
         "libcutils",
         "libutils",
@@ -34,7 +34,7 @@
     name: "test_block_adapter",
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_block_adapter.cpp"],
-    shared_libs: ["libaaudio"],
+    shared_libs: ["libaaudio_internal"],
 }
 
 cc_test {
@@ -170,7 +170,7 @@
     name: "test_atomic_fifo",
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_atomic_fifo.cpp"],
-    shared_libs: ["libaaudio"],
+    shared_libs: ["libaaudio_internal"],
 }
 
 cc_test {
@@ -178,7 +178,7 @@
     defaults: ["libaaudio_tests_defaults"],
     srcs: ["test_flowgraph.cpp"],
     shared_libs: [
-        "libaaudio",
+        "libaaudio_internal",
         "libbinder",
         "libcutils",
         "libutils",
@@ -215,3 +215,27 @@
     srcs: ["test_full_queue.cpp"],
     shared_libs: ["libaaudio"],
 }
+
+cc_test {
+    name: "test_histogram",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_histogram.cpp"],
+    shared_libs: [
+        "libaudioutils",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
+    name: "test_steal_exclusive",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_steal_exclusive.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "liblog",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index 32ee2a3..d540866 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -33,6 +33,7 @@
                             aaudio_content_type_t contentType,
                             aaudio_input_preset_t preset = DONT_SET,
                             aaudio_allowed_capture_policy_t capturePolicy = DONT_SET,
+                            int privacyMode = DONT_SET,
                             aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
 
     float *buffer = new float[kNumFrames * kChannelCount];
@@ -60,6 +61,9 @@
     if (capturePolicy != DONT_SET) {
         AAudioStreamBuilder_setAllowedCapturePolicy(aaudioBuilder, capturePolicy);
     }
+    if (privacyMode != DONT_SET) {
+        AAudioStreamBuilder_setPrivacySensitive(aaudioBuilder, (bool)privacyMode);
+    }
 
     // Create an AAudioStream using the Builder.
     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
@@ -90,6 +94,13 @@
             : preset;
     EXPECT_EQ(expectedCapturePolicy, AAudioStream_getAllowedCapturePolicy(aaudioStream));
 
+    bool expectedPrivacyMode =
+            (privacyMode == DONT_SET) ?
+                ((preset == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION
+                    || preset == AAUDIO_INPUT_PRESET_CAMCORDER) ? true : false) :
+                privacyMode;
+    EXPECT_EQ(expectedPrivacyMode, AAudioStream_isPrivacySensitive(aaudioStream));
+
     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
 
     if (direction == AAUDIO_DIRECTION_INPUT) {
@@ -120,7 +131,11 @@
     AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
     AAUDIO_USAGE_ASSISTANCE_SONIFICATION,
     AAUDIO_USAGE_GAME,
-    AAUDIO_USAGE_ASSISTANT
+    AAUDIO_USAGE_ASSISTANT,
+    AAUDIO_SYSTEM_USAGE_EMERGENCY,
+    AAUDIO_SYSTEM_USAGE_SAFETY,
+    AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS,
+    AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT
 };
 
 static const aaudio_content_type_t sContentypes[] = {
@@ -151,6 +166,12 @@
     AAUDIO_ALLOW_CAPTURE_BY_NONE,
 };
 
+static const int sPrivacyModes[] = {
+    DONT_SET,
+    false,
+    true,
+};
+
 static void checkAttributesUsage(aaudio_performance_mode_t perfMode) {
     for (aaudio_usage_t usage : sUsages) {
         checkAttributes(perfMode, usage, DONT_SET);
@@ -170,6 +191,7 @@
                         DONT_SET,
                         inputPreset,
                         DONT_SET,
+                        DONT_SET,
                         AAUDIO_DIRECTION_INPUT);
     }
 }
@@ -185,6 +207,18 @@
     }
 }
 
+static void checkAttributesPrivacySensitive(aaudio_performance_mode_t perfMode) {
+    for (int privacyMode : sPrivacyModes) {
+        checkAttributes(perfMode,
+                        DONT_SET,
+                        DONT_SET,
+                        DONT_SET,
+                        DONT_SET,
+                        privacyMode,
+                        AAUDIO_DIRECTION_INPUT);
+    }
+}
+
 TEST(test_attributes, aaudio_usage_perfnone) {
     checkAttributesUsage(AAUDIO_PERFORMANCE_MODE_NONE);
 }
@@ -216,3 +250,7 @@
 TEST(test_attributes, aaudio_allowed_capture_policy_lowlat) {
     checkAttributesAllowedCapturePolicy(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
 }
+
+TEST(test_attributes, aaudio_allowed_privacy_sensitive_lowlat) {
+    checkAttributesPrivacySensitive(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
diff --git a/media/libaaudio/tests/test_histogram.cpp b/media/libaaudio/tests/test_histogram.cpp
new file mode 100644
index 0000000..431373d
--- /dev/null
+++ b/media/libaaudio/tests/test_histogram.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 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.
+ */
+
+/*
+ * Test Histogram
+ */
+
+#include <iostream>
+
+#include <gtest/gtest.h>
+
+#include <audio_utils/Histogram.h>
+
+using namespace android::audio_utils;
+
+static constexpr int32_t kBinWidth = 10;
+static constexpr int32_t kNumBins = 20;
+
+TEST(test_histogram, module_sinki16) {
+    Histogram histogram(kNumBins, kBinWidth);
+    ASSERT_EQ(kNumBins, histogram.getNumBinsInRange());
+
+    // Is it clear initially?
+    for (int i = 0; i < kNumBins; i++) {
+        ASSERT_EQ(0, histogram.getCount(i));
+    }
+    ASSERT_EQ(0, histogram.getCountBelowRange());
+    ASSERT_EQ(0, histogram.getCountAboveRange());
+    ASSERT_EQ(0, histogram.getCount());
+
+    // Add some items.
+    histogram.add(27);
+    histogram.add(53);
+    histogram.add(171);
+    histogram.add(23);
+
+    // Did they count correctly.
+    ASSERT_EQ(2, histogram.getCount(2));          // For items 27 and 23
+    ASSERT_EQ(3, histogram.getLastItemNumber(2)); // Item 23 was the 0,1,2,3th item added.
+    ASSERT_EQ(1, histogram.getCount(5));          // For item 53
+    ASSERT_EQ(1, histogram.getLastItemNumber(5)); // item 53 was the second item added.
+    ASSERT_EQ(1, histogram.getCount(17));         // For item 171
+    ASSERT_EQ(4, histogram.getCount());           // A total of four items were added.
+
+    // Add values out of range.
+    histogram.add(-5);
+    ASSERT_EQ(1, histogram.getCountBelowRange()); // -5 is below zero.
+    ASSERT_EQ(0, histogram.getCountAboveRange());
+    ASSERT_EQ(5, histogram.getCount());
+
+    histogram.add(200);
+    ASSERT_EQ(1, histogram.getCountBelowRange());
+    ASSERT_EQ(1, histogram.getCountAboveRange()); // 200 is above top bin
+    ASSERT_EQ(6, histogram.getCount());
+
+    // Try to read values out of range. Should not crash.
+    // Legal index range is 0 to numBins-1
+    histogram.add(-1);
+    histogram.add(kNumBins);
+    ASSERT_EQ(0, histogram.getCount(-1)); // edge
+    ASSERT_EQ(0, histogram.getCount(kNumBins)); // edge
+    ASSERT_EQ(0, histogram.getCount(-1234)); // extreme
+    ASSERT_EQ(0, histogram.getCount(98765)); // extreme
+    ASSERT_EQ(0, histogram.getLastItemNumber(-1));
+    ASSERT_EQ(0, histogram.getLastItemNumber(kNumBins));
+
+    // Clear all the counts.
+    histogram.clear();
+    // Is it clear?
+    for (int i = 0; i < kNumBins; i++) {
+        ASSERT_EQ(0, histogram.getCount(i));
+    }
+    ASSERT_EQ(0, histogram.getCountBelowRange());
+    ASSERT_EQ(0, histogram.getCountAboveRange());
+    ASSERT_EQ(0, histogram.getCount());
+}
diff --git a/media/libaaudio/tests/test_steal_exclusive.cpp b/media/libaaudio/tests/test_steal_exclusive.cpp
new file mode 100644
index 0000000..05c560d
--- /dev/null
+++ b/media/libaaudio/tests/test_steal_exclusive.cpp
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This test starts an exclusive stream.
+ * Then a few seconds later it starts a second exclusive stream.
+ * The first stream should get stolen and they should both end up
+ * as SHARED streams.
+ * The test will print PASS or FAIL.
+ *
+ * If you plug in a headset during the test then you can get them to both
+ * open at almost the same time. This can result in a race condition.
+ * Both streams may try to automatically reopen their streams in EXCLUSIVE mode.
+ * The first stream will have its EXCLUSIVE stream stolen by the second stream.
+ * It will usually get disconnected between its Open and Start calls.
+ * This can also occur in normal use. But is unlikely because the window is very narrow.
+ * In this case, where two streams are responding to the same disconnect event,
+ * it will usually happen.
+ *
+ * Because the stream has not started, this condition will not trigger an onError callback.
+ * But the stream will get an error returned from AAudioStream_requestStart().
+ * The test uses this result to trigger a retry in the onError callback.
+ * That is the best practice for any app restarting a stream.
+ *
+ * You should see that both streams are advancing after the disconnect.
+ *
+ * The headset can connect using a 3.5 mm jack, or USB-C or Bluetooth.
+ *
+ * This test can be used with INPUT by using the -i command line option.
+ * Before running the test you will need to enter "adb root" so that
+ * you can have permission to record.
+ * Also the headset needs to have a microphone.
+ * Then the test should behave essentially the same.
+ */
+
+#include <atomic>
+#include <mutex>
+#include <stdio.h>
+#include <thread>
+#include <unistd.h>
+
+#include <android/log.h>
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+#define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
+#define SOLO_DURATION_MSEC    2000
+#define DUET_DURATION_MSEC    8000
+#define SLEEP_DURATION_MSEC    500
+
+#define MODULE_NAME  "stealAudio"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__)
+
+static const char * s_sharingModeToText(aaudio_sharing_mode_t mode) {
+    return (mode == AAUDIO_SHARING_MODE_EXCLUSIVE) ? "EXCLUSIVE"
+        : ((mode == AAUDIO_SHARING_MODE_SHARED)  ? "SHARED"
+            : AAudio_convertResultToText(mode));
+}
+
+static const char * s_performanceModeToText(aaudio_performance_mode_t mode) {
+    return (mode == AAUDIO_PERFORMANCE_MODE_LOW_LATENCY) ? "LOWLAT"
+        : ((mode == AAUDIO_PERFORMANCE_MODE_NONE)  ? "NONE"
+            : AAudio_convertResultToText(mode));
+}
+
+static aaudio_data_callback_result_t s_myDataCallbackProc(
+        AAudioStream * /* stream */,
+        void *userData,
+        void *audioData,
+        int32_t numFrames);
+
+static void s_myErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error);
+
+class AudioEngine {
+public:
+
+    AudioEngine(const char *name) {
+        mName = name;
+    }
+
+    // These counters are read and written by the callback and the main thread.
+    std::atomic<int32_t> framesCalled{};
+    std::atomic<int32_t> callbackCount{};
+    std::atomic<aaudio_sharing_mode_t> sharingMode{};
+    std::atomic<aaudio_performance_mode_t> performanceMode{};
+    std::atomic<bool> isMMap{false};
+
+    void setMaxRetries(int maxRetries) {
+        mMaxRetries = maxRetries;
+    }
+
+    void setOpenDelayMillis(int openDelayMillis) {
+        mOpenDelayMillis = openDelayMillis;
+    }
+
+    void restartStream() {
+        int retriesLeft = mMaxRetries;
+        aaudio_result_t result;
+        do {
+            closeAudioStream();
+            if (mOpenDelayMillis) usleep(mOpenDelayMillis * 1000);
+            openAudioStream(mDirection, mRequestedSharingMode);
+            // It is possible for the stream to be disconnected, or stolen between the time
+            // it is opened and when it is started. If that happens then try again.
+            // If it was stolen then it should succeed the second time because there will already be
+            // a SHARED stream, which will not get stolen.
+            result = AAudioStream_requestStart(mStream);
+            printf("%s: AAudioStream_requestStart() returns %s\n",
+                    mName.c_str(),
+                    AAudio_convertResultToText(result));
+        } while (retriesLeft-- > 0 && result != AAUDIO_OK);
+    }
+
+    aaudio_data_callback_result_t onAudioReady(
+            void * /*audioData */,
+            int32_t numFrames) {
+        callbackCount++;
+        framesCalled += numFrames;
+        return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    }
+
+    aaudio_result_t openAudioStream(aaudio_direction_t direction,
+            aaudio_sharing_mode_t requestedSharingMode) {
+        std::lock_guard<std::mutex> lock(mLock);
+
+        AAudioStreamBuilder *builder = nullptr;
+        mDirection = direction;
+        mRequestedSharingMode = requestedSharingMode;
+
+        // Use an AAudioStreamBuilder to contain requested parameters.
+        aaudio_result_t result = AAudio_createStreamBuilder(&builder);
+        if (result != AAUDIO_OK) {
+            printf("AAudio_createStreamBuilder returned %s",
+                   AAudio_convertResultToText(result));
+            return result;
+        }
+
+        // Request stream properties.
+        AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
+        AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+        AAudioStreamBuilder_setSharingMode(builder, mRequestedSharingMode);
+        AAudioStreamBuilder_setDirection(builder, direction);
+        AAudioStreamBuilder_setDataCallback(builder, s_myDataCallbackProc, this);
+        AAudioStreamBuilder_setErrorCallback(builder, s_myErrorCallbackProc, this);
+
+        // Create an AAudioStream using the Builder.
+        result = AAudioStreamBuilder_openStream(builder, &mStream);
+        AAudioStreamBuilder_delete(builder);
+        builder = nullptr;
+        if (result != AAUDIO_OK) {
+            printf("AAudioStreamBuilder_openStream returned %s",
+                   AAudio_convertResultToText(result));
+        }
+
+        // See what kind of stream we actually opened.
+        int32_t deviceId = AAudioStream_getDeviceId(mStream);
+        sharingMode = AAudioStream_getSharingMode(mStream);
+        performanceMode = AAudioStream_getPerformanceMode(mStream);
+        isMMap = AAudioStream_isMMapUsed(mStream);
+        printf("%s: opened: deviceId = %3d, sharingMode = %s, perf = %s, %s --------\n",
+               mName.c_str(),
+               deviceId,
+               s_sharingModeToText(sharingMode),
+               s_performanceModeToText(performanceMode),
+               (isMMap ? "MMAP" : "Legacy")
+               );
+
+        return result;
+    }
+
+    aaudio_result_t closeAudioStream() {
+        std::lock_guard<std::mutex> lock(mLock);
+        aaudio_result_t result = AAUDIO_OK;
+        if (mStream != nullptr) {
+            result = AAudioStream_close(mStream);
+            if (result != AAUDIO_OK) {
+                printf("AAudioStream_close returned %s\n",
+                       AAudio_convertResultToText(result));
+            }
+            mStream = nullptr;
+        }
+        return result;
+    }
+
+    /**
+     * @return 0 is OK, -1 for error
+     */
+    int checkEnginePositions() {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStream == nullptr) return 0;
+
+        const int64_t framesRead = AAudioStream_getFramesRead(mStream);
+        const int64_t framesWritten = AAudioStream_getFramesWritten(mStream);
+        const int32_t delta = (int32_t)(framesWritten - framesRead);
+        printf("%s: playing framesRead = %7d, framesWritten = %7d"
+               ", delta = %4d, framesCalled = %6d, callbackCount = %4d\n",
+               mName.c_str(),
+               (int32_t) framesRead,
+               (int32_t) framesWritten,
+               delta,
+               framesCalled.load(),
+               callbackCount.load()
+        );
+        if (delta > AAudioStream_getBufferCapacityInFrames(mStream)) {
+            printf("ERROR - delta > capacity\n");
+            return -1;
+        }
+        return 0;
+    }
+
+    aaudio_result_t start() {
+        std::lock_guard<std::mutex> lock(mLock);
+        reset();
+        if (mStream == nullptr) return 0;
+        return AAudioStream_requestStart(mStream);
+    }
+
+    aaudio_result_t stop() {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStream == nullptr) return 0;
+        return AAudioStream_requestStop(mStream);
+    }
+
+    bool hasAdvanced() {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStream == nullptr) return 0;
+        if (mDirection == AAUDIO_DIRECTION_OUTPUT) {
+            return AAudioStream_getFramesRead(mStream) > 0;
+        } else {
+            return AAudioStream_getFramesWritten(mStream) > 0;
+        }
+    }
+
+    aaudio_result_t verify() {
+        int errorCount = 0;
+        if (hasAdvanced()) {
+            printf("%s: stream is running => PASS\n", mName.c_str());
+        } else {
+            errorCount++;
+            printf("%s: stream should be running => FAIL!!\n", mName.c_str());
+        }
+
+        if (isMMap) {
+            printf("%s: data path is MMAP => PASS\n", mName.c_str());
+        } else {
+            errorCount++;
+            printf("%s: data path is Legacy! => FAIL\n", mName.c_str());
+        }
+
+        // Check for PASS/FAIL
+        if (sharingMode == AAUDIO_SHARING_MODE_SHARED) {
+            printf("%s: mode is SHARED => PASS\n", mName.c_str());
+        } else {
+            errorCount++;
+            printf("%s: modes is EXCLUSIVE => FAIL!!\n", mName.c_str());
+        }
+        return errorCount ? AAUDIO_ERROR_INVALID_FORMAT : AAUDIO_OK;
+    }
+
+private:
+    void reset() {
+        framesCalled.store(0);
+        callbackCount.store(0);
+    }
+
+    AAudioStream       *mStream = nullptr;
+    aaudio_direction_t  mDirection = AAUDIO_DIRECTION_OUTPUT;
+    aaudio_sharing_mode_t mRequestedSharingMode = AAUDIO_UNSPECIFIED;
+    std::mutex          mLock;
+    std::string         mName;
+    int                 mMaxRetries = 1;
+    int                 mOpenDelayMillis = 0;
+};
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t s_myDataCallbackProc(
+        AAudioStream * /* stream */,
+        void *userData,
+        void *audioData,
+        int32_t numFrames
+) {
+    AudioEngine *engine = (AudioEngine *)userData;
+    return engine->onAudioReady(audioData, numFrames);
+}
+
+static void s_myRestartStreamProc(void *userData) {
+    LOGI("%s() called", __func__);
+    printf("%s() - restart in separate thread\n", __func__);
+    AudioEngine *engine = (AudioEngine *) userData;
+    engine->restartStream();
+}
+
+static void s_myErrorCallbackProc(
+        AAudioStream * /* stream */,
+        void *userData,
+        aaudio_result_t error) {
+    LOGI("%s() called", __func__);
+    printf("%s() - error = %s\n", __func__, AAudio_convertResultToText(error));
+    // Handle error on a separate thread.
+    std::thread t(s_myRestartStreamProc, userData);
+    t.detach();
+}
+
+static void s_usage() {
+    printf("test_steal_exclusive [-i] [-r{maxRetries}] [-d{delay}] -s\n");
+    printf("     -i direction INPUT, otherwise OUTPUT\n");
+    printf("     -d delay open by milliseconds, default = 0\n");
+    printf("     -r max retries in the error callback, default = 1\n");
+    printf("     -s try to open in SHARED mode\n");
+}
+
+int main(int argc, char ** argv) {
+    AudioEngine victim("victim");
+    AudioEngine thief("thief");
+    aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT;
+    aaudio_result_t result = AAUDIO_OK;
+    int errorCount = 0;
+    int maxRetries = 1;
+    int openDelayMillis = 0;
+    aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("Test interaction between streams V1.1\n");
+    printf("\n");
+
+    for (int i = 1; i < argc; i++) {
+        const char *arg = argv[i];
+        if (arg[0] == '-') {
+            char option = arg[1];
+            switch (option) {
+                case 'd':
+                    openDelayMillis = atoi(&arg[2]);
+                    break;
+                case 'i':
+                    direction = AAUDIO_DIRECTION_INPUT;
+                    break;
+                case 'r':
+                    maxRetries = atoi(&arg[2]);
+                    break;
+                case 's':
+                    requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
+                    break;
+                default:
+                    s_usage();
+                    exit(EXIT_FAILURE);
+                    break;
+            }
+        } else {
+            s_usage();
+            exit(EXIT_FAILURE);
+            break;
+        }
+    }
+
+    victim.setOpenDelayMillis(openDelayMillis);
+    thief.setOpenDelayMillis(openDelayMillis);
+    victim.setMaxRetries(maxRetries);
+    thief.setMaxRetries(maxRetries);
+
+    result = victim.openAudioStream(direction, requestedSharingMode);
+    if (result != AAUDIO_OK) {
+        printf("s_OpenAudioStream victim returned %s\n",
+               AAudio_convertResultToText(result));
+        errorCount++;
+    }
+
+    if (victim.sharingMode == requestedSharingMode) {
+        printf("Victim modes is %s => OK\n", s_sharingModeToText(requestedSharingMode));
+    } else {
+        printf("Victim modes should be %s => test not valid!\n",
+                s_sharingModeToText(requestedSharingMode));
+        goto onerror;
+    }
+
+    if (victim.isMMap) {
+        printf("Victim data path is MMAP => OK\n");
+    } else {
+        printf("Victim data path is Legacy! => test not valid\n");
+        goto onerror;
+    }
+
+    // Start stream.
+    result = victim.start();
+    printf("AAudioStream_requestStart(VICTIM) returned %d >>>>>>>>>>>>>>>>>>>>>>\n", result);
+    if (result != AAUDIO_OK) {
+        errorCount++;
+    }
+
+    if (result == AAUDIO_OK) {
+        const int watchLoops = SOLO_DURATION_MSEC / SLEEP_DURATION_MSEC;
+        for (int i = watchLoops; i > 0; i--) {
+            errorCount += victim.checkEnginePositions() ? 1 : 0;
+            usleep(SLEEP_DURATION_MSEC * 1000);
+        }
+    }
+
+    printf("Trying to start the THIEF stream, which may steal the VICTIM MMAP resource -----\n");
+    result = thief.openAudioStream(direction, requestedSharingMode);
+    if (result != AAUDIO_OK) {
+        printf("s_OpenAudioStream victim returned %s\n",
+               AAudio_convertResultToText(result));
+        errorCount++;
+    }
+
+    // Start stream.
+    result = thief.start();
+    printf("AAudioStream_requestStart(THIEF) returned %d >>>>>>>>>>>>>>>>>>>>>>\n", result);
+    if (result != AAUDIO_OK) {
+        errorCount++;
+    }
+
+    // Give stream time to advance.
+    usleep(SLEEP_DURATION_MSEC * 1000);
+
+    if (victim.verify()) {
+        errorCount++;
+        goto onerror;
+    }
+    if (thief.verify()) {
+        errorCount++;
+        goto onerror;
+    }
+
+    LOGI("Both streams running. Ask user to plug in headset. ====");
+    printf("\n====\nPlease PLUG IN A HEADSET now!\n====\n\n");
+
+    if (result == AAUDIO_OK) {
+        const int watchLoops = DUET_DURATION_MSEC / SLEEP_DURATION_MSEC;
+        for (int i = watchLoops; i > 0; i--) {
+            errorCount += victim.checkEnginePositions() ? 1 : 0;
+            errorCount += thief.checkEnginePositions() ? 1 : 0;
+            usleep(SLEEP_DURATION_MSEC * 1000);
+        }
+    }
+
+    errorCount += victim.verify() ? 1 : 0;
+    errorCount += thief.verify() ? 1 : 0;
+
+    result = victim.stop();
+    printf("AAudioStream_requestStop() returned %d <<<<<<<<<<<<<<<<<<<<<\n", result);
+    if (result != AAUDIO_OK) {
+        printf("stop result = %d = %s\n", result, AAudio_convertResultToText(result));
+        errorCount++;
+    }
+    result = thief.stop();
+    printf("AAudioStream_requestStop() returned %d <<<<<<<<<<<<<<<<<<<<<\n", result);
+    if (result != AAUDIO_OK) {
+        printf("stop result = %d = %s\n", result, AAudio_convertResultToText(result));
+        errorCount++;
+    }
+
+onerror:
+    victim.closeAudioStream();
+    thief.closeAudioStream();
+
+    printf("aaudio result = %d = %s\n", result, AAudio_convertResultToText(result));
+    printf("test %s\n", errorCount ? "FAILED" : "PASSED");
+
+    return errorCount ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index 4b065c9..a20c799 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -28,24 +28,103 @@
 
 // Callback function that does nothing.
 aaudio_data_callback_result_t NoopDataCallbackProc(
-        AAudioStream *stream,
-        void *userData,
+        AAudioStream * stream,
+        void * /* userData */,
         void *audioData,
         int32_t numFrames
 ) {
-    (void) stream;
-    (void) userData;
-    (void) audioData;
-    (void) numFrames;
+    int channels = AAudioStream_getChannelCount(stream);
+    int numSamples = channels * numFrames;
+    bool allZeros = true;
+    float * const floatData = reinterpret_cast<float *>(audioData);
+    for (int i = 0; i < numSamples; i++) {
+        allZeros &= (floatData[i] == 0.0f);
+        floatData[i] = 0.0f;
+    }
+    EXPECT_TRUE(allZeros);
     return AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
-// Test AAudioStream_setBufferSizeInFrames()
-
 constexpr int64_t NANOS_PER_MILLISECOND = 1000 * 1000;
 
+void checkReleaseThenClose(aaudio_performance_mode_t perfMode,
+        aaudio_sharing_mode_t sharingMode) {
+    AAudioStreamBuilder* aaudioBuilder = nullptr;
+    AAudioStream* aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+    // Request stream properties.
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder,
+                                        NoopDataCallbackProc,
+                                        nullptr);
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+    AAudioStreamBuilder_setSharingMode(aaudioBuilder, sharingMode);
+    AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
+
+    // Create an AAudioStream using the Builder.
+    ASSERT_EQ(AAUDIO_OK,
+              AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    AAudioStreamBuilder_delete(aaudioBuilder);
+
+    ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+    sleep(1);
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
+
+    // We should be able to call this again without crashing.
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
+
+    // We expect these not to crash.
+    AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
+    AAudioStream_setBufferSizeInFrames(aaudioStream, 99999999);
+
+    // We should NOT be able to start or change a stream after it has been released.
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStart(aaudioStream));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestPause(aaudioStream));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, AAudioStream_requestStop(aaudioStream));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(aaudioStream));
+
+    // Does this crash?
+    EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream));
+    EXPECT_LT(0, AAudioStream_getFramesWritten(aaudioStream));
+
+    // Verify Closing State. Does this crash?
+    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
+                                                         AAUDIO_STREAM_STATE_UNKNOWN, &state,
+                                                         500 * NANOS_PER_MILLISECOND));
+    EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+TEST(test_various, aaudio_release_close_none) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_NONE,
+            AAUDIO_SHARING_MODE_SHARED);
+    // No EXCLUSIVE streams with MODE_NONE.
+}
+
+TEST(test_various, aaudio_release_close_low_shared) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+            AAUDIO_SHARING_MODE_SHARED);
+}
+
+TEST(test_various, aaudio_release_close_low_exclusive) {
+    checkReleaseThenClose(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+            AAUDIO_SHARING_MODE_EXCLUSIVE);
+}
+
 enum FunctionToCall {
-    CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH
+    CALL_START, CALL_STOP, CALL_PAUSE, CALL_FLUSH, CALL_RELEASE
 };
 
 void checkStateTransition(aaudio_performance_mode_t perfMode,
@@ -62,6 +141,7 @@
     // Request stream properties.
     AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+    AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
 
     // Create an AAudioStream using the Builder.
     ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
@@ -97,11 +177,27 @@
             } else if (originalState == AAUDIO_STREAM_STATE_PAUSED) {
                 ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
                 inputState = AAUDIO_STREAM_STATE_PAUSING;
+            } else if (originalState == AAUDIO_STREAM_STATE_FLUSHING) {
+                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(aaudioStream));
+                // We can only flush() after pause is complete.
+                ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
+                                                                 AAUDIO_STREAM_STATE_PAUSING,
+                                                                 &state,
+                                                                 1000 * NANOS_PER_MILLISECOND));
+                ASSERT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
+                ASSERT_EQ(AAUDIO_OK, AAudioStream_requestFlush(aaudioStream));
+                // That will put the stream into the FLUSHING state.
+                // The FLUSHING state will persist until we process functionToCall.
+                // That is because the transition to FLUSHED is caused by the callback,
+                // or by calling write() or waitForStateChange(). But those will not
+                // occur.
+            } else if (originalState == AAUDIO_STREAM_STATE_CLOSING) {
+                ASSERT_EQ(AAUDIO_OK, AAudioStream_release(aaudioStream));
             }
         }
     }
 
-    // Wait until past transitional state.
+    // Wait until we get past the transitional state if requested.
     if (inputState != AAUDIO_STREAM_STATE_UNINITIALIZED) {
         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
                                                              inputState,
@@ -128,12 +224,20 @@
             EXPECT_EQ(expectedResult, AAudioStream_requestFlush(aaudioStream));
             transitionalState = AAUDIO_STREAM_STATE_FLUSHING;
             break;
+        case FunctionToCall::CALL_RELEASE:
+            EXPECT_EQ(expectedResult, AAudioStream_release(aaudioStream));
+            // Set to UNINITIALIZED so the waitForStateChange() below will
+            // will return immediately with the current state.
+            transitionalState = AAUDIO_STREAM_STATE_UNINITIALIZED;
+            break;
     }
 
-    EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(aaudioStream,
-                                                         transitionalState,
-                                                         &state,
-                                                         1000 * NANOS_PER_MILLISECOND));
+    EXPECT_EQ(AAUDIO_OK,
+            AAudioStream_waitForStateChange(aaudioStream,
+                    transitionalState,
+                    &state,
+                    1000 * NANOS_PER_MILLISECOND));
+
     // We should not change state when a function fails.
     if (expectedResult != AAUDIO_OK) {
         ASSERT_EQ(originalState, expectedState);
@@ -413,6 +517,88 @@
         AAUDIO_STREAM_STATE_FLUSHED);
 }
 
+// FLUSHING ================================================================
+TEST(test_various, aaudio_state_lowlat_flushing_start) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+        AAUDIO_STREAM_STATE_FLUSHING,
+        FunctionToCall::CALL_START,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_STARTED);
+}
+
+TEST(test_various, aaudio_state_none_flushing_start) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
+        AAUDIO_STREAM_STATE_FLUSHING,
+        FunctionToCall::CALL_START,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_STARTED);
+}
+
+TEST(test_various, aaudio_state_lowlat_flushing_release) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+        AAUDIO_STREAM_STATE_FLUSHING,
+        FunctionToCall::CALL_RELEASE,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_none_flushing_release) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
+        AAUDIO_STREAM_STATE_FLUSHING,
+        FunctionToCall::CALL_RELEASE,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_lowlat_starting_release) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+        AAUDIO_STREAM_STATE_STARTING,
+        FunctionToCall::CALL_RELEASE,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_none_starting_release) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
+        AAUDIO_STREAM_STATE_STARTING,
+        FunctionToCall::CALL_RELEASE,
+        AAUDIO_OK,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+// CLOSING ================================================================
+TEST(test_various, aaudio_state_lowlat_closing_start) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+        AAUDIO_STREAM_STATE_CLOSING,
+        FunctionToCall::CALL_START,
+        AAUDIO_ERROR_INVALID_STATE,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_none_closing_start) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
+        AAUDIO_STREAM_STATE_CLOSING,
+        FunctionToCall::CALL_START,
+        AAUDIO_ERROR_INVALID_STATE,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_lowlat_closing_stop) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+        AAUDIO_STREAM_STATE_CLOSING,
+        FunctionToCall::CALL_STOP,
+        AAUDIO_ERROR_INVALID_STATE,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
+TEST(test_various, aaudio_state_none_closing_stop) {
+checkStateTransition(AAUDIO_PERFORMANCE_MODE_NONE,
+        AAUDIO_STREAM_STATE_CLOSING,
+        FunctionToCall::CALL_STOP,
+        AAUDIO_ERROR_INVALID_STATE,
+        AAUDIO_STREAM_STATE_CLOSING);
+}
+
 // ==========================================================================
 TEST(test_various, aaudio_set_buffer_size) {
 
@@ -441,7 +627,7 @@
            bufferCapacity, bufferCapacity % framesPerBurst);
 
     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 0);
-    EXPECT_GT(actualSize, 0);
+    EXPECT_GE(actualSize, 0); // 0 is legal in R
     EXPECT_LE(actualSize, bufferCapacity);
 
     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, 2 * framesPerBurst);
@@ -469,7 +655,7 @@
     EXPECT_LE(actualSize, bufferCapacity);
 
     actualSize = AAudioStream_setBufferSizeInFrames(aaudioStream, INT32_MIN);
-    EXPECT_GT(actualSize, 0);
+    EXPECT_GE(actualSize, 0); // 0 is legal in R
     EXPECT_LE(actualSize, bufferCapacity);
 
     AAudioStream_close(aaudioStream);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 03bd6ce..0c40cbb 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -1,7 +1,17 @@
 cc_library_headers {
     name: "libaudioclient_headers",
     vendor_available: true,
-    export_include_dirs: ["include"],
+    min_sdk_version: "29",
+
+    header_libs: [
+        "libaudiofoundation_headers",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    export_header_lib_headers: [
+        "libaudiofoundation_headers",
+    ],
 }
 
 cc_library_shared {
@@ -13,6 +23,8 @@
         "AudioVolumeGroup.cpp",
     ],
     shared_libs: [
+        "capture_state_listener-aidl-cpp",
+        "libaudiofoundation",
         "libaudioutils",
         "libbinder",
         "libcutils",
@@ -25,6 +37,9 @@
     ],
     include_dirs: ["system/media/audio_utils/include"],
     export_include_dirs: ["include"],
+    export_shared_lib_headers: [
+        "capture_state_listener-aidl-cpp",
+    ],
 }
 
 cc_library_shared {
@@ -42,7 +57,8 @@
         // AIDL files for audioclient interfaces
         // The headers for these interfaces will be available to any modules that
         // include libaudioclient, at the path "aidl/package/path/BnFoo.h"
-        "aidl/android/media/IAudioRecord.aidl",
+        ":libaudioclient_aidl_callback",
+        ":libaudioclient_aidl_private",
         ":libaudioclient_aidl",
 
         "AudioEffect.cpp",
@@ -63,6 +79,8 @@
         "TrackPlayerBase.cpp",
     ],
     shared_libs: [
+        "capture_state_listener-aidl-cpp",
+        "libaudiofoundation",
         "libaudioutils",
         "libaudiopolicy",
         "libaudiomanager",
@@ -80,10 +98,16 @@
     ],
     export_shared_lib_headers: ["libbinder"],
 
-    local_include_dirs: ["include/media", "aidl"],
+    include_dirs: [
+        "frameworks/av/media/libnbaio/include_mono/",
+    ],
+    local_include_dirs: [
+        "include/media", "aidl"
+    ],
     header_libs: [
         "libaudioclient_headers",
         "libbase_headers",
+        "libmedia_headers",
     ],
     export_header_lib_headers: ["libaudioclient_headers"],
 
@@ -110,4 +134,33 @@
     srcs: [
         "aidl/android/media/IPlayer.aidl",
     ],
+    path: "aidl",
+}
+
+// Used to strip the "aidl/" from the path, so the build system can predict the
+// output filename.
+filegroup {
+    name: "libaudioclient_aidl_private",
+    srcs: [
+        "aidl/android/media/IAudioRecord.aidl",
+    ],
+    path: "aidl",
+}
+
+// AIDL interface for audio track callback
+filegroup {
+    name: "libaudioclient_aidl_callback",
+    srcs: [
+        "aidl/android/media/IAudioTrackCallback.aidl",
+    ],
+    path: "aidl",
+}
+
+aidl_interface {
+    name: "capture_state_listener-aidl",
+    unstable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/media/ICaptureStateListener.aidl",
+    ],
 }
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index cf11936..3ead6cb 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -36,7 +36,7 @@
 // ---------------------------------------------------------------------------
 
 AudioEffect::AudioEffect(const String16& opPackageName)
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
 }
 
@@ -48,12 +48,14 @@
                 effect_callback_t cbf,
                 void* user,
                 audio_session_t sessionId,
-                audio_io_handle_t io
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe
                 )
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
     AutoMutex lock(mConstructLock);
-    mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
+    mStatus = set(type, uuid, priority, cbf, user, sessionId, io, device, probe);
 }
 
 AudioEffect::AudioEffect(const char *typeStr,
@@ -63,9 +65,11 @@
                 effect_callback_t cbf,
                 void* user,
                 audio_session_t sessionId,
-                audio_io_handle_t io
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe
                 )
-    : mStatus(NO_INIT), mOpPackageName(opPackageName)
+    : mStatus(NO_INIT), mProbe(false), mOpPackageName(opPackageName)
 {
     effect_uuid_t type;
     effect_uuid_t *pType = NULL;
@@ -87,7 +91,7 @@
     }
 
     AutoMutex lock(mConstructLock);
-    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
+    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io, device, probe);
 }
 
 status_t AudioEffect::set(const effect_uuid_t *type,
@@ -96,7 +100,9 @@
                 effect_callback_t cbf,
                 void* user,
                 audio_session_t sessionId,
-                audio_io_handle_t io)
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe)
 {
     sp<IEffect> iEffect;
     sp<IMemory> cblk;
@@ -109,6 +115,10 @@
         return INVALID_OPERATION;
     }
 
+    if (sessionId == AUDIO_SESSION_DEVICE && io != AUDIO_IO_HANDLE_NONE) {
+        ALOGW("IO handle should not be specified for device effect");
+        return BAD_VALUE;
+    }
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
         ALOGE("set(): Could not get audioflinger");
@@ -119,7 +129,7 @@
         ALOGW("Must specify at least type or uuid");
         return BAD_VALUE;
     }
-
+    mProbe = probe;
     mPriority = priority;
     mCbf = cbf;
     mUserData = user;
@@ -131,18 +141,24 @@
 
     mIEffectClient = new EffectClient(this);
     mClientPid = IPCThreadState::self()->getCallingPid();
+    mClientUid = IPCThreadState::self()->getCallingUid();
 
     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
-            mIEffectClient, priority, io, mSessionId, mOpPackageName, mClientPid,
-            &mStatus, &mId, &enabled);
+            mIEffectClient, priority, io, mSessionId, device, mOpPackageName, mClientPid,
+            probe, &mStatus, &mId, &enabled);
 
-    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
-        char typeBuffer[64], uuidBuffer[64];
+    // In probe mode, we stop here and return the status: the IEffect interface to
+    // audio flinger will not be retained. initCheck() will return the creation status
+    // but all other APIs will return invalid operation.
+    if (probe || iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+        char typeBuffer[64] = {}, uuidBuffer[64] = {};
         guidToString(type, typeBuffer, sizeof(typeBuffer));
         guidToString(uuid, uuidBuffer, sizeof(uuidBuffer));
-        ALOGE("set(): AudioFlinger could not create effect %s / %s, status: %d",
-                typeBuffer, uuidBuffer, mStatus);
-        if (iEffect == 0) {
+        ALOGE_IF(!probe, "set(): AudioFlinger could not create effect %s / %s, status: %d",
+                type != nullptr ? typeBuffer : "NULL",
+                uuid != nullptr ? uuidBuffer : "NULL",
+                mStatus);
+        if (!probe && iEffect == 0) {
             mStatus = NO_INIT;
         }
         return mStatus;
@@ -159,7 +175,11 @@
 
     mIEffect = iEffect;
     mCblkMemory = cblk;
-    mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    mCblk = static_cast<effect_param_cblk_t*>(cblk->unsecurePointer());
     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
 
@@ -167,8 +187,8 @@
     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
             mStatus, mEnabled, mClientPid);
 
-    if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
-        AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
+    if (!audio_is_global_session(mSessionId)) {
+        AudioSystem::acquireAudioSessionId(mSessionId, mClientPid, mClientUid);
     }
 
     return mStatus;
@@ -179,8 +199,8 @@
 {
     ALOGV("Destructor %p", this);
 
-    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
-        if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+    if (!mProbe && (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS)) {
+        if (!audio_is_global_session(mSessionId)) {
             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
         }
         if (mIEffect != NULL) {
@@ -189,9 +209,9 @@
         }
         mIEffect.clear();
         mCblkMemory.clear();
-        mIEffectClient.clear();
-        IPCThreadState::self()->flushCommands();
     }
+    mIEffectClient.clear();
+    IPCThreadState::self()->flushCommands();
 }
 
 
@@ -214,6 +234,9 @@
 
 status_t AudioEffect::setEnabled(bool enabled)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -242,6 +265,9 @@
                               uint32_t *replySize,
                               void *replyData)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
         ALOGV("command() bad status %d", mStatus);
         return mStatus;
@@ -275,6 +301,9 @@
 
 status_t AudioEffect::setParameter(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -295,6 +324,9 @@
 
 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -321,6 +353,9 @@
 
 status_t AudioEffect::setParameterCommit()
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
@@ -335,6 +370,9 @@
 
 status_t AudioEffect::getParameter(effect_param_t *param)
 {
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
         return mStatus;
     }
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 3cdf095..0522099 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -22,22 +22,6 @@
 namespace android {
 
 //
-//  AudioDeviceTypeAddr implementation
-//
-status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
-    mType = (audio_devices_t) parcel->readInt32();
-    mAddress = parcel->readString8();
-    return NO_ERROR;
-}
-
-status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
-    parcel->writeInt32((int32_t) mType);
-    parcel->writeString8(mAddress);
-    return NO_ERROR;
-}
-
-
-//
 //  AudioMixMatchCriterion implementation
 //
 AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
@@ -69,6 +53,10 @@
     case RULE_EXCLUDE_UID:
         mValue.mUid = (uid_t) parcel->readInt32();
         break;
+    case RULE_MATCH_USERID:
+    case RULE_EXCLUDE_USERID:
+        mValue.mUserId = (int) parcel->readInt32();
+        break;
     default:
         ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
         return BAD_VALUE;
@@ -98,6 +86,7 @@
     mDeviceAddress = parcel->readString8();
     mCbFlags = (uint32_t)parcel->readInt32();
     mAllowPrivilegedPlaybackCapture = parcel->readBool();
+    mVoiceCommunicationCaptureAllowed = parcel->readBool();
     size_t size = (size_t)parcel->readInt32();
     if (size > MAX_CRITERIA_PER_MIX) {
         size = MAX_CRITERIA_PER_MIX;
@@ -122,6 +111,7 @@
     parcel->writeString8(mDeviceAddress);
     parcel->writeInt32(mCbFlags);
     parcel->writeBool(mAllowPrivilegedPlaybackCapture);
+    parcel->writeBool(mVoiceCommunicationCaptureAllowed);
     size_t size = mCriteria.size();
     if (size > MAX_CRITERIA_PER_MIX) {
         size = MAX_CRITERIA_PER_MIX;
@@ -179,6 +169,40 @@
     return false;
 }
 
+void AudioMix::setExcludeUserId(int userId) const {
+    AudioMixMatchCriterion crit;
+    crit.mRule = RULE_EXCLUDE_USERID;
+    crit.mValue.mUserId = userId;
+    mCriteria.add(crit);
+}
+
+void AudioMix::setMatchUserId(int userId) const {
+    AudioMixMatchCriterion crit;
+    crit.mRule = RULE_MATCH_USERID;
+    crit.mValue.mUserId = userId;
+    mCriteria.add(crit);
+}
+
+bool AudioMix::hasUserIdRule(bool match, int userId) const {
+    const uint32_t rule = match ? RULE_MATCH_USERID : RULE_EXCLUDE_USERID;
+    for (size_t i = 0; i < mCriteria.size(); i++) {
+        if (mCriteria[i].mRule == rule
+                && mCriteria[i].mValue.mUserId == userId) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioMix::hasMatchUserIdRule() const {
+    for (size_t i = 0; i < mCriteria.size(); i++) {
+        if (mCriteria[i].mRule == RULE_MATCH_USERID) {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool AudioMix::isDeviceAffinityCompatible() const {
     return ((mMixType == MIX_TYPE_PLAYERS)
             && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
diff --git a/media/libaudioclient/AudioProductStrategy.cpp b/media/libaudioclient/AudioProductStrategy.cpp
index 0e1dfac..cff72fd 100644
--- a/media/libaudioclient/AudioProductStrategy.cpp
+++ b/media/libaudioclient/AudioProductStrategy.cpp
@@ -70,6 +70,7 @@
     return NO_ERROR;
 }
 
+// Keep in sync with android/media/audiopolicy/AudioProductStrategy#attributeMatches
 bool AudioProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
                                         const audio_attributes_t clientAttritubes)
 {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 271e186..df47def 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -32,7 +32,7 @@
 #include <private/media/AudioTrackShared.h>
 #include <processgroup/sched_policy.h>
 #include <media/IAudioFlinger.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/TypeConverter.h>
 
 #define WAIT_PERIOD_MS          10
@@ -79,37 +79,41 @@
 #define MM_PREFIX "android.media.audiorecord." // avoid cut-n-paste errors.
 
     // Java API 28 entries, do not change.
-    mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(record->mFormat).c_str());
-    mAnalyticsItem->setCString(MM_PREFIX "source", toString(record->mAttributes.source).c_str());
-    mAnalyticsItem->setInt32(MM_PREFIX "latency", (int32_t)record->mLatency); // bad estimate.
-    mAnalyticsItem->setInt32(MM_PREFIX "samplerate", (int32_t)record->mSampleRate);
-    mAnalyticsItem->setInt32(MM_PREFIX "channels", (int32_t)record->mChannelCount);
+    mMetricsItem->setCString(MM_PREFIX "encoding", toString(record->mFormat).c_str());
+    mMetricsItem->setCString(MM_PREFIX "source", toString(record->mAttributes.source).c_str());
+    mMetricsItem->setInt32(MM_PREFIX "latency", (int32_t)record->mLatency); // bad estimate.
+    mMetricsItem->setInt32(MM_PREFIX "samplerate", (int32_t)record->mSampleRate);
+    mMetricsItem->setInt32(MM_PREFIX "channels", (int32_t)record->mChannelCount);
 
     // Non-API entries, these can change.
-    mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)record->mPortId);
-    mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)record->mFrameCount);
-    mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(record->mAttributes).c_str());
-    mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)record->mChannelMask);
+    mMetricsItem->setInt32(MM_PREFIX "portId", (int32_t)record->mPortId);
+    mMetricsItem->setInt32(MM_PREFIX "frameCount", (int32_t)record->mFrameCount);
+    mMetricsItem->setCString(MM_PREFIX "attributes", toString(record->mAttributes).c_str());
+    mMetricsItem->setInt64(MM_PREFIX "channelMask", (int64_t)record->mChannelMask);
 
     // log total duration recording, including anything currently running.
     int64_t activeNs = 0;
     if (mStartedNs != 0) {
         activeNs = systemTime() - mStartedNs;
     }
-    mAnalyticsItem->setDouble(MM_PREFIX "durationMs", (mDurationNs + activeNs) * 1e-6);
-    mAnalyticsItem->setInt64(MM_PREFIX "startCount", (int64_t)mCount);
+    mMetricsItem->setDouble(MM_PREFIX "durationMs", (mDurationNs + activeNs) * 1e-6);
+    mMetricsItem->setInt64(MM_PREFIX "startCount", (int64_t)mCount);
 
     if (mLastError != NO_ERROR) {
-        mAnalyticsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
-        mAnalyticsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
+        mMetricsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
+        mMetricsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
     }
 }
 
+static const char *stateToString(bool active) {
+    return active ? "ACTIVE" : "STOPPED";
+}
+
 // hand the user a snapshot of the metrics.
-status_t AudioRecord::getMetrics(MediaAnalyticsItem * &item)
+status_t AudioRecord::getMetrics(mediametrics::Item * &item)
 {
     mMediaMetrics.gather(this);
-    MediaAnalyticsItem *tmp = mMediaMetrics.dup();
+    mediametrics::Item *tmp = mMediaMetrics.dup();
     if (tmp == nullptr) {
         return BAD_VALUE;
     }
@@ -164,6 +168,15 @@
 {
     mMediaMetrics.gather(this);
 
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
+        .set(AMEDIAMETRICS_PROP_CALLERNAME,
+                mCallerName.empty()
+                ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+                : mCallerName.c_str())
+        .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus)
+        .record();
+
     if (mStatus == NO_ERROR) {
         // Make sure that callback function exits in the case where
         // it is looping on buffer empty condition in obtainBuffer().
@@ -186,7 +199,7 @@
         IPCThreadState::self()->flushCommands();
         ALOGV("%s(%d): releasing session id %d",
                 __func__, mPortId, mSessionId);
-        AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/);
+        AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
     }
 }
 
@@ -262,8 +275,12 @@
     }
 
     if (pAttributes == NULL) {
-        memset(&mAttributes, 0, sizeof(audio_attributes_t));
+        mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
         mAttributes.source = inputSource;
+        if (inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || inputSource == AUDIO_SOURCE_CAMCORDER) {
+            mAttributes.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+        }
     } else {
         // stream type shouldn't be looked at, this track has audio attributes
         memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
@@ -357,7 +374,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
-    AudioSystem::acquireAudioSessionId(mSessionId, -1);
+    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid, mClientUid);
     mSequence = 1;
     mObservedSequence = mSequence;
     mInOverrun = false;
@@ -376,11 +393,25 @@
 
 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
 {
+    const int64_t beginNs = systemTime();
     ALOGV("%s(%d): sync event %d trigger session %d", __func__, mPortId, event, triggerSession);
-
     AutoMutex lock(mLock);
+
+    status_t status = NO_ERROR;
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_CALLERNAME,
+                    mCallerName.empty()
+                    ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+                    : mCallerName.c_str())
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
+            .record(); });
+
     if (mActive) {
-        return NO_ERROR;
+        return status;
     }
 
     // discard data in buffer
@@ -388,6 +419,9 @@
     mFramesReadServerOffset -= mFramesRead + framesFlushed;
     mFramesRead = 0;
     mProxy->clearTimestamp();  // timestamp is invalid until next server push
+    mPreviousTimestamp.clear();
+    mTimestampRetrogradePositionReported = false;
+    mTimestampRetrogradeTimeReported = false;
 
     // reset current position as seen by client to 0
     mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
@@ -405,7 +439,6 @@
     // mActive is checked by restoreRecord_l
     mActive = true;
 
-    status_t status = NO_ERROR;
     if (!(flags & CBLK_INVALID)) {
         status = mAudioRecord->start(event, triggerSession).transactionError();
         if (status == DEAD_OBJECT) {
@@ -443,7 +476,15 @@
 
 void AudioRecord::stop()
 {
+    const int64_t beginNs = systemTime();
     AutoMutex lock(mLock);
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
+            .record(); });
+
     ALOGV("%s(%d): mActive:%d\n", __func__, mPortId, mActive);
     if (!mActive) {
         return;
@@ -570,6 +611,39 @@
                 timestamp->mPosition[i] += mFramesReadServerOffset;
             }
         }
+
+        bool timestampRetrogradeTimeReported = false;
+        bool timestampRetrogradePositionReported = false;
+        for (int i = 0; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
+            if (timestamp->mTimeNs[i] >= 0 && mPreviousTimestamp.mTimeNs[i] >= 0) {
+                if (timestamp->mTimeNs[i] < mPreviousTimestamp.mTimeNs[i]) {
+                    if (!mTimestampRetrogradeTimeReported) {
+                        ALOGD("%s: retrograde time adjusting [%d] current:%lld to previous:%lld",
+                                __func__, i, (long long)timestamp->mTimeNs[i],
+                                (long long)mPreviousTimestamp.mTimeNs[i]);
+                        timestampRetrogradeTimeReported = true;
+                    }
+                    timestamp->mTimeNs[i] = mPreviousTimestamp.mTimeNs[i];
+                }
+                if (timestamp->mPosition[i] < mPreviousTimestamp.mPosition[i]) {
+                    if (!mTimestampRetrogradePositionReported) {
+                        ALOGD("%s: retrograde position"
+                                " adjusting [%d] current:%lld to previous:%lld",
+                                __func__, i, (long long)timestamp->mPosition[i],
+                                (long long)mPreviousTimestamp.mPosition[i]);
+                        timestampRetrogradePositionReported = true;
+                    }
+                    timestamp->mPosition[i] = mPreviousTimestamp.mPosition[i];
+                }
+            }
+        }
+        mPreviousTimestamp = *timestamp;
+        if (timestampRetrogradeTimeReported) {
+            mTimestampRetrogradeTimeReported = true;
+        }
+        if (timestampRetrogradePositionReported) {
+            mTimestampRetrogradePositionReported = true;
+        }
     }
     return status;
 }
@@ -659,6 +733,7 @@
 // must be called with mLock held
 status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
 {
+    const int64_t beginNs = systemTime();
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     IAudioFlinger::CreateRecordInput input;
     IAudioFlinger::CreateRecordOutput output;
@@ -696,7 +771,7 @@
             // use case 3: obtain/release mode
             (mTransfer == TRANSFER_OBTAIN);
         if (!useCaseAllowed) {
-            ALOGW("%s(%d): AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
+            ALOGD("%s(%d): AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
                   __func__, mPortId,
                   convertTransferToText(mTransfer));
             mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
@@ -759,7 +834,11 @@
         status = NO_INIT;
         goto exit;
     }
-    iMemPointer = output.cblk ->pointer();
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    iMemPointer = output.cblk ->unsecurePointer();
     if (iMemPointer == NULL) {
         ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
@@ -774,7 +853,11 @@
     if (output.buffers == 0) {
         buffers = cblk + 1;
     } else {
-        buffers = output.buffers->pointer();
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        buffers = output.buffers->unsecurePointer();
         if (buffers == NULL) {
             ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
@@ -837,6 +920,29 @@
     mDeathNotifier = new DeathNotifier(this);
     IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
 
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(mPortId);
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
+        .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+        // the following are immutable (at least until restore)
+        .set(AMEDIAMETRICS_PROP_FLAGS, toString(mFlags).c_str())
+        .set(AMEDIAMETRICS_PROP_ORIGINALFLAGS, toString(mOrigFlags).c_str())
+        .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)mSessionId)
+        .set(AMEDIAMETRICS_PROP_TRACKID, mPortId)
+        .set(AMEDIAMETRICS_PROP_SOURCE, toString(mAttributes.source).c_str())
+        .set(AMEDIAMETRICS_PROP_THREADID, (int32_t)output.inputId)
+        .set(AMEDIAMETRICS_PROP_SELECTEDDEVICEID, (int32_t)mSelectedDeviceId)
+        .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)mRoutedDeviceId)
+        .set(AMEDIAMETRICS_PROP_ENCODING, toString(mFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+        .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        // the following are NOT immutable
+        .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
+        .set(AMEDIAMETRICS_PROP_SELECTEDMICDIRECTION, (int32_t)mSelectedMicDirection)
+        .set(AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION, (double)mSelectedMicFieldDimension)
+        .record();
+
 exit:
     mStatus = status;
     // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
@@ -1276,6 +1382,17 @@
 
 status_t AudioRecord::restoreRecord_l(const char *from)
 {
+    status_t result = NO_ERROR;  // logged: make sure to set this before returning.
+    const int64_t beginNs = systemTime();
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .set(AMEDIAMETRICS_PROP_WHERE, from)
+            .record(); });
+
     ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mPortId, from);
     ++mSequence;
 
@@ -1294,7 +1411,7 @@
     // It will also delete the strong references on previous IAudioRecord and IMemory
     Modulo<uint32_t> position(mProxy->getPosition());
     mNewPosition = position + mUpdatePeriod;
-    status_t result = createRecord_l(position, mOpPackageName);
+    result = createRecord_l(position, mOpPackageName);
 
     if (result == NO_ERROR) {
         if (mActive) {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 02dc516..6357da4 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -18,6 +18,8 @@
 //#define LOG_NDEBUG 0
 
 #include <utils/Log.h>
+
+#include <android/media/BnCaptureStateListener.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <binder/IPCThreadState.h>
@@ -36,18 +38,24 @@
 
 // client singleton for AudioFlinger binder interface
 Mutex AudioSystem::gLock;
+Mutex AudioSystem::gLockErrorCallbacks;
 Mutex AudioSystem::gLockAPS;
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
-audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
+std::set<audio_error_callback> AudioSystem::gAudioErrorCallbacks;
 dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
 record_config_callback AudioSystem::gRecordConfigCallback = NULL;
 
+// Required to be held while calling into gSoundTriggerCaptureStateListener.
+Mutex gSoundTriggerCaptureStateListenerLock;
+sp<AudioSystem::CaptureStateListener> gSoundTriggerCaptureStateListener = nullptr;
+
 // establish binder interface to AudioFlinger service
 const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
 {
     sp<IAudioFlinger> af;
     sp<AudioFlingerClient> afc;
+    bool reportNoError = false;
     {
         Mutex::Autolock _l(gLock);
         if (gAudioFlinger == 0) {
@@ -63,9 +71,7 @@
             if (gAudioFlingerClient == NULL) {
                 gAudioFlingerClient = new AudioFlingerClient();
             } else {
-                if (gAudioErrorCallback) {
-                    gAudioErrorCallback(NO_ERROR);
-                }
+                reportNoError = true;
             }
             binder->linkToDeath(gAudioFlingerClient);
             gAudioFlinger = interface_cast<IAudioFlinger>(binder);
@@ -81,6 +87,7 @@
         af->registerClient(afc);
         IPCThreadState::self()->restoreCallingIdentity(token);
     }
+    if (reportNoError) reportError(NO_ERROR);
     return af;
 }
 
@@ -434,11 +441,11 @@
     return af->newAudioUniqueId(use);
 }
 
-void AudioSystem::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
+void AudioSystem::acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid)
 {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af != 0) {
-        af->acquireAudioSessionId(audioSession, pid);
+        af->acquireAudioSessionId(audioSession, pid, uid);
     }
 }
 
@@ -500,19 +507,16 @@
 
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused)
 {
-    audio_error_callback cb = NULL;
     {
         Mutex::Autolock _l(AudioSystem::gLock);
         AudioSystem::gAudioFlinger.clear();
-        cb = gAudioErrorCallback;
     }
 
     // clear output handles and stream to output map caches
     clearIoCache();
 
-    if (cb) {
-        cb(DEAD_OBJECT);
-    }
+    reportError(DEAD_OBJECT);
+
     ALOGW("AudioFlinger server died!");
 }
 
@@ -717,10 +721,23 @@
     return NO_ERROR;
 }
 
-/* static */ void AudioSystem::setErrorCallback(audio_error_callback cb)
+/* static */ uintptr_t AudioSystem::addErrorCallback(audio_error_callback cb)
 {
-    Mutex::Autolock _l(gLock);
-    gAudioErrorCallback = cb;
+    Mutex::Autolock _l(gLockErrorCallbacks);
+    gAudioErrorCallbacks.insert(cb);
+    return reinterpret_cast<uintptr_t>(cb);
+}
+
+/* static */ void AudioSystem::removeErrorCallback(uintptr_t cb) {
+    Mutex::Autolock _l(gLockErrorCallbacks);
+    gAudioErrorCallbacks.erase(reinterpret_cast<audio_error_callback>(cb));
+}
+
+/* static */ void AudioSystem::reportError(status_t err) {
+    Mutex::Autolock _l(gLockErrorCallbacks);
+    for (auto callback : gAudioErrorCallbacks) {
+      callback(err);
+    }
 }
 
 /*static*/ void AudioSystem::setDynPolicyCallback(dynamic_policy_callback cb)
@@ -783,6 +800,13 @@
 
 // ---------------------------------------------------------------------------
 
+void AudioSystem::onNewAudioModulesAvailable()
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->onNewAudioModulesAvailable();
+}
+
 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                                audio_policy_dev_state_t state,
                                                const char *device_address,
@@ -833,13 +857,13 @@
     return aps->handleDeviceConfigChange(device, address, name, encodedFormat);
 }
 
-status_t AudioSystem::setPhoneState(audio_mode_t state)
+status_t AudioSystem::setPhoneState(audio_mode_t state, uid_t uid)
 {
     if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    return aps->setPhoneState(state);
+    return aps->setPhoneState(state, uid);
 }
 
 status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
@@ -1017,6 +1041,16 @@
     return aps->getDevicesForStream(stream);
 }
 
+status_t AudioSystem::getDevicesForAttributes(const AudioAttributes &aa,
+                                              AudioDeviceTypeAddrVector *devices) {
+    if (devices == nullptr) {
+        return BAD_VALUE;
+    }
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->getDevicesForAttributes(aa, devices);
+}
+
 audio_io_handle_t AudioSystem::getOutputForEffect(const effect_descriptor_t *desc)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1123,6 +1157,12 @@
     }
 }
 
+status_t AudioSystem::setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages) {
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == nullptr) return PERMISSION_DENIED;
+    return aps->setSupportedSystemUsages(systemUsages);
+}
+
 status_t AudioSystem::setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == nullptr) return PERMISSION_DENIED;
@@ -1334,6 +1374,21 @@
     return aps->removeUidDeviceAffinities(uid);
 }
 
+status_t AudioSystem::setUserIdDeviceAffinities(int userId,
+                                                const Vector<AudioDeviceTypeAddr>& devices)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setUserIdDeviceAffinities(userId, devices);
+}
+
+status_t AudioSystem::removeUserIdDeviceAffinities(int userId)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->removeUserIdDeviceAffinities(userId);
+}
+
 status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
                                        const audio_attributes_t *attributes,
                                        audio_port_handle_t *portId)
@@ -1392,6 +1447,12 @@
     return af->getMicrophones(microphones);
 }
 
+status_t AudioSystem::setAudioHalPids(const std::vector<pid_t>& pids) {
+  const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+  if (af == nullptr) return PERMISSION_DENIED;
+  return af->setAudioHalPids(pids);
+}
+
 status_t AudioSystem::getSurroundFormats(unsigned int *numSurroundFormats,
                                          audio_format_t *surroundFormats,
                                          bool *surroundFormatsEnabled,
@@ -1426,6 +1487,14 @@
     return aps->setA11yServicesUids(uids);
 }
 
+status_t AudioSystem::setCurrentImeUid(uid_t uid)
+{
+    const sp <IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->setCurrentImeUid(uid);
+}
+
 bool AudioSystem::isHapticPlaybackSupported()
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
@@ -1485,7 +1554,14 @@
             }
         }
     }
-    ALOGE("invalid attributes %s when converting to stream",  toString(attr).c_str());
+    switch (attr.usage) {
+        case AUDIO_USAGE_VIRTUAL_SOURCE:
+            // virtual source is not expected to have an associated product strategy
+            break;
+        default:
+            ALOGE("invalid attributes %s when converting to stream",  toString(attr).c_str());
+            break;
+    }
     return AUDIO_STREAM_MUSIC;
 }
 
@@ -1519,6 +1595,84 @@
     return aps->setRttEnabled(enabled);
 }
 
+bool AudioSystem::isCallScreenModeSupported()
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return false;
+    return aps->isCallScreenModeSupported();
+}
+
+status_t AudioSystem::setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                    const AudioDeviceTypeAddr &device)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) {
+        return PERMISSION_DENIED;
+    }
+    return aps->setPreferredDeviceForStrategy(strategy, device);
+}
+
+status_t AudioSystem::removePreferredDeviceForStrategy(product_strategy_t strategy)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) {
+        return PERMISSION_DENIED;
+    }
+    return aps->removePreferredDeviceForStrategy(strategy);
+}
+
+status_t AudioSystem::getPreferredDeviceForStrategy(product_strategy_t strategy,
+        AudioDeviceTypeAddr &device)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) {
+        return PERMISSION_DENIED;
+    }
+    return aps->getPreferredDeviceForStrategy(strategy, device);
+}
+
+class CaptureStateListenerImpl : public media::BnCaptureStateListener,
+                                 public IBinder::DeathRecipient {
+public:
+    binder::Status setCaptureState(bool active) override {
+        Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
+        gSoundTriggerCaptureStateListener->onStateChanged(active);
+        return binder::Status::ok();
+    }
+
+    void binderDied(const wp<IBinder>&) override {
+        Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
+        gSoundTriggerCaptureStateListener->onServiceDied();
+        gSoundTriggerCaptureStateListener = nullptr;
+    }
+};
+
+status_t AudioSystem::registerSoundTriggerCaptureStateListener(
+    const sp<CaptureStateListener>& listener) {
+    const sp<IAudioPolicyService>& aps =
+            AudioSystem::get_audio_policy_service();
+    if (aps == 0) {
+        return PERMISSION_DENIED;
+    }
+
+    sp<CaptureStateListenerImpl> wrapper = new CaptureStateListenerImpl();
+
+    Mutex::Autolock _l(gSoundTriggerCaptureStateListenerLock);
+
+    bool active;
+    status_t status =
+        aps->registerSoundTriggerCaptureStateListener(wrapper, &active);
+    if (status != NO_ERROR) {
+        listener->onServiceDied();
+        return NO_ERROR;
+    }
+    gSoundTriggerCaptureStateListener = listener;
+    listener->onStateChanged(active);
+    sp<IBinder> binder = IInterface::asBinder(aps);
+    binder->linkToDeath(wrapper);
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 9a66d48..32129f0 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -35,7 +35,7 @@
 #include <media/AudioParameter.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/TypeConverter.h>
 
 #define WAIT_PERIOD_MS                  10
@@ -73,7 +73,7 @@
 static inline struct timespec convertNsToTimespec(int64_t ns) {
     struct timespec tv;
     tv.tv_sec = static_cast<time_t>(ns / NANOS_PER_SECOND);
-    tv.tv_nsec = static_cast<long>(ns % NANOS_PER_SECOND);
+    tv.tv_nsec = static_cast<int64_t>(ns % NANOS_PER_SECOND);
     return tv;
 }
 
@@ -183,26 +183,26 @@
 #define MM_PREFIX "android.media.audiotrack." // avoid cut-n-paste errors.
 
     // Java API 28 entries, do not change.
-    mAnalyticsItem->setCString(MM_PREFIX "streamtype", toString(track->streamType()).c_str());
-    mAnalyticsItem->setCString(MM_PREFIX "type",
+    mMetricsItem->setCString(MM_PREFIX "streamtype", toString(track->streamType()).c_str());
+    mMetricsItem->setCString(MM_PREFIX "type",
             toString(track->mAttributes.content_type).c_str());
-    mAnalyticsItem->setCString(MM_PREFIX "usage", toString(track->mAttributes.usage).c_str());
+    mMetricsItem->setCString(MM_PREFIX "usage", toString(track->mAttributes.usage).c_str());
 
     // Non-API entries, these can change due to a Java string mistake.
-    mAnalyticsItem->setInt32(MM_PREFIX "sampleRate", (int32_t)track->mSampleRate);
-    mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)track->mChannelMask);
+    mMetricsItem->setInt32(MM_PREFIX "sampleRate", (int32_t)track->mSampleRate);
+    mMetricsItem->setInt64(MM_PREFIX "channelMask", (int64_t)track->mChannelMask);
     // Non-API entries, these can change.
-    mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)track->mPortId);
-    mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(track->mFormat).c_str());
-    mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)track->mFrameCount);
-    mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(track->mAttributes).c_str());
+    mMetricsItem->setInt32(MM_PREFIX "portId", (int32_t)track->mPortId);
+    mMetricsItem->setCString(MM_PREFIX "encoding", toString(track->mFormat).c_str());
+    mMetricsItem->setInt32(MM_PREFIX "frameCount", (int32_t)track->mFrameCount);
+    mMetricsItem->setCString(MM_PREFIX "attributes", toString(track->mAttributes).c_str());
 }
 
 // hand the user a snapshot of the metrics.
-status_t AudioTrack::getMetrics(MediaAnalyticsItem * &item)
+status_t AudioTrack::getMetrics(mediametrics::Item * &item)
 {
     mMediaMetrics.gather(this);
-    MediaAnalyticsItem *tmp = mMediaMetrics.dup();
+    mediametrics::Item *tmp = mMediaMetrics.dup();
     if (tmp == nullptr) {
         return BAD_VALUE;
     }
@@ -217,7 +217,8 @@
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
+      mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
     mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -248,7 +249,8 @@
       mState(STATE_STOPPED),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
-      mPausedPosition(0)
+      mPausedPosition(0),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
 
@@ -281,7 +283,8 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mAudioTrackCallback(new AudioTrackCallback())
 {
     mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
 
@@ -296,6 +299,16 @@
     // pull together the numbers, before we clean up our structures
     mMediaMetrics.gather(this);
 
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
+        .set(AMEDIAMETRICS_PROP_CALLERNAME,
+                mCallerName.empty()
+                ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+                : mCallerName.c_str())
+        .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+        .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus)
+        .record();
+
     if (mStatus == NO_ERROR) {
         // Make sure that callback function exits in the case where
         // it is looping on buffer full condition in obtainBuffer().
@@ -406,7 +419,7 @@
     mDoNotReconnect = doNotReconnect;
 
     ALOGV_IF(sharedBuffer != 0, "%s(): sharedBuffer: %p, size: %zu",
-            __func__, sharedBuffer->pointer(), sharedBuffer->size());
+            __func__, sharedBuffer->unsecurePointer(), sharedBuffer->size());
 
     ALOGV("%s(): streamType %d frameCount %zu flags %04x",
             __func__, streamType, frameCount, flags);
@@ -599,7 +612,7 @@
     mReleased = 0;
     mStartNs = 0;
     mStartFromZeroUs = 0;
-    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
+    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid, mClientUid);
     mSequence = 1;
     mObservedSequence = mSequence;
     mInUnderrun = false;
@@ -627,12 +640,30 @@
 status_t AudioTrack::start()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
         return INVALID_OPERATION;
     }
 
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
+
+    // Defer logging here due to OpenSL ES repeated start calls.
+    // TODO(b/154868033) after fix, restore this logging back to the beginning of start().
+    const int64_t beginNs = systemTime();
+    status_t status = NO_ERROR; // logged: make sure to set this before returning.
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_CALLERNAME,
+                    mCallerName.empty()
+                    ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
+                    : mCallerName.c_str())
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
+            .record(); });
+
+
     mInUnderrun = true;
 
     State previousState = mState;
@@ -703,7 +734,6 @@
     mNewPosition = mPosition + mUpdatePeriod;
     int32_t flags = android_atomic_and(~(CBLK_STREAM_END_DONE | CBLK_DISABLED), &mCblk->mFlags);
 
-    status_t status = NO_ERROR;
     if (!(flags & CBLK_INVALID)) {
         status = mAudioTrack->start();
         if (status == DEAD_OBJECT) {
@@ -749,7 +779,19 @@
 
 void AudioTrack::stop()
 {
+    const int64_t beginNs = systemTime();
+
     AutoMutex lock(mLock);
+    mediametrics::Defer defer([&]() {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+            .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t)mProxy->getBufferSizeInFrames())
+            .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getUnderrunCount_l())
+            .record();
+    });
+
     ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
@@ -801,7 +843,15 @@
 
 void AudioTrack::flush()
 {
+    const int64_t beginNs = systemTime();
     AutoMutex lock(mLock);
+    mediametrics::Defer defer([&]() {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+            .record(); });
+
     ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mSharedBuffer != 0) {
@@ -834,7 +884,15 @@
 
 void AudioTrack::pause()
 {
+    const int64_t beginNs = systemTime();
     AutoMutex lock(mLock);
+    mediametrics::Defer defer([&]() {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+            .record(); });
+
     ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
@@ -876,6 +934,12 @@
         return BAD_VALUE;
     }
 
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOLUME)
+        .set(AMEDIAMETRICS_PROP_VOLUME_LEFT, (double)left)
+        .set(AMEDIAMETRICS_PROP_VOLUME_RIGHT, (double)right)
+        .record();
+
     AutoMutex lock(mLock);
     mVolume[AUDIO_INTERLEAVE_LEFT] = left;
     mVolume[AUDIO_INTERLEAVE_RIGHT] = right;
@@ -1027,6 +1091,20 @@
     //set effective rates
     mProxy->setPlaybackRate(playbackRateTemp);
     mProxy->setSampleRate(effectiveRate); // FIXME: not quite "atomic" with setPlaybackRate
+
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYBACKPARAM)
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        .set(AMEDIAMETRICS_PROP_PLAYBACK_SPEED, (double)mPlaybackRate.mSpeed)
+        .set(AMEDIAMETRICS_PROP_PLAYBACK_PITCH, (double)mPlaybackRate.mPitch)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)effectiveRate)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_PLAYBACK_SPEED, (double)playbackRateTemp.mSpeed)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_PLAYBACK_PITCH, (double)playbackRateTemp.mPitch)
+        .record();
+
     return NO_ERROR;
 }
 
@@ -1042,6 +1120,7 @@
     if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
         return NO_INIT;
     }
+
     return (ssize_t) mProxy->getBufferSizeInFrames();
 }
 
@@ -1073,7 +1152,17 @@
     if (!audio_is_linear_pcm(mFormat)) {
         return INVALID_OPERATION;
     }
-    return (ssize_t) mProxy->setBufferSizeInFrames((uint32_t) bufferSizeInFrames);
+
+    ssize_t originalBufferSize = mProxy->getBufferSizeInFrames();
+    ssize_t finalBufferSize  = mProxy->setBufferSizeInFrames((uint32_t) bufferSizeInFrames);
+    if (originalBufferSize != finalBufferSize) {
+        android::mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETBUFFERSIZE)
+                .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, (int32_t)mProxy->getBufferSizeInFrames())
+                .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t)getUnderrunCount_l())
+                .record();
+    }
+    return finalBufferSize;
 }
 
 status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
@@ -1465,6 +1554,7 @@
     input.notificationFrameCount = mNotificationFramesReq;
     input.selectedDeviceId = mSelectedDeviceId;
     input.sessionId = mSessionId;
+    input.audioTrackCallback = mAudioTrackCallback;
 
     IAudioFlinger::CreateTrackOutput output;
 
@@ -1508,7 +1598,11 @@
         status = NO_INIT;
         goto exit;
     }
-    void *iMemPointer = iMem->pointer();
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    void *iMemPointer = iMem->unsecurePointer();
     if (iMemPointer == NULL) {
         ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
@@ -1535,7 +1629,7 @@
                 mAwaitBoost = true;
             }
         } else {
-            ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu",
+            ALOGD("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu",
                   __func__, mPortId, mReqFrameCount, mFrameCount);
         }
     }
@@ -1563,7 +1657,11 @@
     if (mSharedBuffer == 0) {
         buffers = cblk + 1;
     } else {
-        buffers = mSharedBuffer->pointer();
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        buffers = mSharedBuffer->unsecurePointer();
         if (buffers == NULL) {
             ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
@@ -1610,6 +1708,48 @@
     mDeathNotifier = new DeathNotifier(this);
     IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
 
+    // This is the first log sent from the AudioTrack client.
+    // The creation of the audio track by AudioFlinger (in the code above)
+    // is the first log of the AudioTrack and must be present before
+    // any AudioTrack client logs will be accepted.
+
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(mPortId);
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
+        // the following are immutable
+        .set(AMEDIAMETRICS_PROP_FLAGS, toString(mFlags).c_str())
+        .set(AMEDIAMETRICS_PROP_ORIGINALFLAGS, toString(mOrigFlags).c_str())
+        .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)mSessionId)
+        .set(AMEDIAMETRICS_PROP_TRACKID, mPortId) // dup from key
+        .set(AMEDIAMETRICS_PROP_CONTENTTYPE, toString(mAttributes.content_type).c_str())
+        .set(AMEDIAMETRICS_PROP_USAGE, toString(mAttributes.usage).c_str())
+        .set(AMEDIAMETRICS_PROP_THREADID, (int32_t)output.outputId)
+        .set(AMEDIAMETRICS_PROP_SELECTEDDEVICEID, (int32_t)mSelectedDeviceId)
+        .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)mRoutedDeviceId)
+        .set(AMEDIAMETRICS_PROP_ENCODING, toString(mFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+        .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
+        // the following are NOT immutable
+        .set(AMEDIAMETRICS_PROP_VOLUME_LEFT, (double)mVolume[AUDIO_INTERLEAVE_LEFT])
+        .set(AMEDIAMETRICS_PROP_VOLUME_RIGHT, (double)mVolume[AUDIO_INTERLEAVE_RIGHT])
+        .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+        .set(AMEDIAMETRICS_PROP_AUXEFFECTID, (int32_t)mAuxEffectId)
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        .set(AMEDIAMETRICS_PROP_PLAYBACK_SPEED, (double)mPlaybackRate.mSpeed)
+        .set(AMEDIAMETRICS_PROP_PLAYBACK_PITCH, (double)mPlaybackRate.mPitch)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)effectiveSampleRate)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_PLAYBACK_SPEED, (double)effectiveSpeed)
+        .set(AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE
+                AMEDIAMETRICS_PROP_PLAYBACK_PITCH, (double)effectivePitch)
+        .record();
+
+    // mSendLevel
+    // mReqFrameCount?
+    // mNotificationFramesAct, mNotificationFramesReq, mNotificationsPerBufferReq
+    // mLatency, mAfLatency, mAfFrameCount, mAfSampleRate
+
     }
 
 exit:
@@ -1651,7 +1791,7 @@
     } else if (waitCount > 0) {
         time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
         timeout.tv_sec = ms / 1000;
-        timeout.tv_nsec = (long) (ms % 1000) * 1000000;
+        timeout.tv_nsec = (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
         ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
@@ -2292,6 +2432,17 @@
 
 status_t AudioTrack::restoreTrack_l(const char *from)
 {
+    status_t result = NO_ERROR;  // logged: make sure to set this before returning.
+    const int64_t beginNs = systemTime();
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .set(AMEDIAMETRICS_PROP_WHERE, from)
+            .record(); });
+
     ALOGW("%s(%d): dead IAudioTrack, %s, creating a new one from %s()",
             __func__, mPortId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
     ++mSequence;
@@ -2303,7 +2454,8 @@
     if (isOffloadedOrDirect_l() || mDoNotReconnect) {
         // FIXME re-creation of offloaded and direct tracks is not yet implemented;
         // reconsider enabling for linear PCM encodings when position can be preserved.
-        return DEAD_OBJECT;
+        result = DEAD_OBJECT;
+        return result;
     }
 
     // Save so we can return count since creation.
@@ -2334,7 +2486,7 @@
     // following member variables: mAudioTrack, mCblkMemory and mCblk.
     // It will also delete the strong references on previous IAudioTrack and IMemory.
     // If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact.
-    status_t result = createTrack_l();
+    result = createTrack_l();
 
     if (result == NO_ERROR) {
         // take the frames that will be lost by track recreation into account in saved position
@@ -3252,4 +3404,23 @@
     mPausedNs = ns;
 }
 
+binder::Status AudioTrack::AudioTrackCallback::onCodecFormatChanged(
+        const std::vector<uint8_t>& audioMetadata)
+{
+    AutoMutex _l(mAudioTrackCbLock);
+    sp<media::IAudioTrackCallback> callback = mCallback.promote();
+    if (callback.get() != nullptr) {
+        callback->onCodecFormatChanged(audioMetadata);
+    } else {
+        mCallback.clear();
+    }
+    return binder::Status::ok();
+}
+
+void AudioTrack::AudioTrackCallback::setAudioTrackCallback(
+        const sp<media::IAudioTrackCallback> &callback) {
+    AutoMutex lock(mAudioTrackCbLock);
+    mCallback = callback;
+}
+
 } // namespace android
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index ee6c335..f1f8f9c 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -984,8 +984,9 @@
 // ---------------------------------------------------------------------------
 
 StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
-        size_t frameCount, size_t frameSize)
-    : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
+        size_t frameCount, size_t frameSize, uint32_t sampleRate)
+    : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize, false /*clientInServer*/,
+                            sampleRate),
       mObserver(&cblk->u.mStatic.mSingleStateQueue),
       mPosLoopMutator(&cblk->u.mStatic.mPosLoopQueue),
       mFramesReadySafe(frameCount), mFramesReady(frameCount),
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index efa0512..16d2232 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,8 +24,8 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
-#include <media/TimeCheck.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include "IAudioFlinger.h"
 
 namespace android {
@@ -90,10 +90,12 @@
     SET_MASTER_BALANCE,
     GET_MASTER_BALANCE,
     SET_EFFECT_SUSPENDED,
+    SET_AUDIO_HAL_PIDS
 };
 
 #define MAX_ITEMS_PER_LIST 1024
 
+
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
 {
 public:
@@ -340,11 +342,11 @@
         return reply.readInt32();
     }
 
-    virtual void setRecordSilenced(uid_t uid, bool silenced)
+    virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(uid);
+        data.writeInt32(portId);
         data.writeInt32(silenced ? 1 : 0);
         remote()->transact(SET_RECORD_SILENCED, data, &reply);
     }
@@ -392,20 +394,18 @@
     virtual status_t openOutput(audio_module_handle_t module,
                                 audio_io_handle_t *output,
                                 audio_config_t *config,
-                                audio_devices_t *devices,
-                                const String8& address,
+                                const sp<DeviceDescriptorBase>& device,
                                 uint32_t *latencyMs,
                                 audio_output_flags_t flags)
     {
-        if (output == NULL || config == NULL || devices == NULL || latencyMs == NULL) {
+        if (output == nullptr || config == nullptr || device == nullptr || latencyMs == nullptr) {
             return BAD_VALUE;
         }
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(module);
         data.write(config, sizeof(audio_config_t));
-        data.writeInt32(*devices);
-        data.writeString8(address);
+        data.writeParcelable(*device);
         data.writeInt32((int32_t) flags);
         status_t status = remote()->transact(OPEN_OUTPUT, data, &reply);
         if (status != NO_ERROR) {
@@ -420,7 +420,6 @@
         *output = (audio_io_handle_t)reply.readInt32();
         ALOGV("openOutput() returned output, %d", *output);
         reply.read(config, sizeof(audio_config_t));
-        *devices = (audio_devices_t)reply.readInt32();
         *latencyMs = reply.readInt32();
         return NO_ERROR;
     }
@@ -572,12 +571,13 @@
         return id;
     }
 
-    virtual void acquireAudioSessionId(audio_session_t audioSession, int pid)
+    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(audioSession);
-        data.writeInt32(pid);
+        data.writeInt32((int32_t)pid);
+        data.writeInt32((int32_t)uid);
         remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
     }
 
@@ -659,20 +659,21 @@
                                     int32_t priority,
                                     audio_io_handle_t output,
                                     audio_session_t sessionId,
+                                    const AudioDeviceTypeAddr& device,
                                     const String16& opPackageName,
                                     pid_t pid,
+                                    bool probe,
                                     status_t *status,
                                     int *id,
                                     int *enabled)
     {
         Parcel data, reply;
         sp<IEffect> effect;
-
         if (pDesc == NULL) {
             if (status != NULL) {
                 *status = BAD_VALUE;
             }
-            return effect;
+            return nullptr;
         }
 
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
@@ -681,8 +682,15 @@
         data.writeInt32(priority);
         data.writeInt32((int32_t) output);
         data.writeInt32(sessionId);
+        if (data.writeParcelable(device) != NO_ERROR) {
+            if (status != NULL) {
+                *status = NO_INIT;
+            }
+            return nullptr;
+        }
         data.writeString16(opPackageName);
         data.writeInt32((int32_t) pid);
+        data.writeInt32(probe ? 1 : 0);
 
         status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
         if (lStatus != NO_ERROR) {
@@ -903,6 +911,20 @@
         status = reply.readParcelableVector(microphones);
         return status;
     }
+    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pids.size());
+        for (auto pid : pids) {
+            data.writeInt32(pid);
+        }
+        status_t status = remote()->transact(SET_AUDIO_HAL_PIDS, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast <status_t> (reply.readInt32());
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -958,7 +980,8 @@
         case SET_MODE:
         case SET_MIC_MUTE:
         case SET_LOW_RAM_DEVICE:
-        case SYSTEM_READY: {
+        case SYSTEM_READY:
+        case SET_AUDIO_HAL_PIDS: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1156,11 +1179,9 @@
         } break;
         case SET_RECORD_SILENCED: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            uid_t uid = data.readInt32();
-            audio_source_t source;
-            data.read(&source, sizeof(audio_source_t));
+            audio_port_handle_t portId = data.readInt32();
             bool silenced = data.readInt32() == 1;
-            setRecordSilenced(uid, silenced);
+            setRecordSilenced(portId, silenced);
             return NO_ERROR;
         } break;
         case SET_PARAMETERS: {
@@ -1200,19 +1221,21 @@
             if (data.read(&config, sizeof(audio_config_t)) != NO_ERROR) {
                 ALOGE("b/23905951");
             }
-            audio_devices_t devices = (audio_devices_t)data.readInt32();
-            String8 address(data.readString8());
+            sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
+            status_t status = NO_ERROR;
+            if ((status = data.readParcelable(device.get())) != NO_ERROR) {
+                reply->writeInt32((int32_t)status);
+                return NO_ERROR;
+            }
             audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
             uint32_t latencyMs = 0;
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-            status_t status = openOutput(module, &output, &config,
-                                         &devices, address, &latencyMs, flags);
+            status = openOutput(module, &output, &config, device, &latencyMs, flags);
             ALOGV("OPEN_OUTPUT output, %d", output);
             reply->writeInt32((int32_t)status);
             if (status == NO_ERROR) {
                 reply->writeInt32((int32_t)output);
                 reply->write(&config, sizeof(audio_config_t));
-                reply->writeInt32(devices);
                 reply->writeInt32(latencyMs);
             }
             return NO_ERROR;
@@ -1306,8 +1329,9 @@
         case ACQUIRE_AUDIO_SESSION_ID: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             audio_session_t audioSession = (audio_session_t) data.readInt32();
-            int pid = data.readInt32();
-            acquireAudioSessionId(audioSession, pid);
+            const pid_t pid = (pid_t)data.readInt32();
+            const uid_t uid = (uid_t)data.readInt32();
+            acquireAudioSessionId(audioSession, pid, uid);
             return NO_ERROR;
         } break;
         case RELEASE_AUDIO_SESSION_ID: {
@@ -1366,15 +1390,20 @@
             int32_t priority = data.readInt32();
             audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
             audio_session_t sessionId = (audio_session_t) data.readInt32();
+            AudioDeviceTypeAddr device;
+            status_t status = NO_ERROR;
+            if ((status = data.readParcelable(&device)) != NO_ERROR) {
+                return status;
+            }
             const String16 opPackageName = data.readString16();
             pid_t pid = (pid_t)data.readInt32();
+            bool probe = data.readInt32() == 1;
 
-            status_t status = NO_ERROR;
             int id = 0;
             int enabled = 0;
 
-            sp<IEffect> effect = createEffect(&desc, client, priority, output, sessionId,
-                    opPackageName, pid, &status, &id, &enabled);
+            sp<IEffect> effect = createEffect(&desc, client, priority, output, sessionId, device,
+                    opPackageName, pid, probe, &status, &id, &enabled);
             reply->writeInt32(status);
             reply->writeInt32(id);
             reply->writeInt32(enabled);
@@ -1547,6 +1576,31 @@
             }
             return NO_ERROR;
         }
+        case SET_AUDIO_HAL_PIDS: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            std::vector<pid_t> pids;
+            int32_t size;
+            status_t status = data.readInt32(&size);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            if (size < 0) {
+                return BAD_VALUE;
+            }
+            if (size > MAX_ITEMS_PER_LIST) {
+                size = MAX_ITEMS_PER_LIST;
+            }
+            for (int32_t i = 0; i < size; i++) {
+                int32_t pid;
+                status =  data.readInt32(&pid);
+                if (status != NO_ERROR) {
+                    return status;
+                }
+                pids.push_back(pid);
+            }
+            reply->writeInt32(setAudioHalPids(pids));
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 2fb9491..60af84b 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -22,16 +22,19 @@
 #include <math.h>
 #include <sys/types.h>
 
+#include <android/media/ICaptureStateListener.h>
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <media/AudioEffect.h>
 #include <media/IAudioPolicyService.h>
-#include <media/TimeCheck.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include <system/audio.h>
 
 namespace android {
 
+using media::ICaptureStateListener;
+
 enum {
     SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
     GET_DEVICE_CONNECTION_STATE,
@@ -97,14 +100,25 @@
     IS_HAPTIC_PLAYBACK_SUPPORTED,
     SET_UID_DEVICE_AFFINITY,
     REMOVE_UID_DEVICE_AFFINITY,
+    SET_USERID_DEVICE_AFFINITY,
+    REMOVE_USERID_DEVICE_AFFINITY,
     GET_OFFLOAD_FORMATS_A2DP,
     LIST_AUDIO_PRODUCT_STRATEGIES,
     GET_STRATEGY_FOR_ATTRIBUTES,
     LIST_AUDIO_VOLUME_GROUPS,
     GET_VOLUME_GROUP_FOR_ATTRIBUTES,
+    SET_SUPPORTED_SYSTEM_USAGES,
     SET_ALLOWED_CAPTURE_POLICY,
     MOVE_EFFECTS_TO_IO,
-    SET_RTT_ENABLED
+    SET_RTT_ENABLED,
+    IS_CALL_SCREEN_MODE_SUPPORTED,
+    SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+    REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+    GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+    GET_DEVICES_FOR_ATTRIBUTES,
+    AUDIO_MODULES_UPDATED,  // oneway
+    SET_CURRENT_IME_UID,
+    REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER,
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -162,11 +176,12 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
-    virtual status_t setPhoneState(audio_mode_t state)
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(state);
+        data.writeInt32(uid);
         remote()->transact(SET_PHONE_STATE, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
@@ -327,6 +342,7 @@
             ALOGE("getInputForAttr NULL portId - shouldn't happen");
             return BAD_VALUE;
         }
+
         data.write(attr, sizeof(audio_attributes_t));
         data.writeInt32(*input);
         data.writeInt32(riid);
@@ -617,6 +633,20 @@
         return status;
     }
 
+    status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(systemUsages.size());
+        for (auto systemUsage : systemUsages) {
+            data.writeInt32(systemUsage);
+        }
+        status_t status = remote()->transact(SET_SUPPORTED_SYSTEM_USAGES, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast <status_t> (reply.readInt32());
+    }
+
     status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) override {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -1120,6 +1150,18 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
+    virtual status_t setCurrentImeUid(uid_t uid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        status_t status = remote()->transact(SET_CURRENT_IME_UID, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast <status_t> (reply.readInt32());
+    }
+
     virtual bool isHapticPlaybackSupported()
     {
         Parcel data, reply;
@@ -1176,6 +1218,52 @@
         return status;
     }
 
+        virtual status_t setUserIdDeviceAffinities(int userId,
+                const Vector<AudioDeviceTypeAddr>& devices)
+        {
+            Parcel data, reply;
+            data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+            data.writeInt32((int32_t) userId);
+            size_t size = devices.size();
+            size_t sizePosition = data.dataPosition();
+            data.writeInt32((int32_t) size);
+            size_t finalSize = size;
+            for (size_t i = 0; i < size; i++) {
+                size_t position = data.dataPosition();
+                if (devices[i].writeToParcel(&data) != NO_ERROR) {
+                    data.setDataPosition(position);
+                    finalSize--;
+                }
+            }
+            if (size != finalSize) {
+                size_t position = data.dataPosition();
+                data.setDataPosition(sizePosition);
+                data.writeInt32(finalSize);
+                data.setDataPosition(position);
+            }
+
+            status_t status = remote()->transact(SET_USERID_DEVICE_AFFINITY, data, &reply);
+            if (status == NO_ERROR) {
+                status = (status_t)reply.readInt32();
+            }
+            return status;
+        }
+
+        virtual status_t removeUserIdDeviceAffinities(int userId) {
+            Parcel data, reply;
+            data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+            data.writeInt32((int32_t) userId);
+
+            status_t status =
+                remote()->transact(REMOVE_USERID_DEVICE_AFFINITY, data, &reply);
+            if (status == NO_ERROR) {
+                status = (status_t) reply.readInt32();
+            }
+            return status;
+        }
+
     virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
     {
         Parcel data, reply;
@@ -1284,6 +1372,129 @@
         }
         return static_cast<status_t>(reply.readInt32());
     }
+
+    virtual bool isCallScreenModeSupported()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        status_t status = remote()->transact(IS_CALL_SCREEN_MODE_SUPPORTED, data, &reply);
+        if (status != NO_ERROR) {
+            return false;
+        }
+        return reply.readBool();
+    }
+
+    virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+            const AudioDeviceTypeAddr &device)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeUint32(static_cast<uint32_t>(strategy));
+        status_t status = device.writeToParcel(&data);
+        if (status != NO_ERROR) {
+            return BAD_VALUE;
+        }
+        status = remote()->transact(SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+                data, &reply);
+        if (status != NO_ERROR) {
+           return status;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
+
+    virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeUint32(static_cast<uint32_t>(strategy));
+        status_t status = remote()->transact(REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+                data, &reply);
+        if (status != NO_ERROR) {
+           return status;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
+
+    virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeUint32(static_cast<uint32_t>(strategy));
+        status_t status = remote()->transact(GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
+                data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = device.readFromParcel(&reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
+
+    virtual status_t getDevicesForAttributes(const AudioAttributes &aa,
+            AudioDeviceTypeAddrVector *devices) const
+    {
+        if (devices == nullptr) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        status_t status = aa.writeToParcel(&data);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = remote()->transact(GET_DEVICES_FOR_ATTRIBUTES, data, &reply);
+        if (status != NO_ERROR) {
+            // transaction failed, return error
+            return status;
+        }
+        status = static_cast<status_t>(reply.readInt32());
+        if (status != NO_ERROR) {
+            // APM method call failed, return error
+            return status;
+        }
+
+        const size_t numberOfDevices = (size_t)reply.readInt32();
+        for (size_t i = 0; i < numberOfDevices; i++) {
+            AudioDeviceTypeAddr device;
+            if (device.readFromParcel((Parcel*)&reply) == NO_ERROR) {
+                devices->push_back(device);
+            } else {
+                return FAILED_TRANSACTION;
+            }
+        }
+        return NO_ERROR;
+    }
+
+    virtual void onNewAudioModulesAvailable()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        remote()->transact(AUDIO_MODULES_UPDATED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    status_t registerSoundTriggerCaptureStateListener(
+            const sp<media::ICaptureStateListener>& listener,
+            bool* result) override {
+        Parcel data, reply;
+        status_t status;
+        status =
+            data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        if (status != NO_ERROR) return status;
+        status = data.writeStrongBinder(IInterface::asBinder(listener));
+        if (status != NO_ERROR) return status;
+        status =
+            remote()->transact(REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER,
+                               data,
+                               &reply,
+                               0);
+        if (status != NO_ERROR) return status;
+        status = reply.readBool(result);
+        if (status != NO_ERROR) return status;
+        return NO_ERROR;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1307,8 +1518,6 @@
         case UNREGISTER_EFFECT:
         case SET_EFFECT_ENABLED:
         case GET_OUTPUT_FOR_ATTR:
-        case ACQUIRE_SOUNDTRIGGER_SESSION:
-        case RELEASE_SOUNDTRIGGER_SESSION:
         case MOVE_EFFECTS_TO_IO:
             ALOGW("%s: transaction %d received from PID %d",
                   __func__, code, IPCThreadState::self()->getCallingPid());
@@ -1343,11 +1552,24 @@
         case SET_A11Y_SERVICES_UIDS:
         case SET_UID_DEVICE_AFFINITY:
         case REMOVE_UID_DEVICE_AFFINITY:
+        case SET_USERID_DEVICE_AFFINITY:
+        case REMOVE_USERID_DEVICE_AFFINITY:
         case GET_OFFLOAD_FORMATS_A2DP:
         case LIST_AUDIO_VOLUME_GROUPS:
         case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
+        case ACQUIRE_SOUNDTRIGGER_SESSION:
+        case RELEASE_SOUNDTRIGGER_SESSION:
         case SET_RTT_ENABLED:
-        case SET_ALLOWED_CAPTURE_POLICY: {
+        case IS_CALL_SCREEN_MODE_SUPPORTED:
+        case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
+        case SET_SUPPORTED_SYSTEM_USAGES:
+        case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
+        case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
+        case GET_DEVICES_FOR_ATTRIBUTES:
+        case SET_ALLOWED_CAPTURE_POLICY:
+        case AUDIO_MODULES_UPDATED:
+        case SET_CURRENT_IME_UID:
+        case REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1424,7 +1646,8 @@
         case SET_PHONE_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             reply->writeInt32(static_cast <uint32_t>(setPhoneState(
-                    (audio_mode_t) data.readInt32())));
+                    (audio_mode_t) data.readInt32(),
+                    (uid_t) data.readInt32())));
             return NO_ERROR;
         } break;
 
@@ -1960,8 +2183,6 @@
 
         case ACQUIRE_SOUNDTRIGGER_SESSION: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
-                    data.readStrongBinder());
             audio_session_t session = AUDIO_SESSION_NONE;
             audio_io_handle_t ioHandle = AUDIO_IO_HANDLE_NONE;
             audio_devices_t device = AUDIO_DEVICE_NONE;
@@ -1977,8 +2198,6 @@
 
         case RELEASE_SOUNDTRIGGER_SESSION: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
-                    data.readStrongBinder());
             audio_session_t session = (audio_session_t)data.readInt32();
             status_t status = releaseSoundTriggerSession(session);
             reply->writeInt32(status);
@@ -2238,7 +2457,6 @@
             reply->writeBool(isSupported);
             return NO_ERROR;
         }
-
         case SET_UID_DEVICE_AFFINITY: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             const uid_t uid = (uid_t) data.readInt32();
@@ -2263,6 +2481,30 @@
             return NO_ERROR;
         }
 
+        case SET_USERID_DEVICE_AFFINITY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            const int userId = (int) data.readInt32();
+            Vector<AudioDeviceTypeAddr> devices;
+            size_t size = (size_t)data.readInt32();
+            for (size_t i = 0; i < size; i++) {
+                AudioDeviceTypeAddr device;
+                if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+                    devices.add(device);
+                }
+            }
+            status_t status = setUserIdDeviceAffinities(userId, devices);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
+        case REMOVE_USERID_DEVICE_AFFINITY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            const int userId = (int) data.readInt32();
+            status_t status = removeUserIdDeviceAffinities(userId);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
         case LIST_AUDIO_PRODUCT_STRATEGIES: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             AudioProductStrategyVector strategies;
@@ -2343,16 +2585,46 @@
             if (status != NO_ERROR) {
                 return status;
             }
+
             volume_group_t group;
             status = getVolumeGroupFromAudioAttributes(attributes, group);
-            reply->writeInt32(status);
             if (status != NO_ERROR) {
                 return NO_ERROR;
             }
+
+            reply->writeInt32(status);
             reply->writeUint32(static_cast<int>(group));
             return NO_ERROR;
         }
 
+        case SET_SUPPORTED_SYSTEM_USAGES: {
+             CHECK_INTERFACE(IAudioPolicyService, data, reply);
+             std::vector<audio_usage_t> systemUsages;
+
+             int32_t size;
+             status_t status = data.readInt32(&size);
+             if (status != NO_ERROR) {
+                 return status;
+             }
+             if (size > MAX_ITEMS_PER_LIST) {
+                 size = MAX_ITEMS_PER_LIST;
+             }
+
+             for (int32_t i = 0; i < size; i++) {
+                 int32_t systemUsageInt;
+                 status = data.readInt32(&systemUsageInt);
+                 if (status != NO_ERROR) {
+                     return status;
+                 }
+
+                 audio_usage_t systemUsage = static_cast<audio_usage_t>(systemUsageInt);
+                 systemUsages.push_back(systemUsage);
+             }
+             status = setSupportedSystemUsages(systemUsages);
+             reply->writeInt32(static_cast <int32_t>(status));
+             return NO_ERROR;
+        }
+
         case SET_ALLOWED_CAPTURE_POLICY: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             uid_t uid = data.readInt32();
@@ -2370,6 +2642,121 @@
             return NO_ERROR;
         }
 
+        case IS_CALL_SCREEN_MODE_SUPPORTED: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            bool isAvailable = isCallScreenModeSupported();
+            reply->writeBool(isAvailable);
+            return NO_ERROR;
+        }
+
+        case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            product_strategy_t strategy = (product_strategy_t) data.readUint32();
+            AudioDeviceTypeAddr device;
+            status_t status = device.readFromParcel((Parcel*)&data);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = setPreferredDeviceForStrategy(strategy, device);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
+        case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            product_strategy_t strategy = (product_strategy_t) data.readUint32();
+            status_t status = removePreferredDeviceForStrategy(strategy);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
+        case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            product_strategy_t strategy = (product_strategy_t) data.readUint32();
+            AudioDeviceTypeAddr device;
+            status_t status = getPreferredDeviceForStrategy(strategy, device);
+            status_t marshall_status = device.writeToParcel(reply);
+            if (marshall_status != NO_ERROR) {
+                return marshall_status;
+            }
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
+        case GET_DEVICES_FOR_ATTRIBUTES: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioAttributes attributes;
+            status_t status = attributes.readFromParcel(&data);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            AudioDeviceTypeAddrVector devices;
+            status = getDevicesForAttributes(attributes.getAttributes(), &devices);
+            // reply data formatted as:
+            //  - (int32) method call result from APM
+            //  - (int32) number of devices (n) if method call returned NO_ERROR
+            //  - n AudioDeviceTypeAddr         if method call returned NO_ERROR
+            reply->writeInt32(status);
+            if (status != NO_ERROR) {
+                return NO_ERROR;
+            }
+            status = reply->writeInt32(devices.size());
+            if (status != NO_ERROR) {
+                return status;
+            }
+            for (const auto& device : devices) {
+                status = device.writeToParcel(reply);
+                if (status != NO_ERROR) {
+                    return status;
+                }
+            }
+
+            return NO_ERROR;
+        }
+
+        case AUDIO_MODULES_UPDATED: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            onNewAudioModulesAvailable();
+            return NO_ERROR;
+        } break;
+
+        case SET_CURRENT_IME_UID: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int32_t uid;
+            status_t status = data.readInt32(&uid);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = setCurrentImeUid(uid);
+            reply->writeInt32(static_cast <int32_t>(status));
+            return NO_ERROR;
+        }
+
+        case REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            sp<IBinder> binder = data.readStrongBinder();
+            if (binder == nullptr) {
+                return BAD_VALUE;
+            }
+            sp<ICaptureStateListener>
+                listener = interface_cast<ICaptureStateListener>(
+                binder);
+            if (listener == nullptr) {
+                return BAD_VALUE;
+            }
+            bool ret;
+            status_t status =
+                registerSoundTriggerCaptureStateListener(listener, &ret);
+            LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+                                "Server returned unexpected status code: %d",
+                                status);
+            status = reply->writeBool(ret);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/IAudioTrack.cpp b/media/libaudioclient/IAudioTrack.cpp
index 83a568a..6219e7a 100644
--- a/media/libaudioclient/IAudioTrack.cpp
+++ b/media/libaudioclient/IAudioTrack.cpp
@@ -62,7 +62,7 @@
         status_t status = remote()->transact(GET_CBLK, data, &reply);
         if (status == NO_ERROR) {
             cblk = interface_cast<IMemory>(reply.readStrongBinder());
-            if (cblk != 0 && cblk->pointer() == NULL) {
+            if (cblk != 0 && cblk->unsecurePointer() == NULL) {
                 cblk.clear();
             }
         }
diff --git a/media/libaudioclient/IEffect.cpp b/media/libaudioclient/IEffect.cpp
index ce72dae..5d47dff 100644
--- a/media/libaudioclient/IEffect.cpp
+++ b/media/libaudioclient/IEffect.cpp
@@ -122,7 +122,7 @@
         status_t status = remote()->transact(GET_CBLK, data, &reply);
         if (status == NO_ERROR) {
             cblk = interface_cast<IMemory>(reply.readStrongBinder());
-            if (cblk != 0 && cblk->pointer() == NULL) {
+            if (cblk != 0 && cblk->unsecurePointer() == NULL) {
                 cblk.clear();
             }
         }
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 536b00d..050ad65 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1262,7 +1262,9 @@
             AUDIO_UID_INVALID,
             -1,
             &attr);
-
+    // Set caller name so it can be logged in destructor.
+    // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_TONEGENERATOR
+    mpAudioTrack->setCallerName("tonegenerator");
     if (status != NO_ERROR) {
         ALOGE("AudioTrack(%p) set failed with error %d", mpAudioTrack.get(), status);
         mpAudioTrack.clear();
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl b/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl
new file mode 100644
index 0000000..21553b5
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/IAudioTrackCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * @hide
+ */
+interface IAudioTrackCallback {
+    oneway void onCodecFormatChanged(in byte[] audioMetadata);
+}
diff --git a/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl b/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl
new file mode 100644
index 0000000..8502282
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/ICaptureStateListener.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+interface ICaptureStateListener {
+    void setCaptureState(boolean active);
+}
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/AudioAttributes.h
index 0a35e9e..001c629 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/AudioAttributes.h
@@ -28,7 +28,7 @@
 {
 public:
     AudioAttributes() = default;
-    AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {}
+    AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {} // NOLINT
     AudioAttributes(volume_group_t groupId,
                     audio_stream_type_t stream,
                     const audio_attributes_t &attributes) :
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index 6bd4137..cb76252 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -362,17 +362,25 @@
      *      (AudioTrack or MediaPLayer) within the same audio session.
      * io:  HAL audio output or input stream to which this effect must be attached. Leave at 0 for
      *      automatic output selection by AudioFlinger.
+     * device: An audio device descriptor. Only used when "sessionID" is AUDIO_SESSION_DEVICE.
+     *         Specifies the audio device type and address the effect must be attached to.
+     *         If "sessionID" is AUDIO_SESSION_DEVICE then "io" must be AUDIO_IO_HANDLE_NONE.
+     * probe: true if created in a degraded mode to only verify if effect creation is possible.
+     *        In this mode, no IEffect interface to AudioFlinger is created and all actions
+     *        besides getters implemented in client AudioEffect object are no ops
+     *        after effect creation.
      */
 
     AudioEffect(const effect_uuid_t *type,
                 const String16& opPackageName,
                 const effect_uuid_t *uuid = NULL,
-                  int32_t priority = 0,
-                  effect_callback_t cbf = NULL,
-                  void* user = NULL,
-                  audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
-                  audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
-                  );
+                int32_t priority = 0,
+                effect_callback_t cbf = NULL,
+                void* user = NULL,
+                audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                const AudioDeviceTypeAddr& device = {},
+                bool probe = false);
 
     /* Constructor.
      *      Same as above but with type and uuid specified by character strings
@@ -384,8 +392,9 @@
                     effect_callback_t cbf = NULL,
                     void* user = NULL,
                     audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
-                    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
-                    );
+                    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                    const AudioDeviceTypeAddr& device = {},
+                    bool probe = false);
 
     /* Terminates the AudioEffect and unregisters it from AudioFlinger.
      * The effect engine is also destroyed if this AudioEffect was the last controlling
@@ -406,8 +415,9 @@
                             effect_callback_t cbf = NULL,
                             void* user = NULL,
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
-                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
-                            );
+                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                            const AudioDeviceTypeAddr& device = {},
+                            bool probe = false);
 
     /* Result of constructing the AudioEffect. This must be checked
      * before using any AudioEffect API.
@@ -541,6 +551,8 @@
      audio_session_t         mSessionId;         // audio session ID
      int32_t                 mPriority;          // priority for effect control
      status_t                mStatus;            // effect status
+     bool                    mProbe;             // effect created in probe mode: all commands
+                                                 // are no ops because mIEffect is NULL
      effect_callback_t       mCbf;               // callback function for status, control and
                                                  // parameter changes notifications
      void*                   mUserData;          // client context for callback function
@@ -633,7 +645,8 @@
     sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
     sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
     effect_param_cblk_t*    mCblk;              // control block for deferred parameter setting
-    pid_t                   mClientPid;
+    pid_t                   mClientPid = (pid_t)-1;
+    uid_t                   mClientUid = (uid_t)-1;
 };
 
 
diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h
deleted file mode 100644
index 783eef3..0000000
--- a/media/libaudioclient/include/media/AudioMixer.h
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
-**
-** Copyright 2007, 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 ANDROID_AUDIO_MIXER_H
-#define ANDROID_AUDIO_MIXER_H
-
-#include <map>
-#include <pthread.h>
-#include <sstream>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unordered_map>
-#include <vector>
-
-#include <android/os/IExternalVibratorService.h>
-#include <media/AudioBufferProvider.h>
-#include <media/AudioResampler.h>
-#include <media/AudioResamplerPublic.h>
-#include <media/BufferProviders.h>
-#include <system/audio.h>
-#include <utils/Compat.h>
-#include <utils/threads.h>
-
-// FIXME This is actually unity gain, which might not be max in future, expressed in U.12
-#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
-
-// This must match frameworks/av/services/audioflinger/Configuration.h
-#define FLOAT_AUX
-
-namespace android {
-
-namespace NBLog {
-class Writer;
-}   // namespace NBLog
-
-// ----------------------------------------------------------------------------
-
-class AudioMixer
-{
-public:
-    // Do not change these unless underlying code changes.
-    // This mixer has a hard-coded upper limit of 8 channels for output.
-    static constexpr uint32_t MAX_NUM_CHANNELS = FCC_8;
-    static constexpr uint32_t MAX_NUM_VOLUMES = FCC_2; // stereo volume only
-    // maximum number of channels supported for the content
-    static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;
-
-    static const uint16_t UNITY_GAIN_INT = 0x1000;
-    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
-
-    enum { // names
-        // setParameter targets
-        TRACK           = 0x3000,
-        RESAMPLE        = 0x3001,
-        RAMP_VOLUME     = 0x3002, // ramp to new volume
-        VOLUME          = 0x3003, // don't ramp
-        TIMESTRETCH     = 0x3004,
-
-        // set Parameter names
-        // for target TRACK
-        CHANNEL_MASK    = 0x4000,
-        FORMAT          = 0x4001,
-        MAIN_BUFFER     = 0x4002,
-        AUX_BUFFER      = 0x4003,
-        DOWNMIX_TYPE    = 0X4004,
-        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
-        // for haptic
-        HAPTIC_ENABLED  = 0x4007, // Set haptic data from this track should be played or not.
-        HAPTIC_INTENSITY = 0x4008, // Set the intensity to play haptic data.
-        // for target RESAMPLE
-        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
-                                  // parameter 'value' is the new sample rate in Hz.
-                                  // Only creates a sample rate converter the first time that
-                                  // the track sample rate is different from the mix sample rate.
-                                  // If the new sample rate is the same as the mix sample rate,
-                                  // and a sample rate converter already exists,
-                                  // then the sample rate converter remains present but is a no-op.
-        RESET           = 0x4101, // Reset sample rate converter without changing sample rate.
-                                  // This clears out the resampler's input buffer.
-        REMOVE          = 0x4102, // Remove the sample rate converter on this track name;
-                                  // the track is restored to the mix sample rate.
-        // for target RAMP_VOLUME and VOLUME (8 channels max)
-        // FIXME use float for these 3 to improve the dynamic range
-        VOLUME0         = 0x4200,
-        VOLUME1         = 0x4201,
-        AUXLEVEL        = 0x4210,
-        // for target TIMESTRETCH
-        PLAYBACK_RATE   = 0x4300, // Configure timestretch on this track name;
-                                  // parameter 'value' is a pointer to the new playback rate.
-    };
-
-    typedef enum { // Haptic intensity, should keep consistent with VibratorService
-        HAPTIC_SCALE_MUTE = os::IExternalVibratorService::SCALE_MUTE,
-        HAPTIC_SCALE_VERY_LOW = os::IExternalVibratorService::SCALE_VERY_LOW,
-        HAPTIC_SCALE_LOW = os::IExternalVibratorService::SCALE_LOW,
-        HAPTIC_SCALE_NONE = os::IExternalVibratorService::SCALE_NONE,
-        HAPTIC_SCALE_HIGH = os::IExternalVibratorService::SCALE_HIGH,
-        HAPTIC_SCALE_VERY_HIGH = os::IExternalVibratorService::SCALE_VERY_HIGH,
-    } haptic_intensity_t;
-    static constexpr float HAPTIC_SCALE_VERY_LOW_RATIO = 2.0f / 3.0f;
-    static constexpr float HAPTIC_SCALE_LOW_RATIO = 3.0f / 4.0f;
-    static const constexpr float HAPTIC_MAX_AMPLITUDE_FLOAT = 1.0f;
-
-    static inline bool isValidHapticIntensity(haptic_intensity_t hapticIntensity) {
-        switch (hapticIntensity) {
-        case HAPTIC_SCALE_MUTE:
-        case HAPTIC_SCALE_VERY_LOW:
-        case HAPTIC_SCALE_LOW:
-        case HAPTIC_SCALE_NONE:
-        case HAPTIC_SCALE_HIGH:
-        case HAPTIC_SCALE_VERY_HIGH:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    AudioMixer(size_t frameCount, uint32_t sampleRate)
-        : mSampleRate(sampleRate)
-        , mFrameCount(frameCount) {
-        pthread_once(&sOnceControl, &sInitRoutine);
-    }
-
-    // Create a new track in the mixer.
-    //
-    // \param name        a unique user-provided integer associated with the track.
-    //                    If name already exists, the function will abort.
-    // \param channelMask output channel mask.
-    // \param format      PCM format
-    // \param sessionId   Session id for the track. Tracks with the same
-    //                    session id will be submixed together.
-    //
-    // \return OK        on success.
-    //         BAD_VALUE if the format does not satisfy isValidFormat()
-    //                   or the channelMask does not satisfy isValidChannelMask().
-    status_t    create(
-            int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId);
-
-    bool        exists(int name) const {
-        return mTracks.count(name) > 0;
-    }
-
-    // Free an allocated track by name.
-    void        destroy(int name);
-
-    // Enable or disable an allocated track by name
-    void        enable(int name);
-    void        disable(int name);
-
-    void        setParameter(int name, int target, int param, void *value);
-
-    void        setBufferProvider(int name, AudioBufferProvider* bufferProvider);
-
-    void        process() {
-        for (const auto &pair : mTracks) {
-            // Clear contracted buffer before processing if contracted channels are saved
-            const std::shared_ptr<Track> &t = pair.second;
-            if (t->mKeepContractedChannels) {
-                t->clearContractedBuffer();
-            }
-        }
-        (this->*mHook)();
-        processHapticData();
-    }
-
-    size_t      getUnreleasedFrames(int name) const;
-
-    std::string trackNames() const {
-        std::stringstream ss;
-        for (const auto &pair : mTracks) {
-            ss << pair.first << " ";
-        }
-        return ss.str();
-    }
-
-    void        setNBLogWriter(NBLog::Writer *logWriter) {
-        mNBLogWriter = logWriter;
-    }
-
-    static inline bool isValidFormat(audio_format_t format) {
-        switch (format) {
-        case AUDIO_FORMAT_PCM_8_BIT:
-        case AUDIO_FORMAT_PCM_16_BIT:
-        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
-        case AUDIO_FORMAT_PCM_32_BIT:
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    static inline bool isValidChannelMask(audio_channel_mask_t channelMask) {
-        return audio_channel_mask_is_valid(channelMask); // the RemixBufferProvider is flexible.
-    }
-
-private:
-
-    /* For multi-format functions (calls template functions
-     * in AudioMixerOps.h).  The template parameters are as follows:
-     *
-     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
-     *   USEFLOATVOL (set to true if float volume is used)
-     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
-     *   TO: int32_t (Q4.27) or float
-     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
-     *   TA: int32_t (Q4.27)
-     */
-
-    enum {
-        // FIXME this representation permits up to 8 channels
-        NEEDS_CHANNEL_COUNT__MASK   = 0x00000007,
-    };
-
-    enum {
-        NEEDS_CHANNEL_1             = 0x00000000,   // mono
-        NEEDS_CHANNEL_2             = 0x00000001,   // stereo
-
-        // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT
-
-        NEEDS_MUTE                  = 0x00000100,
-        NEEDS_RESAMPLE              = 0x00001000,
-        NEEDS_AUX                   = 0x00010000,
-    };
-
-    // hook types
-    enum {
-        PROCESSTYPE_NORESAMPLEONETRACK, // others set elsewhere
-    };
-
-    enum {
-        TRACKTYPE_NOP,
-        TRACKTYPE_RESAMPLE,
-        TRACKTYPE_NORESAMPLE,
-        TRACKTYPE_NORESAMPLEMONO,
-    };
-
-    // process hook functionality
-    using process_hook_t = void(AudioMixer::*)();
-
-    struct Track;
-    using hook_t = void(Track::*)(int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
-
-    struct Track {
-        Track()
-            : bufferProvider(nullptr)
-        {
-            // TODO: move additional initialization here.
-        }
-
-        ~Track()
-        {
-            // bufferProvider, mInputBufferProvider need not be deleted.
-            mResampler.reset(nullptr);
-            // Ensure the order of destruction of buffer providers as they
-            // release the upstream provider in the destructor.
-            mTimestretchBufferProvider.reset(nullptr);
-            mPostDownmixReformatBufferProvider.reset(nullptr);
-            mDownmixerBufferProvider.reset(nullptr);
-            mReformatBufferProvider.reset(nullptr);
-            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
-            mAdjustChannelsBufferProvider.reset(nullptr);
-        }
-
-        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
-        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
-        bool        doesResample() const { return mResampler.get() != nullptr; }
-        void        resetResampler() { if (mResampler.get() != nullptr) mResampler->reset(); }
-        void        adjustVolumeRamp(bool aux, bool useFloat = false);
-        size_t      getUnreleasedFrames() const { return mResampler.get() != nullptr ?
-                                                    mResampler->getUnreleasedFrames() : 0; };
-
-        status_t    prepareForDownmix();
-        void        unprepareForDownmix();
-        status_t    prepareForReformat();
-        void        unprepareForReformat();
-        status_t    prepareForAdjustChannels();
-        void        unprepareForAdjustChannels();
-        status_t    prepareForAdjustChannelsNonDestructive(size_t frames);
-        void        unprepareForAdjustChannelsNonDestructive();
-        void        clearContractedBuffer();
-        bool        setPlaybackRate(const AudioPlaybackRate &playbackRate);
-        void        reconfigureBufferProviders();
-
-        static hook_t getTrackHook(int trackType, uint32_t channelCount,
-                audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
-
-        void track__nop(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-
-        template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
-            typename TO, typename TI, typename TA>
-        void volumeMix(TO *out, size_t outFrames, const TI *in, TA *aux, bool ramp);
-
-        uint32_t    needs;
-
-        // TODO: Eventually remove legacy integer volume settings
-        union {
-        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
-        int32_t     volumeRL;
-        };
-
-        int32_t     prevVolume[MAX_NUM_VOLUMES];
-        int32_t     volumeInc[MAX_NUM_VOLUMES];
-        int32_t     auxInc;
-        int32_t     prevAuxLevel;
-        int16_t     auxLevel;       // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
-
-        uint16_t    frameCount;
-
-        uint8_t     channelCount;   // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
-        uint8_t     unused_padding; // formerly format, was always 16
-        uint16_t    enabled;        // actually bool
-        audio_channel_mask_t channelMask;
-
-        // actual buffer provider used by the track hooks, see DownmixerBufferProvider below
-        //  for how the Track buffer provider is wrapped by another one when dowmixing is required
-        AudioBufferProvider*                bufferProvider;
-
-        mutable AudioBufferProvider::Buffer buffer; // 8 bytes
-
-        hook_t      hook;
-        const void  *mIn;             // current location in buffer
-
-        std::unique_ptr<AudioResampler> mResampler;
-        uint32_t            sampleRate;
-        int32_t*           mainBuffer;
-        int32_t*           auxBuffer;
-
-        /* Buffer providers are constructed to translate the track input data as needed.
-         *
-         * TODO: perhaps make a single PlaybackConverterProvider class to move
-         * all pre-mixer track buffer conversions outside the AudioMixer class.
-         *
-         * 1) mInputBufferProvider: The AudioTrack buffer provider.
-         * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
-         *    channel format to another. Expanded channels are filled with zeros and put at the end
-         *    of each audio frame. Contracted channels are copied to the end of the buffer.
-         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
-         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
-         *    data. Contracted channels could be written to given buffer.
-         * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
-         *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
-         *    requires reformat. For example, it may convert floating point input to
-         *    PCM_16_bit if that's required by the downmixer.
-         * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
-         *    the number of channels required by the mixer sink.
-         * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
-         *    the downmixer requirements to the mixer engine input requirements.
-         * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
-         */
-        AudioBufferProvider*     mInputBufferProvider;    // externally provided buffer provider.
-        // TODO: combine mAdjustChannelsBufferProvider and
-        // mContractChannelsNonDestructiveBufferProvider
-        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
-        std::unique_ptr<PassthruBufferProvider> mTimestretchBufferProvider;
-
-        int32_t     sessionId;
-
-        audio_format_t mMixerFormat;     // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-        audio_format_t mFormat;          // input track format
-        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
-                                         // each track must be converted to this format.
-        audio_format_t mDownmixRequiresFormat;  // required downmixer format
-                                                // AUDIO_FORMAT_PCM_16_BIT if 16 bit necessary
-                                                // AUDIO_FORMAT_INVALID if no required format
-
-        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
-        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
-        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment
-
-        float          mAuxLevel;                     // floating point set aux level
-        float          mPrevAuxLevel;                 // floating point prev aux level
-        float          mAuxInc;                       // floating point aux increment
-
-        audio_channel_mask_t mMixerChannelMask;
-        uint32_t             mMixerChannelCount;
-
-        AudioPlaybackRate    mPlaybackRate;
-
-        // Haptic
-        bool                 mHapticPlaybackEnabled;
-        haptic_intensity_t   mHapticIntensity;
-        audio_channel_mask_t mHapticChannelMask;
-        uint32_t             mHapticChannelCount;
-        audio_channel_mask_t mMixerHapticChannelMask;
-        uint32_t             mMixerHapticChannelCount;
-        uint32_t             mAdjustInChannelCount;
-        uint32_t             mAdjustOutChannelCount;
-        uint32_t             mAdjustNonDestructiveInChannelCount;
-        uint32_t             mAdjustNonDestructiveOutChannelCount;
-        bool                 mKeepContractedChannels;
-
-        float getHapticScaleGamma() const {
-        // Need to keep consistent with the value in VibratorService.
-        switch (mHapticIntensity) {
-        case HAPTIC_SCALE_VERY_LOW:
-            return 2.0f;
-        case HAPTIC_SCALE_LOW:
-            return 1.5f;
-        case HAPTIC_SCALE_HIGH:
-            return 0.5f;
-        case HAPTIC_SCALE_VERY_HIGH:
-            return 0.25f;
-        default:
-            return 1.0f;
-        }
-        }
-
-        float getHapticMaxAmplitudeRatio() const {
-        // Need to keep consistent with the value in VibratorService.
-        switch (mHapticIntensity) {
-        case HAPTIC_SCALE_VERY_LOW:
-            return HAPTIC_SCALE_VERY_LOW_RATIO;
-        case HAPTIC_SCALE_LOW:
-            return HAPTIC_SCALE_LOW_RATIO;
-        case HAPTIC_SCALE_NONE:
-        case HAPTIC_SCALE_HIGH:
-        case HAPTIC_SCALE_VERY_HIGH:
-            return 1.0f;
-        default:
-            return 0.0f;
-        }
-        }
-
-    private:
-        // hooks
-        void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-        void track__16BitsStereo(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-        void track__16BitsMono(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
-
-        void volumeRampStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
-        void volumeStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
-
-        // multi-format track hooks
-        template <int MIXTYPE, typename TO, typename TI, typename TA>
-        void track__Resample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
-        template <int MIXTYPE, typename TO, typename TI, typename TA>
-        void track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
-    };
-
-    // TODO: remove BLOCKSIZE unit of processing - it isn't needed anymore.
-    static constexpr int BLOCKSIZE = 16;
-
-    bool setChannelMasks(int name,
-            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);
-
-    // Called when track info changes and a new process hook should be determined.
-    void invalidate() {
-        mHook = &AudioMixer::process__validate;
-    }
-
-    void process__validate();
-    void process__nop();
-    void process__genericNoResampling();
-    void process__genericResampling();
-    void process__oneTrack16BitsStereoNoResampling();
-
-    template <int MIXTYPE, typename TO, typename TI, typename TA>
-    void process__noResampleOneTrack();
-
-    void processHapticData();
-
-    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
-            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
-
-    static void convertMixerFormat(void *out, audio_format_t mixerOutFormat,
-            void *in, audio_format_t mixerInFormat, size_t sampleCount);
-
-    static void sInitRoutine();
-
-    // initialization constants
-    const uint32_t mSampleRate;
-    const size_t mFrameCount;
-
-    NBLog::Writer *mNBLogWriter = nullptr;   // associated NBLog::Writer
-
-    process_hook_t mHook = &AudioMixer::process__nop;   // one of process__*, never nullptr
-
-    // the size of the type (int32_t) should be the largest of all types supported
-    // by the mixer.
-    std::unique_ptr<int32_t[]> mOutputTemp;
-    std::unique_ptr<int32_t[]> mResampleTemp;
-
-    // track names grouped by main buffer, in no particular order of main buffer.
-    // however names for a particular main buffer are in order (by construction).
-    std::unordered_map<void * /* mainBuffer */, std::vector<int /* name */>> mGroups;
-
-    // track names that are enabled, in increasing order (by construction).
-    std::vector<int /* name */> mEnabled;
-
-    // track smart pointers, by name, in increasing order of name.
-    std::map<int /* name */, std::shared_ptr<Track>> mTracks;
-
-    static pthread_once_t sOnceControl; // initialized in constructor by first new
-};
-
-// ----------------------------------------------------------------------------
-} // namespace android
-
-#endif // ANDROID_AUDIO_MIXER_H
diff --git a/media/libaudioclient/include/media/AudioParameter.h b/media/libaudioclient/include/media/AudioParameter.h
deleted file mode 100644
index 24837e3..0000000
--- a/media/libaudioclient/include/media/AudioParameter.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2008-2011 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 ANDROID_AUDIOPARAMETER_H_
-#define ANDROID_AUDIOPARAMETER_H_
-
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class AudioParameter {
-
-public:
-    AudioParameter() {}
-    AudioParameter(const String8& keyValuePairs);
-    virtual ~AudioParameter();
-
-    // reserved parameter keys for changing standard parameters with setParameters() function.
-    // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
-    // configuration changes and act accordingly.
-    //  keyRouting: to change audio routing, value is an int in audio_devices_t
-    //  keySamplingRate: to change sampling rate routing, value is an int
-    //  keyFormat: to change audio format, value is an int in audio_format_t
-    //  keyChannels: to change audio channel configuration, value is an int in audio_channels_t
-    //  keyFrameCount: to change audio output frame count, value is an int
-    //  keyInputSource: to change audio input source, value is an int in audio_source_t
-    //     (defined in media/mediarecorder.h)
-    //  keyScreenState: either "on" or "off"
-    static const char * const keyRouting;
-    static const char * const keySamplingRate;
-    static const char * const keyFormat;
-    static const char * const keyChannels;
-    static const char * const keyFrameCount;
-    static const char * const keyInputSource;
-    static const char * const keyScreenState;
-
-    //  keyBtNrec: BT SCO Noise Reduction + Echo Cancellation parameters
-    //  keyHwAvSync: get HW synchronization source identifier from a device
-    //  keyMonoOutput: Enable mono audio playback
-    //  keyStreamHwAvSync: set HW synchronization source identifier on a stream
-    static const char * const keyBtNrec;
-    static const char * const keyHwAvSync;
-    static const char * const keyMonoOutput;
-    static const char * const keyStreamHwAvSync;
-
-    //  keys for presentation selection
-    //  keyPresentationId: Audio presentation identifier
-    //  keyProgramId: Audio presentation program identifier
-    static const char * const keyPresentationId;
-    static const char * const keyProgramId;
-
-    //  keyAudioLanguagePreferred: Preferred audio language
-    static const char * const keyAudioLanguagePreferred;
-
-    //  keyStreamConnect / Disconnect: value is an int in audio_devices_t
-    static const char * const keyStreamConnect;
-    static const char * const keyStreamDisconnect;
-
-    // For querying stream capabilities. All the returned values are lists.
-    //   keyStreamSupportedFormats: audio_format_t
-    //   keyStreamSupportedChannels: audio_channel_mask_t
-    //   keyStreamSupportedSamplingRates: sampling rate values
-    static const char * const keyStreamSupportedFormats;
-    static const char * const keyStreamSupportedChannels;
-    static const char * const keyStreamSupportedSamplingRates;
-
-    static const char * const valueOn;
-    static const char * const valueOff;
-
-    static const char * const valueListSeparator;
-
-    // keyReconfigA2dp: Ask HwModule to reconfigure A2DP offloaded codec
-    // keyReconfigA2dpSupported: Query if HwModule supports A2DP offload codec config
-    static const char * const keyReconfigA2dp;
-    static const char * const keyReconfigA2dpSupported;
-
-    String8 toString() const { return toStringImpl(true); }
-    String8 keysToString() const { return toStringImpl(false); }
-
-    status_t add(const String8& key, const String8& value);
-    status_t addInt(const String8& key, const int value);
-    status_t addKey(const String8& key);
-    status_t addFloat(const String8& key, const float value);
-
-    status_t remove(const String8& key);
-
-    status_t get(const String8& key, String8& value) const;
-    status_t getInt(const String8& key, int& value) const;
-    status_t getFloat(const String8& key, float& value) const;
-    status_t getAt(size_t index, String8& key) const;
-    status_t getAt(size_t index, String8& key, String8& value) const;
-
-    size_t size() const { return mParameters.size(); }
-
-private:
-    String8 mKeyValuePairs;
-    KeyedVector <String8, String8> mParameters;
-
-    String8 toStringImpl(bool useValues) const;
-};
-
-};  // namespace android
-
-#endif  /*ANDROID_AUDIOPARAMETER_H_*/
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index ef39fd1..00fe278 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -18,11 +18,13 @@
 #ifndef ANDROID_AUDIO_POLICY_H
 #define ANDROID_AUDIO_POLICY_H
 
+#include <binder/Parcel.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
-#include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
+#include <cutils/multiuser.h>
 
 namespace android {
 
@@ -31,10 +33,12 @@
 #define RULE_MATCH_ATTRIBUTE_USAGE           0x1
 #define RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET (0x1 << 1)
 #define RULE_MATCH_UID                      (0x1 << 2)
+#define RULE_MATCH_USERID                   (0x1 << 3)
 #define RULE_EXCLUDE_ATTRIBUTE_USAGE  (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_USAGE)
 #define RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET \
                                       (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)
 #define RULE_EXCLUDE_UID              (RULE_EXCLUSION_MASK|RULE_MATCH_UID)
+#define RULE_EXCLUDE_USERID           (RULE_EXCLUSION_MASK|RULE_MATCH_USERID)
 
 #define MIX_TYPE_INVALID (-1)
 #define MIX_TYPE_PLAYERS 0
@@ -60,19 +64,6 @@
 #define MAX_MIXES_PER_POLICY 10
 #define MAX_CRITERIA_PER_MIX 20
 
-class AudioDeviceTypeAddr {
-public:
-    AudioDeviceTypeAddr() {}
-    AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
-        mType(type), mAddress(address) {}
-
-    status_t readFromParcel(Parcel *parcel);
-    status_t writeToParcel(Parcel *parcel) const;
-
-    audio_devices_t mType;
-    String8 mAddress;
-};
-
 class AudioMixMatchCriterion {
 public:
     AudioMixMatchCriterion() {}
@@ -85,6 +76,7 @@
         audio_usage_t   mUsage;
         audio_source_t  mSource;
         uid_t           mUid;
+        int        mUserId;
     } mValue;
     uint32_t        mRule;
 };
@@ -110,6 +102,13 @@
     bool hasUidRule(bool match, uid_t uid) const;
     /** returns true if this mix has a rule for uid match (any uid) */
     bool hasMatchUidRule() const;
+
+    void setExcludeUserId(int userId) const;
+    void setMatchUserId(int userId) const;
+    /** returns true if this mix has a rule to match or exclude the given userId */
+    bool hasUserIdRule(bool match, int userId) const;
+    /** returns true if this mix has a rule for userId match (any userId) */
+    bool hasMatchUserIdRule() const;
     /** returns true if this mix can be used for uid-device affinity routing */
     bool isDeviceAffinityCompatible() const;
 
@@ -122,6 +121,8 @@
     uint32_t        mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
     /** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
     bool            mAllowPrivilegedPlaybackCapture = false;
+    /** Indicates if the caller can capture voice communication output */
+    bool            mVoiceCommunicationCaptureAllowed = false;
 };
 
 
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 574302b..2f66658 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -24,7 +24,7 @@
 #include <cutils/sched_policy.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/Modulo.h>
 #include <media/MicrophoneInfo.h>
 #include <media/RecordingActivityTracker.h>
@@ -275,7 +275,20 @@
     /*
      * return metrics information for the current instance.
      */
-            status_t getMetrics(MediaAnalyticsItem * &item);
+            status_t getMetrics(mediametrics::Item * &item);
+
+    /*
+     * Set name of API that is using this object.
+     * For example "aaudio" or "opensles".
+     * This may be logged or reported as part of MediaMetrics.
+     */
+            void setCallerName(const std::string &name) {
+                mCallerName = name;
+            }
+
+            std::string getCallerName() const {
+                return mCallerName;
+            };
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
@@ -711,6 +724,10 @@
 
     bool                    mInOverrun;         // whether recorder is currently in overrun state
 
+    ExtendedTimestamp       mPreviousTimestamp{}; // used to detect retrograde motion
+    bool                    mTimestampRetrogradePositionReported = false; // reduce log spam
+    bool                    mTimestampRetrogradeTimeReported = false;     // reduce log spam
+
 private:
     class DeathNotifier : public IBinder::DeathRecipient {
     public:
@@ -741,27 +758,27 @@
 private:
     class MediaMetrics {
       public:
-        MediaMetrics() : mAnalyticsItem(MediaAnalyticsItem::create("audiorecord")),
+        MediaMetrics() : mMetricsItem(mediametrics::Item::create("audiorecord")),
                          mCreatedNs(systemTime(SYSTEM_TIME_REALTIME)),
                          mStartedNs(0), mDurationNs(0), mCount(0),
                          mLastError(NO_ERROR) {
         }
         ~MediaMetrics() {
-            // mAnalyticsItem alloc failure will be flagged in the constructor
+            // mMetricsItem alloc failure will be flagged in the constructor
             // don't log empty records
-            if (mAnalyticsItem->count() > 0) {
-                mAnalyticsItem->selfrecord();
+            if (mMetricsItem->count() > 0) {
+                mMetricsItem->selfrecord();
             }
         }
         void gather(const AudioRecord *record);
-        MediaAnalyticsItem *dup() { return mAnalyticsItem->dup(); }
+        mediametrics::Item *dup() { return mMetricsItem->dup(); }
 
         void logStart(nsecs_t when) { mStartedNs = when; mCount++; }
         void logStop(nsecs_t when) { mDurationNs += (when-mStartedNs); mStartedNs = 0;}
         void markError(status_t errcode, const char *func)
                  { mLastError = errcode; mLastErrorFunc = func;}
       private:
-        std::unique_ptr<MediaAnalyticsItem> mAnalyticsItem;
+        std::unique_ptr<mediametrics::Item> mMetricsItem;
         nsecs_t mCreatedNs;     // XXX: perhaps not worth it in production
         nsecs_t mStartedNs;
         nsecs_t mDurationNs;
@@ -771,6 +788,8 @@
         std::string mLastErrorFunc;
     };
     MediaMetrics mMediaMetrics;
+    std::string mMetricsId;  // GUARDED_BY(mLock), could change in createRecord_l().
+    std::string mCallerName; // for example "aaudio"
 };
 
 }; // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 09e80b2..19c2cbd 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -19,6 +19,7 @@
 
 #include <sys/types.h>
 
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioPolicy.h>
 #include <media/AudioProductStrategy.h>
 #include <media/AudioVolumeGroup.h>
@@ -26,6 +27,7 @@
 #include <media/IAudioFlingerClient.h>
 #include <media/IAudioPolicyServiceClient.h>
 #include <media/MicrophoneInfo.h>
+#include <set>
 #include <system/audio.h>
 #include <system/audio_effect.h>
 #include <system/audio_policy.h>
@@ -106,7 +108,16 @@
     static status_t setParameters(const String8& keyValuePairs);
     static String8  getParameters(const String8& keys);
 
-    static void setErrorCallback(audio_error_callback cb);
+    // Registers an error callback. When this callback is invoked, it means all
+    // state implied by this interface has been reset.
+    // Returns a token that can be used for un-registering.
+    // Might block while callbacks are being invoked.
+    static uintptr_t addErrorCallback(audio_error_callback cb);
+
+    // Un-registers a callback previously added with addErrorCallback.
+    // Might block while callbacks are being invoked.
+    static void removeErrorCallback(uintptr_t cb);
+
     static void setDynPolicyCallback(dynamic_policy_callback cb);
     static void setRecordConfigCallback(record_config_callback);
 
@@ -171,7 +182,7 @@
     //       or an unspecified existing unique ID.
     static audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
 
-    static void acquireAudioSessionId(audio_session_t audioSession, pid_t pid);
+    static void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid);
     static void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
 
     // Get the HW synchronization source used for an audio session.
@@ -210,6 +221,7 @@
     //
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
+    static void onNewAudioModulesAvailable();
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
                                              const char *device_address, const char *device_name,
                                              audio_format_t encodedFormat);
@@ -219,7 +231,7 @@
                                              const char *device_address,
                                              const char *device_name,
                                              audio_format_t encodedFormat);
-    static status_t setPhoneState(audio_mode_t state);
+    static status_t setPhoneState(audio_mode_t state, uid_t uid);
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
 
@@ -278,6 +290,8 @@
 
     static uint32_t getStrategyForStream(audio_stream_type_t stream);
     static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
+    static status_t getDevicesForAttributes(const AudioAttributes &aa,
+                                            AudioDeviceTypeAddrVector *devices);
 
     static audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc);
     static status_t registerEffect(const effect_descriptor_t *desc,
@@ -301,6 +315,8 @@
 
     static status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory);
 
+    static status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages);
+
     static status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags);
 
     // Check if hw offload is possible for given format, stream type, sample rate,
@@ -349,6 +365,10 @@
 
     static status_t removeUidDeviceAffinities(uid_t uid);
 
+    static status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+
+    static status_t removeUserIdDeviceAffinities(int userId);
+
     static status_t startAudioSource(const struct audio_port_config *source,
                                      const audio_attributes_t *attributes,
                                      audio_port_handle_t *portId);
@@ -379,6 +399,7 @@
 
     static status_t setAssistantUid(uid_t uid);
     static status_t setA11yServicesUids(const std::vector<uid_t>& uids);
+    static status_t setCurrentImeUid(uid_t uid);
 
     static bool     isHapticPlaybackSupported();
 
@@ -396,6 +417,49 @@
 
     static status_t setRttEnabled(bool enabled);
 
+    static bool     isCallScreenModeSupported();
+
+     /**
+     * Send audio HAL server process pids to native audioserver process for use
+     * when generating audio HAL servers tombstones
+     */
+    static status_t setAudioHalPids(const std::vector<pid_t>& pids);
+
+    static status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+            const AudioDeviceTypeAddr &device);
+
+    static status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
+
+    static status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device);
+
+    static status_t getDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device);
+
+    // A listener for capture state changes.
+    class CaptureStateListener : public RefBase {
+    public:
+        // Called whenever capture state changes.
+        virtual void onStateChanged(bool active) = 0;
+        // Called whenever the service dies (and hence our listener is no longer
+        // registered).
+        virtual void onServiceDied() = 0;
+
+        virtual ~CaptureStateListener() = default;
+    };
+
+    // Regiseters a listener for sound trigger capture state changes.
+    // There may only be one such listener registered at any point.
+    // The listener onStateChanged() method will be invoked sychronously from
+    // this call with the initial value.
+    // The listener onServiceDied() method will be invoked sychronously from
+    // this call if initial attempt to register failed.
+    // If the audio policy service cannot be reached, this method will return
+    // PERMISSION_DENIED and will not invoke the callback, otherwise, it will
+    // return NO_ERROR.
+    static status_t registerSoundTriggerCaptureStateListener(
+            const sp<CaptureStateListener>& listener);
+
     // ----------------------------------------------------------------------------
 
     class AudioVolumeGroupCallback : public RefBase
@@ -540,15 +604,19 @@
     static const sp<AudioFlingerClient> getAudioFlingerClient();
     static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);
 
+    // Invokes all registered error callbacks with the given error code.
+    static void reportError(status_t err);
+
     static sp<AudioFlingerClient> gAudioFlingerClient;
     static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
     friend class AudioFlingerClient;
     friend class AudioPolicyServiceClient;
 
-    static Mutex gLock;      // protects gAudioFlinger and gAudioErrorCallback,
+    static Mutex gLock;      // protects gAudioFlinger
+    static Mutex gLockErrorCallbacks;      // protects gAudioErrorCallbacks
     static Mutex gLockAPS;   // protects gAudioPolicyService and gAudioPolicyServiceClient
     static sp<IAudioFlinger> gAudioFlinger;
-    static audio_error_callback gAudioErrorCallback;
+    static std::set<audio_error_callback> gAudioErrorCallbacks;
     static dynamic_policy_callback gDynPolicyCallback;
     static record_config_callback gRecordConfigCallback;
 
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index c607918..0dbd842 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -22,10 +22,13 @@
 #include <media/AudioTimestamp.h>
 #include <media/IAudioTrack.h>
 #include <media/AudioResamplerPublic.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/Modulo.h>
 #include <utils/threads.h>
 
+#include "android/media/BnAudioTrackCallback.h"
+#include "android/media/IAudioTrackCallback.h"
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -405,7 +408,20 @@
     /*
      * return metrics information for the current track.
      */
-            status_t getMetrics(MediaAnalyticsItem * &item);
+            status_t getMetrics(mediametrics::Item * &item);
+
+    /*
+     * Set name of API that is using this object.
+     * For example "aaudio" or "opensles".
+     * This may be logged or reported as part of MediaMetrics.
+     */
+            void setCallerName(const std::string &name) {
+                mCallerName = name;
+            }
+
+            std::string getCallerName() const {
+                return mCallerName;
+            };
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
@@ -885,8 +901,6 @@
             virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                              audio_port_handle_t deviceId);
 
-
-
     /* Obtain the pending duration in milliseconds for playback of pure PCM
      * (mixable without embedded timing) data remaining in AudioTrack.
      *
@@ -933,6 +947,10 @@
      */
             audio_port_handle_t getPortId() const { return mPortId; };
 
+            void setAudioTrackCallback(const sp<media::IAudioTrackCallback>& callback) {
+                mAudioTrackCallback->setAudioTrackCallback(callback);
+            }
+
  protected:
     /* copying audio tracks is not allowed */
                         AudioTrack(const AudioTrack& other);
@@ -942,7 +960,7 @@
     class AudioTrackThread : public Thread
     {
     public:
-        AudioTrackThread(AudioTrack& receiver);
+        explicit AudioTrackThread(AudioTrack& receiver);
 
         // Do not call Thread::requestExitAndWait() without first calling requestExit().
         // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
@@ -1221,7 +1239,7 @@
 private:
     class DeathNotifier : public IBinder::DeathRecipient {
     public:
-        DeathNotifier(AudioTrack* audioTrack) : mAudioTrack(audioTrack) { }
+        explicit DeathNotifier(AudioTrack* audioTrack) : mAudioTrack(audioTrack) { }
     protected:
         virtual void        binderDied(const wp<IBinder>& who);
     private:
@@ -1238,21 +1256,35 @@
 private:
     class MediaMetrics {
       public:
-        MediaMetrics() : mAnalyticsItem(MediaAnalyticsItem::create("audiotrack")) {
+        MediaMetrics() : mMetricsItem(mediametrics::Item::create("audiotrack")) {
         }
         ~MediaMetrics() {
-            // mAnalyticsItem alloc failure will be flagged in the constructor
+            // mMetricsItem alloc failure will be flagged in the constructor
             // don't log empty records
-            if (mAnalyticsItem->count() > 0) {
-                mAnalyticsItem->selfrecord();
+            if (mMetricsItem->count() > 0) {
+                mMetricsItem->selfrecord();
             }
         }
         void gather(const AudioTrack *track);
-        MediaAnalyticsItem *dup() { return mAnalyticsItem->dup(); }
+        mediametrics::Item *dup() { return mMetricsItem->dup(); }
       private:
-        std::unique_ptr<MediaAnalyticsItem> mAnalyticsItem;
+        std::unique_ptr<mediametrics::Item> mMetricsItem;
     };
     MediaMetrics mMediaMetrics;
+    std::string mMetricsId;  // GUARDED_BY(mLock), could change in createTrack_l().
+    std::string mCallerName; // for example "aaudio"
+
+private:
+    class AudioTrackCallback : public media::BnAudioTrackCallback {
+    public:
+        binder::Status onCodecFormatChanged(const std::vector<uint8_t>& audioMetadata) override;
+
+        void setAudioTrackCallback(const sp<media::IAudioTrackCallback>& callback);
+    private:
+        Mutex mAudioTrackCbLock;
+        wp<media::IAudioTrackCallback> mCallback;
+    };
+    sp<AudioTrackCallback> mAudioTrackCallback;
 };
 
 }; // namespace android
diff --git a/media/libmedia/include/media/ExtendedAudioBufferProvider.h b/media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
similarity index 100%
rename from media/libmedia/include/media/ExtendedAudioBufferProvider.h
rename to media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8ec8931..612ce7a 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -27,6 +27,7 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 #include <media/AudioClient.h>
+#include <media/DeviceDescriptorBase.h>
 #include <media/IAudioTrack.h>
 #include <media/IAudioFlingerClient.h>
 #include <system/audio.h>
@@ -39,6 +40,7 @@
 #include <vector>
 
 #include "android/media/IAudioRecord.h"
+#include "android/media/IAudioTrackCallback.h"
 
 namespace android {
 
@@ -70,13 +72,19 @@
                 return DEAD_OBJECT;
             }
             if (parcel->readInt32() != 0) {
+                // TODO: Using unsecurePointer() has some associated security
+                //       pitfalls (see declaration for details).
+                //       Either document why it is safe in this case or address
+                //       the issue (e.g. by copying).
                 sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
-                if (sharedBuffer == 0 || sharedBuffer->pointer() == NULL) {
+                if (sharedBuffer == 0 || sharedBuffer->unsecurePointer() == NULL) {
                     return BAD_VALUE;
                 }
             }
             notificationsPerBuffer = parcel->readInt32();
             speed = parcel->readFloat();
+            audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
+                    parcel->readStrongBinder());
 
             /* input/output arguments*/
             (void)parcel->read(&flags, sizeof(audio_output_flags_t));
@@ -100,6 +108,7 @@
             }
             (void)parcel->writeInt32(notificationsPerBuffer);
             (void)parcel->writeFloat(speed);
+            (void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));
 
             /* input/output arguments*/
             (void)parcel->write(&flags, sizeof(audio_output_flags_t));
@@ -117,6 +126,7 @@
         sp<IMemory> sharedBuffer;
         uint32_t notificationsPerBuffer;
         float speed;
+        sp<media::IAudioTrackCallback> audioTrackCallback;
 
         /* input/output */
         audio_output_flags_t flags;
@@ -269,13 +279,21 @@
             (void)parcel->read(&inputId, sizeof(audio_io_handle_t));
             if (parcel->readInt32() != 0) {
                 cblk = interface_cast<IMemory>(parcel->readStrongBinder());
-                if (cblk == 0 || cblk->pointer() == NULL) {
+                // TODO: Using unsecurePointer() has some associated security
+                //       pitfalls (see declaration for details).
+                //       Either document why it is safe in this case or address
+                //       the issue (e.g. by copying).
+                if (cblk == 0 || cblk->unsecurePointer() == NULL) {
                     return BAD_VALUE;
                 }
             }
             if (parcel->readInt32() != 0) {
                 buffers = interface_cast<IMemory>(parcel->readStrongBinder());
-                if (buffers == 0 || buffers->pointer() == NULL) {
+                // TODO: Using unsecurePointer() has some associated security
+                //       pitfalls (see declaration for details).
+                //       Either document why it is safe in this case or address
+                //       the issue (e.g. by copying).
+                if (buffers == 0 || buffers->unsecurePointer() == NULL) {
                     return BAD_VALUE;
                 }
             }
@@ -384,7 +402,7 @@
     // mic mute/state
     virtual     status_t    setMicMute(bool state) = 0;
     virtual     bool        getMicMute() const = 0;
-    virtual     void        setRecordSilenced(uid_t uid, bool silenced) = 0;
+    virtual     void        setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
 
     virtual     status_t    setParameters(audio_io_handle_t ioHandle,
                                     const String8& keyValuePairs) = 0;
@@ -396,7 +414,7 @@
     // Thus the IAudioFlingerClient must be a singleton per process.
     virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
 
-    // retrieve the audio recording buffer size
+    // retrieve the audio recording buffer size in bytes
     // FIXME This API assumes a route, and so should be deprecated.
     virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
             audio_channel_mask_t channelMask) const = 0;
@@ -404,8 +422,7 @@
     virtual status_t openOutput(audio_module_handle_t module,
                                 audio_io_handle_t *output,
                                 audio_config_t *config,
-                                audio_devices_t *devices,
-                                const String8& address,
+                                const sp<DeviceDescriptorBase>& device,
                                 uint32_t *latencyMs,
                                 audio_output_flags_t flags) = 0;
     virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
@@ -434,7 +451,7 @@
 
     virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
 
-    virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+    virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) = 0;
     virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
 
     virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0;
@@ -453,8 +470,10 @@
                                     // AudioFlinger doesn't take over handle reference from client
                                     audio_io_handle_t output,
                                     audio_session_t sessionId,
+                                    const AudioDeviceTypeAddr& device,
                                     const String16& callingPackage,
                                     pid_t pid,
+                                    bool probe,
                                     status_t *status,
                                     int *id,
                                     int *enabled) = 0;
@@ -511,6 +530,8 @@
 
     /* List available microphones and their characteristics */
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+
+    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
 };
 
 
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 32275cf..bb1c07f 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -23,6 +23,7 @@
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioSystem.h>
 #include <media/AudioPolicy.h>
 #include <media/IAudioPolicyServiceClient.h>
@@ -30,6 +31,11 @@
 #include <vector>
 
 namespace android {
+namespace media {
+// Must be pre-declared, or else there isn't a good way to generate a header
+// library.
+class ICaptureStateListener;
+}
 
 // ----------------------------------------------------------------------------
 
@@ -41,6 +47,7 @@
     //
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
+    virtual void onNewAudioModulesAvailable() = 0;
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
                                               const char *device_address,
@@ -52,7 +59,7 @@
                                               const char *device_address,
                                               const char *device_name,
                                               audio_format_t encodedFormat) = 0;
-    virtual status_t setPhoneState(audio_mode_t state) = 0;
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid) = 0;
     virtual status_t setForceUse(audio_policy_force_use_t usage,
                                     audio_policy_forced_cfg_t config) = 0;
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
@@ -107,6 +114,8 @@
 
     virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
     virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
+    virtual status_t getDevicesForAttributes(const AudioAttributes &aa,
+            AudioDeviceTypeAddrVector *devices) const = 0;
     virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0;
     virtual status_t registerEffect(const effect_descriptor_t *desc,
                                     audio_io_handle_t io,
@@ -137,6 +146,7 @@
                                             audio_unique_id_t* id) = 0;
     virtual status_t removeSourceDefaultEffect(audio_unique_id_t id) = 0;
     virtual status_t removeStreamDefaultEffect(audio_unique_id_t id) = 0;
+    virtual status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages) = 0;
     virtual status_t setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t flags) = 0;
    // Check if offload is possible for given format, stream type, sample rate,
     // bit rate, duration, video and streaming or offload property is enabled
@@ -191,6 +201,11 @@
 
     virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
 
+    virtual status_t setUserIdDeviceAffinities(int userId,
+            const Vector<AudioDeviceTypeAddr>& devices) = 0;
+
+    virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId) = 0;
@@ -211,6 +226,7 @@
 
     virtual status_t setAssistantUid(uid_t uid) = 0;
     virtual status_t setA11yServicesUids(const std::vector<uid_t>& uids) = 0;
+    virtual status_t setCurrentImeUid(uid_t uid) = 0;
 
     virtual bool     isHapticPlaybackSupported() = 0;
     virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
@@ -222,6 +238,22 @@
                                                        volume_group_t &volumeGroup) = 0;
 
     virtual status_t setRttEnabled(bool enabled) = 0;
+
+    virtual bool     isCallScreenModeSupported() = 0;
+
+    virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device) = 0;
+
+    virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+
+    virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device) = 0;
+
+    // The return code here is only intended to represent transport errors. The
+    // actual server implementation should always return NO_ERROR.
+    virtual status_t registerSoundTriggerCaptureStateListener(
+        const sp<media::ICaptureStateListener>& listener,
+        bool* result) = 0;
 };
 
 
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 52bb2fb..350a780 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -11,6 +11,10 @@
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["test_create_audiotrack.cpp",
            "test_create_utils.cpp"],
+    header_libs: [
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
     shared_libs: [
         "libaudioclient",
         "libbinder",
@@ -25,6 +29,10 @@
     defaults: ["libaudioclient_tests_defaults"],
     srcs: ["test_create_audiorecord.cpp",
            "test_create_utils.cpp"],
+    header_libs: [
+        "libmedia_headers",
+        "libmediametrics_headers",
+    ],
     shared_libs: [
         "libaudioclient",
         "libbinder",
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
new file mode 100644
index 0000000..548b080
--- /dev/null
+++ b/media/libaudiofoundation/Android.bp
@@ -0,0 +1,52 @@
+cc_library_headers {
+    name: "libaudiofoundation_headers",
+    vendor_available: true,
+    min_sdk_version: "29",
+
+    export_include_dirs: ["include"],
+    header_libs: [
+        "libaudio_system_headers",
+        "libmedia_helper_headers",
+    ],
+    export_header_lib_headers: [
+        "libaudio_system_headers",
+        "libmedia_helper_headers",
+    ],
+}
+
+cc_library {
+    name: "libaudiofoundation",
+    vendor_available: true,
+    double_loadable: true,
+
+    srcs: [
+        "AudioContainers.cpp",
+        "AudioDeviceTypeAddr.cpp",
+        "AudioGain.cpp",
+        "AudioPort.cpp",
+        "AudioProfile.cpp",
+        "DeviceDescriptorBase.cpp",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudiofoundation_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libaudiofoundation_headers",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
new file mode 100644
index 0000000..31257d5
--- /dev/null
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 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 <sstream>
+#include <string>
+
+#include <media/AudioContainers.h>
+
+namespace android {
+
+const DeviceTypeSet& getAudioDeviceOutAllSet() {
+    static const DeviceTypeSet audioDeviceOutAllSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_ALL_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_ARRAY));
+    return audioDeviceOutAllSet;
+}
+
+const DeviceTypeSet& getAudioDeviceOutAllA2dpSet() {
+    static const DeviceTypeSet audioDeviceOutAllA2dpSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_A2DP_ARRAY));
+    return audioDeviceOutAllA2dpSet;
+}
+
+const DeviceTypeSet& getAudioDeviceOutAllScoSet() {
+    static const DeviceTypeSet audioDeviceOutAllScoSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_SCO_ARRAY));
+    return audioDeviceOutAllScoSet;
+}
+
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet() {
+    static const DeviceTypeSet audioDeviceOutAllUsbSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_ALL_USB_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_ALL_USB_ARRAY));
+    return audioDeviceOutAllUsbSet;
+}
+
+const DeviceTypeSet& getAudioDeviceInAllSet() {
+    static const DeviceTypeSet audioDeviceInAllSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
+            std::end(AUDIO_DEVICE_IN_ALL_ARRAY));
+    return audioDeviceInAllSet;
+}
+
+const DeviceTypeSet& getAudioDeviceInAllUsbSet() {
+    static const DeviceTypeSet audioDeviceInAllUsbSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_IN_ALL_USB_ARRAY),
+            std::end(AUDIO_DEVICE_IN_ALL_USB_ARRAY));
+    return audioDeviceInAllUsbSet;
+}
+
+bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
+    if (deviceTypes.empty()) {
+        str = "Empty device types";
+        return true;
+    }
+    bool ret = true;
+    for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
+        std::string deviceTypeStr;
+        ret = audio_is_output_device(*it) ?
+              OutputDeviceConverter::toString(*it, deviceTypeStr) :
+              InputDeviceConverter::toString(*it, deviceTypeStr);
+        if (!ret) {
+            break;
+        }
+        str.append(deviceTypeStr);
+        if (++it != deviceTypes.end()) {
+            str.append(" , ");
+        }
+    }
+    if (!ret) {
+        str = "Unknown values";
+    }
+    return ret;
+}
+
+std::string dumpDeviceTypes(const DeviceTypeSet &deviceTypes) {
+    std::string ret;
+    for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
+        std::stringstream ss;
+        ss << "0x" << std::hex << (*it);
+        ret.append(ss.str());
+        if (++it != deviceTypes.end()) {
+            ret.append(" , ");
+        }
+    }
+    return ret;
+}
+
+std::string toString(const DeviceTypeSet& deviceTypes) {
+    std::string ret;
+    deviceTypesToString(deviceTypes, ret);
+    return ret;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
new file mode 100644
index 0000000..b44043a
--- /dev/null
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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 <media/AudioDeviceTypeAddr.h>
+
+namespace android {
+
+const char* AudioDeviceTypeAddr::getAddress() const {
+    return mAddress.c_str();
+}
+
+bool AudioDeviceTypeAddr::equals(const AudioDeviceTypeAddr& other) const {
+    return mType == other.mType && mAddress == other.mAddress;
+}
+
+bool AudioDeviceTypeAddr::operator<(const AudioDeviceTypeAddr& other) const {
+    if (mType < other.mType)  return true;
+    if (mType > other.mType)  return false;
+
+    if (mAddress < other.mAddress)  return true;
+    // if (mAddress > other.mAddress)  return false;
+
+    return false;
+}
+
+void AudioDeviceTypeAddr::reset() {
+    mType = AUDIO_DEVICE_NONE;
+    mAddress = "";
+}
+
+status_t AudioDeviceTypeAddr::readFromParcel(const Parcel *parcel) {
+    status_t status;
+    if ((status = parcel->readUint32(&mType)) != NO_ERROR) return status;
+    status = parcel->readUtf8FromUtf16(&mAddress);
+    return status;
+}
+
+status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
+    status_t status;
+    if ((status = parcel->writeUint32(mType)) != NO_ERROR) return status;
+    status = parcel->writeUtf8AsUtf16(mAddress);
+    return status;
+}
+
+
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs) {
+    DeviceTypeSet deviceTypes;
+    for (const auto& deviceTypeAddr : deviceTypeAddrs) {
+        deviceTypes.insert(deviceTypeAddr.mType);
+    }
+    return deviceTypes;
+}
+
+}
\ No newline at end of file
diff --git a/media/libaudiofoundation/AudioGain.cpp b/media/libaudiofoundation/AudioGain.cpp
new file mode 100644
index 0000000..0d28335
--- /dev/null
+++ b/media/libaudiofoundation/AudioGain.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2015 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_TAG "AudioGain"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include <algorithm>
+
+#include <android-base/stringprintf.h>
+#include <media/AudioGain.h>
+#include <utils/Log.h>
+
+#include <math.h>
+
+namespace android {
+
+AudioGain::AudioGain(int index, bool useInChannelMask)
+{
+    mIndex = index;
+    mUseInChannelMask = useInChannelMask;
+    memset(&mGain, 0, sizeof(struct audio_gain));
+}
+
+void AudioGain::getDefaultConfig(struct audio_gain_config *config)
+{
+    config->index = mIndex;
+    config->mode = mGain.mode;
+    config->channel_mask = mGain.channel_mask;
+    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        config->values[0] = mGain.default_value;
+    } else {
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            config->values[i] = mGain.default_value;
+        }
+    }
+    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        config->ramp_duration_ms = mGain.min_ramp_ms;
+    }
+}
+
+status_t AudioGain::checkConfig(const struct audio_gain_config *config)
+{
+    if ((config->mode & ~mGain.mode) != 0) {
+        return BAD_VALUE;
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        if ((config->values[0] < mGain.min_value) ||
+                    (config->values[0] > mGain.max_value)) {
+            return BAD_VALUE;
+        }
+    } else {
+        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
+            return BAD_VALUE;
+        }
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(config->channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(config->channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            if ((config->values[i] < mGain.min_value) ||
+                    (config->values[i] > mGain.max_value)) {
+                return BAD_VALUE;
+            }
+        }
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
+                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
+void AudioGain::dump(std::string *dst, int spaces, int index) const
+{
+    dst->append(base::StringPrintf("%*sGain %d:\n", spaces, "", index+1));
+    dst->append(base::StringPrintf("%*s- mode: %08x\n", spaces, "", mGain.mode));
+    dst->append(base::StringPrintf("%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask));
+    dst->append(base::StringPrintf("%*s- min_value: %d mB\n", spaces, "", mGain.min_value));
+    dst->append(base::StringPrintf("%*s- max_value: %d mB\n", spaces, "", mGain.max_value));
+    dst->append(base::StringPrintf("%*s- default_value: %d mB\n", spaces, "", mGain.default_value));
+    dst->append(base::StringPrintf("%*s- step_value: %d mB\n", spaces, "", mGain.step_value));
+    dst->append(base::StringPrintf("%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms));
+    dst->append(base::StringPrintf("%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms));
+}
+
+bool AudioGain::equals(const sp<AudioGain>& other) const
+{
+    return other != nullptr &&
+           mUseInChannelMask == other->mUseInChannelMask &&
+           mUseForVolume == other->mUseForVolume &&
+           // Compare audio gain
+           mGain.mode == other->mGain.mode &&
+           mGain.channel_mask == other->mGain.channel_mask &&
+           mGain.min_value == other->mGain.min_value &&
+           mGain.max_value == other->mGain.max_value &&
+           mGain.default_value == other->mGain.default_value &&
+           mGain.step_value == other->mGain.step_value &&
+           mGain.min_ramp_ms == other->mGain.min_ramp_ms &&
+           mGain.max_ramp_ms == other->mGain.max_ramp_ms;
+}
+
+status_t AudioGain::writeToParcel(android::Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeInt32(mIndex)) != NO_ERROR) return status;
+    if ((status = parcel->writeBool(mUseInChannelMask)) != NO_ERROR) return status;
+    if ((status = parcel->writeBool(mUseForVolume)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.mode)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.channel_mask)) != NO_ERROR) return status;
+    if ((status = parcel->writeInt32(mGain.min_value)) != NO_ERROR) return status;
+    if ((status = parcel->writeInt32(mGain.max_value)) != NO_ERROR) return status;
+    if ((status = parcel->writeInt32(mGain.default_value)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.step_value)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.min_ramp_ms)) != NO_ERROR) return status;
+    status = parcel->writeUint32(mGain.max_ramp_ms);
+    return status;
+}
+
+status_t AudioGain::readFromParcel(const android::Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->readInt32(&mIndex)) != NO_ERROR) return status;
+    if ((status = parcel->readBool(&mUseInChannelMask)) != NO_ERROR) return status;
+    if ((status = parcel->readBool(&mUseForVolume)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+    if ((status = parcel->readInt32(&mGain.min_value)) != NO_ERROR) return status;
+    if ((status = parcel->readInt32(&mGain.max_value)) != NO_ERROR) return status;
+    if ((status = parcel->readInt32(&mGain.default_value)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.step_value)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.min_ramp_ms)) != NO_ERROR) return status;
+    status = parcel->readUint32(&mGain.max_ramp_ms);
+    return status;
+}
+
+bool AudioGains::equals(const AudioGains &other) const
+{
+    return std::equal(begin(), end(), other.begin(), other.end(),
+                      [](const sp<AudioGain>& left, const sp<AudioGain>& right) {
+                          return left->equals(right);
+                      });
+}
+
+status_t AudioGains::writeToParcel(android::Parcel *parcel) const {
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
+    for (const auto &audioGain : *this) {
+        if ((status = parcel->writeParcelable(*audioGain)) != NO_ERROR) {
+            break;
+        }
+    }
+    return status;
+}
+
+status_t AudioGains::readFromParcel(const android::Parcel *parcel) {
+    status_t status = NO_ERROR;
+    this->clear();
+    if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
+    for (size_t i = 0; i < this->size(); i++) {
+        this->at(i) = new AudioGain(0, false);
+        if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
+            this->clear();
+            break;
+        }
+    }
+    return status;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
new file mode 100644
index 0000000..f988690
--- /dev/null
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2019 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_TAG "AudioPort"
+
+#include <algorithm>
+
+#include <android-base/stringprintf.h>
+#include <media/AudioPort.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
+{
+    for (const auto& profileToImport : port->mProfiles) {
+        // Import only valid port, i.e. valid format, non empty rates and channels masks
+        if (!profileToImport->isValid()) {
+            continue;
+        }
+        if (std::find_if(mProfiles.begin(), mProfiles.end(),
+                [profileToImport](const auto &profile) {
+                        return *profile == *profileToImport; }) == mProfiles.end()) {
+            addAudioProfile(profileToImport);
+        }
+    }
+}
+
+void AudioPort::toAudioPort(struct audio_port *port) const {
+    // TODO: update this function once audio_port structure reflects the new profile definition.
+    // For compatibility reason: flatening the AudioProfile into audio_port structure.
+    FormatSet flatenedFormats;
+    SampleRateSet flatenedRates;
+    ChannelMaskSet flatenedChannels;
+    for (const auto& profile : mProfiles) {
+        if (profile->isValid()) {
+            audio_format_t formatToExport = profile->getFormat();
+            const SampleRateSet &ratesToExport = profile->getSampleRates();
+            const ChannelMaskSet &channelsToExport = profile->getChannels();
+
+            flatenedFormats.insert(formatToExport);
+            flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
+            flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
+
+            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
+                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
+                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
+                ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
+                return;
+            }
+        }
+    }
+    port->role = mRole;
+    port->type = mType;
+    strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN);
+    port->num_sample_rates = flatenedRates.size();
+    port->num_channel_masks = flatenedChannels.size();
+    port->num_formats = flatenedFormats.size();
+    std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
+    std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
+    std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
+
+    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
+
+    port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
+    for (size_t i = 0; i < port->num_gains; i++) {
+        port->gains[i] = mGains[i]->getGain();
+    }
+}
+
+void AudioPort::dump(std::string *dst, int spaces, bool verbose) const {
+    if (!mName.empty()) {
+        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+    }
+    if (verbose) {
+        std::string profilesStr;
+        mProfiles.dump(&profilesStr, spaces);
+        dst->append(profilesStr);
+
+        if (mGains.size() != 0) {
+            dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
+            for (size_t i = 0; i < mGains.size(); i++) {
+                std::string gainStr;
+                mGains[i]->dump(&gainStr, spaces + 2, i);
+                dst->append(gainStr);
+            }
+        }
+    }
+}
+
+void AudioPort::log(const char* indent) const
+{
+    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
+}
+
+bool AudioPort::equals(const sp<AudioPort> &other) const
+{
+    return other != nullptr &&
+           mGains.equals(other->getGains()) &&
+           mName.compare(other->getName()) == 0 &&
+           mType == other->getType() &&
+           mRole == other->getRole() &&
+           mProfiles.equals(other->getAudioProfiles());
+}
+
+status_t AudioPort::writeToParcel(Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeUtf8AsUtf16(mName)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mType)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mRole)) != NO_ERROR) return status;
+    if ((status = parcel->writeParcelable(mProfiles)) != NO_ERROR) return status;
+    if ((status = parcel->writeParcelable(mGains)) != NO_ERROR) return status;
+    return status;
+}
+
+status_t AudioPort::readFromParcel(const Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->readUtf8FromUtf16(&mName)) != NO_ERROR) return status;
+    static_assert(sizeof(mType) == sizeof(uint32_t));
+    if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mType))) != NO_ERROR) {
+        return status;
+    }
+    static_assert(sizeof(mRole) == sizeof(uint32_t));
+    if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mRole))) != NO_ERROR) {
+        return status;
+    }
+    mProfiles.clear();
+    if ((status = parcel->readParcelable(&mProfiles)) != NO_ERROR) return status;
+    mGains.clear();
+    if ((status = parcel->readParcelable(&mGains)) != NO_ERROR) return status;
+    return status;
+}
+
+// --- AudioPortConfig class implementation
+
+status_t AudioPortConfig::applyAudioPortConfig(
+        const struct audio_port_config *config,
+        struct audio_port_config *backupConfig __unused)
+{
+    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+        mSamplingRate = config->sample_rate;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+        mChannelMask = config->channel_mask;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+        mFormat = config->format;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
+        mGain = config->gain;
+    }
+
+    return NO_ERROR;
+}
+
+namespace {
+
+template<typename T>
+void updateField(
+        const T& portConfigField, T audio_port_config::*port_config_field,
+        struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
+        unsigned int configMask, T defaultValue)
+{
+    if (dstConfig->config_mask & configMask) {
+        if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
+            dstConfig->*port_config_field = srcConfig->*port_config_field;
+        } else {
+            dstConfig->*port_config_field = portConfigField;
+        }
+    } else {
+        dstConfig->*port_config_field = defaultValue;
+    }
+}
+
+} // namespace
+
+void AudioPortConfig::toAudioPortConfig(
+        struct audio_port_config *dstConfig,
+        const struct audio_port_config *srcConfig) const
+{
+    updateField(mSamplingRate, &audio_port_config::sample_rate,
+            dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
+    updateField(mChannelMask, &audio_port_config::channel_mask,
+            dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
+            (audio_channel_mask_t)AUDIO_CHANNEL_NONE);
+    updateField(mFormat, &audio_port_config::format,
+            dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
+    dstConfig->id = mId;
+
+    sp<AudioPort> audioport = getAudioPort();
+    if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
+        dstConfig->gain = mGain;
+        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
+                && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
+            dstConfig->gain = srcConfig->gain;
+        }
+    } else {
+        dstConfig->gain.index = -1;
+    }
+    if (dstConfig->gain.index != -1) {
+        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+    } else {
+        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
+    }
+}
+
+bool AudioPortConfig::hasGainController(bool canUseForVolume) const
+{
+    sp<AudioPort> audioport = getAudioPort();
+    if (!audioport) {
+        return false;
+    }
+    return canUseForVolume ? audioport->getGains().canUseForVolume()
+                           : audioport->getGains().size() > 0;
+}
+
+bool AudioPortConfig::equals(const sp<AudioPortConfig> &other) const
+{
+    return other != nullptr &&
+           mSamplingRate == other->getSamplingRate() &&
+           mFormat == other->getFormat() &&
+           mChannelMask == other->getChannelMask() &&
+           // Compare audio gain config
+           mGain.index == other->mGain.index &&
+           mGain.mode == other->mGain.mode &&
+           mGain.channel_mask == other->mGain.channel_mask &&
+           std::equal(std::begin(mGain.values), std::end(mGain.values),
+                      std::begin(other->mGain.values)) &&
+           mGain.ramp_duration_ms == other->mGain.ramp_duration_ms;
+}
+
+status_t AudioPortConfig::writeToParcel(Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeUint32(mSamplingRate)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mFormat)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mChannelMask)) != NO_ERROR) return status;
+    if ((status = parcel->writeInt32(mId)) != NO_ERROR) return status;
+    // Write mGain to parcel.
+    if ((status = parcel->writeInt32(mGain.index)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.mode)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.channel_mask)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mGain.ramp_duration_ms)) != NO_ERROR) return status;
+    std::vector<int> values(std::begin(mGain.values), std::end(mGain.values));
+    if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+    return status;
+}
+
+status_t AudioPortConfig::readFromParcel(const Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->readUint32(&mSamplingRate)) != NO_ERROR) return status;
+    static_assert(sizeof(mFormat) == sizeof(uint32_t));
+    if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
+        return status;
+    }
+    if ((status = parcel->readUint32(&mChannelMask)) != NO_ERROR) return status;
+    if ((status = parcel->readInt32(&mId)) != NO_ERROR) return status;
+    // Read mGain from parcel.
+    if ((status = parcel->readInt32(&mGain.index)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.mode)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.channel_mask)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mGain.ramp_duration_ms)) != NO_ERROR) return status;
+    std::vector<int> values;
+    if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+    if (values.size() != std::size(mGain.values)) {
+        return BAD_VALUE;
+    }
+    std::copy(values.begin(), values.end(), mGain.values);
+    return status;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
new file mode 100644
index 0000000..91be346
--- /dev/null
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2019 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 <set>
+
+#define LOG_TAG "AudioProfile"
+//#define LOG_NDEBUG 0
+
+#include <android-base/stringprintf.h>
+#include <media/AudioContainers.h>
+#include <media/AudioProfile.h>
+#include <media/TypeConverter.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+bool operator == (const AudioProfile &left, const AudioProfile &right)
+{
+    return (left.getFormat() == right.getFormat()) &&
+            (left.getChannels() == right.getChannels()) &&
+            (left.getSampleRates() == right.getSampleRates());
+}
+
+// static
+sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
+{
+    AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
+            ChannelMaskSet(), SampleRateSet());
+    dynamicProfile->setDynamicFormat(true);
+    dynamicProfile->setDynamicChannels(true);
+    dynamicProfile->setDynamicRate(true);
+    return dynamicProfile;
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+                           audio_channel_mask_t channelMasks,
+                           uint32_t samplingRate) :
+        mName(""),
+        mFormat(format)
+{
+    mChannelMasks.insert(channelMasks);
+    mSamplingRates.insert(samplingRate);
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+                           const ChannelMaskSet &channelMasks,
+                           const SampleRateSet &samplingRateCollection) :
+        mName(""),
+        mFormat(format),
+        mChannelMasks(channelMasks),
+        mSamplingRates(samplingRateCollection) {}
+
+void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
+{
+    if (mIsDynamicChannels) {
+        mChannelMasks = channelMasks;
+    }
+}
+
+void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
+{
+    if (mIsDynamicRate) {
+        mSamplingRates = sampleRates;
+    }
+}
+
+void AudioProfile::clear()
+{
+    if (mIsDynamicChannels) {
+        mChannelMasks.clear();
+    }
+    if (mIsDynamicRate) {
+        mSamplingRates.clear();
+    }
+}
+
+void AudioProfile::dump(std::string *dst, int spaces) const
+{
+    dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
+             mIsDynamicChannels ? "[dynamic channels]" : "",
+             mIsDynamicRate ? "[dynamic rates]" : ""));
+    if (mName.length() != 0) {
+        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+    }
+    std::string formatLiteral;
+    if (FormatConverter::toString(mFormat, formatLiteral)) {
+        dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
+    }
+    if (!mSamplingRates.empty()) {
+        dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
+        for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
+            dst->append(base::StringPrintf("%d", *it));
+            dst->append(++it == mSamplingRates.end() ? "" : ", ");
+        }
+        dst->append("\n");
+    }
+
+    if (!mChannelMasks.empty()) {
+        dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
+        for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
+            dst->append(base::StringPrintf("0x%04x", *it));
+            dst->append(++it == mChannelMasks.end() ? "" : ", ");
+        }
+        dst->append("\n");
+    }
+}
+
+bool AudioProfile::equals(const sp<AudioProfile>& other) const
+{
+    return other != nullptr &&
+           mName.compare(other->mName) == 0 &&
+           mFormat == other->getFormat() &&
+           mChannelMasks == other->getChannels() &&
+           mSamplingRates == other->getSampleRates() &&
+           mIsDynamicFormat == other->isDynamicFormat() &&
+           mIsDynamicChannels == other->isDynamicChannels() &&
+           mIsDynamicRate == other->isDynamicRate();
+}
+
+status_t AudioProfile::writeToParcel(Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeUtf8AsUtf16(mName)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mFormat)) != NO_ERROR) return status;
+    std::vector<int> values(mChannelMasks.begin(), mChannelMasks.end());
+    if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+    values.clear();
+    values.assign(mSamplingRates.begin(), mSamplingRates.end());
+    if ((status = parcel->writeInt32Vector(values)) != NO_ERROR) return status;
+    if ((status = parcel->writeBool(mIsDynamicFormat)) != NO_ERROR) return status;
+    if ((status = parcel->writeBool(mIsDynamicChannels)) != NO_ERROR) return status;
+    if ((status = parcel->writeBool(mIsDynamicRate)) != NO_ERROR) return status;
+    return status;
+}
+
+status_t AudioProfile::readFromParcel(const Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->readUtf8FromUtf16(&mName)) != NO_ERROR) return status;
+    static_assert(sizeof(mFormat) == sizeof(uint32_t));
+    if ((status = parcel->readUint32(reinterpret_cast<uint32_t*>(&mFormat))) != NO_ERROR) {
+        return status;
+    }
+    std::vector<int> values;
+    if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+    mChannelMasks.clear();
+    mChannelMasks.insert(values.begin(), values.end());
+    values.clear();
+    if ((status = parcel->readInt32Vector(&values)) != NO_ERROR) return status;
+    mSamplingRates.clear();
+    mSamplingRates.insert(values.begin(), values.end());
+    if ((status = parcel->readBool(&mIsDynamicFormat)) != NO_ERROR) return status;
+    if ((status = parcel->readBool(&mIsDynamicChannels)) != NO_ERROR) return status;
+    if ((status = parcel->readBool(&mIsDynamicRate)) != NO_ERROR) return status;
+    return status;
+}
+
+ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
+{
+    ssize_t index = size();
+    push_back(profile);
+    return index;
+}
+
+void AudioProfileVector::clearProfiles()
+{
+    for (auto it = begin(); it != end();) {
+        if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
+            it = erase(it);
+        } else {
+            (*it)->clear();
+            ++it;
+        }
+    }
+}
+
+sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isValid()) {
+            return profile;
+        }
+    }
+    return nullptr;
+}
+
+sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->isValid() && profile->getFormat() == format) {
+            return profile;
+        }
+    }
+    return nullptr;
+}
+
+FormatVector AudioProfileVector::getSupportedFormats() const
+{
+    FormatVector supportedFormats;
+    for (const auto &profile : *this) {
+        if (profile->hasValidFormat()) {
+            supportedFormats.push_back(profile->getFormat());
+        }
+    }
+    return supportedFormats;
+}
+
+bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->getFormat() == format && profile->isDynamicChannels()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVector::hasDynamicFormat() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isDynamicFormat()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVector::hasDynamicProfile() const
+{
+    for (const auto &profile : *this) {
+        if (profile->isDynamic()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
+{
+    for (const auto &profile : *this) {
+        if (profile->getFormat() == format && profile->isDynamicRate()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void AudioProfileVector::dump(std::string *dst, int spaces) const
+{
+    dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
+    for (size_t i = 0; i < size(); i++) {
+        dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
+        std::string profileStr;
+        at(i)->dump(&profileStr, spaces + 8);
+        dst->append(profileStr);
+    }
+}
+
+status_t AudioProfileVector::writeToParcel(Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = parcel->writeVectorSize(*this)) != NO_ERROR) return status;
+    for (const auto &audioProfile : *this) {
+        if ((status = parcel->writeParcelable(*audioProfile)) != NO_ERROR) {
+            break;
+        }
+    }
+    return status;
+}
+
+status_t AudioProfileVector::readFromParcel(const Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    this->clear();
+    if ((status = parcel->resizeOutVector(this)) != NO_ERROR) return status;
+    for (size_t i = 0; i < this->size(); ++i) {
+        this->at(i) = new AudioProfile(AUDIO_FORMAT_DEFAULT, AUDIO_CHANNEL_NONE, 0 /*sampleRate*/);
+        if ((status = parcel->readParcelable(this->at(i).get())) != NO_ERROR) {
+            this->clear();
+            break;
+        }
+    }
+    return status;
+}
+
+bool AudioProfileVector::equals(const AudioProfileVector& other) const
+{
+    return std::equal(begin(), end(), other.begin(), other.end(),
+                      [](const sp<AudioProfile>& left, const sp<AudioProfile>& right) {
+                          return left->equals(right);
+                      });
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
new file mode 100644
index 0000000..3dbe37d
--- /dev/null
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 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_TAG "DeviceDescriptorBase"
+//#define LOG_NDEBUG 0
+
+#include <android-base/stringprintf.h>
+#include <audio_utils/string.h>
+#include <media/DeviceDescriptorBase.h>
+#include <media/TypeConverter.h>
+
+namespace android {
+
+DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type) :
+        DeviceDescriptorBase(type, "")
+{
+}
+
+DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type, const std::string& address) :
+        DeviceDescriptorBase(AudioDeviceTypeAddr(type, address))
+{
+}
+
+DeviceDescriptorBase::DeviceDescriptorBase(const AudioDeviceTypeAddr &deviceTypeAddr) :
+        AudioPort("", AUDIO_PORT_TYPE_DEVICE,
+                  audio_is_output_device(deviceTypeAddr.mType) ? AUDIO_PORT_ROLE_SINK :
+                                         AUDIO_PORT_ROLE_SOURCE),
+        mDeviceTypeAddr(deviceTypeAddr)
+{
+    if (mDeviceTypeAddr.mAddress.empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
+        mDeviceTypeAddr.mAddress = "0";
+    }
+}
+
+void DeviceDescriptorBase::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                             const struct audio_port_config *srcConfig) const
+{
+    dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
+    if (mSamplingRate != 0) {
+        dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+    }
+    if (mChannelMask != AUDIO_CHANNEL_NONE) {
+        dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+    }
+    if (mFormat != AUDIO_FORMAT_INVALID) {
+        dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+    }
+
+    if (srcConfig != NULL) {
+        dstConfig->config_mask |= srcConfig->config_mask;
+    }
+
+    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->role = audio_is_output_device(mDeviceTypeAddr.mType) ?
+                        AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
+    dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
+    dstConfig->ext.device.type = mDeviceTypeAddr.mType;
+
+    (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mDeviceTypeAddr.getAddress());
+}
+
+void DeviceDescriptorBase::toAudioPort(struct audio_port *port) const
+{
+    ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
+    AudioPort::toAudioPort(port);
+    toAudioPortConfig(&port->active_config);
+    port->id = mId;
+    port->ext.device.type = mDeviceTypeAddr.mType;
+    port->ext.device.encapsulation_modes = mEncapsulationModes;
+    port->ext.device.encapsulation_metadata_types = mEncapsulationMetadataTypes;
+    (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mDeviceTypeAddr.getAddress());
+}
+
+status_t DeviceDescriptorBase::setEncapsulationModes(uint32_t encapsulationModes) {
+    if ((encapsulationModes & ~AUDIO_ENCAPSULATION_MODE_ALL_POSITION_BITS) != 0) {
+        return BAD_VALUE;
+    }
+    mEncapsulationModes = encapsulationModes & ~(1 << AUDIO_ENCAPSULATION_MODE_NONE);
+    return NO_ERROR;
+}
+
+status_t DeviceDescriptorBase::setEncapsulationMetadataTypes(uint32_t encapsulationMetadataTypes) {
+    if ((encapsulationMetadataTypes & ~AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS) != 0) {
+        return BAD_VALUE;
+    }
+    mEncapsulationMetadataTypes =
+            encapsulationMetadataTypes & ~(1 << AUDIO_ENCAPSULATION_METADATA_TYPE_NONE);
+    return NO_ERROR;
+}
+
+void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
+                                const char* extraInfo, bool verbose) const
+{
+    dst->append(base::StringPrintf("%*sDevice %d:\n", spaces, "", index + 1));
+    if (mId != 0) {
+        dst->append(base::StringPrintf("%*s- id: %2d\n", spaces, "", mId));
+    }
+
+    if (extraInfo != nullptr) {
+        dst->append(extraInfo);
+    }
+
+    dst->append(base::StringPrintf("%*s- type: %-48s\n",
+            spaces, "", ::android::toString(mDeviceTypeAddr.mType).c_str()));
+
+    dst->append(base::StringPrintf(
+            "%*s- supported encapsulation modes: %u", spaces, "", mEncapsulationModes));
+    dst->append(base::StringPrintf(
+            "%*s- supported encapsulation metadata types: %u",
+            spaces, "", mEncapsulationMetadataTypes));
+
+    if (mDeviceTypeAddr.mAddress.size() != 0) {
+        dst->append(base::StringPrintf(
+                "%*s- address: %-32s\n", spaces, "", mDeviceTypeAddr.getAddress()));
+    }
+    AudioPort::dump(dst, spaces, verbose);
+}
+
+std::string DeviceDescriptorBase::toString() const
+{
+    std::stringstream sstream;
+    sstream << "type:0x" << std::hex << type() << ",@:" << mDeviceTypeAddr.mAddress;
+    return sstream.str();
+}
+
+void DeviceDescriptorBase::log() const
+{
+    ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId,  mDeviceTypeAddr.mType,
+          ::android::toString(mDeviceTypeAddr.mType).c_str(),
+          mDeviceTypeAddr.getAddress());
+
+    AudioPort::log("  ");
+}
+
+bool DeviceDescriptorBase::equals(const sp<DeviceDescriptorBase> &other) const
+{
+    return other != nullptr &&
+           static_cast<const AudioPort*>(this)->equals(other) &&
+           static_cast<const AudioPortConfig*>(this)->equals(other) &&
+           mDeviceTypeAddr.equals(other->mDeviceTypeAddr);
+}
+
+status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
+{
+    status_t status = NO_ERROR;
+    if ((status = AudioPort::writeToParcel(parcel)) != NO_ERROR) return status;
+    if ((status = AudioPortConfig::writeToParcel(parcel)) != NO_ERROR) return status;
+    if ((status = parcel->writeParcelable(mDeviceTypeAddr)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mEncapsulationModes)) != NO_ERROR) return status;
+    if ((status = parcel->writeUint32(mEncapsulationMetadataTypes)) != NO_ERROR) return status;
+    return status;
+}
+
+status_t DeviceDescriptorBase::readFromParcel(const Parcel *parcel)
+{
+    status_t status = NO_ERROR;
+    if ((status = AudioPort::readFromParcel(parcel)) != NO_ERROR) return status;
+    if ((status = AudioPortConfig::readFromParcel(parcel)) != NO_ERROR) return status;
+    if ((status = parcel->readParcelable(&mDeviceTypeAddr)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mEncapsulationModes)) != NO_ERROR) return status;
+    if ((status = parcel->readUint32(&mEncapsulationMetadataTypes)) != NO_ERROR) return status;
+    return status;
+}
+
+std::string toString(const DeviceDescriptorBaseVector& devices)
+{
+    std::string ret;
+    for (const auto& device : devices) {
+        if (device != *devices.begin()) {
+            ret += ";";
+        }
+        ret += device->toString();
+    }
+    return ret;
+}
+
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices)
+{
+    AudioDeviceTypeAddrVector deviceTypeAddrs;
+    for (const auto& device : devices) {
+        deviceTypeAddrs.push_back(device->getDeviceTypeAddr());
+    }
+    return deviceTypeAddrs;
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/TEST_MAPPING b/media/libaudiofoundation/TEST_MAPPING
new file mode 100644
index 0000000..f6d249a
--- /dev/null
+++ b/media/libaudiofoundation/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+       "name": "audiofoundation_parcelable_test"
+    }
+  ]
+}
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
new file mode 100644
index 0000000..72fda49
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <set>
+#include <vector>
+
+#include <media/TypeConverter.h>
+#include <system/audio.h>
+
+namespace android {
+
+using ChannelMaskSet = std::set<audio_channel_mask_t>;
+using DeviceTypeSet = std::set<audio_devices_t>;
+using FormatSet = std::set<audio_format_t>;
+using SampleRateSet = std::set<uint32_t>;
+
+using FormatVector = std::vector<audio_format_t>;
+
+const DeviceTypeSet& getAudioDeviceOutAllSet();
+const DeviceTypeSet& getAudioDeviceOutAllA2dpSet();
+const DeviceTypeSet& getAudioDeviceOutAllScoSet();
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet();
+const DeviceTypeSet& getAudioDeviceInAllSet();
+const DeviceTypeSet& getAudioDeviceInAllUsbSet();
+
+template<typename T>
+static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
+    std::vector<T> intersection;
+    std::set_intersection(a.begin(), a.end(),
+                          b.begin(), b.end(),
+                          std::back_inserter(intersection));
+    return intersection;
+}
+
+static inline ChannelMaskSet asInMask(const ChannelMaskSet& channelMasks) {
+    ChannelMaskSet inMaskSet;
+    for (const auto &channel : channelMasks) {
+        if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
+            inMaskSet.insert(audio_channel_mask_out_to_in(channel));
+        }
+    }
+    return inMaskSet;
+}
+
+static inline ChannelMaskSet asOutMask(const ChannelMaskSet& channelMasks) {
+    ChannelMaskSet outMaskSet;
+    for (const auto &channel : channelMasks) {
+        if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
+            outMaskSet.insert(audio_channel_mask_in_to_out(channel));
+        }
+    }
+    return outMaskSet;
+}
+
+static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
+                                      audio_devices_t deviceType) {
+    return deviceTypes.size() == 1 && *(deviceTypes.begin()) == deviceType;
+}
+
+typedef bool (*DeviceTypeUnaryPredicate)(audio_devices_t);
+static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
+                                      DeviceTypeUnaryPredicate p) {
+    return deviceTypes.size() == 1 && p(*(deviceTypes.begin()));
+}
+
+static inline bool areAllOfSameDeviceType(const DeviceTypeSet& deviceTypes,
+                                          std::function<bool(audio_devices_t)> p) {
+    return std::all_of(deviceTypes.begin(), deviceTypes.end(), p);
+}
+
+static inline void resetDeviceTypes(DeviceTypeSet& deviceTypes, audio_devices_t typeToAdd) {
+    deviceTypes.clear();
+    deviceTypes.insert(typeToAdd);
+}
+
+// FIXME: This is temporary helper function. Remove this when getting rid of all
+//  bit mask usages of audio device types.
+static inline audio_devices_t deviceTypesToBitMask(const DeviceTypeSet& deviceTypes) {
+    audio_devices_t types = AUDIO_DEVICE_NONE;
+    for (auto deviceType : deviceTypes) {
+        types |= deviceType;
+    }
+    return types;
+}
+
+// FIXME: This is temporary helper function. Remove this when getting rid of all
+//  bit mask usages of audio device types.
+static inline DeviceTypeSet deviceTypesFromBitMask(audio_devices_t types) {
+    DeviceTypeSet deviceTypes;
+    if ((types & AUDIO_DEVICE_BIT_IN) == 0) {
+        for (auto deviceType : AUDIO_DEVICE_OUT_ALL_ARRAY) {
+            if ((types & deviceType) == deviceType) {
+                deviceTypes.insert(deviceType);
+            }
+        }
+    } else {
+        for (auto deviceType : AUDIO_DEVICE_IN_ALL_ARRAY) {
+            if ((types & deviceType) == deviceType) {
+                deviceTypes.insert(deviceType);
+            }
+        }
+    }
+    return deviceTypes;
+}
+
+bool deviceTypesToString(const DeviceTypeSet& deviceTypes, std::string &str);
+
+std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
+
+/**
+ * Return human readable string for device types.
+ */
+std::string toString(const DeviceTypeSet& deviceTypes);
+
+
+} // namespace android
\ No newline at end of file
diff --git a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
new file mode 100644
index 0000000..60ea78e
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <binder/Parcelable.h>
+#include <binder/Parcel.h>
+#include <media/AudioContainers.h>
+#include <system/audio.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct AudioDeviceTypeAddr : public Parcelable {
+    AudioDeviceTypeAddr() = default;
+
+    AudioDeviceTypeAddr(audio_devices_t type, const std::string& address) :
+            mType(type), mAddress(address) {}
+
+    const char* getAddress() const;
+
+    bool equals(const AudioDeviceTypeAddr& other) const;
+
+    AudioDeviceTypeAddr& operator= (const AudioDeviceTypeAddr&) = default;
+
+    bool operator<(const AudioDeviceTypeAddr& other) const;
+
+    void reset();
+
+    status_t readFromParcel(const Parcel *parcel) override;
+
+    status_t writeToParcel(Parcel *parcel) const override;
+
+    audio_devices_t mType = AUDIO_DEVICE_NONE;
+    std::string mAddress;
+};
+
+using AudioDeviceTypeAddrVector = std::vector<AudioDeviceTypeAddr>;
+
+/**
+ * Return a collection of audio device types from a collection of AudioDeviceTypeAddr
+ */
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs);
+
+}
diff --git a/media/libaudiofoundation/include/media/AudioGain.h b/media/libaudiofoundation/include/media/AudioGain.h
new file mode 100644
index 0000000..859f1e7
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioGain.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+#include <string>
+#include <vector>
+
+namespace android {
+
+class AudioGain: public RefBase, public Parcelable
+{
+public:
+    AudioGain(int index, bool useInChannelMask);
+    virtual ~AudioGain() {}
+
+    void setMode(audio_gain_mode_t mode) { mGain.mode = mode; }
+    const audio_gain_mode_t &getMode() const { return mGain.mode; }
+
+    void setChannelMask(audio_channel_mask_t mask) { mGain.channel_mask = mask; }
+    const audio_channel_mask_t &getChannelMask() const { return mGain.channel_mask; }
+
+    void setMinValueInMb(int minValue) { mGain.min_value = minValue; }
+    int getMinValueInMb() const { return mGain.min_value; }
+
+    void setMaxValueInMb(int maxValue) { mGain.max_value = maxValue; }
+    int getMaxValueInMb() const { return mGain.max_value; }
+
+    void setDefaultValueInMb(int defaultValue) { mGain.default_value = defaultValue; }
+    int getDefaultValueInMb() const { return mGain.default_value; }
+
+    void setStepValueInMb(uint32_t stepValue) { mGain.step_value = stepValue; }
+    int getStepValueInMb() const { return mGain.step_value; }
+
+    void setMinRampInMs(uint32_t minRamp) { mGain.min_ramp_ms = minRamp; }
+    int getMinRampInMs() const { return mGain.min_ramp_ms; }
+
+    void setMaxRampInMs(uint32_t maxRamp) { mGain.max_ramp_ms = maxRamp; }
+    int getMaxRampInMs() const { return mGain.max_ramp_ms; }
+
+    // TODO: remove dump from here (split serialization)
+    void dump(std::string *dst, int spaces, int index) const;
+
+    void getDefaultConfig(struct audio_gain_config *config);
+    status_t checkConfig(const struct audio_gain_config *config);
+
+    void setUseForVolume(bool canUseForVolume) { mUseForVolume = canUseForVolume; }
+    bool canUseForVolume() const { return mUseForVolume; }
+
+    const struct audio_gain &getGain() const { return mGain; }
+
+    bool equals(const sp<AudioGain>& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+private:
+    int               mIndex;
+    struct audio_gain mGain;
+    bool              mUseInChannelMask;
+    bool              mUseForVolume = false;
+};
+
+class AudioGains : public std::vector<sp<AudioGain> >, public Parcelable
+{
+public:
+    bool canUseForVolume() const
+    {
+        for (const auto &gain: *this) {
+            if (gain->canUseForVolume()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    int32_t add(const sp<AudioGain> gain)
+    {
+        push_back(gain);
+        return 0;
+    }
+
+    bool equals(const AudioGains& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+};
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
new file mode 100644
index 0000000..3c013cb
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <media/AudioGain.h>
+#include <media/AudioProfile.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
+namespace android {
+
+class AudioPort : public virtual RefBase, public virtual Parcelable
+{
+public:
+    AudioPort(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
+            mName(name), mType(type), mRole(role) {}
+
+    virtual ~AudioPort() = default;
+
+    void setName(const std::string &name) { mName = name; }
+    const std::string &getName() const { return mName; }
+
+    audio_port_type_t getType() const { return mType; }
+    audio_port_role_t getRole() const { return mRole; }
+
+    void setGains(const AudioGains &gains) { mGains = gains; }
+    const AudioGains &getGains() const { return mGains; }
+
+    virtual void toAudioPort(struct audio_port *port) const;
+
+    virtual void addAudioProfile(const sp<AudioProfile> &profile) {
+        mProfiles.add(profile);
+    }
+    virtual void clearAudioProfiles() {
+        mProfiles.clearProfiles();
+    }
+
+    bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
+
+    bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
+
+    void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
+    AudioProfileVector &getAudioProfiles() { return mProfiles; }
+
+    virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
+
+    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
+        if (index < 0 || (size_t)index >= mGains.size()) {
+            return BAD_VALUE;
+        }
+        return mGains[index]->checkConfig(gainConfig);
+    }
+
+    bool useInputChannelMask() const
+    {
+        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
+                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
+    }
+
+    void dump(std::string *dst, int spaces, bool verbose = true) const;
+
+    void log(const char* indent) const;
+
+    bool equals(const sp<AudioPort>& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    AudioGains mGains; // gain controllers
+protected:
+    std::string  mName;
+    audio_port_type_t mType;
+    audio_port_role_t mRole;
+    AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
+};
+
+
+class AudioPortConfig : public virtual RefBase, public virtual Parcelable
+{
+public:
+    virtual ~AudioPortConfig() = default;
+
+    virtual sp<AudioPort> getAudioPort() const = 0;
+
+    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+                                          struct audio_port_config *backupConfig = NULL);
+
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+                                   const struct audio_port_config *srcConfig = NULL) const;
+
+    unsigned int getSamplingRate() const { return mSamplingRate; }
+    audio_format_t getFormat() const { return mFormat; }
+    audio_channel_mask_t getChannelMask() const { return mChannelMask; }
+    audio_port_handle_t getId() const { return mId; }
+
+    bool hasGainController(bool canUseForVolume = false) const;
+
+    bool equals(const sp<AudioPortConfig>& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+protected:
+    unsigned int mSamplingRate = 0u;
+    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
+    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
+    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
+    struct audio_gain_config mGain = { .index = -1 };
+};
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
new file mode 100644
index 0000000..730138a
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <media/AudioContainers.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class AudioProfile final : public RefBase, public Parcelable
+{
+public:
+    static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);
+
+    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
+    AudioProfile(audio_format_t format,
+                 const ChannelMaskSet &channelMasks,
+                 const SampleRateSet &samplingRateCollection);
+
+    audio_format_t getFormat() const { return mFormat; }
+    const ChannelMaskSet &getChannels() const { return mChannelMasks; }
+    const SampleRateSet &getSampleRates() const { return mSamplingRates; }
+    void setChannels(const ChannelMaskSet &channelMasks);
+    void setSampleRates(const SampleRateSet &sampleRates);
+
+    void clear();
+    bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
+    bool supportsChannels(audio_channel_mask_t channels) const
+    {
+        return mChannelMasks.count(channels) != 0;
+    }
+    bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
+
+    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
+    bool hasValidRates() const { return !mSamplingRates.empty(); }
+    bool hasValidChannels() const { return !mChannelMasks.empty(); }
+
+    void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
+    bool isDynamicChannels() const { return mIsDynamicChannels; }
+
+    void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
+    bool isDynamicRate() const { return mIsDynamicRate; }
+
+    void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
+    bool isDynamicFormat() const { return mIsDynamicFormat; }
+
+    bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
+
+    void dump(std::string *dst, int spaces) const;
+
+    bool equals(const sp<AudioProfile>& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+private:
+    std::string  mName;
+    audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
+    ChannelMaskSet mChannelMasks;
+    SampleRateSet mSamplingRates;
+
+    bool mIsDynamicFormat = false;
+    bool mIsDynamicChannels = false;
+    bool mIsDynamicRate = false;
+};
+
+class AudioProfileVector : public std::vector<sp<AudioProfile>>, public Parcelable
+{
+public:
+    virtual ~AudioProfileVector() = default;
+
+    virtual ssize_t add(const sp<AudioProfile> &profile);
+
+    // If the profile is dynamic format and has valid format, it will be removed when doing
+    // clearProfiles(). Otherwise, AudioProfile::clear() will be called.
+    virtual void clearProfiles();
+
+    sp<AudioProfile> getFirstValidProfile() const;
+    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
+    bool hasValidProfile() const { return getFirstValidProfile() != 0; }
+
+    FormatVector getSupportedFormats() const;
+    bool hasDynamicChannelsFor(audio_format_t format) const;
+    bool hasDynamicFormat() const;
+    bool hasDynamicProfile() const;
+    bool hasDynamicRateFor(audio_format_t format) const;
+
+    virtual void dump(std::string *dst, int spaces) const;
+
+    bool equals(const AudioProfileVector& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+};
+
+bool operator == (const AudioProfile &left, const AudioProfile &right);
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
new file mode 100644
index 0000000..af04721
--- /dev/null
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <media/AudioContainers.h>
+#include <media/AudioPort.h>
+#include <media/AudioDeviceTypeAddr.h>
+#include <utils/Errors.h>
+#include <cutils/config_utils.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+namespace android {
+
+class DeviceDescriptorBase : public AudioPort, public AudioPortConfig
+{
+public:
+     // Note that empty name refers by convention to a generic device.
+    explicit DeviceDescriptorBase(audio_devices_t type);
+    DeviceDescriptorBase(audio_devices_t type, const std::string& address);
+    explicit DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr);
+
+    virtual ~DeviceDescriptorBase() {}
+
+    audio_devices_t type() const { return mDeviceTypeAddr.mType; }
+    std::string address() const { return mDeviceTypeAddr.mAddress; }
+    void setAddress(const std::string &address) { mDeviceTypeAddr.mAddress = address; }
+    const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
+
+    // AudioPortConfig
+    virtual sp<AudioPort> getAudioPort() const {
+        return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
+    }
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+            const struct audio_port_config *srcConfig = NULL) const;
+
+    // AudioPort
+    virtual void toAudioPort(struct audio_port *port) const;
+
+    status_t setEncapsulationModes(uint32_t encapsulationModes);
+    status_t setEncapsulationMetadataTypes(uint32_t encapsulationMetadataTypes);
+
+    void dump(std::string *dst, int spaces, int index,
+              const char* extraInfo = nullptr, bool verbose = true) const;
+    void log() const;
+    std::string toString() const;
+
+    bool equals(const sp<DeviceDescriptorBase>& other) const;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+protected:
+    AudioDeviceTypeAddr mDeviceTypeAddr;
+    uint32_t mEncapsulationModes = 0;
+    uint32_t mEncapsulationMetadataTypes = 0;
+};
+
+using DeviceDescriptorBaseVector = std::vector<sp<DeviceDescriptorBase>>;
+
+/**
+ * Return human readable string for collection of DeviceDescriptorBase.
+ * For a DeviceDescriptorBase, it contains port id, audio device type and address.
+ */
+std::string toString(const DeviceDescriptorBaseVector& devices);
+
+/**
+ * Return a set of device types and addresses from collection of DeviceDescriptorBase.
+ */
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices);
+
+} // namespace android
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
new file mode 100644
index 0000000..f258b14
--- /dev/null
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -0,0 +1,25 @@
+cc_test {
+    name: "audiofoundation_parcelable_test",
+
+    shared_libs: [
+        "libaudiofoundation",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudio_system_headers",
+    ],
+
+    srcs: [
+        "audiofoundation_parcelable_test.cpp",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
new file mode 100644
index 0000000..068b5d8
--- /dev/null
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 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_TAG "audiofoundation_parcelable_test"
+
+#include <gtest/gtest.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcelable.h>
+#include <binder/ProcessState.h>
+#include <media/AudioGain.h>
+#include <media/AudioPort.h>
+#include <media/AudioProfile.h>
+#include <media/DeviceDescriptorBase.h>
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+namespace android {
+
+static const audio_port_config TEST_AUDIO_PORT_CONFIG = {
+        .id = 0,
+        .role = AUDIO_PORT_ROLE_SINK,
+        .type = AUDIO_PORT_TYPE_DEVICE,
+        .config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE | AUDIO_PORT_CONFIG_CHANNEL_MASK |
+                       AUDIO_PORT_CONFIG_FORMAT | AUDIO_PORT_CONFIG_GAIN,
+        .sample_rate = 48000,
+        .channel_mask = AUDIO_CHANNEL_OUT_STEREO,
+        .format = AUDIO_FORMAT_PCM_16_BIT,
+        .gain = {
+                .index = 0,
+                .mode = AUDIO_GAIN_MODE_JOINT,
+                .channel_mask = AUDIO_CHANNEL_OUT_STEREO,
+        }
+};
+
+class AudioPortConfigTestStub : public AudioPortConfig {
+public:
+    sp<AudioPort> getAudioPort() const override { return nullptr; }
+};
+
+AudioGains getAudioGainsForTest() {
+    AudioGains audioGains;
+    sp<AudioGain> audioGain = new AudioGain(0 /*index*/, false /*useInChannelMask*/);
+    audioGain->setMode(AUDIO_GAIN_MODE_JOINT);
+    audioGain->setChannelMask(AUDIO_CHANNEL_OUT_STEREO);
+    audioGain->setMinValueInMb(-3200);
+    audioGain->setMaxValueInMb(600);
+    audioGain->setDefaultValueInMb(0);
+    audioGain->setStepValueInMb(100);
+    audioGain->setMinRampInMs(100);
+    audioGain->setMaxRampInMs(500);
+    audioGains.push_back(audioGain);
+    return audioGains;
+}
+
+AudioProfileVector getAudioProfileVectorForTest() {
+    AudioProfileVector audioProfiles;
+    sp<AudioProfile> audioProfile = AudioProfile::createFullDynamic();
+    audioProfile->setChannels({AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO});
+    audioProfile->setSampleRates({48000});
+    audioProfiles.add(audioProfile);
+    return audioProfiles;
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingAudioGain) {
+    Parcel data;
+    AudioGains audioGains = getAudioGainsForTest();
+
+    ASSERT_EQ(data.writeParcelable(audioGains), NO_ERROR);
+    data.setDataPosition(0);
+    AudioGains audioGainsFromParcel;
+    ASSERT_EQ(data.readParcelable(&audioGainsFromParcel), NO_ERROR);
+    ASSERT_TRUE(audioGainsFromParcel.equals(audioGains));
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingAudioProfileVector) {
+    Parcel data;
+    AudioProfileVector audioProfiles = getAudioProfileVectorForTest();
+
+    ASSERT_EQ(data.writeParcelable(audioProfiles), NO_ERROR);
+    data.setDataPosition(0);
+    AudioProfileVector audioProfilesFromParcel;
+    ASSERT_EQ(data.readParcelable(&audioProfilesFromParcel), NO_ERROR);
+    ASSERT_TRUE(audioProfilesFromParcel.equals(audioProfiles));
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingAudioPort) {
+    Parcel data;
+    sp<AudioPort> audioPort = new AudioPort(
+            "AudioPortName", AUDIO_PORT_TYPE_DEVICE, AUDIO_PORT_ROLE_SINK);
+    audioPort->setGains(getAudioGainsForTest());
+    audioPort->setAudioProfiles(getAudioProfileVectorForTest());
+
+    ASSERT_EQ(data.writeParcelable(*audioPort), NO_ERROR);
+    data.setDataPosition(0);
+    sp<AudioPort> audioPortFromParcel = new AudioPort(
+            "", AUDIO_PORT_TYPE_NONE, AUDIO_PORT_ROLE_NONE);
+    ASSERT_EQ(data.readParcelable(audioPortFromParcel.get()), NO_ERROR);
+    ASSERT_TRUE(audioPortFromParcel->equals(audioPort));
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingAudioPortConfig) {
+    Parcel data;
+    sp<AudioPortConfig> audioPortConfig = new AudioPortConfigTestStub();
+    audioPortConfig->applyAudioPortConfig(&TEST_AUDIO_PORT_CONFIG);
+
+    ASSERT_EQ(data.writeParcelable(*audioPortConfig), NO_ERROR);
+    data.setDataPosition(0);
+    sp<AudioPortConfig> audioPortConfigFromParcel = new AudioPortConfigTestStub();
+    ASSERT_EQ(data.readParcelable(audioPortConfigFromParcel.get()), NO_ERROR);
+    ASSERT_TRUE(audioPortConfigFromParcel->equals(audioPortConfig));
+}
+
+TEST(AudioFoundationParcelableTest, ParcelingDeviceDescriptorBase) {
+    Parcel data;
+    sp<DeviceDescriptorBase> desc = new DeviceDescriptorBase(AUDIO_DEVICE_OUT_SPEAKER);
+    desc->setGains(getAudioGainsForTest());
+    desc->setAudioProfiles(getAudioProfileVectorForTest());
+    desc->applyAudioPortConfig(&TEST_AUDIO_PORT_CONFIG);
+    desc->setAddress("DeviceDescriptorBaseTestAddress");
+    ASSERT_EQ(desc->setEncapsulationModes(1 << AUDIO_ENCAPSULATION_MODE_HANDLE), NO_ERROR);
+    ASSERT_EQ(desc->setEncapsulationMetadataTypes(
+            AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS), NO_ERROR);
+
+    ASSERT_EQ(data.writeParcelable(*desc), NO_ERROR);
+    data.setDataPosition(0);
+    sp<DeviceDescriptorBase> descFromParcel = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
+    ASSERT_EQ(data.readParcelable(descFromParcel.get()), NO_ERROR);
+    ASSERT_TRUE(descFromParcel->equals(desc));
+}
+
+} // namespace android
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 584c2c0..1709d1e 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -4,6 +4,7 @@
     srcs: [
         "DevicesFactoryHalInterface.cpp",
         "EffectsFactoryHalInterface.cpp",
+        "FactoryHalHidl.cpp",
     ],
 
     cflags: [
@@ -12,21 +13,23 @@
         "-Werror",
     ],
 
-    shared_libs: [
-        "android.hardware.audio.effect@2.0",
-        "android.hardware.audio.effect@4.0",
-        "android.hardware.audio.effect@5.0",
-        "android.hardware.audio@2.0",
-        "android.hardware.audio@4.0",
-        "android.hardware.audio@5.0",
+    required: [
         "libaudiohal@2.0",
         "libaudiohal@4.0",
         "libaudiohal@5.0",
+        "libaudiohal@6.0",
+    ],
+
+    shared_libs: [
+        "libdl",
+        "libhidlbase",
+        "liblog",
         "libutils",
     ],
 
     header_libs: [
-        "libaudiohal_headers"
+        "libaudiohal_headers",
+        "libbase_headers",
     ]
 }
 
@@ -57,4 +60,10 @@
     name: "libaudiohal_headers",
 
     export_include_dirs: ["include"],
+
+    // This is needed because the stream interface includes media/MicrophoneInfo.h
+    // which is not in any library but has a dependency on headers from libbinder.
+    header_libs: ["libbinder_headers"],
+
+    export_header_lib_headers: ["libbinder_headers"],
 }
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
index f86009c..325a547 100644
--- a/media/libaudiohal/DevicesFactoryHalInterface.cpp
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -14,26 +14,15 @@
  * limitations under the License.
  */
 
-#include <android/hardware/audio/2.0/IDevicesFactory.h>
-#include <android/hardware/audio/4.0/IDevicesFactory.h>
-#include <android/hardware/audio/5.0/IDevicesFactory.h>
-
-#include <libaudiohal/FactoryHalHidl.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <media/audiohal/FactoryHalHidl.h>
 
 namespace android {
 
 // static
 sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
-    if (hardware::audio::V5_0::IDevicesFactory::getService() != nullptr) {
-        return V5_0::createDevicesFactoryHal();
-    }
-    if (hardware::audio::V4_0::IDevicesFactory::getService() != nullptr) {
-        return V4_0::createDevicesFactoryHal();
-    }
-    if (hardware::audio::V2_0::IDevicesFactory::getService() != nullptr) {
-        return V2_0::createDevicesFactoryHal();
-    }
-    return nullptr;
+    return createPreferredImpl<DevicesFactoryHalInterface>(
+            "android.hardware.audio", "IDevicesFactory");
 }
 
 } // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index bd3ef61..bc3b4c1 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,26 +14,15 @@
  * limitations under the License.
  */
 
-#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
-#include <android/hardware/audio/effect/4.0/IEffectsFactory.h>
-#include <android/hardware/audio/effect/5.0/IEffectsFactory.h>
-
-#include <libaudiohal/FactoryHalHidl.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <media/audiohal/FactoryHalHidl.h>
 
 namespace android {
 
 // static
 sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
-    if (hardware::audio::effect::V5_0::IEffectsFactory::getService() != nullptr) {
-        return effect::V5_0::createEffectsFactoryHal();
-    }
-    if (hardware::audio::effect::V4_0::IEffectsFactory::getService() != nullptr) {
-        return effect::V4_0::createEffectsFactoryHal();
-    }
-    if (hardware::audio::effect::V2_0::IEffectsFactory::getService() != nullptr) {
-        return effect::V2_0::createEffectsFactoryHal();
-    }
-    return nullptr;
+    return createPreferredImpl<EffectsFactoryHalInterface>(
+            "android.hardware.audio.effect", "IEffectsFactory");
 }
 
 // static
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
new file mode 100644
index 0000000..5985ef0
--- /dev/null
+++ b/media/libaudiohal/FactoryHalHidl.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FactoryHalHidl"
+
+#include <media/audiohal/FactoryHalHidl.h>
+
+#include <dlfcn.h>
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+namespace android::detail {
+
+namespace {
+/** Supported HAL versions, in order of preference.
+ */
+const char* sAudioHALVersions[] = {
+    "6.0",
+    "5.0",
+    "4.0",
+    "2.0",
+    nullptr
+};
+
+bool createHalService(const std::string& version, const std::string& interface,
+        void** rawInterface) {
+    const std::string libName = "libaudiohal@" + version + ".so";
+    const std::string factoryFunctionName = "create" + interface;
+    constexpr int dlMode = RTLD_LAZY;
+    void* handle = nullptr;
+    dlerror(); // clear
+    handle = dlopen(libName.c_str(), dlMode);
+    if (handle == nullptr) {
+        const char* error = dlerror();
+        ALOGE("Failed to dlopen %s: %s", libName.c_str(),
+                error != nullptr ? error : "unknown error");
+        return false;
+    }
+    void* (*factoryFunction)();
+    *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
+    if (!factoryFunction) {
+        const char* error = dlerror();
+        ALOGE("Factory function %s not found in library %s: %s",
+                factoryFunctionName.c_str(), libName.c_str(),
+                error != nullptr ? error : "unknown error");
+        dlclose(handle);
+        return false;
+    }
+    *rawInterface = (*factoryFunction)();
+    ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
+            factoryFunctionName.c_str(), libName.c_str());
+    return true;
+}
+
+bool hasHalService(const std::string& package, const std::string& version,
+        const std::string& interface) {
+    using ::android::hidl::manager::V1_0::IServiceManager;
+    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
+    if (!sm) {
+        ALOGE("Failed to obtain HIDL ServiceManager");
+        return false;
+    }
+    // Since audio HAL doesn't support multiple clients, avoid instantiating
+    // the interface right away. Instead, query the transport type for it.
+    using ::android::hardware::Return;
+    using Transport = IServiceManager::Transport;
+    const std::string fqName = package + "@" + version + "::" + interface;
+    const std::string instance = "default";
+    Return<Transport> transport = sm->getTransport(fqName, instance);
+    if (!transport.isOk()) {
+        ALOGE("Failed to obtain transport type for %s/%s: %s",
+                fqName.c_str(), instance.c_str(), transport.description().c_str());
+        return false;
+    }
+    return transport != Transport::EMPTY;
+}
+
+}  // namespace
+
+void* createPreferredImpl(const std::string& package, const std::string& interface) {
+    for (auto version = detail::sAudioHALVersions; version != nullptr; ++version) {
+        void* rawInterface = nullptr;
+        if (hasHalService(package, *version, interface)
+                && createHalService(*version, interface, &rawInterface)) {
+            return rawInterface;
+        }
+    }
+    return nullptr;
+}
+
+}  // namespace android::detail
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 88533da..967fba1 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -16,17 +16,17 @@
         "StreamHalHidl.cpp",
     ],
 
-    export_include_dirs: ["include"],
-
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-fvisibility=hidden",
     ],
     shared_libs: [
         "android.hardware.audio.common-util",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libaudiofoundation",
         "libaudiohal_deathhandler",
         "libaudioutils",
         "libbase",
@@ -36,8 +36,6 @@
         "libhardware",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libmedia_helper",
         "libmediautils",
@@ -45,6 +43,7 @@
     ],
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
+        "libaudioclient_headers",
         "libaudiohal_headers"
     ],
 
@@ -100,3 +99,20 @@
         "-include common/all-versions/VersionMacro.h",
     ]
 }
+
+cc_library_shared {
+    name: "libaudiohal@6.0",
+    defaults: ["libaudiohal_default"],
+    shared_libs: [
+        "android.hardware.audio.common@6.0",
+        "android.hardware.audio.common@6.0-util",
+        "android.hardware.audio.effect@6.0",
+        "android.hardware.audio@6.0",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=6",
+        "-DMINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ]
+}
+
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index 9f8a520..ebed5fd 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -17,6 +17,7 @@
 #include <string.h>
 
 #define LOG_TAG "HalHidl"
+#include <media/AudioContainers.h>
 #include <media/AudioParameter.h>
 #include <utils/Log.h>
 
@@ -40,16 +41,25 @@
     bool keepFormatValue = halKeys.size() == 2 &&
          (halKeys.get(String8(AudioParameter::keyStreamSupportedChannels), value) == NO_ERROR ||
          halKeys.get(String8(AudioParameter::keyStreamSupportedSamplingRates), value) == NO_ERROR);
+    // When querying encapsulation capabilities, "keyRouting=<value>" pair is used to identify
+    // the device. We need to transform it into a single key string so that it is carried over to
+    // the legacy HAL via HIDL.
+    bool keepRoutingValue =
+            halKeys.get(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES),
+                        value) == NO_ERROR ||
+            halKeys.get(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES),
+                        value) == NO_ERROR;
 
     for (size_t i = 0; i < halKeys.size(); ++i) {
         String8 key;
         status_t status = halKeys.getAt(i, key);
         if (status != OK) return status;
-        if (keepFormatValue && key == AudioParameter::keyFormat) {
-            AudioParameter formatParam;
+        if ((keepFormatValue && key == AudioParameter::keyFormat) ||
+            (keepRoutingValue && key == AudioParameter::keyRouting)) {
+            AudioParameter keepValueParam;
             halKeys.getAt(i, key, value);
-            formatParam.add(key, value);
-            key = formatParam.toString();
+            keepValueParam.add(key, value);
+            key = keepValueParam.toString();
         }
         (*hidlKeys)[i] = key.string();
     }
@@ -109,26 +119,22 @@
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
     memset(halAddress, 0, sizeof(halAddress));
     audio_devices_t halDevice = static_cast<audio_devices_t>(address.device);
-    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
-        (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
+        halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
                  address.address.mac[0], address.address.mac[1], address.address.mac[2],
                  address.address.mac[3], address.address.mac[4], address.address.mac[5]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_IP || halDevice == AUDIO_DEVICE_IN_IP) {
         snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
                  address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
+    } else if (getAudioDeviceOutAllUsbSet().count(halDevice) > 0 ||
+               getAudioDeviceInAllUsbSet().count(halDevice) > 0) {
         snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
                  address.address.alsa.device);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_BUS || halDevice == AUDIO_DEVICE_IN_BUS) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+               halDevice == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
     } else {
         snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index b25f82e..7d0d83d 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -22,11 +22,13 @@
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
 #include <cutils/native_handle.h>
 #include <hwbinder/IPCThreadState.h>
+#include <media/AudioContainers.h>
 #include <utils/Log.h>
 
 #include <common/all-versions/VersionUtils.h>
 
 #include "DeviceHalHidl.h"
+#include "EffectHalHidl.h"
 #include "HidlUtils.h"
 #include "StreamHalHidl.h"
 #include "VersionUtils.h"
@@ -42,6 +44,8 @@
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
+using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
+
 namespace {
 
 status_t deviceAddressFromHal(
@@ -51,42 +55,32 @@
     if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
         return OK;
     }
-    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(device) > 0
+            || device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         int status = sscanf(halAddress,
                 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
                 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
                 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
         return status == 6 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
         int status = sscanf(halAddress,
                 "%hhu.%hhu.%hhu.%hhu",
                 &address->address.ipv4[0], &address->address.ipv4[1],
                 &address->address.ipv4[2], &address->address.ipv4[3]);
         return status == 4 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
-            || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+    } else if (getAudioDeviceOutAllUsbSet().count(device) > 0
+            || getAudioDeviceInAllUsbSet().count(device) > 0) {
         int status = sscanf(halAddress,
                 "card=%d;device=%d",
                 &address->address.alsa.card, &address->address.alsa.device);
         return status == 2 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
-            || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
-        if (halAddress != NULL) {
-            address->busAddress = halAddress;
-            return OK;
-        }
-        return BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
-            || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
-        if (halAddress != NULL) {
-            address->rSubmixAddress = halAddress;
-            return OK;
-        }
-        return BAD_VALUE;
+    } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
+        address->busAddress = halAddress;
+        return OK;
+    } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+            || device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+        address->rSubmixAddress = halAddress;
+        return OK;
     }
     return OK;
 }
@@ -100,8 +94,12 @@
 
 DeviceHalHidl::~DeviceHalHidl() {
     if (mDevice != 0) {
+#if MAJOR_VERSION <= 5
         mDevice.clear();
         hardware::IPCThreadState::self()->flushCommands();
+#elif MAJOR_VERSION >= 6
+        mDevice->close();
+#endif
     }
 }
 
@@ -229,14 +227,14 @@
 
 status_t DeviceHalHidl::openOutputStream(
         audio_io_handle_t handle,
-        audio_devices_t devices,
+        audio_devices_t deviceType,
         audio_output_flags_t flags,
         struct audio_config *config,
         const char *address,
         sp<StreamOutHalInterface> *outStream) {
     if (mDevice == 0) return NO_INIT;
     DeviceAddress hidlDevice;
-    status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
+    status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
     if (status != OK) return status;
     AudioConfig hidlConfig;
     HidlUtils::audioConfigFromHal(*config, &hidlConfig);
@@ -294,6 +292,10 @@
         sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
     }
 #endif
+#if MAJOR_VERSION <= 5
+    // Some flags were specific to framework and must not leak to the HAL.
+    flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
+#endif
     Return<void> ret = mDevice->openInputStream(
             handle,
             hidlDevice,
@@ -322,19 +324,47 @@
         const struct audio_port_config *sinks,
         audio_patch_handle_t *patch) {
     if (mDevice == 0) return NO_INIT;
+    if (patch == nullptr) return BAD_VALUE;
+
+#if MAJOR_VERSION < 6
+    if (*patch != AUDIO_PATCH_HANDLE_NONE) {
+        status_t status = releaseAudioPatch(*patch);
+        ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
+            __func__, status, *patch);
+        *patch = AUDIO_PATCH_HANDLE_NONE;
+    }
+#endif
+
     hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
     HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
     HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
-    Result retval;
-    Return<void> ret = mDevice->createAudioPatch(
-            hidlSources, hidlSinks,
-            [&](Result r, AudioPatchHandle hidlPatch) {
-                retval = r;
-                if (retval == Result::OK) {
-                    *patch = static_cast<audio_patch_handle_t>(hidlPatch);
-                }
-            });
-    return processReturn("createAudioPatch", ret, retval);
+    Result retval = Result::OK;
+    Return<void> ret;
+    std::string methodName = "createAudioPatch";
+    if (*patch == AUDIO_PATCH_HANDLE_NONE) {  // always true for MAJOR_VERSION < 6
+        ret = mDevice->createAudioPatch(
+                hidlSources, hidlSinks,
+                [&](Result r, AudioPatchHandle hidlPatch) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        *patch = static_cast<audio_patch_handle_t>(hidlPatch);
+                    }
+                });
+    } else {
+#if MAJOR_VERSION >= 6
+        ret = mDevice->updateAudioPatch(
+                *patch,
+                hidlSources, hidlSinks,
+                [&](Result r, AudioPatchHandle hidlPatch) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        *patch = static_cast<audio_patch_handle_t>(hidlPatch);
+                    }
+                });
+        methodName = "updateAudioPatch";
+#endif
+    }
+    return processReturn(methodName.c_str(), ret, retval);
 }
 
 status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
@@ -390,6 +420,36 @@
 }
 #endif
 
+#if MAJOR_VERSION >= 6
+status_t DeviceHalHidl::addDeviceEffect(
+        audio_port_handle_t device, sp<EffectHalInterface> effect) {
+    if (mDevice == 0) return NO_INIT;
+    return processReturn("addDeviceEffect", mDevice->addDeviceEffect(
+            static_cast<AudioPortHandle>(device),
+            static_cast<EffectHalHidl*>(effect.get())->effectId()));
+}
+#else
+status_t DeviceHalHidl::addDeviceEffect(
+        audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+    return INVALID_OPERATION;
+}
+#endif
+
+#if MAJOR_VERSION >= 6
+status_t DeviceHalHidl::removeDeviceEffect(
+        audio_port_handle_t device, sp<EffectHalInterface> effect) {
+    if (mDevice == 0) return NO_INIT;
+    return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect(
+            static_cast<AudioPortHandle>(device),
+            static_cast<EffectHalHidl*>(effect.get())->effectId()));
+}
+#else
+status_t DeviceHalHidl::removeDeviceEffect(
+        audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+    return INVALID_OPERATION;
+}
+#endif
+
 status_t DeviceHalHidl::dump(int fd) {
     if (mDevice == 0) return NO_INIT;
     native_handle_t* hidlHandle = native_handle_create(1, 0);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index f7d465f..d342d4a 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -113,6 +113,9 @@
     // List microphones
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
 
+    status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+    status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
     virtual status_t dump(int fd);
 
   private:
diff --git a/media/libaudiohal/impl/DeviceHalLocal.cpp b/media/libaudiohal/impl/DeviceHalLocal.cpp
index ee68252..8021d92 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.cpp
+++ b/media/libaudiohal/impl/DeviceHalLocal.cpp
@@ -104,7 +104,7 @@
 
 status_t DeviceHalLocal::openOutputStream(
         audio_io_handle_t handle,
-        audio_devices_t devices,
+        audio_devices_t deviceType,
         audio_output_flags_t flags,
         struct audio_config *config,
         const char *address,
@@ -112,11 +112,11 @@
     audio_stream_out_t *halStream;
     ALOGV("open_output_stream handle: %d devices: %x flags: %#x"
             "srate: %d format %#x channels %x address %s",
-            handle, devices, flags,
+            handle, deviceType, flags,
             config->sample_rate, config->format, config->channel_mask,
             address);
     int openResut = mDev->open_output_stream(
-            mDev, handle, devices, flags, config, &halStream, address);
+            mDev, handle, deviceType, flags, config, &halStream, address);
     if (openResut == OK) {
         *outStream = new StreamOutHalLocal(halStream, this);
     }
@@ -206,6 +206,17 @@
 }
 #endif
 
+// Local HAL implementation does not support effects
+status_t DeviceHalLocal::addDeviceEffect(
+        audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalLocal::removeDeviceEffect(
+        audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+    return INVALID_OPERATION;
+}
+
 status_t DeviceHalLocal::dump(int fd) {
     return mDev->dump(mDev, fd);
 }
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 36db72e..d85e2a7 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -106,6 +106,9 @@
     // List microphones
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
 
+    status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+    status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
     virtual status_t dump(int fd);
 
     void closeOutputStream(struct audio_stream_out *stream_out);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 5e01e42..1c0eacb 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -15,11 +15,13 @@
  */
 
 #include <string.h>
-#include <vector>
+#include <set>
 
 #define LOG_TAG "DevicesFactoryHalHidl"
 //#define LOG_NDEBUG 0
 
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
 #include <media/audiohal/hidl/HalDeathHandler.h>
 #include <utils/Log.h>
@@ -31,31 +33,54 @@
 using ::android::hardware::audio::CPP_VERSION::IDevice;
 using ::android::hardware::audio::CPP_VERSION::Result;
 using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
 
 namespace android {
 namespace CPP_VERSION {
 
-DevicesFactoryHalHidl::DevicesFactoryHalHidl() {
-    sp<IDevicesFactory> defaultFactory{IDevicesFactory::getService()};
-    if (!defaultFactory) {
-        ALOGE("Failed to obtain IDevicesFactory/default service, terminating process.");
-        exit(1);
-    }
-    mDeviceFactories.push_back(defaultFactory);
-    if (MAJOR_VERSION >= 4) {
-        // The MSD factory is optional and only available starting at HAL 4.0
-        sp<IDevicesFactory> msdFactory{IDevicesFactory::getService(AUDIO_HAL_SERVICE_NAME_MSD)};
-        if (msdFactory) {
-            mDeviceFactories.push_back(msdFactory);
+class ServiceNotificationListener : public IServiceNotification {
+  public:
+    explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
+            : mFactory(factory) {}
+
+    Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
+            const hidl_string& instance_name,
+            bool /*pre_existing*/) override {
+        if (static_cast<std::string>(instance_name) == "default") return Void();
+        sp<DevicesFactoryHalHidl> factory = mFactory.promote();
+        if (!factory) return Void();
+        sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name);
+        if (halFactory) {
+            factory->addDeviceFactory(halFactory, true /*needToNotify*/);
         }
+        return Void();
     }
-    for (const auto& factory : mDeviceFactories) {
-        // It is assumed that the DevicesFactoryHalInterface instance is owned
-        // by AudioFlinger and thus have the same lifespan.
-        factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
-    }
+
+  private:
+    wp<DevicesFactoryHalHidl> mFactory;
+};
+
+DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
+    ALOG_ASSERT(devicesFactory != nullptr, "Provided default IDevicesFactory service is NULL");
+    addDeviceFactory(devicesFactory, false /*needToNotify*/);
 }
 
+void DevicesFactoryHalHidl::onFirstRef() {
+    sp<IServiceManager> sm = IServiceManager::getService();
+    ALOG_ASSERT(sm != nullptr, "Hardware service manager is not running");
+    sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
+    Return<bool> result = sm->registerForNotifications(
+            IDevicesFactory::descriptor, "", listener);
+    if (result.isOk()) {
+        ALOGE_IF(!static_cast<bool>(result),
+                "Hardware service manager refused to register listener");
+    } else {
+        ALOGE("Failed to register for hardware service manager notifications: %s",
+                result.description().c_str());
+    }
+}
 
 #if MAJOR_VERSION == 2
 static IDevicesFactory::Device idFromHal(const char *name, status_t* status) {
@@ -83,12 +108,13 @@
 #endif
 
 status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
-    if (mDeviceFactories.empty()) return NO_INIT;
+    auto factories = copyDeviceFactories();
+    if (factories.empty()) return NO_INIT;
     status_t status;
     auto hidlId = idFromHal(name, &status);
     if (status != OK) return status;
     Result retval = Result::NOT_INITIALIZED;
-    for (const auto& factory : mDeviceFactories) {
+    for (const auto& factory : factories) {
         Return<void> ret = factory->openDevice(
                 hidlId,
                 [&](Result r, const sp<IDevice>& result) {
@@ -111,5 +137,71 @@
     return BAD_VALUE;
 }
 
+status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
+    std::set<pid_t> pidsSet;
+    auto factories = copyDeviceFactories();
+    for (const auto& factory : factories) {
+        using ::android::hidl::base::V1_0::DebugInfo;
+
+        DebugInfo debugInfo;
+        auto ret = factory->getDebugInfo([&] (const auto &info) {
+               debugInfo = info;
+            });
+        if (!ret.isOk()) {
+           return INVALID_OPERATION;
+        }
+        if (debugInfo.pid == (int)IServiceManager::PidConstant::NO_PID) {
+            continue;
+        }
+        pidsSet.insert(debugInfo.pid);
+    }
+
+    *pids = {pidsSet.begin(), pidsSet.end()};
+    return NO_ERROR;
+}
+
+status_t DevicesFactoryHalHidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+    ALOG_ASSERT(callback != nullptr);
+    bool needToCallCallback = false;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mCallback.unsafe_get()) return INVALID_OPERATION;
+        mCallback = callback;
+        if (mHaveUndeliveredNotifications) {
+            needToCallCallback = true;
+            mHaveUndeliveredNotifications = false;
+        }
+    }
+    if (needToCallCallback) {
+        callback->onNewDevicesAvailable();
+    }
+    return NO_ERROR;
+}
+
+void DevicesFactoryHalHidl::addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify) {
+    // It is assumed that the DevicesFactoryHalInterface instance is owned
+    // by AudioFlinger and thus have the same lifespan.
+    factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
+    sp<DevicesFactoryHalCallback> callback;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        mDeviceFactories.push_back(factory);
+        if (needToNotify) {
+            callback = mCallback.promote();
+            if (!callback) {
+                mHaveUndeliveredNotifications = true;
+            }
+        }
+    }
+    if (callback) {
+        callback->onNewDevicesAvailable();
+    }
+}
+
+std::vector<sp<IDevicesFactory>> DevicesFactoryHalHidl::copyDeviceFactories() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mDeviceFactories;
+}
+
 } // namespace CPP_VERSION
 } // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 27e0649..6f84efe 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
 #define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
 
+#include <mutex>
+#include <vector>
+
 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <utils/Errors.h>
@@ -32,17 +35,26 @@
 class DevicesFactoryHalHidl : public DevicesFactoryHalInterface
 {
   public:
+    explicit DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
+    void onFirstRef() override;
+
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
-    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+    status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
+
+    status_t getHalPids(std::vector<pid_t> *pids) override;
+
+    status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
 
   private:
-    friend class DevicesFactoryHalHybrid;
+    friend class ServiceNotificationListener;
+    void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
+    std::vector<sp<IDevicesFactory>> copyDeviceFactories();
 
-    std::vector<sp<IDevicesFactory>> mDeviceFactories;
-
-    // Can not be constructed directly by clients.
-    DevicesFactoryHalHidl();
+    std::mutex mLock;
+    std::vector<sp<IDevicesFactory>> mDeviceFactories;  // GUARDED_BY(mLock)
+    wp<DevicesFactoryHalCallback> mCallback;  // GUARDED_BY(mLock)
+    bool mHaveUndeliveredNotifications = false;  // GUARDED_BY(mLock)
 
     virtual ~DevicesFactoryHalHidl() = default;
 };
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
index f337a8b..cde8d85 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
@@ -17,16 +17,16 @@
 #define LOG_TAG "DevicesFactoryHalHybrid"
 //#define LOG_NDEBUG 0
 
+#include "DevicesFactoryHalHidl.h"
 #include "DevicesFactoryHalHybrid.h"
 #include "DevicesFactoryHalLocal.h"
-#include "DevicesFactoryHalHidl.h"
 
 namespace android {
 namespace CPP_VERSION {
 
-DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
+DevicesFactoryHalHybrid::DevicesFactoryHalHybrid(sp<IDevicesFactory> hidlFactory)
         : mLocalFactory(new DevicesFactoryHalLocal()),
-          mHidlFactory(new DevicesFactoryHalHidl()) {
+          mHidlFactory(new DevicesFactoryHalHidl(hidlFactory)) {
 }
 
 status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
@@ -37,5 +37,25 @@
     return mLocalFactory->openDevice(name, device);
 }
 
+status_t DevicesFactoryHalHybrid::getHalPids(std::vector<pid_t> *pids) {
+    if (mHidlFactory != 0) {
+        return mHidlFactory->getHalPids(pids);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t DevicesFactoryHalHybrid::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+    if (mHidlFactory) {
+        return mHidlFactory->setCallbackOnce(callback);
+    }
+    return INVALID_OPERATION;
+}
+
 } // namespace CPP_VERSION
+
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+    auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
+    return service ? new CPP_VERSION::DevicesFactoryHalHybrid(service) : nullptr;
+}
+
 } // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
index 5ac0d0d..568a1fb 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
@@ -17,31 +17,34 @@
 #ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
 #define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HYBRID_H
 
+#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
+using ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
+
 namespace android {
 namespace CPP_VERSION {
 
 class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface
 {
   public:
-    DevicesFactoryHalHybrid();
+    DevicesFactoryHalHybrid(sp<IDevicesFactory> hidlFactory);
 
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
 
+            status_t getHalPids(std::vector<pid_t> *pids) override;
+
+            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
+
   private:
     sp<DevicesFactoryHalInterface> mLocalFactory;
     sp<DevicesFactoryHalInterface> mHidlFactory;
 };
 
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal() {
-    return new DevicesFactoryHalHybrid();
-}
-
 } // namespace CPP_VERSION
 } // namespace android
 
diff --git a/media/libaudiohal/impl/DevicesFactoryHalLocal.h b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
index 5d108dd..32bf362 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalLocal.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
@@ -33,6 +33,14 @@
     // necessary to release references to the returned object.
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
 
+            status_t getHalPids(std::vector<pid_t> *pids __unused) override {
+                return INVALID_OPERATION;
+            }
+
+            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback __unused) override {
+                return INVALID_OPERATION;
+            }
+
   private:
     friend class DevicesFactoryHalHybrid;
 
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 7fd6bde..9192a31 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -19,10 +19,10 @@
 
 #include <cutils/native_handle.h>
 
-#include "EffectsFactoryHalHidl.h"
 #include "ConversionHelperHidl.h"
 #include "EffectBufferHalHidl.h"
 #include "EffectHalHidl.h"
+#include "EffectsFactoryHalHidl.h"
 #include "HidlUtils.h"
 
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
@@ -35,12 +35,10 @@
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
-EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
-    mEffectsFactory = IEffectsFactory::getService();
-    if (mEffectsFactory == 0) {
-        ALOGE("Failed to obtain IEffectsFactory service, terminating process.");
-        exit(1);
-    }
+EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
+        : ConversionHelperHidl("EffectsFactory") {
+    ALOG_ASSERT(effectsFactory != nullptr, "Provided IDevicesFactory service is NULL");
+    mEffectsFactory = effectsFactory;
 }
 
 status_t EffectsFactoryHalHidl::queryAllDescriptors() {
@@ -106,12 +104,26 @@
 
 status_t EffectsFactoryHalHidl::createEffect(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId,
-        sp<EffectHalInterface> *effect) {
+        int32_t deviceId __unused, sp<EffectHalInterface> *effect) {
     if (mEffectsFactory == 0) return NO_INIT;
     Uuid hidlUuid;
     HidlUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
     Result retval = Result::NOT_INITIALIZED;
-    Return<void> ret = mEffectsFactory->createEffect(
+    Return<void> ret;
+#if MAJOR_VERSION >= 6
+    ret = mEffectsFactory->createEffect(
+            hidlUuid, sessionId, ioId, deviceId,
+            [&](Result r, const sp<IEffect>& result, uint64_t effectId) {
+                retval = r;
+                if (retval == Result::OK) {
+                    *effect = new EffectHalHidl(result, effectId);
+                }
+            });
+#else
+    if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    ret = mEffectsFactory->createEffect(
             hidlUuid, sessionId, ioId,
             [&](Result r, const sp<IEffect>& result, uint64_t effectId) {
                 retval = r;
@@ -119,6 +131,7 @@
                     *effect = new EffectHalHidl(result, effectId);
                 }
             });
+#endif
     if (ret.isOk()) {
         if (retval == Result::OK) return OK;
         else if (retval == Result::INVALID_ARGUMENTS) return NAME_NOT_FOUND;
@@ -147,4 +160,10 @@
 
 } // namespace CPP_VERSION
 } // namespace effect
+
+extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
+    auto service = hardware::audio::effect::CPP_VERSION::IEffectsFactory::getService();
+    return service ? new effect::CPP_VERSION::EffectsFactoryHalHidl(service) : nullptr;
+}
+
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 01178ff..dece1bb 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -18,7 +18,6 @@
 #define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
 
 #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
-#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h)
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 
 #include "ConversionHelperHidl.h"
@@ -34,7 +33,7 @@
 class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public ConversionHelperHidl
 {
   public:
-    EffectsFactoryHalHidl();
+    EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory);
 
     // Returns the number of different effects in all loaded libraries.
     virtual status_t queryNumberEffects(uint32_t *pNumEffects);
@@ -50,7 +49,7 @@
     // To release the effect engine, it is necessary to release references
     // to the returned effect object.
     virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
-            int32_t sessionId, int32_t ioId,
+            int32_t sessionId, int32_t ioId, int32_t deviceId,
             sp<EffectHalInterface> *effect);
 
     virtual status_t dumpEffects(int fd);
@@ -66,10 +65,6 @@
     status_t queryAllDescriptors();
 };
 
-sp<EffectsFactoryHalInterface> createEffectsFactoryHal() {
-    return new EffectsFactoryHalHidl();
-}
-
 } // namespace CPP_VERSION
 } // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index c08dddb..2726e36 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -299,10 +299,17 @@
         if (mCallback.unsafe_get()) {
             processReturn("clearCallback", mStream->clearCallback());
         }
+#if MAJOR_VERSION >= 6
+        if (mEventCallback.unsafe_get() != nullptr) {
+            processReturn("setEventCallback",
+                    mStream->setEventCallback(nullptr));
+        }
+#endif
         processReturn("close", mStream->close());
         mStream.clear();
     }
     mCallback.clear();
+    mEventCallback.clear();
     hardware::IPCThreadState::self()->flushCommands();
     if (mEfGroup) {
         EventFlag::deleteEventFlag(&mEfGroup);
@@ -614,6 +621,50 @@
 }
 #endif
 
+#if MAJOR_VERSION < 6
+status_t StreamOutHalHidl::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
+    // Codec format callback is supported starting from audio HAL V6.0
+    return INVALID_OPERATION;
+}
+#else
+
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutEventCallback.h)
+
+namespace {
+
+struct StreamOutEventCallback : public IStreamOutEventCallback {
+    StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
+
+    // IStreamOutEventCallback implementation
+    Return<void> onCodecFormatChanged(
+            const android::hardware::hidl_vec<uint8_t>& audioMetadata)  override {
+        sp<StreamOutHalHidl> stream = mStream.promote();
+        if (stream != nullptr) {
+            std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
+            stream->onCodecFormatChanged(metadataBs);
+        }
+        return Void();
+    }
+
+  private:
+    wp<StreamOutHalHidl> mStream;
+};
+
+}  // namespace
+
+status_t StreamOutHalHidl::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback) {
+    if (mStream == nullptr) return NO_INIT;
+    mEventCallback = callback;
+    status_t status = processReturn(
+            "setEventCallback",
+            mStream->setEventCallback(
+                    callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
+    return status;
+}
+#endif
+
 void StreamOutHalHidl::onWriteReady() {
     sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
     if (callback == 0) return;
@@ -635,6 +686,13 @@
     callback->onError();
 }
 
+void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
+    sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.promote();
+    if (callback == nullptr) return;
+    ALOGV("asyncCodecFormatCallback %s", __func__);
+    callback->onCodecFormatChanged(metadataBs);
+}
+
 
 StreamInHalHidl::StreamInHalHidl(const sp<IStreamIn>& stream)
         : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index f587889..88f8587 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -173,6 +173,11 @@
     void onDrainReady();
     void onError();
 
+    status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
+    // Methods used by StreamCodecFormatCallback (HIDL).
+    void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs);
+
   private:
     friend class DeviceHalHidl;
     typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
@@ -180,6 +185,7 @@
     typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
     wp<StreamOutHalInterfaceCallback> mCallback;
+    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
     sp<IStreamOut> mStream;
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 4818fd8..69be303 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -275,6 +275,43 @@
     return mStream->get_mmap_position(mStream, position);
 }
 
+status_t StreamOutHalLocal::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback) {
+    if (mStream->set_event_callback == nullptr) {
+        return INVALID_OPERATION;
+    }
+    stream_event_callback_t asyncCallback =
+            callback == nullptr ? nullptr : StreamOutHalLocal::asyncEventCallback;
+    status_t result = mStream->set_event_callback(mStream, asyncCallback, this);
+    if (result == OK) {
+        mEventCallback = callback;
+    }
+    return result;
+}
+
+// static
+int StreamOutHalLocal::asyncEventCallback(
+        stream_event_callback_type_t event, void *param, void *cookie) {
+    // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
+    // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
+    // already running, because the destructor is invoked after the refcount has been atomically
+    // decremented.
+    wp<StreamOutHalLocal> weakSelf(static_cast<StreamOutHalLocal*>(cookie));
+    sp<StreamOutHalLocal> self = weakSelf.promote();
+    if (self == nullptr) return 0;
+    sp<StreamOutHalInterfaceEventCallback> callback = self->mEventCallback.promote();
+    if (callback.get() == nullptr) return 0;
+    switch (event) {
+        case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED:
+            callback->onCodecFormatChanged(std::basic_string<uint8_t>((uint8_t*)param));
+            break;
+        default:
+            ALOGW("%s unknown event %d", __func__, event);
+            break;
+    }
+    return 0;
+}
+
 StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
         : StreamHalLocal(&stream->common, device), mStream(stream) {
 }
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index 34f2bd8..d17f9f3 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -156,9 +156,12 @@
     // Called when the metadata of the stream's source has been changed.
     status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
 
+    status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
   private:
     audio_stream_out_t *mStream;
     wp<StreamOutHalInterfaceCallback> mCallback;
+    wp<StreamOutHalInterfaceEventCallback> mEventCallback;
 
     friend class DeviceHalLocal;
 
@@ -168,6 +171,8 @@
     virtual ~StreamOutHalLocal();
 
     static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+
+    static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
 };
 
 class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
diff --git a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
deleted file mode 100644
index c7319d0..0000000
--- a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 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 ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
-
-/** @file Library entry points to create the HAL factories. */
-
-#include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace effect {
-namespace V2_0 {
-sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-} // namespace V2_0
-
-namespace V4_0 {
-sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-} // namespace V4_0
-
-namespace V5_0 {
-sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-} // namespace V5_0
-} // namespace effect
-
-namespace V2_0 {
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
-} // namespace V2_0
-
-namespace V4_0 {
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
-} // namespace V4_0
-
-namespace V5_0 {
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
-} // namespace V5_0
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index e565237..1e04b21 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 #define ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
 
+#include <media/audiohal/EffectHalInterface.h>
 #include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <utils/Errors.h>
@@ -69,7 +70,7 @@
     // by releasing all references to the returned object.
     virtual status_t openOutputStream(
             audio_io_handle_t handle,
-            audio_devices_t devices,
+            audio_devices_t deviceType,
             audio_output_flags_t flags,
             struct audio_config *config,
             const char *address,
@@ -111,6 +112,11 @@
     // List microphones
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
 
+    virtual status_t addDeviceEffect(
+            audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
+    virtual status_t removeDeviceEffect(
+            audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
+
     virtual status_t dump(int fd) = 0;
 
   protected:
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 14af384..5091558 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -20,9 +20,16 @@
 #include <media/audiohal/DeviceHalInterface.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
+#include <vector>
 
 namespace android {
 
+class DevicesFactoryHalCallback : public RefBase
+{
+  public:
+    virtual void onNewDevicesAvailable() = 0;
+};
+
 class DevicesFactoryHalInterface : public RefBase
 {
   public:
@@ -30,6 +37,12 @@
     // necessary to release references to the returned object.
     virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
 
+    virtual status_t getHalPids(std::vector<pid_t> *pids) = 0;
+
+    // Sets a DevicesFactoryHalCallback to notify the client.
+    // The callback can be only set once.
+    virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
+
     static sp<DevicesFactoryHalInterface> create();
 
   protected:
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index 316a46c..3a76f9f 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -41,7 +41,7 @@
     // To release the effect engine, it is necessary to release references
     // to the returned effect object.
     virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
-            int32_t sessionId, int32_t ioId,
+            int32_t sessionId, int32_t ioId, int32_t deviceId,
             sp<EffectHalInterface> *effect) = 0;
 
     virtual status_t dumpEffects(int fd) = 0;
diff --git a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h b/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
new file mode 100644
index 0000000..d353ed0
--- /dev/null
+++ b/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 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 ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
+#define ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
+
+#include <string>
+
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace detail {
+
+void* createPreferredImpl(const std::string& package, const std::string& interface);
+
+}  // namespace detail
+
+/** @Return the preferred available implementation or nullptr if none are available. */
+template <class Interface>
+static sp<Interface> createPreferredImpl(const std::string& package, const std::string& interface) {
+    return sp<Interface>{static_cast<Interface*>(detail::createPreferredImpl(package, interface))};
+}
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 6c3b21c..e30cb72 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -101,6 +101,15 @@
     virtual ~StreamOutHalInterfaceCallback() {}
 };
 
+class StreamOutHalInterfaceEventCallback : public virtual RefBase {
+public:
+    virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
+
+protected:
+    StreamOutHalInterfaceEventCallback() {}
+    virtual ~StreamOutHalInterfaceEventCallback() {}
+};
+
 class StreamOutHalInterface : public virtual StreamHalInterface {
   public:
     // Return the audio hardware driver estimated latency in milliseconds.
@@ -157,6 +166,8 @@
      */
     virtual status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) = 0;
 
+    virtual status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) = 0;
+
   protected:
     virtual ~StreamOutHalInterface() {}
 };
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index cb78063..39b0ceb 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -3,20 +3,13 @@
 
     export_include_dirs: ["include"],
 
+    header_libs: ["libaudioclient_headers"],
+
     shared_libs: [
-        "libaudiohal",
         "libaudioutils",
         "libcutils",
         "liblog",
-        "libnbaio",
-        "libnblog",
-        "libsonic",
         "libutils",
-        "libvibrator",
-    ],
-
-    header_libs: [
-        "libbase_headers",
     ],
 
     cflags: [
@@ -26,6 +19,25 @@
         // uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
         // "-DUSE_NEON=false",
     ],
+
+    arch: {
+        x86: {
+            avx2: {
+                cflags: [
+                    "-mavx2",
+                    "-mfma",
+                ],
+            },
+        },
+        x86_64: {
+            avx2: {
+                cflags: [
+                    "-mavx2",
+                    "-mfma",
+                ],
+            },
+        },
+    },
 }
 
 cc_library_shared {
@@ -33,18 +45,33 @@
     defaults: ["libaudioprocessing_defaults"],
 
     srcs: [
+        "AudioMixer.cpp",
         "BufferProviders.cpp",
         "RecordBufferConverter.cpp",
     ],
-    whole_static_libs: ["libaudioprocessing_arm"],
+
+    header_libs: [
+        "libaudiohal_headers",
+        "libbase_headers",
+        "libmedia_headers"
+    ],
+
+    shared_libs: [
+        "libaudiohal",
+        "libsonic",
+        "libvibrator",
+    ],
+
+    whole_static_libs: ["libaudioprocessing_base"],
 }
 
 cc_library_static {
-    name: "libaudioprocessing_arm",
+    name: "libaudioprocessing_base",
     defaults: ["libaudioprocessing_defaults"],
+    vendor_available: true,
 
     srcs: [
-        "AudioMixer.cpp",
+        "AudioMixerBase.cpp",
         "AudioResampler.cpp",
         "AudioResamplerCubic.cpp",
         "AudioResamplerSinc.cpp",
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index f7cc096..1a31420 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "AudioMixer"
 //#define LOG_NDEBUG 0
 
+#include <sstream>
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
@@ -27,9 +28,6 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
-#include <cutils/compiler.h>
-#include <utils/Debug.h>
-
 #include <system/audio.h>
 
 #include <audio_utils/primitives.h>
@@ -58,138 +56,15 @@
 #define ALOGVV(a...) do { } while (0)
 #endif
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-#endif
-
-// Set kUseNewMixer to true to use the new mixer engine always. Otherwise the
-// original code will be used for stereo sinks, the new mixer for multichannel.
-static constexpr bool kUseNewMixer = true;
-
-// Set kUseFloat to true to allow floating input into the mixer engine.
-// If kUseNewMixer is false, this is ignored or may be overridden internally
-// because of downmix/upmix support.
-static constexpr bool kUseFloat = true;
-
-#ifdef FLOAT_AUX
-using TYPE_AUX = float;
-static_assert(kUseNewMixer && kUseFloat,
-        "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
-#else
-using TYPE_AUX = int32_t; // q4.27
-#endif
-
 // Set to default copy buffer size in frames for input processing.
-static const size_t kCopyBufferFrameCount = 256;
+static constexpr size_t kCopyBufferFrameCount = 256;
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 
-static inline audio_format_t selectMixerInFormat(audio_format_t inputFormat __unused) {
-    return kUseFloat && kUseNewMixer ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
-}
-
-status_t AudioMixer::create(
-        int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId)
-{
-    LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name);
-
-    if (!isValidChannelMask(channelMask)) {
-        ALOGE("%s invalid channelMask: %#x", __func__, channelMask);
-        return BAD_VALUE;
-    }
-    if (!isValidFormat(format)) {
-        ALOGE("%s invalid format: %#x", __func__, format);
-        return BAD_VALUE;
-    }
-
-    auto t = std::make_shared<Track>();
-    {
-        // TODO: move initialization to the Track constructor.
-        // assume default parameters for the track, except where noted below
-        t->needs = 0;
-
-        // Integer volume.
-        // Currently integer volume is kept for the legacy integer mixer.
-        // Will be removed when the legacy mixer path is removed.
-        t->volume[0] = 0;
-        t->volume[1] = 0;
-        t->prevVolume[0] = 0 << 16;
-        t->prevVolume[1] = 0 << 16;
-        t->volumeInc[0] = 0;
-        t->volumeInc[1] = 0;
-        t->auxLevel = 0;
-        t->auxInc = 0;
-        t->prevAuxLevel = 0;
-
-        // Floating point volume.
-        t->mVolume[0] = 0.f;
-        t->mVolume[1] = 0.f;
-        t->mPrevVolume[0] = 0.f;
-        t->mPrevVolume[1] = 0.f;
-        t->mVolumeInc[0] = 0.;
-        t->mVolumeInc[1] = 0.;
-        t->mAuxLevel = 0.;
-        t->mAuxInc = 0.;
-        t->mPrevAuxLevel = 0.;
-
-        // no initialization needed
-        // t->frameCount
-        t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
-        t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
-        channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
-        t->channelCount = audio_channel_count_from_out_mask(channelMask);
-        t->enabled = false;
-        ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
-                "Non-stereo channel mask: %d\n", channelMask);
-        t->channelMask = channelMask;
-        t->sessionId = sessionId;
-        // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
-        t->bufferProvider = NULL;
-        t->buffer.raw = NULL;
-        // no initialization needed
-        // t->buffer.frameCount
-        t->hook = NULL;
-        t->mIn = NULL;
-        t->sampleRate = mSampleRate;
-        // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
-        t->mainBuffer = NULL;
-        t->auxBuffer = NULL;
-        t->mInputBufferProvider = NULL;
-        t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
-        t->mFormat = format;
-        t->mMixerInFormat = selectMixerInFormat(format);
-        t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required
-        t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits(
-                AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
-        t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
-        t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
-        // haptic
-        t->mHapticPlaybackEnabled = false;
-        t->mHapticIntensity = HAPTIC_SCALE_NONE;
-        t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
-        t->mMixerHapticChannelCount = 0;
-        t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
-        t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
-        t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
-        t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
-        t->mKeepContractedChannels = false;
-        // Check the downmixing (or upmixing) requirements.
-        status_t status = t->prepareForDownmix();
-        if (status != OK) {
-            ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
-            return BAD_VALUE;
-        }
-        // prepareForDownmix() may change mDownmixRequiresFormat
-        ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
-        t->prepareForReformat();
-        t->prepareForAdjustChannelsNonDestructive(mFrameCount);
-        t->prepareForAdjustChannels();
-
-        mTracks[name] = t;
-        return OK;
-    }
+bool AudioMixer::isValidChannelMask(audio_channel_mask_t channelMask) const {
+    return audio_channel_mask_is_valid(channelMask); // the RemixBufferProvider is flexible.
 }
 
 // Called when channel masks have changed for a track name
@@ -198,7 +73,7 @@
 bool AudioMixer::setChannelMasks(int name,
         audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     if (trackChannelMask == (track->channelMask | track->mHapticChannelMask)
             && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
@@ -255,14 +130,8 @@
     track->prepareForAdjustChannelsNonDestructive(mFrameCount);
     track->prepareForAdjustChannels();
 
-    if (track->mResampler.get() != nullptr) {
-        // resampler channels may have changed.
-        const uint32_t resetToSampleRate = track->sampleRate;
-        track->mResampler.reset(nullptr);
-        track->sampleRate = mSampleRate; // without resampler, track rate is device sample rate.
-        // recreate the resampler with updated format, channels, saved sampleRate.
-        track->setResampler(resetToSampleRate /*trackSampleRate*/, mSampleRate /*devSampleRate*/);
-    }
+    // Resampler channels may have changed.
+    track->recreateResampler(mSampleRate);
     return true;
 }
 
@@ -293,10 +162,10 @@
     // discard the previous downmixer if there was one
     unprepareForDownmix();
     // MONO_HACK Only remix (upmix or downmix) if the track and mixer/device channel masks
-    // are not the same and not handled internally, as mono -> stereo currently is.
+    // are not the same and not handled internally, as mono for channel position masks is.
     if (channelMask == mMixerChannelMask
             || (channelMask == AUDIO_CHANNEL_OUT_MONO
-                    && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) {
+                    && isAudioChannelPositionMask(mMixerChannelMask))) {
         return NO_ERROR;
     }
     // DownmixerBufferProvider is only used for position masks.
@@ -477,171 +346,10 @@
     }
 }
 
-void AudioMixer::destroy(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    ALOGV("deleteTrackName(%d)", name);
-
-    if (mTracks[name]->enabled) {
-        invalidate();
-    }
-    mTracks.erase(name); // deallocate track
-}
-
-void AudioMixer::enable(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
-
-    if (!track->enabled) {
-        track->enabled = true;
-        ALOGV("enable(%d)", name);
-        invalidate();
-    }
-}
-
-void AudioMixer::disable(int name)
-{
-    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
-
-    if (track->enabled) {
-        track->enabled = false;
-        ALOGV("disable(%d)", name);
-        invalidate();
-    }
-}
-
-/* Sets the volume ramp variables for the AudioMixer.
- *
- * The volume ramp variables are used to transition from the previous
- * volume to the set volume.  ramp controls the duration of the transition.
- * Its value is typically one state framecount period, but may also be 0,
- * meaning "immediate."
- *
- * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment
- * even if there is a nonzero floating point increment (in that case, the volume
- * change is immediate).  This restriction should be changed when the legacy mixer
- * is removed (see #2).
- * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed
- * when no longer needed.
- *
- * @param newVolume set volume target in floating point [0.0, 1.0].
- * @param ramp number of frames to increment over. if ramp is 0, the volume
- * should be set immediately.  Currently ramp should not exceed 65535 (frames).
- * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return.
- * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return.
- * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return.
- * @param pSetVolume pointer to the float target volume, set on return.
- * @param pPrevVolume pointer to the float previous volume, set on return.
- * @param pVolumeInc pointer to the float increment per output audio frame, set on return.
- * @return true if the volume has changed, false if volume is same.
- */
-static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
-        int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
-        float *pSetVolume, float *pPrevVolume, float *pVolumeInc) {
-    // check floating point volume to see if it is identical to the previously
-    // set volume.
-    // We do not use a tolerance here (and reject changes too small)
-    // as it may be confusing to use a different value than the one set.
-    // If the resulting volume is too small to ramp, it is a direct set of the volume.
-    if (newVolume == *pSetVolume) {
-        return false;
-    }
-    if (newVolume < 0) {
-        newVolume = 0; // should not have negative volumes
-    } else {
-        switch (fpclassify(newVolume)) {
-        case FP_SUBNORMAL:
-        case FP_NAN:
-            newVolume = 0;
-            break;
-        case FP_ZERO:
-            break; // zero volume is fine
-        case FP_INFINITE:
-            // Infinite volume could be handled consistently since
-            // floating point math saturates at infinities,
-            // but we limit volume to unity gain float.
-            // ramp = 0; break;
-            //
-            newVolume = AudioMixer::UNITY_GAIN_FLOAT;
-            break;
-        case FP_NORMAL:
-        default:
-            // Floating point does not have problems with overflow wrap
-            // that integer has.  However, we limit the volume to
-            // unity gain here.
-            // TODO: Revisit the volume limitation and perhaps parameterize.
-            if (newVolume > AudioMixer::UNITY_GAIN_FLOAT) {
-                newVolume = AudioMixer::UNITY_GAIN_FLOAT;
-            }
-            break;
-        }
-    }
-
-    // set floating point volume ramp
-    if (ramp != 0) {
-        // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there
-        // is no computational mismatch; hence equality is checked here.
-        ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished,"
-                " prev:%f  set_to:%f", *pPrevVolume, *pSetVolume);
-        const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal
-        // could be inf, cannot be nan, subnormal
-        const float maxv = std::max(newVolume, *pPrevVolume);
-
-        if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan)
-                && maxv + inc != maxv) { // inc must make forward progress
-            *pVolumeInc = inc;
-            // ramp is set now.
-            // Note: if newVolume is 0, then near the end of the ramp,
-            // it may be possible that the ramped volume may be subnormal or
-            // temporarily negative by a small amount or subnormal due to floating
-            // point inaccuracies.
-        } else {
-            ramp = 0; // ramp not allowed
-        }
-    }
-
-    // compute and check integer volume, no need to check negative values
-    // The integer volume is limited to "unity_gain" to avoid wrapping and other
-    // audio artifacts, so it never reaches the range limit of U4.28.
-    // We safely use signed 16 and 32 bit integers here.
-    const float scaledVolume = newVolume * AudioMixer::UNITY_GAIN_INT; // not neg, subnormal, nan
-    const int32_t intVolume = (scaledVolume >= (float)AudioMixer::UNITY_GAIN_INT) ?
-            AudioMixer::UNITY_GAIN_INT : (int32_t)scaledVolume;
-
-    // set integer volume ramp
-    if (ramp != 0) {
-        // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28.
-        // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there
-        // is no computational mismatch; hence equality is checked here.
-        ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished,"
-                " prev:%d  set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16);
-        const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp;
-
-        if (inc != 0) { // inc must make forward progress
-            *pIntVolumeInc = inc;
-        } else {
-            ramp = 0; // ramp not allowed
-        }
-    }
-
-    // if no ramp, or ramp not allowed, then clear float and integer increments
-    if (ramp == 0) {
-        *pVolumeInc = 0;
-        *pPrevVolume = newVolume;
-        *pIntVolumeInc = 0;
-        *pIntPrevVolume = intVolume << 16;
-    }
-    *pSetVolume = newVolume;
-    *pIntSetVolume = intVolume;
-    return true;
-}
-
 void AudioMixer::setParameter(int name, int target, int param, void *value)
 {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
     int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
@@ -670,11 +378,7 @@
             }
             break;
         case AUX_BUFFER:
-            if (track->auxBuffer != valueBuf) {
-                track->auxBuffer = valueBuf;
-                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
-                invalidate();
-            }
+            AudioMixerBase::setParameter(name, target, param, value);
             break;
         case FORMAT: {
             audio_format_t format = static_cast<audio_format_t>(valueInt);
@@ -730,127 +434,38 @@
         break;
 
     case RESAMPLE:
-        switch (param) {
-        case SAMPLE_RATE:
-            ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
-            if (track->setResampler(uint32_t(valueInt), mSampleRate)) {
-                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
-                        uint32_t(valueInt));
-                invalidate();
-            }
-            break;
-        case RESET:
-            track->resetResampler();
-            invalidate();
-            break;
-        case REMOVE:
-            track->mResampler.reset(nullptr);
-            track->sampleRate = mSampleRate;
-            invalidate();
-            break;
-        default:
-            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
-        }
-        break;
-
     case RAMP_VOLUME:
     case VOLUME:
+        AudioMixerBase::setParameter(name, target, param, value);
+        break;
+    case TIMESTRETCH:
         switch (param) {
-        case AUXLEVEL:
-            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
-                    target == RAMP_VOLUME ? mFrameCount : 0,
-                    &track->auxLevel, &track->prevAuxLevel, &track->auxInc,
-                    &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) {
-                ALOGV("setParameter(%s, AUXLEVEL: %04x)",
-                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel);
-                invalidate();
+        case PLAYBACK_RATE: {
+            const AudioPlaybackRate *playbackRate =
+                    reinterpret_cast<AudioPlaybackRate*>(value);
+            ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate),
+                    "bad parameters speed %f, pitch %f",
+                    playbackRate->mSpeed, playbackRate->mPitch);
+            if (track->setPlaybackRate(*playbackRate)) {
+                ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE "
+                        "%f %f %d %d",
+                        playbackRate->mSpeed,
+                        playbackRate->mPitch,
+                        playbackRate->mStretchMode,
+                        playbackRate->mFallbackMode);
+                // invalidate();  (should not require reconfigure)
             }
-            break;
+        } break;
         default:
-            if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
-                if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
-                        target == RAMP_VOLUME ? mFrameCount : 0,
-                        &track->volume[param - VOLUME0],
-                        &track->prevVolume[param - VOLUME0],
-                        &track->volumeInc[param - VOLUME0],
-                        &track->mVolume[param - VOLUME0],
-                        &track->mPrevVolume[param - VOLUME0],
-                        &track->mVolumeInc[param - VOLUME0])) {
-                    ALOGV("setParameter(%s, VOLUME%d: %04x)",
-                            target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
-                                    track->volume[param - VOLUME0]);
-                    invalidate();
-                }
-            } else {
-                LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
-            }
+            LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param);
         }
         break;
-        case TIMESTRETCH:
-            switch (param) {
-            case PLAYBACK_RATE: {
-                const AudioPlaybackRate *playbackRate =
-                        reinterpret_cast<AudioPlaybackRate*>(value);
-                ALOGW_IF(!isAudioPlaybackRateValid(*playbackRate),
-                        "bad parameters speed %f, pitch %f",
-                        playbackRate->mSpeed, playbackRate->mPitch);
-                if (track->setPlaybackRate(*playbackRate)) {
-                    ALOGV("setParameter(TIMESTRETCH, PLAYBACK_RATE, STRETCH_MODE, FALLBACK_MODE "
-                            "%f %f %d %d",
-                            playbackRate->mSpeed,
-                            playbackRate->mPitch,
-                            playbackRate->mStretchMode,
-                            playbackRate->mFallbackMode);
-                    // invalidate();  (should not require reconfigure)
-                }
-            } break;
-            default:
-                LOG_ALWAYS_FATAL("setParameter timestretch: bad param %d", param);
-            }
-            break;
 
     default:
         LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
     }
 }
 
-bool AudioMixer::Track::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate)
-{
-    if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) {
-        if (sampleRate != trackSampleRate) {
-            sampleRate = trackSampleRate;
-            if (mResampler.get() == nullptr) {
-                ALOGV("Creating resampler from track %d Hz to device %d Hz",
-                        trackSampleRate, devSampleRate);
-                AudioResampler::src_quality quality;
-                // force lowest quality level resampler if use case isn't music or video
-                // FIXME this is flawed for dynamic sample rates, as we choose the resampler
-                // quality level based on the initial ratio, but that could change later.
-                // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
-                if (isMusicRate(trackSampleRate)) {
-                    quality = AudioResampler::DEFAULT_QUALITY;
-                } else {
-                    quality = AudioResampler::DYN_LOW_QUALITY;
-                }
-
-                // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
-                // but if none exists, it is the channel count (1 for mono).
-                const int resamplerChannelCount = mDownmixerBufferProvider.get() != nullptr
-                        ? mMixerChannelCount : channelCount;
-                ALOGVV("Creating resampler:"
-                        " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
-                        mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
-                mResampler.reset(AudioResampler::create(
-                        mMixerInFormat,
-                        resamplerChannelCount,
-                        devSampleRate, quality));
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
 bool AudioMixer::Track::setPlaybackRate(const AudioPlaybackRate &playbackRate)
 {
     if ((mTimestretchBufferProvider.get() == nullptr &&
@@ -863,8 +478,7 @@
     if (mTimestretchBufferProvider.get() == nullptr) {
         // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
         // but if none exists, it is the channel count (1 for mono).
-        const int timestretchChannelCount = mDownmixerBufferProvider.get() != nullptr
-                ? mMixerChannelCount : channelCount;
+        const int timestretchChannelCount = getOutputChannelCount();
         mTimestretchBufferProvider.reset(new TimestretchBufferProvider(timestretchChannelCount,
                 mMixerInFormat, sampleRate, playbackRate));
         reconfigureBufferProviders();
@@ -875,84 +489,10 @@
     return true;
 }
 
-/* Checks to see if the volume ramp has completed and clears the increment
- * variables appropriately.
- *
- * FIXME: There is code to handle int/float ramp variable switchover should it not
- * complete within a mixer buffer processing call, but it is preferred to avoid switchover
- * due to precision issues.  The switchover code is included for legacy code purposes
- * and can be removed once the integer volume is removed.
- *
- * It is not sufficient to clear only the volumeInc integer variable because
- * if one channel requires ramping, all channels are ramped.
- *
- * There is a bit of duplicated code here, but it keeps backward compatibility.
- */
-inline void AudioMixer::Track::adjustVolumeRamp(bool aux, bool useFloat)
-{
-    if (useFloat) {
-        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
-            if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) ||
-                     (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) {
-                volumeInc[i] = 0;
-                prevVolume[i] = volume[i] << 16;
-                mVolumeInc[i] = 0.;
-                mPrevVolume[i] = mVolume[i];
-            } else {
-                //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]);
-                prevVolume[i] = u4_28_from_float(mPrevVolume[i]);
-            }
-        }
-    } else {
-        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
-            if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
-                    ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
-                volumeInc[i] = 0;
-                prevVolume[i] = volume[i] << 16;
-                mVolumeInc[i] = 0.;
-                mPrevVolume[i] = mVolume[i];
-            } else {
-                //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]);
-                mPrevVolume[i]  = float_from_u4_28(prevVolume[i]);
-            }
-        }
-    }
-
-    if (aux) {
-#ifdef FLOAT_AUX
-        if (useFloat) {
-            if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
-                    (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
-                auxInc = 0;
-                prevAuxLevel = auxLevel << 16;
-                mAuxInc = 0.f;
-                mPrevAuxLevel = mAuxLevel;
-            }
-        } else
-#endif
-        if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
-                (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
-            auxInc = 0;
-            prevAuxLevel = auxLevel << 16;
-            mAuxInc = 0.f;
-            mPrevAuxLevel = mAuxLevel;
-        }
-    }
-}
-
-size_t AudioMixer::getUnreleasedFrames(int name) const
-{
-    const auto it = mTracks.find(name);
-    if (it != mTracks.end()) {
-        return it->second->getUnreleasedFrames();
-    }
-    return 0;
-}
-
 void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
 {
     LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
-    const std::shared_ptr<Track> &track = mTracks[name];
+    const std::shared_ptr<Track> &track = getTrack(name);
 
     if (track->mInputBufferProvider == bufferProvider) {
         return; // don't reset any buffer providers if identical.
@@ -976,679 +516,6 @@
     track->reconfigureBufferProviders();
 }
 
-void AudioMixer::process__validate()
-{
-    // TODO: fix all16BitsStereNoResample logic to
-    // either properly handle muted tracks (it should ignore them)
-    // or remove altogether as an obsolete optimization.
-    bool all16BitsStereoNoResample = true;
-    bool resampling = false;
-    bool volumeRamp = false;
-
-    mEnabled.clear();
-    mGroups.clear();
-    for (const auto &pair : mTracks) {
-        const int name = pair.first;
-        const std::shared_ptr<Track> &t = pair.second;
-        if (!t->enabled) continue;
-
-        mEnabled.emplace_back(name);  // we add to mEnabled in order of name.
-        mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name.
-
-        uint32_t n = 0;
-        // FIXME can overflow (mask is only 3 bits)
-        n |= NEEDS_CHANNEL_1 + t->channelCount - 1;
-        if (t->doesResample()) {
-            n |= NEEDS_RESAMPLE;
-        }
-        if (t->auxLevel != 0 && t->auxBuffer != NULL) {
-            n |= NEEDS_AUX;
-        }
-
-        if (t->volumeInc[0]|t->volumeInc[1]) {
-            volumeRamp = true;
-        } else if (!t->doesResample() && t->volumeRL == 0) {
-            n |= NEEDS_MUTE;
-        }
-        t->needs = n;
-
-        if (n & NEEDS_MUTE) {
-            t->hook = &Track::track__nop;
-        } else {
-            if (n & NEEDS_AUX) {
-                all16BitsStereoNoResample = false;
-            }
-            if (n & NEEDS_RESAMPLE) {
-                all16BitsStereoNoResample = false;
-                resampling = true;
-                t->hook = Track::getTrackHook(TRACKTYPE_RESAMPLE, t->mMixerChannelCount,
-                        t->mMixerInFormat, t->mMixerFormat);
-                ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
-                        "Track %d needs downmix + resample", name);
-            } else {
-                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
-                    t->hook = Track::getTrackHook(
-                            (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO  // TODO: MONO_HACK
-                                    && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
-                                ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
-                            t->mMixerChannelCount,
-                            t->mMixerInFormat, t->mMixerFormat);
-                    all16BitsStereoNoResample = false;
-                }
-                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
-                    t->hook = Track::getTrackHook(TRACKTYPE_NORESAMPLE, t->mMixerChannelCount,
-                            t->mMixerInFormat, t->mMixerFormat);
-                    ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
-                            "Track %d needs downmix", name);
-                }
-            }
-        }
-    }
-
-    // select the processing hooks
-    mHook = &AudioMixer::process__nop;
-    if (mEnabled.size() > 0) {
-        if (resampling) {
-            if (mOutputTemp.get() == nullptr) {
-                mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
-            }
-            if (mResampleTemp.get() == nullptr) {
-                mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
-            }
-            mHook = &AudioMixer::process__genericResampling;
-        } else {
-            // we keep temp arrays around.
-            mHook = &AudioMixer::process__genericNoResampling;
-            if (all16BitsStereoNoResample && !volumeRamp) {
-                if (mEnabled.size() == 1) {
-                    const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-                    if ((t->needs & NEEDS_MUTE) == 0) {
-                        // The check prevents a muted track from acquiring a process hook.
-                        //
-                        // This is dangerous if the track is MONO as that requires
-                        // special case handling due to implicit channel duplication.
-                        // Stereo or Multichannel should actually be fine here.
-                        mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
-                                t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
-                    }
-                }
-            }
-        }
-    }
-
-    ALOGV("mixer configuration change: %zu "
-        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
-        mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp);
-
-   process();
-
-    // Now that the volume ramp has been done, set optimal state and
-    // track hooks for subsequent mixer process
-    if (mEnabled.size() > 0) {
-        bool allMuted = true;
-
-        for (const int name : mEnabled) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            if (!t->doesResample() && t->volumeRL == 0) {
-                t->needs |= NEEDS_MUTE;
-                t->hook = &Track::track__nop;
-            } else {
-                allMuted = false;
-            }
-        }
-        if (allMuted) {
-            mHook = &AudioMixer::process__nop;
-        } else if (all16BitsStereoNoResample) {
-            if (mEnabled.size() == 1) {
-                //const int i = 31 - __builtin_clz(enabledTracks);
-                const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-                // Muted single tracks handled by allMuted above.
-                mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
-                        t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat);
-            }
-        }
-    }
-}
-
-void AudioMixer::Track::track__genericResample(
-        int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
-{
-    ALOGVV("track__genericResample\n");
-    mResampler->setSampleRate(sampleRate);
-
-    // ramp gain - resample to temp buffer and scale/mix in 2nd step
-    if (aux != NULL) {
-        // always resample with unity gain when sending to auxiliary buffer to be able
-        // to apply send level after resampling
-        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t));
-        mResampler->resample(temp, outFrameCount, bufferProvider);
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            volumeRampStereo(out, outFrameCount, temp, aux);
-        } else {
-            volumeStereo(out, outFrameCount, temp, aux);
-        }
-    } else {
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
-            mResampler->resample(temp, outFrameCount, bufferProvider);
-            volumeRampStereo(out, outFrameCount, temp, aux);
-        }
-
-        // constant gain
-        else {
-            mResampler->setVolume(mVolume[0], mVolume[1]);
-            mResampler->resample(out, outFrameCount, bufferProvider);
-        }
-    }
-}
-
-void AudioMixer::Track::track__nop(int32_t* out __unused,
-        size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
-{
-}
-
-void AudioMixer::Track::volumeRampStereo(
-        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
-    int32_t vl = prevVolume[0];
-    int32_t vr = prevVolume[1];
-    const int32_t vlInc = volumeInc[0];
-    const int32_t vrInc = volumeInc[1];
-
-    //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-    //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-    // ramp volume
-    if (CC_UNLIKELY(aux != NULL)) {
-        int32_t va = prevAuxLevel;
-        const int32_t vaInc = auxInc;
-        int32_t l;
-        int32_t r;
-
-        do {
-            l = (*temp++ >> 12);
-            r = (*temp++ >> 12);
-            *out++ += (vl >> 16) * l;
-            *out++ += (vr >> 16) * r;
-            *aux++ += (va >> 17) * (l + r);
-            vl += vlInc;
-            vr += vrInc;
-            va += vaInc;
-        } while (--frameCount);
-        prevAuxLevel = va;
-    } else {
-        do {
-            *out++ += (vl >> 16) * (*temp++ >> 12);
-            *out++ += (vr >> 16) * (*temp++ >> 12);
-            vl += vlInc;
-            vr += vrInc;
-        } while (--frameCount);
-    }
-    prevVolume[0] = vl;
-    prevVolume[1] = vr;
-    adjustVolumeRamp(aux != NULL);
-}
-
-void AudioMixer::Track::volumeStereo(
-        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
-    const int16_t vl = volume[0];
-    const int16_t vr = volume[1];
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        const int16_t va = auxLevel;
-        do {
-            int16_t l = (int16_t)(*temp++ >> 12);
-            int16_t r = (int16_t)(*temp++ >> 12);
-            out[0] = mulAdd(l, vl, out[0]);
-            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
-            out[1] = mulAdd(r, vr, out[1]);
-            out += 2;
-            aux[0] = mulAdd(a, va, aux[0]);
-            aux++;
-        } while (--frameCount);
-    } else {
-        do {
-            int16_t l = (int16_t)(*temp++ >> 12);
-            int16_t r = (int16_t)(*temp++ >> 12);
-            out[0] = mulAdd(l, vl, out[0]);
-            out[1] = mulAdd(r, vr, out[1]);
-            out += 2;
-        } while (--frameCount);
-    }
-}
-
-void AudioMixer::Track::track__16BitsStereo(
-        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
-{
-    ALOGVV("track__16BitsStereo\n");
-    const int16_t *in = static_cast<const int16_t *>(mIn);
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        int32_t l;
-        int32_t r;
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            int32_t va = prevAuxLevel;
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-            const int32_t vaInc = auxInc;
-            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                l = (int32_t)*in++;
-                r = (int32_t)*in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * r;
-                *aux++ += (va >> 17) * (l + r);
-                vl += vlInc;
-                vr += vrInc;
-                va += vaInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            prevAuxLevel = va;
-            adjustVolumeRamp(true);
-        }
-
-        // constant gain
-        else {
-            const uint32_t vrl = volumeRL;
-            const int16_t va = (int16_t)auxLevel;
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
-                in += 2;
-                out[0] = mulAddRL(1, rl, vrl, out[0]);
-                out[1] = mulAddRL(0, rl, vrl, out[1]);
-                out += 2;
-                aux[0] = mulAdd(a, va, aux[0]);
-                aux++;
-            } while (--frameCount);
-        }
-    } else {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-
-            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                *out++ += (vl >> 16) * (int32_t) *in++;
-                *out++ += (vr >> 16) * (int32_t) *in++;
-                vl += vlInc;
-                vr += vrInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            adjustVolumeRamp(false);
-        }
-
-        // constant gain
-        else {
-            const uint32_t vrl = volumeRL;
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                in += 2;
-                out[0] = mulAddRL(1, rl, vrl, out[0]);
-                out[1] = mulAddRL(0, rl, vrl, out[1]);
-                out += 2;
-            } while (--frameCount);
-        }
-    }
-    mIn = in;
-}
-
-void AudioMixer::Track::track__16BitsMono(
-        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
-{
-    ALOGVV("track__16BitsMono\n");
-    const int16_t *in = static_cast<int16_t const *>(mIn);
-
-    if (CC_UNLIKELY(aux != NULL)) {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            int32_t va = prevAuxLevel;
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-            const int32_t vaInc = auxInc;
-
-            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                int32_t l = *in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * l;
-                *aux++ += (va >> 16) * l;
-                vl += vlInc;
-                vr += vrInc;
-                va += vaInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            prevAuxLevel = va;
-            adjustVolumeRamp(true);
-        }
-        // constant gain
-        else {
-            const int16_t vl = volume[0];
-            const int16_t vr = volume[1];
-            const int16_t va = (int16_t)auxLevel;
-            do {
-                int16_t l = *in++;
-                out[0] = mulAdd(l, vl, out[0]);
-                out[1] = mulAdd(l, vr, out[1]);
-                out += 2;
-                aux[0] = mulAdd(l, va, aux[0]);
-                aux++;
-            } while (--frameCount);
-        }
-    } else {
-        // ramp gain
-        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
-            int32_t vl = prevVolume[0];
-            int32_t vr = prevVolume[1];
-            const int32_t vlInc = volumeInc[0];
-            const int32_t vrInc = volumeInc[1];
-
-            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
-            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
-            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
-
-            do {
-                int32_t l = *in++;
-                *out++ += (vl >> 16) * l;
-                *out++ += (vr >> 16) * l;
-                vl += vlInc;
-                vr += vrInc;
-            } while (--frameCount);
-
-            prevVolume[0] = vl;
-            prevVolume[1] = vr;
-            adjustVolumeRamp(false);
-        }
-        // constant gain
-        else {
-            const int16_t vl = volume[0];
-            const int16_t vr = volume[1];
-            do {
-                int16_t l = *in++;
-                out[0] = mulAdd(l, vl, out[0]);
-                out[1] = mulAdd(l, vr, out[1]);
-                out += 2;
-            } while (--frameCount);
-        }
-    }
-    mIn = in;
-}
-
-// no-op case
-void AudioMixer::process__nop()
-{
-    ALOGVV("process__nop\n");
-
-    for (const auto &pair : mGroups) {
-        // process by group of tracks with same output buffer to
-        // avoid multiple memset() on same buffer
-        const auto &group = pair.second;
-
-        const std::shared_ptr<Track> &t = mTracks[group[0]];
-        memset(t->mainBuffer, 0,
-                mFrameCount * audio_bytes_per_frame(
-                        t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat));
-
-        // now consume data
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            size_t outFrames = mFrameCount;
-            while (outFrames) {
-                t->buffer.frameCount = outFrames;
-                t->bufferProvider->getNextBuffer(&t->buffer);
-                if (t->buffer.raw == NULL) break;
-                outFrames -= t->buffer.frameCount;
-                t->bufferProvider->releaseBuffer(&t->buffer);
-            }
-        }
-    }
-}
-
-// generic code without resampling
-void AudioMixer::process__genericNoResampling()
-{
-    ALOGVV("process__genericNoResampling\n");
-    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
-
-    for (const auto &pair : mGroups) {
-        // process by group of tracks with same output main buffer to
-        // avoid multiple memset() on same buffer
-        const auto &group = pair.second;
-
-        // acquire buffer
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            t->buffer.frameCount = mFrameCount;
-            t->bufferProvider->getNextBuffer(&t->buffer);
-            t->frameCount = t->buffer.frameCount;
-            t->mIn = t->buffer.raw;
-        }
-
-        int32_t *out = (int *)pair.first;
-        size_t numFrames = 0;
-        do {
-            const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames);
-            memset(outTemp, 0, sizeof(outTemp));
-            for (const int name : group) {
-                const std::shared_ptr<Track> &t = mTracks[name];
-                int32_t *aux = NULL;
-                if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
-                    aux = t->auxBuffer + numFrames;
-                }
-                for (int outFrames = frameCount; outFrames > 0; ) {
-                    // t->in == nullptr can happen if the track was flushed just after having
-                    // been enabled for mixing.
-                    if (t->mIn == nullptr) {
-                        break;
-                    }
-                    size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount;
-                    if (inFrames > 0) {
-                        (t.get()->*t->hook)(
-                                outTemp + (frameCount - outFrames) * t->mMixerChannelCount,
-                                inFrames, mResampleTemp.get() /* naked ptr */, aux);
-                        t->frameCount -= inFrames;
-                        outFrames -= inFrames;
-                        if (CC_UNLIKELY(aux != NULL)) {
-                            aux += inFrames;
-                        }
-                    }
-                    if (t->frameCount == 0 && outFrames) {
-                        t->bufferProvider->releaseBuffer(&t->buffer);
-                        t->buffer.frameCount = (mFrameCount - numFrames) -
-                                (frameCount - outFrames);
-                        t->bufferProvider->getNextBuffer(&t->buffer);
-                        t->mIn = t->buffer.raw;
-                        if (t->mIn == nullptr) {
-                            break;
-                        }
-                        t->frameCount = t->buffer.frameCount;
-                    }
-                }
-            }
-
-            const std::shared_ptr<Track> &t1 = mTracks[group[0]];
-            convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat,
-                    frameCount * t1->mMixerChannelCount);
-            // TODO: fix ugly casting due to choice of out pointer type
-            out = reinterpret_cast<int32_t*>((uint8_t*)out
-                    + frameCount * t1->mMixerChannelCount
-                    * audio_bytes_per_sample(t1->mMixerFormat));
-            numFrames += frameCount;
-        } while (numFrames < mFrameCount);
-
-        // release each track's buffer
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            t->bufferProvider->releaseBuffer(&t->buffer);
-        }
-    }
-}
-
-// generic code with resampling
-void AudioMixer::process__genericResampling()
-{
-    ALOGVV("process__genericResampling\n");
-    int32_t * const outTemp = mOutputTemp.get(); // naked ptr
-    size_t numFrames = mFrameCount;
-
-    for (const auto &pair : mGroups) {
-        const auto &group = pair.second;
-        const std::shared_ptr<Track> &t1 = mTracks[group[0]];
-
-        // clear temp buffer
-        memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);
-        for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
-            int32_t *aux = NULL;
-            if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
-                aux = t->auxBuffer;
-            }
-
-            // this is a little goofy, on the resampling case we don't
-            // acquire/release the buffers because it's done by
-            // the resampler.
-            if (t->needs & NEEDS_RESAMPLE) {
-                (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);
-            } else {
-
-                size_t outFrames = 0;
-
-                while (outFrames < numFrames) {
-                    t->buffer.frameCount = numFrames - outFrames;
-                    t->bufferProvider->getNextBuffer(&t->buffer);
-                    t->mIn = t->buffer.raw;
-                    // t->mIn == nullptr can happen if the track was flushed just after having
-                    // been enabled for mixing.
-                    if (t->mIn == nullptr) break;
-
-                    (t.get()->*t->hook)(
-                            outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,
-                            mResampleTemp.get() /* naked ptr */,
-                            aux != nullptr ? aux + outFrames : nullptr);
-                    outFrames += t->buffer.frameCount;
-
-                    t->bufferProvider->releaseBuffer(&t->buffer);
-                }
-            }
-        }
-        convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,
-                outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);
-    }
-}
-
-// one track, 16 bits stereo without resampling is the most common case
-void AudioMixer::process__oneTrack16BitsStereoNoResampling()
-{
-    ALOGVV("process__oneTrack16BitsStereoNoResampling\n");
-    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0,
-            "%zu != 1 tracks enabled", mEnabled.size());
-    const int name = mEnabled[0];
-    const std::shared_ptr<Track> &t = mTracks[name];
-
-    AudioBufferProvider::Buffer& b(t->buffer);
-
-    int32_t* out = t->mainBuffer;
-    float *fout = reinterpret_cast<float*>(out);
-    size_t numFrames = mFrameCount;
-
-    const int16_t vl = t->volume[0];
-    const int16_t vr = t->volume[1];
-    const uint32_t vrl = t->volumeRL;
-    while (numFrames) {
-        b.frameCount = numFrames;
-        t->bufferProvider->getNextBuffer(&b);
-        const int16_t *in = b.i16;
-
-        // in == NULL can happen if the track was flushed just after having
-        // been enabled for mixing.
-        if (in == NULL || (((uintptr_t)in) & 3)) {
-            if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) {
-                 memset((char*)fout, 0, numFrames
-                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
-            } else {
-                 memset((char*)out, 0, numFrames
-                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
-            }
-            ALOGE_IF((((uintptr_t)in) & 3),
-                    "process__oneTrack16BitsStereoNoResampling: misaligned buffer"
-                    " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
-                    in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]);
-            return;
-        }
-        size_t outFrames = b.frameCount;
-
-        switch (t->mMixerFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            do {
-                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                in += 2;
-                int32_t l = mulRL(1, rl, vrl);
-                int32_t r = mulRL(0, rl, vrl);
-                *fout++ = float_from_q4_27(l);
-                *fout++ = float_from_q4_27(r);
-                // Note: In case of later int16_t sink output,
-                // conversion and clamping is done by memcpy_to_i16_from_float().
-            } while (--outFrames);
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
-                // volume is boosted, so we might need to clamp even though
-                // we process only one track.
-                do {
-                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                    in += 2;
-                    int32_t l = mulRL(1, rl, vrl) >> 12;
-                    int32_t r = mulRL(0, rl, vrl) >> 12;
-                    // clamping...
-                    l = clamp16(l);
-                    r = clamp16(r);
-                    *out++ = (r<<16) | (l & 0xFFFF);
-                } while (--outFrames);
-            } else {
-                do {
-                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
-                    in += 2;
-                    int32_t l = mulRL(1, rl, vrl) >> 12;
-                    int32_t r = mulRL(0, rl, vrl) >> 12;
-                    *out++ = (r<<16) | (l & 0xFFFF);
-                } while (--outFrames);
-            }
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat);
-        }
-        numFrames -= b.frameCount;
-        t->bufferProvider->releaseBuffer(&b);
-    }
-}
-
 /*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
 
 /*static*/ void AudioMixer::sInitRoutine()
@@ -1656,211 +523,71 @@
     DownmixerBufferProvider::init(); // for the downmixer
 }
 
-/* TODO: consider whether this level of optimization is necessary.
- * Perhaps just stick with a single for loop.
- */
-
-// Needs to derive a compile time constant (constexpr).  Could be targeted to go
-// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
-#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
-        (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
-
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE,
-        typename TO, typename TI, typename TV, typename TA, typename TAV>
-static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
-        const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
+std::shared_ptr<AudioMixerBase::TrackBase> AudioMixer::preCreateTrack()
 {
-    switch (channels) {
-    case 1:
-        volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 2:
-        volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 3:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 4:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 5:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 6:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 7:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    case 8:
-        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
-                frameCount, in, aux, vol, volinc, vola, volainc);
-        break;
-    }
+    return std::make_shared<Track>();
 }
 
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE,
-        typename TO, typename TI, typename TV, typename TA, typename TAV>
-static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
-        const TI* in, TA* aux, const TV *vol, TAV vola)
+status_t AudioMixer::postCreateTrack(TrackBase *track)
 {
-    switch (channels) {
-    case 1:
-        volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 2:
-        volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 3:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 4:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 5:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 6:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 7:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
-        break;
-    case 8:
-        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
-        break;
+    Track* t = static_cast<Track*>(track);
+
+    audio_channel_mask_t channelMask = t->channelMask;
+    t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+    t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
+    channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+    t->channelCount = audio_channel_count_from_out_mask(channelMask);
+    ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
+            "Non-stereo channel mask: %d\n", channelMask);
+    t->channelMask = channelMask;
+    t->mInputBufferProvider = NULL;
+    t->mDownmixRequiresFormat = AUDIO_FORMAT_INVALID; // no format required
+    t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
+    // haptic
+    t->mHapticPlaybackEnabled = false;
+    t->mHapticIntensity = HAPTIC_SCALE_NONE;
+    t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
+    t->mMixerHapticChannelCount = 0;
+    t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
+    t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
+    t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
+    t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
+    t->mKeepContractedChannels = false;
+    // Check the downmixing (or upmixing) requirements.
+    status_t status = t->prepareForDownmix();
+    if (status != OK) {
+        ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
+        return BAD_VALUE;
     }
+    // prepareForDownmix() may change mDownmixRequiresFormat
+    ALOGVV("mMixerFormat:%#x  mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
+    t->prepareForReformat();
+    t->prepareForAdjustChannelsNonDestructive(mFrameCount);
+    t->prepareForAdjustChannels();
+    return OK;
 }
 
-/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * USEFLOATVOL (set to true if float volume is used)
- * ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
-    typename TO, typename TI, typename TA>
-void AudioMixer::Track::volumeMix(TO *out, size_t outFrames,
-        const TI *in, TA *aux, bool ramp)
+void AudioMixer::preProcess()
 {
-    if (USEFLOATVOL) {
-        if (ramp) {
-            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    mPrevVolume, mVolumeInc,
-#ifdef FLOAT_AUX
-                    &mPrevAuxLevel, mAuxInc
-#else
-                    &prevAuxLevel, auxInc
-#endif
-                );
-            if (ADJUSTVOL) {
-                adjustVolumeRamp(aux != NULL, true);
-            }
-        } else {
-            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    mVolume,
-#ifdef FLOAT_AUX
-                    mAuxLevel
-#else
-                    auxLevel
-#endif
-            );
-        }
-    } else {
-        if (ramp) {
-            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    prevVolume, volumeInc, &prevAuxLevel, auxInc);
-            if (ADJUSTVOL) {
-                adjustVolumeRamp(aux != NULL);
-            }
-        } else {
-            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
-                    volume, auxLevel);
+    for (const auto &pair : mTracks) {
+        // Clear contracted buffer before processing if contracted channels are saved
+        const std::shared_ptr<TrackBase> &tb = pair.second;
+        Track *t = static_cast<Track*>(tb.get());
+        if (t->mKeepContractedChannels) {
+            t->clearContractedBuffer();
         }
     }
 }
 
-/* This process hook is called when there is a single track without
- * aux buffer, volume ramp, or resampling.
- * TODO: Update the hook selection: this can properly handle aux and ramp.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27)
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::process__noResampleOneTrack()
+void AudioMixer::postProcess()
 {
-    ALOGVV("process__noResampleOneTrack\n");
-    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1,
-            "%zu != 1 tracks enabled", mEnabled.size());
-    const std::shared_ptr<Track> &t = mTracks[mEnabled[0]];
-    const uint32_t channels = t->mMixerChannelCount;
-    TO* out = reinterpret_cast<TO*>(t->mainBuffer);
-    TA* aux = reinterpret_cast<TA*>(t->auxBuffer);
-    const bool ramp = t->needsRamp();
-
-    for (size_t numFrames = mFrameCount; numFrames > 0; ) {
-        AudioBufferProvider::Buffer& b(t->buffer);
-        // get input buffer
-        b.frameCount = numFrames;
-        t->bufferProvider->getNextBuffer(&b);
-        const TI *in = reinterpret_cast<TI*>(b.raw);
-
-        // in == NULL can happen if the track was flushed just after having
-        // been enabled for mixing.
-        if (in == NULL || (((uintptr_t)in) & 3)) {
-            memset(out, 0, numFrames
-                    * channels * audio_bytes_per_sample(t->mMixerFormat));
-            ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: "
-                    "buffer %p track %p, channels %d, needs %#x",
-                    in, &t, t->channelCount, t->needs);
-            return;
-        }
-
-        const size_t outFrames = b.frameCount;
-        t->volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, false /* ADJUSTVOL */> (
-                out, outFrames, in, aux, ramp);
-
-        out += outFrames * channels;
-        if (aux != NULL) {
-            aux += outFrames;
-        }
-        numFrames -= b.frameCount;
-
-        // release buffer
-        t->bufferProvider->releaseBuffer(&b);
-    }
-    if (ramp) {
-        t->adjustVolumeRamp(aux != NULL, is_same<TI, float>::value);
-    }
-}
-
-void AudioMixer::processHapticData()
-{
+    // Process haptic data.
     // Need to keep consistent with VibrationEffect.scale(int, float, int)
     for (const auto &pair : mGroups) {
         // process by group of tracks with same output main buffer.
         const auto &group = pair.second;
         for (const int name : group) {
-            const std::shared_ptr<Track> &t = mTracks[name];
+            const std::shared_ptr<Track> &t = getTrack(name);
             if (t->mHapticPlaybackEnabled) {
                 size_t sampleCount = mFrameCount * t->mMixerHapticChannelCount;
                 float gamma = t->getHapticScaleGamma();
@@ -1887,225 +614,5 @@
     }
 }
 
-/* This track hook is called to do resampling then mixing,
- * pulling from the track's upstream AudioBufferProvider.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::Track::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux)
-{
-    ALOGVV("track__Resample\n");
-    mResampler->setSampleRate(sampleRate);
-    const bool ramp = needsRamp();
-    if (ramp || aux != NULL) {
-        // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step.
-        // if aux != NULL: resample with unity gain to temp buffer then apply send level.
-
-        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
-        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO));
-        mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider);
-
-        volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
-                out, outFrameCount, temp, aux, ramp);
-
-    } else { // constant volume gain
-        mResampler->setVolume(mVolume[0], mVolume[1]);
-        mResampler->resample((int32_t*)out, outFrameCount, bufferProvider);
-    }
-}
-
-/* This track hook is called to mix a track, when no resampling is required.
- * The input buffer should be present in in.
- *
- * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
- * TO: int32_t (Q4.27) or float
- * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
- * TA: int32_t (Q4.27) or float
- */
-template <int MIXTYPE, typename TO, typename TI, typename TA>
-void AudioMixer::Track::track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux)
-{
-    ALOGVV("track__NoResample\n");
-    const TI *in = static_cast<const TI *>(mIn);
-
-    volumeMix<MIXTYPE, is_same<TI, float>::value /* USEFLOATVOL */, true /* ADJUSTVOL */>(
-            out, frameCount, in, aux, needsRamp());
-
-    // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
-    // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
-    in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount;
-    mIn = in;
-}
-
-/* The Mixer engine generates either int32_t (Q4_27) or float data.
- * We use this function to convert the engine buffers
- * to the desired mixer output format, either int16_t (Q.15) or float.
- */
-/* static */
-void AudioMixer::convertMixerFormat(void *out, audio_format_t mixerOutFormat,
-        void *in, audio_format_t mixerInFormat, size_t sampleCount)
-{
-    switch (mixerInFormat) {
-    case AUDIO_FORMAT_PCM_FLOAT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    case AUDIO_FORMAT_PCM_16_BIT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
-            break;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-        break;
-    }
-}
-
-/* Returns the proper track hook to use for mixing the track into the output buffer.
- */
-/* static */
-AudioMixer::hook_t AudioMixer::Track::getTrackHook(int trackType, uint32_t channelCount,
-        audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
-{
-    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
-        switch (trackType) {
-        case TRACKTYPE_NOP:
-            return &Track::track__nop;
-        case TRACKTYPE_RESAMPLE:
-            return &Track::track__genericResample;
-        case TRACKTYPE_NORESAMPLEMONO:
-            return &Track::track__16BitsMono;
-        case TRACKTYPE_NORESAMPLE:
-            return &Track::track__16BitsStereo;
-        default:
-            LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
-            break;
-        }
-    }
-    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
-    switch (trackType) {
-    case TRACKTYPE_NOP:
-        return &Track::track__nop;
-    case TRACKTYPE_RESAMPLE:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__Resample<
-                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__Resample<
-                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    case TRACKTYPE_NORESAMPLEMONO:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                            MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                            MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    case TRACKTYPE_NORESAMPLE:
-        switch (mixerInFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return (AudioMixer::hook_t) &Track::track__NoResample<
-                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
-        break;
-    }
-    return NULL;
-}
-
-/* Returns the proper process hook for mixing tracks. Currently works only for
- * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
- *
- * TODO: Due to the special mixing considerations of duplicating to
- * a stereo output track, the input track cannot be MONO.  This should be
- * prevented by the caller.
- */
-/* static */
-AudioMixer::process_hook_t AudioMixer::getProcessHook(
-        int processType, uint32_t channelCount,
-        audio_format_t mixerInFormat, audio_format_t mixerOutFormat)
-{
-    if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK
-        LOG_ALWAYS_FATAL("bad processType: %d", processType);
-        return NULL;
-    }
-    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
-        return &AudioMixer::process__oneTrack16BitsStereoNoResampling;
-    }
-    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
-    switch (mixerInFormat) {
-    case AUDIO_FORMAT_PCM_FLOAT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, float /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, float /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    case AUDIO_FORMAT_PCM_16_BIT:
-        switch (mixerOutFormat) {
-        case AUDIO_FORMAT_PCM_FLOAT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, float /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return &AudioMixer::process__noResampleOneTrack<
-                    MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
-        default:
-            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
-            break;
-        }
-        break;
-    default:
-        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
-        break;
-    }
-    return NULL;
-}
-
 // ----------------------------------------------------------------------------
 } // namespace android
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
new file mode 100644
index 0000000..a54e22f
--- /dev/null
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -0,0 +1,1803 @@
+/*
+**
+** Copyright 2019, 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_TAG "AudioMixer"
+//#define LOG_NDEBUG 0
+
+#include <sstream>
+#include <string.h>
+
+#include <audio_utils/primitives.h>
+#include <cutils/compiler.h>
+#include <media/AudioMixerBase.h>
+#include <utils/Log.h>
+
+#include "AudioMixerOps.h"
+
+// The FCC_2 macro refers to the Fixed Channel Count of 2 for the legacy integer mixer.
+#ifndef FCC_2
+#define FCC_2 2
+#endif
+
+// Look for MONO_HACK for any Mono hack involving legacy mono channel to
+// stereo channel conversion.
+
+/* VERY_VERY_VERBOSE_LOGGING will show exactly which process hook and track hook is
+ * being used. This is a considerable amount of log spam, so don't enable unless you
+ * are verifying the hook based code.
+ */
+//#define VERY_VERY_VERBOSE_LOGGING
+#ifdef VERY_VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+//define ALOGVV printf  // for test-mixer.cpp
+#else
+#define ALOGVV(a...) do { } while (0)
+#endif
+
+// TODO: remove BLOCKSIZE unit of processing - it isn't needed anymore.
+static constexpr int BLOCKSIZE = 16;
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+bool AudioMixerBase::isValidFormat(audio_format_t format) const
+{
+    switch (format) {
+    case AUDIO_FORMAT_PCM_8_BIT:
+    case AUDIO_FORMAT_PCM_16_BIT:
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_FLOAT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool AudioMixerBase::isValidChannelMask(audio_channel_mask_t channelMask) const
+{
+    return audio_channel_count_from_out_mask(channelMask) <= MAX_NUM_CHANNELS;
+}
+
+std::shared_ptr<AudioMixerBase::TrackBase> AudioMixerBase::preCreateTrack()
+{
+    return std::make_shared<TrackBase>();
+}
+
+status_t AudioMixerBase::create(
+        int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId)
+{
+    LOG_ALWAYS_FATAL_IF(exists(name), "name %d already exists", name);
+
+    if (!isValidChannelMask(channelMask)) {
+        ALOGE("%s invalid channelMask: %#x", __func__, channelMask);
+        return BAD_VALUE;
+    }
+    if (!isValidFormat(format)) {
+        ALOGE("%s invalid format: %#x", __func__, format);
+        return BAD_VALUE;
+    }
+
+    auto t = preCreateTrack();
+    {
+        // TODO: move initialization to the Track constructor.
+        // assume default parameters for the track, except where noted below
+        t->needs = 0;
+
+        // Integer volume.
+        // Currently integer volume is kept for the legacy integer mixer.
+        // Will be removed when the legacy mixer path is removed.
+        t->volume[0] = 0;
+        t->volume[1] = 0;
+        t->prevVolume[0] = 0 << 16;
+        t->prevVolume[1] = 0 << 16;
+        t->volumeInc[0] = 0;
+        t->volumeInc[1] = 0;
+        t->auxLevel = 0;
+        t->auxInc = 0;
+        t->prevAuxLevel = 0;
+
+        // Floating point volume.
+        t->mVolume[0] = 0.f;
+        t->mVolume[1] = 0.f;
+        t->mPrevVolume[0] = 0.f;
+        t->mPrevVolume[1] = 0.f;
+        t->mVolumeInc[0] = 0.;
+        t->mVolumeInc[1] = 0.;
+        t->mAuxLevel = 0.;
+        t->mAuxInc = 0.;
+        t->mPrevAuxLevel = 0.;
+
+        // no initialization needed
+        // t->frameCount
+        t->channelCount = audio_channel_count_from_out_mask(channelMask);
+        t->enabled = false;
+        ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
+                "Non-stereo channel mask: %d\n", channelMask);
+        t->channelMask = channelMask;
+        t->sessionId = sessionId;
+        // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
+        t->bufferProvider = NULL;
+        t->buffer.raw = NULL;
+        // no initialization needed
+        // t->buffer.frameCount
+        t->hook = NULL;
+        t->mIn = NULL;
+        t->sampleRate = mSampleRate;
+        // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
+        t->mainBuffer = NULL;
+        t->auxBuffer = NULL;
+        t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
+        t->mFormat = format;
+        t->mMixerInFormat = kUseFloat && kUseNewMixer ?
+                AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
+        t->mMixerChannelMask = audio_channel_mask_from_representation_and_bits(
+                AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
+        t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
+        status_t status = postCreateTrack(t.get());
+        if (status != OK) return status;
+        mTracks[name] = t;
+        return OK;
+    }
+}
+
+// Called when channel masks have changed for a track name
+bool AudioMixerBase::setChannelMasks(int name,
+        audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (trackChannelMask == track->channelMask && mixerChannelMask == track->mMixerChannelMask) {
+        return false;  // no need to change
+    }
+    // always recompute for both channel masks even if only one has changed.
+    const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
+    const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
+
+    ALOG_ASSERT(trackChannelCount && mixerChannelCount);
+    track->channelMask = trackChannelMask;
+    track->channelCount = trackChannelCount;
+    track->mMixerChannelMask = mixerChannelMask;
+    track->mMixerChannelCount = mixerChannelCount;
+
+    // Resampler channels may have changed.
+    track->recreateResampler(mSampleRate);
+    return true;
+}
+
+void AudioMixerBase::destroy(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    ALOGV("deleteTrackName(%d)", name);
+
+    if (mTracks[name]->enabled) {
+        invalidate();
+    }
+    mTracks.erase(name); // deallocate track
+}
+
+void AudioMixerBase::enable(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (!track->enabled) {
+        track->enabled = true;
+        ALOGV("enable(%d)", name);
+        invalidate();
+    }
+}
+
+void AudioMixerBase::disable(int name)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    if (track->enabled) {
+        track->enabled = false;
+        ALOGV("disable(%d)", name);
+        invalidate();
+    }
+}
+
+/* Sets the volume ramp variables for the AudioMixer.
+ *
+ * The volume ramp variables are used to transition from the previous
+ * volume to the set volume.  ramp controls the duration of the transition.
+ * Its value is typically one state framecount period, but may also be 0,
+ * meaning "immediate."
+ *
+ * FIXME: 1) Volume ramp is enabled only if there is a nonzero integer increment
+ * even if there is a nonzero floating point increment (in that case, the volume
+ * change is immediate).  This restriction should be changed when the legacy mixer
+ * is removed (see #2).
+ * FIXME: 2) Integer volume variables are used for Legacy mixing and should be removed
+ * when no longer needed.
+ *
+ * @param newVolume set volume target in floating point [0.0, 1.0].
+ * @param ramp number of frames to increment over. if ramp is 0, the volume
+ * should be set immediately.  Currently ramp should not exceed 65535 (frames).
+ * @param pIntSetVolume pointer to the U4.12 integer target volume, set on return.
+ * @param pIntPrevVolume pointer to the U4.28 integer previous volume, set on return.
+ * @param pIntVolumeInc pointer to the U4.28 increment per output audio frame, set on return.
+ * @param pSetVolume pointer to the float target volume, set on return.
+ * @param pPrevVolume pointer to the float previous volume, set on return.
+ * @param pVolumeInc pointer to the float increment per output audio frame, set on return.
+ * @return true if the volume has changed, false if volume is same.
+ */
+static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
+        int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
+        float *pSetVolume, float *pPrevVolume, float *pVolumeInc) {
+    // check floating point volume to see if it is identical to the previously
+    // set volume.
+    // We do not use a tolerance here (and reject changes too small)
+    // as it may be confusing to use a different value than the one set.
+    // If the resulting volume is too small to ramp, it is a direct set of the volume.
+    if (newVolume == *pSetVolume) {
+        return false;
+    }
+    if (newVolume < 0) {
+        newVolume = 0; // should not have negative volumes
+    } else {
+        switch (fpclassify(newVolume)) {
+        case FP_SUBNORMAL:
+        case FP_NAN:
+            newVolume = 0;
+            break;
+        case FP_ZERO:
+            break; // zero volume is fine
+        case FP_INFINITE:
+            // Infinite volume could be handled consistently since
+            // floating point math saturates at infinities,
+            // but we limit volume to unity gain float.
+            // ramp = 0; break;
+            //
+            newVolume = AudioMixerBase::UNITY_GAIN_FLOAT;
+            break;
+        case FP_NORMAL:
+        default:
+            // Floating point does not have problems with overflow wrap
+            // that integer has.  However, we limit the volume to
+            // unity gain here.
+            // TODO: Revisit the volume limitation and perhaps parameterize.
+            if (newVolume > AudioMixerBase::UNITY_GAIN_FLOAT) {
+                newVolume = AudioMixerBase::UNITY_GAIN_FLOAT;
+            }
+            break;
+        }
+    }
+
+    // set floating point volume ramp
+    if (ramp != 0) {
+        // when the ramp completes, *pPrevVolume is set to *pSetVolume, so there
+        // is no computational mismatch; hence equality is checked here.
+        ALOGD_IF(*pPrevVolume != *pSetVolume, "previous float ramp hasn't finished,"
+                " prev:%f  set_to:%f", *pPrevVolume, *pSetVolume);
+        const float inc = (newVolume - *pPrevVolume) / ramp; // could be inf, nan, subnormal
+        // could be inf, cannot be nan, subnormal
+        const float maxv = std::max(newVolume, *pPrevVolume);
+
+        if (isnormal(inc) // inc must be a normal number (no subnormals, infinite, nan)
+                && maxv + inc != maxv) { // inc must make forward progress
+            *pVolumeInc = inc;
+            // ramp is set now.
+            // Note: if newVolume is 0, then near the end of the ramp,
+            // it may be possible that the ramped volume may be subnormal or
+            // temporarily negative by a small amount or subnormal due to floating
+            // point inaccuracies.
+        } else {
+            ramp = 0; // ramp not allowed
+        }
+    }
+
+    // compute and check integer volume, no need to check negative values
+    // The integer volume is limited to "unity_gain" to avoid wrapping and other
+    // audio artifacts, so it never reaches the range limit of U4.28.
+    // We safely use signed 16 and 32 bit integers here.
+    const float scaledVolume = newVolume * AudioMixerBase::UNITY_GAIN_INT; // not neg, subnormal, nan
+    const int32_t intVolume = (scaledVolume >= (float)AudioMixerBase::UNITY_GAIN_INT) ?
+            AudioMixerBase::UNITY_GAIN_INT : (int32_t)scaledVolume;
+
+    // set integer volume ramp
+    if (ramp != 0) {
+        // integer volume is U4.12 (to use 16 bit multiplies), but ramping uses U4.28.
+        // when the ramp completes, *pIntPrevVolume is set to *pIntSetVolume << 16, so there
+        // is no computational mismatch; hence equality is checked here.
+        ALOGD_IF(*pIntPrevVolume != *pIntSetVolume << 16, "previous int ramp hasn't finished,"
+                " prev:%d  set_to:%d", *pIntPrevVolume, *pIntSetVolume << 16);
+        const int32_t inc = ((intVolume << 16) - *pIntPrevVolume) / ramp;
+
+        if (inc != 0) { // inc must make forward progress
+            *pIntVolumeInc = inc;
+        } else {
+            ramp = 0; // ramp not allowed
+        }
+    }
+
+    // if no ramp, or ramp not allowed, then clear float and integer increments
+    if (ramp == 0) {
+        *pVolumeInc = 0;
+        *pPrevVolume = newVolume;
+        *pIntVolumeInc = 0;
+        *pIntPrevVolume = intVolume << 16;
+    }
+    *pSetVolume = newVolume;
+    *pIntSetVolume = intVolume;
+    return true;
+}
+
+void AudioMixerBase::setParameter(int name, int target, int param, void *value)
+{
+    LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
+    const std::shared_ptr<TrackBase> &track = mTracks[name];
+
+    int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
+    int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
+
+    switch (target) {
+
+    case TRACK:
+        switch (param) {
+        case CHANNEL_MASK: {
+            const audio_channel_mask_t trackChannelMask =
+                static_cast<audio_channel_mask_t>(valueInt);
+            if (setChannelMasks(name, trackChannelMask, track->mMixerChannelMask)) {
+                ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
+                invalidate();
+            }
+            } break;
+        case MAIN_BUFFER:
+            if (track->mainBuffer != valueBuf) {
+                track->mainBuffer = valueBuf;
+                ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
+                invalidate();
+            }
+            break;
+        case AUX_BUFFER:
+            if (track->auxBuffer != valueBuf) {
+                track->auxBuffer = valueBuf;
+                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
+                invalidate();
+            }
+            break;
+        case FORMAT: {
+            audio_format_t format = static_cast<audio_format_t>(valueInt);
+            if (track->mFormat != format) {
+                ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format);
+                track->mFormat = format;
+                ALOGV("setParameter(TRACK, FORMAT, %#x)", format);
+                invalidate();
+            }
+            } break;
+        case MIXER_FORMAT: {
+            audio_format_t format = static_cast<audio_format_t>(valueInt);
+            if (track->mMixerFormat != format) {
+                track->mMixerFormat = format;
+                ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
+            }
+            } break;
+        case MIXER_CHANNEL_MASK: {
+            const audio_channel_mask_t mixerChannelMask =
+                    static_cast<audio_channel_mask_t>(valueInt);
+            if (setChannelMasks(name, track->channelMask, mixerChannelMask)) {
+                ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
+                invalidate();
+            }
+            } break;
+        default:
+            LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
+        }
+        break;
+
+    case RESAMPLE:
+        switch (param) {
+        case SAMPLE_RATE:
+            ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
+            if (track->setResampler(uint32_t(valueInt), mSampleRate)) {
+                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
+                        uint32_t(valueInt));
+                invalidate();
+            }
+            break;
+        case RESET:
+            track->resetResampler();
+            invalidate();
+            break;
+        case REMOVE:
+            track->mResampler.reset(nullptr);
+            track->sampleRate = mSampleRate;
+            invalidate();
+            break;
+        default:
+            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
+        }
+        break;
+
+    case RAMP_VOLUME:
+    case VOLUME:
+        switch (param) {
+        case AUXLEVEL:
+            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
+                    target == RAMP_VOLUME ? mFrameCount : 0,
+                    &track->auxLevel, &track->prevAuxLevel, &track->auxInc,
+                    &track->mAuxLevel, &track->mPrevAuxLevel, &track->mAuxInc)) {
+                ALOGV("setParameter(%s, AUXLEVEL: %04x)",
+                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track->auxLevel);
+                invalidate();
+            }
+            break;
+        default:
+            if ((unsigned)param >= VOLUME0 && (unsigned)param < VOLUME0 + MAX_NUM_VOLUMES) {
+                if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
+                        target == RAMP_VOLUME ? mFrameCount : 0,
+                        &track->volume[param - VOLUME0],
+                        &track->prevVolume[param - VOLUME0],
+                        &track->volumeInc[param - VOLUME0],
+                        &track->mVolume[param - VOLUME0],
+                        &track->mPrevVolume[param - VOLUME0],
+                        &track->mVolumeInc[param - VOLUME0])) {
+                    ALOGV("setParameter(%s, VOLUME%d: %04x)",
+                            target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
+                                    track->volume[param - VOLUME0]);
+                    invalidate();
+                }
+            } else {
+                LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
+            }
+        }
+        break;
+
+    default:
+        LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
+    }
+}
+
+bool AudioMixerBase::TrackBase::setResampler(uint32_t trackSampleRate, uint32_t devSampleRate)
+{
+    if (trackSampleRate != devSampleRate || mResampler.get() != nullptr) {
+        if (sampleRate != trackSampleRate) {
+            sampleRate = trackSampleRate;
+            if (mResampler.get() == nullptr) {
+                ALOGV("Creating resampler from track %d Hz to device %d Hz",
+                        trackSampleRate, devSampleRate);
+                AudioResampler::src_quality quality;
+                // force lowest quality level resampler if use case isn't music or video
+                // FIXME this is flawed for dynamic sample rates, as we choose the resampler
+                // quality level based on the initial ratio, but that could change later.
+                // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
+                if (isMusicRate(trackSampleRate)) {
+                    quality = AudioResampler::DEFAULT_QUALITY;
+                } else {
+                    quality = AudioResampler::DYN_LOW_QUALITY;
+                }
+
+                // TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
+                // but if none exists, it is the channel count (1 for mono).
+                const int resamplerChannelCount = getOutputChannelCount();
+                ALOGVV("Creating resampler:"
+                        " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
+                        mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
+                mResampler.reset(AudioResampler::create(
+                        mMixerInFormat,
+                        resamplerChannelCount,
+                        devSampleRate, quality));
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+/* Checks to see if the volume ramp has completed and clears the increment
+ * variables appropriately.
+ *
+ * FIXME: There is code to handle int/float ramp variable switchover should it not
+ * complete within a mixer buffer processing call, but it is preferred to avoid switchover
+ * due to precision issues.  The switchover code is included for legacy code purposes
+ * and can be removed once the integer volume is removed.
+ *
+ * It is not sufficient to clear only the volumeInc integer variable because
+ * if one channel requires ramping, all channels are ramped.
+ *
+ * There is a bit of duplicated code here, but it keeps backward compatibility.
+ */
+void AudioMixerBase::TrackBase::adjustVolumeRamp(bool aux, bool useFloat)
+{
+    if (useFloat) {
+        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
+            if ((mVolumeInc[i] > 0 && mPrevVolume[i] + mVolumeInc[i] >= mVolume[i]) ||
+                     (mVolumeInc[i] < 0 && mPrevVolume[i] + mVolumeInc[i] <= mVolume[i])) {
+                volumeInc[i] = 0;
+                prevVolume[i] = volume[i] << 16;
+                mVolumeInc[i] = 0.;
+                mPrevVolume[i] = mVolume[i];
+            } else {
+                //ALOGV("ramp: %f %f %f", mVolume[i], mPrevVolume[i], mVolumeInc[i]);
+                prevVolume[i] = u4_28_from_float(mPrevVolume[i]);
+            }
+        }
+    } else {
+        for (uint32_t i = 0; i < MAX_NUM_VOLUMES; i++) {
+            if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
+                    ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
+                volumeInc[i] = 0;
+                prevVolume[i] = volume[i] << 16;
+                mVolumeInc[i] = 0.;
+                mPrevVolume[i] = mVolume[i];
+            } else {
+                //ALOGV("ramp: %d %d %d", volume[i] << 16, prevVolume[i], volumeInc[i]);
+                mPrevVolume[i]  = float_from_u4_28(prevVolume[i]);
+            }
+        }
+    }
+
+    if (aux) {
+#ifdef FLOAT_AUX
+        if (useFloat) {
+            if ((mAuxInc > 0.f && mPrevAuxLevel + mAuxInc >= mAuxLevel) ||
+                    (mAuxInc < 0.f && mPrevAuxLevel + mAuxInc <= mAuxLevel)) {
+                auxInc = 0;
+                prevAuxLevel = auxLevel << 16;
+                mAuxInc = 0.f;
+                mPrevAuxLevel = mAuxLevel;
+            }
+        } else
+#endif
+        if ((auxInc > 0 && ((prevAuxLevel + auxInc) >> 16) >= auxLevel) ||
+                (auxInc < 0 && ((prevAuxLevel + auxInc) >> 16) <= auxLevel)) {
+            auxInc = 0;
+            prevAuxLevel = auxLevel << 16;
+            mAuxInc = 0.f;
+            mPrevAuxLevel = mAuxLevel;
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::recreateResampler(uint32_t devSampleRate)
+{
+    if (mResampler.get() != nullptr) {
+        const uint32_t resetToSampleRate = sampleRate;
+        mResampler.reset(nullptr);
+        sampleRate = devSampleRate; // without resampler, track rate is device sample rate.
+        // recreate the resampler with updated format, channels, saved sampleRate.
+        setResampler(resetToSampleRate /*trackSampleRate*/, devSampleRate);
+    }
+}
+
+size_t AudioMixerBase::getUnreleasedFrames(int name) const
+{
+    const auto it = mTracks.find(name);
+    if (it != mTracks.end()) {
+        return it->second->getUnreleasedFrames();
+    }
+    return 0;
+}
+
+std::string AudioMixerBase::trackNames() const
+{
+    std::stringstream ss;
+    for (const auto &pair : mTracks) {
+        ss << pair.first << " ";
+    }
+    return ss.str();
+}
+
+void AudioMixerBase::process__validate()
+{
+    // TODO: fix all16BitsStereNoResample logic to
+    // either properly handle muted tracks (it should ignore them)
+    // or remove altogether as an obsolete optimization.
+    bool all16BitsStereoNoResample = true;
+    bool resampling = false;
+    bool volumeRamp = false;
+
+    mEnabled.clear();
+    mGroups.clear();
+    for (const auto &pair : mTracks) {
+        const int name = pair.first;
+        const std::shared_ptr<TrackBase> &t = pair.second;
+        if (!t->enabled) continue;
+
+        mEnabled.emplace_back(name);  // we add to mEnabled in order of name.
+        mGroups[t->mainBuffer].emplace_back(name); // mGroups also in order of name.
+
+        uint32_t n = 0;
+        // FIXME can overflow (mask is only 3 bits)
+        n |= NEEDS_CHANNEL_1 + t->channelCount - 1;
+        if (t->doesResample()) {
+            n |= NEEDS_RESAMPLE;
+        }
+        if (t->auxLevel != 0 && t->auxBuffer != NULL) {
+            n |= NEEDS_AUX;
+        }
+
+        if (t->volumeInc[0]|t->volumeInc[1]) {
+            volumeRamp = true;
+        } else if (!t->doesResample() && t->volumeRL == 0) {
+            n |= NEEDS_MUTE;
+        }
+        t->needs = n;
+
+        if (n & NEEDS_MUTE) {
+            t->hook = &TrackBase::track__nop;
+        } else {
+            if (n & NEEDS_AUX) {
+                all16BitsStereoNoResample = false;
+            }
+            if (n & NEEDS_RESAMPLE) {
+                all16BitsStereoNoResample = false;
+                resampling = true;
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1
+                        && t->channelMask == AUDIO_CHANNEL_OUT_MONO // MONO_HACK
+                        && isAudioChannelPositionMask(t->mMixerChannelMask)) {
+                    t->hook = TrackBase::getTrackHook(
+                            TRACKTYPE_RESAMPLEMONO, t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                } else if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2
+                        && t->useStereoVolume()) {
+                    t->hook = TrackBase::getTrackHook(
+                            TRACKTYPE_RESAMPLESTEREO, t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                } else {
+                    t->hook = TrackBase::getTrackHook(
+                            TRACKTYPE_RESAMPLE, t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                }
+                ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
+                        "Track %d needs downmix + resample", name);
+            } else {
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
+                    t->hook = TrackBase::getTrackHook(
+                            (isAudioChannelPositionMask(t->mMixerChannelMask)  // TODO: MONO_HACK
+                                    && t->channelMask == AUDIO_CHANNEL_OUT_MONO)
+                                ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
+                            t->mMixerChannelCount,
+                            t->mMixerInFormat, t->mMixerFormat);
+                    all16BitsStereoNoResample = false;
+                }
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
+                    t->hook = TrackBase::getTrackHook(
+                            t->useStereoVolume() ? TRACKTYPE_NORESAMPLESTEREO
+                                    : TRACKTYPE_NORESAMPLE,
+                            t->mMixerChannelCount, t->mMixerInFormat,
+                            t->mMixerFormat);
+                    ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
+                            "Track %d needs downmix", name);
+                }
+            }
+        }
+    }
+
+    // select the processing hooks
+    mHook = &AudioMixerBase::process__nop;
+    if (mEnabled.size() > 0) {
+        if (resampling) {
+            if (mOutputTemp.get() == nullptr) {
+                mOutputTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
+            }
+            if (mResampleTemp.get() == nullptr) {
+                mResampleTemp.reset(new int32_t[MAX_NUM_CHANNELS * mFrameCount]);
+            }
+            mHook = &AudioMixerBase::process__genericResampling;
+        } else {
+            // we keep temp arrays around.
+            mHook = &AudioMixerBase::process__genericNoResampling;
+            if (all16BitsStereoNoResample && !volumeRamp) {
+                if (mEnabled.size() == 1) {
+                    const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+                    if ((t->needs & NEEDS_MUTE) == 0) {
+                        // The check prevents a muted track from acquiring a process hook.
+                        //
+                        // This is dangerous if the track is MONO as that requires
+                        // special case handling due to implicit channel duplication.
+                        // Stereo or Multichannel should actually be fine here.
+                        mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
+                                t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat,
+                                t->useStereoVolume());
+                    }
+                }
+            }
+        }
+    }
+
+    ALOGV("mixer configuration change: %zu "
+        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
+        mEnabled.size(), all16BitsStereoNoResample, resampling, volumeRamp);
+
+    process();
+
+    // Now that the volume ramp has been done, set optimal state and
+    // track hooks for subsequent mixer process
+    if (mEnabled.size() > 0) {
+        bool allMuted = true;
+
+        for (const int name : mEnabled) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            if (!t->doesResample() && t->volumeRL == 0) {
+                t->needs |= NEEDS_MUTE;
+                t->hook = &TrackBase::track__nop;
+            } else {
+                allMuted = false;
+            }
+        }
+        if (allMuted) {
+            mHook = &AudioMixerBase::process__nop;
+        } else if (all16BitsStereoNoResample) {
+            if (mEnabled.size() == 1) {
+                //const int i = 31 - __builtin_clz(enabledTracks);
+                const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+                // Muted single tracks handled by allMuted above.
+                mHook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
+                        t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat,
+                        t->useStereoVolume());
+            }
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::track__genericResample(
+        int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+    ALOGVV("track__genericResample\n");
+    mResampler->setSampleRate(sampleRate);
+
+    // ramp gain - resample to temp buffer and scale/mix in 2nd step
+    if (aux != NULL) {
+        // always resample with unity gain when sending to auxiliary buffer to be able
+        // to apply send level after resampling
+        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(int32_t));
+        mResampler->resample(temp, outFrameCount, bufferProvider);
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            volumeRampStereo(out, outFrameCount, temp, aux);
+        } else {
+            volumeStereo(out, outFrameCount, temp, aux);
+        }
+    } else {
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+            mResampler->resample(temp, outFrameCount, bufferProvider);
+            volumeRampStereo(out, outFrameCount, temp, aux);
+        }
+
+        // constant gain
+        else {
+            mResampler->setVolume(mVolume[0], mVolume[1]);
+            mResampler->resample(out, outFrameCount, bufferProvider);
+        }
+    }
+}
+
+void AudioMixerBase::TrackBase::track__nop(int32_t* out __unused,
+        size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
+{
+}
+
+void AudioMixerBase::TrackBase::volumeRampStereo(
+        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    int32_t vl = prevVolume[0];
+    int32_t vr = prevVolume[1];
+    const int32_t vlInc = volumeInc[0];
+    const int32_t vrInc = volumeInc[1];
+
+    //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+    //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+    // ramp volume
+    if (CC_UNLIKELY(aux != NULL)) {
+        int32_t va = prevAuxLevel;
+        const int32_t vaInc = auxInc;
+        int32_t l;
+        int32_t r;
+
+        do {
+            l = (*temp++ >> 12);
+            r = (*temp++ >> 12);
+            *out++ += (vl >> 16) * l;
+            *out++ += (vr >> 16) * r;
+            *aux++ += (va >> 17) * (l + r);
+            vl += vlInc;
+            vr += vrInc;
+            va += vaInc;
+        } while (--frameCount);
+        prevAuxLevel = va;
+    } else {
+        do {
+            *out++ += (vl >> 16) * (*temp++ >> 12);
+            *out++ += (vr >> 16) * (*temp++ >> 12);
+            vl += vlInc;
+            vr += vrInc;
+        } while (--frameCount);
+    }
+    prevVolume[0] = vl;
+    prevVolume[1] = vr;
+    adjustVolumeRamp(aux != NULL);
+}
+
+void AudioMixerBase::TrackBase::volumeStereo(
+        int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    const int16_t vl = volume[0];
+    const int16_t vr = volume[1];
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        const int16_t va = auxLevel;
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+            aux[0] = mulAdd(a, va, aux[0]);
+            aux++;
+        } while (--frameCount);
+    } else {
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+        } while (--frameCount);
+    }
+}
+
+void AudioMixerBase::TrackBase::track__16BitsStereo(
+        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
+{
+    ALOGVV("track__16BitsStereo\n");
+    const int16_t *in = static_cast<const int16_t *>(mIn);
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        int32_t l;
+        int32_t r;
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            int32_t va = prevAuxLevel;
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+            const int32_t vaInc = auxInc;
+            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                l = (int32_t)*in++;
+                r = (int32_t)*in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * r;
+                *aux++ += (va >> 17) * (l + r);
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            prevAuxLevel = va;
+            adjustVolumeRamp(true);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = volumeRL;
+            const int16_t va = (int16_t)auxLevel;
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+                aux[0] = mulAdd(a, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+
+            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                *out++ += (vl >> 16) * (int32_t) *in++;
+                *out++ += (vr >> 16) * (int32_t) *in++;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            adjustVolumeRamp(false);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = volumeRL;
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    mIn = in;
+}
+
+void AudioMixerBase::TrackBase::track__16BitsMono(
+        int32_t* out, size_t frameCount, int32_t* temp __unused, int32_t* aux)
+{
+    ALOGVV("track__16BitsMono\n");
+    const int16_t *in = static_cast<int16_t const *>(mIn);
+
+    if (CC_UNLIKELY(aux != NULL)) {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1]|auxInc)) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            int32_t va = prevAuxLevel;
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+            const int32_t vaInc = auxInc;
+
+            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                *aux++ += (va >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            prevAuxLevel = va;
+            adjustVolumeRamp(true);
+        }
+        // constant gain
+        else {
+            const int16_t vl = volume[0];
+            const int16_t vr = volume[1];
+            const int16_t va = (int16_t)auxLevel;
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+                aux[0] = mulAdd(l, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if (CC_UNLIKELY(volumeInc[0]|volumeInc[1])) {
+            int32_t vl = prevVolume[0];
+            int32_t vr = prevVolume[1];
+            const int32_t vlInc = volumeInc[0];
+            const int32_t vrInc = volumeInc[1];
+
+            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            prevVolume[0] = vl;
+            prevVolume[1] = vr;
+            adjustVolumeRamp(false);
+        }
+        // constant gain
+        else {
+            const int16_t vl = volume[0];
+            const int16_t vr = volume[1];
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    mIn = in;
+}
+
+// no-op case
+void AudioMixerBase::process__nop()
+{
+    ALOGVV("process__nop\n");
+
+    for (const auto &pair : mGroups) {
+        // process by group of tracks with same output buffer to
+        // avoid multiple memset() on same buffer
+        const auto &group = pair.second;
+
+        const std::shared_ptr<TrackBase> &t = mTracks[group[0]];
+        memset(t->mainBuffer, 0,
+                mFrameCount * audio_bytes_per_frame(t->getMixerChannelCount(), t->mMixerFormat));
+
+        // now consume data
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            size_t outFrames = mFrameCount;
+            while (outFrames) {
+                t->buffer.frameCount = outFrames;
+                t->bufferProvider->getNextBuffer(&t->buffer);
+                if (t->buffer.raw == NULL) break;
+                outFrames -= t->buffer.frameCount;
+                t->bufferProvider->releaseBuffer(&t->buffer);
+            }
+        }
+    }
+}
+
+// generic code without resampling
+void AudioMixerBase::process__genericNoResampling()
+{
+    ALOGVV("process__genericNoResampling\n");
+    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
+
+    for (const auto &pair : mGroups) {
+        // process by group of tracks with same output main buffer to
+        // avoid multiple memset() on same buffer
+        const auto &group = pair.second;
+
+        // acquire buffer
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            t->buffer.frameCount = mFrameCount;
+            t->bufferProvider->getNextBuffer(&t->buffer);
+            t->frameCount = t->buffer.frameCount;
+            t->mIn = t->buffer.raw;
+        }
+
+        int32_t *out = (int *)pair.first;
+        size_t numFrames = 0;
+        do {
+            const size_t frameCount = std::min((size_t)BLOCKSIZE, mFrameCount - numFrames);
+            memset(outTemp, 0, sizeof(outTemp));
+            for (const int name : group) {
+                const std::shared_ptr<TrackBase> &t = mTracks[name];
+                int32_t *aux = NULL;
+                if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
+                    aux = t->auxBuffer + numFrames;
+                }
+                for (int outFrames = frameCount; outFrames > 0; ) {
+                    // t->in == nullptr can happen if the track was flushed just after having
+                    // been enabled for mixing.
+                    if (t->mIn == nullptr) {
+                        break;
+                    }
+                    size_t inFrames = (t->frameCount > outFrames)?outFrames:t->frameCount;
+                    if (inFrames > 0) {
+                        (t.get()->*t->hook)(
+                                outTemp + (frameCount - outFrames) * t->mMixerChannelCount,
+                                inFrames, mResampleTemp.get() /* naked ptr */, aux);
+                        t->frameCount -= inFrames;
+                        outFrames -= inFrames;
+                        if (CC_UNLIKELY(aux != NULL)) {
+                            aux += inFrames;
+                        }
+                    }
+                    if (t->frameCount == 0 && outFrames) {
+                        t->bufferProvider->releaseBuffer(&t->buffer);
+                        t->buffer.frameCount = (mFrameCount - numFrames) -
+                                (frameCount - outFrames);
+                        t->bufferProvider->getNextBuffer(&t->buffer);
+                        t->mIn = t->buffer.raw;
+                        if (t->mIn == nullptr) {
+                            break;
+                        }
+                        t->frameCount = t->buffer.frameCount;
+                    }
+                }
+            }
+
+            const std::shared_ptr<TrackBase> &t1 = mTracks[group[0]];
+            convertMixerFormat(out, t1->mMixerFormat, outTemp, t1->mMixerInFormat,
+                    frameCount * t1->mMixerChannelCount);
+            // TODO: fix ugly casting due to choice of out pointer type
+            out = reinterpret_cast<int32_t*>((uint8_t*)out
+                    + frameCount * t1->mMixerChannelCount
+                    * audio_bytes_per_sample(t1->mMixerFormat));
+            numFrames += frameCount;
+        } while (numFrames < mFrameCount);
+
+        // release each track's buffer
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            t->bufferProvider->releaseBuffer(&t->buffer);
+        }
+    }
+}
+
+// generic code with resampling
+void AudioMixerBase::process__genericResampling()
+{
+    ALOGVV("process__genericResampling\n");
+    int32_t * const outTemp = mOutputTemp.get(); // naked ptr
+    size_t numFrames = mFrameCount;
+
+    for (const auto &pair : mGroups) {
+        const auto &group = pair.second;
+        const std::shared_ptr<TrackBase> &t1 = mTracks[group[0]];
+
+        // clear temp buffer
+        memset(outTemp, 0, sizeof(*outTemp) * t1->mMixerChannelCount * mFrameCount);
+        for (const int name : group) {
+            const std::shared_ptr<TrackBase> &t = mTracks[name];
+            int32_t *aux = NULL;
+            if (CC_UNLIKELY(t->needs & NEEDS_AUX)) {
+                aux = t->auxBuffer;
+            }
+
+            // this is a little goofy, on the resampling case we don't
+            // acquire/release the buffers because it's done by
+            // the resampler.
+            if (t->needs & NEEDS_RESAMPLE) {
+                (t.get()->*t->hook)(outTemp, numFrames, mResampleTemp.get() /* naked ptr */, aux);
+            } else {
+
+                size_t outFrames = 0;
+
+                while (outFrames < numFrames) {
+                    t->buffer.frameCount = numFrames - outFrames;
+                    t->bufferProvider->getNextBuffer(&t->buffer);
+                    t->mIn = t->buffer.raw;
+                    // t->mIn == nullptr can happen if the track was flushed just after having
+                    // been enabled for mixing.
+                    if (t->mIn == nullptr) break;
+
+                    (t.get()->*t->hook)(
+                            outTemp + outFrames * t->mMixerChannelCount, t->buffer.frameCount,
+                            mResampleTemp.get() /* naked ptr */,
+                            aux != nullptr ? aux + outFrames : nullptr);
+                    outFrames += t->buffer.frameCount;
+
+                    t->bufferProvider->releaseBuffer(&t->buffer);
+                }
+            }
+        }
+        convertMixerFormat(t1->mainBuffer, t1->mMixerFormat,
+                outTemp, t1->mMixerInFormat, numFrames * t1->mMixerChannelCount);
+    }
+}
+
+// one track, 16 bits stereo without resampling is the most common case
+void AudioMixerBase::process__oneTrack16BitsStereoNoResampling()
+{
+    ALOGVV("process__oneTrack16BitsStereoNoResampling\n");
+    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 0,
+            "%zu != 1 tracks enabled", mEnabled.size());
+    const int name = mEnabled[0];
+    const std::shared_ptr<TrackBase> &t = mTracks[name];
+
+    AudioBufferProvider::Buffer& b(t->buffer);
+
+    int32_t* out = t->mainBuffer;
+    float *fout = reinterpret_cast<float*>(out);
+    size_t numFrames = mFrameCount;
+
+    const int16_t vl = t->volume[0];
+    const int16_t vr = t->volume[1];
+    const uint32_t vrl = t->volumeRL;
+    while (numFrames) {
+        b.frameCount = numFrames;
+        t->bufferProvider->getNextBuffer(&b);
+        const int16_t *in = b.i16;
+
+        // in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (in == NULL || (((uintptr_t)in) & 3)) {
+            if ( AUDIO_FORMAT_PCM_FLOAT == t->mMixerFormat ) {
+                 memset((char*)fout, 0, numFrames
+                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
+            } else {
+                 memset((char*)out, 0, numFrames
+                         * t->mMixerChannelCount * audio_bytes_per_sample(t->mMixerFormat));
+            }
+            ALOGE_IF((((uintptr_t)in) & 3),
+                    "process__oneTrack16BitsStereoNoResampling: misaligned buffer"
+                    " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
+                    in, name, t->channelCount, t->needs, vrl, t->mVolume[0], t->mVolume[1]);
+            return;
+        }
+        size_t outFrames = b.frameCount;
+
+        switch (t->mMixerFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            do {
+                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                in += 2;
+                int32_t l = mulRL(1, rl, vrl);
+                int32_t r = mulRL(0, rl, vrl);
+                *fout++ = float_from_q4_27(l);
+                *fout++ = float_from_q4_27(r);
+                // Note: In case of later int16_t sink output,
+                // conversion and clamping is done by memcpy_to_i16_from_float().
+            } while (--outFrames);
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
+                // volume is boosted, so we might need to clamp even though
+                // we process only one track.
+                do {
+                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                    in += 2;
+                    int32_t l = mulRL(1, rl, vrl) >> 12;
+                    int32_t r = mulRL(0, rl, vrl) >> 12;
+                    // clamping...
+                    l = clamp16(l);
+                    r = clamp16(r);
+                    *out++ = (r<<16) | (l & 0xFFFF);
+                } while (--outFrames);
+            } else {
+                do {
+                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+                    in += 2;
+                    int32_t l = mulRL(1, rl, vrl) >> 12;
+                    int32_t r = mulRL(0, rl, vrl) >> 12;
+                    *out++ = (r<<16) | (l & 0xFFFF);
+                } while (--outFrames);
+            }
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixer format: %d", t->mMixerFormat);
+        }
+        numFrames -= b.frameCount;
+        t->bufferProvider->releaseBuffer(&b);
+    }
+}
+
+/* TODO: consider whether this level of optimization is necessary.
+ * Perhaps just stick with a single for loop.
+ */
+
+// Needs to derive a compile time constant (constexpr).  Could be targeted to go
+// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
+#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
+        (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE,
+        typename TO, typename TI, typename TV, typename TA, typename TAV>
+static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
+        const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
+{
+    switch (channels) {
+    case 1:
+        volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 2:
+        volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 3:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 4:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 5:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 6:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 7:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    case 8:
+        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
+                frameCount, in, aux, vol, volinc, vola, volainc);
+        break;
+    }
+}
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE,
+        typename TO, typename TI, typename TV, typename TA, typename TAV>
+static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
+        const TI* in, TA* aux, const TV *vol, TAV vola)
+{
+    switch (channels) {
+    case 1:
+        volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 2:
+        volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 3:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 4:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 5:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 6:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 7:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
+        break;
+    case 8:
+        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
+        break;
+    }
+}
+
+/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * USEFLOATVOL (set to true if float volume is used)
+ * ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
+    typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::volumeMix(TO *out, size_t outFrames,
+        const TI *in, TA *aux, bool ramp)
+{
+    if (USEFLOATVOL) {
+        if (ramp) {
+            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    mPrevVolume, mVolumeInc,
+#ifdef FLOAT_AUX
+                    &mPrevAuxLevel, mAuxInc
+#else
+                    &prevAuxLevel, auxInc
+#endif
+                );
+            if (ADJUSTVOL) {
+                adjustVolumeRamp(aux != NULL, true);
+            }
+        } else {
+            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    mVolume,
+#ifdef FLOAT_AUX
+                    mAuxLevel
+#else
+                    auxLevel
+#endif
+            );
+        }
+    } else {
+        if (ramp) {
+            volumeRampMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    prevVolume, volumeInc, &prevAuxLevel, auxInc);
+            if (ADJUSTVOL) {
+                adjustVolumeRamp(aux != NULL);
+            }
+        } else {
+            volumeMulti<MIXTYPE>(mMixerChannelCount, out, outFrames, in, aux,
+                    volume, auxLevel);
+        }
+    }
+}
+
+/* This process hook is called when there is a single track without
+ * aux buffer, volume ramp, or resampling.
+ * TODO: Update the hook selection: this can properly handle aux and ramp.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27)
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::process__noResampleOneTrack()
+{
+    ALOGVV("process__noResampleOneTrack\n");
+    LOG_ALWAYS_FATAL_IF(mEnabled.size() != 1,
+            "%zu != 1 tracks enabled", mEnabled.size());
+    const std::shared_ptr<TrackBase> &t = mTracks[mEnabled[0]];
+    const uint32_t channels = t->mMixerChannelCount;
+    TO* out = reinterpret_cast<TO*>(t->mainBuffer);
+    TA* aux = reinterpret_cast<TA*>(t->auxBuffer);
+    const bool ramp = t->needsRamp();
+
+    for (size_t numFrames = mFrameCount; numFrames > 0; ) {
+        AudioBufferProvider::Buffer& b(t->buffer);
+        // get input buffer
+        b.frameCount = numFrames;
+        t->bufferProvider->getNextBuffer(&b);
+        const TI *in = reinterpret_cast<TI*>(b.raw);
+
+        // in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (in == NULL || (((uintptr_t)in) & 3)) {
+            memset(out, 0, numFrames
+                    * channels * audio_bytes_per_sample(t->mMixerFormat));
+            ALOGE_IF((((uintptr_t)in) & 3), "process__noResampleOneTrack: bus error: "
+                    "buffer %p track %p, channels %d, needs %#x",
+                    in, &t, t->channelCount, t->needs);
+            return;
+        }
+
+        const size_t outFrames = b.frameCount;
+        t->volumeMix<MIXTYPE, std::is_same_v<TI, float> /* USEFLOATVOL */, false /* ADJUSTVOL */> (
+                out, outFrames, in, aux, ramp);
+
+        out += outFrames * channels;
+        if (aux != NULL) {
+            aux += outFrames;
+        }
+        numFrames -= b.frameCount;
+
+        // release buffer
+        t->bufferProvider->releaseBuffer(&b);
+    }
+    if (ramp) {
+        t->adjustVolumeRamp(aux != NULL, std::is_same_v<TI, float>);
+    }
+}
+
+/* This track hook is called to do resampling then mixing,
+ * pulling from the track's upstream AudioBufferProvider.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::track__Resample(TO* out, size_t outFrameCount, TO* temp, TA* aux)
+{
+    ALOGVV("track__Resample\n");
+    mResampler->setSampleRate(sampleRate);
+    const bool ramp = needsRamp();
+    if (MIXTYPE == MIXTYPE_MONOEXPAND || MIXTYPE == MIXTYPE_STEREOEXPAND // custom volume handling
+            || ramp || aux != NULL) {
+        // if ramp:        resample with unity gain to temp buffer and scale/mix in 2nd step.
+        // if aux != NULL: resample with unity gain to temp buffer then apply send level.
+
+        mResampler->setVolume(UNITY_GAIN_FLOAT, UNITY_GAIN_FLOAT);
+        memset(temp, 0, outFrameCount * mMixerChannelCount * sizeof(TO));
+        mResampler->resample((int32_t*)temp, outFrameCount, bufferProvider);
+
+        volumeMix<MIXTYPE, std::is_same_v<TI, float> /* USEFLOATVOL */, true /* ADJUSTVOL */>(
+                out, outFrameCount, temp, aux, ramp);
+
+    } else { // constant volume gain
+        mResampler->setVolume(mVolume[0], mVolume[1]);
+        mResampler->resample((int32_t*)out, outFrameCount, bufferProvider);
+    }
+}
+
+/* This track hook is called to mix a track, when no resampling is required.
+ * The input buffer should be present in in.
+ *
+ * MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+ * TO: int32_t (Q4.27) or float
+ * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+ * TA: int32_t (Q4.27) or float
+ */
+template <int MIXTYPE, typename TO, typename TI, typename TA>
+void AudioMixerBase::TrackBase::track__NoResample(
+        TO* out, size_t frameCount, TO* temp __unused, TA* aux)
+{
+    ALOGVV("track__NoResample\n");
+    const TI *in = static_cast<const TI *>(mIn);
+
+    volumeMix<MIXTYPE, std::is_same_v<TI, float> /* USEFLOATVOL */, true /* ADJUSTVOL */>(
+            out, frameCount, in, aux, needsRamp());
+
+    // MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
+    // MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
+    in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * mMixerChannelCount;
+    mIn = in;
+}
+
+/* The Mixer engine generates either int32_t (Q4_27) or float data.
+ * We use this function to convert the engine buffers
+ * to the desired mixer output format, either int16_t (Q.15) or float.
+ */
+/* static */
+void AudioMixerBase::convertMixerFormat(void *out, audio_format_t mixerOutFormat,
+        void *in, audio_format_t mixerInFormat, size_t sampleCount)
+{
+    switch (mixerInFormat) {
+    case AUDIO_FORMAT_PCM_FLOAT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            memcpy(out, in, sampleCount * sizeof(float)); // MEMCPY. TODO optimize out
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            memcpy_to_i16_from_float((int16_t*)out, (float*)in, sampleCount);
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    case AUDIO_FORMAT_PCM_16_BIT:
+        switch (mixerOutFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            memcpy_to_float_from_q4_27((float*)out, (const int32_t*)in, sampleCount);
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            memcpy_to_i16_from_q4_27((int16_t*)out, (const int32_t*)in, sampleCount);
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+            break;
+        }
+        break;
+    default:
+        LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+        break;
+    }
+}
+
+/* Returns the proper track hook to use for mixing the track into the output buffer.
+ */
+/* static */
+AudioMixerBase::hook_t AudioMixerBase::TrackBase::getTrackHook(int trackType, uint32_t channelCount,
+        audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
+{
+    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
+        switch (trackType) {
+        case TRACKTYPE_NOP:
+            return &TrackBase::track__nop;
+        case TRACKTYPE_RESAMPLE:
+            return &TrackBase::track__genericResample;
+        case TRACKTYPE_NORESAMPLEMONO:
+            return &TrackBase::track__16BitsMono;
+        case TRACKTYPE_NORESAMPLE:
+            return &TrackBase::track__16BitsStereo;
+        default:
+            LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
+            break;
+        }
+    }
+    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
+    switch (trackType) {
+    case TRACKTYPE_NOP:
+        return &TrackBase::track__nop;
+    case TRACKTYPE_RESAMPLE:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_RESAMPLESTEREO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI_STEREOVOL, float /*TO*/, float /*TI*/,
+                    TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_MULTI_STEREOVOL, int32_t /*TO*/, int16_t /*TI*/,
+                    TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    // RESAMPLEMONO needs MIXTYPE_STEREOEXPAND since resampler will upmix mono
+    // track to stereo track
+    case TRACKTYPE_RESAMPLEMONO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_STEREOEXPAND, float /*TO*/, float /*TI*/,
+                    TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__Resample<
+                    MIXTYPE_STEREOEXPAND, int32_t /*TO*/, int16_t /*TI*/,
+                    TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_NORESAMPLEMONO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                            MIXTYPE_MONOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                            MIXTYPE_MONOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_NORESAMPLE:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI, float /*TO*/, float /*TI*/, TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    case TRACKTYPE_NORESAMPLESTEREO:
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI_STEREOVOL, float /*TO*/, float /*TI*/,
+                    TYPE_AUX>;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            return (AudioMixerBase::hook_t) &TrackBase::track__NoResample<
+                    MIXTYPE_MULTI_STEREOVOL, int32_t /*TO*/, int16_t /*TI*/,
+                    TYPE_AUX>;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+        break;
+    default:
+        LOG_ALWAYS_FATAL("bad trackType: %d", trackType);
+        break;
+    }
+    return NULL;
+}
+
+/* Returns the proper process hook for mixing tracks. Currently works only for
+ * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
+ *
+ * TODO: Due to the special mixing considerations of duplicating to
+ * a stereo output track, the input track cannot be MONO.  This should be
+ * prevented by the caller.
+ */
+/* static */
+AudioMixerBase::process_hook_t AudioMixerBase::getProcessHook(
+        int processType, uint32_t channelCount,
+        audio_format_t mixerInFormat, audio_format_t mixerOutFormat,
+        bool stereoVolume)
+{
+    if (processType != PROCESSTYPE_NORESAMPLEONETRACK) { // Only NORESAMPLEONETRACK
+        LOG_ALWAYS_FATAL("bad processType: %d", processType);
+        return NULL;
+    }
+    if (!kUseNewMixer && channelCount == FCC_2 && mixerInFormat == AUDIO_FORMAT_PCM_16_BIT) {
+        return &AudioMixerBase::process__oneTrack16BitsStereoNoResampling;
+    }
+    LOG_ALWAYS_FATAL_IF(channelCount > MAX_NUM_CHANNELS);
+
+    if (stereoVolume) { // templated arguments require explicit values.
+        switch (mixerInFormat) {
+        case AUDIO_FORMAT_PCM_FLOAT:
+            switch (mixerOutFormat) {
+            case AUDIO_FORMAT_PCM_FLOAT:
+                return &AudioMixerBase::process__noResampleOneTrack<
+                        MIXTYPE_MULTI_SAVEONLY_STEREOVOL, float /*TO*/,
+                        float /*TI*/, TYPE_AUX>;
+            case AUDIO_FORMAT_PCM_16_BIT:
+                return &AudioMixerBase::process__noResampleOneTrack<
+                        MIXTYPE_MULTI_SAVEONLY_STEREOVOL, int16_t /*TO*/,
+                        float /*TI*/, TYPE_AUX>;
+            default:
+                LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+                break;
+            }
+            break;
+        case AUDIO_FORMAT_PCM_16_BIT:
+            switch (mixerOutFormat) {
+            case AUDIO_FORMAT_PCM_FLOAT:
+                return &AudioMixerBase::process__noResampleOneTrack<
+                        MIXTYPE_MULTI_SAVEONLY_STEREOVOL, float /*TO*/,
+                        int16_t /*TI*/, TYPE_AUX>;
+            case AUDIO_FORMAT_PCM_16_BIT:
+                return &AudioMixerBase::process__noResampleOneTrack<
+                        MIXTYPE_MULTI_SAVEONLY_STEREOVOL, int16_t /*TO*/,
+                        int16_t /*TI*/, TYPE_AUX>;
+            default:
+                LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+                break;
+            }
+            break;
+        default:
+            LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+            break;
+        }
+    } else {
+          switch (mixerInFormat) {
+          case AUDIO_FORMAT_PCM_FLOAT:
+              switch (mixerOutFormat) {
+              case AUDIO_FORMAT_PCM_FLOAT:
+                  return &AudioMixerBase::process__noResampleOneTrack<
+                          MIXTYPE_MULTI_SAVEONLY, float /*TO*/,
+                          float /*TI*/, TYPE_AUX>;
+              case AUDIO_FORMAT_PCM_16_BIT:
+                  return &AudioMixerBase::process__noResampleOneTrack<
+                          MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/,
+                          float /*TI*/, TYPE_AUX>;
+              default:
+                  LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+                  break;
+              }
+              break;
+          case AUDIO_FORMAT_PCM_16_BIT:
+              switch (mixerOutFormat) {
+              case AUDIO_FORMAT_PCM_FLOAT:
+                  return &AudioMixerBase::process__noResampleOneTrack<
+                          MIXTYPE_MULTI_SAVEONLY, float /*TO*/,
+                          int16_t /*TI*/, TYPE_AUX>;
+              case AUDIO_FORMAT_PCM_16_BIT:
+                  return &AudioMixerBase::process__noResampleOneTrack<
+                          MIXTYPE_MULTI_SAVEONLY, int16_t /*TO*/,
+                          int16_t /*TI*/, TYPE_AUX>;
+              default:
+                  LOG_ALWAYS_FATAL("bad mixerOutFormat: %#x", mixerOutFormat);
+                  break;
+              }
+              break;
+          default:
+              LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
+              break;
+          }
+    }
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+} // namespace android
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index f33e361..80bd093 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -19,21 +19,10 @@
 
 namespace android {
 
-/* Behavior of is_same<>::value is true if the types are identical,
- * false otherwise. Identical to the STL std::is_same.
- */
-template<typename T, typename U>
-struct is_same
-{
-    static const bool value = false;
-};
-
-template<typename T>
-struct is_same<T, T>  // partial specialization
-{
-    static const bool value = true;
-};
-
+// Hack to make static_assert work in a constexpr
+// https://en.cppreference.com/w/cpp/language/if
+template <int N>
+inline constexpr bool dependent_false = false;
 
 /* MixMul is a multiplication operator to scale an audio input signal
  * by a volume gain, with the formula:
@@ -179,7 +168,7 @@
 
 template <typename TO, typename TI>
 inline void MixAccum(TO *auxaccum, TI value) {
-    if (!is_same<TO, TI>::value) {
+    if (!std::is_same_v<TO, TI>) {
         LOG_ALWAYS_FATAL("MixAccum type not properly specialized: %zu %zu\n",
                 sizeof(TO), sizeof(TI));
     }
@@ -228,9 +217,80 @@
     MIXTYPE_MULTI_SAVEONLY,
     MIXTYPE_MULTI_MONOVOL,
     MIXTYPE_MULTI_SAVEONLY_MONOVOL,
+    MIXTYPE_MULTI_STEREOVOL,
+    MIXTYPE_MULTI_SAVEONLY_STEREOVOL,
+    MIXTYPE_STEREOEXPAND,
 };
 
 /*
+ * TODO: We should work on non-interleaved streams - the
+ * complexity of working on interleaved streams is now getting
+ * too high, and likely limits compiler optimization.
+ */
+template <int MIXTYPE, int NCHAN,
+        typename TO, typename TI, typename TV,
+        typename F>
+void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
+    static_assert(NCHAN > 0 && NCHAN <= 8);
+    static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+            || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+            || MIXTYPE == MIXTYPE_STEREOEXPAND);
+    auto proc = [](auto& a, const auto& b) {
+        if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+                || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+            a += b;
+        } else {
+            a = b;
+        }
+    };
+    auto inp = [&in]() -> const TI& {
+        if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) {
+            return *in;
+        } else {
+            return *in++;
+        }
+    };
+
+    // HALs should only expose the canonical channel masks.
+    proc(*out++, f(inp(), vol[0])); // front left
+    if constexpr (NCHAN == 1) return;
+    proc(*out++, f(inp(), vol[1])); // front right
+    if constexpr (NCHAN == 2)  return;
+    if constexpr (NCHAN == 4) {
+        proc(*out++, f(inp(), vol[0])); // back left
+        proc(*out++, f(inp(), vol[1])); // back right
+        return;
+    }
+
+    // TODO: Precompute center volume if not ramping.
+    std::decay_t<TV> center;
+    if constexpr (std::is_floating_point_v<TV>) {
+        center = (vol[0] + vol[1]) * 0.5;       // do not use divide
+    } else {
+        center = (vol[0] >> 1) + (vol[1] >> 1); // rounds to 0.
+    }
+    proc(*out++, f(inp(), center)); // center (or 2.1 LFE)
+    if constexpr (NCHAN == 3) return;
+    if constexpr (NCHAN == 5) {
+        proc(*out++, f(inp(), vol[0]));  // back left
+        proc(*out++, f(inp(), vol[1]));  // back right
+        return;
+    }
+
+    proc(*out++, f(inp(), center)); // lfe
+    proc(*out++, f(inp(), vol[0])); // back left
+    proc(*out++, f(inp(), vol[1])); // back right
+    if constexpr (NCHAN == 6) return;
+    if constexpr (NCHAN == 7) {
+        proc(*out++, f(inp(), center)); // back center
+        return;
+    }
+    // NCHAN == 8
+    proc(*out++, f(inp(), vol[0])); // side left
+    proc(*out++, f(inp(), vol[1])); // side right
+}
+
+/*
  * The volumeRampMulti and volumeRamp functions take a MIXTYPE
  * which indicates the per-frame mixing and accumulation strategy.
  *
@@ -271,6 +331,17 @@
  * MIXTYPE_MULTI_SAVEONLY_MONOVOL:
  *   Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0].
  *
+ * MIXTYPE_MULTI_STEREOVOL:
+ *   Same as MIXTYPE_MULTI, but uses only volume[0] and volume[1].
+ *
+ * MIXTYPE_MULTI_SAVEONLY_STEREOVOL:
+ *   Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0] and volume[1].
+ *
+ * MIXTYPE_STEREOEXPAND:
+ *   Stereo input channel. NCHAN represents number of output channels.
+ *   Expand size 2 array "in" and "vol" to multi-channel output. Note
+ *   that the 2 array is assumed to have replicated L+R.
+ *
  */
 
 template <int MIXTYPE, int NCHAN,
@@ -284,41 +355,44 @@
     if (aux != NULL) {
         do {
             TA auxaccum = 0;
-            switch (MIXTYPE) {
-            case MIXTYPE_MULTI:
+            if constexpr (MIXTYPE == MIXTYPE_MULTI) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                     vol[i] += volinc[i];
                 }
-                break;
-            case MIXTYPE_MONOEXPAND:
+            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                     vol[i] += volinc[i];
                 }
                 in++;
-                break;
-            case MIXTYPE_MULTI_SAVEONLY:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                     vol[i] += volinc[i];
                 }
-                break;
-            case MIXTYPE_MULTI_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                 }
                 vol[0] += volinc[0];
-                break;
-            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                 }
                 vol[0] += volinc[0];
-                break;
-            default:
-                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
-                break;
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+                stereoVolumeHelper<MIXTYPE, NCHAN>(
+                        out, in, vol, [&auxaccum] (auto &a, const auto &b) {
+                    return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
+                });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
+                vol[0] += volinc[0];
+                vol[1] += volinc[1];
+            } else /* constexpr */ {
+                static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }
             auxaccum /= NCHAN;
             *aux++ += MixMul<TA, TA, TAV>(auxaccum, *vola);
@@ -326,41 +400,43 @@
         } while (--frameCount);
     } else {
         do {
-            switch (MIXTYPE) {
-            case MIXTYPE_MULTI:
+            if constexpr (MIXTYPE == MIXTYPE_MULTI) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
                     vol[i] += volinc[i];
                 }
-                break;
-            case MIXTYPE_MONOEXPAND:
+            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                     vol[i] += volinc[i];
                 }
                 in++;
-                break;
-            case MIXTYPE_MULTI_SAVEONLY:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                     vol[i] += volinc[i];
                 }
-                break;
-            case MIXTYPE_MULTI_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
                 }
                 vol[0] += volinc[0];
-                break;
-            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
                 }
                 vol[0] += volinc[0];
-                break;
-            default:
-                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
-                break;
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+                stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
+                    return MixMul<TO, TI, TV>(a, b);
+                });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
+                vol[0] += volinc[0];
+                vol[1] += volinc[1];
+            } else /* constexpr */ {
+                static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }
         } while (--frameCount);
     }
@@ -377,72 +453,73 @@
     if (aux != NULL) {
         do {
             TA auxaccum = 0;
-            switch (MIXTYPE) {
-            case MIXTYPE_MULTI:
+            if constexpr (MIXTYPE == MIXTYPE_MULTI) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                 }
-                break;
-            case MIXTYPE_MONOEXPAND:
+            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                 }
                 in++;
-                break;
-            case MIXTYPE_MULTI_SAVEONLY:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                 }
-                break;
-            case MIXTYPE_MULTI_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                 }
-                break;
-            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                 }
-                break;
-            default:
-                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
-                break;
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+                stereoVolumeHelper<MIXTYPE, NCHAN>(
+                        out, in, vol, [&auxaccum] (auto &a, const auto &b) {
+                    return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
+                });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
+            } else /* constexpr */ {
+                static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }
             auxaccum /= NCHAN;
             *aux++ += MixMul<TA, TA, TAV>(auxaccum, vola);
         } while (--frameCount);
     } else {
         do {
-            switch (MIXTYPE) {
-            case MIXTYPE_MULTI:
+            if constexpr (MIXTYPE == MIXTYPE_MULTI) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
                 }
-                break;
-            case MIXTYPE_MONOEXPAND:
+            } else if constexpr (MIXTYPE == MIXTYPE_MONOEXPAND) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                 }
                 in++;
-                break;
-            case MIXTYPE_MULTI_SAVEONLY:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                 }
-                break;
-            case MIXTYPE_MULTI_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
                 }
-                break;
-            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_SAVEONLY_MONOVOL) {
                 for (int i = 0; i < NCHAN; ++i) {
                     *out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
                 }
-                break;
-            default:
-                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
-                break;
+            } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
+                    || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
+                    || MIXTYPE == MIXTYPE_STEREOEXPAND) {
+                stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
+                    return MixMul<TO, TI, TV>(a, b);
+                });
+                if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
+            } else /* constexpr */ {
+                static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
             }
         } while (--frameCount);
     }
diff --git a/media/libaudioprocessing/AudioResamplerFirOps.h b/media/libaudioprocessing/AudioResamplerFirOps.h
index 2e4cee3..a3f5ff5 100644
--- a/media/libaudioprocessing/AudioResamplerFirOps.h
+++ b/media/libaudioprocessing/AudioResamplerFirOps.h
@@ -36,13 +36,20 @@
 #include <arm_neon.h>
 #endif
 
-#if defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#if defined(__AVX2__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_AVX2 (true)  // Inference AVX2/FMA Intrinsics
 #define USE_SSE (true)
+#include <immintrin.h>
+#elif defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_SSE (true)  // Inference SSE Intrinsics
+#define USE_AVX2 (false)
 #include <tmmintrin.h>
 #else
 #define USE_SSE (false)
+#define USE_AVX2(false)
 #endif
 
+
 template<typename T, typename U>
 struct is_same
 {
diff --git a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
index 30233b5..1c16bc4 100644
--- a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
+++ b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
@@ -80,11 +80,16 @@
             posCoef1 = _mm_sub_ps(posCoef1, posCoef);
             negCoef = _mm_sub_ps(negCoef, negCoef1);
 
+
+            #if USE_AVX2
+            posCoef = _mm_fmadd_ps(posCoef1, interp, posCoef);
+            negCoef = _mm_fmadd_ps(negCoef, interp, negCoef1);
+            #else
             posCoef1 = _mm_mul_ps(posCoef1, interp);
             negCoef = _mm_mul_ps(negCoef, interp);
-
             posCoef = _mm_add_ps(posCoef1, posCoef);
             negCoef = _mm_add_ps(negCoef, negCoef1);
+            #endif //USE_AVX2
         }
         switch (CHANNELS) {
         case 1: {
@@ -94,11 +99,17 @@
             sN += 4;
 
             posSamp = _mm_shuffle_ps(posSamp, posSamp, 0x1B);
+
+            #if USE_AVX2
+            accL = _mm_fmadd_ps(posSamp, posCoef, accL);
+            accL = _mm_fmadd_ps(negSamp, negCoef, accL);
+            #else
             posSamp = _mm_mul_ps(posSamp, posCoef);
             negSamp = _mm_mul_ps(negSamp, negCoef);
-
             accL = _mm_add_ps(accL, posSamp);
             accL = _mm_add_ps(accL, negSamp);
+            #endif
+
         } break;
         case 2: {
             __m128 posSamp0 = _mm_loadu_ps(sP);
@@ -114,15 +125,23 @@
             __m128 negSampL = _mm_shuffle_ps(negSamp0, negSamp1, 0x88);
             __m128 negSampR = _mm_shuffle_ps(negSamp0, negSamp1, 0xDD);
 
-            posSampL = _mm_mul_ps(posSampL, posCoef);
-            posSampR = _mm_mul_ps(posSampR, posCoef);
-            negSampL = _mm_mul_ps(negSampL, negCoef);
-            negSampR = _mm_mul_ps(negSampR, negCoef);
+           #if USE_AVX2
+           accL = _mm_fmadd_ps(posSampL, posCoef, accL);
+           accR = _mm_fmadd_ps(posSampR, posCoef, accR);
+           accL = _mm_fmadd_ps(negSampL, negCoef, accL);
+           accR = _mm_fmadd_ps(negSampR, negCoef, accR);
+           #else
+           posSampL = _mm_mul_ps(posSampL, posCoef);
+           posSampR = _mm_mul_ps(posSampR, posCoef);
+           negSampL = _mm_mul_ps(negSampL, negCoef);
+           negSampR = _mm_mul_ps(negSampR, negCoef);
 
-            accL = _mm_add_ps(accL, posSampL);
-            accR = _mm_add_ps(accR, posSampR);
-            accL = _mm_add_ps(accL, negSampL);
-            accR = _mm_add_ps(accR, negSampR);
+           accL = _mm_add_ps(accL, posSampL);
+           accR = _mm_add_ps(accR, posSampR);
+           accL = _mm_add_ps(accL, negSampL);
+           accR = _mm_add_ps(accR, negSampR);
+           #endif
+
         } break;
         }
     } while (count -= 4);
@@ -144,9 +163,13 @@
         outAccum = _mm_hadd_ps(accL, accR);
         outAccum = _mm_hadd_ps(outAccum, outAccum);
     }
-
+    #if USE_AVX2
+    outSamp = _mm_fmadd_ps(outAccum, vLR,outSamp);
+    #else
     outAccum = _mm_mul_ps(outAccum, vLR);
     outSamp = _mm_add_ps(outSamp, outAccum);
+    #endif
+
     _mm_storel_pi(reinterpret_cast<__m64*>(out), outSamp);
 }
 
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 21d25e1..6d31c12 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -164,6 +164,7 @@
     if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
                                       sessionId,
                                       SESSION_ID_INVALID_AND_IGNORED,
+                                      AUDIO_PORT_HANDLE_NONE,
                                       &mDownmixInterface) != 0) {
          ALOGE("DownmixerBufferProvider() error creating downmixer effect");
          mDownmixInterface.clear();
diff --git a/media/libaudioprocessing/include/media/AudioMixer.h b/media/libaudioprocessing/include/media/AudioMixer.h
new file mode 100644
index 0000000..3f7cd48
--- /dev/null
+++ b/media/libaudioprocessing/include/media/AudioMixer.h
@@ -0,0 +1,238 @@
+/*
+**
+** Copyright 2007, 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 ANDROID_AUDIO_MIXER_H
+#define ANDROID_AUDIO_MIXER_H
+
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <android/os/IExternalVibratorService.h>
+#include <media/AudioMixerBase.h>
+#include <media/BufferProviders.h>
+#include <utils/threads.h>
+
+// FIXME This is actually unity gain, which might not be max in future, expressed in U.12
+#define MAX_GAIN_INT AudioMixerBase::UNITY_GAIN_INT
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// AudioMixer extends AudioMixerBase by adding support for down- and up-mixing
+// and time stretch that are implemented via Effects HAL, and adding support
+// for haptic channels which depends on Vibrator service. This is the version
+// that is used by Audioflinger.
+
+class AudioMixer : public AudioMixerBase
+{
+public:
+    // maximum number of channels supported for the content
+    static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;
+
+    enum { // extension of AudioMixerBase parameters
+        DOWNMIX_TYPE    = 0x4004,
+        // for haptic
+        HAPTIC_ENABLED  = 0x4007, // Set haptic data from this track should be played or not.
+        HAPTIC_INTENSITY = 0x4008, // Set the intensity to play haptic data.
+        // for target TIMESTRETCH
+        PLAYBACK_RATE   = 0x4300, // Configure timestretch on this track name;
+                                  // parameter 'value' is a pointer to the new playback rate.
+    };
+
+    typedef enum { // Haptic intensity, should keep consistent with VibratorService
+        HAPTIC_SCALE_MUTE = os::IExternalVibratorService::SCALE_MUTE,
+        HAPTIC_SCALE_VERY_LOW = os::IExternalVibratorService::SCALE_VERY_LOW,
+        HAPTIC_SCALE_LOW = os::IExternalVibratorService::SCALE_LOW,
+        HAPTIC_SCALE_NONE = os::IExternalVibratorService::SCALE_NONE,
+        HAPTIC_SCALE_HIGH = os::IExternalVibratorService::SCALE_HIGH,
+        HAPTIC_SCALE_VERY_HIGH = os::IExternalVibratorService::SCALE_VERY_HIGH,
+    } haptic_intensity_t;
+    static constexpr float HAPTIC_SCALE_VERY_LOW_RATIO = 2.0f / 3.0f;
+    static constexpr float HAPTIC_SCALE_LOW_RATIO = 3.0f / 4.0f;
+    static const constexpr float HAPTIC_MAX_AMPLITUDE_FLOAT = 1.0f;
+
+    static inline bool isValidHapticIntensity(haptic_intensity_t hapticIntensity) {
+        switch (hapticIntensity) {
+        case HAPTIC_SCALE_MUTE:
+        case HAPTIC_SCALE_VERY_LOW:
+        case HAPTIC_SCALE_LOW:
+        case HAPTIC_SCALE_NONE:
+        case HAPTIC_SCALE_HIGH:
+        case HAPTIC_SCALE_VERY_HIGH:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    AudioMixer(size_t frameCount, uint32_t sampleRate)
+            : AudioMixerBase(frameCount, sampleRate) {
+        pthread_once(&sOnceControl, &sInitRoutine);
+    }
+
+    bool isValidChannelMask(audio_channel_mask_t channelMask) const override;
+
+    void setParameter(int name, int target, int param, void *value) override;
+    void setBufferProvider(int name, AudioBufferProvider* bufferProvider);
+
+private:
+
+    struct Track : public TrackBase {
+        Track() : TrackBase() {}
+
+        ~Track()
+        {
+            // mInputBufferProvider need not be deleted.
+            // Ensure the order of destruction of buffer providers as they
+            // release the upstream provider in the destructor.
+            mTimestretchBufferProvider.reset(nullptr);
+            mPostDownmixReformatBufferProvider.reset(nullptr);
+            mDownmixerBufferProvider.reset(nullptr);
+            mReformatBufferProvider.reset(nullptr);
+            mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
+            mAdjustChannelsBufferProvider.reset(nullptr);
+        }
+
+        uint32_t getOutputChannelCount() override {
+            return mDownmixerBufferProvider.get() != nullptr ? mMixerChannelCount : channelCount;
+        }
+        uint32_t getMixerChannelCount() override {
+            return mMixerChannelCount + mMixerHapticChannelCount;
+        }
+
+        status_t    prepareForDownmix();
+        void        unprepareForDownmix();
+        status_t    prepareForReformat();
+        void        unprepareForReformat();
+        status_t    prepareForAdjustChannels();
+        void        unprepareForAdjustChannels();
+        status_t    prepareForAdjustChannelsNonDestructive(size_t frames);
+        void        unprepareForAdjustChannelsNonDestructive();
+        void        clearContractedBuffer();
+        bool        setPlaybackRate(const AudioPlaybackRate &playbackRate);
+        void        reconfigureBufferProviders();
+
+        /* Buffer providers are constructed to translate the track input data as needed.
+         * See DownmixerBufferProvider below for how the Track buffer provider
+         * is wrapped by another one when dowmixing is required.
+         *
+         * TODO: perhaps make a single PlaybackConverterProvider class to move
+         * all pre-mixer track buffer conversions outside the AudioMixer class.
+         *
+         * 1) mInputBufferProvider: The AudioTrack buffer provider.
+         * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
+         *    channel format to another. Expanded channels are filled with zeros and put at the end
+         *    of each audio frame. Contracted channels are copied to the end of the buffer.
+         * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
+         *    This is currently using at audio-haptic coupled playback to separate audio and haptic
+         *    data. Contracted channels could be written to given buffer.
+         * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
+         *    match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
+         *    requires reformat. For example, it may convert floating point input to
+         *    PCM_16_bit if that's required by the downmixer.
+         * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
+         *    the number of channels required by the mixer sink.
+         * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
+         *    the downmixer requirements to the mixer engine input requirements.
+         * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
+         */
+        AudioBufferProvider* mInputBufferProvider;    // externally provided buffer provider.
+        // TODO: combine mAdjustChannelsBufferProvider and
+        // mContractChannelsNonDestructiveBufferProvider
+        std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
+        std::unique_ptr<PassthruBufferProvider> mTimestretchBufferProvider;
+
+        audio_format_t mDownmixRequiresFormat;  // required downmixer format
+                                                // AUDIO_FORMAT_PCM_16_BIT if 16 bit necessary
+                                                // AUDIO_FORMAT_INVALID if no required format
+
+        AudioPlaybackRate    mPlaybackRate;
+
+        // Haptic
+        bool                 mHapticPlaybackEnabled;
+        haptic_intensity_t   mHapticIntensity;
+        audio_channel_mask_t mHapticChannelMask;
+        uint32_t             mHapticChannelCount;
+        audio_channel_mask_t mMixerHapticChannelMask;
+        uint32_t             mMixerHapticChannelCount;
+        uint32_t             mAdjustInChannelCount;
+        uint32_t             mAdjustOutChannelCount;
+        uint32_t             mAdjustNonDestructiveInChannelCount;
+        uint32_t             mAdjustNonDestructiveOutChannelCount;
+        bool                 mKeepContractedChannels;
+
+        float getHapticScaleGamma() const {
+        // Need to keep consistent with the value in VibratorService.
+        switch (mHapticIntensity) {
+        case HAPTIC_SCALE_VERY_LOW:
+            return 2.0f;
+        case HAPTIC_SCALE_LOW:
+            return 1.5f;
+        case HAPTIC_SCALE_HIGH:
+            return 0.5f;
+        case HAPTIC_SCALE_VERY_HIGH:
+            return 0.25f;
+        default:
+            return 1.0f;
+        }
+        }
+
+        float getHapticMaxAmplitudeRatio() const {
+        // Need to keep consistent with the value in VibratorService.
+        switch (mHapticIntensity) {
+        case HAPTIC_SCALE_VERY_LOW:
+            return HAPTIC_SCALE_VERY_LOW_RATIO;
+        case HAPTIC_SCALE_LOW:
+            return HAPTIC_SCALE_LOW_RATIO;
+        case HAPTIC_SCALE_NONE:
+        case HAPTIC_SCALE_HIGH:
+        case HAPTIC_SCALE_VERY_HIGH:
+            return 1.0f;
+        default:
+            return 0.0f;
+        }
+        }
+    };
+
+    inline std::shared_ptr<Track> getTrack(int name) {
+        return std::static_pointer_cast<Track>(mTracks[name]);
+    }
+
+    std::shared_ptr<TrackBase> preCreateTrack() override;
+    status_t postCreateTrack(TrackBase *track) override;
+
+    void preProcess() override;
+    void postProcess() override;
+
+    bool setChannelMasks(int name,
+            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask) override;
+
+    static void sInitRoutine();
+
+    static pthread_once_t sOnceControl; // initialized in constructor by first new
+};
+
+// ----------------------------------------------------------------------------
+} // namespace android
+
+#endif // ANDROID_AUDIO_MIXER_H
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
new file mode 100644
index 0000000..cf84b83
--- /dev/null
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -0,0 +1,371 @@
+/*
+**
+** Copyright 2019, 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 ANDROID_AUDIO_MIXER_BASE_H
+#define ANDROID_AUDIO_MIXER_BASE_H
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <media/AudioBufferProvider.h>
+#include <media/AudioResampler.h>
+#include <media/AudioResamplerPublic.h>
+#include <system/audio.h>
+#include <utils/Compat.h>
+
+// This must match frameworks/av/services/audioflinger/Configuration.h
+// when used with the Audio Framework.
+#define FLOAT_AUX
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// AudioMixerBase is functional on its own if only mixing and resampling
+// is needed.
+
+class AudioMixerBase
+{
+public:
+    // Do not change these unless underlying code changes.
+    // This mixer has a hard-coded upper limit of 8 channels for output.
+    static constexpr uint32_t MAX_NUM_CHANNELS = FCC_8;
+    static constexpr uint32_t MAX_NUM_VOLUMES = FCC_2; // stereo volume only
+
+    static const uint16_t UNITY_GAIN_INT = 0x1000;
+    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
+
+    enum { // names
+        // setParameter targets
+        TRACK           = 0x3000,
+        RESAMPLE        = 0x3001,
+        RAMP_VOLUME     = 0x3002, // ramp to new volume
+        VOLUME          = 0x3003, // don't ramp
+        TIMESTRETCH     = 0x3004,
+
+        // set Parameter names
+        // for target TRACK
+        CHANNEL_MASK    = 0x4000,
+        FORMAT          = 0x4001,
+        MAIN_BUFFER     = 0x4002,
+        AUX_BUFFER      = 0x4003,
+        // 0x4004 reserved
+        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
+        // for target RESAMPLE
+        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
+                                  // parameter 'value' is the new sample rate in Hz.
+                                  // Only creates a sample rate converter the first time that
+                                  // the track sample rate is different from the mix sample rate.
+                                  // If the new sample rate is the same as the mix sample rate,
+                                  // and a sample rate converter already exists,
+                                  // then the sample rate converter remains present but is a no-op.
+        RESET           = 0x4101, // Reset sample rate converter without changing sample rate.
+                                  // This clears out the resampler's input buffer.
+        REMOVE          = 0x4102, // Remove the sample rate converter on this track name;
+                                  // the track is restored to the mix sample rate.
+        // for target RAMP_VOLUME and VOLUME (8 channels max)
+        // FIXME use float for these 3 to improve the dynamic range
+        VOLUME0         = 0x4200,
+        VOLUME1         = 0x4201,
+        AUXLEVEL        = 0x4210,
+    };
+
+    AudioMixerBase(size_t frameCount, uint32_t sampleRate)
+        : mSampleRate(sampleRate)
+        , mFrameCount(frameCount) {
+    }
+
+    virtual ~AudioMixerBase() {}
+
+    virtual bool isValidFormat(audio_format_t format) const;
+    virtual bool isValidChannelMask(audio_channel_mask_t channelMask) const;
+
+    // Create a new track in the mixer.
+    //
+    // \param name        a unique user-provided integer associated with the track.
+    //                    If name already exists, the function will abort.
+    // \param channelMask output channel mask.
+    // \param format      PCM format
+    // \param sessionId   Session id for the track. Tracks with the same
+    //                    session id will be submixed together.
+    //
+    // \return OK        on success.
+    //         BAD_VALUE if the format does not satisfy isValidFormat()
+    //                   or the channelMask does not satisfy isValidChannelMask().
+    status_t    create(
+            int name, audio_channel_mask_t channelMask, audio_format_t format, int sessionId);
+
+    bool        exists(int name) const {
+        return mTracks.count(name) > 0;
+    }
+
+    // Free an allocated track by name.
+    void        destroy(int name);
+
+    // Enable or disable an allocated track by name
+    void        enable(int name);
+    void        disable(int name);
+
+    virtual void setParameter(int name, int target, int param, void *value);
+
+    void        process() {
+        preProcess();
+        (this->*mHook)();
+        postProcess();
+    }
+
+    size_t      getUnreleasedFrames(int name) const;
+
+    std::string trackNames() const;
+
+  protected:
+    // Set kUseNewMixer to true to use the new mixer engine always. Otherwise the
+    // original code will be used for stereo sinks, the new mixer for everything else.
+    static constexpr bool kUseNewMixer = true;
+
+    // Set kUseFloat to true to allow floating input into the mixer engine.
+    // If kUseNewMixer is false, this is ignored or may be overridden internally
+    static constexpr bool kUseFloat = true;
+
+#ifdef FLOAT_AUX
+    using TYPE_AUX = float;
+    static_assert(kUseNewMixer && kUseFloat,
+            "kUseNewMixer and kUseFloat must be true for FLOAT_AUX option");
+#else
+    using TYPE_AUX = int32_t; // q4.27
+#endif
+
+    /* For multi-format functions (calls template functions
+     * in AudioMixerOps.h).  The template parameters are as follows:
+     *
+     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
+     *   USEFLOATVOL (set to true if float volume is used)
+     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
+     *   TO: int32_t (Q4.27) or float
+     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
+     *   TA: int32_t (Q4.27)
+     */
+
+    enum {
+        // FIXME this representation permits up to 8 channels
+        NEEDS_CHANNEL_COUNT__MASK   = 0x00000007,
+    };
+
+    enum {
+        NEEDS_CHANNEL_1             = 0x00000000,   // mono
+        NEEDS_CHANNEL_2             = 0x00000001,   // stereo
+
+        // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT
+
+        NEEDS_MUTE                  = 0x00000100,
+        NEEDS_RESAMPLE              = 0x00001000,
+        NEEDS_AUX                   = 0x00010000,
+    };
+
+    // hook types
+    enum {
+        PROCESSTYPE_NORESAMPLEONETRACK, // others set elsewhere
+    };
+
+    enum {
+        TRACKTYPE_NOP,
+        TRACKTYPE_RESAMPLE,
+        TRACKTYPE_RESAMPLEMONO,
+        TRACKTYPE_RESAMPLESTEREO,
+        TRACKTYPE_NORESAMPLE,
+        TRACKTYPE_NORESAMPLEMONO,
+        TRACKTYPE_NORESAMPLESTEREO,
+    };
+
+    // process hook functionality
+    using process_hook_t = void(AudioMixerBase::*)();
+
+    static bool isAudioChannelPositionMask(audio_channel_mask_t channelMask) {
+        return audio_channel_mask_get_representation(channelMask)
+                == AUDIO_CHANNEL_REPRESENTATION_POSITION;
+    }
+
+    struct TrackBase;
+    using hook_t = void(TrackBase::*)(
+            int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
+
+    struct TrackBase {
+        TrackBase()
+            : bufferProvider(nullptr)
+        {
+            // TODO: move additional initialization here.
+        }
+        virtual ~TrackBase() {}
+
+        virtual uint32_t getOutputChannelCount() { return channelCount; }
+        virtual uint32_t getMixerChannelCount() { return mMixerChannelCount; }
+
+        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
+        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
+        bool        doesResample() const { return mResampler.get() != nullptr; }
+        void        recreateResampler(uint32_t devSampleRate);
+        void        resetResampler() { if (mResampler.get() != nullptr) mResampler->reset(); }
+        void        adjustVolumeRamp(bool aux, bool useFloat = false);
+        size_t      getUnreleasedFrames() const { return mResampler.get() != nullptr ?
+                                                    mResampler->getUnreleasedFrames() : 0; };
+
+        bool        useStereoVolume() const { return channelMask == AUDIO_CHANNEL_OUT_STEREO
+                                        && isAudioChannelPositionMask(mMixerChannelMask); }
+
+        static hook_t getTrackHook(int trackType, uint32_t channelCount,
+                audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
+
+        void track__nop(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+
+        template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
+            typename TO, typename TI, typename TA>
+        void volumeMix(TO *out, size_t outFrames, const TI *in, TA *aux, bool ramp);
+
+        uint32_t    needs;
+
+        // TODO: Eventually remove legacy integer volume settings
+        union {
+        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
+        int32_t     volumeRL;
+        };
+
+        int32_t     prevVolume[MAX_NUM_VOLUMES];
+        int32_t     volumeInc[MAX_NUM_VOLUMES];
+        int32_t     auxInc;
+        int32_t     prevAuxLevel;
+        int16_t     auxLevel;       // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
+
+        uint16_t    frameCount;
+
+        uint8_t     channelCount;   // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
+        uint8_t     unused_padding; // formerly format, was always 16
+        uint16_t    enabled;        // actually bool
+        audio_channel_mask_t channelMask;
+
+        // actual buffer provider used by the track hooks
+        AudioBufferProvider*                bufferProvider;
+
+        mutable AudioBufferProvider::Buffer buffer; // 8 bytes
+
+        hook_t      hook;
+        const void  *mIn;             // current location in buffer
+
+        std::unique_ptr<AudioResampler> mResampler;
+        uint32_t    sampleRate;
+        int32_t*    mainBuffer;
+        int32_t*    auxBuffer;
+
+        int32_t     sessionId;
+
+        audio_format_t mMixerFormat;     // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+        audio_format_t mFormat;          // input track format
+        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
+                                         // each track must be converted to this format.
+
+        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
+        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
+        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment
+
+        float          mAuxLevel;                     // floating point set aux level
+        float          mPrevAuxLevel;                 // floating point prev aux level
+        float          mAuxInc;                       // floating point aux increment
+
+        audio_channel_mask_t mMixerChannelMask;
+        uint32_t             mMixerChannelCount;
+
+      protected:
+
+        // hooks
+        void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+        void track__16BitsStereo(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+        void track__16BitsMono(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+
+        void volumeRampStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+        void volumeStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+
+        // multi-format track hooks
+        template <int MIXTYPE, typename TO, typename TI, typename TA>
+        void track__Resample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
+        template <int MIXTYPE, typename TO, typename TI, typename TA>
+        void track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
+    };
+
+    // preCreateTrack must create an instance of a proper TrackBase descendant.
+    // postCreateTrack is called after filling out fields of TrackBase. It can
+    // abort track creation by returning non-OK status. See the implementation
+    // of create() for details.
+    virtual std::shared_ptr<TrackBase> preCreateTrack();
+    virtual status_t postCreateTrack(TrackBase *track __unused) { return OK; }
+
+    // preProcess is called before the process hook, postProcess after,
+    // see the implementation of process() method.
+    virtual void preProcess() {}
+    virtual void postProcess() {}
+
+    virtual bool setChannelMasks(int name,
+            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);
+
+    // Called when track info changes and a new process hook should be determined.
+    void invalidate() {
+        mHook = &AudioMixerBase::process__validate;
+    }
+
+    void process__validate();
+    void process__nop();
+    void process__genericNoResampling();
+    void process__genericResampling();
+    void process__oneTrack16BitsStereoNoResampling();
+
+    template <int MIXTYPE, typename TO, typename TI, typename TA>
+    void process__noResampleOneTrack();
+
+    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
+            audio_format_t mixerInFormat, audio_format_t mixerOutFormat,
+            bool useStereoVolume);
+
+    static void convertMixerFormat(void *out, audio_format_t mixerOutFormat,
+            void *in, audio_format_t mixerInFormat, size_t sampleCount);
+
+    // initialization constants
+    const uint32_t mSampleRate;
+    const size_t mFrameCount;
+
+    process_hook_t mHook = &AudioMixerBase::process__nop;   // one of process__*, never nullptr
+
+    // the size of the type (int32_t) should be the largest of all types supported
+    // by the mixer.
+    std::unique_ptr<int32_t[]> mOutputTemp;
+    std::unique_ptr<int32_t[]> mResampleTemp;
+
+    // track names grouped by main buffer, in no particular order of main buffer.
+    // however names for a particular main buffer are in order (by construction).
+    std::unordered_map<void * /* mainBuffer */, std::vector<int /* name */>> mGroups;
+
+    // track names that are enabled, in increasing order (by construction).
+    std::vector<int /* name */> mEnabled;
+
+    // track smart pointers, by name, in increasing order of name.
+    std::map<int /* name */, std::shared_ptr<TrackBase>> mTracks;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_AUDIO_MIXER_BASE_H
diff --git a/media/libaudioprocessing/include/media/AudioResamplerPublic.h b/media/libaudioprocessing/include/media/AudioResamplerPublic.h
index 50ca33d..1b39067 100644
--- a/media/libaudioprocessing/include/media/AudioResamplerPublic.h
+++ b/media/libaudioprocessing/include/media/AudioResamplerPublic.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <math.h>
+#include <system/audio.h>
 
 namespace android {
 
@@ -37,68 +38,16 @@
 // an int32_t of the phase increments, making the resulting sample rate inexact.
 #define AUDIO_RESAMPLER_UP_RATIO_MAX 65536
 
-// AUDIO_TIMESTRETCH_SPEED_MIN and AUDIO_TIMESTRETCH_SPEED_MAX define the min and max time stretch
-// speeds supported by the system. These are enforced by the system and values outside this range
-// will result in a runtime error.
-// Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than
-// the ones specified here
-// AUDIO_TIMESTRETCH_SPEED_MIN_DELTA is the minimum absolute speed difference that might trigger a
-// parameter update
-#define AUDIO_TIMESTRETCH_SPEED_MIN    0.01f
-#define AUDIO_TIMESTRETCH_SPEED_MAX    20.0f
-#define AUDIO_TIMESTRETCH_SPEED_NORMAL 1.0f
-#define AUDIO_TIMESTRETCH_SPEED_MIN_DELTA 0.0001f
-
-// AUDIO_TIMESTRETCH_PITCH_MIN and AUDIO_TIMESTRETCH_PITCH_MAX define the min and max time stretch
-// pitch shifting supported by the system. These are not enforced by the system and values
-// outside this range might result in a pitch different than the one requested.
-// Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than
-// the ones specified here.
-// AUDIO_TIMESTRETCH_PITCH_MIN_DELTA is the minimum absolute pitch difference that might trigger a
-// parameter update
-#define AUDIO_TIMESTRETCH_PITCH_MIN    0.25f
-#define AUDIO_TIMESTRETCH_PITCH_MAX    4.0f
-#define AUDIO_TIMESTRETCH_PITCH_NORMAL 1.0f
-#define AUDIO_TIMESTRETCH_PITCH_MIN_DELTA 0.0001f
-
-
 //Determines the current algorithm used for stretching
-enum AudioTimestretchStretchMode : int32_t {
-    AUDIO_TIMESTRETCH_STRETCH_DEFAULT            = 0,
-    AUDIO_TIMESTRETCH_STRETCH_SPEECH             = 1,
-    //TODO: add more stretch modes/algorithms
-};
-
-//Limits for AUDIO_TIMESTRETCH_STRETCH_SPEECH mode
-#define TIMESTRETCH_SONIC_SPEED_MIN 0.1f
-#define TIMESTRETCH_SONIC_SPEED_MAX 6.0f
+using AudioTimestretchStretchMode = ::audio_timestretch_stretch_mode_t;
 
 //Determines behavior of Timestretch if current algorithm can't perform
 //with current parameters.
-// FALLBACK_CUT_REPEAT: (internal only) for speed <1.0 will truncate frames
-//    for speed > 1.0 will repeat frames
-// FALLBACK_MUTE: will set all processed frames to zero
-// FALLBACK_FAIL:  will stop program execution and log a fatal error
-enum AudioTimestretchFallbackMode : int32_t {
-    AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT     = -1,
-    AUDIO_TIMESTRETCH_FALLBACK_DEFAULT        = 0,
-    AUDIO_TIMESTRETCH_FALLBACK_MUTE           = 1,
-    AUDIO_TIMESTRETCH_FALLBACK_FAIL           = 2,
-};
+using AudioTimestretchFallbackMode = ::audio_timestretch_fallback_mode_t;
 
-struct AudioPlaybackRate {
-    float mSpeed;
-    float mPitch;
-    enum AudioTimestretchStretchMode  mStretchMode;
-    enum AudioTimestretchFallbackMode mFallbackMode;
-};
+using AudioPlaybackRate = ::audio_playback_rate_t;
 
-static const AudioPlaybackRate AUDIO_PLAYBACK_RATE_DEFAULT = {
-        AUDIO_TIMESTRETCH_SPEED_NORMAL,
-        AUDIO_TIMESTRETCH_PITCH_NORMAL,
-        AUDIO_TIMESTRETCH_STRETCH_DEFAULT,
-        AUDIO_TIMESTRETCH_FALLBACK_DEFAULT
-};
+static const AudioPlaybackRate AUDIO_PLAYBACK_RATE_DEFAULT = ::AUDIO_PLAYBACK_RATE_INITIALIZER;
 
 static inline bool isAudioPlaybackRateEqual(const AudioPlaybackRate &pr1,
         const AudioPlaybackRate &pr2) {
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libaudioprocessing/include/media/BufferProviders.h
similarity index 100%
rename from media/libmedia/include/media/BufferProviders.h
rename to media/libaudioprocessing/include/media/BufferProviders.h
diff --git a/media/libmedia/include/media/RecordBufferConverter.h b/media/libaudioprocessing/include/media/RecordBufferConverter.h
similarity index 100%
rename from media/libmedia/include/media/RecordBufferConverter.h
rename to media/libaudioprocessing/include/media/RecordBufferConverter.h
diff --git a/media/libaudioprocessing/tests/Android.bp b/media/libaudioprocessing/tests/Android.bp
index d990111..18acef7 100644
--- a/media/libaudioprocessing/tests/Android.bp
+++ b/media/libaudioprocessing/tests/Android.bp
@@ -3,8 +3,13 @@
 cc_defaults {
     name: "libaudioprocessing_test_defaults",
 
-    header_libs: ["libbase_headers"],
+    header_libs: [
+        "libbase_headers",
+        "libmedia_headers",
+    ],
+
     shared_libs: [
+        "libaudioclient",
         "libaudioprocessing",
         "libaudioutils",
         "libcutils",
@@ -50,3 +55,26 @@
     srcs: ["test-resampler.cpp"],
     static_libs: ["libsndfile"],
 }
+
+//
+// build mixerops objdump
+//
+// This is used to verify proper optimization of the code.
+//
+// For example, use:
+// ./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-objdump
+//      -d --source ./out/target/product/crosshatch/symbols/system/bin/mixerops_objdump
+//
+cc_binary {
+    name: "mixerops_objdump",
+    srcs: ["mixerops_objdump.cpp"],
+}
+
+//
+// build mixerops benchmark
+//
+cc_benchmark {
+    name: "mixerops_benchmark",
+    srcs: ["mixerops_benchmark.cpp"],
+    static_libs: ["libgoogle-benchmark"],
+}
diff --git a/media/libaudioprocessing/tests/fuzzer/Android.bp b/media/libaudioprocessing/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..1df47b7
--- /dev/null
+++ b/media/libaudioprocessing/tests/fuzzer/Android.bp
@@ -0,0 +1,10 @@
+cc_fuzz {
+  name: "libaudioprocessing_resampler_fuzzer",
+  srcs: [
+    "libaudioprocessing_resampler_fuzzer.cpp",
+  ],
+  defaults: ["libaudioprocessing_test_defaults"],
+  static_libs: [
+    "libsndfile",
+  ],
+}
diff --git a/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp b/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp
new file mode 100644
index 0000000..938c610
--- /dev/null
+++ b/media/libaudioprocessing/tests/fuzzer/libaudioprocessing_resampler_fuzzer.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 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 <android-base/macros.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/sndfile.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <math.h>
+#include <media/AudioBufferProvider.h>
+#include <media/AudioResampler.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Vector.h>
+
+#include <memory>
+
+using namespace android;
+
+const int MAX_FRAMES = 10;
+const int MIN_FREQ = 1e3;
+const int MAX_FREQ = 100e3;
+
+const AudioResampler::src_quality qualities[] = {
+    AudioResampler::DEFAULT_QUALITY,
+    AudioResampler::LOW_QUALITY,
+    AudioResampler::MED_QUALITY,
+    AudioResampler::HIGH_QUALITY,
+    AudioResampler::VERY_HIGH_QUALITY,
+    AudioResampler::DYN_LOW_QUALITY,
+    AudioResampler::DYN_MED_QUALITY,
+    AudioResampler::DYN_HIGH_QUALITY,
+};
+
+class Provider : public AudioBufferProvider {
+  const void* mAddr;        // base address
+  const size_t mNumFrames;  // total frames
+  const size_t mFrameSize;  // size of each frame in bytes
+  size_t mNextFrame;        // index of next frame to provide
+  size_t mUnrel;            // number of frames not yet released
+ public:
+  Provider(const void* addr, size_t frames, size_t frameSize)
+      : mAddr(addr),
+        mNumFrames(frames),
+        mFrameSize(frameSize),
+        mNextFrame(0),
+        mUnrel(0) {}
+  status_t getNextBuffer(Buffer* buffer) override {
+    if (buffer->frameCount > mNumFrames - mNextFrame) {
+      buffer->frameCount = mNumFrames - mNextFrame;
+    }
+    mUnrel = buffer->frameCount;
+    if (buffer->frameCount > 0) {
+      buffer->raw = (char*)mAddr + mFrameSize * mNextFrame;
+      return NO_ERROR;
+    } else {
+      buffer->raw = nullptr;
+      return NOT_ENOUGH_DATA;
+    }
+  }
+  virtual void releaseBuffer(Buffer* buffer) {
+    if (buffer->frameCount > mUnrel) {
+      mNextFrame += mUnrel;
+      mUnrel = 0;
+    } else {
+      mNextFrame += buffer->frameCount;
+      mUnrel -= buffer->frameCount;
+    }
+    buffer->frameCount = 0;
+    buffer->raw = nullptr;
+  }
+  void reset() { mNextFrame = 0; }
+};
+
+audio_format_t chooseFormat(AudioResampler::src_quality quality,
+                            uint8_t input_byte) {
+  switch (quality) {
+    case AudioResampler::DYN_LOW_QUALITY:
+    case AudioResampler::DYN_MED_QUALITY:
+    case AudioResampler::DYN_HIGH_QUALITY:
+      if (input_byte % 2) {
+        return AUDIO_FORMAT_PCM_FLOAT;
+      }
+      FALLTHROUGH_INTENDED;
+    default:
+      return AUDIO_FORMAT_PCM_16_BIT;
+  }
+}
+
+int parseValue(const uint8_t* src, int index, void* dst, size_t size) {
+  memcpy(dst, &src[index], size);
+  return size;
+}
+
+bool validFreq(int freq) { return freq > MIN_FREQ && freq < MAX_FREQ; }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  int input_freq = 0;
+  int output_freq = 0;
+  int input_channels = 0;
+
+  float left_volume = 0;
+  float right_volume = 0;
+
+  size_t metadata_size = 2 + 3 * sizeof(int) + 2 * sizeof(float);
+  if (size < metadata_size) {
+    // not enough data to set options
+    return 0;
+  }
+
+  AudioResampler::src_quality quality = qualities[data[0] % 8];
+  audio_format_t format = chooseFormat(quality, data[1]);
+
+  int index = 2;
+
+  index += parseValue(data, index, &input_freq, sizeof(int));
+  index += parseValue(data, index, &output_freq, sizeof(int));
+  index += parseValue(data, index, &input_channels, sizeof(int));
+
+  index += parseValue(data, index, &left_volume, sizeof(float));
+  index += parseValue(data, index, &right_volume, sizeof(float));
+
+  if (!validFreq(input_freq) || !validFreq(output_freq)) {
+    // sampling frequencies must be reasonable
+    return 0;
+  }
+
+  if (input_channels < 1 ||
+      input_channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
+    // invalid number of input channels
+    return 0;
+  }
+
+  size_t single_channel_size =
+      format == AUDIO_FORMAT_PCM_FLOAT ? sizeof(float) : sizeof(int16_t);
+  size_t input_frame_size = single_channel_size * input_channels;
+  size_t input_size = size - metadata_size;
+  uint8_t input_data[input_size];
+  memcpy(input_data, &data[metadata_size], input_size);
+
+  size_t input_frames = input_size / input_frame_size;
+  if (input_frames > MAX_FRAMES) {
+    return 0;
+  }
+
+  Provider provider(input_data, input_frames, input_frame_size);
+
+  std::unique_ptr<AudioResampler> resampler(
+      AudioResampler::create(format, input_channels, output_freq, quality));
+
+  resampler->setSampleRate(input_freq);
+  resampler->setVolume(left_volume, right_volume);
+
+  // output is at least stereo samples
+  int output_channels = input_channels > 2 ? input_channels : 2;
+  size_t output_frame_size = output_channels * sizeof(int32_t);
+  size_t output_frames = (input_frames * output_freq) / input_freq;
+  size_t output_size = output_frames * output_frame_size;
+
+  uint8_t output_data[output_size];
+  for (size_t i = 0; i < output_frames; i++) {
+    memset(output_data, 0, output_size);
+    resampler->resample((int*)output_data, i, &provider);
+  }
+
+  return 0;
+}
diff --git a/media/libaudioprocessing/tests/mixerops_benchmark.cpp b/media/libaudioprocessing/tests/mixerops_benchmark.cpp
new file mode 100644
index 0000000..86f5429
--- /dev/null
+++ b/media/libaudioprocessing/tests/mixerops_benchmark.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+#include <type_traits>
+#include "../../../../system/media/audio_utils/include/audio_utils/primitives.h"
+#define LOG_ALWAYS_FATAL(...)
+
+#include <../AudioMixerOps.h>
+
+#include <benchmark/benchmark.h>
+
+using namespace android;
+
+template <int MIXTYPE, int NCHAN>
+static void BM_VolumeRampMulti(benchmark::State& state) {
+    constexpr size_t FRAME_COUNT = 1000;
+    constexpr size_t SAMPLE_COUNT = FRAME_COUNT * NCHAN;
+
+    // data inialized to 0.
+    float out[SAMPLE_COUNT]{};
+    float in[SAMPLE_COUNT]{};
+    float aux[FRAME_COUNT]{};
+
+    // volume initialized to 0
+    float vola = 0.f;
+    float vol[2] = {0.f, 0.f};
+
+    // some volume increment
+    float volainc = 0.01f;
+    float volinc[2] = {0.01f, 0.01f};
+
+    while (state.KeepRunning()) {
+        benchmark::DoNotOptimize(out);
+        benchmark::DoNotOptimize(in);
+        volumeRampMulti<MIXTYPE, NCHAN>(out, FRAME_COUNT, in, aux, vol, volinc, &vola, volainc);
+        benchmark::ClobberMemory();
+    }
+}
+
+template <int MIXTYPE, int NCHAN>
+static void BM_VolumeMulti(benchmark::State& state) {
+    constexpr size_t FRAME_COUNT = 1000;
+    constexpr size_t SAMPLE_COUNT = FRAME_COUNT * NCHAN;
+
+    // data inialized to 0.
+    float out[SAMPLE_COUNT]{};
+    float in[SAMPLE_COUNT]{};
+    float aux[FRAME_COUNT]{};
+
+    // volume initialized to 0
+    float vola = 0.f;
+    float vol[2] = {0.f, 0.f};
+
+
+    while (state.KeepRunning()) {
+        benchmark::DoNotOptimize(out);
+        benchmark::DoNotOptimize(in);
+        volumeMulti<MIXTYPE, NCHAN>(out, FRAME_COUNT, in, aux, vol, vola);
+        benchmark::ClobberMemory();
+    }
+}
+
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 2);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 2);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 2);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 2);
+
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 4);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 4);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 4);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 4);
+
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 5);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 5);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 5);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 5);
+
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI, 8);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY, 8);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_STEREOVOL, 8);
+BENCHMARK_TEMPLATE(BM_VolumeRampMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 8);
+
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI, 8);
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_SAVEONLY, 8);
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_STEREOVOL, 8);
+BENCHMARK_TEMPLATE(BM_VolumeMulti, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, 8);
+
+BENCHMARK_MAIN();
diff --git a/media/libaudioprocessing/tests/mixerops_objdump.cpp b/media/libaudioprocessing/tests/mixerops_objdump.cpp
new file mode 100644
index 0000000..ee7e837
--- /dev/null
+++ b/media/libaudioprocessing/tests/mixerops_objdump.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+#include <type_traits>
+#include "../../../../system/media/audio_utils/include/audio_utils/primitives.h"
+#define LOG_ALWAYS_FATAL(...)
+
+#include <../AudioMixerOps.h>
+
+using namespace android;
+
+template <int MIXTYPE, int NCHAN>
+static void checkVolumeRampMulti() {
+    constexpr size_t FRAME_COUNT = 1000;
+    constexpr size_t SAMPLE_COUNT = FRAME_COUNT * NCHAN;
+
+    // data inialized to 0.
+    float out[SAMPLE_COUNT]{};
+    float in[SAMPLE_COUNT]{};
+    float aux[FRAME_COUNT]{};
+
+    // volume initialized to 0
+    float vola = 0.f;
+    float vol[2] = {0.f, 0.f};
+
+    // some volume increment
+    float volainc = 0.01f;
+    float volinc[2] = {0.01f, 0.01f};
+
+    // try the multi ramp code.
+    volumeRampMulti<MIXTYPE, NCHAN>(out, FRAME_COUNT, in, aux, vol, volinc, &vola, volainc);
+}
+
+// Use this to check the objdump to ensure reasonable code.
+int main() {
+    checkVolumeRampMulti<MIXTYPE_MULTI_STEREOVOL, 5>();
+    return EXIT_SUCCESS;
+}
diff --git a/media/libcpustats/Android.bp b/media/libcpustats/Android.bp
index 8fcd8a4..6e8ca1d 100644
--- a/media/libcpustats/Android.bp
+++ b/media/libcpustats/Android.bp
@@ -6,6 +6,14 @@
         "ThreadCpuUsage.cpp",
     ],
 
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libdatasource/Android.bp b/media/libdatasource/Android.bp
new file mode 100644
index 0000000..f191c21
--- /dev/null
+++ b/media/libdatasource/Android.bp
@@ -0,0 +1,63 @@
+cc_library {
+    name: "libdatasource",
+
+    srcs: [
+        "DataSourceFactory.cpp",
+        "DataURISource.cpp",
+        "FileSource.cpp",
+        "HTTPBase.cpp",
+        "MediaHTTP.cpp",
+        "NuCachedSource2.cpp",
+    ],
+
+    aidl: {
+        local_include_dirs: ["aidl"],
+        export_aidl_headers: true,
+    },
+
+    header_libs: [
+        "libstagefright_headers",
+        "media_ndk_headers",
+        "libmedia_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libstagefright_headers",
+        "media_ndk_headers",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libstagefright_foundation",
+        "libdl",
+    ],
+
+    static_libs: [
+        "libc_malloc_debug_backtrace",  // for memory heap analysis
+        "libmedia_midiiowrapper",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
new file mode 100644
index 0000000..bb6a08c
--- /dev/null
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 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 "DataSource"
+
+
+#include <datasource/DataSourceFactory.h>
+#include <datasource/DataURISource.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/FileSource.h>
+#include <datasource/MediaHTTP.h>
+#include <datasource/NuCachedSource2.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// static
+sp<DataSourceFactory> DataSourceFactory::sInstance;
+// static
+Mutex DataSourceFactory::sInstanceLock;
+
+// static
+sp<DataSourceFactory> DataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new DataSourceFactory();
+    }
+    return sInstance;
+}
+
+sp<DataSource> DataSourceFactory::CreateFromURI(
+        const sp<MediaHTTPService> &httpService,
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        String8 *contentType,
+        HTTPBase *httpSource) {
+    if (contentType != NULL) {
+        *contentType = "";
+    }
+
+    sp<DataSource> source;
+    if (!strncasecmp("file://", uri, 7)) {
+        source = CreateFileSource(uri + 7);
+    } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
+        if (httpService == NULL) {
+            ALOGE("Invalid http service!");
+            return NULL;
+        }
+
+        sp<HTTPBase> mediaHTTP = httpSource;
+        if (mediaHTTP == NULL) {
+            mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
+        }
+
+        String8 cacheConfig;
+        bool disconnectAtHighwatermark = false;
+        KeyedVector<String8, String8> nonCacheSpecificHeaders;
+        if (headers != NULL) {
+            nonCacheSpecificHeaders = *headers;
+            NuCachedSource2::RemoveCacheSpecificHeaders(
+                    &nonCacheSpecificHeaders,
+                    &cacheConfig,
+                    &disconnectAtHighwatermark);
+        }
+
+        if (mediaHTTP->connect(uri, &nonCacheSpecificHeaders) != OK) {
+            ALOGE("Failed to connect http source!");
+            return NULL;
+        }
+
+        if (contentType != NULL) {
+            *contentType = mediaHTTP->getMIMEType();
+        }
+
+        source = NuCachedSource2::Create(
+                mediaHTTP,
+                cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+                disconnectAtHighwatermark);
+    } else if (!strncasecmp("data:", uri, 5)) {
+        source = DataURISource::Create(uri);
+    } else {
+        // Assume it's a filename.
+        source = CreateFileSource(uri);
+    }
+
+    if (source == NULL || source->initCheck() != OK) {
+        return NULL;
+    }
+
+    return source;
+}
+
+sp<DataSource> DataSourceFactory::CreateFromFd(int fd, int64_t offset, int64_t length) {
+    sp<FileSource> source = new FileSource(fd, offset, length);
+    return source->initCheck() != OK ? nullptr : source;
+}
+
+sp<DataSource> DataSourceFactory::CreateMediaHTTP(const sp<MediaHTTPService> &httpService) {
+    if (httpService == NULL) {
+        return NULL;
+    }
+
+    sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
+    if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
+        return NULL;
+    } else {
+        return new MediaHTTP(conn);
+    }
+}
+
+sp<DataSource> DataSourceFactory::CreateFileSource(const char *uri) {
+    return new FileSource(uri);
+}
+
+}  // namespace android
diff --git a/media/libdatasource/DataURISource.cpp b/media/libdatasource/DataURISource.cpp
new file mode 100644
index 0000000..216f3d0
--- /dev/null
+++ b/media/libdatasource/DataURISource.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 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 <datasource/DataURISource.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+
+namespace android {
+
+// static
+sp<DataURISource> DataURISource::Create(const char *uri) {
+    if (strncasecmp("data:", uri, 5)) {
+        return NULL;
+    }
+
+    const char *commaPos = strrchr(uri, ',');
+
+    if (commaPos == NULL) {
+        return NULL;
+    }
+
+    sp<ABuffer> buffer;
+
+    AString tmp(&uri[5], commaPos - &uri[5]);
+
+    if (tmp.endsWith(";base64")) {
+
+        // strip all CR and LF characters.
+        const char *src = commaPos+1;
+        int len = strlen(src) + 1;
+        char *cleansed = (char *) malloc(len);
+        if (cleansed == NULL) return NULL;
+        char *keeping = cleansed;
+        int left = len;
+        for (int i = 0; i < len ; i++)
+        {
+            const char c = *src++;
+            if (c == '\r' || c == '\n') {
+                continue;
+            }
+            *keeping++ = c;
+            left--;
+        }
+        memset(keeping, 0, left);
+
+        AString encoded(cleansed);
+        free(cleansed);
+
+        buffer = decodeBase64(encoded);
+
+        if (buffer == NULL) {
+            ALOGE("Malformed base64 encoded content found.");
+            return NULL;
+        }
+    } else {
+#if 0
+        size_t dataLen = strlen(uri) - tmp.size() - 6;
+        buffer = new ABuffer(dataLen);
+        memcpy(buffer->data(), commaPos + 1, dataLen);
+
+        // unescape
+#else
+        // MediaPlayer doesn't care for this right now as we don't
+        // play any text-based media.
+        return NULL;
+#endif
+    }
+
+    // We don't really care about charset or mime type.
+
+    return new DataURISource(buffer);
+}
+
+DataURISource::DataURISource(const sp<ABuffer> &buffer)
+    : mBuffer(buffer) {
+}
+
+DataURISource::~DataURISource() {
+}
+
+status_t DataURISource::initCheck() const {
+    return OK;
+}
+
+ssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) {
+    if ((offset < 0) || (offset >= (off64_t)mBuffer->size())) {
+        return 0;
+    }
+
+    size_t copy = mBuffer->size() - offset;
+    if (copy > size) {
+        copy = size;
+    }
+
+    memcpy(data, mBuffer->data() + offset, copy);
+
+    return copy;
+}
+
+status_t DataURISource::getSize(off64_t *size) {
+    *size = mBuffer->size();
+
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/media/libdatasource/FileSource.cpp b/media/libdatasource/FileSource.cpp
new file mode 100644
index 0000000..3d34d0c
--- /dev/null
+++ b/media/libdatasource/FileSource.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 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 "FileSource"
+#include <utils/Log.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/FoundationUtils.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace android {
+
+FileSource::FileSource(const char *filename)
+    : mFd(-1),
+      mOffset(0),
+      mLength(-1),
+      mName("<null>") {
+
+    if (filename) {
+        mName = String8::format("FileSource(%s)", filename);
+    }
+    ALOGV("%s", filename);
+    mFd = open(filename, O_LARGEFILE | O_RDONLY);
+
+    if (mFd >= 0) {
+        mLength = lseek64(mFd, 0, SEEK_END);
+    } else {
+        ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
+    }
+}
+
+FileSource::FileSource(int fd, int64_t offset, int64_t length)
+    : mFd(fd),
+      mOffset(offset),
+      mLength(length),
+      mName("<null>") {
+    ALOGV("fd=%d (%s), offset=%lld, length=%lld",
+            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
+
+    if (mOffset < 0) {
+        mOffset = 0;
+    }
+    if (mLength < 0) {
+        mLength = 0;
+    }
+    if (mLength > INT64_MAX - mOffset) {
+        mLength = INT64_MAX - mOffset;
+    }
+    struct stat s;
+    if (fstat(fd, &s) == 0) {
+        if (mOffset > s.st_size) {
+            mOffset = s.st_size;
+            mLength = 0;
+        }
+        if (mOffset + mLength > s.st_size) {
+            mLength = s.st_size - mOffset;
+        }
+    }
+    if (mOffset != offset || mLength != length) {
+        ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld",
+                (long long) offset, (long long) length,
+                (long long) mOffset, (long long) mLength);
+    }
+
+    mName = String8::format(
+            "FileSource(fd(%s), %lld, %lld)",
+            nameForFd(fd).c_str(),
+            (long long) mOffset,
+            (long long) mLength);
+
+}
+
+FileSource::~FileSource() {
+    if (mFd >= 0) {
+        ::close(mFd);
+        mFd = -1;
+    }
+}
+
+status_t FileSource::initCheck() const {
+    return mFd >= 0 ? OK : NO_INIT;
+}
+
+ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
+    if (mFd < 0) {
+        return NO_INIT;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    if (mLength >= 0) {
+        if (offset < 0) {
+            return UNKNOWN_ERROR;
+        }
+        if (offset >= mLength) {
+            return 0;  // read beyond EOF.
+        }
+        uint64_t numAvailable = mLength - offset;
+        if ((uint64_t)size > numAvailable) {
+            size = numAvailable;
+        }
+    }
+    return readAt_l(offset, data, size);
+}
+
+ssize_t FileSource::readAt_l(off64_t offset, void *data, size_t size) {
+    off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
+    if (result == -1) {
+        ALOGE("seek to %lld failed", (long long)(offset + mOffset));
+        return UNKNOWN_ERROR;
+    }
+
+    return ::read(mFd, data, size);
+}
+
+status_t FileSource::getSize(off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mFd < 0) {
+        return NO_INIT;
+    }
+
+    *size = mLength;
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libdatasource/HTTPBase.cpp b/media/libdatasource/HTTPBase.cpp
new file mode 100644
index 0000000..ef29c48
--- /dev/null
+++ b/media/libdatasource/HTTPBase.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 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 "HTTPBase"
+#include <utils/Log.h>
+
+#include <datasource/HTTPBase.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+#include <cutils/properties.h>
+#include <cutils/qtaguid.h>
+
+namespace android {
+
+HTTPBase::HTTPBase()
+    : mNumBandwidthHistoryItems(0),
+      mTotalTransferTimeUs(0),
+      mTotalTransferBytes(0),
+      mMaxBandwidthHistoryItems(100),
+      mPrevBandwidthMeasureTimeUs(0),
+      mPrevEstimatedBandWidthKbps(0),
+      mBandWidthCollectFreqMs(5000) {
+    mName = String8("HTTPBase(<disconnected>)");
+}
+
+void HTTPBase::addBandwidthMeasurement(
+        size_t numBytes, int64_t delayUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    BandwidthEntry entry;
+    entry.mDelayUs = delayUs;
+    entry.mNumBytes = numBytes;
+    mTotalTransferTimeUs += delayUs;
+    mTotalTransferBytes += numBytes;
+
+    mBandwidthHistory.push_back(entry);
+    if (++mNumBandwidthHistoryItems > mMaxBandwidthHistoryItems) {
+        BandwidthEntry *entry = &*mBandwidthHistory.begin();
+        mTotalTransferTimeUs -= entry->mDelayUs;
+        mTotalTransferBytes -= entry->mNumBytes;
+        mBandwidthHistory.erase(mBandwidthHistory.begin());
+        --mNumBandwidthHistoryItems;
+
+        int64_t timeNowUs = ALooper::GetNowUs();
+        if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
+                mBandWidthCollectFreqMs * 1000LL) {
+
+            if (mPrevBandwidthMeasureTimeUs != 0) {
+                mPrevEstimatedBandWidthKbps =
+                    (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
+            }
+            mPrevBandwidthMeasureTimeUs = timeNowUs;
+        }
+    }
+
+}
+
+bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
+    Mutex::Autolock autoLock(mLock);
+
+    // Do not do bandwidth estimation if we don't have enough samples, or
+    // total bytes download are too small (<64K).
+    // Bandwidth estimation from these samples can often shoot up and cause
+    // unwanted bw adaption behaviors.
+    if (mNumBandwidthHistoryItems < 2 || mTotalTransferBytes < 65536) {
+        return false;
+    }
+
+    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+    return true;
+}
+
+status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
+    Mutex::Autolock autoLock(mLock);
+    *kbps = mPrevEstimatedBandWidthKbps;
+    return OK;
+}
+
+status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (freqMs < kMinBandwidthCollectFreqMs
+            || freqMs > kMaxBandwidthCollectFreqMs) {
+
+        ALOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
+        return BAD_VALUE;
+    }
+
+    ALOGI("frequency set to %d ms", freqMs);
+    mBandWidthCollectFreqMs = freqMs;
+    return OK;
+}
+
+void HTTPBase::setBandwidthHistorySize(size_t numHistoryItems) {
+    mMaxBandwidthHistoryItems = numHistoryItems;
+}
+
+}  // namespace android
diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
new file mode 100644
index 0000000..58c1ce8
--- /dev/null
+++ b/media/libdatasource/MediaHTTP.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 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 "MediaHTTP"
+#include <utils/Log.h>
+
+#include <datasource/MediaHTTP.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/FoundationUtils.h>
+
+#include <media/MediaHTTPConnection.h>
+
+namespace android {
+
+MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
+    : mInitCheck((conn != NULL) ? OK : NO_INIT),
+      mHTTPConnection(conn),
+      mCachedSizeValid(false),
+      mCachedSize(0ll) {
+}
+
+MediaHTTP::~MediaHTTP() {
+}
+
+status_t MediaHTTP::connect(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t /* offset */) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    KeyedVector<String8, String8> extHeaders;
+    if (headers != NULL) {
+        extHeaders = *headers;
+    }
+
+    if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
+        extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
+    }
+
+    mLastURI = uri;
+    // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
+    // as part of the above assignment. Ensure no accidental later use.
+    uri = NULL;
+
+    bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
+
+    mLastHeaders = extHeaders;
+
+    mCachedSizeValid = false;
+
+    if (success) {
+        AString sanitized = uriDebugString(mLastURI);
+        mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
+    }
+
+    return success ? OK : UNKNOWN_ERROR;
+}
+
+void MediaHTTP::close() {
+    disconnect();
+}
+
+void MediaHTTP::disconnect() {
+    mName = String8("MediaHTTP(<disconnected>)");
+    if (mInitCheck != OK) {
+        return;
+    }
+
+    mHTTPConnection->disconnect();
+}
+
+status_t MediaHTTP::initCheck() const {
+    return mInitCheck;
+}
+
+ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    int64_t startTimeUs = ALooper::GetNowUs();
+
+    size_t numBytesRead = 0;
+    while (numBytesRead < size) {
+        size_t copy = size - numBytesRead;
+
+        if (copy > 64 * 1024) {
+            // limit the buffer sizes transferred across binder boundaries
+            // to avoid spurious transaction failures.
+            copy = 64 * 1024;
+        }
+
+        ssize_t n = mHTTPConnection->readAt(
+                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
+
+        if (n < 0) {
+            return n;
+        } else if (n == 0) {
+            break;
+        }
+
+        numBytesRead += n;
+    }
+
+    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+    addBandwidthMeasurement(numBytesRead, delayUs);
+
+    return numBytesRead;
+}
+
+status_t MediaHTTP::getSize(off64_t *size) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    // Caching the returned size so that it stays valid even after a
+    // disconnect. NuCachedSource2 relies on this.
+
+    if (!mCachedSizeValid) {
+        mCachedSize = mHTTPConnection->getSize();
+        mCachedSizeValid = true;
+    }
+
+    *size = mCachedSize;
+
+    return *size < 0 ? *size : static_cast<status_t>(OK);
+}
+
+uint32_t MediaHTTP::flags() {
+    return kWantsPrefetching | kIsHTTPBasedSource;
+}
+
+status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
+    return connect(mLastURI.c_str(), &mLastHeaders, offset);
+}
+
+
+String8 MediaHTTP::getUri() {
+    if (mInitCheck != OK) {
+        return String8::empty();
+    }
+
+    String8 uri;
+    if (OK == mHTTPConnection->getUri(&uri)) {
+        return uri;
+    }
+    return String8(mLastURI.c_str());
+}
+
+String8 MediaHTTP::getMIMEType() const {
+    if (mInitCheck != OK) {
+        return String8("application/octet-stream");
+    }
+
+    String8 mimeType;
+    status_t err = mHTTPConnection->getMIMEType(&mimeType);
+
+    if (err != OK) {
+        return String8("application/octet-stream");
+    }
+
+    return mimeType;
+}
+
+}  // namespace android
diff --git a/media/libdatasource/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
new file mode 100644
index 0000000..6d63ffb
--- /dev/null
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -0,0 +1,780 @@
+/*
+ * Copyright (C) 2010 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 <inttypes.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NuCachedSource2"
+#include <utils/Log.h>
+
+#include <datasource/NuCachedSource2.h>
+#include <datasource/HTTPBase.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct PageCache {
+    explicit PageCache(size_t pageSize);
+    ~PageCache();
+
+    struct Page {
+        void *mData;
+        size_t mSize;
+    };
+
+    Page *acquirePage();
+    void releasePage(Page *page);
+
+    void appendPage(Page *page);
+    size_t releaseFromStart(size_t maxBytes);
+
+    size_t totalSize() const {
+        return mTotalSize;
+    }
+
+    void copy(size_t from, void *data, size_t size);
+
+private:
+    size_t mPageSize;
+    size_t mTotalSize;
+
+    List<Page *> mActivePages;
+    List<Page *> mFreePages;
+
+    void freePages(List<Page *> *list);
+
+    DISALLOW_EVIL_CONSTRUCTORS(PageCache);
+};
+
+PageCache::PageCache(size_t pageSize)
+    : mPageSize(pageSize),
+      mTotalSize(0) {
+}
+
+PageCache::~PageCache() {
+    freePages(&mActivePages);
+    freePages(&mFreePages);
+}
+
+void PageCache::freePages(List<Page *> *list) {
+    List<Page *>::iterator it = list->begin();
+    while (it != list->end()) {
+        Page *page = *it;
+
+        free(page->mData);
+        delete page;
+        page = NULL;
+
+        ++it;
+    }
+}
+
+PageCache::Page *PageCache::acquirePage() {
+    if (!mFreePages.empty()) {
+        List<Page *>::iterator it = mFreePages.begin();
+        Page *page = *it;
+        mFreePages.erase(it);
+
+        return page;
+    }
+
+    Page *page = new Page;
+    page->mData = malloc(mPageSize);
+    page->mSize = 0;
+
+    return page;
+}
+
+void PageCache::releasePage(Page *page) {
+    page->mSize = 0;
+    mFreePages.push_back(page);
+}
+
+void PageCache::appendPage(Page *page) {
+    mTotalSize += page->mSize;
+    mActivePages.push_back(page);
+}
+
+size_t PageCache::releaseFromStart(size_t maxBytes) {
+    size_t bytesReleased = 0;
+
+    while (maxBytes > 0 && !mActivePages.empty()) {
+        List<Page *>::iterator it = mActivePages.begin();
+
+        Page *page = *it;
+
+        if (maxBytes < page->mSize) {
+            break;
+        }
+
+        mActivePages.erase(it);
+
+        maxBytes -= page->mSize;
+        bytesReleased += page->mSize;
+
+        releasePage(page);
+    }
+
+    mTotalSize -= bytesReleased;
+    return bytesReleased;
+}
+
+void PageCache::copy(size_t from, void *data, size_t size) {
+    ALOGV("copy from %zu size %zu", from, size);
+
+    if (size == 0) {
+        return;
+    }
+
+    CHECK_LE(from + size, mTotalSize);
+
+    size_t offset = 0;
+    List<Page *>::iterator it = mActivePages.begin();
+    while (from >= offset + (*it)->mSize) {
+        offset += (*it)->mSize;
+        ++it;
+    }
+
+    size_t delta = from - offset;
+    size_t avail = (*it)->mSize - delta;
+
+    if (avail >= size) {
+        memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
+        return;
+    }
+
+    memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
+    ++it;
+    data = (uint8_t *)data + avail;
+    size -= avail;
+
+    while (size > 0) {
+        size_t copy = (*it)->mSize;
+        if (copy > size) {
+            copy = size;
+        }
+        memcpy(data, (*it)->mData, copy);
+        data = (uint8_t *)data + copy;
+        size -= copy;
+        ++it;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NuCachedSource2::NuCachedSource2(
+        const sp<DataSource> &source,
+        const char *cacheConfig,
+        bool disconnectAtHighwatermark)
+    : mSource(source),
+      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
+      mLooper(new ALooper),
+      mCache(new PageCache(kPageSize)),
+      mCacheOffset(0),
+      mFinalStatus(OK),
+      mLastAccessPos(0),
+      mFetching(true),
+      mDisconnecting(false),
+      mLastFetchTimeUs(-1),
+      mNumRetriesLeft(kMaxNumRetries),
+      mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
+      mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
+      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
+      mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
+    // We are NOT going to support disconnect-at-highwatermark indefinitely
+    // and we are not guaranteeing support for client-specified cache
+    // parameters. Both of these are temporary measures to solve a specific
+    // problem that will be solved in a better way going forward.
+
+    updateCacheParamsFromSystemProperty();
+
+    if (cacheConfig != NULL) {
+        updateCacheParamsFromString(cacheConfig);
+    }
+
+    if (mDisconnectAtHighwatermark) {
+        // Makes no sense to disconnect and do keep-alives...
+        mKeepAliveIntervalUs = 0;
+    }
+
+    mLooper->setName("NuCachedSource2");
+    mLooper->registerHandler(mReflector);
+
+    // Since it may not be obvious why our looper thread needs to be
+    // able to call into java since it doesn't appear to do so at all...
+    // IMediaHTTPConnection may be (and most likely is) implemented in JAVA
+    // and a local JAVA IBinder will call directly into JNI methods.
+    // So whenever we call DataSource::readAt it may end up in a call to
+    // IMediaHTTPConnection::readAt and therefore call back into JAVA.
+    mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
+
+    mName = String8::format("NuCachedSource2(%s)", mSource->toString().string());
+}
+
+NuCachedSource2::~NuCachedSource2() {
+    mLooper->stop();
+    mLooper->unregisterHandler(mReflector->id());
+
+    delete mCache;
+    mCache = NULL;
+}
+
+// static
+sp<NuCachedSource2> NuCachedSource2::Create(
+        const sp<DataSource> &source,
+        const char *cacheConfig,
+        bool disconnectAtHighwatermark) {
+    sp<NuCachedSource2> instance = new NuCachedSource2(
+            source, cacheConfig, disconnectAtHighwatermark);
+    Mutex::Autolock autoLock(instance->mLock);
+    (new AMessage(kWhatFetchMore, instance->mReflector))->post();
+    return instance;
+}
+
+status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
+    if (mSource->flags() & kIsHTTPBasedSource) {
+        HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
+        return source->getEstimatedBandwidthKbps(kbps);
+    }
+    return ERROR_UNSUPPORTED;
+}
+
+void NuCachedSource2::close() {
+    disconnect();
+}
+
+void NuCachedSource2::disconnect() {
+    if (mSource->flags() & kIsHTTPBasedSource) {
+        ALOGV("disconnecting HTTPBasedSource");
+
+        {
+            Mutex::Autolock autoLock(mLock);
+            // set mDisconnecting to true, if a fetch returns after
+            // this, the source will be marked as EOS.
+            mDisconnecting = true;
+
+            // explicitly signal mCondition so that the pending readAt()
+            // will immediately return
+            mCondition.signal();
+        }
+
+        // explicitly disconnect from the source, to allow any
+        // pending reads to return more promptly
+        static_cast<HTTPBase *>(mSource.get())->disconnect();
+    }
+}
+
+status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
+    if (mSource->flags() & kIsHTTPBasedSource) {
+        HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
+        return source->setBandwidthStatCollectFreq(freqMs);
+    }
+    return ERROR_UNSUPPORTED;
+}
+
+status_t NuCachedSource2::initCheck() const {
+    return mSource->initCheck();
+}
+
+status_t NuCachedSource2::getSize(off64_t *size) {
+    return mSource->getSize(size);
+}
+
+uint32_t NuCachedSource2::flags() {
+    // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
+    uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
+    return (flags | kIsCachingDataSource);
+}
+
+void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatFetchMore:
+        {
+            onFetch();
+            break;
+        }
+
+        case kWhatRead:
+        {
+            onRead(msg);
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+}
+
+void NuCachedSource2::fetchInternal() {
+    ALOGV("fetchInternal");
+
+    bool reconnect = false;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
+
+        if (mFinalStatus != OK) {
+            --mNumRetriesLeft;
+
+            reconnect = true;
+        }
+    }
+
+    if (reconnect) {
+        status_t err =
+            mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
+
+        Mutex::Autolock autoLock(mLock);
+
+        if (mDisconnecting) {
+            mNumRetriesLeft = 0;
+            mFinalStatus = ERROR_END_OF_STREAM;
+            return;
+        } else if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
+            // These are errors that are not likely to go away even if we
+            // retry, i.e. the server doesn't support range requests or similar.
+            mNumRetriesLeft = 0;
+            return;
+        } else if (err != OK) {
+            ALOGI("The attempt to reconnect failed, %d retries remaining",
+                 mNumRetriesLeft);
+
+            return;
+        }
+    }
+
+    PageCache::Page *page = mCache->acquirePage();
+
+    ssize_t n = mSource->readAt(
+            mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (n == 0 || mDisconnecting) {
+        ALOGI("caching reached eos.");
+
+        mNumRetriesLeft = 0;
+        mFinalStatus = ERROR_END_OF_STREAM;
+
+        mCache->releasePage(page);
+    } else if (n < 0) {
+        mFinalStatus = n;
+        if (n == ERROR_UNSUPPORTED || n == -EPIPE) {
+            // These are errors that are not likely to go away even if we
+            // retry, i.e. the server doesn't support range requests or similar.
+            mNumRetriesLeft = 0;
+        }
+
+        ALOGE("source returned error %zd, %d retries left", n, mNumRetriesLeft);
+        mCache->releasePage(page);
+    } else {
+        if (mFinalStatus != OK) {
+            ALOGI("retrying a previously failed read succeeded.");
+        }
+        mNumRetriesLeft = kMaxNumRetries;
+        mFinalStatus = OK;
+
+        page->mSize = n;
+        mCache->appendPage(page);
+    }
+}
+
+void NuCachedSource2::onFetch() {
+    ALOGV("onFetch");
+
+    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
+        ALOGV("EOS reached, done prefetching for now");
+        mFetching = false;
+    }
+
+    bool keepAlive =
+        !mFetching
+            && mFinalStatus == OK
+            && mKeepAliveIntervalUs > 0
+            && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs;
+
+    if (mFetching || keepAlive) {
+        if (keepAlive) {
+            ALOGI("Keep alive");
+        }
+
+        fetchInternal();
+
+        mLastFetchTimeUs = ALooper::GetNowUs();
+
+        if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
+            ALOGI("Cache full, done prefetching for now");
+            mFetching = false;
+
+            if (mDisconnectAtHighwatermark
+                    && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
+                ALOGV("Disconnecting at high watermark");
+                static_cast<HTTPBase *>(mSource.get())->disconnect();
+                mFinalStatus = -EAGAIN;
+            }
+        }
+    } else {
+        Mutex::Autolock autoLock(mLock);
+        restartPrefetcherIfNecessary_l();
+    }
+
+    int64_t delayUs;
+    if (mFetching) {
+        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+            // We failed this time and will try again in 3 seconds.
+            delayUs = 3000000LL;
+        } else {
+            delayUs = 0;
+        }
+    } else {
+        delayUs = 100000LL;
+    }
+
+    (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
+}
+
+void NuCachedSource2::onRead(const sp<AMessage> &msg) {
+    ALOGV("onRead");
+
+    int64_t offset;
+    CHECK(msg->findInt64("offset", &offset));
+
+    void *data;
+    CHECK(msg->findPointer("data", &data));
+
+    size_t size;
+    CHECK(msg->findSize("size", &size));
+
+    ssize_t result = readInternal(offset, data, size);
+
+    if (result == -EAGAIN) {
+        msg->post(50000);
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    if (mDisconnecting) {
+        mCondition.signal();
+        return;
+    }
+
+    CHECK(mAsyncResult == NULL);
+
+    mAsyncResult = new AMessage;
+    mAsyncResult->setInt32("result", result);
+
+    mCondition.signal();
+}
+
+void NuCachedSource2::restartPrefetcherIfNecessary_l(
+        bool ignoreLowWaterThreshold, bool force) {
+    static const size_t kGrayArea = 1024 * 1024;
+
+    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
+        return;
+    }
+
+    if (!ignoreLowWaterThreshold && !force
+            && mCacheOffset + mCache->totalSize() - mLastAccessPos
+                >= mLowwaterThresholdBytes) {
+        return;
+    }
+
+    size_t maxBytes = mLastAccessPos - mCacheOffset;
+
+    if (!force) {
+        if (maxBytes < kGrayArea) {
+            return;
+        }
+
+        maxBytes -= kGrayArea;
+    }
+
+    size_t actualBytes = mCache->releaseFromStart(maxBytes);
+    mCacheOffset += actualBytes;
+
+    ALOGI("restarting prefetcher, totalSize = %zu", mCache->totalSize());
+    mFetching = true;
+}
+
+ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
+    Mutex::Autolock autoSerializer(mSerializer);
+
+    ALOGV("readAt offset %lld, size %zu", (long long)offset, size);
+
+    Mutex::Autolock autoLock(mLock);
+    if (mDisconnecting) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    // If the request can be completely satisfied from the cache, do so.
+
+    if (offset >= mCacheOffset
+            && offset + size <= mCacheOffset + mCache->totalSize()) {
+        size_t delta = offset - mCacheOffset;
+        mCache->copy(delta, data, size);
+
+        mLastAccessPos = offset + size;
+
+        return size;
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatRead, mReflector);
+    msg->setInt64("offset", offset);
+    msg->setPointer("data", data);
+    msg->setSize("size", size);
+
+    CHECK(mAsyncResult == NULL);
+    msg->post();
+
+    while (mAsyncResult == NULL && !mDisconnecting) {
+        mCondition.wait(mLock);
+    }
+
+    if (mDisconnecting) {
+        mAsyncResult.clear();
+        return ERROR_END_OF_STREAM;
+    }
+
+    int32_t result;
+    CHECK(mAsyncResult->findInt32("result", &result));
+
+    mAsyncResult.clear();
+
+    if (result > 0) {
+        mLastAccessPos = offset + result;
+    }
+
+    return (ssize_t)result;
+}
+
+size_t NuCachedSource2::cachedSize() {
+    Mutex::Autolock autoLock(mLock);
+    return mCacheOffset + mCache->totalSize();
+}
+
+status_t NuCachedSource2::getAvailableSize(off64_t offset, off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+    status_t finalStatus = UNKNOWN_ERROR;
+    *size = approxDataRemaining_l(offset, &finalStatus);
+    return finalStatus;
+}
+
+size_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) const {
+    Mutex::Autolock autoLock(mLock);
+    return approxDataRemaining_l(mLastAccessPos, finalStatus);
+}
+
+size_t NuCachedSource2::approxDataRemaining_l(off64_t offset, status_t *finalStatus) const {
+    *finalStatus = mFinalStatus;
+
+    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+        // Pretend that everything is fine until we're out of retries.
+        *finalStatus = OK;
+    }
+
+    offset = offset >= 0 ? offset : mLastAccessPos;
+    off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
+    if (offset < lastBytePosCached) {
+        return lastBytePosCached - offset;
+    }
+    return 0;
+}
+
+ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
+    CHECK_LE(size, (size_t)mHighwaterThresholdBytes);
+
+    ALOGV("readInternal offset %lld size %zu", (long long)offset, size);
+
+    Mutex::Autolock autoLock(mLock);
+
+    // If we're disconnecting, return EOS and don't access *data pointer.
+    // data could be on the stack of the caller to NuCachedSource2::readAt(),
+    // which may have exited already.
+    if (mDisconnecting) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    if (!mFetching) {
+        mLastAccessPos = offset;
+        restartPrefetcherIfNecessary_l(
+                false, // ignoreLowWaterThreshold
+                true); // force
+    }
+
+    if (offset < mCacheOffset
+            || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
+        static const off64_t kPadding = 256 * 1024;
+
+        // In the presence of multiple decoded streams, once of them will
+        // trigger this seek request, the other one will request data "nearby"
+        // soon, adjust the seek position so that that subsequent request
+        // does not trigger another seek.
+        off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
+
+        seekInternal_l(seekOffset);
+    }
+
+    size_t delta = offset - mCacheOffset;
+
+    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
+        if (delta >= mCache->totalSize()) {
+            return mFinalStatus;
+        }
+
+        size_t avail = mCache->totalSize() - delta;
+
+        if (avail > size) {
+            avail = size;
+        }
+
+        mCache->copy(delta, data, avail);
+
+        return avail;
+    }
+
+    if (offset + size <= mCacheOffset + mCache->totalSize()) {
+        mCache->copy(delta, data, size);
+
+        return size;
+    }
+
+    ALOGV("deferring read");
+
+    return -EAGAIN;
+}
+
+status_t NuCachedSource2::seekInternal_l(off64_t offset) {
+    mLastAccessPos = offset;
+
+    if (offset >= mCacheOffset
+            && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) {
+        return OK;
+    }
+
+    ALOGI("new range: offset= %lld", (long long)offset);
+
+    mCacheOffset = offset;
+
+    size_t totalSize = mCache->totalSize();
+    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
+
+    mNumRetriesLeft = kMaxNumRetries;
+    mFetching = true;
+
+    return OK;
+}
+
+void NuCachedSource2::resumeFetchingIfNecessary() {
+    Mutex::Autolock autoLock(mLock);
+
+    restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
+}
+
+String8 NuCachedSource2::getUri() {
+    return mSource->getUri();
+}
+
+String8 NuCachedSource2::getMIMEType() const {
+    return mSource->getMIMEType();
+}
+
+void NuCachedSource2::updateCacheParamsFromSystemProperty() {
+    char value[PROPERTY_VALUE_MAX];
+    if (!property_get("media.stagefright.cache-params", value, NULL)) {
+        return;
+    }
+
+    updateCacheParamsFromString(value);
+}
+
+void NuCachedSource2::updateCacheParamsFromString(const char *s) {
+    ssize_t lowwaterMarkKb, highwaterMarkKb;
+    int keepAliveSecs;
+
+    if (sscanf(s, "%zd/%zd/%d",
+               &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) {
+        ALOGE("Failed to parse cache parameters from '%s'.", s);
+        return;
+    }
+
+    if (lowwaterMarkKb >= 0) {
+        mLowwaterThresholdBytes = lowwaterMarkKb * 1024;
+    } else {
+        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
+    }
+
+    if (highwaterMarkKb >= 0) {
+        mHighwaterThresholdBytes = highwaterMarkKb * 1024;
+    } else {
+        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
+    }
+
+    if (mLowwaterThresholdBytes >= mHighwaterThresholdBytes) {
+        ALOGE("Illegal low/highwater marks specified, reverting to defaults.");
+
+        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
+        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
+    }
+
+    if (keepAliveSecs >= 0) {
+        mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
+    } else {
+        mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
+    }
+
+    ALOGV("lowwater = %zu bytes, highwater = %zu bytes, keepalive = %lld us",
+         mLowwaterThresholdBytes,
+         mHighwaterThresholdBytes,
+         (long long)mKeepAliveIntervalUs);
+}
+
+// static
+void NuCachedSource2::RemoveCacheSpecificHeaders(
+        KeyedVector<String8, String8> *headers,
+        String8 *cacheConfig,
+        bool *disconnectAtHighwatermark) {
+    *cacheConfig = String8();
+    *disconnectAtHighwatermark = false;
+
+    if (headers == NULL) {
+        return;
+    }
+
+    ssize_t index;
+    if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
+        *cacheConfig = headers->valueAt(index);
+
+        headers->removeItemsAt(index);
+
+        ALOGV("Using special cache config '%s'", cacheConfig->string());
+    }
+
+    if ((index = headers->indexOfKey(
+                    String8("x-disconnect-at-highwatermark"))) >= 0) {
+        *disconnectAtHighwatermark = true;
+        headers->removeItemsAt(index);
+
+        ALOGV("Client requested disconnection at highwater mark");
+    }
+}
+
+}  // namespace android
diff --git a/media/libdatasource/include/datasource/DataSourceFactory.h b/media/libdatasource/include/datasource/DataSourceFactory.h
new file mode 100644
index 0000000..194abe2
--- /dev/null
+++ b/media/libdatasource/include/datasource/DataSourceFactory.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 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 DATA_SOURCE_FACTORY_H_
+
+#define DATA_SOURCE_FACTORY_H_
+
+#include <media/DataSource.h>
+#include <sys/types.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaHTTPService;
+class String8;
+struct HTTPBase;
+
+class DataSourceFactory : public RefBase {
+public:
+    static sp<DataSourceFactory> getInstance();
+    sp<DataSource> CreateFromURI(
+            const sp<MediaHTTPService> &httpService,
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            String8 *contentType = NULL,
+            HTTPBase *httpSource = NULL);
+
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+    sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+    DataSourceFactory() {};
+    virtual ~DataSourceFactory() {};
+
+private:
+    static sp<DataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
+};
+
+}  // namespace android
+
+#endif  // DATA_SOURCE_FACTORY_H_
diff --git a/media/libstagefright/include/media/stagefright/DataURISource.h b/media/libdatasource/include/datasource/DataURISource.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/DataURISource.h
rename to media/libdatasource/include/datasource/DataURISource.h
diff --git a/media/libdatasource/include/datasource/FileSource.h b/media/libdatasource/include/datasource/FileSource.h
new file mode 100644
index 0000000..dee0c33
--- /dev/null
+++ b/media/libdatasource/include/datasource/FileSource.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 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 FILE_SOURCE_H_
+
+#define FILE_SOURCE_H_
+
+#include <stdio.h>
+
+#include <media/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class FileSource : public DataSource {
+public:
+    FileSource(const char *filename);
+    // FileSource takes ownership and will close the fd
+    FileSource(int fd, int64_t offset, int64_t length);
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+    virtual status_t getSize(off64_t *size);
+
+    virtual uint32_t flags() {
+        return kIsLocalFileSource;
+    }
+
+    virtual String8 toString() {
+        return mName;
+    }
+
+protected:
+    virtual ~FileSource();
+    virtual ssize_t readAt_l(off64_t offset, void *data, size_t size);
+
+    int mFd;
+    int64_t mOffset;
+    int64_t mLength;
+    Mutex mLock;
+
+private:
+    String8 mName;
+
+    FileSource(const FileSource &);
+    FileSource &operator=(const FileSource &);
+};
+
+}  // namespace android
+
+#endif  // FILE_SOURCE_H_
+
diff --git a/media/libdatasource/include/datasource/HTTPBase.h b/media/libdatasource/include/datasource/HTTPBase.h
new file mode 100644
index 0000000..656e85e
--- /dev/null
+++ b/media/libdatasource/include/datasource/HTTPBase.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 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 HTTP_BASE_H_
+
+#define HTTP_BASE_H_
+
+#include <media/DataSource.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct HTTPBase : public DataSource {
+    enum Flags {
+        // Don't log any URLs.
+        kFlagIncognito = 1
+    };
+
+    HTTPBase();
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off64_t offset = 0) = 0;
+
+    virtual void disconnect() = 0;
+
+    // Returns true if bandwidth could successfully be estimated,
+    // false otherwise.
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+    virtual status_t getEstimatedBandwidthKbps(int32_t *kbps);
+
+    virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
+
+    virtual void setBandwidthHistorySize(size_t numHistoryItems);
+
+    virtual String8 toString() {
+        return mName;
+    }
+
+protected:
+    virtual void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+    String8 mName;
+
+private:
+    struct BandwidthEntry {
+        int64_t mDelayUs;
+        size_t mNumBytes;
+    };
+
+    Mutex mLock;
+
+    List<BandwidthEntry> mBandwidthHistory;
+    size_t mNumBandwidthHistoryItems;
+    int64_t mTotalTransferTimeUs;
+    size_t mTotalTransferBytes;
+    size_t mMaxBandwidthHistoryItems;
+
+    enum {
+        kMinBandwidthCollectFreqMs = 1000,   // 1 second
+        kMaxBandwidthCollectFreqMs = 60000,  // one minute
+    };
+
+    int64_t mPrevBandwidthMeasureTimeUs;
+    int32_t mPrevEstimatedBandWidthKbps;
+    int32_t mBandWidthCollectFreqMs;
+
+    DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
+};
+
+}  // namespace android
+
+#endif  // HTTP_BASE_H_
diff --git a/media/libdatasource/include/datasource/MediaHTTP.h b/media/libdatasource/include/datasource/MediaHTTP.h
new file mode 100644
index 0000000..a8d203b
--- /dev/null
+++ b/media/libdatasource/include/datasource/MediaHTTP.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 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 MEDIA_HTTP_H_
+
+#define MEDIA_HTTP_H_
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+struct MediaHTTPConnection;
+
+struct MediaHTTP : public HTTPBase {
+    MediaHTTP(const sp<MediaHTTPConnection> &conn);
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    virtual void close();
+
+    virtual void disconnect();
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+    virtual status_t getSize(off64_t *size);
+
+    virtual uint32_t flags();
+
+    virtual status_t reconnectAtOffset(off64_t offset);
+
+protected:
+    virtual ~MediaHTTP();
+
+    virtual String8 getUri();
+    virtual String8 getMIMEType() const;
+
+    AString mLastURI;
+
+private:
+    status_t mInitCheck;
+    sp<MediaHTTPConnection> mHTTPConnection;
+
+    KeyedVector<String8, String8> mLastHeaders;
+
+    bool mCachedSizeValid;
+    off64_t mCachedSize;
+
+    DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_HTTP_H_
diff --git a/media/libdatasource/include/datasource/NuCachedSource2.h b/media/libdatasource/include/datasource/NuCachedSource2.h
new file mode 100644
index 0000000..4c253ad
--- /dev/null
+++ b/media/libdatasource/include/datasource/NuCachedSource2.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 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 NU_CACHED_SOURCE_2_H_
+
+#define NU_CACHED_SOURCE_2_H_
+
+#include <media/DataSource.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+
+namespace android {
+
+struct ALooper;
+struct PageCache;
+
+struct NuCachedSource2 : public DataSource {
+    static sp<NuCachedSource2> Create(
+            const sp<DataSource> &source,
+            const char *cacheConfig = NULL,
+            bool disconnectAtHighwatermark = false);
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+    virtual void close();
+
+    virtual void disconnect();
+
+    virtual status_t getSize(off64_t *size);
+    virtual uint32_t flags();
+
+    virtual String8 getUri();
+
+    virtual String8 getMIMEType() const;
+
+    virtual String8 toString() {
+        return mName;
+    }
+
+    status_t getAvailableSize(off64_t offset, off64_t *size);
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    size_t cachedSize();
+    size_t approxDataRemaining(status_t *finalStatus) const;
+
+    void resumeFetchingIfNecessary();
+
+    // The following methods are supported only if the
+    // data source is HTTP-based; otherwise, ERROR_UNSUPPORTED
+    // is returned.
+    status_t getEstimatedBandwidthKbps(int32_t *kbps);
+    status_t setCacheStatCollectFreq(int32_t freqMs);
+
+    static void RemoveCacheSpecificHeaders(
+            KeyedVector<String8, String8> *headers,
+            String8 *cacheConfig,
+            bool *disconnectAtHighwatermark);
+
+protected:
+    virtual ~NuCachedSource2();
+
+private:
+    friend struct AHandlerReflector<NuCachedSource2>;
+
+    NuCachedSource2(
+            const sp<DataSource> &source,
+            const char *cacheConfig,
+            bool disconnectAtHighwatermark);
+
+    enum {
+        kPageSize                       = 65536,
+        kDefaultHighWaterThreshold      = 20 * 1024 * 1024,
+        kDefaultLowWaterThreshold       = 4 * 1024 * 1024,
+
+        // Read data after a 15 sec timeout whether we're actively
+        // fetching or not.
+        kDefaultKeepAliveIntervalUs     = 15000000,
+    };
+
+    enum {
+        kWhatFetchMore  = 'fetc',
+        kWhatRead       = 'read',
+    };
+
+    enum {
+        kMaxNumRetries = 10,
+    };
+
+    sp<DataSource> mSource;
+    sp<AHandlerReflector<NuCachedSource2> > mReflector;
+    sp<ALooper> mLooper;
+    String8 mName;
+
+    Mutex mSerializer;
+    mutable Mutex mLock;
+    Condition mCondition;
+
+    PageCache *mCache;
+    off64_t mCacheOffset;
+    status_t mFinalStatus;
+    off64_t mLastAccessPos;
+    sp<AMessage> mAsyncResult;
+    bool mFetching;
+    bool mDisconnecting;
+    int64_t mLastFetchTimeUs;
+
+    int32_t mNumRetriesLeft;
+
+    size_t mHighwaterThresholdBytes;
+    size_t mLowwaterThresholdBytes;
+
+    // If the keep-alive interval is 0, keep-alives are disabled.
+    int64_t mKeepAliveIntervalUs;
+
+    bool mDisconnectAtHighwatermark;
+
+    void onMessageReceived(const sp<AMessage> &msg);
+    void onFetch();
+    void onRead(const sp<AMessage> &msg);
+
+    void fetchInternal();
+    ssize_t readInternal(off64_t offset, void *data, size_t size);
+    status_t seekInternal_l(off64_t offset);
+
+    size_t approxDataRemaining_l(off64_t offset, status_t *finalStatus) const;
+
+    void restartPrefetcherIfNecessary_l(
+            bool ignoreLowWaterThreshold = false, bool force = false);
+
+    void updateCacheParamsFromSystemProperty();
+    void updateCacheParamsFromString(const char *s);
+
+    DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
+};
+
+}  // namespace android
+
+#endif  // NU_CACHED_SOURCE_2_H_
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
index 5fa9da9..8493e30 100644
--- a/media/libeffects/config/Android.bp
+++ b/media/libeffects/config/Android.bp
@@ -13,6 +13,9 @@
     shared_libs: [
         "liblog",
         "libtinyxml2",
+        "libutils",
+        "libmedia_helper",
+        "libcutils",
     ],
 
     header_libs: ["libaudio_system_headers"],
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index fa0415b..57d4dd7 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -35,11 +35,6 @@
 /** Default path of effect configuration file. Relative to DEFAULT_LOCATIONS. */
 constexpr const char* DEFAULT_NAME = "audio_effects.xml";
 
-/** Default path of effect configuration file.
- * The /vendor partition is the recommended one, the others are deprecated.
- */
-constexpr const char* DEFAULT_LOCATIONS[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
-
 /** Directories where the effect libraries will be search for. */
 constexpr const char* LD_EFFECT_LIBRARY_PATH[] =
 #ifdef __LP64__
@@ -76,6 +71,10 @@
 using OutputStream = Stream<audio_stream_type_t>;
 using InputStream = Stream<audio_source_t>;
 
+struct DeviceEffects : Stream<audio_devices_t> {
+    std::string address;
+};
+
 /** Parsed configuration.
  * Intended to be a transient structure only used for deserialization.
  * Note: Everything is copied in the configuration from the xml dom.
@@ -89,6 +88,7 @@
     Effects effects;
     std::vector<OutputStream> postprocess;
     std::vector<InputStream> preprocess;
+    std::vector<DeviceEffects> deviceprocess;
 };
 
 /** Result of `parse(const char*)` */
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index f39eb0c..26eaaf8 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -26,6 +26,8 @@
 #include <log/log.h>
 
 #include <media/EffectsConfig.h>
+#include <media/TypeConverter.h>
+#include <system/audio_config.h>
 
 using namespace tinyxml2;
 
@@ -100,6 +102,7 @@
         {AUDIO_STREAM_ENFORCED_AUDIBLE, "enforced_audible"},
         {AUDIO_STREAM_DTMF, "dtmf"},
         {AUDIO_STREAM_TTS, "tts"},
+        {AUDIO_STREAM_ASSISTANT, "assistant"},
 };
 
 /** All input stream types which support effects.
@@ -116,6 +119,8 @@
         {AUDIO_SOURCE_VOICE_COMMUNICATION, "voice_communication"},
         {AUDIO_SOURCE_UNPROCESSED, "unprocessed"},
         {AUDIO_SOURCE_VOICE_PERFORMANCE, "voice_performance"},
+        {AUDIO_SOURCE_ECHO_REFERENCE, "echo_reference"},
+        {AUDIO_SOURCE_FM_TUNER, "fm_tuner"},
 };
 
 /** Find the stream type enum corresponding to the stream type name or return false */
@@ -131,6 +136,11 @@
     return false;
 }
 
+template <>
+bool stringToStreamType(const char *streamName, audio_devices_t* type) {
+    return deviceFromString(streamName, *type);
+}
+
 /** Parse a library xml note and push the result in libraries or return false on failure. */
 bool parseLibrary(const XMLElement& xmlLibrary, Libraries* libraries) {
     const char* name = xmlLibrary.Attribute("name");
@@ -218,7 +228,7 @@
     return true;
 }
 
-/** Parse an stream from an xml element describing it.
+/** Parse an <Output|Input>stream or a device from an xml element describing it.
  * @return true and pushes the stream in streams on success,
  *         false on failure. */
 template <class Stream>
@@ -230,14 +240,14 @@
     }
     Stream stream;
     if (!stringToStreamType(streamType, &stream.type)) {
-        ALOGE("Invalid stream type %s: %s", streamType, dump(xmlStream));
+        ALOGE("Invalid <stream|device> type %s: %s", streamType, dump(xmlStream));
         return false;
     }
 
     for (auto& xmlApply : getChildren(xmlStream, "apply")) {
         const char* effectName = xmlApply.get().Attribute("effect");
         if (effectName == nullptr) {
-            ALOGE("stream/apply must have reference an effect: %s", dump(xmlApply));
+            ALOGE("<stream|device>/apply must have reference an effect: %s", dump(xmlApply));
             return false;
         }
         auto* effect = findByName(effectName, effects);
@@ -251,6 +261,21 @@
     return true;
 }
 
+bool parseDeviceEffects(
+        const XMLElement& xmlDevice, Effects& effects, std::vector<DeviceEffects>* deviceEffects) {
+
+    const char* address = xmlDevice.Attribute("address");
+    if (address == nullptr) {
+        ALOGE("device must have an address: %s", dump(xmlDevice));
+        return false;
+    }
+    if (!parseStream(xmlDevice, effects, deviceEffects)) {
+        return false;
+    }
+    deviceEffects->back().address = address;
+    return true;
+}
+
 /** Internal version of the public parse(const char* path) where path always exist. */
 ParsingResult parseWithPath(std::string&& path) {
     XMLDocument doc;
@@ -295,6 +320,14 @@
                 registerFailure(parseStream(xmlStream, config->effects, &config->postprocess));
             }
         }
+
+        // Parse device effect chains
+        for (auto& xmlDeviceEffects : getChildren(xmlConfig, "deviceEffects")) {
+            for (auto& xmlDevice : getChildren(xmlDeviceEffects, "devicePort")) {
+                registerFailure(
+                            parseDeviceEffects(xmlDevice, config->effects, &config->deviceprocess));
+            }
+        }
     }
     return {std::move(config), nbSkippedElements, std::move(path)};
 }
@@ -306,7 +339,7 @@
         return parseWithPath(path);
     }
 
-    for (const std::string& location : DEFAULT_LOCATIONS) {
+    for (const std::string& location : audio_get_configuration_paths()) {
         std::string defaultPath = location + '/' + DEFAULT_NAME;
         if (access(defaultPath.c_str(), R_OK) != 0) {
             continue;
diff --git a/media/libeffects/data/audio_effects.xml b/media/libeffects/data/audio_effects.xml
index 3f85052..2e5f529 100644
--- a/media/libeffects/data/audio_effects.xml
+++ b/media/libeffects/data/audio_effects.xml
@@ -99,4 +99,31 @@
         </postprocess>
     -->
 
+     <!-- Device pre/post processor configurations.
+          The device pre/post processor configuration is described in a deviceEffects element and
+          consists in a list of elements each describing pre/post proecessor settings for a given
+          device or "devicePort".
+          Each devicePort element has a "type" attribute corresponding to the device type (e.g.
+          speaker, bus), an "address" attribute corresponding to the device address and contains a
+          list of "apply" elements indicating one effect to apply.
+          If the device is a source, only pre processing effects are expected, if the
+          device is a sink, only post processing effects are expected.
+          The effect to apply is designated by its name in the "effects" elements.
+          The effect will be enabled by default and the audio framework will automatically add
+          and activate the effect if the given port is involved in an audio patch.
+          If the patch is "HW", the effect must be HW accelerated.
+
+        <deviceEffects>
+            <devicePort type="AUDIO_DEVICE_OUT_BUS" address="BUS00_USAGE_MAIN">
+                <apply effect="equalizer"/>
+            </devicePort>
+            <devicePort type="AUDIO_DEVICE_OUT_BUS" address="BUS04_USAGE_VOICE">
+                <apply effect="volume"/>
+            </devicePort>
+            <devicePort type="AUDIO_DEVICE_IN_BUILTIN_MIC" address="bottom">
+                <apply effect="agc"/>
+            </devicePort>
+        </deviceEffects>
+    -->
+
 </audio_effects_conf>
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 9c82b1d..2a2f36e 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -6,6 +6,7 @@
     srcs: ["EffectDownmix.c"],
 
     shared_libs: [
+        "libaudioutils",
         "libcutils",
         "liblog",
     ],
@@ -23,5 +24,4 @@
         "libaudioeffects",
         "libhardware_headers",
     ],
-    static_libs: ["libaudioutils" ],
 }
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index c1ce513..dcdf634 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -254,7 +254,8 @@
     return ret;
 }
 
-int EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle)
+int doEffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, int32_t deviceId,
+        effect_handle_t *pHandle)
 {
     list_elem_t *e = gLibraryList;
     lib_entry_t *l = NULL;
@@ -268,9 +269,9 @@
     }
 
     ALOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
-            uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
-            uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
-            uuid->node[3],uuid->node[4],uuid->node[5]);
+          uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
+          uuid->clockSeq, uuid->node[0], uuid->node[1], uuid->node[2],
+          uuid->node[3], uuid->node[4], uuid->node[5]);
 
     ret = init();
 
@@ -282,17 +283,29 @@
     pthread_mutex_lock(&gLibLock);
 
     ret = findEffect(NULL, uuid, &l, &d);
-    if (ret < 0){
+    if (ret < 0) {
         // Sub effects are not associated with the library->effects,
         // so, findEffect will fail. Search for the effect in gSubEffectList.
         ret = findSubEffect(uuid, &l, &d);
-        if (ret < 0 ) {
+        if (ret < 0) {
             goto exit;
         }
     }
 
     // create effect in library
-    ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe);
+    if (sessionId == AUDIO_SESSION_DEVICE) {
+        if (l->desc->version >= EFFECT_LIBRARY_API_VERSION_3_1) {
+            ALOGI("EffectCreate() create_effect_3_1");
+            ret = l->desc->create_effect_3_1(uuid, sessionId, ioId, deviceId, &itfe);
+        } else {
+            ALOGE("EffectCreate() cannot create device effect on library with API version < 3.1");
+            ret = -ENOSYS;
+        }
+    } else {
+        ALOGI("EffectCreate() create_effect");
+        ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe);
+    }
+
     if (ret != 0) {
         ALOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret);
         goto exit;
@@ -324,6 +337,16 @@
     return ret;
 }
 
+int EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId,
+        effect_handle_t *pHandle) {
+    return doEffectCreate(uuid, sessionId, ioId, AUDIO_PORT_HANDLE_NONE, pHandle);
+}
+
+int EffectCreateOnDevice(const effect_uuid_t *uuid, int32_t deviceId, int32_t ioId,
+        effect_handle_t *pHandle) {
+    return doEffectCreate(uuid, AUDIO_SESSION_DEVICE, ioId, deviceId, pHandle);
+}
+
 int EffectRelease(effect_handle_t handle)
 {
     effect_entry_t *fx;
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index 29dbc9c..1936343 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -27,6 +27,8 @@
 extern "C" {
 #endif
 
+#define EFFECT_LIBRARY_API_VERSION_CURRENT EFFECT_LIBRARY_API_VERSION_3_1
+
 #define PROPERTY_IGNORE_EFFECTS "ro.audio.ignore_effects"
 
 typedef struct list_elem_s {
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 052a88b..505be7c 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -94,7 +94,7 @@
     }
 
     uint32_t majorVersion = EFFECT_API_VERSION_MAJOR(description->version);
-    uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION);
+    uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION_CURRENT);
     if (majorVersion != expectedMajorVersion) {
         ALOGE("Unsupported major version %#08x, expected %#08x for library %s",
               majorVersion, expectedMajorVersion, path);
diff --git a/media/libeffects/factory/include/media/EffectsFactoryApi.h b/media/libeffects/factory/include/media/EffectsFactoryApi.h
index a5a12eb..8f7239e 100644
--- a/media/libeffects/factory/include/media/EffectsFactoryApi.h
+++ b/media/libeffects/factory/include/media/EffectsFactoryApi.h
@@ -119,6 +119,36 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 //
+//    Function:       EffectCreateOnDevice
+//
+//    Description:    Same as EffectCreate but uesed when creating an effect attached to a
+//                 particular audio device instance
+//
+//    Input:
+//          pEffectUuid:    pointer to the effect uuid.
+//          deviceId:  identifies the sink or source device this effect is directed to in
+//              audio HAL. Must be specified if sessionId is AUDIO_SESSION_DEVICE.
+//              deviceId is the audio_port_handle_t used for the device when the audio
+//              patch is created at the audio HAL.//
+//          ioId:   identifies the output or input stream this effect is directed to at audio HAL.
+//              For future use especially with tunneled HW accelerated effects
+//    Input/Output:
+//          pHandle:        address where to return the effect handle.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pHandle
+//                          -ENOENT     no effect with this uuid found
+//        *pHandle:         updated with the effect handle.
+//
+////////////////////////////////////////////////////////////////////////////////
+ANDROID_API
+int EffectCreateOnDevice(const effect_uuid_t *pEffectUuid, int32_t deviceId, int32_t ioId,
+        effect_handle_t *pHandle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
 //    Function:       EffectRelease
 //
 //    Description:    Releases the effect engine whose handle is given as argument.
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index d150f18..1f2a5e1 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -10,107 +10,107 @@
 
     vendor: true,
     srcs: [
-        "StereoWidening/src/LVCS_BypassMix.c",
-        "StereoWidening/src/LVCS_Control.c",
-        "StereoWidening/src/LVCS_Equaliser.c",
-        "StereoWidening/src/LVCS_Init.c",
-        "StereoWidening/src/LVCS_Process.c",
-        "StereoWidening/src/LVCS_ReverbGenerator.c",
-        "StereoWidening/src/LVCS_StereoEnhancer.c",
-        "StereoWidening/src/LVCS_Tables.c",
-        "Bass/src/LVDBE_Control.c",
-        "Bass/src/LVDBE_Init.c",
-        "Bass/src/LVDBE_Process.c",
-        "Bass/src/LVDBE_Tables.c",
-        "Bundle/src/LVM_API_Specials.c",
-        "Bundle/src/LVM_Buffers.c",
-        "Bundle/src/LVM_Init.c",
-        "Bundle/src/LVM_Process.c",
-        "Bundle/src/LVM_Tables.c",
-        "Bundle/src/LVM_Control.c",
-        "SpectrumAnalyzer/src/LVPSA_Control.c",
-        "SpectrumAnalyzer/src/LVPSA_Init.c",
-        "SpectrumAnalyzer/src/LVPSA_Memory.c",
-        "SpectrumAnalyzer/src/LVPSA_Process.c",
-        "SpectrumAnalyzer/src/LVPSA_QPD_Init.c",
-        "SpectrumAnalyzer/src/LVPSA_QPD_Process.c",
-        "SpectrumAnalyzer/src/LVPSA_Tables.c",
-        "Eq/src/LVEQNB_CalcCoef.c",
-        "Eq/src/LVEQNB_Control.c",
-        "Eq/src/LVEQNB_Init.c",
-        "Eq/src/LVEQNB_Process.c",
-        "Eq/src/LVEQNB_Tables.c",
-        "Common/src/InstAlloc.c",
-        "Common/src/DC_2I_D16_TRC_WRA_01.c",
-        "Common/src/DC_2I_D16_TRC_WRA_01_Init.c",
-        "Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c",
-        "Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c",
-        "Common/src/FO_1I_D16F16C15_TRC_WRA_01.c",
-        "Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c",
-        "Common/src/BP_1I_D16F32C30_TRC_WRA_01.c",
-        "Common/src/BP_1I_D16F16C14_TRC_WRA_01.c",
-        "Common/src/BP_1I_D32F32C30_TRC_WRA_02.c",
-        "Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c",
-        "Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c",
-        "Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c",
-        "Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c",
-        "Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c",
-        "Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c",
-        "Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c",
-        "Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c",
-        "Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c",
-        "Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c",
-        "Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c",
-        "Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c",
-        "Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c",
-        "Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c",
-        "Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c",
-        "Common/src/Int16LShiftToInt32_16x32.c",
-        "Common/src/From2iToMono_16.c",
-        "Common/src/Copy_16.c",
-        "Common/src/MonoTo2I_16.c",
-        "Common/src/MonoTo2I_32.c",
-        "Common/src/LoadConst_16.c",
-        "Common/src/LoadConst_32.c",
-        "Common/src/dB_to_Lin32.c",
-        "Common/src/Shift_Sat_v16xv16.c",
-        "Common/src/Shift_Sat_v32xv32.c",
-        "Common/src/Abs_32.c",
-        "Common/src/Int32RShiftToInt16_Sat_32x16.c",
-        "Common/src/From2iToMono_32.c",
-        "Common/src/mult3s_16x16.c",
-        "Common/src/Mult3s_32x16.c",
-        "Common/src/NonLinComp_D16.c",
-        "Common/src/DelayMix_16x16.c",
-        "Common/src/MSTo2i_Sat_16x16.c",
-        "Common/src/From2iToMS_16x16.c",
-        "Common/src/Mac3s_Sat_16x16.c",
-        "Common/src/Mac3s_Sat_32x16.c",
-        "Common/src/Add2_Sat_16x16.c",
-        "Common/src/Add2_Sat_32x32.c",
-        "Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c",
-        "Common/src/LVC_MixSoft_1St_D16C31_SAT.c",
-        "Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c",
-        "Common/src/LVC_Mixer_SetTimeConstant.c",
-        "Common/src/LVC_Mixer_SetTarget.c",
-        "Common/src/LVC_Mixer_GetTarget.c",
-        "Common/src/LVC_Mixer_Init.c",
-        "Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c",
-        "Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c",
-        "Common/src/LVC_Core_MixInSoft_D16C31_SAT.c",
-        "Common/src/LVC_Mixer_GetCurrent.c",
-        "Common/src/LVC_MixSoft_2St_D16C31_SAT.c",
-        "Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c",
-        "Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c",
-        "Common/src/LVC_MixInSoft_D16C31_SAT.c",
-        "Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c",
-        "Common/src/LVM_Timer.c",
-        "Common/src/LVM_Timer_Init.c",
+        "StereoWidening/src/LVCS_BypassMix.cpp",
+        "StereoWidening/src/LVCS_Control.cpp",
+        "StereoWidening/src/LVCS_Equaliser.cpp",
+        "StereoWidening/src/LVCS_Init.cpp",
+        "StereoWidening/src/LVCS_Process.cpp",
+        "StereoWidening/src/LVCS_ReverbGenerator.cpp",
+        "StereoWidening/src/LVCS_StereoEnhancer.cpp",
+        "StereoWidening/src/LVCS_Tables.cpp",
+        "Bass/src/LVDBE_Control.cpp",
+        "Bass/src/LVDBE_Init.cpp",
+        "Bass/src/LVDBE_Process.cpp",
+        "Bass/src/LVDBE_Tables.cpp",
+        "Bundle/src/LVM_API_Specials.cpp",
+        "Bundle/src/LVM_Buffers.cpp",
+        "Bundle/src/LVM_Init.cpp",
+        "Bundle/src/LVM_Process.cpp",
+        "Bundle/src/LVM_Tables.cpp",
+        "Bundle/src/LVM_Control.cpp",
+        "SpectrumAnalyzer/src/LVPSA_Control.cpp",
+        "SpectrumAnalyzer/src/LVPSA_Init.cpp",
+        "SpectrumAnalyzer/src/LVPSA_Memory.cpp",
+        "SpectrumAnalyzer/src/LVPSA_Process.cpp",
+        "SpectrumAnalyzer/src/LVPSA_QPD_Init.cpp",
+        "SpectrumAnalyzer/src/LVPSA_QPD_Process.cpp",
+        "SpectrumAnalyzer/src/LVPSA_Tables.cpp",
+        "Eq/src/LVEQNB_CalcCoef.cpp",
+        "Eq/src/LVEQNB_Control.cpp",
+        "Eq/src/LVEQNB_Init.cpp",
+        "Eq/src/LVEQNB_Process.cpp",
+        "Eq/src/LVEQNB_Tables.cpp",
+        "Common/src/InstAlloc.cpp",
+        "Common/src/DC_2I_D16_TRC_WRA_01.cpp",
+        "Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp",
+        "Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp",
+        "Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp",
+        "Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp",
+        "Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp",
+        "Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp",
+        "Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp",
+        "Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp",
+        "Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp",
+        "Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp",
+        "Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp",
+        "Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp",
+        "Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp",
+        "Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp",
+        "Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp",
+        "Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp",
+        "Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp",
+        "Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp",
+        "Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp",
+        "Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp",
+        "Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp",
+        "Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp",
+        "Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp",
+        "Common/src/Int16LShiftToInt32_16x32.cpp",
+        "Common/src/From2iToMono_16.cpp",
+        "Common/src/Copy_16.cpp",
+        "Common/src/MonoTo2I_16.cpp",
+        "Common/src/MonoTo2I_32.cpp",
+        "Common/src/LoadConst_16.cpp",
+        "Common/src/LoadConst_32.cpp",
+        "Common/src/dB_to_Lin32.cpp",
+        "Common/src/Shift_Sat_v16xv16.cpp",
+        "Common/src/Shift_Sat_v32xv32.cpp",
+        "Common/src/Abs_32.cpp",
+        "Common/src/Int32RShiftToInt16_Sat_32x16.cpp",
+        "Common/src/From2iToMono_32.cpp",
+        "Common/src/mult3s_16x16.cpp",
+        "Common/src/Mult3s_32x16.cpp",
+        "Common/src/NonLinComp_D16.cpp",
+        "Common/src/DelayMix_16x16.cpp",
+        "Common/src/MSTo2i_Sat_16x16.cpp",
+        "Common/src/From2iToMS_16x16.cpp",
+        "Common/src/Mac3s_Sat_16x16.cpp",
+        "Common/src/Mac3s_Sat_32x16.cpp",
+        "Common/src/Add2_Sat_16x16.cpp",
+        "Common/src/Add2_Sat_32x32.cpp",
+        "Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp",
+        "Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp",
+        "Common/src/LVC_Mixer_VarSlope_SetTimeConstant.cpp",
+        "Common/src/LVC_Mixer_SetTimeConstant.cpp",
+        "Common/src/LVC_Mixer_SetTarget.cpp",
+        "Common/src/LVC_Mixer_GetTarget.cpp",
+        "Common/src/LVC_Mixer_Init.cpp",
+        "Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp",
+        "Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp",
+        "Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp",
+        "Common/src/LVC_Mixer_GetCurrent.cpp",
+        "Common/src/LVC_MixSoft_2St_D16C31_SAT.cpp",
+        "Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp",
+        "Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp",
+        "Common/src/LVC_MixInSoft_D16C31_SAT.cpp",
+        "Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp",
+        "Common/src/LVM_Timer.cpp",
+        "Common/src/LVM_Timer_Init.cpp",
     ],
 
     local_include_dirs: [
@@ -135,10 +135,8 @@
     header_libs: [
         "libhardware_headers"
     ],
-    cflags: [
+    cppflags: [
         "-fvisibility=hidden",
-        "-DBUILD_FLOAT",
-        "-DHIGHER_FS",
         "-DSUPPORT_MC",
 
         "-Wall",
@@ -159,42 +157,42 @@
 
     vendor: true,
     srcs: [
-        "Reverb/src/LVREV_ApplyNewSettings.c",
-        "Reverb/src/LVREV_ClearAudioBuffers.c",
-        "Reverb/src/LVREV_GetControlParameters.c",
-        "Reverb/src/LVREV_GetInstanceHandle.c",
-        "Reverb/src/LVREV_GetMemoryTable.c",
-        "Reverb/src/LVREV_Process.c",
-        "Reverb/src/LVREV_SetControlParameters.c",
-        "Reverb/src/LVREV_Tables.c",
-        "Common/src/Abs_32.c",
-        "Common/src/InstAlloc.c",
-        "Common/src/LoadConst_16.c",
-        "Common/src/LoadConst_32.c",
-        "Common/src/From2iToMono_32.c",
-        "Common/src/Mult3s_32x16.c",
-        "Common/src/FO_1I_D32F32C31_TRC_WRA_01.c",
-        "Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c",
-        "Common/src/DelayAllPass_Sat_32x16To32.c",
-        "Common/src/Copy_16.c",
-        "Common/src/Mac3s_Sat_32x16.c",
-        "Common/src/DelayWrite_32.c",
-        "Common/src/Shift_Sat_v32xv32.c",
-        "Common/src/Add2_Sat_32x32.c",
-        "Common/src/JoinTo2i_32x32.c",
-        "Common/src/MonoTo2I_32.c",
-        "Common/src/LVM_FO_HPF.c",
-        "Common/src/LVM_FO_LPF.c",
-        "Common/src/LVM_Polynomial.c",
-        "Common/src/LVM_Power10.c",
-        "Common/src/LVM_GetOmega.c",
-        "Common/src/MixSoft_2St_D32C31_SAT.c",
-        "Common/src/MixSoft_1St_D32C31_WRA.c",
-        "Common/src/MixInSoft_D32C31_SAT.c",
-        "Common/src/LVM_Mixer_TimeConstant.c",
-        "Common/src/Core_MixHard_2St_D32C31_SAT.c",
-        "Common/src/Core_MixSoft_1St_D32C31_WRA.c",
-        "Common/src/Core_MixInSoft_D32C31_SAT.c",
+        "Reverb/src/LVREV_ApplyNewSettings.cpp",
+        "Reverb/src/LVREV_ClearAudioBuffers.cpp",
+        "Reverb/src/LVREV_GetControlParameters.cpp",
+        "Reverb/src/LVREV_GetInstanceHandle.cpp",
+        "Reverb/src/LVREV_GetMemoryTable.cpp",
+        "Reverb/src/LVREV_Process.cpp",
+        "Reverb/src/LVREV_SetControlParameters.cpp",
+        "Reverb/src/LVREV_Tables.cpp",
+        "Common/src/Abs_32.cpp",
+        "Common/src/InstAlloc.cpp",
+        "Common/src/LoadConst_16.cpp",
+        "Common/src/LoadConst_32.cpp",
+        "Common/src/From2iToMono_32.cpp",
+        "Common/src/Mult3s_32x16.cpp",
+        "Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp",
+        "Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp",
+        "Common/src/DelayAllPass_Sat_32x16To32.cpp",
+        "Common/src/Copy_16.cpp",
+        "Common/src/Mac3s_Sat_32x16.cpp",
+        "Common/src/DelayWrite_32.cpp",
+        "Common/src/Shift_Sat_v32xv32.cpp",
+        "Common/src/Add2_Sat_32x32.cpp",
+        "Common/src/JoinTo2i_32x32.cpp",
+        "Common/src/MonoTo2I_32.cpp",
+        "Common/src/LVM_FO_HPF.cpp",
+        "Common/src/LVM_FO_LPF.cpp",
+        "Common/src/LVM_Polynomial.cpp",
+        "Common/src/LVM_Power10.cpp",
+        "Common/src/LVM_GetOmega.cpp",
+        "Common/src/MixSoft_2St_D32C31_SAT.cpp",
+        "Common/src/MixSoft_1St_D32C31_WRA.cpp",
+        "Common/src/MixInSoft_D32C31_SAT.cpp",
+        "Common/src/LVM_Mixer_TimeConstant.cpp",
+        "Common/src/Core_MixHard_2St_D32C31_SAT.cpp",
+        "Common/src/Core_MixSoft_1St_D32C31_WRA.cpp",
+        "Common/src/Core_MixInSoft_D32C31_SAT.cpp",
     ],
 
     local_include_dirs: [
@@ -206,10 +204,8 @@
         "Common/lib",
     ],
 
-    cflags: [
+    cppflags: [
         "-fvisibility=hidden",
-        "-DBUILD_FLOAT",
-        "-DHIGHER_FS",
 
         "-Wall",
         "-Werror",
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
index cc066b0..948d79c 100644
--- a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -55,11 +55,6 @@
 #ifndef __LVDBE_H__
 #define __LVDBE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Includes                                                                          */
@@ -68,7 +63,6 @@
 
 #include "LVM_Types.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Definitions                                                                       */
@@ -85,7 +79,6 @@
 #define LVDBE_EFFECT_12DB            12
 #define LVDBE_EFFECT_15DB            15
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Types                                                                             */
@@ -95,7 +88,6 @@
 /* Instance handle */
 typedef void    *LVDBE_Handle_t;
 
-
 /* Operating modes */
 typedef enum
 {
@@ -104,7 +96,6 @@
     LVDBE_MODE_MAX = LVM_MAXINT_32
 } LVDBE_Mode_en;
 
-
 /* High pass filter */
 typedef enum
 {
@@ -113,7 +104,6 @@
     LVDBE_HPF_MAX = LVM_MAXINT_32
 } LVDBE_FilterSelect_en;
 
-
 /* Volume control */
 typedef enum
 {
@@ -122,7 +112,6 @@
     LVDBE_VOLUME_MAX = LVM_MAXINT_32
 } LVDBE_Volume_en;
 
-
 /* Memory Types */
 typedef enum
 {
@@ -134,7 +123,6 @@
 
 } LVDBE_MemoryTypes_en;
 
-
 /* Function return status */
 typedef enum
 {
@@ -146,7 +134,6 @@
     LVDBE_STATUS_MAX     = LVM_MAXINT_32
 } LVDBE_ReturnStatus_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Linked enumerated type and capability definitions                                 */
@@ -185,7 +172,6 @@
     LVDBE_CENTRE_MAX  = LVM_MAXINT_32
 } LVDBE_CentreFreq_en;
 
-
 /*
  * Supported sample rates in samples per second
  */
@@ -198,12 +184,10 @@
 #define LVDBE_CAP_FS_32000               64
 #define LVDBE_CAP_FS_44100               128
 #define LVDBE_CAP_FS_48000               256
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
 #define LVDBE_CAP_FS_88200               512
 #define LVDBE_CAP_FS_96000               1024
 #define LVDBE_CAP_FS_176400              2048
 #define LVDBE_CAP_FS_192000              4096
-#endif
 
 typedef enum
 {
@@ -216,16 +200,13 @@
     LVDBE_FS_32000 = 6,
     LVDBE_FS_44100 = 7,
     LVDBE_FS_48000 = 8,
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
     LVDBE_FS_88200 = 9,
     LVDBE_FS_96000 = 10,
     LVDBE_FS_176400 = 11,
     LVDBE_FS_192000 = 12,
-#endif
     LVDBE_FS_MAX   = LVM_MAXINT_32
 } LVDBE_Fs_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Structures                                                                        */
@@ -241,14 +222,12 @@
     void                      *pBaseAddress;              /* Pointer to the region base address */
 } LVDBE_MemoryRegion_t;
 
-
 /* Memory table containing the region definitions */
 typedef struct
 {
     LVDBE_MemoryRegion_t    Region[LVDBE_NR_MEMORY_REGIONS];  /* One definition for each region */
 } LVDBE_MemTab_t;
 
-
 /* Parameter structure */
 typedef struct
 {
@@ -266,7 +245,6 @@
 
 } LVDBE_Params_t;
 
-
 /* Capability structure */
 typedef struct
 {
@@ -275,7 +253,6 @@
       LVM_UINT16              MaxBlockSize;             /* Maximum block size in sample pairs */
 } LVDBE_Capabilities_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Function Prototypes                                                               */
@@ -317,7 +294,6 @@
                                    LVDBE_MemTab_t           *pMemoryTable,
                                    LVDBE_Capabilities_t     *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVDBE_Init                                                 */
@@ -355,7 +331,6 @@
                                    LVDBE_MemTab_t           *pMemoryTable,
                                    LVDBE_Capabilities_t     *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                  LVDBE_GetParameters                                       */
@@ -379,7 +354,6 @@
 LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
                                             LVDBE_Params_t      *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                  LVDBE_GetCapabilities                                     */
@@ -403,7 +377,6 @@
 LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
                                               LVDBE_Capabilities_t    *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVDBE_Control                                               */
@@ -444,7 +417,6 @@
 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t      hInstance,
                                       LVDBE_Params_t    *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVDBE_Process                                              */
@@ -465,20 +437,9 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t          hInstance,
                                        const LVM_FLOAT      *pInData,
                                        LVM_FLOAT            *pOutData,
                                        LVM_UINT16           NumSamples);
-#else
-LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t          hInstance,
-                                       const LVM_INT16      *pInData,
-                                       LVM_INT16            *pOutData,
-                                       LVM_UINT16           NumSamples);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif /* __LVDBE_H__ */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
index 8f058e8..b364dae 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
@@ -18,8 +18,6 @@
 #ifndef __LVDBE_COEFFS_H__
 #define __LVDBE_COEFFS_H__
 
-
-#ifndef BUILD_FLOAT
 /************************************************************************************/
 /*                                                                                  */
 /* General                                                                          */
@@ -28,504 +26,6 @@
 
 #define LVDBE_SCALESHIFT                                    10         /* As a power of 2 */
 
-
-/************************************************************************************/
-/*                                                                                  */
-/* High Pass Filter coefficients                                                    */
-/*                                                                                  */
-/************************************************************************************/
-
- /* Coefficients for centre frequency 55Hz */
-#define HPF_Fs8000_Fc55_A0                         1029556328         /* Floating point value 0.958849 */
-#define HPF_Fs8000_Fc55_A1                       (-2059112655)        /* Floating point value -1.917698 */
-#define HPF_Fs8000_Fc55_A2                         1029556328         /* Floating point value 0.958849 */
-#define HPF_Fs8000_Fc55_B1                       (-2081986375)        /* Floating point value -1.939001 */
-#define HPF_Fs8000_Fc55_B2                         1010183914         /* Floating point value 0.940807 */
-#define HPF_Fs11025_Fc55_A0                        1038210831         /* Floating point value 0.966909 */
-#define HPF_Fs11025_Fc55_A1                      (-2076421662)        /* Floating point value -1.933818 */
-#define HPF_Fs11025_Fc55_A2                        1038210831         /* Floating point value 0.966909 */
-#define HPF_Fs11025_Fc55_B1                      (-2099950710)        /* Floating point value -1.955732 */
-#define HPF_Fs11025_Fc55_B2                        1027238450         /* Floating point value 0.956690 */
-#define HPF_Fs12000_Fc55_A0                        1040079943         /* Floating point value 0.968650 */
-#define HPF_Fs12000_Fc55_A1                      (-2080159885)        /* Floating point value -1.937300 */
-#define HPF_Fs12000_Fc55_A2                        1040079943         /* Floating point value 0.968650 */
-#define HPF_Fs12000_Fc55_B1                      (-2103811702)        /* Floating point value -1.959327 */
-#define HPF_Fs12000_Fc55_B2                        1030940477         /* Floating point value 0.960138 */
-#define HPF_Fs16000_Fc55_A0                        1045381988         /* Floating point value 0.973588 */
-#define HPF_Fs16000_Fc55_A1                      (-2090763976)        /* Floating point value -1.947176 */
-#define HPF_Fs16000_Fc55_A2                        1045381988         /* Floating point value 0.973588 */
-#define HPF_Fs16000_Fc55_B1                      (-2114727793)        /* Floating point value -1.969494 */
-#define HPF_Fs16000_Fc55_B2                        1041478147         /* Floating point value 0.969952 */
-#define HPF_Fs22050_Fc55_A0                        1049766523         /* Floating point value 0.977671 */
-#define HPF_Fs22050_Fc55_A1                      (-2099533046)        /* Floating point value -1.955343 */
-#define HPF_Fs22050_Fc55_A2                        1049766523         /* Floating point value 0.977671 */
-#define HPF_Fs22050_Fc55_B1                      (-2123714381)        /* Floating point value -1.977863 */
-#define HPF_Fs22050_Fc55_B2                        1050232780         /* Floating point value 0.978105 */
-#define HPF_Fs24000_Fc55_A0                        1050711051         /* Floating point value 0.978551 */
-#define HPF_Fs24000_Fc55_A1                      (-2101422103)        /* Floating point value -1.957102 */
-#define HPF_Fs24000_Fc55_A2                        1050711051         /* Floating point value 0.978551 */
-#define HPF_Fs24000_Fc55_B1                      (-2125645498)        /* Floating point value -1.979662 */
-#define HPF_Fs24000_Fc55_B2                        1052123526         /* Floating point value 0.979866 */
-#define HPF_Fs32000_Fc55_A0                        1053385759         /* Floating point value 0.981042 */
-#define HPF_Fs32000_Fc55_A1                      (-2106771519)        /* Floating point value -1.962084 */
-#define HPF_Fs32000_Fc55_A2                        1053385759         /* Floating point value 0.981042 */
-#define HPF_Fs32000_Fc55_B1                      (-2131104794)        /* Floating point value -1.984746 */
-#define HPF_Fs32000_Fc55_B2                        1057486949         /* Floating point value 0.984861 */
-#define HPF_Fs44100_Fc55_A0                        1055592498         /* Floating point value 0.983097 */
-#define HPF_Fs44100_Fc55_A1                      (-2111184995)        /* Floating point value -1.966194 */
-#define HPF_Fs44100_Fc55_A2                        1055592498         /* Floating point value 0.983097 */
-#define HPF_Fs44100_Fc55_B1                      (-2135598658)        /* Floating point value -1.988931 */
-#define HPF_Fs44100_Fc55_B2                        1061922249         /* Floating point value 0.988992 */
-#define HPF_Fs48000_Fc55_A0                        1056067276         /* Floating point value 0.983539 */
-#define HPF_Fs48000_Fc55_A1                      (-2112134551)        /* Floating point value -1.967079 */
-#define HPF_Fs48000_Fc55_A2                        1056067276         /* Floating point value 0.983539 */
-#define HPF_Fs48000_Fc55_B1                      (-2136564296)        /* Floating point value -1.989831 */
-#define HPF_Fs48000_Fc55_B2                        1062877714         /* Floating point value 0.989882 */
-
- /* Coefficients for centre frequency 66Hz */
-#define HPF_Fs8000_Fc66_A0                         1023293271         /* Floating point value 0.953016 */
-#define HPF_Fs8000_Fc66_A1                       (-2046586542)        /* Floating point value -1.906032 */
-#define HPF_Fs8000_Fc66_A2                         1023293271         /* Floating point value 0.953016 */
-#define HPF_Fs8000_Fc66_B1                       (-2068896860)        /* Floating point value -1.926810 */
-#define HPF_Fs8000_Fc66_B2                          997931110         /* Floating point value 0.929396 */
-#define HPF_Fs11025_Fc66_A0                        1033624228         /* Floating point value 0.962638 */
-#define HPF_Fs11025_Fc66_A1                      (-2067248455)        /* Floating point value -1.925275 */
-#define HPF_Fs11025_Fc66_A2                        1033624228         /* Floating point value 0.962638 */
-#define HPF_Fs11025_Fc66_B1                      (-2090448000)        /* Floating point value -1.946881 */
-#define HPF_Fs11025_Fc66_B2                        1018182305         /* Floating point value 0.948256 */
-#define HPF_Fs12000_Fc66_A0                        1035857662         /* Floating point value 0.964718 */
-#define HPF_Fs12000_Fc66_A1                      (-2071715325)        /* Floating point value -1.929435 */
-#define HPF_Fs12000_Fc66_A2                        1035857662         /* Floating point value 0.964718 */
-#define HPF_Fs12000_Fc66_B1                      (-2095080333)        /* Floating point value -1.951196 */
-#define HPF_Fs12000_Fc66_B2                        1022587158         /* Floating point value 0.952359 */
-#define HPF_Fs16000_Fc66_A0                        1042197528         /* Floating point value 0.970622 */
-#define HPF_Fs16000_Fc66_A1                      (-2084395056)        /* Floating point value -1.941244 */
-#define HPF_Fs16000_Fc66_A2                        1042197528         /* Floating point value 0.970622 */
-#define HPF_Fs16000_Fc66_B1                      (-2108177912)        /* Floating point value -1.963394 */
-#define HPF_Fs16000_Fc66_B2                        1035142690         /* Floating point value 0.964052 */
-#define HPF_Fs22050_Fc66_A0                        1047445145         /* Floating point value 0.975509 */
-#define HPF_Fs22050_Fc66_A1                      (-2094890289)        /* Floating point value -1.951019 */
-#define HPF_Fs22050_Fc66_A2                        1047445145         /* Floating point value 0.975509 */
-#define HPF_Fs22050_Fc66_B1                      (-2118961025)        /* Floating point value -1.973436 */
-#define HPF_Fs22050_Fc66_B2                        1045593102         /* Floating point value 0.973784 */
-#define HPF_Fs24000_Fc66_A0                        1048576175         /* Floating point value 0.976563 */
-#define HPF_Fs24000_Fc66_A1                      (-2097152349)        /* Floating point value -1.953125 */
-#define HPF_Fs24000_Fc66_A2                        1048576175         /* Floating point value 0.976563 */
-#define HPF_Fs24000_Fc66_B1                      (-2121278255)        /* Floating point value -1.975594 */
-#define HPF_Fs24000_Fc66_B2                        1047852379         /* Floating point value 0.975889 */
-#define HPF_Fs32000_Fc66_A0                        1051780119         /* Floating point value 0.979547 */
-#define HPF_Fs32000_Fc66_A1                      (-2103560237)        /* Floating point value -1.959093 */
-#define HPF_Fs32000_Fc66_A2                        1051780119         /* Floating point value 0.979547 */
-#define HPF_Fs32000_Fc66_B1                      (-2127829187)        /* Floating point value -1.981695 */
-#define HPF_Fs32000_Fc66_B2                        1054265623         /* Floating point value 0.981861 */
-#define HPF_Fs44100_Fc66_A0                        1054424722         /* Floating point value 0.982010 */
-#define HPF_Fs44100_Fc66_A1                      (-2108849444)        /* Floating point value -1.964019 */
-#define HPF_Fs44100_Fc66_A2                        1054424722         /* Floating point value 0.982010 */
-#define HPF_Fs44100_Fc66_B1                      (-2133221723)        /* Floating point value -1.986718 */
-#define HPF_Fs44100_Fc66_B2                        1059573993         /* Floating point value 0.986805 */
-#define HPF_Fs48000_Fc66_A0                        1054993851         /* Floating point value 0.982540 */
-#define HPF_Fs48000_Fc66_A1                      (-2109987702)        /* Floating point value -1.965079 */
-#define HPF_Fs48000_Fc66_A2                        1054993851         /* Floating point value 0.982540 */
-#define HPF_Fs48000_Fc66_B1                      (-2134380475)        /* Floating point value -1.987797 */
-#define HPF_Fs48000_Fc66_B2                        1060718118         /* Floating point value 0.987871 */
-
- /* Coefficients for centre frequency 78Hz */
-#define HPF_Fs8000_Fc78_A0                         1016504203         /* Floating point value 0.946693 */
-#define HPF_Fs8000_Fc78_A1                       (-2033008405)        /* Floating point value -1.893387 */
-#define HPF_Fs8000_Fc78_A2                         1016504203         /* Floating point value 0.946693 */
-#define HPF_Fs8000_Fc78_B1                       (-2054623390)        /* Floating point value -1.913517 */
-#define HPF_Fs8000_Fc78_B2                          984733853         /* Floating point value 0.917105 */
-#define HPF_Fs11025_Fc78_A0                        1028643741         /* Floating point value 0.957999 */
-#define HPF_Fs11025_Fc78_A1                      (-2057287482)        /* Floating point value -1.915998 */
-#define HPF_Fs11025_Fc78_A2                        1028643741         /* Floating point value 0.957999 */
-#define HPF_Fs11025_Fc78_B1                      (-2080083769)        /* Floating point value -1.937229 */
-#define HPF_Fs11025_Fc78_B2                        1008393904         /* Floating point value 0.939140 */
-#define HPF_Fs12000_Fc78_A0                        1031271067         /* Floating point value 0.960446 */
-#define HPF_Fs12000_Fc78_A1                      (-2062542133)        /* Floating point value -1.920892 */
-#define HPF_Fs12000_Fc78_A2                        1031271067         /* Floating point value 0.960446 */
-#define HPF_Fs12000_Fc78_B1                      (-2085557048)        /* Floating point value -1.942326 */
-#define HPF_Fs12000_Fc78_B2                        1013551620         /* Floating point value 0.943944 */
-#define HPF_Fs16000_Fc78_A0                        1038734628         /* Floating point value 0.967397 */
-#define HPF_Fs16000_Fc78_A1                      (-2077469256)        /* Floating point value -1.934794 */
-#define HPF_Fs16000_Fc78_A2                        1038734628         /* Floating point value 0.967397 */
-#define HPF_Fs16000_Fc78_B1                      (-2101033380)        /* Floating point value -1.956740 */
-#define HPF_Fs16000_Fc78_B2                        1028275228         /* Floating point value 0.957656 */
-#define HPF_Fs22050_Fc78_A0                        1044918584         /* Floating point value 0.973156 */
-#define HPF_Fs22050_Fc78_A1                      (-2089837169)        /* Floating point value -1.946313 */
-#define HPF_Fs22050_Fc78_A2                        1044918584         /* Floating point value 0.973156 */
-#define HPF_Fs22050_Fc78_B1                      (-2113775854)        /* Floating point value -1.968607 */
-#define HPF_Fs22050_Fc78_B2                        1040555007         /* Floating point value 0.969092 */
-#define HPF_Fs24000_Fc78_A0                        1046252164         /* Floating point value 0.974398 */
-#define HPF_Fs24000_Fc78_A1                      (-2092504328)        /* Floating point value -1.948797 */
-#define HPF_Fs24000_Fc78_A2                        1046252164         /* Floating point value 0.974398 */
-#define HPF_Fs24000_Fc78_B1                      (-2116514229)        /* Floating point value -1.971157 */
-#define HPF_Fs24000_Fc78_B2                        1043212719         /* Floating point value 0.971568 */
-#define HPF_Fs32000_Fc78_A0                        1050031301         /* Floating point value 0.977918 */
-#define HPF_Fs32000_Fc78_A1                      (-2100062603)        /* Floating point value -1.955836 */
-#define HPF_Fs32000_Fc78_A2                        1050031301         /* Floating point value 0.977918 */
-#define HPF_Fs32000_Fc78_B1                      (-2124255900)        /* Floating point value -1.978367 */
-#define HPF_Fs32000_Fc78_B2                        1050762639         /* Floating point value 0.978599 */
-#define HPF_Fs44100_Fc78_A0                        1053152258         /* Floating point value 0.980824 */
-#define HPF_Fs44100_Fc78_A1                      (-2106304516)        /* Floating point value -1.961649 */
-#define HPF_Fs44100_Fc78_A2                        1053152258         /* Floating point value 0.980824 */
-#define HPF_Fs44100_Fc78_B1                      (-2130628742)        /* Floating point value -1.984303 */
-#define HPF_Fs44100_Fc78_B2                        1057018180         /* Floating point value 0.984425 */
-#define HPF_Fs48000_Fc78_A0                        1053824087         /* Floating point value 0.981450 */
-#define HPF_Fs48000_Fc78_A1                      (-2107648173)        /* Floating point value -1.962900 */
-#define HPF_Fs48000_Fc78_A2                        1053824087         /* Floating point value 0.981450 */
-#define HPF_Fs48000_Fc78_B1                      (-2131998154)        /* Floating point value -1.985578 */
-#define HPF_Fs48000_Fc78_B2                        1058367200         /* Floating point value 0.985681 */
-
- /* Coefficients for centre frequency 90Hz */
-#define HPF_Fs8000_Fc90_A0                         1009760053         /* Floating point value 0.940412 */
-#define HPF_Fs8000_Fc90_A1                       (-2019520105)        /* Floating point value -1.880825 */
-#define HPF_Fs8000_Fc90_A2                         1009760053         /* Floating point value 0.940412 */
-#define HPF_Fs8000_Fc90_B1                       (-2040357139)        /* Floating point value -1.900231 */
-#define HPF_Fs8000_Fc90_B2                          971711129         /* Floating point value 0.904977 */
-#define HPF_Fs11025_Fc90_A0                        1023687217         /* Floating point value 0.953383 */
-#define HPF_Fs11025_Fc90_A1                      (-2047374434)        /* Floating point value -1.906766 */
-#define HPF_Fs11025_Fc90_A2                        1023687217         /* Floating point value 0.953383 */
-#define HPF_Fs11025_Fc90_B1                      (-2069722397)        /* Floating point value -1.927579 */
-#define HPF_Fs11025_Fc90_B2                         998699604         /* Floating point value 0.930111 */
-#define HPF_Fs12000_Fc90_A0                        1026704754         /* Floating point value 0.956193 */
-#define HPF_Fs12000_Fc90_A1                      (-2053409508)        /* Floating point value -1.912387 */
-#define HPF_Fs12000_Fc90_A2                        1026704754         /* Floating point value 0.956193 */
-#define HPF_Fs12000_Fc90_B1                      (-2076035996)        /* Floating point value -1.933459 */
-#define HPF_Fs12000_Fc90_B2                        1004595918         /* Floating point value 0.935603 */
-#define HPF_Fs16000_Fc90_A0                        1035283225         /* Floating point value 0.964183 */
-#define HPF_Fs16000_Fc90_A1                      (-2070566451)        /* Floating point value -1.928365 */
-#define HPF_Fs16000_Fc90_A2                        1035283225         /* Floating point value 0.964183 */
-#define HPF_Fs16000_Fc90_B1                      (-2093889811)        /* Floating point value -1.950087 */
-#define HPF_Fs16000_Fc90_B2                        1021453326         /* Floating point value 0.951303 */
-#define HPF_Fs22050_Fc90_A0                        1042398116         /* Floating point value 0.970809 */
-#define HPF_Fs22050_Fc90_A1                      (-2084796232)        /* Floating point value -1.941618 */
-#define HPF_Fs22050_Fc90_A2                        1042398116         /* Floating point value 0.970809 */
-#define HPF_Fs22050_Fc90_B1                      (-2108591057)        /* Floating point value -1.963778 */
-#define HPF_Fs22050_Fc90_B2                        1035541188         /* Floating point value 0.964423 */
-#define HPF_Fs24000_Fc90_A0                        1043933302         /* Floating point value 0.972239 */
-#define HPF_Fs24000_Fc90_A1                      (-2087866604)        /* Floating point value -1.944477 */
-#define HPF_Fs24000_Fc90_A2                        1043933302         /* Floating point value 0.972239 */
-#define HPF_Fs24000_Fc90_B1                      (-2111750495)        /* Floating point value -1.966721 */
-#define HPF_Fs24000_Fc90_B2                        1038593601         /* Floating point value 0.967266 */
-#define HPF_Fs32000_Fc90_A0                        1048285391         /* Floating point value 0.976292 */
-#define HPF_Fs32000_Fc90_A1                      (-2096570783)        /* Floating point value -1.952584 */
-#define HPF_Fs32000_Fc90_A2                        1048285391         /* Floating point value 0.976292 */
-#define HPF_Fs32000_Fc90_B1                      (-2120682737)        /* Floating point value -1.975040 */
-#define HPF_Fs32000_Fc90_B2                        1047271295         /* Floating point value 0.975347 */
-#define HPF_Fs44100_Fc90_A0                        1051881330         /* Floating point value 0.979641 */
-#define HPF_Fs44100_Fc90_A1                      (-2103762660)        /* Floating point value -1.959282 */
-#define HPF_Fs44100_Fc90_A2                        1051881330         /* Floating point value 0.979641 */
-#define HPF_Fs44100_Fc90_B1                      (-2128035809)        /* Floating point value -1.981888 */
-#define HPF_Fs44100_Fc90_B2                        1054468533         /* Floating point value 0.982050 */
-#define HPF_Fs48000_Fc90_A0                        1052655619         /* Floating point value 0.980362 */
-#define HPF_Fs48000_Fc90_A1                      (-2105311238)        /* Floating point value -1.960724 */
-#define HPF_Fs48000_Fc90_A2                        1052655619         /* Floating point value 0.980362 */
-#define HPF_Fs48000_Fc90_B1                      (-2129615871)        /* Floating point value -1.983359 */
-#define HPF_Fs48000_Fc90_B2                        1056021492         /* Floating point value 0.983497 */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* Band Pass Filter coefficients                                                    */
-/*                                                                                  */
-/************************************************************************************/
-
- /* Coefficients for centre frequency 55Hz */
-#define BPF_Fs8000_Fc55_A0                            9875247         /* Floating point value 0.009197 */
-#define BPF_Fs8000_Fc55_A1                                  0         /* Floating point value 0.000000 */
-#define BPF_Fs8000_Fc55_A2                          (-9875247)        /* Floating point value -0.009197 */
-#define BPF_Fs8000_Fc55_B1                       (-2125519830)        /* Floating point value -1.979545 */
-#define BPF_Fs8000_Fc55_B2                         1053762629         /* Floating point value 0.981393 */
-#define BPF_Fs11025_Fc55_A0                           7183952         /* Floating point value 0.006691 */
-#define BPF_Fs11025_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs11025_Fc55_A2                         (-7183952)        /* Floating point value -0.006691 */
-#define BPF_Fs11025_Fc55_B1                      (-2131901658)        /* Floating point value -1.985488 */
-#define BPF_Fs11025_Fc55_B2                        1059207548         /* Floating point value 0.986464 */
-#define BPF_Fs12000_Fc55_A0                           6603871         /* Floating point value 0.006150 */
-#define BPF_Fs12000_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs12000_Fc55_A2                         (-6603871)        /* Floating point value -0.006150 */
-#define BPF_Fs12000_Fc55_B1                      (-2133238092)        /* Floating point value -1.986733 */
-#define BPF_Fs12000_Fc55_B2                        1060381143         /* Floating point value 0.987557 */
-#define BPF_Fs16000_Fc55_A0                           4960591         /* Floating point value 0.004620 */
-#define BPF_Fs16000_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs16000_Fc55_A2                         (-4960591)        /* Floating point value -0.004620 */
-#define BPF_Fs16000_Fc55_B1                      (-2136949052)        /* Floating point value -1.990189 */
-#define BPF_Fs16000_Fc55_B2                        1063705760         /* Floating point value 0.990653 */
-#define BPF_Fs22050_Fc55_A0                           3604131         /* Floating point value 0.003357 */
-#define BPF_Fs22050_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs22050_Fc55_A2                         (-3604131)        /* Floating point value -0.003357 */
-#define BPF_Fs22050_Fc55_B1                      (-2139929085)        /* Floating point value -1.992964 */
-#define BPF_Fs22050_Fc55_B2                        1066450095         /* Floating point value 0.993209 */
-#define BPF_Fs24000_Fc55_A0                           3312207         /* Floating point value 0.003085 */
-#define BPF_Fs24000_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs24000_Fc55_A2                         (-3312207)        /* Floating point value -0.003085 */
-#define BPF_Fs24000_Fc55_B1                      (-2140560606)        /* Floating point value -1.993552 */
-#define BPF_Fs24000_Fc55_B2                        1067040703         /* Floating point value 0.993759 */
-#define BPF_Fs32000_Fc55_A0                           2486091         /* Floating point value 0.002315 */
-#define BPF_Fs32000_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs32000_Fc55_A2                         (-2486091)        /* Floating point value -0.002315 */
-#define BPF_Fs32000_Fc55_B1                      (-2142328962)        /* Floating point value -1.995199 */
-#define BPF_Fs32000_Fc55_B2                        1068712067         /* Floating point value 0.995316 */
-#define BPF_Fs44100_Fc55_A0                           1805125         /* Floating point value 0.001681 */
-#define BPF_Fs44100_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs44100_Fc55_A2                         (-1805125)        /* Floating point value -0.001681 */
-#define BPF_Fs44100_Fc55_B1                      (-2143765772)        /* Floating point value -1.996537 */
-#define BPF_Fs44100_Fc55_B2                        1070089770         /* Floating point value 0.996599 */
-#define BPF_Fs48000_Fc55_A0                           1658687         /* Floating point value 0.001545 */
-#define BPF_Fs48000_Fc55_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs48000_Fc55_A2                         (-1658687)        /* Floating point value -0.001545 */
-#define BPF_Fs48000_Fc55_B1                      (-2144072292)        /* Floating point value -1.996823 */
-#define BPF_Fs48000_Fc55_B2                        1070386036         /* Floating point value 0.996875 */
-
- /* Coefficients for centre frequency 66Hz */
-#define BPF_Fs8000_Fc66_A0                           13580189         /* Floating point value 0.012648 */
-#define BPF_Fs8000_Fc66_A1                                  0         /* Floating point value 0.000000 */
-#define BPF_Fs8000_Fc66_A2                         (-13580189)        /* Floating point value -0.012648 */
-#define BPF_Fs8000_Fc66_B1                       (-2117161175)        /* Floating point value -1.971760 */
-#define BPF_Fs8000_Fc66_B2                         1046266945         /* Floating point value 0.974412 */
-#define BPF_Fs11025_Fc66_A0                           9888559         /* Floating point value 0.009209 */
-#define BPF_Fs11025_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs11025_Fc66_A2                         (-9888559)        /* Floating point value -0.009209 */
-#define BPF_Fs11025_Fc66_B1                      (-2125972738)        /* Floating point value -1.979966 */
-#define BPF_Fs11025_Fc66_B2                        1053735698         /* Floating point value 0.981368 */
-#define BPF_Fs12000_Fc66_A0                           9091954         /* Floating point value 0.008468 */
-#define BPF_Fs12000_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs12000_Fc66_A2                         (-9091954)        /* Floating point value -0.008468 */
-#define BPF_Fs12000_Fc66_B1                      (-2127818004)        /* Floating point value -1.981685 */
-#define BPF_Fs12000_Fc66_B2                        1055347356         /* Floating point value 0.982869 */
-#define BPF_Fs16000_Fc66_A0                           6833525         /* Floating point value 0.006364 */
-#define BPF_Fs16000_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs16000_Fc66_A2                         (-6833525)        /* Floating point value -0.006364 */
-#define BPF_Fs16000_Fc66_B1                      (-2132941739)        /* Floating point value -1.986457 */
-#define BPF_Fs16000_Fc66_B2                        1059916517         /* Floating point value 0.987124 */
-#define BPF_Fs22050_Fc66_A0                           4967309         /* Floating point value 0.004626 */
-#define BPF_Fs22050_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs22050_Fc66_A2                         (-4967309)        /* Floating point value -0.004626 */
-#define BPF_Fs22050_Fc66_B1                      (-2137056003)        /* Floating point value -1.990288 */
-#define BPF_Fs22050_Fc66_B2                        1063692170         /* Floating point value 0.990641 */
-#define BPF_Fs24000_Fc66_A0                           4565445         /* Floating point value 0.004252 */
-#define BPF_Fs24000_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs24000_Fc66_A2                         (-4565445)        /* Floating point value -0.004252 */
-#define BPF_Fs24000_Fc66_B1                      (-2137927842)        /* Floating point value -1.991100 */
-#define BPF_Fs24000_Fc66_B2                        1064505202         /* Floating point value 0.991398 */
-#define BPF_Fs32000_Fc66_A0                           3427761         /* Floating point value 0.003192 */
-#define BPF_Fs32000_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs32000_Fc66_A2                         (-3427761)        /* Floating point value -0.003192 */
-#define BPF_Fs32000_Fc66_B1                      (-2140369007)        /* Floating point value -1.993374 */
-#define BPF_Fs32000_Fc66_B2                        1066806920         /* Floating point value 0.993541 */
-#define BPF_Fs44100_Fc66_A0                           2489466         /* Floating point value 0.002318 */
-#define BPF_Fs44100_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs44100_Fc66_A2                         (-2489466)        /* Floating point value -0.002318 */
-#define BPF_Fs44100_Fc66_B1                      (-2142352342)        /* Floating point value -1.995221 */
-#define BPF_Fs44100_Fc66_B2                        1068705240         /* Floating point value 0.995309 */
-#define BPF_Fs48000_Fc66_A0                           2287632         /* Floating point value 0.002131 */
-#define BPF_Fs48000_Fc66_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs48000_Fc66_A2                         (-2287632)        /* Floating point value -0.002131 */
-#define BPF_Fs48000_Fc66_B1                      (-2142775436)        /* Floating point value -1.995615 */
-#define BPF_Fs48000_Fc66_B2                        1069113581         /* Floating point value 0.995690 */
-
- /* Coefficients for centre frequency 78Hz */
-#define BPF_Fs8000_Fc78_A0                           19941180         /* Floating point value 0.018572 */
-#define BPF_Fs8000_Fc78_A1                                  0         /* Floating point value 0.000000 */
-#define BPF_Fs8000_Fc78_A2                         (-19941180)        /* Floating point value -0.018572 */
-#define BPF_Fs8000_Fc78_B1                       (-2103186749)        /* Floating point value -1.958745 */
-#define BPF_Fs8000_Fc78_B2                         1033397648         /* Floating point value 0.962427 */
-#define BPF_Fs11025_Fc78_A0                          14543934         /* Floating point value 0.013545 */
-#define BPF_Fs11025_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs11025_Fc78_A2                        (-14543934)        /* Floating point value -0.013545 */
-#define BPF_Fs11025_Fc78_B1                      (-2115966638)        /* Floating point value -1.970647 */
-#define BPF_Fs11025_Fc78_B2                        1044317135         /* Floating point value 0.972596 */
-#define BPF_Fs12000_Fc78_A0                          13376999         /* Floating point value 0.012458 */
-#define BPF_Fs12000_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs12000_Fc78_A2                        (-13376999)        /* Floating point value -0.012458 */
-#define BPF_Fs12000_Fc78_B1                      (-2118651708)        /* Floating point value -1.973148 */
-#define BPF_Fs12000_Fc78_B2                        1046678029         /* Floating point value 0.974795 */
-#define BPF_Fs16000_Fc78_A0                          10064222         /* Floating point value 0.009373 */
-#define BPF_Fs16000_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs16000_Fc78_A2                        (-10064222)        /* Floating point value -0.009373 */
-#define BPF_Fs16000_Fc78_B1                      (-2126124342)        /* Floating point value -1.980108 */
-#define BPF_Fs16000_Fc78_B2                        1053380304         /* Floating point value 0.981037 */
-#define BPF_Fs22050_Fc78_A0                           7321780         /* Floating point value 0.006819 */
-#define BPF_Fs22050_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs22050_Fc78_A2                         (-7321780)        /* Floating point value -0.006819 */
-#define BPF_Fs22050_Fc78_B1                      (-2132143771)        /* Floating point value -1.985714 */
-#define BPF_Fs22050_Fc78_B2                        1058928700         /* Floating point value 0.986204 */
-#define BPF_Fs24000_Fc78_A0                           6730640         /* Floating point value 0.006268 */
-#define BPF_Fs24000_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs24000_Fc78_A2                         (-6730640)        /* Floating point value -0.006268 */
-#define BPF_Fs24000_Fc78_B1                      (-2133421607)        /* Floating point value -1.986904 */
-#define BPF_Fs24000_Fc78_B2                        1060124669         /* Floating point value 0.987318 */
-#define BPF_Fs32000_Fc78_A0                           5055965         /* Floating point value 0.004709 */
-#define BPF_Fs32000_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs32000_Fc78_A2                         (-5055965)        /* Floating point value -0.004709 */
-#define BPF_Fs32000_Fc78_B1                      (-2137003977)        /* Floating point value -1.990240 */
-#define BPF_Fs32000_Fc78_B2                        1063512802         /* Floating point value 0.990473 */
-#define BPF_Fs44100_Fc78_A0                           3673516         /* Floating point value 0.003421 */
-#define BPF_Fs44100_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs44100_Fc78_A2                         (-3673516)        /* Floating point value -0.003421 */
-#define BPF_Fs44100_Fc78_B1                      (-2139919394)        /* Floating point value -1.992955 */
-#define BPF_Fs44100_Fc78_B2                        1066309718         /* Floating point value 0.993078 */
-#define BPF_Fs48000_Fc78_A0                           3375990         /* Floating point value 0.003144 */
-#define BPF_Fs48000_Fc78_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs48000_Fc78_A2                         (-3375990)        /* Floating point value -0.003144 */
-#define BPF_Fs48000_Fc78_B1                      (-2140541906)        /* Floating point value -1.993535 */
-#define BPF_Fs48000_Fc78_B2                        1066911660         /* Floating point value 0.993639 */
-
- /* Coefficients for centre frequency 90Hz */
-#define BPF_Fs8000_Fc90_A0                           24438548         /* Floating point value 0.022760 */
-#define BPF_Fs8000_Fc90_A1                                  0         /* Floating point value 0.000000 */
-#define BPF_Fs8000_Fc90_A2                         (-24438548)        /* Floating point value -0.022760 */
-#define BPF_Fs8000_Fc90_B1                       (-2092801347)        /* Floating point value -1.949073 */
-#define BPF_Fs8000_Fc90_B2                         1024298757         /* Floating point value 0.953953 */
-#define BPF_Fs11025_Fc90_A0                          17844385         /* Floating point value 0.016619 */
-#define BPF_Fs11025_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs11025_Fc90_A2                        (-17844385)        /* Floating point value -0.016619 */
-#define BPF_Fs11025_Fc90_B1                      (-2108604921)        /* Floating point value -1.963791 */
-#define BPF_Fs11025_Fc90_B2                        1037639797         /* Floating point value 0.966377 */
-#define BPF_Fs12000_Fc90_A0                          16416707         /* Floating point value 0.015289 */
-#define BPF_Fs12000_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs12000_Fc90_A2                        (-16416707)        /* Floating point value -0.015289 */
-#define BPF_Fs12000_Fc90_B1                      (-2111922936)        /* Floating point value -1.966882 */
-#define BPF_Fs12000_Fc90_B2                        1040528216         /* Floating point value 0.969067 */
-#define BPF_Fs16000_Fc90_A0                          12359883         /* Floating point value 0.011511 */
-#define BPF_Fs16000_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs16000_Fc90_A2                        (-12359883)        /* Floating point value -0.011511 */
-#define BPF_Fs16000_Fc90_B1                      (-2121152162)        /* Floating point value -1.975477 */
-#define BPF_Fs16000_Fc90_B2                        1048735817         /* Floating point value 0.976711 */
-#define BPF_Fs22050_Fc90_A0                           8997173         /* Floating point value 0.008379 */
-#define BPF_Fs22050_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs22050_Fc90_A2                         (-8997173)        /* Floating point value -0.008379 */
-#define BPF_Fs22050_Fc90_B1                      (-2128580762)        /* Floating point value -1.982395 */
-#define BPF_Fs22050_Fc90_B2                        1055539113         /* Floating point value 0.983047 */
-#define BPF_Fs24000_Fc90_A0                           8271818         /* Floating point value 0.007704 */
-#define BPF_Fs24000_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs24000_Fc90_A2                         (-8271818)        /* Floating point value -0.007704 */
-#define BPF_Fs24000_Fc90_B1                      (-2130157013)        /* Floating point value -1.983863 */
-#define BPF_Fs24000_Fc90_B2                        1057006621         /* Floating point value 0.984414 */
-#define BPF_Fs32000_Fc90_A0                           6215918         /* Floating point value 0.005789 */
-#define BPF_Fs32000_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs32000_Fc90_A2                         (-6215918)        /* Floating point value -0.005789 */
-#define BPF_Fs32000_Fc90_B1                      (-2134574521)        /* Floating point value -1.987977 */
-#define BPF_Fs32000_Fc90_B2                        1061166033         /* Floating point value 0.988288 */
-#define BPF_Fs44100_Fc90_A0                           4517651         /* Floating point value 0.004207 */
-#define BPF_Fs44100_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs44100_Fc90_A2                         (-4517651)        /* Floating point value -0.004207 */
-#define BPF_Fs44100_Fc90_B1                      (-2138167926)        /* Floating point value -1.991324 */
-#define BPF_Fs44100_Fc90_B2                        1064601898         /* Floating point value 0.991488 */
-#define BPF_Fs48000_Fc90_A0                           4152024         /* Floating point value 0.003867 */
-#define BPF_Fs48000_Fc90_A1                                 0         /* Floating point value 0.000000 */
-#define BPF_Fs48000_Fc90_A2                         (-4152024)        /* Floating point value -0.003867 */
-#define BPF_Fs48000_Fc90_B1                      (-2138935002)        /* Floating point value -1.992038 */
-#define BPF_Fs48000_Fc90_B2                        1065341620         /* Floating point value 0.992177 */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* Automatic Gain Control time constants and gain settings                          */
-/*                                                                                  */
-/************************************************************************************/
-
-/* AGC Time constants */
-#define AGC_ATTACK_Fs8000                               27571         /* Floating point value 0.841395 */
-#define AGC_ATTACK_Fs11025                              28909         /* Floating point value 0.882223 */
-#define AGC_ATTACK_Fs12000                              29205         /* Floating point value 0.891251 */
-#define AGC_ATTACK_Fs16000                              30057         /* Floating point value 0.917276 */
-#define AGC_ATTACK_Fs22050                              30778         /* Floating point value 0.939267 */
-#define AGC_ATTACK_Fs24000                              30935         /* Floating point value 0.944061 */
-#define AGC_ATTACK_Fs32000                              31383         /* Floating point value 0.957745 */
-#define AGC_ATTACK_Fs44100                              31757         /* Floating point value 0.969158 */
-#define AGC_ATTACK_Fs48000                              31838         /* Floating point value 0.971628 */
-#define DECAY_SHIFT                                        10         /* As a power of 2 */
-#define AGC_DECAY_Fs8000                                   44         /* Floating point value 0.000042 */
-#define AGC_DECAY_Fs11025                                  32         /* Floating point value 0.000030 */
-#define AGC_DECAY_Fs12000                                  29         /* Floating point value 0.000028 */
-#define AGC_DECAY_Fs16000                                  22         /* Floating point value 0.000021 */
-#define AGC_DECAY_Fs22050                                  16         /* Floating point value 0.000015 */
-#define AGC_DECAY_Fs24000                                  15         /* Floating point value 0.000014 */
-#define AGC_DECAY_Fs32000                                  11         /* Floating point value 0.000010 */
-#define AGC_DECAY_Fs44100                                   8         /* Floating point value 0.000008 */
-#define AGC_DECAY_Fs48000                                   7         /* Floating point value 0.000007 */
-
-/* AGC Gain settings */
-#define AGC_GAIN_SCALE                                        31         /* As a power of 2 */
-#define AGC_GAIN_SHIFT                                         4         /* As a power of 2 */
-#define AGC_TARGETLEVEL                              33170337         /* Floating point value -0.100000dB */
-#define AGC_HPFGAIN_0dB                             110739704         /* Floating point value 0.412538 */
-#define AGC_GAIN_0dB                                        0         /* Floating point value 0.000000 */
-#define AGC_HPFGAIN_1dB                             157006071         /* Floating point value 0.584893 */
-#define AGC_GAIN_1dB                                 32754079         /* Floating point value 0.122018 */
-#define AGC_HPFGAIN_2dB                             208917788         /* Floating point value 0.778279 */
-#define AGC_GAIN_2dB                                 69504761         /* Floating point value 0.258925 */
-#define AGC_HPFGAIN_3dB                             267163693         /* Floating point value 0.995262 */
-#define AGC_GAIN_3dB                                110739704         /* Floating point value 0.412538 */
-#define AGC_HPFGAIN_4dB                             332516674         /* Floating point value 1.238721 */
-#define AGC_GAIN_4dB                                157006071         /* Floating point value 0.584893 */
-#define AGC_HPFGAIN_5dB                             405843924         /* Floating point value 1.511886 */
-#define AGC_GAIN_5dB                                208917788         /* Floating point value 0.778279 */
-#define AGC_HPFGAIN_6dB                             488118451         /* Floating point value 1.818383 */
-#define AGC_GAIN_6dB                                267163693         /* Floating point value 0.995262 */
-#define AGC_HPFGAIN_7dB                             580431990         /* Floating point value 2.162278 */
-#define AGC_GAIN_7dB                                332516674         /* Floating point value 1.238721 */
-#define AGC_HPFGAIN_8dB                             684009483         /* Floating point value 2.548134 */
-#define AGC_GAIN_8dB                                405843924         /* Floating point value 1.511886 */
-#define AGC_HPFGAIN_9dB                             800225343         /* Floating point value 2.981072 */
-#define AGC_GAIN_9dB                                488118451         /* Floating point value 1.818383 */
-#define AGC_HPFGAIN_10dB                            930621681         /* Floating point value 3.466836 */
-#define AGC_GAIN_10dB                               580431990         /* Floating point value 2.162278 */
-#define AGC_HPFGAIN_11dB                           1076928780         /* Floating point value 4.011872 */
-#define AGC_GAIN_11dB                               684009483         /* Floating point value 2.548134 */
-#define AGC_HPFGAIN_12dB                           1241088045         /* Floating point value 4.623413 */
-#define AGC_GAIN_12dB                               800225343         /* Floating point value 2.981072 */
-#define AGC_HPFGAIN_13dB                           1425277769         /* Floating point value 5.309573 */
-#define AGC_GAIN_13dB                               930621681         /* Floating point value 3.466836 */
-#define AGC_HPFGAIN_14dB                           1631942039         /* Floating point value 6.079458 */
-#define AGC_GAIN_14dB                              1076928780         /* Floating point value 4.011872 */
-#define AGC_HPFGAIN_15dB                           1863823163         /* Floating point value 6.943282 */
-#define AGC_GAIN_15dB                              1241088045         /* Floating point value 4.623413 */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* Volume control                                                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Volume control gain */
-#define VOLUME_MAX                                          0         /* In dBs */
-#define VOLUME_SHIFT                                        0         /* In dBs */
-
-/* Volume control time constants */
-#define VOL_TC_SHIFT                                       21         /* As a power of 2 */
-#define VOL_TC_Fs8000                                   25889         /* Floating point value 0.024690 */
-#define VOL_TC_Fs11025                                  18850         /* Floating point value 0.017977 */
-#define VOL_TC_Fs12000                                  17331         /* Floating point value 0.016529 */
-#define VOL_TC_Fs16000                                  13026         /* Floating point value 0.012422 */
-#define VOL_TC_Fs22050                                   9468         /* Floating point value 0.009029 */
-#define VOL_TC_Fs24000                                   8702         /* Floating point value 0.008299 */
-#define VOL_TC_Fs32000                                   6533         /* Floating point value 0.006231 */
-#define VOL_TC_Fs44100                                   4745         /* Floating point value 0.004525 */
-#define VOL_TC_Fs48000                                   4360         /* Floating point value 0.004158 */
-#define MIX_TC_Fs8000                                   29365         /* Floating point value 0.896151 */
-#define MIX_TC_Fs11025                                  30230         /* Floating point value 0.922548 */
-#define MIX_TC_Fs12000                                  30422         /* Floating point value 0.928415 */
-#define MIX_TC_Fs16000                                  30978         /* Floating point value 0.945387 */
-#define MIX_TC_Fs22050                                  31451         /* Floating point value 0.959804 */
-#define MIX_TC_Fs24000                                  31554         /* Floating point value 0.962956 */
-#define MIX_TC_Fs32000                                  31850         /* Floating point value 0.971973 */
-#define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
-#define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
-
-#else /*BUILD_FLOAT*/
-
-/************************************************************************************/
-/*                                                                                  */
-/* General                                                                          */
-/*                                                                                  */
-/************************************************************************************/
-
-#define LVDBE_SCALESHIFT                                    10         /* As a power of 2 */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /* High Pass Filter coefficients                                                    */
@@ -579,7 +79,6 @@
 #define HPF_Fs48000_Fc55_B1                       (-1.989831f)
 #define HPF_Fs48000_Fc55_B2                       0.989882f
 
-#ifdef HIGHER_FS
 #define HPF_Fs88200_Fc55_A0                       0.985818f
 #define HPF_Fs88200_Fc55_A1                       (-1.971636f)
 #define HPF_Fs88200_Fc55_A2                       0.985818f
@@ -603,8 +102,6 @@
 #define HPF_Fs192000_Fc55_A2                      0.987294f
 #define HPF_Fs192000_Fc55_B1                      (-1.997458f)
 #define HPF_Fs192000_Fc55_B2                      0.997461f
-#endif
-
 
  /* Coefficients for centre frequency 66Hz */
 #define HPF_Fs8000_Fc66_A0                        0.953016f
@@ -653,7 +150,6 @@
 #define HPF_Fs48000_Fc66_B1                       (-1.987797f)
 #define HPF_Fs48000_Fc66_B2                       0.987871f
 
-#ifdef HIGHER_FS
 #define HPF_Fs88200_Fc66_A0                       0.985273f
 #define HPF_Fs88200_Fc66_A1                       (-1.970546f)
 #define HPF_Fs88200_Fc66_A2                       0.985273f
@@ -677,7 +173,6 @@
 #define HPF_Fs192000_Fc66_A2                      0.987043f
 #define HPF_Fs192000_Fc66_B1                      (-1.996949f)
 #define HPF_Fs192000_Fc66_B2                      0.996954f
-#endif
 
 /* Coefficients for centre frequency 78Hz */
 #define HPF_Fs8000_Fc78_A0                        0.946693f
@@ -726,7 +221,6 @@
 #define HPF_Fs48000_Fc78_B1                       (-1.985578f)
 #define HPF_Fs48000_Fc78_B2                       0.985681f
 
-#ifdef HIGHER_FS
 #define HPF_Fs88200_Fc78_A0                       0.984678f
 #define HPF_Fs88200_Fc78_A1                       (-1.969356f)
 #define HPF_Fs88200_Fc78_A2                       0.984678f
@@ -750,7 +244,6 @@
 #define HPF_Fs192000_Fc78_A2                      0.986769f
 #define HPF_Fs192000_Fc78_B1                      (-1.996394f)
 #define HPF_Fs192000_Fc78_B2                      0.996401f
-#endif
 
 /* Coefficients for centre frequency 90Hz */
 #define HPF_Fs8000_Fc90_A0                       0.940412f
@@ -799,7 +292,6 @@
 #define HPF_Fs48000_Fc90_B1                      (-1.983359f)
 #define HPF_Fs48000_Fc90_B2                      0.983497f
 
-#ifdef HIGHER_FS
 #define HPF_Fs88200_Fc90_A0                       0.984084f
 #define HPF_Fs88200_Fc90_A1                       (-1.968168f)
 #define HPF_Fs88200_Fc90_A2                       0.984084f
@@ -823,7 +315,6 @@
 #define HPF_Fs192000_Fc90_A2                      0.986496f
 #define HPF_Fs192000_Fc90_B1                      (-1.995840f)
 #define HPF_Fs192000_Fc90_B2                      0.995848f
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
@@ -878,7 +369,6 @@
 #define BPF_Fs48000_Fc55_B1                      (-1.996823f)
 #define BPF_Fs48000_Fc55_B2                      0.996875f
 
-#ifdef HIGHER_FS
 #define BPF_Fs88200_Fc55_A0                      0.000831f
 #define BPF_Fs88200_Fc55_A1                      0.000000f
 #define BPF_Fs88200_Fc55_A2                      (-0.000831f)
@@ -902,7 +392,6 @@
 #define BPF_Fs192000_Fc55_A2                     (-0.000381f)
 #define BPF_Fs192000_Fc55_B1                     (-1.999234f)
 #define BPF_Fs192000_Fc55_B2                     0.999238f
-#endif
 
 /* Coefficients for centre frequency 66Hz */
 #define BPF_Fs8000_Fc66_A0                      0.012648f
@@ -951,7 +440,6 @@
 #define BPF_Fs48000_Fc66_B1                     (-1.995615f)
 #define BPF_Fs48000_Fc66_B2                     0.995690f
 
-#ifdef HIGHER_FS
 #define BPF_Fs88200_Fc66_A0                     0.001146f
 #define BPF_Fs88200_Fc66_A1                     0.000000f
 #define BPF_Fs88200_Fc66_A2                     (-0.001146f)
@@ -975,7 +463,6 @@
 #define BPF_Fs192000_Fc66_A2                   (-0.000528f)
 #define BPF_Fs192000_Fc66_B1                   (-1.998939f)
 #define BPF_Fs192000_Fc66_B2                    0.998945f
-#endif
 
 /* Coefficients for centre frequency 78Hz */
 #define BPF_Fs8000_Fc78_A0                      0.018572f
@@ -1024,7 +511,6 @@
 #define BPF_Fs48000_Fc78_B1                     (-1.993535f)
 #define BPF_Fs48000_Fc78_B2                     0.993639f
 
-#ifdef HIGHER_FS
 #define BPF_Fs88200_Fc78_A0                    0.001693f
 #define BPF_Fs88200_Fc78_A1                    0.000000f
 #define BPF_Fs88200_Fc78_A2                    (-0.001693f)
@@ -1048,7 +534,6 @@
 #define BPF_Fs192000_Fc78_A2                   (-0.000778f)
 #define BPF_Fs192000_Fc78_B1                   (-1.998437f)
 #define BPF_Fs192000_Fc78_B2                    0.998444f
-#endif
 
 /* Coefficients for centre frequency 90Hz */
 #define BPF_Fs8000_Fc90_A0                       0.022760f
@@ -1097,7 +582,6 @@
 #define BPF_Fs48000_Fc90_B1                      (-1.992038f)
 #define BPF_Fs48000_Fc90_B2                      0.992177f
 
-#ifdef HIGHER_FS
 #define BPF_Fs88200_Fc90_A0                      0.002083f
 #define BPF_Fs88200_Fc90_A1                      0.000000f
 #define BPF_Fs88200_Fc90_A2                      (-0.002083f)
@@ -1121,7 +605,6 @@
 #define BPF_Fs192000_Fc90_A2                    (-0.000958f)
 #define BPF_Fs192000_Fc90_B1                    (-1.998075f)
 #define BPF_Fs192000_Fc90_B2                     0.998085f
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
@@ -1140,12 +623,10 @@
 #define AGC_ATTACK_Fs44100                            0.969158f
 #define AGC_ATTACK_Fs48000                            0.971628f
 
-#ifdef HIGHER_FS
 #define AGC_ATTACK_Fs88200                             0.984458f
 #define AGC_ATTACK_Fs96000                             0.985712f
 #define AGC_ATTACK_Fs176400                            0.992199f
 #define AGC_ATTACK_Fs192000                            0.992830f
-#endif
 
 #define DECAY_SHIFT                                   10
 
@@ -1159,12 +640,10 @@
 #define AGC_DECAY_Fs44100                             0.000008f
 #define AGC_DECAY_Fs48000                             0.000007f
 
-#ifdef HIGHER_FS
 #define AGC_DECAY_Fs88200                            0.0000038f
 #define AGC_DECAY_FS96000                            0.0000035f
 #define AGC_DECAY_Fs176400                          0.00000188f
 #define AGC_DECAY_FS192000                          0.00000175f
-#endif
 
 /* AGC Gain settings */
 #define AGC_GAIN_SCALE                                        31         /* As a power of 2 */
@@ -1224,12 +703,10 @@
 #define VOL_TC_Fs32000                                  0.006231f
 #define VOL_TC_Fs44100                                  0.004525f
 #define VOL_TC_Fs48000                                  0.004158f
-#ifdef HIGHER_FS
 #define VOL_TC_Fs88200                                  0.002263f
 #define VOL_TC_Fs96000                                  0.002079f
 #define VOL_TC_Fs176400                                 0.001131f
 #define VOL_TC_Fs192000                                 0.001039f
-#endif
 #define MIX_TC_Fs8000                                   29365         /* Floating point value 0.896151 */
 #define MIX_TC_Fs11025                                  30230         /* Floating point value 0.922548 */
 #define MIX_TC_Fs12000                                  30422         /* Floating point value 0.928415 */
@@ -1239,14 +716,11 @@
 #define MIX_TC_Fs32000                                  31850         /* Floating point value 0.971973 */
 #define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
 #define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
-#ifdef HIGHER_FS
 /* Floating point value 0.989704 */
 #define MIX_TC_Fs88200                                  32430
 #define MIX_TC_Fs96000                                  32456         /* Floating point value 0.990530 */
 /* Floating point value 0.994838 */
 #define MIX_TC_Fs176400                                 32598
 #define MIX_TC_Fs192000                                 32611         /* Floating point value 0.992524 */
-#endif
 
-#endif /*BUILD_FLOAT*/
 #endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
deleted file mode 100644
index 0ba2c86..0000000
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVDBE.h"
-#include "LVDBE_Private.h"
-#include "VectorArithmetic.h"
-#include "LVDBE_Coeffs.h"
-#include "LVDBE_Tables.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                  LVDBE_GetParameters                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Request the Dynamic Bass Enhancement parameters. The current parameter set is     */
-/*  returned via the parameter pointer.                                                 */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance                   Instance handle                                         */
-/*  pParams                  Pointer to an empty parameter structure                    */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVDBE_SUCCESS            Always succeeds                                            */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.    This function may be interrupted by the LVDBE_Process function                */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
-                                            LVDBE_Params_t        *pParams)
-{
-
-    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
-
-    *pParams = pInstance->Params;
-
-    return(LVDBE_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                  LVDBE_GetCapabilities                                 */
-/*                                                                                  */
-/* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
-/* returned via the pointer.                                                        */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance                   Instance handle                                     */
-/*  pCapabilities              Pointer to an empty capability structure             */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVDBE_Success             Always succeeds                                       */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.    This function may be interrupted by the LVDBE_Process function            */
-/*                                                                                  */
-/************************************************************************************/
-
-LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
-                                              LVDBE_Capabilities_t    *pCapabilities)
-{
-
-    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
-
-    *pCapabilities = pInstance->Capabilities;
-
-    return(LVDBE_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVDBE_SetFilters                                            */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the filter coefficients and clears the data history                        */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-void    LVDBE_SetFilters(LVDBE_Instance_t     *pInstance,
-                         LVDBE_Params_t       *pParams)
-{
-
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-    /*
-     * Calculate the table offsets
-     */
-    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
-                                    (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
-#else
-    /*
-     * Calculate the table offsets
-     */
-    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
-                                    (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
-#endif
-
-    /*
-     * Setup the high pass filter
-     */
-#ifndef BUILD_FLOAT
-    LoadConst_16(0,                                              /* Clear the history, value 0 */
-                 (void *)&pInstance->pData->HPFTaps,             /* Destination Cast to void: \
-                                                                    no dereferencing in function*/
-                 sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16));   /* Number of words */
-#else
-    LoadConst_Float(0,                                          /* Clear the history, value 0 */
-                   (void *)&pInstance->pData->HPFTaps,          /* Destination Cast to void: \
-                                                                  no dereferencing in function*/
-                    sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
-#endif
-#ifndef BUILD_FLOAT
-    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
-                                    &pInstance->pData->HPFTaps,
-                                    (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
-#else
-    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
-                                    &pInstance->pData->HPFTaps,
-                                    (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
-#endif
-
-
-    /*
-     * Setup the band pass filter
-     */
-#ifndef BUILD_FLOAT
-    LoadConst_16(0,                                                 /* Clear the history, value 0 */
-                 (void *)&pInstance->pData->BPFTaps,                /* Destination Cast to void: \
-                                                                     no dereferencing in function*/
-                 sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16));   /* Number of words */
-#else
-    LoadConst_Float(0,                                           /* Clear the history, value 0 */
-                 (void *)&pInstance->pData->BPFTaps,             /* Destination Cast to void: \
-                                                                    no dereferencing in function*/
-                 sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
-#endif
-#ifndef BUILD_FLOAT
-    BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,         /* Initialise the filter */
-                                    &pInstance->pData->BPFTaps,
-                                    (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
-#else
-    BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
-                                    &pInstance->pData->BPFTaps,
-                                    (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
-#endif
-}
-
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVDBE_SetAGC                                                */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the AGC gain level and attack and decay times constants.                   */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-void    LVDBE_SetAGC(LVDBE_Instance_t     *pInstance,
-                     LVDBE_Params_t       *pParams)
-{
-
-    /*
-     * Get the attack and decay time constants
-     */
-    pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate];  /* Attack multiplier */
-    pInstance->pData->AGCInstance.AGC_Decay  = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate];   /* Decay multipler */
-
-
-    /*
-     * Get the boost gain
-     */
-    if (pParams->HPFSelect == LVDBE_HPF_ON)
-    {
-        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel];  /* High pass filter on */
-    }
-    else
-    {
-        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
-    }
-#ifndef BUILD_FLOAT
-    pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
-#endif
-    pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
-
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVDBE_SetVolume                                             */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Converts the input volume demand from dBs to linear.                            */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1. The volume should have the following settings:                               */
-/*                                                                                  */
-/*          DBE         Vol Control           Volume setting                        */
-/*          ===         ===========         ===================                     */
-/*          Off             Off                 HeadroomdB                          */
-/*          Off             On              VolumedB+HeadroomdB                     */
-/*          On              Off                 HeadroomdB                          */
-/*          On              On              VolumedB+HeadroomdB                     */
-/*                                                                                  */
-/************************************************************************************/
-
-void    LVDBE_SetVolume(LVDBE_Instance_t     *pInstance,
-                        LVDBE_Params_t       *pParams)
-{
-
-    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
-    LVM_UINT16      dBOffset;                                   /* Table offset */
-    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
-
-#ifdef BUILD_FLOAT
-    LVM_FLOAT        dBShifts_fac;
-#endif
-    /*
-     * Apply the volume if enabled
-     */
-    if (pParams->VolumeControl == LVDBE_VOLUME_ON)
-    {
-        /*
-         * Limit the gain to the maximum allowed
-         */
-        if  (pParams->VolumedB > VOLUME_MAX)
-        {
-            Volume = VOLUME_MAX;
-        }
-        else
-        {
-            Volume = pParams->VolumedB;
-        }
-    }
-
-
-    /*
-     * Calculate the required gain and shifts
-     */
-    dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
-    dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
-
-#ifdef BUILD_FLOAT
-    dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
-#endif
-    /*
-     * When DBE is enabled use AGC volume
-     */
-#ifndef BUILD_FLOAT
-    pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
-    pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
-#else
-    pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
-    pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
-#endif
-    pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
-#ifndef BUILD_FLOAT
-    pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
-#endif
-
-    /*
-     * When DBE is disabled use the bypass volume control
-     */
-    if(dBShifts > 0)
-    {
-#ifndef BUILD_FLOAT
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
-#else
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
-                            LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
-#endif
-    }
-    else
-    {
-#ifndef BUILD_FLOAT
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
-#else
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
-                            LVDBE_VolumeTable[dBOffset]);
-#endif
-    }
-
-    pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
-#ifndef BUILD_FLOAT
-    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
-                                LVDBE_MIXER_TC,
-                                (LVM_Fs_en)pInstance->Params.SampleRate,
-                                2);
-#else
-    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
-                                LVDBE_MIXER_TC,
-                                (LVM_Fs_en)pInstance->Params.SampleRate,
-                                2);
-#endif
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVDBE_Control                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
-/*  module is processing signals may have the following side effects:                   */
-/*                                                                                      */
-/*  General parameters:                                                                 */
-/*  ===================                                                                 */
-/*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
-/*                      level or cause pops and clicks.                                 */
-/*                                                                                      */
-/*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
-/*                                                                                      */
-/*  EffectLevel:        Changing the effect level may cause pops and clicks             */
-/*                                                                                      */
-/*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
-/*                                                                                      */
-/*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
-/*                      clicks                                                          */
-/*                                                                                      */
-/*  VolumedB            Changing the volume setting will have no side effects           */
-/*                                                                                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pParams                 Pointer to a parameter structure                            */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVDBE_SUCCESS           Always succeeds                                             */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function must not be interrupted by the LVDBE_Process function             */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t         hInstance,
-                                      LVDBE_Params_t         *pParams)
-{
-
-    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
-#ifndef BUILD_FLOAT
-    LVMixer3_2St_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
-#else
-    LVMixer3_2St_FLOAT_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
-#endif
-
-
-    /*
-     * Update the filters
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
-    {
-        LVDBE_SetFilters(pInstance,                     /* Instance pointer */
-                         pParams);                      /* New parameters */
-    }
-
-
-    /*
-     * Update the AGC is the effect level has changed
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
-        (pInstance->Params.HPFSelect != pParams->HPFSelect))
-    {
-        LVDBE_SetAGC(pInstance,                         /* Instance pointer */
-                     pParams);                          /* New parameters */
-#ifndef BUILD_FLOAT
-        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
-            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-
-        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
-            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-#else
-        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
-            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
-
-        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
-            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
-#endif
-
-
-    }
-
-
-    /*
-     * Update the Volume if the volume demand has changed
-     */
-    if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
-        (pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
-        (pInstance->Params.VolumeControl != pParams->VolumeControl))
-    {
-        LVDBE_SetVolume(pInstance,                      /* Instance pointer */
-                       pParams);                        /* New parameters */
-    }
-
-    if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
-    {
-#ifndef BUILD_FLOAT
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
-#else
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
-#endif
-    }
-    if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
-    {
-#ifndef BUILD_FLOAT
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
-#else
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
-        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
-#endif
-    }
-
-    /*
-     * Update the instance parameters
-     */
-    pInstance->Params = *pParams;
-
-
-    return(LVDBE_SUCCESS);
-}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
new file mode 100644
index 0000000..53feae8
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "LVDBE_Coeffs.h"
+#include "LVDBE_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVDBE_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Request the Dynamic Bass Enhancement parameters. The current parameter set is     */
+/*  returned via the parameter pointer.                                                 */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                   Instance handle                                         */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Always succeeds                                            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.    This function may be interrupted by the LVDBE_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
+                                            LVDBE_Params_t        *pParams)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+
+    *pParams = pInstance->Params;
+
+    return(LVDBE_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                  LVDBE_GetCapabilities                                 */
+/*                                                                                  */
+/* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
+/* returned via the pointer.                                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                   Instance handle                                     */
+/*  pCapabilities              Pointer to an empty capability structure             */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVDBE_Success             Always succeeds                                       */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.    This function may be interrupted by the LVDBE_Process function            */
+/*                                                                                  */
+/************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
+                                              LVDBE_Capabilities_t    *pCapabilities)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+
+    *pCapabilities = pInstance->Capabilities;
+
+    return(LVDBE_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetFilters                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter coefficients and clears the data history                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetFilters(LVDBE_Instance_t     *pInstance,
+                         LVDBE_Params_t       *pParams)
+{
+
+    /*
+     * Calculate the table offsets
+     */
+    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
+                                    (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
+
+    /*
+     * Setup the high pass filter
+     */
+    LoadConst_Float(0,                                          /* Clear the history, value 0 */
+                   (LVM_FLOAT *)&pInstance->pData->HPFTaps,     /* Destination */
+                    sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
+    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
+                                    &pInstance->pData->HPFTaps,
+                                    (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
+
+    /*
+     * Setup the band pass filter
+     */
+    LoadConst_Float(0,                                           /* Clear the history, value 0 */
+                 (LVM_FLOAT *)&pInstance->pData->BPFTaps,        /* Destination */
+                 sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
+    BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
+                                    &pInstance->pData->BPFTaps,
+                                    (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetAGC                                                */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the AGC gain level and attack and decay times constants.                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetAGC(LVDBE_Instance_t     *pInstance,
+                     LVDBE_Params_t       *pParams)
+{
+
+    /*
+     * Get the attack and decay time constants
+     */
+    pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate];  /* Attack multiplier */
+    pInstance->pData->AGCInstance.AGC_Decay  = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate];   /* Decay multipler */
+
+    /*
+     * Get the boost gain
+     */
+    if (pParams->HPFSelect == LVDBE_HPF_ON)
+    {
+        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel];  /* High pass filter on */
+    }
+    else
+    {
+        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
+    }
+    pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
+
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetVolume                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Converts the input volume demand from dBs to linear.                            */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. The volume should have the following settings:                               */
+/*                                                                                  */
+/*          DBE         Vol Control           Volume setting                        */
+/*          ===         ===========         ===================                     */
+/*          Off             Off                 HeadroomdB                          */
+/*          Off             On              VolumedB+HeadroomdB                     */
+/*          On              Off                 HeadroomdB                          */
+/*          On              On              VolumedB+HeadroomdB                     */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetVolume(LVDBE_Instance_t     *pInstance,
+                        LVDBE_Params_t       *pParams)
+{
+
+    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
+    LVM_UINT16      dBOffset;                                   /* Table offset */
+    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
+
+    LVM_FLOAT        dBShifts_fac;
+    /*
+     * Apply the volume if enabled
+     */
+    if (pParams->VolumeControl == LVDBE_VOLUME_ON)
+    {
+        /*
+         * Limit the gain to the maximum allowed
+         */
+        if  (pParams->VolumedB > VOLUME_MAX)
+        {
+            Volume = VOLUME_MAX;
+        }
+        else
+        {
+            Volume = pParams->VolumedB;
+        }
+    }
+
+    /*
+     * Calculate the required gain and shifts
+     */
+    dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
+    dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
+
+    dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
+    /*
+     * When DBE is enabled use AGC volume
+     */
+    pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
+    pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
+    pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
+
+    /*
+     * When DBE is disabled use the bypass volume control
+     */
+    if(dBShifts > 0)
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
+                            LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
+    }
+    else
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
+                            LVDBE_VolumeTable[dBOffset]);
+    }
+
+    pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
+                                LVDBE_MIXER_TC,
+                                (LVM_Fs_en)pInstance->Params.SampleRate,
+                                2);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVDBE_Control                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
+/*  module is processing signals may have the following side effects:                   */
+/*                                                                                      */
+/*  General parameters:                                                                 */
+/*  ===================                                                                 */
+/*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
+/*                      level or cause pops and clicks.                                 */
+/*                                                                                      */
+/*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
+/*                                                                                      */
+/*  EffectLevel:        Changing the effect level may cause pops and clicks             */
+/*                                                                                      */
+/*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
+/*                                                                                      */
+/*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
+/*                      clicks                                                          */
+/*                                                                                      */
+/*  VolumedB            Changing the volume setting will have no side effects           */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS           Always succeeds                                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function must not be interrupted by the LVDBE_Process function             */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t         hInstance,
+                                      LVDBE_Params_t         *pParams)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+    LVMixer3_2St_FLOAT_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+
+    /*
+     * Update the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
+    {
+        LVDBE_SetFilters(pInstance,                     /* Instance pointer */
+                         pParams);                      /* New parameters */
+    }
+
+    /*
+     * Update the AGC is the effect level has changed
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+        (pInstance->Params.HPFSelect != pParams->HPFSelect))
+    {
+        LVDBE_SetAGC(pInstance,                         /* Instance pointer */
+                     pParams);                          /* New parameters */
+        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
+
+        LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+            LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
+
+    }
+
+    /*
+     * Update the Volume if the volume demand has changed
+     */
+    if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
+        (pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
+        (pInstance->Params.VolumeControl != pParams->VolumeControl))
+    {
+        LVDBE_SetVolume(pInstance,                      /* Instance pointer */
+                       pParams);                        /* New parameters */
+    }
+
+    if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
+    }
+    if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
+    }
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params = *pParams;
+
+    return(LVDBE_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
deleted file mode 100644
index 2946734..0000000
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVDBE.h"
-#include "LVDBE_Private.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVDBE_Memory                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    This function is used for memory allocation and free. It can be called in         */
-/*    two ways:                                                                         */
-/*                                                                                      */
-/*        hInstance = NULL                Returns the memory requirements               */
-/*        hInstance = Instance handle        Returns the memory requirements and        */
-/*                                        allocated base addresses for the instance     */
-/*                                                                                      */
-/*    When this function is called for memory allocation (hInstance=NULL) the memory    */
-/*  base address pointers are NULL on return.                                           */
-/*                                                                                      */
-/*    When the function is called for free (hInstance = Instance Handle) the memory     */
-/*  table returns the allocated memory and base addresses used during initialisation.   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance                Instance Handle                                            */
-/*  pMemoryTable             Pointer to an empty memory definition table                */
-/*    pCapabilities           Pointer to the instance capabilities                      */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVDBE_SUCCESS            Succeeded                                                  */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*    1.    This function may be interrupted by the LVDBE_Process function              */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t            hInstance,
-                                   LVDBE_MemTab_t            *pMemoryTable,
-                                   LVDBE_Capabilities_t      *pCapabilities)
-{
-
-    LVM_UINT32          ScratchSize;
-    LVDBE_Instance_t    *pInstance = (LVDBE_Instance_t *)hInstance;
-
-
-    /*
-     * Fill in the memory table
-     */
-    if (hInstance == LVM_NULL)
-    {
-        /*
-         * Instance memory
-         */
-        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size         = sizeof(LVDBE_Instance_t);
-        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment    = LVDBE_INSTANCE_ALIGN;
-        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type         = LVDBE_PERSISTENT;
-        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
-
-        /*
-         * Data memory
-         */
-#ifdef BUILD_FLOAT
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size   = sizeof(LVDBE_Data_FLOAT_t);
-#else
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size         = sizeof(LVDBE_Data_t);
-#endif
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment    = LVDBE_PERSISTENT_DATA_ALIGN;
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type         = LVDBE_PERSISTENT_DATA;
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
-
-        /*
-         * Coef memory
-         */
-#ifdef BUILD_FLOAT
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size   = sizeof(LVDBE_Coef_FLOAT_t);
-#else
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size         = sizeof(LVDBE_Coef_t);
-#endif
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment    = LVDBE_PERSISTENT_COEF_ALIGN;
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type         = LVDBE_PERSISTENT_COEF;
-        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
-
-        /*
-         * Scratch memory
-         */
-#ifdef BUILD_FLOAT
-        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT) * \
-                                        pCapabilities->MaxBlockSize);
-#else /*BUILD_FLOAT*/
-        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
-#endif
-        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size         = ScratchSize;
-        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment    = LVDBE_SCRATCH_ALIGN;
-        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type         = LVDBE_SCRATCH;
-        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
-    }
-    else
-    {
-        /* Read back memory allocation table */
-        *pMemoryTable = pInstance->MemoryTable;
-    }
-
-    return(LVDBE_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVDBE_Init                                                 */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Create and initialisation function for the Dynamic Bass Enhancement module        */
-/*                                                                                      */
-/*    This function can be used to create an algorithm instance by calling with         */
-/*    hInstance set to NULL. In this case the algorithm returns the new instance        */
-/*    handle.                                                                           */
-/*                                                                                      */
-/*    This function can be used to force a full re-initialisation of the algorithm      */
-/*    by calling with hInstance = Instance Handle. In this case the memory table        */
-/*    should be correct for the instance, this can be ensured by calling the function   */
-/*    DBE_Memory before calling this function.                                          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance                  Instance handle                                          */
-/*  pMemoryTable             Pointer to the memory definition table                     */
-/*  pCapabilities              Pointer to the instance capabilities                     */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVDBE_SUCCESS            Initialisation succeeded                                   */
-/*  LVDBE_ALIGNMENTERROR    Instance or scratch memory on incorrect alignment           */
-/*    LVDBE_NULLADDRESS        Instance or scratch memory has a NULL pointer            */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.     The instance handle is the pointer to the base address of the first memory   */
-/*        region.                                                                       */
-/*    2.    This function must not be interrupted by the LVDBE_Process function         */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t         *phInstance,
-                                   LVDBE_MemTab_t       *pMemoryTable,
-                                   LVDBE_Capabilities_t *pCapabilities)
-{
-
-    LVDBE_Instance_t      *pInstance;
-#ifdef BUILD_FLOAT
-    LVMixer3_1St_FLOAT_st       *pMixer_Instance;
-    LVMixer3_2St_FLOAT_st       *pBypassMixer_Instance;
-    LVM_FLOAT             MixGain;
-#else
-    LVMixer3_1St_st       *pMixer_Instance;
-    LVMixer3_2St_st       *pBypassMixer_Instance;
-    LVM_INT32             MixGain;
-#endif
-    LVM_INT16             i;
-
-
-    /*
-     * Set the instance handle if not already initialised
-     */
-    if (*phInstance == LVM_NULL)
-    {
-        *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
-    }
-    pInstance =(LVDBE_Instance_t  *)*phInstance;
-
-
-    /*
-     * Check the memory table for NULL pointers and incorrectly aligned data
-     */
-    for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
-    {
-        if (pMemoryTable->Region[i].Size!=0)
-        {
-            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
-            {
-                return(LVDBE_NULLADDRESS);
-            }
-            if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
-                return(LVDBE_ALIGNMENTERROR);
-            }
-        }
-    }
-
-
-    /*
-     * Save the memory table in the instance structure
-     */
-    pInstance->Capabilities = *pCapabilities;
-
-
-    /*
-     * Save the memory table in the instance structure
-     */
-    pInstance->MemoryTable = *pMemoryTable;
-
-
-    /*
-     * Set the default instance parameters
-     */
-    pInstance->Params.CentreFrequency   =    LVDBE_CENTRE_55HZ;
-    pInstance->Params.EffectLevel       =    0;
-    pInstance->Params.HeadroomdB        =    0;
-    pInstance->Params.HPFSelect         =    LVDBE_HPF_OFF;
-    pInstance->Params.OperatingMode     =    LVDBE_OFF;
-    pInstance->Params.SampleRate        =    LVDBE_FS_8000;
-    pInstance->Params.VolumeControl     =    LVDBE_VOLUME_OFF;
-    pInstance->Params.VolumedB          =    0;
-
-
-    /*
-     * Set pointer to data and coef memory
-     */
-    pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
-    pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
-
-
-    /*
-     * Initialise the filters
-     */
-    LVDBE_SetFilters(pInstance,                 /* Set the filter taps and coefficients */
-                     &pInstance->Params);
-
-
-    /*
-     * Initialise the AGC
-     */
-    LVDBE_SetAGC(pInstance,                                     /* Set the AGC gain */
-                 &pInstance->Params);
-    pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
-                                                /* Default to the bass boost setting */
-
-    // initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
-    // reading uninitialized data
-    pMixer_Instance = &pInstance->pData->BypassVolume;
-#ifndef BUILD_FLOAT
-    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],0x00007FFF,0x00007FFF);
-#else
-    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], 1.0, 1.0);
-#endif
-
-    /*
-     * Initialise the volume
-     */
-    LVDBE_SetVolume(pInstance,                                         /* Set the Volume */
-                    &pInstance->Params);
-
-    pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
-                                                /* Initialise as the target */
-#ifndef BUILD_FLOAT
-    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
-    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
-#else
-    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
-    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], MixGain, MixGain);
-#endif
-
-    /* Configure the mixer process path */
-    pMixer_Instance->MixerStream[0].CallbackParam = 0;
-    pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
-    pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
-    pMixer_Instance->MixerStream[0].CallbackSet = 0;
-
-    /*
-     * Initialise the clicks minimisation BypassMixer
-     */
-
-    pBypassMixer_Instance = &pInstance->pData->BypassMixer;
-
-    /*
-     * Setup the mixer gain for the processed path
-     */
-    pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
-    pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
-    pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
-    pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
-
-    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
-    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
-        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
-
-    /*
-     * Setup the mixer gain for the unprocessed path
-     */
-    pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
-    pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
-    pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
-    pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
-#ifndef BUILD_FLOAT
-    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
-    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
-        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
-#else
-    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1], 1.0, 1.0);
-    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
-        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate, 2);
-#endif
-
-    return(LVDBE_SUCCESS);
-}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
new file mode 100644
index 0000000..ad77696
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This function is used for memory allocation and free. It can be called in         */
+/*    two ways:                                                                         */
+/*                                                                                      */
+/*        hInstance = NULL                Returns the memory requirements               */
+/*        hInstance = Instance handle        Returns the memory requirements and        */
+/*                                        allocated base addresses for the instance     */
+/*                                                                                      */
+/*    When this function is called for memory allocation (hInstance=NULL) the memory    */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*    When the function is called for free (hInstance = Instance Handle) the memory     */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance Handle                                            */
+/*  pMemoryTable             Pointer to an empty memory definition table                */
+/*    pCapabilities           Pointer to the instance capabilities                      */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Succeeded                                                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*    1.    This function may be interrupted by the LVDBE_Process function              */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t            hInstance,
+                                   LVDBE_MemTab_t            *pMemoryTable,
+                                   LVDBE_Capabilities_t      *pCapabilities)
+{
+
+    LVM_UINT32          ScratchSize;
+    LVDBE_Instance_t    *pInstance = (LVDBE_Instance_t *)hInstance;
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size         = sizeof(LVDBE_Instance_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment    = LVDBE_INSTANCE_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type         = LVDBE_PERSISTENT;
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+        /*
+         * Data memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size   = sizeof(LVDBE_Data_FLOAT_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment    = LVDBE_PERSISTENT_DATA_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type         = LVDBE_PERSISTENT_DATA;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Coef memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size   = sizeof(LVDBE_Coef_FLOAT_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment    = LVDBE_PERSISTENT_COEF_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type         = LVDBE_PERSISTENT_COEF;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT) * \
+                                        pCapabilities->MaxBlockSize);
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size         = ScratchSize;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment    = LVDBE_SCRATCH_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type         = LVDBE_SCRATCH;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVDBE_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Create and initialisation function for the Dynamic Bass Enhancement module        */
+/*                                                                                      */
+/*    This function can be used to create an algorithm instance by calling with         */
+/*    hInstance set to NULL. In this case the algorithm returns the new instance        */
+/*    handle.                                                                           */
+/*                                                                                      */
+/*    This function can be used to force a full re-initialisation of the algorithm      */
+/*    by calling with hInstance = Instance Handle. In this case the memory table        */
+/*    should be correct for the instance, this can be ensured by calling the function   */
+/*    DBE_Memory before calling this function.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                  Instance handle                                          */
+/*  pMemoryTable             Pointer to the memory definition table                     */
+/*  pCapabilities              Pointer to the instance capabilities                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Initialisation succeeded                                   */
+/*  LVDBE_ALIGNMENTERROR    Instance or scratch memory on incorrect alignment           */
+/*    LVDBE_NULLADDRESS        Instance or scratch memory has a NULL pointer            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.     The instance handle is the pointer to the base address of the first memory   */
+/*        region.                                                                       */
+/*    2.    This function must not be interrupted by the LVDBE_Process function         */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t         *phInstance,
+                                   LVDBE_MemTab_t       *pMemoryTable,
+                                   LVDBE_Capabilities_t *pCapabilities)
+{
+
+    LVDBE_Instance_t      *pInstance;
+    LVMixer3_1St_FLOAT_st       *pMixer_Instance;
+    LVMixer3_2St_FLOAT_st       *pBypassMixer_Instance;
+    LVM_FLOAT             MixGain;
+    LVM_INT16             i;
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
+    }
+    pInstance =(LVDBE_Instance_t  *)*phInstance;
+
+    /*
+     * Check the memory table for NULL pointers and incorrectly aligned data
+     */
+    for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
+    {
+        if (pMemoryTable->Region[i].Size!=0)
+        {
+            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+            {
+                return(LVDBE_NULLADDRESS);
+            }
+            if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
+                return(LVDBE_ALIGNMENTERROR);
+            }
+        }
+    }
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->MemoryTable = *pMemoryTable;
+
+    /*
+     * Set the default instance parameters
+     */
+    pInstance->Params.CentreFrequency   =    LVDBE_CENTRE_55HZ;
+    pInstance->Params.EffectLevel       =    0;
+    pInstance->Params.HeadroomdB        =    0;
+    pInstance->Params.HPFSelect         =    LVDBE_HPF_OFF;
+    pInstance->Params.OperatingMode     =    LVDBE_OFF;
+    pInstance->Params.SampleRate        =    LVDBE_FS_8000;
+    pInstance->Params.VolumeControl     =    LVDBE_VOLUME_OFF;
+    pInstance->Params.VolumedB          =    0;
+
+    /*
+     * Set pointer to data and coef memory
+     */
+    pInstance->pData =
+         (LVDBE_Data_FLOAT_t *)pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
+    pInstance->pCoef =
+         (LVDBE_Coef_FLOAT_t *)pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
+
+    /*
+     * Initialise the filters
+     */
+    LVDBE_SetFilters(pInstance,                 /* Set the filter taps and coefficients */
+                     &pInstance->Params);
+
+    /*
+     * Initialise the AGC
+     */
+    LVDBE_SetAGC(pInstance,                                     /* Set the AGC gain */
+                 &pInstance->Params);
+    pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
+                                                /* Default to the bass boost setting */
+
+    // initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
+    // reading uninitialized data
+    pMixer_Instance = &pInstance->pData->BypassVolume;
+    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], 1.0, 1.0);
+
+    /*
+     * Initialise the volume
+     */
+    LVDBE_SetVolume(pInstance,                                         /* Set the Volume */
+                    &pInstance->Params);
+
+    pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
+                                                /* Initialise as the target */
+    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
+    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0], MixGain, MixGain);
+
+    /* Configure the mixer process path */
+    pMixer_Instance->MixerStream[0].CallbackParam = 0;
+    pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+    pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+    pMixer_Instance->MixerStream[0].CallbackSet = 0;
+
+    /*
+     * Initialise the clicks minimisation BypassMixer
+     */
+
+    pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+
+    /*
+     * Setup the mixer gain for the processed path
+     */
+    pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
+    pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+    pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+    pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
+
+    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
+    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate,2);
+
+    /*
+     * Setup the mixer gain for the unprocessed path
+     */
+    pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
+    pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
+    pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
+    pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
+    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1], 1.0, 1.0);
+    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+        LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pInstance->Params.SampleRate, 2);
+
+    return(LVDBE_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 4225a30..f3faaed 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -27,11 +27,6 @@
 #ifndef __LVDBE_PRIVATE_H__
 #define __LVDBE_PRIVATE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Includes                                                                          */
@@ -43,7 +38,6 @@
 #include "LVC_Mixer.h"
 #include "AGC.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Defines                                                                           */
@@ -74,7 +68,6 @@
 #define LVDBE_MIXER_TC                   5       /* Mixer time  */
 #define LVDBE_BYPASS_MIXER_TC            100     /* Bypass mixer time */
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*    Structures                                                                        */
@@ -82,29 +75,6 @@
 /****************************************************************************************/
 
 /* Data structure */
-#ifndef BUILD_FLOAT
-typedef struct
-{
-    /* AGC parameters */
-    AGC_MIX_VOL_2St1Mon_D32_t   AGCInstance;        /* AGC instance parameters */
-
-    /* Process variables */
-    Biquad_2I_Order2_Taps_t     HPFTaps;            /* High pass filter taps */
-    Biquad_1I_Order2_Taps_t     BPFTaps;            /* Band pass filter taps */
-    LVMixer3_1St_st             BypassVolume;       /* Bypass volume scaler */
-    LVMixer3_2St_st             BypassMixer;        /* Bypass Mixer for Click Removal */
-
-} LVDBE_Data_t;
-
-/* Coefs structure */
-typedef struct
-{
-    /* Process variables */
-    Biquad_Instance_t           HPFInstance;        /* High pass filter instance */
-    Biquad_Instance_t           BPFInstance;        /* Band pass filter instance */
-
-} LVDBE_Coef_t;
-#else
 /* Data structure */
 typedef struct
 {
@@ -126,7 +96,6 @@
     Biquad_FLOAT_Instance_t           HPFInstance;        /* High pass filter instance */
     Biquad_FLOAT_Instance_t           BPFInstance;        /* Band pass filter instance */
 } LVDBE_Coef_FLOAT_t;
-#endif
 /* Instance structure */
 typedef struct
 {
@@ -136,16 +105,10 @@
     LVDBE_Capabilities_t        Capabilities;         /* Instance capabilities */
 
     /* Data and coefficient pointers */
-#ifndef BUILD_FLOAT
-    LVDBE_Data_t                *pData;                /* Instance data */
-    LVDBE_Coef_t                *pCoef;                /* Instance coefficients */
-#else
     LVDBE_Data_FLOAT_t                *pData;                /* Instance data */
     LVDBE_Coef_FLOAT_t                *pCoef;                /* Instance coefficients */
-#endif
 } LVDBE_Instance_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* Function prototypes                                                                  */
@@ -155,17 +118,10 @@
 void    LVDBE_SetAGC(LVDBE_Instance_t       *pInstance,
                      LVDBE_Params_t         *pParams);
 
-
 void    LVDBE_SetVolume(LVDBE_Instance_t    *pInstance,
                         LVDBE_Params_t      *pParams);
 
-
 void    LVDBE_SetFilters(LVDBE_Instance_t   *pInstance,
                          LVDBE_Params_t     *pParams);
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif      /* __LVDBE_PRIVATE_H__ */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
deleted file mode 100644
index c4d3403..0000000
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include <string.h> // memset
-#include "LVDBE.h"
-#include "LVDBE_Private.h"
-#include "VectorArithmetic.h"
-#include "AGC.h"
-#include "LVDBE_Coeffs.h"               /* Filter coefficients */
-#include <log/log.h>
-
-/********************************************************************************************/
-/*                                                                                          */
-/* FUNCTION:                 LVDBE_Process                                                  */
-/*                                                                                          */
-/* DESCRIPTION:                                                                             */
-/*  Process function for the Bass Enhancement module.                                       */
-/*                                                                                          */
-/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono            */
-/*  format is not supported, the calling routine must convert the mono stream to            */
-/*  mono-in-stereo.                                                                         */
-/*                                                        ___________                       */
-/*       ________                                        |           |    ________          */
-/*      |        |    _____   |------------------------->|           |   |        |         */
-/*      | 16-bit |   |     |  |    ________              |           |   | 32-bit |         */
-/* -+-->|   to   |-->| HPF |--|   |        |    _____    | AGC Mixer |-->|   to   |--|      */
-/*  |   | 32-bit |   |_____|  |   | Stereo |   |     |   |           |   | 16-bit |  |      */
-/*  |   |________|            |-->|   to   |-->| BPF |-->|           |   |________|  0      */
-/*  |                             |  Mono  |   |_____|   |___________|                \-->  */
-/*  |                             |________|                                                */
-/*  |                                                     _________                  0      */
-/*  |                                                    |         |                 |      */
-/*  |----------------------------------------------------| Volume  |-----------------|      */
-/*                                                       | Control |                        */
-/*                                                       |_________|                        */
-/*                                                                                          */
-/* PARAMETERS:                                                                              */
-/*  hInstance                 Instance handle                                               */
-/*  pInData                  Pointer to the input data                                      */
-/*  pOutData                 Pointer to the output data                                     */
-/*  NumSamples                 Number of samples in the input buffer                        */
-/*                                                                                          */
-/* RETURNS:                                                                                 */
-/*  LVDBE_SUCCESS            Succeeded                                                      */
-/*    LVDBE_TOOMANYSAMPLES    NumSamples was larger than the maximum block size             */
-/*                                                                                          */
-/* NOTES:                                                                                   */
-/*  1. The input and output data must be 32-bit format. The input is scaled by a shift      */
-/*     when converting from 16-bit format, this scaling allows for internal headroom in the */
-/*     bass enhancement algorithm.                                                          */
-/*  2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with   */
-/*     the headroom loss. This headroom loss is compensated in the volume control so the    */
-/*     overall end to end gain is odB.                                                      */
-/*                                                                                          */
-/********************************************************************************************/
-#ifndef BUILD_FLOAT
-LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
-    const LVM_INT16 *pInData, LVM_INT16 *pOutData, LVM_UINT16 NumSamples) {
-
-  LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *) hInstance;
-  LVM_INT32 *pScratch =
-      (LVM_INT32 *) pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
-  LVM_INT32 *pMono;
-  LVM_INT16 *pInput = (LVM_INT16 *) pInData;
-
-  /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
-  LVM_INT16 *pScratchVol = (LVM_INT16 *) (&pScratch[NumSamples]);
-
-  /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
-  pMono = &pScratch[2 * NumSamples];
-
-  /*
-   * Check the number of samples is not too large
-   */
-  if (NumSamples > pInstance->Capabilities.MaxBlockSize) {
-    return (LVDBE_TOOMANYSAMPLES);
-  }
-
-  /*
-   * Check if the algorithm is enabled
-   */
-  /* DBE path is processed when DBE is ON or during On/Off transitions */
-  if ((pInstance->Params.OperatingMode == LVDBE_ON)
-      || (LVC_Mixer_GetCurrent(
-          &pInstance->pData->BypassMixer.MixerStream[0])
-          != LVC_Mixer_GetTarget(
-              &pInstance->pData->BypassMixer.MixerStream[0]))) {
-
-    /*
-     * Convert 16-bit samples to 32-bit and scale
-     * (For a 16-bit implementation apply headroom loss here)
-     */
-    Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data    */
-    pScratch, /* Dest. 32-bit data     */
-    (LVM_INT16) (2 * NumSamples), /* Left and right        */
-    LVDBE_SCALESHIFT); /* Shift scale           */
-
-    /*
-     * Apply the high pass filter if selected
-     */
-    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
-      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
-      (LVM_INT32 *) pScratch, /* Source               */
-      (LVM_INT32 *) pScratch, /* Destination          */
-      (LVM_INT16) NumSamples); /* Number of samples    */
-    }
-
-    /*
-     * Create the mono stream
-     */
-    From2iToMono_32(pScratch, /* Stereo source         */
-    pMono, /* Mono destination      */
-    (LVM_INT16) NumSamples); /* Number of samples     */
-
-    /*
-     * Apply the band pass filter
-     */
-    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
-    (LVM_INT32 *) pMono, /* Source                */
-    (LVM_INT32 *) pMono, /* Destination           */
-    (LVM_INT16) NumSamples); /* Number of samples     */
-
-    /*
-     * Apply the AGC and mix
-     */
-    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
-    pScratch, /* Stereo source         */
-    pMono, /* Mono band pass source */
-    pScratch, /* Stereo destination    */
-    NumSamples); /* Number of samples     */
-
-    /*
-     * Convert 32-bit samples to 16-bit and saturate
-     * (Not required for 16-bit implemenations)
-     */
-    Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data    */
-    (LVM_INT16 *) pScratch, /* Dest. 16-bit data     */
-    (LVM_INT16) (2 * NumSamples), /* Left and right        */
-    LVDBE_SCALESHIFT); /* Shift scale           */
-
-  }
-
-  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
-  if ((pInstance->Params.OperatingMode == LVDBE_OFF)
-      || (LVC_Mixer_GetCurrent(
-          &pInstance->pData->BypassMixer.MixerStream[1])
-          != LVC_Mixer_GetTarget(
-              &pInstance->pData->BypassMixer.MixerStream[1]))) {
-
-    /*
-     * The algorithm is disabled but volume management is required to compensate for
-     * headroom and volume (if enabled)
-     */
-    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, pInData,
-        pScratchVol, (LVM_INT16) (2 * NumSamples)); /* Left and right          */
-
-  }
-
-  /*
-   * Mix DBE processed path and bypass volume path
-   */
-  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
-      (LVM_INT16 *) pScratch, pScratchVol, pOutData,
-      (LVM_INT16) (2 * NumSamples));
-
-  return (LVDBE_SUCCESS);
-}
-#else /*BUILD_FLOAT*/
-LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
-    const LVM_FLOAT *pInData,
-    LVM_FLOAT *pOutData,
-    const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
-{
-  LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
-
-  /*Extract number of Channels info*/
-#ifdef SUPPORT_MC
-  // Mono passed in as stereo
-  const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
-      ? 2 : pInstance->Params.NrChannels;
-#else
-  const LVM_INT32 NrChannels = 2; // FCC_2
-#endif
-  const LVM_INT32 NrSamples = NrChannels * NrFrames;
-
-  /* Space to store DBE path computation */
-  LVM_FLOAT * const pScratch =
-          (LVM_FLOAT *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
-
-  /*
-   * Scratch for Mono path starts at offset of
-   * NrSamples float values from pScratch.
-   */
-  LVM_FLOAT * const pMono = pScratch + NrSamples;
-
-  /*
-   * TRICKY: pMono is used and discarded by the DBE path.
-   *         so it is available for use for the pScratchVol
-   *         path which is computed afterwards.
-   *
-   * Space to store Volume Control path computation.
-   * This is identical to pMono (see TRICKY comment).
-   */
-  LVM_FLOAT * const pScratchVol = pMono;
-
-  /*
-   * Check the number of frames is not too large
-   */
-  if (NrFrames > pInstance->Capabilities.MaxBlockSize)
-  {
-    return LVDBE_TOOMANYSAMPLES;
-  }
-
-  /*
-   * Check if the algorithm is enabled
-   */
-  /* DBE path is processed when DBE is ON or during On/Off transitions */
-  if ((pInstance->Params.OperatingMode == LVDBE_ON)||
-      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
-          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
-  {
-    // make copy of input data
-    Copy_Float(pInData,
-        pScratch,
-        (LVM_INT16)NrSamples);
-
-    /*
-     * Apply the high pass filter if selected
-     */
-    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
-    {
-#ifdef SUPPORT_MC
-      BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance      */
-          pScratch, /* Source               */
-          pScratch, /* Destination          */
-          (LVM_INT16)NrFrames,
-          (LVM_INT16)NrChannels);
-#else
-      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
-          pScratch, /* Source               */
-          pScratch, /* Destination          */
-          (LVM_INT16)NrFrames);
-#endif
-    }
-
-    /*
-     * Create the mono stream
-     */
-#ifdef SUPPORT_MC
-    FromMcToMono_Float(pScratch, /* Source */
-        pMono, /* Mono destination */
-        (LVM_INT16)NrFrames,  /* Number of frames */
-        (LVM_INT16)NrChannels);
-#else
-    From2iToMono_Float(pScratch, /* Stereo source         */
-        pMono, /* Mono destination      */
-        (LVM_INT16)NrFrames);
-#endif
-
-    /*
-     * Apply the band pass filter
-     */
-    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
-        pMono, /* Source                */
-        pMono, /* Destination           */
-        (LVM_INT16)NrFrames);
-
-    /*
-     * Apply the AGC and mix
-     */
-#ifdef SUPPORT_MC
-    AGC_MIX_VOL_Mc1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
-        pScratch, /* Source         */
-        pMono, /* Mono band pass source */
-        pScratch, /* Destination    */
-        NrFrames, /* Number of frames     */
-        NrChannels); /* Number of channels     */
-#else
-    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
-        pScratch, /* Stereo source         */
-        pMono, /* Mono band pass source */
-        pScratch, /* Stereo destination    */
-        NrFrames);
-#endif
-
-    for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
-      //TODO: replace with existing clamping function
-      if (pScratch[ii] < -1.0) {
-        pScratch[ii] = -1.0;
-      } else if (pScratch[ii] > 1.0) {
-        pScratch[ii] = 1.0;
-      }
-    }
-  } else {
-    // clear DBE processed path
-    memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
-  }
-
-  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
-  if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
-      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
-          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
-  {
-
-    /*
-     * The algorithm is disabled but volume management is required to compensate for
-     * headroom and volume (if enabled)
-     */
-#ifdef SUPPORT_MC
-    LVC_MixSoft_Mc_D16C31_SAT(&pInstance->pData->BypassVolume,
-        pInData,
-        pScratchVol,
-        (LVM_INT16)NrFrames,
-        (LVM_INT16)NrChannels);
-#else
-    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
-        pInData,
-        pScratchVol,
-        (LVM_INT16)NrSamples); /* Left and right, really # samples */
-#endif
-  } else {
-    // clear bypass volume path
-    memset(pScratchVol, 0, sizeof(*pScratchVol) * NrSamples);
-  }
-
-  /*
-   * Mix DBE processed path and bypass volume path
-   */
-#ifdef SUPPORT_MC
-  LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->pData->BypassMixer,
-      pScratch,
-      pScratchVol,
-      pOutData,
-      (LVM_INT16)NrFrames,
-      (LVM_INT16)NrChannels);
-#else
-  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
-      pScratch,
-      pScratchVol,
-      pOutData,
-      (LVM_INT16)NrSamples);
-#endif
-  return LVDBE_SUCCESS;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
new file mode 100644
index 0000000..b4a71c7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include <string.h> // memset
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "AGC.h"
+#include "LVDBE_Coeffs.h"               /* Filter coefficients */
+#include <log/log.h>
+
+/********************************************************************************************/
+/*                                                                                          */
+/* FUNCTION:                 LVDBE_Process                                                  */
+/*                                                                                          */
+/* DESCRIPTION:                                                                             */
+/*  Process function for the Bass Enhancement module.                                       */
+/*                                                                                          */
+/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono            */
+/*  format is not supported, the calling routine must convert the mono stream to            */
+/*  mono-in-stereo.                                                                         */
+/*                                                        ___________                       */
+/*       ________                                        |           |    ________          */
+/*      |        |    _____   |------------------------->|           |   |        |         */
+/*      | 16-bit |   |     |  |    ________              |           |   | 32-bit |         */
+/* -+-->|   to   |-->| HPF |--|   |        |    _____    | AGC Mixer |-->|   to   |--|      */
+/*  |   | 32-bit |   |_____|  |   | Stereo |   |     |   |           |   | 16-bit |  |      */
+/*  |   |________|            |-->|   to   |-->| BPF |-->|           |   |________|  0      */
+/*  |                             |  Mono  |   |_____|   |___________|                \-->  */
+/*  |                             |________|                                                */
+/*  |                                                     _________                  0      */
+/*  |                                                    |         |                 |      */
+/*  |----------------------------------------------------| Volume  |-----------------|      */
+/*                                                       | Control |                        */
+/*                                                       |_________|                        */
+/*                                                                                          */
+/* PARAMETERS:                                                                              */
+/*  hInstance                 Instance handle                                               */
+/*  pInData                  Pointer to the input data                                      */
+/*  pOutData                 Pointer to the output data                                     */
+/*  NumSamples                 Number of samples in the input buffer                        */
+/*                                                                                          */
+/* RETURNS:                                                                                 */
+/*  LVDBE_SUCCESS            Succeeded                                                      */
+/*    LVDBE_TOOMANYSAMPLES    NumSamples was larger than the maximum block size             */
+/*                                                                                          */
+/* NOTES:                                                                                   */
+/*  1. The input and output data must be 32-bit format. The input is scaled by a shift      */
+/*     when converting from 16-bit format, this scaling allows for internal headroom in the */
+/*     bass enhancement algorithm.                                                          */
+/*  2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with   */
+/*     the headroom loss. This headroom loss is compensated in the volume control so the    */
+/*     overall end to end gain is odB.                                                      */
+/*                                                                                          */
+/********************************************************************************************/
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
+    const LVM_FLOAT *pInData,
+    LVM_FLOAT *pOutData,
+    const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
+{
+  LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+
+  /*Extract number of Channels info*/
+#ifdef SUPPORT_MC
+  // Mono passed in as stereo
+  const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
+      ? 2 : pInstance->Params.NrChannels;
+#else
+  const LVM_INT32 NrChannels = 2; // FCC_2
+#endif
+  const LVM_INT32 NrSamples = NrChannels * NrFrames;
+
+  /* Space to store DBE path computation */
+  LVM_FLOAT * const pScratch =
+          (LVM_FLOAT *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
+
+  /*
+   * Scratch for Mono path starts at offset of
+   * NrSamples float values from pScratch.
+   */
+  LVM_FLOAT * const pMono = pScratch + NrSamples;
+
+  /*
+   * TRICKY: pMono is used and discarded by the DBE path.
+   *         so it is available for use for the pScratchVol
+   *         path which is computed afterwards.
+   *
+   * Space to store Volume Control path computation.
+   * This is identical to pMono (see TRICKY comment).
+   */
+  LVM_FLOAT * const pScratchVol = pMono;
+
+  /*
+   * Check the number of frames is not too large
+   */
+  if (NrFrames > pInstance->Capabilities.MaxBlockSize)
+  {
+    return LVDBE_TOOMANYSAMPLES;
+  }
+
+  /*
+   * Check if the algorithm is enabled
+   */
+  /* DBE path is processed when DBE is ON or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_ON)||
+      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
+          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
+  {
+    // make copy of input data
+    Copy_Float(pInData,
+        pScratch,
+        (LVM_INT16)NrSamples);
+
+    /*
+     * Apply the high pass filter if selected
+     */
+    if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
+    {
+#ifdef SUPPORT_MC
+      BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance      */
+          pScratch, /* Source               */
+          pScratch, /* Destination          */
+          (LVM_INT16)NrFrames,
+          (LVM_INT16)NrChannels);
+#else
+      BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance      */
+          pScratch, /* Source               */
+          pScratch, /* Destination          */
+          (LVM_INT16)NrFrames);
+#endif
+    }
+
+    /*
+     * Create the mono stream
+     */
+#ifdef SUPPORT_MC
+    FromMcToMono_Float(pScratch, /* Source */
+        pMono, /* Mono destination */
+        (LVM_INT16)NrFrames,  /* Number of frames */
+        (LVM_INT16)NrChannels);
+#else
+    From2iToMono_Float(pScratch, /* Stereo source         */
+        pMono, /* Mono destination      */
+        (LVM_INT16)NrFrames);
+#endif
+
+    /*
+     * Apply the band pass filter
+     */
+    BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance       */
+        pMono, /* Source                */
+        pMono, /* Destination           */
+        (LVM_INT16)NrFrames);
+
+    /*
+     * Apply the AGC and mix
+     */
+#ifdef SUPPORT_MC
+    AGC_MIX_VOL_Mc1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
+        pScratch, /* Source         */
+        pMono, /* Mono band pass source */
+        pScratch, /* Destination    */
+        NrFrames, /* Number of frames     */
+        NrChannels); /* Number of channels     */
+#else
+    AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer      */
+        pScratch, /* Stereo source         */
+        pMono, /* Mono band pass source */
+        pScratch, /* Stereo destination    */
+        NrFrames);
+#endif
+
+    for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
+      //TODO: replace with existing clamping function
+      if (pScratch[ii] < -1.0) {
+        pScratch[ii] = -1.0;
+      } else if (pScratch[ii] > 1.0) {
+        pScratch[ii] = 1.0;
+      }
+    }
+  } else {
+    // clear DBE processed path
+    memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
+  }
+
+  /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
+  if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
+      (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
+          !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
+  {
+
+    /*
+     * The algorithm is disabled but volume management is required to compensate for
+     * headroom and volume (if enabled)
+     */
+#ifdef SUPPORT_MC
+    LVC_MixSoft_Mc_D16C31_SAT(&pInstance->pData->BypassVolume,
+        pInData,
+        pScratchVol,
+        (LVM_INT16)NrFrames,
+        (LVM_INT16)NrChannels);
+#else
+    LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
+        pInData,
+        pScratchVol,
+        (LVM_INT16)NrSamples); /* Left and right, really # samples */
+#endif
+  } else {
+    // clear bypass volume path
+    memset(pScratchVol, 0, sizeof(*pScratchVol) * NrSamples);
+  }
+
+  /*
+   * Mix DBE processed path and bypass volume path
+   */
+#ifdef SUPPORT_MC
+  LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->pData->BypassMixer,
+      pScratch,
+      pScratchVol,
+      pOutData,
+      (LVM_INT16)NrFrames,
+      (LVM_INT16)NrChannels);
+#else
+  LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
+      pScratch,
+      pScratchVol,
+      pOutData,
+      (LVM_INT16)NrSamples);
+#endif
+  return LVDBE_SUCCESS;
+}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
deleted file mode 100644
index a2ce404..0000000
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Includes                                                                      */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVDBE.h"
-#include "LVDBE_Coeffs.h"               /* Filter coefficients */
-#include "BIQUAD.h"
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Coefficients constant table                                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * High Pass Filter Coefficient table
- */
-#ifndef BUILD_FLOAT
-const BQ_C32_Coefs_t LVDBE_HPF_Table[] = {
-#else /*BUILD_FLOAT*/
-const BQ_FLOAT_Coefs_t LVDBE_HPF_Table[] = {
-#endif /*BUILD_FLOAT*/
-    /* Coefficients for 55Hz centre frequency */
-    {HPF_Fs8000_Fc55_A2,                /* 8kS/s coefficients */
-     HPF_Fs8000_Fc55_A1,
-     HPF_Fs8000_Fc55_A0,
-     -HPF_Fs8000_Fc55_B2,
-     -HPF_Fs8000_Fc55_B1},
-    {HPF_Fs11025_Fc55_A2,                /* 11kS/s coefficients */
-     HPF_Fs11025_Fc55_A1,
-     HPF_Fs11025_Fc55_A0,
-     -HPF_Fs11025_Fc55_B2,
-     -HPF_Fs11025_Fc55_B1},
-    {HPF_Fs12000_Fc55_A2,                /* 12kS/s coefficients */
-     HPF_Fs12000_Fc55_A1,
-     HPF_Fs12000_Fc55_A0,
-     -HPF_Fs12000_Fc55_B2,
-     -HPF_Fs12000_Fc55_B1},
-    {HPF_Fs16000_Fc55_A2,                /* 16kS/s coefficients */
-     HPF_Fs16000_Fc55_A1,
-     HPF_Fs16000_Fc55_A0,
-     -HPF_Fs16000_Fc55_B2,
-     -HPF_Fs16000_Fc55_B1},
-    {HPF_Fs22050_Fc55_A2,                /* 22kS/s coefficients */
-     HPF_Fs22050_Fc55_A1,
-     HPF_Fs22050_Fc55_A0,
-     -HPF_Fs22050_Fc55_B2,
-     -HPF_Fs22050_Fc55_B1},
-    {HPF_Fs24000_Fc55_A2,                /* 24kS/s coefficients */
-     HPF_Fs24000_Fc55_A1,
-     HPF_Fs24000_Fc55_A0,
-     -HPF_Fs24000_Fc55_B2,
-     -HPF_Fs24000_Fc55_B1},
-    {HPF_Fs32000_Fc55_A2,                /* 32kS/s coefficients */
-     HPF_Fs32000_Fc55_A1,
-     HPF_Fs32000_Fc55_A0,
-     -HPF_Fs32000_Fc55_B2,
-     -HPF_Fs32000_Fc55_B1},
-    {HPF_Fs44100_Fc55_A2,                /* 44kS/s coefficients */
-     HPF_Fs44100_Fc55_A1,
-     HPF_Fs44100_Fc55_A0,
-     -HPF_Fs44100_Fc55_B2,
-     -HPF_Fs44100_Fc55_B1},
-    {HPF_Fs48000_Fc55_A2,                /* 48kS/s coefficients */
-     HPF_Fs48000_Fc55_A1,
-     HPF_Fs48000_Fc55_A0,
-     -HPF_Fs48000_Fc55_B2,
-     -HPF_Fs48000_Fc55_B1},
-#ifdef HIGHER_FS
-    {HPF_Fs88200_Fc55_A2,                /* 88kS/s coefficients */
-     HPF_Fs88200_Fc55_A1,
-     HPF_Fs88200_Fc55_A0,
-     -HPF_Fs88200_Fc55_B2,
-     -HPF_Fs88200_Fc55_B1},
-    {HPF_Fs96000_Fc55_A2,                /* 96kS/s coefficients */
-     HPF_Fs96000_Fc55_A1,
-     HPF_Fs96000_Fc55_A0,
-     -HPF_Fs96000_Fc55_B2,
-     -HPF_Fs96000_Fc55_B1},
-    {HPF_Fs176400_Fc55_A2,                /* 176kS/s coefficients */
-     HPF_Fs176400_Fc55_A1,
-     HPF_Fs176400_Fc55_A0,
-     -HPF_Fs176400_Fc55_B2,
-     -HPF_Fs176400_Fc55_B1},
-    {HPF_Fs192000_Fc55_A2,                /* 192kS/s coefficients */
-     HPF_Fs192000_Fc55_A1,
-     HPF_Fs192000_Fc55_A0,
-     -HPF_Fs192000_Fc55_B2,
-     -HPF_Fs192000_Fc55_B1},
-#endif
-
-    /* Coefficients for 66Hz centre frequency */
-    {HPF_Fs8000_Fc66_A2,                /* 8kS/s coefficients */
-     HPF_Fs8000_Fc66_A1,
-     HPF_Fs8000_Fc66_A0,
-     -HPF_Fs8000_Fc66_B2,
-     -HPF_Fs8000_Fc66_B1},
-    {HPF_Fs11025_Fc66_A2,                /* 11kS/s coefficients */
-     HPF_Fs11025_Fc66_A1,
-     HPF_Fs11025_Fc66_A0,
-     -HPF_Fs11025_Fc66_B2,
-     -HPF_Fs11025_Fc66_B1},
-    {HPF_Fs12000_Fc66_A2,                /* 12kS/s coefficients */
-     HPF_Fs12000_Fc66_A1,
-     HPF_Fs12000_Fc66_A0,
-     -HPF_Fs12000_Fc66_B2,
-     -HPF_Fs12000_Fc66_B1},
-    {HPF_Fs16000_Fc66_A2,                /* 16kS/s coefficients */
-     HPF_Fs16000_Fc66_A1,
-     HPF_Fs16000_Fc66_A0,
-     -HPF_Fs16000_Fc66_B2,
-     -HPF_Fs16000_Fc66_B1},
-    {HPF_Fs22050_Fc66_A2,                /* 22kS/s coefficients */
-     HPF_Fs22050_Fc66_A1,
-     HPF_Fs22050_Fc66_A0,
-     -HPF_Fs22050_Fc66_B2,
-     -HPF_Fs22050_Fc66_B1},
-    {HPF_Fs24000_Fc66_A2,                /* 24kS/s coefficients */
-     HPF_Fs24000_Fc66_A1,
-     HPF_Fs24000_Fc66_A0,
-     -HPF_Fs24000_Fc66_B2,
-     -HPF_Fs24000_Fc66_B1},
-    {HPF_Fs32000_Fc66_A2,                /* 32kS/s coefficients */
-     HPF_Fs32000_Fc66_A1,
-     HPF_Fs32000_Fc66_A0,
-     -HPF_Fs32000_Fc66_B2,
-     -HPF_Fs32000_Fc66_B1},
-    {HPF_Fs44100_Fc66_A2,                /* 44kS/s coefficients */
-     HPF_Fs44100_Fc66_A1,
-     HPF_Fs44100_Fc66_A0,
-     -HPF_Fs44100_Fc66_B2,
-     -HPF_Fs44100_Fc66_B1},
-    {HPF_Fs48000_Fc66_A2,                /* 48kS/s coefficients */
-     HPF_Fs48000_Fc66_A1,
-     HPF_Fs48000_Fc66_A0,
-     -HPF_Fs48000_Fc66_B2,
-     -HPF_Fs48000_Fc66_B1},
-#ifdef HIGHER_FS
-    {HPF_Fs88200_Fc66_A2,                /* 88kS/s coefficients */
-     HPF_Fs88200_Fc66_A1,
-     HPF_Fs88200_Fc66_A0,
-     -HPF_Fs88200_Fc66_B2,
-     -HPF_Fs88200_Fc66_B1},
-    {HPF_Fs96000_Fc66_A2,                /* 96kS/s coefficients */
-     HPF_Fs96000_Fc66_A1,
-     HPF_Fs96000_Fc66_A0,
-     -HPF_Fs96000_Fc66_B2,
-     -HPF_Fs96000_Fc66_B1},
-    {HPF_Fs176400_Fc66_A2,                /* 176kS/s coefficients */
-     HPF_Fs176400_Fc66_A1,
-     HPF_Fs176400_Fc66_A0,
-     -HPF_Fs176400_Fc66_B2,
-     -HPF_Fs176400_Fc66_B1},
-    {HPF_Fs192000_Fc66_A2,                /* 192kS/s coefficients */
-     HPF_Fs192000_Fc66_A1,
-     HPF_Fs192000_Fc66_A0,
-     -HPF_Fs192000_Fc66_B2,
-     -HPF_Fs192000_Fc66_B1},
-#endif
-
-
-    /* Coefficients for 78Hz centre frequency */
-    {HPF_Fs8000_Fc78_A2,                /* 8kS/s coefficients */
-     HPF_Fs8000_Fc78_A1,
-     HPF_Fs8000_Fc78_A0,
-     -HPF_Fs8000_Fc78_B2,
-     -HPF_Fs8000_Fc78_B1},
-    {HPF_Fs11025_Fc78_A2,                /* 11kS/s coefficients */
-     HPF_Fs11025_Fc78_A1,
-     HPF_Fs11025_Fc78_A0,
-     -HPF_Fs11025_Fc78_B2,
-     -HPF_Fs11025_Fc78_B1},
-    {HPF_Fs12000_Fc78_A2,                /* 12kS/s coefficients */
-     HPF_Fs12000_Fc78_A1,
-     HPF_Fs12000_Fc78_A0,
-     -HPF_Fs12000_Fc78_B2,
-     -HPF_Fs12000_Fc78_B1},
-    {HPF_Fs16000_Fc78_A2,                /* 16kS/s coefficients */
-     HPF_Fs16000_Fc78_A1,
-     HPF_Fs16000_Fc78_A0,
-     -HPF_Fs16000_Fc78_B2,
-     -HPF_Fs16000_Fc78_B1},
-    {HPF_Fs22050_Fc78_A2,                /* 22kS/s coefficients */
-     HPF_Fs22050_Fc78_A1,
-     HPF_Fs22050_Fc78_A0,
-     -HPF_Fs22050_Fc78_B2,
-     -HPF_Fs22050_Fc78_B1},
-    {HPF_Fs24000_Fc78_A2,                /* 24kS/s coefficients */
-     HPF_Fs24000_Fc78_A1,
-     HPF_Fs24000_Fc78_A0,
-     -HPF_Fs24000_Fc78_B2,
-     -HPF_Fs24000_Fc78_B1},
-    {HPF_Fs32000_Fc78_A2,                /* 32kS/s coefficients */
-     HPF_Fs32000_Fc78_A1,
-     HPF_Fs32000_Fc78_A0,
-     -HPF_Fs32000_Fc78_B2,
-     -HPF_Fs32000_Fc78_B1},
-    {HPF_Fs44100_Fc78_A2,                /* 44kS/s coefficients */
-     HPF_Fs44100_Fc78_A1,
-     HPF_Fs44100_Fc78_A0,
-     -HPF_Fs44100_Fc78_B2,
-     -HPF_Fs44100_Fc78_B1},
-    {HPF_Fs48000_Fc78_A2,                /* 48kS/s coefficients */
-     HPF_Fs48000_Fc78_A1,
-     HPF_Fs48000_Fc78_A0,
-     -HPF_Fs48000_Fc78_B2,
-     -HPF_Fs48000_Fc78_B1},
-#ifdef HIGHER_FS
-    {HPF_Fs88200_Fc78_A2,                /* 88kS/s coefficients */
-     HPF_Fs88200_Fc78_A1,
-     HPF_Fs88200_Fc78_A0,
-     -HPF_Fs88200_Fc78_B2,
-     -HPF_Fs88200_Fc78_B1},
-    {HPF_Fs96000_Fc78_A2,                /* 96kS/s coefficients */
-     HPF_Fs96000_Fc78_A1,
-     HPF_Fs96000_Fc78_A0,
-     -HPF_Fs96000_Fc78_B2,
-     -HPF_Fs96000_Fc78_B1},
-    {HPF_Fs176400_Fc78_A2,                /* 176kS/s coefficients */
-     HPF_Fs176400_Fc78_A1,
-     HPF_Fs176400_Fc78_A0,
-     -HPF_Fs176400_Fc78_B2,
-     -HPF_Fs176400_Fc78_B1},
-    {HPF_Fs192000_Fc78_A2,                /* 192kS/s coefficients */
-     HPF_Fs192000_Fc78_A1,
-     HPF_Fs192000_Fc78_A0,
-     -HPF_Fs192000_Fc78_B2,
-     -HPF_Fs192000_Fc78_B1},
-#endif
-
-
-    /* Coefficients for 90Hz centre frequency */
-    {HPF_Fs8000_Fc90_A2,                /* 8kS/s coefficients */
-     HPF_Fs8000_Fc90_A1,
-     HPF_Fs8000_Fc90_A0,
-     -HPF_Fs8000_Fc90_B2,
-     -HPF_Fs8000_Fc90_B1},
-    {HPF_Fs11025_Fc90_A2,                /* 11kS/s coefficients */
-     HPF_Fs11025_Fc90_A1,
-     HPF_Fs11025_Fc90_A0,
-     -HPF_Fs11025_Fc90_B2,
-     -HPF_Fs11025_Fc90_B1},
-    {HPF_Fs12000_Fc90_A2,                /* 12kS/s coefficients */
-     HPF_Fs12000_Fc90_A1,
-     HPF_Fs12000_Fc90_A0,
-     -HPF_Fs12000_Fc90_B2,
-     -HPF_Fs12000_Fc90_B1},
-    {HPF_Fs16000_Fc90_A2,                /* 16kS/s coefficients */
-     HPF_Fs16000_Fc90_A1,
-     HPF_Fs16000_Fc90_A0,
-     -HPF_Fs16000_Fc90_B2,
-     -HPF_Fs16000_Fc90_B1},
-    {HPF_Fs22050_Fc90_A2,                /* 22kS/s coefficients */
-     HPF_Fs22050_Fc90_A1,
-     HPF_Fs22050_Fc90_A0,
-     -HPF_Fs22050_Fc90_B2,
-     -HPF_Fs22050_Fc90_B1},
-    {HPF_Fs24000_Fc90_A2,                /* 24kS/s coefficients */
-     HPF_Fs24000_Fc90_A1,
-     HPF_Fs24000_Fc90_A0,
-     -HPF_Fs24000_Fc90_B2,
-     -HPF_Fs24000_Fc90_B1},
-    {HPF_Fs32000_Fc90_A2,                /* 32kS/s coefficients */
-     HPF_Fs32000_Fc90_A1,
-     HPF_Fs32000_Fc90_A0,
-     -HPF_Fs32000_Fc90_B2,
-     -HPF_Fs32000_Fc90_B1},
-    {HPF_Fs44100_Fc90_A2,                /* 44kS/s coefficients */
-     HPF_Fs44100_Fc90_A1,
-     HPF_Fs44100_Fc90_A0,
-     -HPF_Fs44100_Fc90_B2,
-     -HPF_Fs44100_Fc90_B1},
-    {HPF_Fs48000_Fc90_A2,                /* 48kS/s coefficients */
-     HPF_Fs48000_Fc90_A1,
-     HPF_Fs48000_Fc90_A0,
-     -HPF_Fs48000_Fc90_B2,
-     -HPF_Fs48000_Fc90_B1}
-
-#ifdef HIGHER_FS
-    ,
-    {HPF_Fs88200_Fc90_A2,                /* 88kS/s coefficients */
-     HPF_Fs88200_Fc90_A1,
-     HPF_Fs88200_Fc90_A0,
-     -HPF_Fs88200_Fc90_B2,
-     -HPF_Fs88200_Fc90_B1},
-    {HPF_Fs96000_Fc90_A2,                /* 96kS/s coefficients */
-     HPF_Fs96000_Fc90_A1,
-     HPF_Fs96000_Fc90_A0,
-     -HPF_Fs96000_Fc90_B2,
-     -HPF_Fs96000_Fc90_B1},
-    {HPF_Fs176400_Fc90_A2,                /* 176kS/s coefficients */
-     HPF_Fs176400_Fc90_A1,
-     HPF_Fs176400_Fc90_A0,
-     -HPF_Fs176400_Fc90_B2,
-     -HPF_Fs176400_Fc90_B1},
-    {HPF_Fs192000_Fc90_A2,                /* 192kS/s coefficients */
-     HPF_Fs192000_Fc90_A1,
-     HPF_Fs192000_Fc90_A0,
-     -HPF_Fs192000_Fc90_B2,
-     -HPF_Fs192000_Fc90_B1}
-#endif
-
-};
-
-/*
- * Band Pass Filter coefficient table
- */
-#ifndef BUILD_FLOAT
-const BP_C32_Coefs_t LVDBE_BPF_Table[] = {
-#else /*BUILD_FLOAT*/
-const BP_FLOAT_Coefs_t LVDBE_BPF_Table[] = {
-#endif /*BUILD_FLOAT*/
-    /* Coefficients for 55Hz centre frequency */
-    {BPF_Fs8000_Fc55_A0,                /* 8kS/s coefficients */
-     -BPF_Fs8000_Fc55_B2,
-     -BPF_Fs8000_Fc55_B1},
-    {BPF_Fs11025_Fc55_A0,                /* 11kS/s coefficients */
-     -BPF_Fs11025_Fc55_B2,
-     -BPF_Fs11025_Fc55_B1},
-    {BPF_Fs12000_Fc55_A0,                /* 12kS/s coefficients */
-     -BPF_Fs12000_Fc55_B2,
-     -BPF_Fs12000_Fc55_B1},
-    {BPF_Fs16000_Fc55_A0,                /* 16kS/s coefficients */
-     -BPF_Fs16000_Fc55_B2,
-     -BPF_Fs16000_Fc55_B1},
-    {BPF_Fs22050_Fc55_A0,                /* 22kS/s coefficients */
-     -BPF_Fs22050_Fc55_B2,
-     -BPF_Fs22050_Fc55_B1},
-    {BPF_Fs24000_Fc55_A0,                /* 24kS/s coefficients */
-     -BPF_Fs24000_Fc55_B2,
-     -BPF_Fs24000_Fc55_B1},
-    {BPF_Fs32000_Fc55_A0,                /* 32kS/s coefficients */
-     -BPF_Fs32000_Fc55_B2,
-     -BPF_Fs32000_Fc55_B1},
-    {BPF_Fs44100_Fc55_A0,                /* 44kS/s coefficients */
-     -BPF_Fs44100_Fc55_B2,
-     -BPF_Fs44100_Fc55_B1},
-    {BPF_Fs48000_Fc55_A0,                /* 48kS/s coefficients */
-     -BPF_Fs48000_Fc55_B2,
-     -BPF_Fs48000_Fc55_B1},
-#ifdef HIGHER_FS
-     {BPF_Fs88200_Fc55_A0,                /* 88kS/s coefficients */
-      -BPF_Fs88200_Fc55_B2,
-      -BPF_Fs88200_Fc55_B1},
-     {BPF_Fs96000_Fc55_A0,                /* 96kS/s coefficients */
-     -BPF_Fs96000_Fc55_B2,
-     -BPF_Fs96000_Fc55_B1},
-     {BPF_Fs176400_Fc55_A0,                /* 176kS/s coefficients */
-      -BPF_Fs176400_Fc55_B2,
-      -BPF_Fs176400_Fc55_B1},
-     {BPF_Fs192000_Fc55_A0,                /* 192kS/s coefficients */
-     -BPF_Fs192000_Fc55_B2,
-     -BPF_Fs192000_Fc55_B1},
-#endif
-
-    /* Coefficients for 66Hz centre frequency */
-    {BPF_Fs8000_Fc66_A0,                /* 8kS/s coefficients */
-     -BPF_Fs8000_Fc66_B2,
-     -BPF_Fs8000_Fc66_B1},
-    {BPF_Fs11025_Fc66_A0,                /* 11kS/s coefficients */
-     -BPF_Fs11025_Fc66_B2,
-     -BPF_Fs11025_Fc66_B1},
-    {BPF_Fs12000_Fc66_A0,                /* 12kS/s coefficients */
-     -BPF_Fs12000_Fc66_B2,
-     -BPF_Fs12000_Fc66_B1},
-    {BPF_Fs16000_Fc66_A0,                /* 16kS/s coefficients */
-     -BPF_Fs16000_Fc66_B2,
-     -BPF_Fs16000_Fc66_B1},
-    {BPF_Fs22050_Fc66_A0,                /* 22kS/s coefficients */
-     -BPF_Fs22050_Fc66_B2,
-     -BPF_Fs22050_Fc66_B1},
-    {BPF_Fs24000_Fc66_A0,                /* 24kS/s coefficients */
-     -BPF_Fs24000_Fc66_B2,
-     -BPF_Fs24000_Fc66_B1},
-    {BPF_Fs32000_Fc66_A0,                /* 32kS/s coefficients */
-     -BPF_Fs32000_Fc66_B2,
-     -BPF_Fs32000_Fc66_B1},
-    {BPF_Fs44100_Fc66_A0,                /* 44kS/s coefficients */
-     -BPF_Fs44100_Fc66_B2,
-     -BPF_Fs44100_Fc66_B1},
-    {BPF_Fs48000_Fc66_A0,                /* 48kS/s coefficients */
-     -BPF_Fs48000_Fc66_B2,
-     -BPF_Fs48000_Fc66_B1},
-#ifdef HIGHER_FS
-    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
-     -BPF_Fs88200_Fc66_B2,
-     -BPF_Fs88200_Fc66_B1},
-    {BPF_Fs96000_Fc66_A0,                /* 96kS/s coefficients */
-     -BPF_Fs96000_Fc66_B2,
-     -BPF_Fs96000_Fc66_B1},
-    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
-     -BPF_Fs176400_Fc66_B2,
-     -BPF_Fs176400_Fc66_B1},
-    {BPF_Fs192000_Fc66_A0,                /* 192kS/s coefficients */
-     -BPF_Fs192000_Fc66_B2,
-     -BPF_Fs192000_Fc66_B1},
-#endif
-
-    /* Coefficients for 78Hz centre frequency */
-    {BPF_Fs8000_Fc78_A0,                /* 8kS/s coefficients */
-     -BPF_Fs8000_Fc78_B2,
-     -BPF_Fs8000_Fc78_B1},
-    {BPF_Fs11025_Fc78_A0,                /* 11kS/s coefficients */
-     -BPF_Fs11025_Fc78_B2,
-     -BPF_Fs11025_Fc78_B1},
-    {BPF_Fs12000_Fc78_A0,                /* 12kS/s coefficients */
-     -BPF_Fs12000_Fc78_B2,
-     -BPF_Fs12000_Fc78_B1},
-    {BPF_Fs16000_Fc78_A0,                /* 16kS/s coefficients */
-     -BPF_Fs16000_Fc78_B2,
-     -BPF_Fs16000_Fc78_B1},
-    {BPF_Fs22050_Fc78_A0,                /* 22kS/s coefficients */
-     -BPF_Fs22050_Fc78_B2,
-     -BPF_Fs22050_Fc78_B1},
-    {BPF_Fs24000_Fc78_A0,                /* 24kS/s coefficients */
-     -BPF_Fs24000_Fc78_B2,
-     -BPF_Fs24000_Fc78_B1},
-    {BPF_Fs32000_Fc78_A0,                /* 32kS/s coefficients */
-     -BPF_Fs32000_Fc78_B2,
-     -BPF_Fs32000_Fc78_B1},
-    {BPF_Fs44100_Fc78_A0,                /* 44kS/s coefficients */
-     -BPF_Fs44100_Fc78_B2,
-     -BPF_Fs44100_Fc78_B1},
-    {BPF_Fs48000_Fc78_A0,                /* 48kS/s coefficients */
-     -BPF_Fs48000_Fc78_B2,
-     -BPF_Fs48000_Fc78_B1},
-#ifdef HIGHER_FS
-    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
-     -BPF_Fs88200_Fc66_B2,
-     -BPF_Fs88200_Fc66_B1},
-    {BPF_Fs96000_Fc78_A0,                /* 96kS/s coefficients */
-     -BPF_Fs96000_Fc78_B2,
-     -BPF_Fs96000_Fc78_B1},
-    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
-     -BPF_Fs176400_Fc66_B2,
-     -BPF_Fs176400_Fc66_B1},
-    {BPF_Fs192000_Fc78_A0,                /* 192kS/s coefficients */
-     -BPF_Fs192000_Fc78_B2,
-     -BPF_Fs192000_Fc78_B1},
-#endif
-
-    /* Coefficients for 90Hz centre frequency */
-    {BPF_Fs8000_Fc90_A0,                /* 8kS/s coefficients */
-     -BPF_Fs8000_Fc90_B2,
-     -BPF_Fs8000_Fc90_B1},
-    {BPF_Fs11025_Fc90_A0,                /* 11kS/s coefficients */
-     -BPF_Fs11025_Fc90_B2,
-     -BPF_Fs11025_Fc90_B1},
-    {BPF_Fs12000_Fc90_A0,                /* 12kS/s coefficients */
-     -BPF_Fs12000_Fc90_B2,
-     -BPF_Fs12000_Fc90_B1},
-    {BPF_Fs16000_Fc90_A0,                /* 16kS/s coefficients */
-     -BPF_Fs16000_Fc90_B2,
-     -BPF_Fs16000_Fc90_B1},
-    {BPF_Fs22050_Fc90_A0,                /* 22kS/s coefficients */
-     -BPF_Fs22050_Fc90_B2,
-     -BPF_Fs22050_Fc90_B1},
-    {BPF_Fs24000_Fc90_A0,                /* 24kS/s coefficients */
-     -BPF_Fs24000_Fc90_B2,
-     -BPF_Fs24000_Fc90_B1},
-    {BPF_Fs32000_Fc90_A0,                /* 32kS/s coefficients */
-     -BPF_Fs32000_Fc90_B2,
-     -BPF_Fs32000_Fc90_B1},
-    {BPF_Fs44100_Fc90_A0,                /* 44kS/s coefficients */
-     -BPF_Fs44100_Fc90_B2,
-     -BPF_Fs44100_Fc90_B1},
-    {BPF_Fs48000_Fc90_A0,                /* 48kS/s coefficients */
-     -BPF_Fs48000_Fc90_B2,
-     -BPF_Fs48000_Fc90_B1}
-#ifdef HIGHER_FS
-    ,
-    {BPF_Fs88200_Fc90_A0,                /* 88kS/s coefficients */
-     -BPF_Fs88200_Fc90_B2,
-     -BPF_Fs88200_Fc90_B1},
-    {BPF_Fs96000_Fc90_A0,                /* 96kS/s coefficients */
-     -BPF_Fs96000_Fc90_B2,
-     -BPF_Fs96000_Fc90_B1},
-    {BPF_Fs176400_Fc90_A0,                /* 176kS/s coefficients */
-     -BPF_Fs176400_Fc90_B2,
-     -BPF_Fs176400_Fc90_B1},
-    {BPF_Fs192000_Fc90_A0,                /* 192kS/s coefficients */
-     -BPF_Fs192000_Fc90_B2,
-     -BPF_Fs192000_Fc90_B1}
-#endif
-
-
-};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    AGC constant tables                                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Attack time (signal too large) */
-#ifndef BUILD_FLOAT
-const LVM_INT16 LVDBE_AGC_ATTACK_Table[] = {
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_AGC_ATTACK_Table[] = {
-#endif /*BUILD_FLOAT*/
-    AGC_ATTACK_Fs8000,
-    AGC_ATTACK_Fs11025,
-    AGC_ATTACK_Fs12000,
-    AGC_ATTACK_Fs16000,
-    AGC_ATTACK_Fs22050,
-    AGC_ATTACK_Fs24000,
-    AGC_ATTACK_Fs32000,
-    AGC_ATTACK_Fs44100,
-    AGC_ATTACK_Fs48000
-#ifdef HIGHER_FS
-    ,AGC_ATTACK_Fs88200
-    ,AGC_ATTACK_Fs96000
-    ,AGC_ATTACK_Fs176400
-    ,AGC_ATTACK_Fs192000
-#endif
-
-};
-
-/* Decay time (signal too small) */
-#ifndef BUILD_FLOAT
-const LVM_INT16 LVDBE_AGC_DECAY_Table[] = {
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_AGC_DECAY_Table[] = {
-#endif /*BUILD_FLOAT*/
-    AGC_DECAY_Fs8000,
-    AGC_DECAY_Fs11025,
-    AGC_DECAY_Fs12000,
-    AGC_DECAY_Fs16000,
-    AGC_DECAY_Fs22050,
-    AGC_DECAY_Fs24000,
-    AGC_DECAY_Fs32000,
-    AGC_DECAY_Fs44100,
-    AGC_DECAY_Fs48000
-#ifdef HIGHER_FS
-    ,AGC_DECAY_Fs88200
-    ,AGC_DECAY_FS96000
-    ,AGC_DECAY_Fs176400
-    ,AGC_DECAY_FS192000
-#endif
-
-};
-
-/* Gain for use without the high pass filter */
-#ifndef BUILD_FLOAT
-const LVM_INT32 LVDBE_AGC_GAIN_Table[] = {
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_AGC_GAIN_Table[] = {
-#endif /*BUILD_FLOAT*/
-    AGC_GAIN_0dB,
-    AGC_GAIN_1dB,
-    AGC_GAIN_2dB,
-    AGC_GAIN_3dB,
-    AGC_GAIN_4dB,
-    AGC_GAIN_5dB,
-    AGC_GAIN_6dB,
-    AGC_GAIN_7dB,
-    AGC_GAIN_8dB,
-    AGC_GAIN_9dB,
-    AGC_GAIN_10dB,
-    AGC_GAIN_11dB,
-    AGC_GAIN_12dB,
-    AGC_GAIN_13dB,
-    AGC_GAIN_14dB,
-    AGC_GAIN_15dB};
-
-/* Gain for use with the high pass filter */
-#ifndef BUILD_FLOAT
-const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[] = {
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_AGC_HPFGAIN_Table[] = {
-#endif /*BUILD_FLOAT*/
-    AGC_HPFGAIN_0dB,
-    AGC_HPFGAIN_1dB,
-    AGC_HPFGAIN_2dB,
-    AGC_HPFGAIN_3dB,
-    AGC_HPFGAIN_4dB,
-    AGC_HPFGAIN_5dB,
-    AGC_HPFGAIN_6dB,
-    AGC_HPFGAIN_7dB,
-    AGC_HPFGAIN_8dB,
-    AGC_HPFGAIN_9dB,
-    AGC_HPFGAIN_10dB,
-    AGC_HPFGAIN_11dB,
-    AGC_HPFGAIN_12dB,
-    AGC_HPFGAIN_13dB,
-    AGC_HPFGAIN_14dB,
-    AGC_HPFGAIN_15dB};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Volume control gain and time constant tables                                  */
-/*                                                                                  */
-/************************************************************************************/
-
-/* dB to linear conversion table */
-#ifndef BUILD_FLOAT
-const LVM_INT16 LVDBE_VolumeTable[] = {
-    0x4000,             /* -6dB */
-    0x47FB,             /* -5dB */
-    0x50C3,             /* -4dB */
-    0x5A9E,             /* -3dB */
-    0x65AD,             /* -2dB */
-    0x7215,             /* -1dB */
-    0x7FFF};            /*  0dB */
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_VolumeTable[] = {
-    0.500000f,         /* -6dB */
-    0.562341f,         /* -5dB */
-    0.630957f,         /* -4dB */
-    0.707946f,         /* -3dB */
-    0.794328f,         /* -2dB */
-    0.891251f,         /* -1dB */
-    1.000000f};        /*  0dB */
-#endif /*BUILD_FLOAT*/
-
-#ifndef BUILD_FLOAT
-const LVM_INT16 LVDBE_VolumeTCTable[] = {
-#else /*BUILD_FLOAT*/
-const LVM_FLOAT LVDBE_VolumeTCTable[] = {
-#endif /*BUILD_FLOAT*/
-    VOL_TC_Fs8000,
-    VOL_TC_Fs11025,
-    VOL_TC_Fs12000,
-    VOL_TC_Fs16000,
-    VOL_TC_Fs22050,
-    VOL_TC_Fs24000,
-    VOL_TC_Fs32000,
-    VOL_TC_Fs44100,
-    VOL_TC_Fs48000
-#ifdef HIGHER_FS
-    ,VOL_TC_Fs88200
-    ,VOL_TC_Fs96000
-    ,VOL_TC_Fs176400
-    ,VOL_TC_Fs192000
-#endif
-};
-
-
-
-const LVM_INT16 LVDBE_MixerTCTable[] = {
-
-    MIX_TC_Fs8000,
-    MIX_TC_Fs11025,
-    MIX_TC_Fs12000,
-    MIX_TC_Fs16000,
-    MIX_TC_Fs22050,
-    MIX_TC_Fs24000,
-    MIX_TC_Fs32000,
-    MIX_TC_Fs44100,
-    MIX_TC_Fs48000
-#ifdef HIGHER_FS
-    ,MIX_TC_Fs88200
-    ,MIX_TC_Fs96000
-    ,MIX_TC_Fs176400
-    ,MIX_TC_Fs192000
-#endif
-
-};
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.cpp
new file mode 100644
index 0000000..728575c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.cpp
@@ -0,0 +1,610 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Coeffs.h"               /* Filter coefficients */
+#include "LVDBE_Tables.h"
+#include "BIQUAD.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficients constant table                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+const BQ_FLOAT_Coefs_t LVDBE_HPF_Table[] = {
+    /* Coefficients for 55Hz centre frequency */
+    {HPF_Fs8000_Fc55_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc55_A1,
+     HPF_Fs8000_Fc55_A0,
+     -HPF_Fs8000_Fc55_B2,
+     -HPF_Fs8000_Fc55_B1},
+    {HPF_Fs11025_Fc55_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc55_A1,
+     HPF_Fs11025_Fc55_A0,
+     -HPF_Fs11025_Fc55_B2,
+     -HPF_Fs11025_Fc55_B1},
+    {HPF_Fs12000_Fc55_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc55_A1,
+     HPF_Fs12000_Fc55_A0,
+     -HPF_Fs12000_Fc55_B2,
+     -HPF_Fs12000_Fc55_B1},
+    {HPF_Fs16000_Fc55_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc55_A1,
+     HPF_Fs16000_Fc55_A0,
+     -HPF_Fs16000_Fc55_B2,
+     -HPF_Fs16000_Fc55_B1},
+    {HPF_Fs22050_Fc55_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc55_A1,
+     HPF_Fs22050_Fc55_A0,
+     -HPF_Fs22050_Fc55_B2,
+     -HPF_Fs22050_Fc55_B1},
+    {HPF_Fs24000_Fc55_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc55_A1,
+     HPF_Fs24000_Fc55_A0,
+     -HPF_Fs24000_Fc55_B2,
+     -HPF_Fs24000_Fc55_B1},
+    {HPF_Fs32000_Fc55_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc55_A1,
+     HPF_Fs32000_Fc55_A0,
+     -HPF_Fs32000_Fc55_B2,
+     -HPF_Fs32000_Fc55_B1},
+    {HPF_Fs44100_Fc55_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc55_A1,
+     HPF_Fs44100_Fc55_A0,
+     -HPF_Fs44100_Fc55_B2,
+     -HPF_Fs44100_Fc55_B1},
+    {HPF_Fs48000_Fc55_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc55_A1,
+     HPF_Fs48000_Fc55_A0,
+     -HPF_Fs48000_Fc55_B2,
+     -HPF_Fs48000_Fc55_B1},
+    {HPF_Fs88200_Fc55_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc55_A1,
+     HPF_Fs88200_Fc55_A0,
+     -HPF_Fs88200_Fc55_B2,
+     -HPF_Fs88200_Fc55_B1},
+    {HPF_Fs96000_Fc55_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc55_A1,
+     HPF_Fs96000_Fc55_A0,
+     -HPF_Fs96000_Fc55_B2,
+     -HPF_Fs96000_Fc55_B1},
+    {HPF_Fs176400_Fc55_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc55_A1,
+     HPF_Fs176400_Fc55_A0,
+     -HPF_Fs176400_Fc55_B2,
+     -HPF_Fs176400_Fc55_B1},
+    {HPF_Fs192000_Fc55_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc55_A1,
+     HPF_Fs192000_Fc55_A0,
+     -HPF_Fs192000_Fc55_B2,
+     -HPF_Fs192000_Fc55_B1},
+
+    /* Coefficients for 66Hz centre frequency */
+    {HPF_Fs8000_Fc66_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc66_A1,
+     HPF_Fs8000_Fc66_A0,
+     -HPF_Fs8000_Fc66_B2,
+     -HPF_Fs8000_Fc66_B1},
+    {HPF_Fs11025_Fc66_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc66_A1,
+     HPF_Fs11025_Fc66_A0,
+     -HPF_Fs11025_Fc66_B2,
+     -HPF_Fs11025_Fc66_B1},
+    {HPF_Fs12000_Fc66_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc66_A1,
+     HPF_Fs12000_Fc66_A0,
+     -HPF_Fs12000_Fc66_B2,
+     -HPF_Fs12000_Fc66_B1},
+    {HPF_Fs16000_Fc66_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc66_A1,
+     HPF_Fs16000_Fc66_A0,
+     -HPF_Fs16000_Fc66_B2,
+     -HPF_Fs16000_Fc66_B1},
+    {HPF_Fs22050_Fc66_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc66_A1,
+     HPF_Fs22050_Fc66_A0,
+     -HPF_Fs22050_Fc66_B2,
+     -HPF_Fs22050_Fc66_B1},
+    {HPF_Fs24000_Fc66_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc66_A1,
+     HPF_Fs24000_Fc66_A0,
+     -HPF_Fs24000_Fc66_B2,
+     -HPF_Fs24000_Fc66_B1},
+    {HPF_Fs32000_Fc66_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc66_A1,
+     HPF_Fs32000_Fc66_A0,
+     -HPF_Fs32000_Fc66_B2,
+     -HPF_Fs32000_Fc66_B1},
+    {HPF_Fs44100_Fc66_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc66_A1,
+     HPF_Fs44100_Fc66_A0,
+     -HPF_Fs44100_Fc66_B2,
+     -HPF_Fs44100_Fc66_B1},
+    {HPF_Fs48000_Fc66_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc66_A1,
+     HPF_Fs48000_Fc66_A0,
+     -HPF_Fs48000_Fc66_B2,
+     -HPF_Fs48000_Fc66_B1},
+    {HPF_Fs88200_Fc66_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc66_A1,
+     HPF_Fs88200_Fc66_A0,
+     -HPF_Fs88200_Fc66_B2,
+     -HPF_Fs88200_Fc66_B1},
+    {HPF_Fs96000_Fc66_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc66_A1,
+     HPF_Fs96000_Fc66_A0,
+     -HPF_Fs96000_Fc66_B2,
+     -HPF_Fs96000_Fc66_B1},
+    {HPF_Fs176400_Fc66_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc66_A1,
+     HPF_Fs176400_Fc66_A0,
+     -HPF_Fs176400_Fc66_B2,
+     -HPF_Fs176400_Fc66_B1},
+    {HPF_Fs192000_Fc66_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc66_A1,
+     HPF_Fs192000_Fc66_A0,
+     -HPF_Fs192000_Fc66_B2,
+     -HPF_Fs192000_Fc66_B1},
+
+    /* Coefficients for 78Hz centre frequency */
+    {HPF_Fs8000_Fc78_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc78_A1,
+     HPF_Fs8000_Fc78_A0,
+     -HPF_Fs8000_Fc78_B2,
+     -HPF_Fs8000_Fc78_B1},
+    {HPF_Fs11025_Fc78_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc78_A1,
+     HPF_Fs11025_Fc78_A0,
+     -HPF_Fs11025_Fc78_B2,
+     -HPF_Fs11025_Fc78_B1},
+    {HPF_Fs12000_Fc78_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc78_A1,
+     HPF_Fs12000_Fc78_A0,
+     -HPF_Fs12000_Fc78_B2,
+     -HPF_Fs12000_Fc78_B1},
+    {HPF_Fs16000_Fc78_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc78_A1,
+     HPF_Fs16000_Fc78_A0,
+     -HPF_Fs16000_Fc78_B2,
+     -HPF_Fs16000_Fc78_B1},
+    {HPF_Fs22050_Fc78_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc78_A1,
+     HPF_Fs22050_Fc78_A0,
+     -HPF_Fs22050_Fc78_B2,
+     -HPF_Fs22050_Fc78_B1},
+    {HPF_Fs24000_Fc78_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc78_A1,
+     HPF_Fs24000_Fc78_A0,
+     -HPF_Fs24000_Fc78_B2,
+     -HPF_Fs24000_Fc78_B1},
+    {HPF_Fs32000_Fc78_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc78_A1,
+     HPF_Fs32000_Fc78_A0,
+     -HPF_Fs32000_Fc78_B2,
+     -HPF_Fs32000_Fc78_B1},
+    {HPF_Fs44100_Fc78_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc78_A1,
+     HPF_Fs44100_Fc78_A0,
+     -HPF_Fs44100_Fc78_B2,
+     -HPF_Fs44100_Fc78_B1},
+    {HPF_Fs48000_Fc78_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc78_A1,
+     HPF_Fs48000_Fc78_A0,
+     -HPF_Fs48000_Fc78_B2,
+     -HPF_Fs48000_Fc78_B1},
+    {HPF_Fs88200_Fc78_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc78_A1,
+     HPF_Fs88200_Fc78_A0,
+     -HPF_Fs88200_Fc78_B2,
+     -HPF_Fs88200_Fc78_B1},
+    {HPF_Fs96000_Fc78_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc78_A1,
+     HPF_Fs96000_Fc78_A0,
+     -HPF_Fs96000_Fc78_B2,
+     -HPF_Fs96000_Fc78_B1},
+    {HPF_Fs176400_Fc78_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc78_A1,
+     HPF_Fs176400_Fc78_A0,
+     -HPF_Fs176400_Fc78_B2,
+     -HPF_Fs176400_Fc78_B1},
+    {HPF_Fs192000_Fc78_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc78_A1,
+     HPF_Fs192000_Fc78_A0,
+     -HPF_Fs192000_Fc78_B2,
+     -HPF_Fs192000_Fc78_B1},
+
+    /* Coefficients for 90Hz centre frequency */
+    {HPF_Fs8000_Fc90_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc90_A1,
+     HPF_Fs8000_Fc90_A0,
+     -HPF_Fs8000_Fc90_B2,
+     -HPF_Fs8000_Fc90_B1},
+    {HPF_Fs11025_Fc90_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc90_A1,
+     HPF_Fs11025_Fc90_A0,
+     -HPF_Fs11025_Fc90_B2,
+     -HPF_Fs11025_Fc90_B1},
+    {HPF_Fs12000_Fc90_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc90_A1,
+     HPF_Fs12000_Fc90_A0,
+     -HPF_Fs12000_Fc90_B2,
+     -HPF_Fs12000_Fc90_B1},
+    {HPF_Fs16000_Fc90_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc90_A1,
+     HPF_Fs16000_Fc90_A0,
+     -HPF_Fs16000_Fc90_B2,
+     -HPF_Fs16000_Fc90_B1},
+    {HPF_Fs22050_Fc90_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc90_A1,
+     HPF_Fs22050_Fc90_A0,
+     -HPF_Fs22050_Fc90_B2,
+     -HPF_Fs22050_Fc90_B1},
+    {HPF_Fs24000_Fc90_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc90_A1,
+     HPF_Fs24000_Fc90_A0,
+     -HPF_Fs24000_Fc90_B2,
+     -HPF_Fs24000_Fc90_B1},
+    {HPF_Fs32000_Fc90_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc90_A1,
+     HPF_Fs32000_Fc90_A0,
+     -HPF_Fs32000_Fc90_B2,
+     -HPF_Fs32000_Fc90_B1},
+    {HPF_Fs44100_Fc90_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc90_A1,
+     HPF_Fs44100_Fc90_A0,
+     -HPF_Fs44100_Fc90_B2,
+     -HPF_Fs44100_Fc90_B1},
+    {HPF_Fs48000_Fc90_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc90_A1,
+     HPF_Fs48000_Fc90_A0,
+     -HPF_Fs48000_Fc90_B2,
+     -HPF_Fs48000_Fc90_B1}
+
+    ,
+    {HPF_Fs88200_Fc90_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc90_A1,
+     HPF_Fs88200_Fc90_A0,
+     -HPF_Fs88200_Fc90_B2,
+     -HPF_Fs88200_Fc90_B1},
+    {HPF_Fs96000_Fc90_A2,                /* 96kS/s coefficients */
+     HPF_Fs96000_Fc90_A1,
+     HPF_Fs96000_Fc90_A0,
+     -HPF_Fs96000_Fc90_B2,
+     -HPF_Fs96000_Fc90_B1},
+    {HPF_Fs176400_Fc90_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc90_A1,
+     HPF_Fs176400_Fc90_A0,
+     -HPF_Fs176400_Fc90_B2,
+     -HPF_Fs176400_Fc90_B1},
+    {HPF_Fs192000_Fc90_A2,                /* 192kS/s coefficients */
+     HPF_Fs192000_Fc90_A1,
+     HPF_Fs192000_Fc90_A0,
+     -HPF_Fs192000_Fc90_B2,
+     -HPF_Fs192000_Fc90_B1}
+
+};
+
+/*
+ * Band Pass Filter coefficient table
+ */
+const BP_FLOAT_Coefs_t LVDBE_BPF_Table[] = {
+    /* Coefficients for 55Hz centre frequency */
+    {BPF_Fs8000_Fc55_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc55_B2,
+     -BPF_Fs8000_Fc55_B1},
+    {BPF_Fs11025_Fc55_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc55_B2,
+     -BPF_Fs11025_Fc55_B1},
+    {BPF_Fs12000_Fc55_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc55_B2,
+     -BPF_Fs12000_Fc55_B1},
+    {BPF_Fs16000_Fc55_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc55_B2,
+     -BPF_Fs16000_Fc55_B1},
+    {BPF_Fs22050_Fc55_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc55_B2,
+     -BPF_Fs22050_Fc55_B1},
+    {BPF_Fs24000_Fc55_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc55_B2,
+     -BPF_Fs24000_Fc55_B1},
+    {BPF_Fs32000_Fc55_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc55_B2,
+     -BPF_Fs32000_Fc55_B1},
+    {BPF_Fs44100_Fc55_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc55_B2,
+     -BPF_Fs44100_Fc55_B1},
+    {BPF_Fs48000_Fc55_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc55_B2,
+     -BPF_Fs48000_Fc55_B1},
+     {BPF_Fs88200_Fc55_A0,                /* 88kS/s coefficients */
+      -BPF_Fs88200_Fc55_B2,
+      -BPF_Fs88200_Fc55_B1},
+     {BPF_Fs96000_Fc55_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc55_B2,
+     -BPF_Fs96000_Fc55_B1},
+     {BPF_Fs176400_Fc55_A0,                /* 176kS/s coefficients */
+      -BPF_Fs176400_Fc55_B2,
+      -BPF_Fs176400_Fc55_B1},
+     {BPF_Fs192000_Fc55_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc55_B2,
+     -BPF_Fs192000_Fc55_B1},
+
+    /* Coefficients for 66Hz centre frequency */
+    {BPF_Fs8000_Fc66_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc66_B2,
+     -BPF_Fs8000_Fc66_B1},
+    {BPF_Fs11025_Fc66_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc66_B2,
+     -BPF_Fs11025_Fc66_B1},
+    {BPF_Fs12000_Fc66_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc66_B2,
+     -BPF_Fs12000_Fc66_B1},
+    {BPF_Fs16000_Fc66_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc66_B2,
+     -BPF_Fs16000_Fc66_B1},
+    {BPF_Fs22050_Fc66_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc66_B2,
+     -BPF_Fs22050_Fc66_B1},
+    {BPF_Fs24000_Fc66_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc66_B2,
+     -BPF_Fs24000_Fc66_B1},
+    {BPF_Fs32000_Fc66_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc66_B2,
+     -BPF_Fs32000_Fc66_B1},
+    {BPF_Fs44100_Fc66_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc66_B2,
+     -BPF_Fs44100_Fc66_B1},
+    {BPF_Fs48000_Fc66_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc66_B2,
+     -BPF_Fs48000_Fc66_B1},
+    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc66_B2,
+     -BPF_Fs88200_Fc66_B1},
+    {BPF_Fs96000_Fc66_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc66_B2,
+     -BPF_Fs96000_Fc66_B1},
+    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc66_B2,
+     -BPF_Fs176400_Fc66_B1},
+    {BPF_Fs192000_Fc66_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc66_B2,
+     -BPF_Fs192000_Fc66_B1},
+
+    /* Coefficients for 78Hz centre frequency */
+    {BPF_Fs8000_Fc78_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc78_B2,
+     -BPF_Fs8000_Fc78_B1},
+    {BPF_Fs11025_Fc78_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc78_B2,
+     -BPF_Fs11025_Fc78_B1},
+    {BPF_Fs12000_Fc78_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc78_B2,
+     -BPF_Fs12000_Fc78_B1},
+    {BPF_Fs16000_Fc78_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc78_B2,
+     -BPF_Fs16000_Fc78_B1},
+    {BPF_Fs22050_Fc78_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc78_B2,
+     -BPF_Fs22050_Fc78_B1},
+    {BPF_Fs24000_Fc78_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc78_B2,
+     -BPF_Fs24000_Fc78_B1},
+    {BPF_Fs32000_Fc78_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc78_B2,
+     -BPF_Fs32000_Fc78_B1},
+    {BPF_Fs44100_Fc78_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc78_B2,
+     -BPF_Fs44100_Fc78_B1},
+    {BPF_Fs48000_Fc78_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc78_B2,
+     -BPF_Fs48000_Fc78_B1},
+    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc66_B2,
+     -BPF_Fs88200_Fc66_B1},
+    {BPF_Fs96000_Fc78_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc78_B2,
+     -BPF_Fs96000_Fc78_B1},
+    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc66_B2,
+     -BPF_Fs176400_Fc66_B1},
+    {BPF_Fs192000_Fc78_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc78_B2,
+     -BPF_Fs192000_Fc78_B1},
+
+    /* Coefficients for 90Hz centre frequency */
+    {BPF_Fs8000_Fc90_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc90_B2,
+     -BPF_Fs8000_Fc90_B1},
+    {BPF_Fs11025_Fc90_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc90_B2,
+     -BPF_Fs11025_Fc90_B1},
+    {BPF_Fs12000_Fc90_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc90_B2,
+     -BPF_Fs12000_Fc90_B1},
+    {BPF_Fs16000_Fc90_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc90_B2,
+     -BPF_Fs16000_Fc90_B1},
+    {BPF_Fs22050_Fc90_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc90_B2,
+     -BPF_Fs22050_Fc90_B1},
+    {BPF_Fs24000_Fc90_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc90_B2,
+     -BPF_Fs24000_Fc90_B1},
+    {BPF_Fs32000_Fc90_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc90_B2,
+     -BPF_Fs32000_Fc90_B1},
+    {BPF_Fs44100_Fc90_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc90_B2,
+     -BPF_Fs44100_Fc90_B1},
+    {BPF_Fs48000_Fc90_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc90_B2,
+     -BPF_Fs48000_Fc90_B1}
+    ,
+    {BPF_Fs88200_Fc90_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc90_B2,
+     -BPF_Fs88200_Fc90_B1},
+    {BPF_Fs96000_Fc90_A0,                /* 96kS/s coefficients */
+     -BPF_Fs96000_Fc90_B2,
+     -BPF_Fs96000_Fc90_B1},
+    {BPF_Fs176400_Fc90_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc90_B2,
+     -BPF_Fs176400_Fc90_B1},
+    {BPF_Fs192000_Fc90_A0,                /* 192kS/s coefficients */
+     -BPF_Fs192000_Fc90_B2,
+     -BPF_Fs192000_Fc90_B1}
+
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*    AGC constant tables                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+const LVM_FLOAT LVDBE_AGC_ATTACK_Table[] = {
+    AGC_ATTACK_Fs8000,
+    AGC_ATTACK_Fs11025,
+    AGC_ATTACK_Fs12000,
+    AGC_ATTACK_Fs16000,
+    AGC_ATTACK_Fs22050,
+    AGC_ATTACK_Fs24000,
+    AGC_ATTACK_Fs32000,
+    AGC_ATTACK_Fs44100,
+    AGC_ATTACK_Fs48000
+    ,AGC_ATTACK_Fs88200
+    ,AGC_ATTACK_Fs96000
+    ,AGC_ATTACK_Fs176400
+    ,AGC_ATTACK_Fs192000
+
+};
+
+/* Decay time (signal too small) */
+const LVM_FLOAT LVDBE_AGC_DECAY_Table[] = {
+    AGC_DECAY_Fs8000,
+    AGC_DECAY_Fs11025,
+    AGC_DECAY_Fs12000,
+    AGC_DECAY_Fs16000,
+    AGC_DECAY_Fs22050,
+    AGC_DECAY_Fs24000,
+    AGC_DECAY_Fs32000,
+    AGC_DECAY_Fs44100,
+    AGC_DECAY_Fs48000
+    ,AGC_DECAY_Fs88200
+    ,AGC_DECAY_FS96000
+    ,AGC_DECAY_Fs176400
+    ,AGC_DECAY_FS192000
+
+};
+
+/* Gain for use without the high pass filter */
+const LVM_FLOAT LVDBE_AGC_GAIN_Table[] = {
+    AGC_GAIN_0dB,
+    AGC_GAIN_1dB,
+    AGC_GAIN_2dB,
+    AGC_GAIN_3dB,
+    AGC_GAIN_4dB,
+    AGC_GAIN_5dB,
+    AGC_GAIN_6dB,
+    AGC_GAIN_7dB,
+    AGC_GAIN_8dB,
+    AGC_GAIN_9dB,
+    AGC_GAIN_10dB,
+    AGC_GAIN_11dB,
+    AGC_GAIN_12dB,
+    AGC_GAIN_13dB,
+    AGC_GAIN_14dB,
+    AGC_GAIN_15dB};
+
+/* Gain for use with the high pass filter */
+const LVM_FLOAT LVDBE_AGC_HPFGAIN_Table[] = {
+    AGC_HPFGAIN_0dB,
+    AGC_HPFGAIN_1dB,
+    AGC_HPFGAIN_2dB,
+    AGC_HPFGAIN_3dB,
+    AGC_HPFGAIN_4dB,
+    AGC_HPFGAIN_5dB,
+    AGC_HPFGAIN_6dB,
+    AGC_HPFGAIN_7dB,
+    AGC_HPFGAIN_8dB,
+    AGC_HPFGAIN_9dB,
+    AGC_HPFGAIN_10dB,
+    AGC_HPFGAIN_11dB,
+    AGC_HPFGAIN_12dB,
+    AGC_HPFGAIN_13dB,
+    AGC_HPFGAIN_14dB,
+    AGC_HPFGAIN_15dB};
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Volume control gain and time constant tables                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_FLOAT LVDBE_VolumeTable[] = {
+    0.500000f,         /* -6dB */
+    0.562341f,         /* -5dB */
+    0.630957f,         /* -4dB */
+    0.707946f,         /* -3dB */
+    0.794328f,         /* -2dB */
+    0.891251f,         /* -1dB */
+    1.000000f};        /*  0dB */
+
+const LVM_FLOAT LVDBE_VolumeTCTable[] = {
+    VOL_TC_Fs8000,
+    VOL_TC_Fs11025,
+    VOL_TC_Fs12000,
+    VOL_TC_Fs16000,
+    VOL_TC_Fs22050,
+    VOL_TC_Fs24000,
+    VOL_TC_Fs32000,
+    VOL_TC_Fs44100,
+    VOL_TC_Fs48000
+    ,VOL_TC_Fs88200
+    ,VOL_TC_Fs96000
+    ,VOL_TC_Fs176400
+    ,VOL_TC_Fs192000
+};
+
+const LVM_INT16 LVDBE_MixerTCTable[] = {
+
+    MIX_TC_Fs8000,
+    MIX_TC_Fs11025,
+    MIX_TC_Fs12000,
+    MIX_TC_Fs16000,
+    MIX_TC_Fs22050,
+    MIX_TC_Fs24000,
+    MIX_TC_Fs32000,
+    MIX_TC_Fs44100,
+    MIX_TC_Fs48000
+    ,MIX_TC_Fs88200
+    ,MIX_TC_Fs96000
+    ,MIX_TC_Fs176400
+    ,MIX_TC_Fs192000
+
+};
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
index ca46e37..6eabdd2 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Includes                                                                      */
@@ -24,61 +23,9 @@
 #ifndef __LVBDE_TABLES_H__
 #define __LVBDE_TABLES_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include "BIQUAD.h"
 #include "LVM_Types.h"
 
-#ifndef BUILD_FLOAT
-/************************************************************************************/
-/*                                                                                  */
-/*    Coefficients constant table                                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * High Pass Filter Coefficient table
- */
-extern const BQ_C32_Coefs_t LVDBE_HPF_Table[];
-
-/*
- * Band Pass Filter coefficient table
- */
-extern const BP_C32_Coefs_t LVDBE_BPF_Table[];
-
-/************************************************************************************/
-/*                                                                                  */
-/*    AGC constant tables                                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Attack time (signal too large) */
-extern const LVM_INT16 LVDBE_AGC_ATTACK_Table[];
-
-/* Decay time (signal too small) */
-extern const LVM_INT16 LVDBE_AGC_DECAY_Table[];
-
-/* Gain for use without the high pass filter */
-extern const LVM_INT32 LVDBE_AGC_GAIN_Table[];
-
-/* Gain for use with the high pass filter */
-extern const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[];
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Volume control gain and time constant tables                                  */
-/*                                                                                  */
-/************************************************************************************/
-
-/* dB to linear conversion table */
-extern const LVM_INT16 LVDBE_VolumeTable[];
-
-extern const LVM_INT16 LVDBE_VolumeTCTable[];
-
-#else /*BUILD_FLOAT*/
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Coefficients constant table                                                   */
@@ -123,13 +70,6 @@
 extern const LVM_FLOAT LVDBE_VolumeTable[];
 extern const LVM_FLOAT LVDBE_VolumeTCTable[];
 
-#endif /*BUILD_FLOAT*/
-
 extern const LVM_INT16 LVDBE_MixerTCTable[];
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* __LVBDE_TABLES_H__ */
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
index 5082a53..e4e8450 100644
--- a/media/libeffects/lvm/lib/Bundle/lib/LVM.h
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -53,11 +53,6 @@
 #ifndef __LVM_H__
 #define __LVM_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -66,7 +61,6 @@
 
 #include "LVM_Types.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Definitions                                                                         */
@@ -108,7 +102,6 @@
 /* Instance handle */
 typedef void *LVM_Handle_t;
 
-
 /* Status return values */
 typedef enum
 {
@@ -123,7 +116,6 @@
     LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM
 } LVM_ReturnStatus_en;
 
-
 /* Buffer Management mode */
 typedef enum
 {
@@ -227,7 +219,6 @@
     LVM_CHAR                    *pPlatform;             /* Pointer to the library platform type */
 } LVM_VersionInfo_st;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
@@ -248,7 +239,6 @@
     LVM_UINT16                  QFactor;                /* Band quality factor (x100) */
 } LVM_EQNB_BandDef_t;
 
-
 /* Headroom band definition */
 typedef struct
 {
@@ -257,7 +247,6 @@
     LVM_INT16                   Headroom_Offset;        /* Headroom = biggest band gain - Headroom_Offset */
 } LVM_HeadroomBandDef_t;
 
-
 /* Control Parameter structure */
 typedef struct
 {
@@ -303,7 +292,6 @@
 
 } LVM_ControlParams_t;
 
-
 /* Instance Parameter structure */
 typedef struct
 {
@@ -333,7 +321,6 @@
 /*                                                                                      */
 /****************************************************************************************/
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_GetVersionInfo                                          */
@@ -354,7 +341,6 @@
 /****************************************************************************************/
 LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st  *pVersion);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_GetMemoryTable                                          */
@@ -391,7 +377,6 @@
                                        LVM_MemTab_t         *pMemoryTable,
                                        LVM_InstParams_t     *pInstParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_GetInstanceHandle                                       */
@@ -418,7 +403,6 @@
                                           LVM_MemTab_t        *pMemoryTable,
                                           LVM_InstParams_t    *pInstParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_ClearAudioBuffers                                       */
@@ -439,7 +423,6 @@
 /****************************************************************************************/
 LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t  hInstance);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVM_GetControlParameters                                   */
@@ -463,7 +446,6 @@
 LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t           hInstance,
                                              LVM_ControlParams_t    *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_SetControlParameters                                    */
@@ -487,7 +469,6 @@
 LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t           hInstance,
                                              LVM_ControlParams_t    *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_Process                                                 */
@@ -518,20 +499,11 @@
 /*      STEREO              the number of sample pairs in the block                     */
 /*                                                                                      */
 /****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
                                 const LVM_FLOAT             *pInData,
                                 LVM_FLOAT                      *pOutData,
                                 LVM_UINT16                  NumSamples,
                                 LVM_UINT32                  AudioTime);
-#else
-LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
-                                const LVM_INT16             *pInData,
-                                LVM_INT16                   *pOutData,
-                                LVM_UINT16                  NumSamples,
-                                LVM_UINT32                  AudioTime);
-#endif
-
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -555,7 +527,6 @@
 LVM_ReturnStatus_en LVM_SetHeadroomParams(  LVM_Handle_t            hInstance,
                                             LVM_HeadroomParams_t    *pHeadroomParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_GetHeadroomParams                                       */
@@ -578,7 +549,6 @@
 LVM_ReturnStatus_en LVM_GetHeadroomParams(  LVM_Handle_t            hInstance,
                                             LVM_HeadroomParams_t    *pHeadroomParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVM_GetSpectrum                                             */
@@ -632,10 +602,5 @@
 LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t           hInstance,
                                               LVM_ControlParams_t    *pParams);
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif      /* __LVM_H__ */
 
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
deleted file mode 100644
index 07b7f0e..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVM_Private.h"
-#include "LVM_Tables.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_GetSpectrum                                             */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/* This function is used to retrieve Spectral information at a given Audio time         */
-/* for display usage                                                                    */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pCurrentPeaks           Pointer to location where currents peaks are to be saved    */
-/*  pPastPeaks              Pointer to location where past peaks are to be saved        */
-/*  AudioTime               Audio time at which the spectral information is needed      */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Succeeded                                                   */
-/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
-/*  LVM_WRONGAUDIOTIME      Failure due to audio time error                             */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function may be interrupted by the LVM_Process function                     */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_ReturnStatus_en LVM_GetSpectrum(
-                                    LVM_Handle_t            hInstance,
-                                    LVM_UINT8               *pCurrentPeaks,
-                                    LVM_UINT8               *pPastPeaks,
-                                    LVM_INT32               AudioTime
-                                    )
-{
-    LVM_Instance_t           *pInstance   = (LVM_Instance_t  *)hInstance;
-
-    pLVPSA_Handle_t        *hPSAInstance;
-    LVPSA_RETURN           LVPSA_Status;
-
-
-    if(pInstance == LVM_NULL)
-    {
-        return LVM_NULLADDRESS;
-    }
-
-    /*If PSA is not included at the time of instance creation, return without any processing*/
-    if(pInstance->InstParams.PSA_Included!=LVM_PSA_ON)
-    {
-        return LVM_SUCCESS;
-    }
-
-    hPSAInstance = pInstance->hPSAInstance;
-
-    if((pCurrentPeaks == LVM_NULL) ||
-        (pPastPeaks == LVM_NULL))
-    {
-        return LVM_NULLADDRESS;
-    }
-
-
-    /*
-     * Update new parameters if necessary
-     */
-    if (pInstance->ControlPending == LVM_TRUE)
-    {
-        LVM_ApplyNewSettings(hInstance);
-    }
-
-    /* If PSA module is disabled, do nothing */
-    if(pInstance->Params.PSA_Enable==LVM_PSA_OFF)
-    {
-        return LVM_ALGORITHMDISABLED;
-    }
-
-    LVPSA_Status = LVPSA_GetSpectrum(hPSAInstance,
-                            (LVPSA_Time) (AudioTime),
-                            (LVM_UINT8*) pCurrentPeaks,
-                            (LVM_UINT8*) pPastPeaks );
-
-    if(LVPSA_Status != LVPSA_OK)
-    {
-        if(LVPSA_Status == LVPSA_ERROR_WRONGTIME)
-        {
-            return (LVM_ReturnStatus_en) LVM_WRONGAUDIOTIME;
-        }
-        else
-        {
-            return (LVM_ReturnStatus_en) LVM_NULLADDRESS;
-        }
-    }
-
-    return(LVM_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_SetVolumeNoSmoothing                                    */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/* This function is used to set output volume without any smoothing                     */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pParams                 Control Parameters, only volume value is used here          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Succeeded                                                   */
-/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
-/*  LVM_OUTOFRANGE          When any of the control parameters are out of range         */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function may be interrupted by the LVM_Process function                     */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t           hInstance,
-                                              LVM_ControlParams_t    *pParams)
-{
-    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
-    LVM_ReturnStatus_en Error;
-
-    /*Apply new controls*/
-    Error = LVM_SetControlParameters(hInstance,pParams);
-    pInstance->NoSmoothVolume = LVM_TRUE;
-    return Error;
-}
-
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.cpp
new file mode 100644
index 0000000..e241cdd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetSpectrum                                             */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to retrieve Spectral information at a given Audio time         */
+/* for display usage                                                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pCurrentPeaks           Pointer to location where currents peaks are to be saved    */
+/*  pPastPeaks              Pointer to location where past peaks are to be saved        */
+/*  AudioTime               Audio time at which the spectral information is needed      */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_WRONGAUDIOTIME      Failure due to audio time error                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetSpectrum(
+                                    LVM_Handle_t            hInstance,
+                                    LVM_UINT8               *pCurrentPeaks,
+                                    LVM_UINT8               *pPastPeaks,
+                                    LVM_INT32               AudioTime
+                                    )
+{
+    LVM_Instance_t           *pInstance   = (LVM_Instance_t  *)hInstance;
+
+    pLVPSA_Handle_t        *hPSAInstance;
+    LVPSA_RETURN           LVPSA_Status;
+
+    if(pInstance == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*If PSA is not included at the time of instance creation, return without any processing*/
+    if(pInstance->InstParams.PSA_Included!=LVM_PSA_ON)
+    {
+        return LVM_SUCCESS;
+    }
+
+    hPSAInstance = (pLVPSA_Handle_t *)pInstance->hPSAInstance;
+
+    if((pCurrentPeaks == LVM_NULL) ||
+        (pPastPeaks == LVM_NULL))
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*
+     * Update new parameters if necessary
+     */
+    if (pInstance->ControlPending == LVM_TRUE)
+    {
+        LVM_ApplyNewSettings(hInstance);
+    }
+
+    /* If PSA module is disabled, do nothing */
+    if(pInstance->Params.PSA_Enable==LVM_PSA_OFF)
+    {
+        return LVM_ALGORITHMDISABLED;
+    }
+
+    LVPSA_Status = LVPSA_GetSpectrum(hPSAInstance,
+                            (LVPSA_Time) (AudioTime),
+                            (LVM_UINT8*) pCurrentPeaks,
+                            (LVM_UINT8*) pPastPeaks );
+
+    if(LVPSA_Status != LVPSA_OK)
+    {
+        if(LVPSA_Status == LVPSA_ERROR_WRONGTIME)
+        {
+            return (LVM_ReturnStatus_en) LVM_WRONGAUDIOTIME;
+        }
+        else
+        {
+            return (LVM_ReturnStatus_en) LVM_NULLADDRESS;
+        }
+    }
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetVolumeNoSmoothing                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to set output volume without any smoothing                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pParams                 Control Parameters, only volume value is used here          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_OUTOFRANGE          When any of the control parameters are out of range         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t           hInstance,
+                                              LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_ReturnStatus_en Error;
+
+    /*Apply new controls*/
+    Error = LVM_SetControlParameters(hInstance,pParams);
+    pInstance->NoSmoothVolume = LVM_TRUE;
+    return Error;
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
deleted file mode 100644
index bdca5e3..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
+++ /dev/null
@@ -1,1338 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/****************************************************************************************/
-/*                                                                                        */
-/*    Includes                                                                              */
-/*                                                                                        */
-/****************************************************************************************/
-
-#include "LVM_Private.h"
-#include "VectorArithmetic.h"
-
-#include <log/log.h>
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferManagedIn                                        */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Full buffer management allowing the user to provide input and output buffers on   */
-/*  any alignment and with any number of samples. The alignment is corrected within     */
-/*  the buffer management and the samples are grouped in to blocks of the correct size  */
-/*  before processing.                                                                  */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        -    Instance handle                                             */
-/*    pInData            -    Pointer to the input data stream                          */
-/*  *pToProcess        -    Pointer to pointer to the start of data processing          */
-/*  *pProcessed        -    Pointer to pointer to the destination of the processed data */
-/*    pNumSamples        -    Pointer to the number of samples to process               */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
-                         const LVM_FLOAT    *pInData,
-                         LVM_FLOAT          **pToProcess,
-                         LVM_FLOAT          **pProcessed,
-                         LVM_UINT16         *pNumSamples)
-{
-
-    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
-    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
-    LVM_FLOAT        *pStart;
-    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t     *pBuffer;
-    LVM_FLOAT        *pDest;
-#ifdef SUPPORT_MC
-    LVM_INT16        NumChannels = pInstance->NrChannels;
-#else
-    LVM_INT16        NumChannels = 2;
-#endif
-
-    /*
-     * Set the processing address pointers
-     */
-    pBuffer     = pInstance->pBufferManagement;
-    pDest       = pBuffer->pScratch;
-    *pToProcess = pBuffer->pScratch;
-    *pProcessed = pBuffer->pScratch;
-
-    /*
-     * Check if it is the first call of a block
-     */
-    if (pInstance->SamplesToProcess == 0)
-    {
-        /*
-         * First call for a new block of samples
-         */
-        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
-        pInstance->pInputSamples    = (LVM_FLOAT *)pInData;
-        pBuffer->BufferState        = LVM_FIRSTCALL;
-    }
-    pStart = pInstance->pInputSamples;                 /* Pointer to the input samples */
-    pBuffer->SamplesToOutput  = 0;                     /* Samples to output is same as
-                                                          number read for inplace processing */
-
-
-    /*
-     * Calculate the number of samples to process this call and update the buffer state
-     */
-    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
-    {
-        /*
-         * Process the maximum bock size of samples.
-         */
-        SampleCount = pInstance->InternalBlockSize;
-        NumSamples  = pInstance->InternalBlockSize;
-    }
-    else
-    {
-        /*
-         * Last call for the block, so calculate how many frames and samples to process
-          */
-        LVM_INT16   NumFrames;
-
-        NumSamples  = pInstance->SamplesToProcess;
-        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
-        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
-
-        /*
-         * Update the buffer state
-         */
-        if (pBuffer->BufferState == LVM_FIRSTCALL)
-        {
-            pBuffer->BufferState = LVM_FIRSTLASTCALL;
-        }
-        else
-        {
-            pBuffer->BufferState = LVM_LASTCALL;
-        }
-    }
-    *pNumSamples = (LVM_UINT16)SampleCount;  /* Set the number of samples to process this call */
-
-
-    /*
-     * Copy samples from the delay buffer as required
-     */
-    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
-        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
-        (pBuffer->InDelaySamples != 0))
-    {
-        Copy_Float(&pBuffer->InDelayBuffer[0],                             /* Source */
-                   pDest,                                                  /* Destination */
-                   (LVM_INT16)(NumChannels * pBuffer->InDelaySamples));    /* Number of delay \
-                                                                       samples, left and right */
-        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
-        pDest += NumChannels * pBuffer->InDelaySamples;      /* Update the destination pointer */
-    }
-
-
-    /*
-     * Copy the rest of the samples for this call from the input buffer
-     */
-    if (NumSamples > 0)
-    {
-        Copy_Float(pStart,                                      /* Source */
-                   pDest,                                       /* Destination */
-                   (LVM_INT16)(NumChannels * NumSamples));      /* Number of input samples */
-        pStart += NumChannels * NumSamples;                     /* Update the input pointer */
-
-        /*
-         * Update the input data pointer and samples to output
-         */
-        /* Update samples to output */
-        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples);
-    }
-
-
-    /*
-      * Update the sample count and input pointer
-     */
-    /* Update the count of samples */
-    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);
-    pInstance->pInputSamples     = pStart; /* Update input sample pointer */
-
-
-    /*
-     * Save samples to the delay buffer if any left unprocessed
-     */
-    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
-        (pBuffer->BufferState == LVM_LASTCALL))
-    {
-        NumSamples = pInstance->SamplesToProcess;
-        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
-        pStart    += NumChannels * SampleCount; /* Offset by the number of processed samples */
-        if (NumSamples != 0)
-        {
-            Copy_Float(pStart,                                         /* Source */
-                       &pBuffer->InDelayBuffer[0],                     /* Destination */
-                       (LVM_INT16)(NumChannels * NumSamples));   /* Number of input samples */
-        }
-
-
-        /*
-         * Update the delay sample count
-         */
-        pBuffer->InDelaySamples     = NumSamples;       /* Number of delay sample pairs */
-        pInstance->SamplesToProcess = 0;                            /* All Samples used */
-    }
-}
-#else
-void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
-                         const LVM_INT16    *pInData,
-                         LVM_INT16          **pToProcess,
-                         LVM_INT16          **pProcessed,
-                         LVM_UINT16         *pNumSamples)
-{
-
-    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
-    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
-    LVM_INT16        *pStart;
-    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t     *pBuffer;
-    LVM_INT16        *pDest;
-    LVM_INT16        NumChannels = 2;
-
-    /*
-     * Set the processing address pointers
-     */
-    pBuffer     = pInstance->pBufferManagement;
-    pDest       = pBuffer->pScratch;
-    *pToProcess = pBuffer->pScratch;
-    *pProcessed = pBuffer->pScratch;
-
-    /*
-     * Check if it is the first call of a block
-     */
-    if (pInstance->SamplesToProcess == 0)
-    {
-        /*
-         * First call for a new block of samples
-         */
-        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
-        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
-        pBuffer->BufferState        = LVM_FIRSTCALL;
-    }
-    pStart = pInstance->pInputSamples;                       /* Pointer to the input samples */
-    pBuffer->SamplesToOutput  = 0;                           /* Samples to output is same as number read for inplace processing */
-
-
-    /*
-     * Calculate the number of samples to process this call and update the buffer state
-     */
-    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
-    {
-        /*
-         * Process the maximum bock size of samples.
-         */
-        SampleCount = pInstance->InternalBlockSize;
-        NumSamples  = pInstance->InternalBlockSize;
-    }
-    else
-    {
-        /*
-         * Last call for the block, so calculate how many frames and samples to process
-          */
-        LVM_INT16   NumFrames;
-
-        NumSamples  = pInstance->SamplesToProcess;
-        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
-        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
-
-        /*
-         * Update the buffer state
-         */
-        if (pBuffer->BufferState == LVM_FIRSTCALL)
-        {
-            pBuffer->BufferState = LVM_FIRSTLASTCALL;
-        }
-        else
-        {
-            pBuffer->BufferState = LVM_LASTCALL;
-        }
-    }
-    *pNumSamples = (LVM_UINT16)SampleCount;                        /* Set the number of samples to process this call */
-
-
-    /*
-     * Copy samples from the delay buffer as required
-     */
-    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
-        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
-        (pBuffer->InDelaySamples != 0))
-    {
-        Copy_16(&pBuffer->InDelayBuffer[0],                             /* Source */
-                pDest,                                                  /* Destination */
-                (LVM_INT16)(NumChannels*pBuffer->InDelaySamples));      /* Number of delay samples, left and right */
-        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
-        pDest += NumChannels * pBuffer->InDelaySamples;                 /* Update the destination pointer */
-    }
-
-
-    /*
-     * Copy the rest of the samples for this call from the input buffer
-     */
-    if (NumSamples > 0)
-    {
-        Copy_16(pStart,                                             /* Source */
-                pDest,                                              /* Destination */
-                (LVM_INT16)(NumChannels*NumSamples));               /* Number of input samples */
-        pStart += NumChannels * NumSamples;                         /* Update the input pointer */
-
-        /*
-         * Update the input data pointer and samples to output
-         */
-        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
-    }
-
-
-    /*
-      * Update the sample count and input pointer
-     */
-    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);      /* Update the count of samples */
-    pInstance->pInputSamples     = pStart;                                                      /* Update input sample pointer */
-
-
-    /*
-     * Save samples to the delay buffer if any left unprocessed
-     */
-    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
-        (pBuffer->BufferState == LVM_LASTCALL))
-    {
-        NumSamples = pInstance->SamplesToProcess;
-        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
-        pStart    += NumChannels*SampleCount;                       /* Offset by the number of processed samples */
-        if (NumSamples != 0)
-        {
-            Copy_16(pStart,                                         /* Source */
-                    &pBuffer->InDelayBuffer[0],                     /* Destination */
-                    (LVM_INT16)(NumChannels*NumSamples));           /* Number of input samples */
-        }
-
-
-        /*
-         * Update the delay sample count
-         */
-        pBuffer->InDelaySamples     = NumSamples;                   /* Number of delay sample pairs */
-        pInstance->SamplesToProcess = 0;                            /* All Samples used */
-    }
-}
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    This mode is selected by the user code and disables the buffer management with the */
-/*  exception of the maximum block size processing. The user must ensure that the       */
-/*  input and output buffers are 32-bit aligned and also that the number of samples to  */
-/*    process is a correct multiple of samples.                                         */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        -    Instance handle                                             */
-/*  *pToProcess        -    Pointer to the start of data processing                     */
-/*  *pProcessed        -    Pointer to the destination of the processed data            */
-/*    pNumSamples        -    Pointer to the number of samples to process               */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
-                           LVM_FLOAT        **pToProcess,
-                           LVM_FLOAT        **pProcessed,
-                           LVM_UINT16       *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check if this is the first call of a block
-     */
-    if (pInstance->SamplesToProcess == 0)
-    {
-        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;    /* Get the number of samples
-                                                                               on first call */
-        pInstance->pInputSamples    = *pToProcess;                /* Get the I/O pointers */
-        pInstance->pOutputSamples    = *pProcessed;
-
-
-        /*
-         * Set te block size to process
-         */
-        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
-        {
-            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
-        }
-        else
-        {
-            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
-        }
-    }
-
-    /*
-     * Set the process pointers
-     */
-    *pToProcess = pInstance->pInputSamples;
-    *pProcessed = pInstance->pOutputSamples;
-}
-#else
-void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
-                           LVM_INT16        **pToProcess,
-                           LVM_INT16        **pProcessed,
-                           LVM_UINT16       *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check if this is the first call of a block
-     */
-    if (pInstance->SamplesToProcess == 0)
-    {
-        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;       /* Get the number of samples on first call */
-        pInstance->pInputSamples    = *pToProcess;                   /* Get the I/O pointers */
-        pInstance->pOutputSamples    = *pProcessed;
-
-
-        /*
-         * Set te block size to process
-         */
-        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
-        {
-            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
-        }
-        else
-        {
-            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
-        }
-    }
-
-    /*
-     * Set the process pointers
-     */
-    *pToProcess = pInstance->pInputSamples;
-    *pProcessed = pInstance->pOutputSamples;
-}
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferOptimisedIn                                      */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Optimised buffer management for the case where the data is outplace processing,   */
-/*    the output data is 32-bit aligned and there are sufficient samples to allow some  */
-/*    processing directly in the output buffer. This saves one data copy per sample     */
-/*    compared with the unoptimsed version.                                             */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        -    Instance handle                                             */
-/*    pInData            -    Pointer to the input data stream                          */
-/*  *pToProcess        -    Pointer to the start of data processing                     */
-/*  *pProcessed        -    Pointer to the destination of the processed data            */
-/*    pNumSamples        -    Pointer to the number of samples to process               */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-
-#ifndef BUILD_FLOAT
-void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
-                           const LVM_INT16      *pInData,
-                           LVM_INT16            **pToProcess,
-                           LVM_INT16            **pProcessed,
-                           LVM_UINT16           *pNumSamples)
-{
-
-    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t     *pBuffer    = pInstance->pBufferManagement;
-    LVM_INT16        *pDest;
-    LVM_INT16        SampleCount;
-    LVM_INT16        NumSamples;
-    LVM_INT16        NumFrames;
-
-    /*
-     * Check if it is the first call for this block
-     */
-    if (pInstance->SamplesToProcess == 0)
-    {
-        /*
-         * First call for a new block of samples
-         */
-        pBuffer->BufferState = LVM_FIRSTCALL;
-        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
-        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
-        pBuffer->SamplesToOutput    = (LVM_INT16)*pNumSamples;
-        pDest = *pProcessed;                                    /* The start of the output buffer */
-
-
-        /*
-         * Copy the already processed samples to the output buffer
-         */
-        if (pBuffer->OutDelaySamples != 0)
-        {
-            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
-                    pDest,                                          /* Destination */
-                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
-            pDest += 2 * pBuffer->OutDelaySamples;                  /* Update the output pointer */
-            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
-        }
-        *pToProcess = pDest;                                    /* Set the address to start processing */
-        *pProcessed = pDest;                                    /* Process in the output buffer, now inplace */
-
-        /*
-         * Copy the input delay buffer (unprocessed) samples to the output buffer
-         */
-        if (pBuffer->InDelaySamples != 0)
-        {
-            Copy_16(&pBuffer->InDelayBuffer[0],                     /* Source */
-                    pDest,                                          /* Destination */
-                    (LVM_INT16)(2*pBuffer->InDelaySamples));        /* Number of delay samples */
-            pDest += 2 * pBuffer->InDelaySamples;                   /* Update the output pointer */
-        }
-
-
-        /*
-         * Calculate how many input samples to process and copy
-         */
-        NumSamples    = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples);  /* Number that will fit in the output buffer */
-        if (NumSamples >= pInstance->InternalBlockSize)
-        {
-            NumSamples = pInstance->InternalBlockSize;
-        }
-        NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
-        SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
-        *pNumSamples  = (LVM_UINT16)SampleCount;                                        /* The number of samples to process */
-        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
-        SampleCount   = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples);             /* The number of samples to copy from the input */
-
-
-        /*
-         * Copy samples from the input buffer and update counts and pointers
-         */
-        Copy_16(pInstance->pInputSamples,                           /* Source */
-                pDest,                                              /* Destination */
-                (LVM_INT16)(2*SampleCount));                        /* Number of input samples */
-        pInstance->pInputSamples += 2 * SampleCount;                /* Update the input pointer */
-        pInstance->pOutputSamples = pDest + (2 * SampleCount);      /* Update the output pointer */
-        pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
-    }
-    else
-    {
-        /*
-         * Second or subsequent call in optimised mode
-         */
-        if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
-        {
-            /*
-             * More samples can be processed directly in the output buffer
-             */
-            *pToProcess = pInstance->pOutputSamples;                /* Set the address to start processing */
-            *pProcessed = pInstance->pOutputSamples;                /* Process in the output buffer, now inplace */
-            NumSamples  = pBuffer->SamplesToOutput;                 /* Number that will fit in the output buffer */
-            if (NumSamples >= pInstance->InternalBlockSize)
-            {
-                NumSamples = pInstance->InternalBlockSize;
-            }
-            NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
-            SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
-            *pNumSamples  = (LVM_UINT16)SampleCount;            /* The number of samples to process */
-
-
-            /*
-             * Copy samples from the input buffer and update counts and pointers
-             */
-            Copy_16(pInstance->pInputSamples,                       /* Source */
-                    pInstance->pOutputSamples,                      /* Destination */
-                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
-            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
-            pInstance->pOutputSamples += 2 * SampleCount;           /* Update the output pointer */
-            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);   /* Samples left in the input buffer */
-            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount);         /* Number that will fit in the output buffer */
-        }
-        else
-        {
-            /*
-             * The remaining samples can not be processed in the output buffer
-             */
-            pBuffer->BufferState = LVM_LASTCALL;                    /* Indicate this is the last bock to process */
-            *pToProcess  = pBuffer->pScratch;                       /* Set the address to start processing */
-            *pProcessed  = pBuffer->pScratch;                       /* Process in the output buffer, now inplace */
-            NumSamples   = pInstance->SamplesToProcess;             /* Number left to be processed */
-            NumFrames     = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
-            SampleCount  = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
-            *pNumSamples = (LVM_UINT16)SampleCount;                /* The number of samples to process */
-
-
-            /*
-             * Copy samples from the input buffer and update counts and pointers
-             */
-            Copy_16(pInstance->pInputSamples,                       /* Source */
-                    pBuffer->pScratch,                              /* Destination */
-                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
-            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
-            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
-        }
-    }
-}
-#endif
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferIn                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    This function manages the data input, it has the following features:              */
-/*        - Accepts data in 16-bit aligned memory                                       */
-/*        - Copies the data to 32-bit aligned memory                                    */
-/*        - Converts Mono inputs to Mono-in-Stereo                                      */
-/*        - Accepts any number of samples as input, except 0                            */
-/*        - Breaks the input sample stream in to blocks of the configured frame size or */
-/*          multiples of the frame size                                                 */
-/*        - Limits the processing block size to the maximum block size.                 */
-/*        - Works with inplace or outplace processing automatically                     */
-/*                                                                                      */
-/*  To manage the data the function has a number of operating states:                   */
-/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
-/*        LVM_MAXBLOCKCALL    - The current block is the maximum size. Only used for the */
-/*                              second and subsequent blocks.                           */
-/*        LVM_LASTCALL        - The last call for this block of input samples           */
-/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
-/*                              samples, this occurs when the number of samples to      */
-/*                              process is less than the maximum block size.            */
-/*                                                                                      */
-/*    The function uses an internal delay buffer the size of the minimum frame, this is */
-/*  used to temporarily hold samples when the number of samples to process is not a     */
-/*  multiple of the frame size.                                                         */
-/*                                                                                      */
-/*    To ensure correct operation with inplace buffering the number of samples to output*/
-/*  per call is calculated in this function and is set to the number of samples read    */
-/*  from the input buffer.                                                              */
-/*                                                                                      */
-/*    The total number of samples to process is stored when the function is called for  */
-/*  the first time. The value is overwritten by the size of the block to be processed   */
-/*  in each call so the size of the processing blocks can be controlled. The number of  */
-/*    samples actually processed for each block of input samples is always a multiple of*/
-/*  the frame size so for any particular block of input samples the actual number of    */
-/*  processed samples may not match the number of input samples, sometime it will be    */
-/*  sometimes less. The average is the same and the difference is never more than the   */
-/*  frame size.                                                                         */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        -    Instance handle                                             */
-/*    pInData            -    Pointer to the input data stream                          */
-/*  *pToProcess        -    Pointer to the start of data processing                     */
-/*  *pProcessed        -    Pointer to the destination of the processed data            */
-/*    pNumSamples        -    Pointer to the number of samples to process               */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-void LVM_BufferIn(LVM_Handle_t      hInstance,
-                  const LVM_FLOAT   *pInData,
-                  LVM_FLOAT         **pToProcess,
-                  LVM_FLOAT         **pProcessed,
-                  LVM_UINT16        *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check which mode, managed or unmanaged
-     */
-    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        LVM_BufferManagedIn(hInstance,
-                            pInData,
-                            pToProcess,
-                            pProcessed,
-                            pNumSamples);
-    }
-    else
-    {
-        LVM_BufferUnmanagedIn(hInstance,
-                              pToProcess,
-                              pProcessed,
-                              pNumSamples);
-    }
-}
-#else
-void LVM_BufferIn(LVM_Handle_t      hInstance,
-                  const LVM_INT16   *pInData,
-                  LVM_INT16         **pToProcess,
-                  LVM_INT16         **pProcessed,
-                  LVM_UINT16        *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check which mode, managed or unmanaged
-     */
-    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        LVM_BufferManagedIn(hInstance,
-                            pInData,
-                            pToProcess,
-                            pProcessed,
-                            pNumSamples);
-    }
-    else
-    {
-        LVM_BufferUnmanagedIn(hInstance,
-                              pToProcess,
-                              pProcessed,
-                              pNumSamples);
-    }
-}
-#endif
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferManagedOut                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Full buffer management output. This works in conjunction with the managed input     */
-/*  routine and ensures the correct number of samples are always output to the output   */
-/*  buffer.                                                                             */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        - Instance handle                                                */
-/*    pOutData        - Pointer to the output data stream                               */
-/*    pNumSamples        - Pointer to the number of samples to process                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
-                          LVM_FLOAT            *pOutData,
-                          LVM_UINT16        *pNumSamples)
-{
-
-    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
-    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
-    LVM_INT16       NumSamples;
-    LVM_FLOAT       *pStart;
-    LVM_FLOAT       *pDest;
-#ifdef SUPPORT_MC
-    LVM_INT32       NrChannels = pInstance->NrChannels;
-#define NrFrames NumSamples  // alias for clarity
-#define FrameCount SampleCount
-#endif
-
-    /*
-     * Set the pointers
-     */
-    NumSamples = pBuffer->SamplesToOutput;
-    pStart     = pBuffer->pScratch;
-
-    /*
-     * check if it is the first call of a block
-      */
-    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
-        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
-    {
-        /* First call for a new block */
-        pInstance->pOutputSamples = pOutData;                 /* Initialise the destination */
-    }
-    pDest = pInstance->pOutputSamples;                        /* Set the output address */
-
-
-    /*
-     * If the number of samples is non-zero then there are still samples to send to
-     * the output buffer
-     */
-    if ((NumSamples != 0) &&
-        (pBuffer->OutDelaySamples != 0))
-    {
-        /*
-         * Copy the delayed output buffer samples to the output
-         */
-        if (pBuffer->OutDelaySamples <= NumSamples)
-        {
-            /*
-             * Copy all output delay samples to the output
-             */
-#ifdef SUPPORT_MC
-            Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
-                       pDest,                                      /* Destination */
-                       /* Number of delay samples */
-                       (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
-#else
-            Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
-                       pDest,                                      /* Destination */
-                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of delay samples */
-#endif
-
-            /*
-             * Update the pointer and sample counts
-             */
-#ifdef SUPPORT_MC
-            pDest += NrChannels * pBuffer->OutDelaySamples; /* Output sample pointer */
-#else
-            pDest += 2 * pBuffer->OutDelaySamples; /* Output sample pointer */
-#endif
-            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left \
-                                                                                to send */
-            pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
-        }
-        else
-        {
-            /*
-             * Copy only some of the ouput delay samples to the output
-             */
-#ifdef SUPPORT_MC
-            Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
-                       pDest,                                          /* Destination */
-                       (LVM_INT16)(NrChannels * NrFrames));       /* Number of delay samples */
-#else
-            Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
-                       pDest,                                          /* Destination */
-                       (LVM_INT16)(2 * NumSamples));       /* Number of delay samples */
-#endif
-
-            /*
-             * Update the pointer and sample counts
-             */
-#ifdef SUPPORT_MC
-            pDest += NrChannels * NrFrames; /* Output sample pointer */
-#else
-            pDest += 2 * NumSamples; /* Output sample pointer */
-#endif
-            /* No samples left in the buffer */
-            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);
-
-            /*
-             * Realign the delay buffer data to avoid using circular buffer management
-             */
-#ifdef SUPPORT_MC
-            Copy_Float(&pBuffer->OutDelayBuffer[NrChannels * NrFrames],         /* Source */
-                       &pBuffer->OutDelayBuffer[0],                    /* Destination */
-                       /* Number of samples to move */
-                       (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
-#else
-            Copy_Float(&pBuffer->OutDelayBuffer[2 * NumSamples],         /* Source */
-                       &pBuffer->OutDelayBuffer[0],                    /* Destination */
-                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of samples to move */
-#endif
-            NumSamples = 0;                                /* Samples left to send */
-        }
-    }
-
-
-    /*
-     * Copy the processed results to the output
-     */
-    if ((NumSamples != 0) &&
-        (SampleCount != 0))
-    {
-        if (SampleCount <= NumSamples)
-        {
-            /*
-             * Copy all processed samples to the output
-             */
-#ifdef SUPPORT_MC
-            Copy_Float(pStart,                                      /* Source */
-                       pDest,                                       /* Destination */
-                       (LVM_INT16)(NrChannels * FrameCount)); /* Number of processed samples */
-#else
-            Copy_Float(pStart,                                      /* Source */
-                       pDest,                                       /* Destination */
-                       (LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
-#endif
-            /*
-             * Update the pointer and sample counts
-             */
-#ifdef SUPPORT_MC
-            pDest      += NrChannels * FrameCount;                 /* Output sample pointer */
-#else
-            pDest      += 2 * SampleCount;                          /* Output sample pointer */
-#endif
-            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
-            SampleCount = 0; /* No samples left in the buffer */
-        }
-        else
-        {
-            /*
-             * Copy only some processed samples to the output
-             */
-#ifdef SUPPORT_MC
-            Copy_Float(pStart,                                         /* Source */
-                       pDest,                                          /* Destination */
-                       (LVM_INT16)(NrChannels * NrFrames));  /* Number of processed samples */
-#else
-            Copy_Float(pStart,                                         /* Source */
-                       pDest,                                          /* Destination */
-                       (LVM_INT16)(2 * NumSamples));     /* Number of processed samples */
-#endif
-            /*
-             * Update the pointers and sample counts
-               */
-#ifdef SUPPORT_MC
-            pStart      += NrChannels * NrFrames;               /* Processed sample pointer */
-            pDest       += NrChannels * NrFrames;               /* Output sample pointer */
-#else
-            pStart      += 2 * NumSamples;                        /* Processed sample pointer */
-            pDest       += 2 * NumSamples;                        /* Output sample pointer */
-#endif
-            SampleCount  = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
-            NumSamples   = 0;                                     /* Clear the sample count */
-        }
-    }
-
-
-    /*
-     * Copy the remaining processed data to the output delay buffer
-     */
-    if (SampleCount != 0)
-    {
-#ifdef SUPPORT_MC
-        Copy_Float(pStart,                                                 /* Source */
-                   /* Destination */
-                   &pBuffer->OutDelayBuffer[NrChannels * pBuffer->OutDelaySamples],
-                   (LVM_INT16)(NrChannels * FrameCount));      /* Number of processed samples */
-#else
-        Copy_Float(pStart,                                                 /* Source */
-                   &pBuffer->OutDelayBuffer[2 * pBuffer->OutDelaySamples], /* Destination */
-                   (LVM_INT16)(2 * SampleCount));               /* Number of processed samples */
-#endif
-        /* Update the buffer count */
-        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount);
-    }
-
-    /*
-     * pointers, counts and set default buffer processing
-     */
-    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
-    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
-    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call \
-                                                                            block size */
-    /* This will terminate the loop when all samples processed */
-    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
-}
-#else
-void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
-                          LVM_INT16            *pOutData,
-                          LVM_UINT16        *pNumSamples)
-{
-
-    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
-    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
-    LVM_INT16       NumSamples;
-    LVM_INT16       *pStart;
-    LVM_INT16       *pDest;
-
-
-    /*
-     * Set the pointers
-     */
-    NumSamples = pBuffer->SamplesToOutput;
-    pStart     = pBuffer->pScratch;
-
-
-    /*
-     * check if it is the first call of a block
-      */
-    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
-        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
-    {
-        /* First call for a new block */
-        pInstance->pOutputSamples = pOutData;                        /* Initialise the destination */
-    }
-    pDest = pInstance->pOutputSamples;                               /* Set the output address */
-
-
-    /*
-     * If the number of samples is non-zero then there are still samples to send to
-     * the output buffer
-     */
-    if ((NumSamples != 0) &&
-        (pBuffer->OutDelaySamples != 0))
-    {
-        /*
-         * Copy the delayed output buffer samples to the output
-         */
-        if (pBuffer->OutDelaySamples <= NumSamples)
-        {
-            /*
-             * Copy all output delay samples to the output
-             */
-            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
-                    pDest,                                          /* Detsination */
-                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
-
-            /*
-             * Update the pointer and sample counts
-             */
-            pDest += 2*pBuffer->OutDelaySamples;                                /* Output sample pointer */
-            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples);    /* Samples left to send */
-            pBuffer->OutDelaySamples = 0;                                       /* No samples left in the buffer */
-
-        }
-        else
-        {
-            /*
-             * Copy only some of the ouput delay samples to the output
-             */
-            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
-                    pDest,                                          /* Detsination */
-                    (LVM_INT16)(2*NumSamples));                     /* Number of delay samples */
-
-            /*
-             * Update the pointer and sample counts
-             */
-            pDest += 2*NumSamples;                                                              /* Output sample pointer */
-            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);      /* No samples left in the buffer */
-
-
-            /*
-             * Realign the delay buffer data to avoid using circular buffer management
-             */
-            Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples],         /* Source */
-                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
-                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of samples to move */
-            NumSamples = 0;                                         /* Samples left to send */
-        }
-    }
-
-
-    /*
-     * Copy the processed results to the output
-     */
-    if ((NumSamples != 0) &&
-        (SampleCount != 0))
-    {
-        if (SampleCount <= NumSamples)
-        {
-            /*
-             * Copy all processed samples to the output
-             */
-            Copy_16(pStart,                                      /* Source */
-                    pDest,                                       /* Detsination */
-                    (LVM_INT16)(2*SampleCount));                 /* Number of processed samples */
-
-            /*
-             * Update the pointer and sample counts
-             */
-            pDest      += 2 * SampleCount;                          /* Output sample pointer */
-            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
-            SampleCount = 0;                                        /* No samples left in the buffer */
-        }
-        else
-        {
-            /*
-             * Copy only some processed samples to the output
-             */
-            Copy_16(pStart,                                         /* Source */
-                    pDest,                                          /* Destination */
-                    (LVM_INT16)(2*NumSamples));                     /* Number of processed samples */
-
-
-            /*
-             * Update the pointers and sample counts
-               */
-            pStart      += 2 * NumSamples;                          /* Processed sample pointer */
-            pDest        += 2 * NumSamples;                         /* Output sample pointer */
-            SampleCount  = (LVM_INT16)(SampleCount - NumSamples);   /* Processed samples left */
-            NumSamples   = 0;                                       /* Clear the sample count */
-        }
-    }
-
-
-    /*
-     * Copy the remaining processed data to the output delay buffer
-     */
-    if (SampleCount != 0)
-    {
-        Copy_16(pStart,                                                 /* Source */
-                &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples],   /* Destination */
-                (LVM_INT16)(2*SampleCount));                            /* Number of processed samples */
-        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
-    }
-
-
-    /*
-     * pointers, counts and set default buffer processing
-     */
-    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
-    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
-    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call block size */
-    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;         /* This will terminate the loop when all samples processed */
-}
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This works in conjunction with the unmanaged input routine and updates the number   */
-/*    of samples left to be processed    and adjusts the buffer pointers.               */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        - Instance handle                                                */
-/*    pNumSamples        - Pointer to the number of samples to process                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-
-void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
-                            LVM_UINT16          *pNumSamples)
-{
-
-    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
-#ifdef SUPPORT_MC
-    LVM_INT16           NumChannels = pInstance->NrChannels;
-    if (NumChannels == 1)
-    {
-        /* Mono input is processed as stereo by LVM module */
-        NumChannels = 2;
-    }
-#undef NrFrames
-#define NrFrames (*pNumSamples) // alias for clarity
-#else
-    LVM_INT16           NumChannels = 2;
-#endif
-
-
-    /*
-     * Update sample counts
-     */
-    pInstance->pInputSamples    += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
-#ifdef SUPPORT_MC
-    pInstance->pOutputSamples   += (LVM_INT16)(NrFrames * NumChannels);
-#else
-    pInstance->pOutputSamples   += (LVM_INT16)(*pNumSamples * 2);
-#endif
-    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
-
-    /*
-     * Set te block size to process
-     */
-    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
-    {
-        *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
-    }
-    else
-    {
-        *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
-    }
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferOptimisedOut                                     */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This works in conjunction with the optimised input routine and copies the last few  */
-/*  processed and unprocessed samples to their respective buffers.                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        - Instance handle                                                */
-/*    pNumSamples        - Pointer to the number of samples to process                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-
-#ifndef BUILD_FLOAT
-void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
-                            LVM_UINT16        *pNumSamples)
-{
-
-    LVM_Instance_t      *pInstance = (LVM_Instance_t  *)hInstance;
-    LVM_Buffer_t        *pBuffer   = pInstance->pBufferManagement;
-
-    /*
-     * Check if it is the last block to process
-     */
-    if (pBuffer->BufferState == LVM_LASTCALL)
-    {
-        LVM_INT16    *pSrc = pBuffer->pScratch;
-
-        /*
-         * Copy the unprocessed samples to the input delay buffer
-         */
-        if (pInstance->SamplesToProcess != 0)
-        {
-            Copy_16(pInstance->pInputSamples,                       /* Source */
-                    &pBuffer->InDelayBuffer[0],                     /* Destination */
-                    (LVM_INT16)(2*pInstance->SamplesToProcess));    /* Number of input samples */
-            pBuffer->InDelaySamples = pInstance->SamplesToProcess;
-            pInstance->SamplesToProcess = 0;
-        }
-        else
-        {
-            pBuffer->InDelaySamples = 0;
-        }
-
-
-        /*
-         * Fill the last empty spaces in the output buffer
-         */
-        if (pBuffer->SamplesToOutput != 0)
-        {
-            Copy_16(pSrc,                                           /* Source */
-                    pInstance->pOutputSamples,                      /* Destination */
-                    (LVM_INT16)(2*pBuffer->SamplesToOutput));       /* Number of input samples */
-            *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
-            pSrc += 2 * pBuffer->SamplesToOutput;                  /* Update scratch pointer */
-            pBuffer->SamplesToOutput = 0;                          /* No more samples in this block */
-        }
-
-
-        /*
-         * Save any remaining processed samples in the output delay buffer
-         */
-        if (*pNumSamples != 0)
-        {
-            Copy_16(pSrc,                                           /* Source */
-                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
-                    (LVM_INT16)(2**pNumSamples));                   /* Number of input samples */
-
-            pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
-
-            *pNumSamples = 0;                                      /* No more samples in this block */
-        }
-        else
-        {
-            pBuffer->OutDelaySamples = 0;
-        }
-    }
-}
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVM_BufferOut                                              */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function manages the data output, it has the following features:               */
-/*        - Output data to 16-bit aligned memory                                        */
-/*        - Reads data from 32-bit aligned memory                                       */
-/*        - Reads data only in blocks of frame size or multiples of frame size          */
-/*        - Writes the same number of samples as the LVM_BufferIn function reads        */
-/*        - Works with inplace or outplace processing automatically                     */
-/*                                                                                      */
-/*  To manage the data the function has a number of operating states:                   */
-/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
-/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
-/*                              samples, this occurs when the number of samples to      */
-/*                              process is less than the maximum block size.            */
-/*                                                                                      */
-/*    The function uses an internal delay buffer the size of the minimum frame, this is */
-/*  used to temporarily hold samples when the number of samples to write is not a       */
-/*  multiple of the frame size.                                                         */
-/*                                                                                      */
-/*    To ensure correct operation with inplace buffering the number of samples to output*/
-/*  per call is always the same as the number of samples read from the input buffer.    */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    hInstance        - Instance handle                                                */
-/*    pOutData        - Pointer to the output data stream                               */
-/*    pNumSamples        - Pointer to the number of samples to process                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-void LVM_BufferOut(LVM_Handle_t     hInstance,
-                   LVM_FLOAT        *pOutData,
-                   LVM_UINT16       *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check which mode, managed or unmanaged
-     */
-    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        LVM_BufferManagedOut(hInstance,
-                             pOutData,
-                             pNumSamples);
-    }
-    else
-    {
-        LVM_BufferUnmanagedOut(hInstance,
-                               pNumSamples);
-    }
-}
-#else
-void LVM_BufferOut(LVM_Handle_t     hInstance,
-                   LVM_INT16        *pOutData,
-                   LVM_UINT16       *pNumSamples)
-{
-
-    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check which mode, managed or unmanaged
-     */
-    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        LVM_BufferManagedOut(hInstance,
-                             pOutData,
-                             pNumSamples);
-    }
-    else
-    {
-        LVM_BufferUnmanagedOut(hInstance,
-                               pNumSamples);
-    }
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp
new file mode 100644
index 0000000..3aeddbb
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.cpp
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                        */
+/*    Includes                                                                              */
+/*                                                                                        */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+
+#include <log/log.h>
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferManagedIn                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Full buffer management allowing the user to provide input and output buffers on   */
+/*  any alignment and with any number of samples. The alignment is corrected within     */
+/*  the buffer management and the samples are grouped in to blocks of the correct size  */
+/*  before processing.                                                                  */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to pointer to the start of data processing          */
+/*  *pProcessed        -    Pointer to pointer to the destination of the processed data */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
+                         const LVM_FLOAT    *pInData,
+                         LVM_FLOAT          **pToProcess,
+                         LVM_FLOAT          **pProcessed,
+                         LVM_UINT16         *pNumSamples)
+{
+
+    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
+    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
+    LVM_FLOAT        *pStart;
+    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t     *pBuffer;
+    LVM_FLOAT        *pDest;
+#ifdef SUPPORT_MC
+    LVM_INT16        NumChannels = pInstance->NrChannels;
+#else
+    LVM_INT16        NumChannels = 2;
+#endif
+
+    /*
+     * Set the processing address pointers
+     */
+    pBuffer     = pInstance->pBufferManagement;
+    pDest       = pBuffer->pScratch;
+    *pToProcess = pBuffer->pScratch;
+    *pProcessed = pBuffer->pScratch;
+
+    /*
+     * Check if it is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        /*
+         * First call for a new block of samples
+         */
+        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
+        pInstance->pInputSamples    = (LVM_FLOAT *)pInData;
+        pBuffer->BufferState        = LVM_FIRSTCALL;
+    }
+    pStart = pInstance->pInputSamples;                 /* Pointer to the input samples */
+    pBuffer->SamplesToOutput  = 0;                     /* Samples to output is same as
+                                                          number read for inplace processing */
+
+    /*
+     * Calculate the number of samples to process this call and update the buffer state
+     */
+    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+    {
+        /*
+         * Process the maximum bock size of samples.
+         */
+        SampleCount = pInstance->InternalBlockSize;
+        NumSamples  = pInstance->InternalBlockSize;
+    }
+    else
+    {
+        /*
+         * Last call for the block, so calculate how many frames and samples to process
+          */
+        LVM_INT16   NumFrames;
+
+        NumSamples  = pInstance->SamplesToProcess;
+        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+
+        /*
+         * Update the buffer state
+         */
+        if (pBuffer->BufferState == LVM_FIRSTCALL)
+        {
+            pBuffer->BufferState = LVM_FIRSTLASTCALL;
+        }
+        else
+        {
+            pBuffer->BufferState = LVM_LASTCALL;
+        }
+    }
+    *pNumSamples = (LVM_UINT16)SampleCount;  /* Set the number of samples to process this call */
+
+    /*
+     * Copy samples from the delay buffer as required
+     */
+    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
+        (pBuffer->InDelaySamples != 0))
+    {
+        Copy_Float(&pBuffer->InDelayBuffer[0],                             /* Source */
+                   pDest,                                                  /* Destination */
+                   (LVM_INT16)(NumChannels * pBuffer->InDelaySamples));    /* Number of delay \
+                                                                       samples, left and right */
+        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
+        pDest += NumChannels * pBuffer->InDelaySamples;      /* Update the destination pointer */
+    }
+
+    /*
+     * Copy the rest of the samples for this call from the input buffer
+     */
+    if (NumSamples > 0)
+    {
+        Copy_Float(pStart,                                      /* Source */
+                   pDest,                                       /* Destination */
+                   (LVM_INT16)(NumChannels * NumSamples));      /* Number of input samples */
+        pStart += NumChannels * NumSamples;                     /* Update the input pointer */
+
+        /*
+         * Update the input data pointer and samples to output
+         */
+        /* Update samples to output */
+        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples);
+    }
+
+    /*
+      * Update the sample count and input pointer
+     */
+    /* Update the count of samples */
+    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);
+    pInstance->pInputSamples     = pStart; /* Update input sample pointer */
+
+    /*
+     * Save samples to the delay buffer if any left unprocessed
+     */
+    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
+        (pBuffer->BufferState == LVM_LASTCALL))
+    {
+        NumSamples = pInstance->SamplesToProcess;
+        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
+        pStart    += NumChannels * SampleCount; /* Offset by the number of processed samples */
+        if (NumSamples != 0)
+        {
+            Copy_Float(pStart,                                         /* Source */
+                       &pBuffer->InDelayBuffer[0],                     /* Destination */
+                       (LVM_INT16)(NumChannels * NumSamples));   /* Number of input samples */
+        }
+
+        /*
+         * Update the delay sample count
+         */
+        pBuffer->InDelaySamples     = NumSamples;       /* Number of delay sample pairs */
+        pInstance->SamplesToProcess = 0;                            /* All Samples used */
+    }
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This mode is selected by the user code and disables the buffer management with the */
+/*  exception of the maximum block size processing. The user must ensure that the       */
+/*  input and output buffers are 32-bit aligned and also that the number of samples to  */
+/*    process is a correct multiple of samples.                                         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
+                           LVM_FLOAT        **pToProcess,
+                           LVM_FLOAT        **pProcessed,
+                           LVM_UINT16       *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+    /*
+     * Check if this is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;    /* Get the number of samples
+                                                                               on first call */
+        pInstance->pInputSamples    = *pToProcess;                /* Get the I/O pointers */
+        pInstance->pOutputSamples    = *pProcessed;
+
+        /*
+         * Set te block size to process
+         */
+        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+        }
+        else
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+        }
+    }
+
+    /*
+     * Set the process pointers
+     */
+    *pToProcess = pInstance->pInputSamples;
+    *pProcessed = pInstance->pOutputSamples;
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOptimisedIn                                      */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Optimised buffer management for the case where the data is outplace processing,   */
+/*    the output data is 32-bit aligned and there are sufficient samples to allow some  */
+/*    processing directly in the output buffer. This saves one data copy per sample     */
+/*    compared with the unoptimsed version.                                             */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferIn                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This function manages the data input, it has the following features:              */
+/*        - Accepts data in 16-bit aligned memory                                       */
+/*        - Copies the data to 32-bit aligned memory                                    */
+/*        - Converts Mono inputs to Mono-in-Stereo                                      */
+/*        - Accepts any number of samples as input, except 0                            */
+/*        - Breaks the input sample stream in to blocks of the configured frame size or */
+/*          multiples of the frame size                                                 */
+/*        - Limits the processing block size to the maximum block size.                 */
+/*        - Works with inplace or outplace processing automatically                     */
+/*                                                                                      */
+/*  To manage the data the function has a number of operating states:                   */
+/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
+/*        LVM_MAXBLOCKCALL    - The current block is the maximum size. Only used for the */
+/*                              second and subsequent blocks.                           */
+/*        LVM_LASTCALL        - The last call for this block of input samples           */
+/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
+/*                              samples, this occurs when the number of samples to      */
+/*                              process is less than the maximum block size.            */
+/*                                                                                      */
+/*    The function uses an internal delay buffer the size of the minimum frame, this is */
+/*  used to temporarily hold samples when the number of samples to process is not a     */
+/*  multiple of the frame size.                                                         */
+/*                                                                                      */
+/*    To ensure correct operation with inplace buffering the number of samples to output*/
+/*  per call is calculated in this function and is set to the number of samples read    */
+/*  from the input buffer.                                                              */
+/*                                                                                      */
+/*    The total number of samples to process is stored when the function is called for  */
+/*  the first time. The value is overwritten by the size of the block to be processed   */
+/*  in each call so the size of the processing blocks can be controlled. The number of  */
+/*    samples actually processed for each block of input samples is always a multiple of*/
+/*  the frame size so for any particular block of input samples the actual number of    */
+/*  processed samples may not match the number of input samples, sometime it will be    */
+/*  sometimes less. The average is the same and the difference is never more than the   */
+/*  frame size.                                                                         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_BufferIn(LVM_Handle_t      hInstance,
+                  const LVM_FLOAT   *pInData,
+                  LVM_FLOAT         **pToProcess,
+                  LVM_FLOAT         **pProcessed,
+                  LVM_UINT16        *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedIn(hInstance,
+                            pInData,
+                            pToProcess,
+                            pProcessed,
+                            pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedIn(hInstance,
+                              pToProcess,
+                              pProcessed,
+                              pNumSamples);
+    }
+}
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferManagedOut                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Full buffer management output. This works in conjunction with the managed input     */
+/*  routine and ensures the correct number of samples are always output to the output   */
+/*  buffer.                                                                             */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pOutData        - Pointer to the output data stream                               */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
+                          LVM_FLOAT            *pOutData,
+                          LVM_UINT16        *pNumSamples)
+{
+
+    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
+    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
+    LVM_INT16       NumSamples;
+    LVM_FLOAT       *pStart;
+    LVM_FLOAT       *pDest;
+#ifdef SUPPORT_MC
+    LVM_INT32       NrChannels = pInstance->NrChannels;
+#define NrFrames NumSamples  // alias for clarity
+#define FrameCount SampleCount
+#endif
+
+    /*
+     * Set the pointers
+     */
+    NumSamples = pBuffer->SamplesToOutput;
+    pStart     = pBuffer->pScratch;
+
+    /*
+     * check if it is the first call of a block
+      */
+    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
+    {
+        /* First call for a new block */
+        pInstance->pOutputSamples = pOutData;                 /* Initialise the destination */
+    }
+    pDest = pInstance->pOutputSamples;                        /* Set the output address */
+
+    /*
+     * If the number of samples is non-zero then there are still samples to send to
+     * the output buffer
+     */
+    if ((NumSamples != 0) &&
+        (pBuffer->OutDelaySamples != 0))
+    {
+        /*
+         * Copy the delayed output buffer samples to the output
+         */
+        if (pBuffer->OutDelaySamples <= NumSamples)
+        {
+            /*
+             * Copy all output delay samples to the output
+             */
+#ifdef SUPPORT_MC
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
+                       pDest,                                      /* Destination */
+                       /* Number of delay samples */
+                       (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
+#else
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
+                       pDest,                                      /* Destination */
+                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of delay samples */
+#endif
+
+            /*
+             * Update the pointer and sample counts
+             */
+#ifdef SUPPORT_MC
+            pDest += NrChannels * pBuffer->OutDelaySamples; /* Output sample pointer */
+#else
+            pDest += 2 * pBuffer->OutDelaySamples; /* Output sample pointer */
+#endif
+            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left \
+                                                                                to send */
+            pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
+        }
+        else
+        {
+            /*
+             * Copy only some of the ouput delay samples to the output
+             */
+#ifdef SUPPORT_MC
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                       pDest,                                          /* Destination */
+                       (LVM_INT16)(NrChannels * NrFrames));       /* Number of delay samples */
+#else
+            Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                       pDest,                                          /* Destination */
+                       (LVM_INT16)(2 * NumSamples));       /* Number of delay samples */
+#endif
+
+            /*
+             * Update the pointer and sample counts
+             */
+#ifdef SUPPORT_MC
+            pDest += NrChannels * NrFrames; /* Output sample pointer */
+#else
+            pDest += 2 * NumSamples; /* Output sample pointer */
+#endif
+            /* No samples left in the buffer */
+            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);
+
+            /*
+             * Realign the delay buffer data to avoid using circular buffer management
+             */
+#ifdef SUPPORT_MC
+            Copy_Float(&pBuffer->OutDelayBuffer[NrChannels * NrFrames],         /* Source */
+                       &pBuffer->OutDelayBuffer[0],                    /* Destination */
+                       /* Number of samples to move */
+                       (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
+#else
+            Copy_Float(&pBuffer->OutDelayBuffer[2 * NumSamples],         /* Source */
+                       &pBuffer->OutDelayBuffer[0],                    /* Destination */
+                       (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of samples to move */
+#endif
+            NumSamples = 0;                                /* Samples left to send */
+        }
+    }
+
+    /*
+     * Copy the processed results to the output
+     */
+    if ((NumSamples != 0) &&
+        (SampleCount != 0))
+    {
+        if (SampleCount <= NumSamples)
+        {
+            /*
+             * Copy all processed samples to the output
+             */
+#ifdef SUPPORT_MC
+            Copy_Float(pStart,                                      /* Source */
+                       pDest,                                       /* Destination */
+                       (LVM_INT16)(NrChannels * FrameCount)); /* Number of processed samples */
+#else
+            Copy_Float(pStart,                                      /* Source */
+                       pDest,                                       /* Destination */
+                       (LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
+#endif
+            /*
+             * Update the pointer and sample counts
+             */
+#ifdef SUPPORT_MC
+            pDest      += NrChannels * FrameCount;                 /* Output sample pointer */
+#else
+            pDest      += 2 * SampleCount;                          /* Output sample pointer */
+#endif
+            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
+            SampleCount = 0; /* No samples left in the buffer */
+        }
+        else
+        {
+            /*
+             * Copy only some processed samples to the output
+             */
+#ifdef SUPPORT_MC
+            Copy_Float(pStart,                                         /* Source */
+                       pDest,                                          /* Destination */
+                       (LVM_INT16)(NrChannels * NrFrames));  /* Number of processed samples */
+#else
+            Copy_Float(pStart,                                         /* Source */
+                       pDest,                                          /* Destination */
+                       (LVM_INT16)(2 * NumSamples));     /* Number of processed samples */
+#endif
+            /*
+             * Update the pointers and sample counts
+               */
+#ifdef SUPPORT_MC
+            pStart      += NrChannels * NrFrames;               /* Processed sample pointer */
+            pDest       += NrChannels * NrFrames;               /* Output sample pointer */
+#else
+            pStart      += 2 * NumSamples;                        /* Processed sample pointer */
+            pDest       += 2 * NumSamples;                        /* Output sample pointer */
+#endif
+            SampleCount  = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
+            NumSamples   = 0;                                     /* Clear the sample count */
+        }
+    }
+
+    /*
+     * Copy the remaining processed data to the output delay buffer
+     */
+    if (SampleCount != 0)
+    {
+#ifdef SUPPORT_MC
+        Copy_Float(pStart,                                                 /* Source */
+                   /* Destination */
+                   &pBuffer->OutDelayBuffer[NrChannels * pBuffer->OutDelaySamples],
+                   (LVM_INT16)(NrChannels * FrameCount));      /* Number of processed samples */
+#else
+        Copy_Float(pStart,                                                 /* Source */
+                   &pBuffer->OutDelayBuffer[2 * pBuffer->OutDelaySamples], /* Destination */
+                   (LVM_INT16)(2 * SampleCount));               /* Number of processed samples */
+#endif
+        /* Update the buffer count */
+        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount);
+    }
+
+    /*
+     * pointers, counts and set default buffer processing
+     */
+    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
+    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
+    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call \
+                                                                            block size */
+    /* This will terminate the loop when all samples processed */
+    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This works in conjunction with the unmanaged input routine and updates the number   */
+/*    of samples left to be processed    and adjusts the buffer pointers.               */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
+                            LVM_UINT16          *pNumSamples)
+{
+
+    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
+#ifdef SUPPORT_MC
+    LVM_INT16           NumChannels = pInstance->NrChannels;
+    if (NumChannels == 1)
+    {
+        /* Mono input is processed as stereo by LVM module */
+        NumChannels = 2;
+    }
+#undef NrFrames
+#define NrFrames (*pNumSamples) // alias for clarity
+#else
+    LVM_INT16           NumChannels = 2;
+#endif
+
+    /*
+     * Update sample counts
+     */
+    pInstance->pInputSamples    += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
+#ifdef SUPPORT_MC
+    pInstance->pOutputSamples   += (LVM_INT16)(NrFrames * NumChannels);
+#else
+    pInstance->pOutputSamples   += (LVM_INT16)(*pNumSamples * 2);
+#endif
+    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
+
+    /*
+     * Set te block size to process
+     */
+    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+    {
+        *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+    }
+    else
+    {
+        *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+    }
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOptimisedOut                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This works in conjunction with the optimised input routine and copies the last few  */
+/*  processed and unprocessed samples to their respective buffers.                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOut                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function manages the data output, it has the following features:               */
+/*        - Output data to 16-bit aligned memory                                        */
+/*        - Reads data from 32-bit aligned memory                                       */
+/*        - Reads data only in blocks of frame size or multiples of frame size          */
+/*        - Writes the same number of samples as the LVM_BufferIn function reads        */
+/*        - Works with inplace or outplace processing automatically                     */
+/*                                                                                      */
+/*  To manage the data the function has a number of operating states:                   */
+/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
+/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
+/*                              samples, this occurs when the number of samples to      */
+/*                              process is less than the maximum block size.            */
+/*                                                                                      */
+/*    The function uses an internal delay buffer the size of the minimum frame, this is */
+/*  used to temporarily hold samples when the number of samples to write is not a       */
+/*  multiple of the frame size.                                                         */
+/*                                                                                      */
+/*    To ensure correct operation with inplace buffering the number of samples to output*/
+/*  per call is always the same as the number of samples read from the input buffer.    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pOutData        - Pointer to the output data stream                               */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_BufferOut(LVM_Handle_t     hInstance,
+                   LVM_FLOAT        *pOutData,
+                   LVM_UINT16       *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedOut(hInstance,
+                             pOutData,
+                             pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedOut(hInstance,
+                               pNumSamples);
+    }
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
index bab4049..812f8e5 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
@@ -18,7 +18,6 @@
 #ifndef __LVM_COEFFS_H__
 #define __LVM_COEFFS_H__
 
-
 /************************************************************************************/
 /*                                                                                  */
 /* High Pass Shelving Filter coefficients                                           */
@@ -29,7 +28,6 @@
 #define TrebleBoostMinRate                                    4
 #define TrebleBoostSteps                                     15
 
-#ifdef BUILD_FLOAT
 /* Coefficients for sample rate 22050Hz */
                                                                     /* Gain =  1.000000 dB */
 #define HPF_Fs22050_Gain1_A0                            1.038434
@@ -486,7 +484,6 @@
 #define HPF_Fs48000_Gain15_B1                         (-0.267949)
 #define HPF_Fs48000_Gain15_B2                         0.000000
 
-#ifdef HIGHER_FS
 /* Coefficients for sample rate 88200 */
 /* Gain = 1.000000 dB */
 #define HPF_Fs88200_Gain1_A0                          1.094374f
@@ -856,547 +853,3 @@
 #define HPF_Fs192000_Gain15_B2                         0.000000
 
 #endif
-
-#else
-/* Coefficients for sample rate 22050Hz */
-                                                                    /* Gain =  1.000000 dB */
-#define HPF_Fs22050_Gain1_A0                             5383         /* Floating point value 0.164291 */
-#define HPF_Fs22050_Gain1_A1                            16859         /* Floating point value 0.514492 */
-#define HPF_Fs22050_Gain1_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain1_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain1_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain1_Shift                             1         /* Shift value */
-                                                                    /* Gain =  2.000000 dB */
-#define HPF_Fs22050_Gain2_A0                             4683         /* Floating point value 0.142925 */
-#define HPF_Fs22050_Gain2_A1                            17559         /* Floating point value 0.535858 */
-#define HPF_Fs22050_Gain2_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain2_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain2_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain2_Shift                             1         /* Shift value */
-                                                                    /* Gain =  3.000000 dB */
-#define HPF_Fs22050_Gain3_A0                             3898         /* Floating point value 0.118953 */
-#define HPF_Fs22050_Gain3_A1                            18345         /* Floating point value 0.559830 */
-#define HPF_Fs22050_Gain3_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain3_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain3_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain3_Shift                             1         /* Shift value */
-                                                                    /* Gain =  4.000000 dB */
-#define HPF_Fs22050_Gain4_A0                             3016         /* Floating point value 0.092055 */
-#define HPF_Fs22050_Gain4_A1                            19226         /* Floating point value 0.586728 */
-#define HPF_Fs22050_Gain4_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain4_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain4_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain4_Shift                             1         /* Shift value */
-                                                                    /* Gain =  5.000000 dB */
-#define HPF_Fs22050_Gain5_A0                             2028         /* Floating point value 0.061876 */
-#define HPF_Fs22050_Gain5_A1                            20215         /* Floating point value 0.616907 */
-#define HPF_Fs22050_Gain5_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain5_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain5_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain5_Shift                             1         /* Shift value */
-                                                                    /* Gain =  6.000000 dB */
-#define HPF_Fs22050_Gain6_A0                              918         /* Floating point value 0.028013 */
-#define HPF_Fs22050_Gain6_A1                            21324         /* Floating point value 0.650770 */
-#define HPF_Fs22050_Gain6_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain6_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain6_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain6_Shift                             1         /* Shift value */
-                                                                    /* Gain =  7.000000 dB */
-#define HPF_Fs22050_Gain7_A0                            (-164)        /* Floating point value -0.005002 */
-#define HPF_Fs22050_Gain7_A1                            11311         /* Floating point value 0.345199 */
-#define HPF_Fs22050_Gain7_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain7_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain7_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain7_Shift                             2         /* Shift value */
-                                                                    /* Gain =  8.000000 dB */
-#define HPF_Fs22050_Gain8_A0                            (-864)        /* Floating point value -0.026368 */
-#define HPF_Fs22050_Gain8_A1                            12012         /* Floating point value 0.366565 */
-#define HPF_Fs22050_Gain8_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain8_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain8_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain8_Shift                             2         /* Shift value */
-                                                                    /* Gain =  9.000000 dB */
-#define HPF_Fs22050_Gain9_A0                           (-1650)        /* Floating point value -0.050340 */
-#define HPF_Fs22050_Gain9_A1                            12797         /* Floating point value 0.390537 */
-#define HPF_Fs22050_Gain9_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain9_B1                            12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain9_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain9_Shift                             2         /* Shift value */
-                                                                    /* Gain =  10.000000 dB */
-#define HPF_Fs22050_Gain10_A0                          (-2531)        /* Floating point value -0.077238 */
-#define HPF_Fs22050_Gain10_A1                           13679         /* Floating point value 0.417435 */
-#define HPF_Fs22050_Gain10_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain10_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain10_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain10_Shift                            2         /* Shift value */
-                                                                    /* Gain =  11.000000 dB */
-#define HPF_Fs22050_Gain11_A0                          (-3520)        /* Floating point value -0.107417 */
-#define HPF_Fs22050_Gain11_A1                           14667         /* Floating point value 0.447615 */
-#define HPF_Fs22050_Gain11_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain11_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain11_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain11_Shift                            2         /* Shift value */
-                                                                    /* Gain =  12.000000 dB */
-#define HPF_Fs22050_Gain12_A0                          (-4629)        /* Floating point value -0.141279 */
-#define HPF_Fs22050_Gain12_A1                           15777         /* Floating point value 0.481477 */
-#define HPF_Fs22050_Gain12_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain12_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain12_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain12_Shift                            2         /* Shift value */
-                                                                    /* Gain =  13.000000 dB */
-#define HPF_Fs22050_Gain13_A0                          (-2944)        /* Floating point value -0.089849 */
-#define HPF_Fs22050_Gain13_A1                            8531         /* Floating point value 0.260352 */
-#define HPF_Fs22050_Gain13_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain13_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain13_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain13_Shift                            3         /* Shift value */
-                                                                    /* Gain =  14.000000 dB */
-#define HPF_Fs22050_Gain14_A0                          (-3644)        /* Floating point value -0.111215 */
-#define HPF_Fs22050_Gain14_A1                            9231         /* Floating point value 0.281718 */
-#define HPF_Fs22050_Gain14_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain14_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain14_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain14_Shift                            3         /* Shift value */
-                                                                    /* Gain =  15.000000 dB */
-#define HPF_Fs22050_Gain15_A0                          (-4430)        /* Floating point value -0.135187 */
-#define HPF_Fs22050_Gain15_A1                           10017         /* Floating point value 0.305690 */
-#define HPF_Fs22050_Gain15_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain15_B1                           12125         /* Floating point value 0.370033 */
-#define HPF_Fs22050_Gain15_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs22050_Gain15_Shift                            3         /* Shift value */
-
-
-/* Coefficients for sample rate 24000Hz */
-                                                                    /* Gain =  1.000000 dB */
-#define HPF_Fs24000_Gain1_A0                             3625         /* Floating point value 0.110628 */
-#define HPF_Fs24000_Gain1_A1                            16960         /* Floating point value 0.517578 */
-#define HPF_Fs24000_Gain1_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain1_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain1_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain1_Shift                             1         /* Shift value */
-                                                                    /* Gain =  2.000000 dB */
-#define HPF_Fs24000_Gain2_A0                             2811         /* Floating point value 0.085800 */
-#define HPF_Fs24000_Gain2_A1                            17774         /* Floating point value 0.542406 */
-#define HPF_Fs24000_Gain2_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain2_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain2_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain2_Shift                             1         /* Shift value */
-                                                                    /* Gain =  3.000000 dB */
-#define HPF_Fs24000_Gain3_A0                             1899         /* Floating point value 0.057943 */
-#define HPF_Fs24000_Gain3_A1                            18686         /* Floating point value 0.570263 */
-#define HPF_Fs24000_Gain3_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain3_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain3_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain3_Shift                             1         /* Shift value */
-                                                                    /* Gain =  4.000000 dB */
-#define HPF_Fs24000_Gain4_A0                              874         /* Floating point value 0.026687 */
-#define HPF_Fs24000_Gain4_A1                            19711         /* Floating point value 0.601519 */
-#define HPF_Fs24000_Gain4_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain4_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain4_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain4_Shift                             1         /* Shift value */
-                                                                    /* Gain =  5.000000 dB */
-#define HPF_Fs24000_Gain5_A0                            (-275)        /* Floating point value -0.008383 */
-#define HPF_Fs24000_Gain5_A1                            20860         /* Floating point value 0.636589 */
-#define HPF_Fs24000_Gain5_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain5_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain5_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain5_Shift                             1         /* Shift value */
-                                                                    /* Gain =  6.000000 dB */
-#define HPF_Fs24000_Gain6_A0                           (-1564)        /* Floating point value -0.047733 */
-#define HPF_Fs24000_Gain6_A1                            22149         /* Floating point value 0.675938 */
-#define HPF_Fs24000_Gain6_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain6_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain6_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain6_Shift                             1         /* Shift value */
-                                                                    /* Gain =  7.000000 dB */
-#define HPF_Fs24000_Gain7_A0                           (-1509)        /* Floating point value -0.046051 */
-#define HPF_Fs24000_Gain7_A1                            11826         /* Floating point value 0.360899 */
-#define HPF_Fs24000_Gain7_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain7_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain7_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain7_Shift                             2         /* Shift value */
-                                                                    /* Gain =  8.000000 dB */
-#define HPF_Fs24000_Gain8_A0                           (-2323)        /* Floating point value -0.070878 */
-#define HPF_Fs24000_Gain8_A1                            12640         /* Floating point value 0.385727 */
-#define HPF_Fs24000_Gain8_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain8_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain8_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain8_Shift                             2         /* Shift value */
-                                                                    /* Gain =  9.000000 dB */
-#define HPF_Fs24000_Gain9_A0                           (-3235)        /* Floating point value -0.098736 */
-#define HPF_Fs24000_Gain9_A1                            13552         /* Floating point value 0.413584 */
-#define HPF_Fs24000_Gain9_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain9_B1                             8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain9_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain9_Shift                             2         /* Shift value */
-                                                                    /* Gain =  10.000000 dB */
-#define HPF_Fs24000_Gain10_A0                          (-4260)        /* Floating point value -0.129992 */
-#define HPF_Fs24000_Gain10_A1                           14577         /* Floating point value 0.444841 */
-#define HPF_Fs24000_Gain10_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain10_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain10_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain10_Shift                            2         /* Shift value */
-                                                                    /* Gain =  11.000000 dB */
-#define HPF_Fs24000_Gain11_A0                          (-5409)        /* Floating point value -0.165062 */
-#define HPF_Fs24000_Gain11_A1                           15726         /* Floating point value 0.479911 */
-#define HPF_Fs24000_Gain11_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain11_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain11_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain11_Shift                            2         /* Shift value */
-                                                                    /* Gain =  12.000000 dB */
-#define HPF_Fs24000_Gain12_A0                          (-6698)        /* Floating point value -0.204411 */
-#define HPF_Fs24000_Gain12_A1                           17015         /* Floating point value 0.519260 */
-#define HPF_Fs24000_Gain12_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain12_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain12_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain12_Shift                            2         /* Shift value */
-                                                                    /* Gain =  13.000000 dB */
-#define HPF_Fs24000_Gain13_A0                          (-4082)        /* Floating point value -0.124576 */
-#define HPF_Fs24000_Gain13_A1                            9253         /* Floating point value 0.282374 */
-#define HPF_Fs24000_Gain13_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain13_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain13_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain13_Shift                            3         /* Shift value */
-                                                                    /* Gain =  14.000000 dB */
-#define HPF_Fs24000_Gain14_A0                          (-4896)        /* Floating point value -0.149404 */
-#define HPF_Fs24000_Gain14_A1                           10066         /* Floating point value 0.307202 */
-#define HPF_Fs24000_Gain14_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain14_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain14_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain14_Shift                            3         /* Shift value */
-                                                                    /* Gain =  15.000000 dB */
-#define HPF_Fs24000_Gain15_A0                          (-5808)        /* Floating point value -0.177261 */
-#define HPF_Fs24000_Gain15_A1                           10979         /* Floating point value 0.335059 */
-#define HPF_Fs24000_Gain15_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain15_B1                            8780         /* Floating point value 0.267949 */
-#define HPF_Fs24000_Gain15_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs24000_Gain15_Shift                            3         /* Shift value */
-
-
-/* Coefficients for sample rate 32000Hz */
-                                                                    /* Gain =  1.000000 dB */
-#define HPF_Fs32000_Gain1_A0                            17225         /* Floating point value 0.525677 */
-#define HPF_Fs32000_Gain1_A1                            (-990)        /* Floating point value -0.030227 */
-#define HPF_Fs32000_Gain1_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain1_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain1_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain1_Shift                             1         /* Shift value */
-                                                                    /* Gain =  2.000000 dB */
-#define HPF_Fs32000_Gain2_A0                            18337         /* Floating point value 0.559593 */
-#define HPF_Fs32000_Gain2_A1                           (-2102)        /* Floating point value -0.064142 */
-#define HPF_Fs32000_Gain2_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain2_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain2_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain2_Shift                             1         /* Shift value */
-                                                                    /* Gain =  3.000000 dB */
-#define HPF_Fs32000_Gain3_A0                            19584         /* Floating point value 0.597646 */
-#define HPF_Fs32000_Gain3_A1                           (-3349)        /* Floating point value -0.102196 */
-#define HPF_Fs32000_Gain3_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain3_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain3_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain3_Shift                             1         /* Shift value */
-                                                                    /* Gain =  4.000000 dB */
-#define HPF_Fs32000_Gain4_A0                            20983         /* Floating point value 0.640343 */
-#define HPF_Fs32000_Gain4_A1                           (-4748)        /* Floating point value -0.144893 */
-#define HPF_Fs32000_Gain4_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain4_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain4_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain4_Shift                             1         /* Shift value */
-                                                                    /* Gain =  5.000000 dB */
-#define HPF_Fs32000_Gain5_A0                            22553         /* Floating point value 0.688250 */
-#define HPF_Fs32000_Gain5_A1                           (-6318)        /* Floating point value -0.192799 */
-#define HPF_Fs32000_Gain5_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain5_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain5_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain5_Shift                             1         /* Shift value */
-                                                                    /* Gain =  6.000000 dB */
-#define HPF_Fs32000_Gain6_A0                            24314         /* Floating point value 0.742002 */
-#define HPF_Fs32000_Gain6_A1                           (-8079)        /* Floating point value -0.246551 */
-#define HPF_Fs32000_Gain6_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain6_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain6_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain6_Shift                             1         /* Shift value */
-                                                                    /* Gain =  7.000000 dB */
-#define HPF_Fs32000_Gain7_A0                            13176         /* Floating point value 0.402109 */
-#define HPF_Fs32000_Gain7_A1                           (-5040)        /* Floating point value -0.153795 */
-#define HPF_Fs32000_Gain7_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain7_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain7_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain7_Shift                             2         /* Shift value */
-                                                                    /* Gain =  8.000000 dB */
-#define HPF_Fs32000_Gain8_A0                            14288         /* Floating point value 0.436024 */
-#define HPF_Fs32000_Gain8_A1                           (-6151)        /* Floating point value -0.187711 */
-#define HPF_Fs32000_Gain8_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain8_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain8_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain8_Shift                             2         /* Shift value */
-                                                                    /* Gain =  9.000000 dB */
-#define HPF_Fs32000_Gain9_A0                            15535         /* Floating point value 0.474078 */
-#define HPF_Fs32000_Gain9_A1                           (-7398)        /* Floating point value -0.225764 */
-#define HPF_Fs32000_Gain9_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain9_B1                                0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain9_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain9_Shift                             2         /* Shift value */
-                                                                    /* Gain =  10.000000 dB */
-#define HPF_Fs32000_Gain10_A0                           16934         /* Floating point value 0.516774 */
-#define HPF_Fs32000_Gain10_A1                          (-8797)        /* Floating point value -0.268461 */
-#define HPF_Fs32000_Gain10_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain10_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain10_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain10_Shift                            2         /* Shift value */
-                                                                    /* Gain =  11.000000 dB */
-#define HPF_Fs32000_Gain11_A0                           18503         /* Floating point value 0.564681 */
-#define HPF_Fs32000_Gain11_A1                         (-10367)        /* Floating point value -0.316368 */
-#define HPF_Fs32000_Gain11_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain11_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain11_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain11_Shift                            2         /* Shift value */
-                                                                    /* Gain =  12.000000 dB */
-#define HPF_Fs32000_Gain12_A0                           20265         /* Floating point value 0.618433 */
-#define HPF_Fs32000_Gain12_A1                         (-12128)        /* Floating point value -0.370120 */
-#define HPF_Fs32000_Gain12_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain12_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain12_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain12_Shift                            2         /* Shift value */
-                                                                    /* Gain =  13.000000 dB */
-#define HPF_Fs32000_Gain13_A0                           11147         /* Floating point value 0.340178 */
-#define HPF_Fs32000_Gain13_A1                          (-7069)        /* Floating point value -0.215726 */
-#define HPF_Fs32000_Gain13_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain13_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain13_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain13_Shift                            3         /* Shift value */
-                                                                    /* Gain =  14.000000 dB */
-#define HPF_Fs32000_Gain14_A0                           12258         /* Floating point value 0.374093 */
-#define HPF_Fs32000_Gain14_A1                          (-8180)        /* Floating point value -0.249642 */
-#define HPF_Fs32000_Gain14_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain14_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain14_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain14_Shift                            3         /* Shift value */
-                                                                    /* Gain =  15.000000 dB */
-#define HPF_Fs32000_Gain15_A0                           13505         /* Floating point value 0.412147 */
-#define HPF_Fs32000_Gain15_A1                          (-9427)        /* Floating point value -0.287695 */
-#define HPF_Fs32000_Gain15_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain15_B1                               0         /* Floating point value -0.000000 */
-#define HPF_Fs32000_Gain15_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs32000_Gain15_Shift                            3         /* Shift value */
-
-
-/* Coefficients for sample rate 44100Hz */
-                                                                    /* Gain =  1.000000 dB */
-#define HPF_Fs44100_Gain1_A0                            17442         /* Floating point value 0.532294 */
-#define HPF_Fs44100_Gain1_A1                           (-4761)        /* Floating point value -0.145294 */
-#define HPF_Fs44100_Gain1_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain1_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain1_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain1_Shift                             1         /* Shift value */
-                                                                    /* Gain =  2.000000 dB */
-#define HPF_Fs44100_Gain2_A0                            18797         /* Floating point value 0.573633 */
-#define HPF_Fs44100_Gain2_A1                           (-6116)        /* Floating point value -0.186634 */
-#define HPF_Fs44100_Gain2_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain2_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain2_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain2_Shift                             1         /* Shift value */
-                                                                    /* Gain =  3.000000 dB */
-#define HPF_Fs44100_Gain3_A0                            20317         /* Floating point value 0.620016 */
-#define HPF_Fs44100_Gain3_A1                           (-7635)        /* Floating point value -0.233017 */
-#define HPF_Fs44100_Gain3_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain3_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain3_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain3_Shift                             1         /* Shift value */
-                                                                    /* Gain =  4.000000 dB */
-#define HPF_Fs44100_Gain4_A0                            22022         /* Floating point value 0.672059 */
-#define HPF_Fs44100_Gain4_A1                           (-9341)        /* Floating point value -0.285060 */
-#define HPF_Fs44100_Gain4_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain4_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain4_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain4_Shift                             1         /* Shift value */
-                                                                    /* Gain =  5.000000 dB */
-#define HPF_Fs44100_Gain5_A0                            23935         /* Floating point value 0.730452 */
-#define HPF_Fs44100_Gain5_A1                          (-11254)        /* Floating point value -0.343453 */
-#define HPF_Fs44100_Gain5_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain5_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain5_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain5_Shift                             1         /* Shift value */
-                                                                    /* Gain =  6.000000 dB */
-#define HPF_Fs44100_Gain6_A0                            26082         /* Floating point value 0.795970 */
-#define HPF_Fs44100_Gain6_A1                          (-13401)        /* Floating point value -0.408971 */
-#define HPF_Fs44100_Gain6_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain6_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain6_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain6_Shift                             1         /* Shift value */
-                                                                    /* Gain =  7.000000 dB */
-#define HPF_Fs44100_Gain7_A0                            14279         /* Floating point value 0.435774 */
-#define HPF_Fs44100_Gain7_A1                           (-7924)        /* Floating point value -0.241815 */
-#define HPF_Fs44100_Gain7_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain7_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain7_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain7_Shift                             2         /* Shift value */
-                                                                    /* Gain =  8.000000 dB */
-#define HPF_Fs44100_Gain8_A0                            15634         /* Floating point value 0.477113 */
-#define HPF_Fs44100_Gain8_A1                           (-9278)        /* Floating point value -0.283154 */
-#define HPF_Fs44100_Gain8_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain8_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain8_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain8_Shift                             2         /* Shift value */
-                                                                    /* Gain =  9.000000 dB */
-#define HPF_Fs44100_Gain9_A0                            17154         /* Floating point value 0.523496 */
-#define HPF_Fs44100_Gain9_A1                          (-10798)        /* Floating point value -0.329537 */
-#define HPF_Fs44100_Gain9_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain9_B1                           (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain9_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain9_Shift                             2         /* Shift value */
-                                                                    /* Gain =  10.000000 dB */
-#define HPF_Fs44100_Gain10_A0                           18859         /* Floating point value 0.575539 */
-#define HPF_Fs44100_Gain10_A1                         (-12504)        /* Floating point value -0.381580 */
-#define HPF_Fs44100_Gain10_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain10_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain10_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain10_Shift                            2         /* Shift value */
-                                                                    /* Gain =  11.000000 dB */
-#define HPF_Fs44100_Gain11_A0                           20773         /* Floating point value 0.633932 */
-#define HPF_Fs44100_Gain11_A1                         (-14417)        /* Floating point value -0.439973 */
-#define HPF_Fs44100_Gain11_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain11_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain11_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain11_Shift                            2         /* Shift value */
-                                                                    /* Gain =  12.000000 dB */
-#define HPF_Fs44100_Gain12_A0                           22920         /* Floating point value 0.699450 */
-#define HPF_Fs44100_Gain12_A1                         (-16564)        /* Floating point value -0.505491 */
-#define HPF_Fs44100_Gain12_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain12_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain12_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain12_Shift                            2         /* Shift value */
-                                                                    /* Gain =  13.000000 dB */
-#define HPF_Fs44100_Gain13_A0                           12694         /* Floating point value 0.387399 */
-#define HPF_Fs44100_Gain13_A1                          (-9509)        /* Floating point value -0.290189 */
-#define HPF_Fs44100_Gain13_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain13_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain13_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain13_Shift                            3         /* Shift value */
-                                                                    /* Gain =  14.000000 dB */
-#define HPF_Fs44100_Gain14_A0                           14049         /* Floating point value 0.428738 */
-#define HPF_Fs44100_Gain14_A1                         (-10864)        /* Floating point value -0.331528 */
-#define HPF_Fs44100_Gain14_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain14_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain14_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain14_Shift                            3         /* Shift value */
-                                                                    /* Gain =  15.000000 dB */
-#define HPF_Fs44100_Gain15_A0                           15569         /* Floating point value 0.475121 */
-#define HPF_Fs44100_Gain15_A1                         (-12383)        /* Floating point value -0.377912 */
-#define HPF_Fs44100_Gain15_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain15_B1                          (-7173)        /* Floating point value -0.218894 */
-#define HPF_Fs44100_Gain15_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs44100_Gain15_Shift                            3         /* Shift value */
-
-
-/* Coefficients for sample rate 48000Hz */
-                                                                    /* Gain =  1.000000 dB */
-#define HPF_Fs48000_Gain1_A0                            17491         /* Floating point value 0.533777 */
-#define HPF_Fs48000_Gain1_A1                           (-5606)        /* Floating point value -0.171082 */
-#define HPF_Fs48000_Gain1_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain1_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain1_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain1_Shift                             1         /* Shift value */
-                                                                    /* Gain =  2.000000 dB */
-#define HPF_Fs48000_Gain2_A0                            18900         /* Floating point value 0.576779 */
-#define HPF_Fs48000_Gain2_A1                           (-7015)        /* Floating point value -0.214085 */
-#define HPF_Fs48000_Gain2_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain2_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain2_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain2_Shift                             1         /* Shift value */
-                                                                    /* Gain =  3.000000 dB */
-#define HPF_Fs48000_Gain3_A0                            20481         /* Floating point value 0.625029 */
-#define HPF_Fs48000_Gain3_A1                           (-8596)        /* Floating point value -0.262335 */
-#define HPF_Fs48000_Gain3_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain3_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain3_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain3_Shift                             1         /* Shift value */
-                                                                    /* Gain =  4.000000 dB */
-#define HPF_Fs48000_Gain4_A0                            22255         /* Floating point value 0.679167 */
-#define HPF_Fs48000_Gain4_A1                          (-10370)        /* Floating point value -0.316472 */
-#define HPF_Fs48000_Gain4_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain4_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain4_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain4_Shift                             1         /* Shift value */
-                                                                    /* Gain =  5.000000 dB */
-#define HPF_Fs48000_Gain5_A0                            24245         /* Floating point value 0.739910 */
-#define HPF_Fs48000_Gain5_A1                          (-12361)        /* Floating point value -0.377215 */
-#define HPF_Fs48000_Gain5_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain5_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain5_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain5_Shift                             1         /* Shift value */
-                                                                    /* Gain =  6.000000 dB */
-#define HPF_Fs48000_Gain6_A0                            26479         /* Floating point value 0.808065 */
-#define HPF_Fs48000_Gain6_A1                          (-14594)        /* Floating point value -0.445370 */
-#define HPF_Fs48000_Gain6_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain6_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain6_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain6_Shift                             1         /* Shift value */
-                                                                    /* Gain =  7.000000 dB */
-#define HPF_Fs48000_Gain7_A0                            14527         /* Floating point value 0.443318 */
-#define HPF_Fs48000_Gain7_A1                           (-8570)        /* Floating point value -0.261540 */
-#define HPF_Fs48000_Gain7_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain7_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain7_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain7_Shift                             2         /* Shift value */
-                                                                    /* Gain =  8.000000 dB */
-#define HPF_Fs48000_Gain8_A0                            15936         /* Floating point value 0.486321 */
-#define HPF_Fs48000_Gain8_A1                           (-9979)        /* Floating point value -0.304543 */
-#define HPF_Fs48000_Gain8_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain8_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain8_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain8_Shift                             2         /* Shift value */
-                                                                    /* Gain =  9.000000 dB */
-#define HPF_Fs48000_Gain9_A0                            17517         /* Floating point value 0.534571 */
-#define HPF_Fs48000_Gain9_A1                          (-11560)        /* Floating point value -0.352793 */
-#define HPF_Fs48000_Gain9_A2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain9_B1                           (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain9_B2                                0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain9_Shift                             2         /* Shift value */
-                                                                    /* Gain =  10.000000 dB */
-#define HPF_Fs48000_Gain10_A0                           19291         /* Floating point value 0.588708 */
-#define HPF_Fs48000_Gain10_A1                         (-13334)        /* Floating point value -0.406930 */
-#define HPF_Fs48000_Gain10_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain10_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain10_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain10_Shift                            2         /* Shift value */
-                                                                    /* Gain =  11.000000 dB */
-#define HPF_Fs48000_Gain11_A0                           21281         /* Floating point value 0.649452 */
-#define HPF_Fs48000_Gain11_A1                         (-15325)        /* Floating point value -0.467674 */
-#define HPF_Fs48000_Gain11_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain11_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain11_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain11_Shift                            2         /* Shift value */
-                                                                    /* Gain =  12.000000 dB */
-#define HPF_Fs48000_Gain12_A0                           23515         /* Floating point value 0.717607 */
-#define HPF_Fs48000_Gain12_A1                         (-17558)        /* Floating point value -0.535829 */
-#define HPF_Fs48000_Gain12_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain12_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain12_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain12_Shift                            2         /* Shift value */
-                                                                    /* Gain =  13.000000 dB */
-#define HPF_Fs48000_Gain13_A0                           13041         /* Floating point value 0.397982 */
-#define HPF_Fs48000_Gain13_A1                         (-10056)        /* Floating point value -0.306877 */
-#define HPF_Fs48000_Gain13_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain13_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain13_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain13_Shift                            3         /* Shift value */
-                                                                    /* Gain =  14.000000 dB */
-#define HPF_Fs48000_Gain14_A0                           14450         /* Floating point value 0.440984 */
-#define HPF_Fs48000_Gain14_A1                         (-11465)        /* Floating point value -0.349880 */
-#define HPF_Fs48000_Gain14_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain14_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain14_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain14_Shift                            3         /* Shift value */
-                                                                    /* Gain =  15.000000 dB */
-#define HPF_Fs48000_Gain15_A0                           16031         /* Floating point value 0.489234 */
-#define HPF_Fs48000_Gain15_A1                         (-13046)        /* Floating point value -0.398130 */
-#define HPF_Fs48000_Gain15_A2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain15_B1                          (-8780)        /* Floating point value -0.267949 */
-#define HPF_Fs48000_Gain15_B2                               0         /* Floating point value 0.000000 */
-#define HPF_Fs48000_Gain15_Shift                            3         /* Shift value */
-
-
-#endif
-#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
deleted file mode 100644
index 1b27cb4..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* Includes                                                                             */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "ScalarArithmetic.h"
-#include "LVM_Coeffs.h"
-#include "LVM_Tables.h"
-#include "LVM_Private.h"
-
-#include <log/log.h>
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:           LVM_SetControlParameters                                         */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Sets or changes the LifeVibes module parameters.                                    */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance          Instance handle                                                  */
-/*  pParams            Pointer to a parameter structure                                 */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS        Succeeded                                                        */
-/*  LVM_NULLADDRESS    When hInstance, pParams or any control pointers are NULL         */
-/*  LVM_OUTOFRANGE     When any of the control parameters are out of range              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function may be interrupted by the LVM_Process function                     */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t           hInstance,
-                                             LVM_ControlParams_t    *pParams)
-{
-    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
-
-
-    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    pInstance->NewParams = *pParams;
-
-    if(
-        /* General parameters */
-        ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON))                                         ||
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-    ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
-     (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)      &&
-     (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)      &&
-     (pParams->SampleRate != LVM_FS_88200) && (pParams->SampleRate != LVM_FS_96000) &&
-     (pParams->SampleRate != LVM_FS_176400) && (pParams->SampleRate != LVM_FS_192000))      ||
-#else
-        ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
-        (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)       &&
-        (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000))      ||
-#endif
-#ifdef SUPPORT_MC
-        ((pParams->SourceFormat != LVM_STEREO) &&
-         (pParams->SourceFormat != LVM_MONOINSTEREO) &&
-         (pParams->SourceFormat != LVM_MONO) &&
-         (pParams->SourceFormat != LVM_MULTICHANNEL)) ||
-#else
-        ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
-#endif
-        (pParams->SpeakerType > LVM_EX_HEADPHONES))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-#ifdef SUPPORT_MC
-    pInstance->Params.NrChannels = pParams->NrChannels;
-    pInstance->Params.ChMask     = pParams->ChMask;
-#endif
-    /*
-     * Cinema Sound parameters
-     */
-    if((pParams->VirtualizerOperatingMode != LVM_MODE_OFF) && (pParams->VirtualizerOperatingMode != LVM_MODE_ON))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if(pParams->VirtualizerType != LVM_CONCERTSOUND)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if(pParams->VirtualizerReverbLevel > LVM_VIRTUALIZER_MAX_REVERB_LEVEL)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if(pParams->CS_EffectLevel < LVM_CS_MIN_EFFECT_LEVEL)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /*
-     * N-Band Equalizer
-     */
-    if(pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /* Definition pointer */
-    if ((pParams->pEQNB_BandDefinition == LVM_NULL) &&
-        (pParams->EQNB_NBands != 0))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    /*
-     * Copy the filter definitions for the Equaliser
-     */
-    {
-        LVM_INT16           i;
-
-        if (pParams->EQNB_NBands != 0)
-        {
-            for (i=0; i<pParams->EQNB_NBands; i++)
-            {
-                pInstance->pEQNB_BandDefs[i] = pParams->pEQNB_BandDefinition[i];
-            }
-            pInstance->NewParams.pEQNB_BandDefinition = pInstance->pEQNB_BandDefs;
-        }
-    }
-    if( /* N-Band Equaliser parameters */
-        ((pParams->EQNB_OperatingMode != LVM_EQNB_OFF) && (pParams->EQNB_OperatingMode != LVM_EQNB_ON)) ||
-        (pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-    /* Band parameters*/
-    {
-        LVM_INT16 i;
-        for(i = 0; i < pParams->EQNB_NBands; i++)
-        {
-            if(((pParams->pEQNB_BandDefinition[i].Frequency < LVM_EQNB_MIN_BAND_FREQ)  ||
-                (pParams->pEQNB_BandDefinition[i].Frequency > LVM_EQNB_MAX_BAND_FREQ)) ||
-                ((pParams->pEQNB_BandDefinition[i].Gain     < LVM_EQNB_MIN_BAND_GAIN)  ||
-                (pParams->pEQNB_BandDefinition[i].Gain      > LVM_EQNB_MAX_BAND_GAIN)) ||
-                ((pParams->pEQNB_BandDefinition[i].QFactor  < LVM_EQNB_MIN_QFACTOR)     ||
-                (pParams->pEQNB_BandDefinition[i].QFactor   > LVM_EQNB_MAX_QFACTOR)))
-            {
-                return (LVM_OUTOFRANGE);
-            }
-        }
-    }
-
-    /*
-     * Bass Enhancement parameters
-     */
-    if(((pParams->BE_OperatingMode != LVM_BE_OFF) && (pParams->BE_OperatingMode != LVM_BE_ON))                      ||
-        ((pParams->BE_EffectLevel < LVM_BE_MIN_EFFECTLEVEL ) || (pParams->BE_EffectLevel > LVM_BE_MAX_EFFECTLEVEL ))||
-        ((pParams->BE_CentreFreq != LVM_BE_CENTRE_55Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_66Hz)           &&
-        (pParams->BE_CentreFreq != LVM_BE_CENTRE_78Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_90Hz))           ||
-        ((pParams->BE_HPF != LVM_BE_HPF_OFF) && (pParams->BE_HPF != LVM_BE_HPF_ON)))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /*
-     * Volume Control parameters
-     */
-    if((pParams->VC_EffectLevel < LVM_VC_MIN_EFFECTLEVEL ) || (pParams->VC_EffectLevel > LVM_VC_MAX_EFFECTLEVEL ))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-    if((pParams->VC_Balance < LVM_VC_BALANCE_MIN ) || (pParams->VC_Balance > LVM_VC_BALANCE_MAX ))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /*
-     * PSA parameters
-     */
-    if( (pParams->PSA_PeakDecayRate > LVPSA_SPEED_HIGH) ||
-        (pParams->PSA_Enable > LVM_PSA_ON))
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-
-    /*
-    * Set the flag to indicate there are new parameters to use
-    *
-    * Protect the copy of the new parameters from interrupts to avoid possible problems
-    * with loss control parameters. This problem can occur if this control function is called more
-    * than once before a call to the process function. If the process function interrupts
-    * the copy to NewParams then one frame may have mixed parameters, some old and some new.
-    */
-    pInstance->ControlPending = LVM_TRUE;
-
-    return(LVM_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:             LVM_GetControlParameters                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Request the LifeVibes module parameters. The current parameter set is returned      */
-/*  via the parameter pointer.                                                          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance            Instance handle                                                */
-/*  pParams              Pointer to an empty parameter structure                        */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS          Succeeded                                                      */
-/*  LVM_NULLADDRESS      when any of hInstance or pParams is NULL                       */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function may be interrupted by the LVM_Process function                     */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t           hInstance,
-                                             LVM_ControlParams_t    *pParams)
-{
-    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
-
-
-    /*
-     * Check pointer
-     */
-    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-    *pParams = pInstance->NewParams;
-
-    /*
-     * Copy the filter definitions for the Equaliser
-     */
-    {
-        LVM_INT16           i;
-
-        if (pInstance->NewParams.EQNB_NBands != 0)
-        for (i=0; i<pInstance->NewParams.EQNB_NBands; i++)
-        {
-            pInstance->pEQNB_UserDefs[i] = pInstance->pEQNB_BandDefs[i];
-        }
-        pParams->pEQNB_BandDefinition = pInstance->pEQNB_UserDefs;
-    }
-
-    return(LVM_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_SetTrebleBoost                                          */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Enable the treble boost when the settings are appropriate, i.e. non-zero gain       */
-/*  and the sample rate is high enough for the effect to be heard.                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pInstance               Pointer to the instance structure                           */
-/*  pParams                 Pointer to the parameters to use                            */
-/*                                                                                      */
-/****************************************************************************************/
-void LVM_SetTrebleBoost(LVM_Instance_t         *pInstance,
-                        LVM_ControlParams_t    *pParams)
-{
-#ifdef BUILD_FLOAT
-    extern FO_FLOAT_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
-#else
-    extern FO_C16_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
-#endif
-
-    LVM_INT16               Offset;
-    LVM_INT16               EffectLevel = 0;
-
-    /*
-     * Load the coefficients
-     */
-    if ((pParams->TE_OperatingMode == LVM_TE_ON) &&
-        (pParams->SampleRate >= TrebleBoostMinRate) &&
-        (pParams->OperatingMode == LVM_MODE_ON) &&
-        (pParams->TE_EffectLevel > 0))
-    {
-        if((pParams->TE_EffectLevel == LVM_TE_LOW_MIPS) &&
-            ((pParams->SpeakerType == LVM_HEADPHONES)||
-            (pParams->SpeakerType == LVM_EX_HEADPHONES)))
-        {
-            pInstance->TE_Active = LVM_FALSE;
-        }
-        else
-        {
-            EffectLevel = pParams->TE_EffectLevel;
-            pInstance->TE_Active = LVM_TRUE;
-        }
-
-        if(pInstance->TE_Active == LVM_TRUE)
-        {
-            /*
-             * Load the coefficients and enabled the treble boost
-             */
-            Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
-#ifdef BUILD_FLOAT
-            FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
-                                            &pInstance->pTE_Taps->TrebleBoost_Taps,
-                                            &LVM_TrebleBoostCoefs[Offset]);
-
-            /*
-             * Clear the taps
-             */
-            LoadConst_Float((LVM_FLOAT)0,                                     /* Value */
-                            (void *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
-                                                     Cast to void: no dereferencing in function */
-                            (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) / \
-                                                        sizeof(LVM_FLOAT))); /* Number of words */
-#else
-            FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
-                                            &pInstance->pTE_Taps->TrebleBoost_Taps,
-                                            &LVM_TrebleBoostCoefs[Offset]);
-
-            /*
-             * Clear the taps
-             */
-            LoadConst_16((LVM_INT16)0,                                     /* Value */
-                         (void *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
-                                                     Cast to void: no dereferencing in function */
-                         (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps)/sizeof(LVM_INT16))); /* Number of words */
-#endif
-        }
-    }
-    else
-    {
-        /*
-         * Disable the treble boost
-         */
-        pInstance->TE_Active = LVM_FALSE;
-    }
-
-    return;
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVM_SetVolume                                               */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Converts the input volume demand from dBs to linear.                            */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/************************************************************************************/
-void    LVM_SetVolume(LVM_Instance_t         *pInstance,
-                      LVM_ControlParams_t    *pParams)
-{
-
-    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
-    LVM_UINT16      dBOffset;                                   /* Table offset */
-    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
-#ifdef BUILD_FLOAT
-    LVM_FLOAT        Temp;
-#endif
-
-    /*
-     * Limit the gain to the maximum allowed
-     */
-     if  (pParams->VC_EffectLevel > 0)
-     {
-         Volume = 0;
-     }
-     else
-     {
-         Volume = pParams->VC_EffectLevel;
-     }
-
-     /* Compensate this volume in PSA plot */
-     if(Volume > -60)  /* Limit volume loss to PSA Limits*/
-         pInstance->PSA_GainOffset=(LVM_INT16)(-Volume);/* Loss is compensated by Gain*/
-     else
-         pInstance->PSA_GainOffset=(LVM_INT16)60;/* Loss is compensated by Gain*/
-
-    pInstance->VC_AVLFixedVolume = 0;
-
-    /*
-     * Set volume control and AVL volumes according to headroom and volume user setting
-     */
-    if(pParams->OperatingMode == LVM_MODE_ON)
-    {
-        /* Default Situation with no AVL and no RS */
-        if(pParams->EQNB_OperatingMode == LVM_EQNB_ON)
-        {
-            if(Volume > -pInstance->Headroom)
-                Volume = (LVM_INT16)-pInstance->Headroom;
-        }
-    }
-
-    /*
-     * Activate volume control if necessary
-     */
-    pInstance->VC_Active   = LVM_TRUE;
-    if (Volume != 0)
-    {
-        pInstance->VC_VolumedB = Volume;
-    }
-    else
-    {
-        pInstance->VC_VolumedB = 0;
-    }
-
-    /*
-     * Calculate the required gain and shifts
-     */
-    dBOffset = (LVM_UINT16)((-Volume) % 6);             /* Get the dBs 0-5 */
-    dBShifts = (LVM_UINT16)(Volume / -6);               /* Get the 6dB shifts */
-
-
-    /*
-     * Set the parameters
-     */
-    if(dBShifts == 0)
-    {
-#ifdef BUILD_FLOAT
-        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
-                                (LVM_FLOAT)LVM_VolumeTable[dBOffset]);
-#else
-        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
-                                (LVM_INT32)LVM_VolumeTable[dBOffset]);
-#endif
-        }
-    else
-    {
-#ifdef BUILD_FLOAT
-        Temp = LVM_VolumeTable[dBOffset];
-        while(dBShifts) {
-            Temp = Temp / 2.0f;
-            dBShifts--;
-        }
-        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0], Temp);
-#else
-        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
-                                (((LVM_INT32)LVM_VolumeTable[dBOffset])>>dBShifts));
-#endif
-    }
-    pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
-    if(pInstance->NoSmoothVolume == LVM_TRUE)
-    {
-#ifdef BUILD_FLOAT
-        LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0,
-                                  pInstance->Params.SampleRate, 2);
-#else
-        LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,pInstance->Params.SampleRate,2);
-#endif
-    }
-    else
-    {
-#ifdef BUILD_FLOAT
-        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],
-                                           LVM_VC_MIXER_TIME, pInstance->Params.SampleRate, 2);
-#else
-        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],LVM_VC_MIXER_TIME,pInstance->Params.SampleRate,2);
-#endif
-    }
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVM_SetHeadroom                                             */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Find suitable headroom based on EQ settings.                                    */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  void                Nothing                                                     */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-void    LVM_SetHeadroom(LVM_Instance_t         *pInstance,
-                        LVM_ControlParams_t    *pParams)
-{
-    LVM_INT16   ii, jj;
-    LVM_INT16   Headroom = 0;
-    LVM_INT16   MaxGain = 0;
-
-
-    if ((pParams->EQNB_OperatingMode == LVEQNB_ON) && (pInstance->HeadroomParams.Headroom_OperatingMode == LVM_HEADROOM_ON))
-    {
-        /* Find typical headroom value */
-        for(jj = 0; jj < pInstance->HeadroomParams.NHeadroomBands; jj++)
-        {
-            MaxGain = 0;
-            for( ii = 0; ii < pParams->EQNB_NBands; ii++)
-            {
-                if((pParams->pEQNB_BandDefinition[ii].Frequency >= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_Low) &&
-                   (pParams->pEQNB_BandDefinition[ii].Frequency <= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_High))
-                {
-                    if(pParams->pEQNB_BandDefinition[ii].Gain > MaxGain)
-                    {
-                        MaxGain = pParams->pEQNB_BandDefinition[ii].Gain;
-                    }
-                }
-            }
-
-            if((MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset) > Headroom){
-                Headroom = (LVM_INT16)(MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset);
-            }
-        }
-
-        /* Saturate */
-        if(Headroom < 0)
-            Headroom = 0;
-    }
-    pInstance->Headroom = (LVM_UINT16)Headroom ;
-
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_ApplyNewSettings                                        */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Applies changes to parametres. This function makes no assumptions about what        */
-/*  each module needs for initialisation and hence passes all parameters to all the     */
-/*  the modules in turn.                                                                */
-/*                                                                                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_Success             Succeeded                                                   */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t   hInstance)
-{
-    LVM_Instance_t         *pInstance =(LVM_Instance_t *)hInstance;
-    LVM_ControlParams_t    LocalParams;
-    LVM_INT16              Count = 5;
-
-
-    /*
-     * Copy the new parameters but make sure they didn't change while copying
-     */
-    do
-    {
-        pInstance->ControlPending = LVM_FALSE;
-        LocalParams = pInstance->NewParams;
-        pInstance->HeadroomParams = pInstance->NewHeadroomParams;
-        Count--;
-    } while ((pInstance->ControlPending != LVM_FALSE) &&
-             (Count > 0));
-
-#ifdef SUPPORT_MC
-    pInstance->NrChannels = LocalParams.NrChannels;
-    pInstance->ChMask = LocalParams.ChMask;
-#endif
-
-    /* Clear all internal data if format change*/
-    if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
-    {
-        LVM_ClearAudioBuffers(pInstance);
-        pInstance->ControlPending = LVM_FALSE;
-    }
-
-    /*
-     * Update the treble boost if required
-     */
-    if ((pInstance->Params.SampleRate != LocalParams.SampleRate) ||
-        (pInstance->Params.TE_EffectLevel != LocalParams.TE_EffectLevel) ||
-        (pInstance->Params.TE_OperatingMode != LocalParams.TE_OperatingMode) ||
-        (pInstance->Params.OperatingMode != LocalParams.OperatingMode) ||
-        (pInstance->Params.SpeakerType != LocalParams.SpeakerType))
-    {
-        LVM_SetTrebleBoost(pInstance,
-                           &LocalParams);
-    }
-
-    /*
-     * Update the headroom if required
-     */
-        LVM_SetHeadroom(pInstance,                      /* Instance pointer */
-                        &LocalParams);                  /* New parameters */
-
-    /*
-     * Update the volume if required
-     */
-    {
-        LVM_SetVolume(pInstance,                      /* Instance pointer */
-                      &LocalParams);                  /* New parameters */
-    }
-    /* Apply balance changes*/
-    if(pInstance->Params.VC_Balance != LocalParams.VC_Balance)
-    {
-        /* Configure Mixer module for gradual changes to volume*/
-        if(LocalParams.VC_Balance < 0)
-        {
-#ifdef BUILD_FLOAT
-            LVM_FLOAT Target_Float;
-#else
-            LVM_INT32 Target;
-#endif
-            /* Drop in right channel volume*/
-#ifdef BUILD_FLOAT
-            Target_Float = LVM_MAXFLOAT;
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
-                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
-
-            Target_Float = dB_to_LinFloat((LVM_INT16)(LocalParams.VC_Balance << 4));
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
-                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
-#else
-            Target = LVM_MAXINT_16;
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-
-            Target = dB_to_Lin32((LVM_INT16)(LocalParams.VC_Balance<<4));
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-#endif
-        }
-        else if(LocalParams.VC_Balance >0)
-        {
-#ifdef BUILD_FLOAT
-            LVM_FLOAT Target_Float;
-#else
-            LVM_INT32 Target;
-#endif
-            /* Drop in left channel volume*/
-#ifdef BUILD_FLOAT
-            Target_Float = dB_to_LinFloat((LVM_INT16)((-LocalParams.VC_Balance) << 4));
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
-                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
-
-            Target_Float = LVM_MAXFLOAT;
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
-                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
-#else
-            Target = dB_to_Lin32((LVM_INT16)((-LocalParams.VC_Balance)<<4));
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-
-            Target = LVM_MAXINT_16;
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-#endif
-        }
-        else
-        {
-#ifdef BUILD_FLOAT
-            LVM_FLOAT Target_Float;
-#else
-            LVM_INT32 Target;
-#endif
-            /* No drop*/
-#ifdef BUILD_FLOAT
-            Target_Float = LVM_MAXFLOAT;
-#else
-            Target = LVM_MAXINT_16;
-#endif
-#ifdef BUILD_FLOAT
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
-                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
-
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target_Float);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
-                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
-#else
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-
-            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
-#endif
-        }
-    }
-    /*
-     * Update the bass enhancement
-     */
-    {
-        LVDBE_ReturnStatus_en       DBE_Status;
-        LVDBE_Params_t              DBE_Params;
-        LVDBE_Handle_t              *hDBEInstance = pInstance->hDBEInstance;
-
-
-        /*
-         * Set the new parameters
-         */
-        if(LocalParams.OperatingMode == LVM_MODE_OFF)
-        {
-            DBE_Params.OperatingMode = LVDBE_OFF;
-        }
-        else
-        {
-            DBE_Params.OperatingMode    = (LVDBE_Mode_en)LocalParams.BE_OperatingMode;
-        }
-        DBE_Params.SampleRate       = (LVDBE_Fs_en)LocalParams.SampleRate;
-        DBE_Params.EffectLevel      = LocalParams.BE_EffectLevel;
-        DBE_Params.CentreFrequency  = (LVDBE_CentreFreq_en)LocalParams.BE_CentreFreq;
-        DBE_Params.HPFSelect        = (LVDBE_FilterSelect_en)LocalParams.BE_HPF;
-        DBE_Params.HeadroomdB       = 0;
-        DBE_Params.VolumeControl    = LVDBE_VOLUME_OFF;
-        DBE_Params.VolumedB         = 0;
-#ifdef SUPPORT_MC
-        DBE_Params.NrChannels         = LocalParams.NrChannels;
-#endif
-
-        /*
-         * Make the changes
-         */
-        DBE_Status = LVDBE_Control(hDBEInstance,
-                                   &DBE_Params);
-
-
-        /*
-         * Quit if the changes were not accepted
-         */
-        if (DBE_Status != LVDBE_SUCCESS)
-        {
-            return((LVM_ReturnStatus_en)DBE_Status);
-        }
-
-
-        /*
-         * Set the control flag
-         */
-        pInstance->DBE_Active = LVM_TRUE;
-    }
-
-    /*
-     * Update the N-Band Equaliser
-     */
-    {
-        LVEQNB_ReturnStatus_en      EQNB_Status;
-        LVEQNB_Params_t             EQNB_Params;
-        LVEQNB_Handle_t             *hEQNBInstance = pInstance->hEQNBInstance;
-
-
-        /*
-         * Set the new parameters
-         */
-
-        if(LocalParams.OperatingMode == LVM_MODE_OFF)
-        {
-            EQNB_Params.OperatingMode    = LVEQNB_BYPASS;
-        }
-        else
-        {
-            EQNB_Params.OperatingMode    = (LVEQNB_Mode_en)LocalParams.EQNB_OperatingMode;
-        }
-
-        EQNB_Params.SampleRate       = (LVEQNB_Fs_en)LocalParams.SampleRate;
-        EQNB_Params.NBands           = LocalParams.EQNB_NBands;
-        EQNB_Params.pBandDefinition  = (LVEQNB_BandDef_t *)LocalParams.pEQNB_BandDefinition;
-        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
-        {
-            EQNB_Params.SourceFormat = LVEQNB_STEREO;
-        }
-#ifdef SUPPORT_MC
-        /* Note: Currently SourceFormat field of EQNB is not been
-         *       used by the module.
-         */
-        else if (LocalParams.SourceFormat == LVM_MULTICHANNEL)
-        {
-            EQNB_Params.SourceFormat = LVEQNB_MULTICHANNEL;
-        }
-#endif
-        else
-        {
-            EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO;     /* Force to Mono-in-Stereo mode */
-        }
-#ifdef SUPPORT_MC
-        EQNB_Params.NrChannels         = LocalParams.NrChannels;
-#endif
-
-        /*
-         * Set the control flag
-         */
-        if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
-            (LocalParams.EQNB_OperatingMode == LVM_EQNB_ON))
-        {
-            pInstance->EQNB_Active = LVM_TRUE;
-        }
-        else
-        {
-            EQNB_Params.OperatingMode = LVEQNB_BYPASS;
-        }
-
-        /*
-         * Make the changes
-         */
-        EQNB_Status = LVEQNB_Control(hEQNBInstance,
-                                     &EQNB_Params);
-
-
-        /*
-         * Quit if the changes were not accepted
-         */
-        if (EQNB_Status != LVEQNB_SUCCESS)
-        {
-            return((LVM_ReturnStatus_en)EQNB_Status);
-        }
-
-    }
-
-
-    /*
-     * Update concert sound
-     */
-    {
-        LVCS_ReturnStatus_en        CS_Status;
-        LVCS_Params_t               CS_Params;
-        LVCS_Handle_t               *hCSInstance = pInstance->hCSInstance;
-        LVM_Mode_en                 CompressorMode=LVM_MODE_ON;
-
-        /*
-         * Set the new parameters
-         */
-        if(LocalParams.VirtualizerOperatingMode == LVM_MODE_ON)
-        {
-            CS_Params.OperatingMode    = LVCS_ON;
-        }
-        else
-        {
-            CS_Params.OperatingMode    = LVCS_OFF;
-        }
-
-        if((LocalParams.TE_OperatingMode == LVM_TE_ON) && (LocalParams.TE_EffectLevel == LVM_TE_LOW_MIPS))
-        {
-            CS_Params.SpeakerType  = LVCS_EX_HEADPHONES;
-        }
-        else
-        {
-            CS_Params.SpeakerType  = LVCS_HEADPHONES;
-        }
-
-#ifdef SUPPORT_MC
-        /* Concert sound module processes only the left and right channels
-         * data. So the Source Format is set to LVCS_STEREO for multichannel
-         * input also.
-         */
-        if (LocalParams.SourceFormat == LVM_STEREO ||
-            LocalParams.SourceFormat == LVM_MULTICHANNEL)
-#else
-        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
-#endif
-        {
-            CS_Params.SourceFormat = LVCS_STEREO;
-        }
-        else
-        {
-            CS_Params.SourceFormat = LVCS_MONOINSTEREO;          /* Force to Mono-in-Stereo mode */
-        }
-        CS_Params.SampleRate  = LocalParams.SampleRate;
-        CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
-        CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
-#ifdef SUPPORT_MC
-        CS_Params.NrChannels  = LocalParams.NrChannels;
-#endif
-
-        /*
-         * Set the control flag
-         */
-        if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
-            (LocalParams.VirtualizerOperatingMode != LVCS_OFF))
-        {
-            pInstance->CS_Active = LVM_TRUE;
-        }
-        else
-        {
-            CS_Params.OperatingMode = LVCS_OFF;
-        }
-
-        CS_Params.CompressorMode=CompressorMode;
-
-        /*
-         * Make the changes
-         */
-        CS_Status = LVCS_Control(hCSInstance,
-                                 &CS_Params);
-
-
-        /*
-         * Quit if the changes were not accepted
-         */
-        if (CS_Status != LVCS_SUCCESS)
-        {
-            return((LVM_ReturnStatus_en)CS_Status);
-        }
-
-    }
-
-    /*
-     * Update the Power Spectrum Analyser
-     */
-    {
-        LVPSA_RETURN                PSA_Status;
-        LVPSA_ControlParams_t       PSA_Params;
-        pLVPSA_Handle_t             *hPSAInstance = pInstance->hPSAInstance;
-
-
-        /*
-         * Set the new parameters
-         */
-        PSA_Params.Fs = LocalParams.SampleRate;
-        PSA_Params.LevelDetectionSpeed = (LVPSA_LevelDetectSpeed_en)LocalParams.PSA_PeakDecayRate;
-
-        /*
-         * Make the changes
-         */
-        if(pInstance->InstParams.PSA_Included==LVM_PSA_ON)
-        {
-            PSA_Status = LVPSA_Control(hPSAInstance,
-                &PSA_Params);
-
-            if (PSA_Status != LVPSA_OK)
-            {
-                return((LVM_ReturnStatus_en)PSA_Status);
-            }
-
-            /*
-             * Apply new settings
-             */
-            PSA_Status = LVPSA_ApplyNewSettings ((LVPSA_InstancePr_t*)hPSAInstance);
-            if(PSA_Status != LVPSA_OK)
-            {
-                return((LVM_ReturnStatus_en)PSA_Status);
-            }
-        }
-    }
-
-    /*
-     * Update the parameters and clear the flag
-     */
-    pInstance->NoSmoothVolume = LVM_FALSE;
-    pInstance->Params =  LocalParams;
-
-
-    return(LVM_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_SetHeadroomParams                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to set the automatiuc headroom management parameters.         */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pHeadroomParams         Pointer to headroom parameter structure                     */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_Success             Succeeded                                                   */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVM_Process function                    */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_SetHeadroomParams(LVM_Handle_t              hInstance,
-                                          LVM_HeadroomParams_t      *pHeadroomParams)
-{
-    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
-    LVM_UINT16          ii, NBands;
-
-    /* Check for NULL pointers */
-    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-    if ((pHeadroomParams->NHeadroomBands != 0) && (pHeadroomParams->pHeadroomDefinition == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    /* Consider only the LVM_HEADROOM_MAX_NBANDS first bands*/
-    if (pHeadroomParams->NHeadroomBands > LVM_HEADROOM_MAX_NBANDS)
-    {
-        NBands = LVM_HEADROOM_MAX_NBANDS;
-    }
-    else
-    {
-        NBands = pHeadroomParams->NHeadroomBands;
-    }
-    pInstance->NewHeadroomParams.NHeadroomBands = NBands;
-
-    /* Copy settings in memory */
-    for(ii = 0; ii < NBands; ii++)
-    {
-        pInstance->pHeadroom_BandDefs[ii] = pHeadroomParams->pHeadroomDefinition[ii];
-    }
-
-    pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
-    pInstance->NewHeadroomParams.Headroom_OperatingMode = pHeadroomParams->Headroom_OperatingMode;
-    pInstance->ControlPending = LVM_TRUE;
-
-    return(LVM_SUCCESS);
-}
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_GetHeadroomParams                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to get the automatic headroom management parameters.          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pHeadroomParams         Pointer to headroom parameter structure (output)            */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Succeeded                                                   */
-/*  LVM_NULLADDRESS         When hInstance or pHeadroomParams are NULL                  */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVM_Process function                    */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_GetHeadroomParams(LVM_Handle_t          hInstance,
-                                          LVM_HeadroomParams_t  *pHeadroomParams)
-{
-    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
-    LVM_UINT16          ii;
-
-    /* Check for NULL pointers */
-    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    pHeadroomParams->NHeadroomBands = pInstance->NewHeadroomParams.NHeadroomBands;
-
-
-    /* Copy settings in memory */
-    for(ii = 0; ii < pInstance->NewHeadroomParams.NHeadroomBands; ii++)
-    {
-        pInstance->pHeadroom_UserDefs[ii] = pInstance->pHeadroom_BandDefs[ii];
-    }
-
-
-    pHeadroomParams->pHeadroomDefinition = pInstance->pHeadroom_UserDefs;
-    pHeadroomParams->Headroom_OperatingMode = pInstance->NewHeadroomParams.Headroom_OperatingMode;
-    return(LVM_SUCCESS);
-}
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_AlgoCallBack                                            */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This is the callback function of the algorithm.                                     */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pBundleHandle           Pointer to the Instance Handle                              */
-/*  pData                   Pointer to the data                                         */
-/*  callbackId              ID of the callback                                          */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVM_Process function                    */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_INT32 LVM_AlgoCallBack( void          *pBundleHandle,
-                            void          *pData,
-                            LVM_INT16     callbackId)
-{
-    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)pBundleHandle;
-
-    (void) pData;
-
-    switch(callbackId & 0xFF00){
-        case ALGORITHM_CS_ID:
-            switch(callbackId & 0x00FF)
-            {
-                case LVCS_EVENT_ALGOFF:
-                    pInstance->CS_Active = LVM_FALSE;
-                    break;
-                default:
-                    break;
-            }
-            break;
-        case ALGORITHM_EQNB_ID:
-            switch(callbackId & 0x00FF)
-            {
-                case LVEQNB_EVENT_ALGOFF:
-                    pInstance->EQNB_Active = LVM_FALSE;
-                    break;
-                default:
-                    break;
-            }
-            break;
-        default:
-            break;
-    }
-
-    return 0;
-}
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_VCCallBack                                              */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This is the callback function of the Volume control.                                */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pBundleHandle           Pointer to the Instance Handle                              */
-/*  pGeneralPurpose         Pointer to the data                                         */
-/*  CallBackParam           ID of the callback                                          */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVM_Process function                    */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_INT32    LVM_VCCallBack(void*   pBundleHandle,
-                            void*   pGeneralPurpose,
-                            short   CallBackParam)
-{
-    LVM_Instance_t *pInstance =(LVM_Instance_t  *)pBundleHandle;
-#ifdef BUILD_FLOAT
-    LVM_FLOAT    Target;
-#else
-    LVM_INT32    Target;
-#endif
-
-    (void) pGeneralPurpose;
-    (void) CallBackParam;
-
-    /* When volume mixer has reached 0 dB target then stop it to avoid
-       unnecessary processing. */
-#ifdef BUILD_FLOAT
-    Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
-    if(Target == 1.0f)
-    {
-        pInstance->VC_Active = LVM_FALSE;
-    }
-#else
-    Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
-
-    if(Target == 0x7FFF)
-    {
-        pInstance->VC_Active = LVM_FALSE;
-    }
-#endif
-    return 1;
-}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
new file mode 100644
index 0000000..ff2c90a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Includes                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Coeffs.h"
+#include "LVM_Tables.h"
+#include "LVM_Private.h"
+
+#include <log/log.h>
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:           LVM_SetControlParameters                                         */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LifeVibes module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance          Instance handle                                                  */
+/*  pParams            Pointer to a parameter structure                                 */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS        Succeeded                                                        */
+/*  LVM_NULLADDRESS    When hInstance, pParams or any control pointers are NULL         */
+/*  LVM_OUTOFRANGE     When any of the control parameters are out of range              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
+
+    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    pInstance->NewParams = *pParams;
+
+    if(
+        /* General parameters */
+        ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON))                                         ||
+    ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
+     (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)      &&
+     (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)      &&
+     (pParams->SampleRate != LVM_FS_88200) && (pParams->SampleRate != LVM_FS_96000) &&
+     (pParams->SampleRate != LVM_FS_176400) && (pParams->SampleRate != LVM_FS_192000))      ||
+#ifdef SUPPORT_MC
+        ((pParams->SourceFormat != LVM_STEREO) &&
+         (pParams->SourceFormat != LVM_MONOINSTEREO) &&
+         (pParams->SourceFormat != LVM_MONO) &&
+         (pParams->SourceFormat != LVM_MULTICHANNEL)) ||
+#else
+        ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
+#endif
+        (pParams->SpeakerType > LVM_EX_HEADPHONES))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+#ifdef SUPPORT_MC
+    pInstance->Params.NrChannels = pParams->NrChannels;
+    pInstance->Params.ChMask     = pParams->ChMask;
+#endif
+    /*
+     * Cinema Sound parameters
+     */
+    if((pParams->VirtualizerOperatingMode != LVM_MODE_OFF) && (pParams->VirtualizerOperatingMode != LVM_MODE_ON))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->VirtualizerType != LVM_CONCERTSOUND)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->VirtualizerReverbLevel > LVM_VIRTUALIZER_MAX_REVERB_LEVEL)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->CS_EffectLevel < LVM_CS_MIN_EFFECT_LEVEL)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * N-Band Equalizer
+     */
+    if(pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /* Definition pointer */
+    if ((pParams->pEQNB_BandDefinition == LVM_NULL) &&
+        (pParams->EQNB_NBands != 0))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * Copy the filter definitions for the Equaliser
+     */
+    {
+        LVM_INT16           i;
+
+        if (pParams->EQNB_NBands != 0)
+        {
+            for (i=0; i<pParams->EQNB_NBands; i++)
+            {
+                pInstance->pEQNB_BandDefs[i] = pParams->pEQNB_BandDefinition[i];
+            }
+            pInstance->NewParams.pEQNB_BandDefinition = pInstance->pEQNB_BandDefs;
+        }
+    }
+    if( /* N-Band Equaliser parameters */
+        ((pParams->EQNB_OperatingMode != LVM_EQNB_OFF) && (pParams->EQNB_OperatingMode != LVM_EQNB_ON)) ||
+        (pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+    /* Band parameters*/
+    {
+        LVM_INT16 i;
+        for(i = 0; i < pParams->EQNB_NBands; i++)
+        {
+            if(((pParams->pEQNB_BandDefinition[i].Frequency < LVM_EQNB_MIN_BAND_FREQ)  ||
+                (pParams->pEQNB_BandDefinition[i].Frequency > LVM_EQNB_MAX_BAND_FREQ)) ||
+                ((pParams->pEQNB_BandDefinition[i].Gain     < LVM_EQNB_MIN_BAND_GAIN)  ||
+                (pParams->pEQNB_BandDefinition[i].Gain      > LVM_EQNB_MAX_BAND_GAIN)) ||
+                ((pParams->pEQNB_BandDefinition[i].QFactor  < LVM_EQNB_MIN_QFACTOR)     ||
+                (pParams->pEQNB_BandDefinition[i].QFactor   > LVM_EQNB_MAX_QFACTOR)))
+            {
+                return (LVM_OUTOFRANGE);
+            }
+        }
+    }
+
+    /*
+     * Bass Enhancement parameters
+     */
+    if(((pParams->BE_OperatingMode != LVM_BE_OFF) && (pParams->BE_OperatingMode != LVM_BE_ON))                      ||
+        ((pParams->BE_EffectLevel < LVM_BE_MIN_EFFECTLEVEL ) || (pParams->BE_EffectLevel > LVM_BE_MAX_EFFECTLEVEL ))||
+        ((pParams->BE_CentreFreq != LVM_BE_CENTRE_55Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_66Hz)           &&
+        (pParams->BE_CentreFreq != LVM_BE_CENTRE_78Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_90Hz))           ||
+        ((pParams->BE_HPF != LVM_BE_HPF_OFF) && (pParams->BE_HPF != LVM_BE_HPF_ON)))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Volume Control parameters
+     */
+    if((pParams->VC_EffectLevel < LVM_VC_MIN_EFFECTLEVEL ) || (pParams->VC_EffectLevel > LVM_VC_MAX_EFFECTLEVEL ))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+    if((pParams->VC_Balance < LVM_VC_BALANCE_MIN ) || (pParams->VC_Balance > LVM_VC_BALANCE_MAX ))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * PSA parameters
+     */
+    if (((LVPSA_LevelDetectSpeed_en)pParams->PSA_PeakDecayRate > LVPSA_SPEED_HIGH) ||
+        (pParams->PSA_Enable > LVM_PSA_ON))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+    * Set the flag to indicate there are new parameters to use
+    *
+    * Protect the copy of the new parameters from interrupts to avoid possible problems
+    * with loss control parameters. This problem can occur if this control function is called more
+    * than once before a call to the process function. If the process function interrupts
+    * the copy to NewParams then one frame may have mixed parameters, some old and some new.
+    */
+    pInstance->ControlPending = LVM_TRUE;
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:             LVM_GetControlParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the LifeVibes module parameters. The current parameter set is returned      */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance            Instance handle                                                */
+/*  pParams              Pointer to an empty parameter structure                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS          Succeeded                                                      */
+/*  LVM_NULLADDRESS      when any of hInstance or pParams is NULL                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
+
+    /*
+     * Check pointer
+     */
+    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+    *pParams = pInstance->NewParams;
+
+    /*
+     * Copy the filter definitions for the Equaliser
+     */
+    {
+        LVM_INT16           i;
+
+        if (pInstance->NewParams.EQNB_NBands != 0)
+        for (i=0; i<pInstance->NewParams.EQNB_NBands; i++)
+        {
+            pInstance->pEQNB_UserDefs[i] = pInstance->pEQNB_BandDefs[i];
+        }
+        pParams->pEQNB_BandDefinition = pInstance->pEQNB_UserDefs;
+    }
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetTrebleBoost                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Enable the treble boost when the settings are appropriate, i.e. non-zero gain       */
+/*  and the sample rate is high enough for the effect to be heard.                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pInstance               Pointer to the instance structure                           */
+/*  pParams                 Pointer to the parameters to use                            */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_SetTrebleBoost(LVM_Instance_t         *pInstance,
+                        LVM_ControlParams_t    *pParams)
+{
+    extern FO_FLOAT_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
+
+    LVM_INT16               Offset;
+    LVM_INT16               EffectLevel = 0;
+
+    /*
+     * Load the coefficients
+     */
+    if ((pParams->TE_OperatingMode == LVM_TE_ON) &&
+        (pParams->SampleRate >= TrebleBoostMinRate) &&
+        (pParams->OperatingMode == LVM_MODE_ON) &&
+        (pParams->TE_EffectLevel > 0))
+    {
+        if((pParams->TE_EffectLevel == LVM_TE_LOW_MIPS) &&
+            ((pParams->SpeakerType == LVM_HEADPHONES)||
+            (pParams->SpeakerType == LVM_EX_HEADPHONES)))
+        {
+            pInstance->TE_Active = LVM_FALSE;
+        }
+        else
+        {
+            EffectLevel = pParams->TE_EffectLevel;
+            pInstance->TE_Active = LVM_TRUE;
+        }
+
+        if(pInstance->TE_Active == LVM_TRUE)
+        {
+            /*
+             * Load the coefficients and enabled the treble boost
+             */
+            Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+            FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
+                                            &pInstance->pTE_Taps->TrebleBoost_Taps,
+                                            &LVM_TrebleBoostCoefs[Offset]);
+
+            /*
+             * Clear the taps
+             */
+            LoadConst_Float((LVM_FLOAT)0,                                     /* Value */
+                            (LVM_FLOAT *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
+                                                     Cast to void: no dereferencing in function */
+                            (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) / \
+                                                        sizeof(LVM_FLOAT))); /* Number of words */
+        }
+    }
+    else
+    {
+        /*
+         * Disable the treble boost
+         */
+        pInstance->TE_Active = LVM_FALSE;
+    }
+
+    return;
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVM_SetVolume                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Converts the input volume demand from dBs to linear.                            */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+void    LVM_SetVolume(LVM_Instance_t         *pInstance,
+                      LVM_ControlParams_t    *pParams)
+{
+
+    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
+    LVM_UINT16      dBOffset;                                   /* Table offset */
+    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
+    LVM_FLOAT        Temp;
+
+    /*
+     * Limit the gain to the maximum allowed
+     */
+     if  (pParams->VC_EffectLevel > 0)
+     {
+         Volume = 0;
+     }
+     else
+     {
+         Volume = pParams->VC_EffectLevel;
+     }
+
+     /* Compensate this volume in PSA plot */
+     if(Volume > -60)  /* Limit volume loss to PSA Limits*/
+         pInstance->PSA_GainOffset=(LVM_INT16)(-Volume);/* Loss is compensated by Gain*/
+     else
+         pInstance->PSA_GainOffset=(LVM_INT16)60;/* Loss is compensated by Gain*/
+
+    pInstance->VC_AVLFixedVolume = 0;
+
+    /*
+     * Set volume control and AVL volumes according to headroom and volume user setting
+     */
+    if(pParams->OperatingMode == LVM_MODE_ON)
+    {
+        /* Default Situation with no AVL and no RS */
+        if(pParams->EQNB_OperatingMode == LVM_EQNB_ON)
+        {
+            if(Volume > -pInstance->Headroom)
+                Volume = (LVM_INT16)-pInstance->Headroom;
+        }
+    }
+
+    /*
+     * Activate volume control if necessary
+     */
+    pInstance->VC_Active   = LVM_TRUE;
+    if (Volume != 0)
+    {
+        pInstance->VC_VolumedB = Volume;
+    }
+    else
+    {
+        pInstance->VC_VolumedB = 0;
+    }
+
+    /*
+     * Calculate the required gain and shifts
+     */
+    dBOffset = (LVM_UINT16)((-Volume) % 6);             /* Get the dBs 0-5 */
+    dBShifts = (LVM_UINT16)(Volume / -6);               /* Get the 6dB shifts */
+
+    /*
+     * Set the parameters
+     */
+    if(dBShifts == 0)
+    {
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+                                (LVM_FLOAT)LVM_VolumeTable[dBOffset]);
+        }
+    else
+    {
+        Temp = LVM_VolumeTable[dBOffset];
+        while(dBShifts) {
+            Temp = Temp / 2.0f;
+            dBShifts--;
+        }
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0], Temp);
+    }
+    pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
+    if(pInstance->NoSmoothVolume == LVM_TRUE)
+    {
+        LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0,
+                                  pInstance->Params.SampleRate, 2);
+    }
+    else
+    {
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],
+                                           LVM_VC_MIXER_TIME, pInstance->Params.SampleRate, 2);
+    }
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVM_SetHeadroom                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Find suitable headroom based on EQ settings.                                    */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  void                Nothing                                                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+void    LVM_SetHeadroom(LVM_Instance_t         *pInstance,
+                        LVM_ControlParams_t    *pParams)
+{
+    LVM_INT16   ii, jj;
+    LVM_INT16   Headroom = 0;
+    LVM_INT16   MaxGain = 0;
+
+    if (((LVEQNB_Mode_en)pParams->EQNB_OperatingMode == LVEQNB_ON)
+           && (pInstance->HeadroomParams.Headroom_OperatingMode == LVM_HEADROOM_ON))
+    {
+        /* Find typical headroom value */
+        for(jj = 0; jj < pInstance->HeadroomParams.NHeadroomBands; jj++)
+        {
+            MaxGain = 0;
+            for( ii = 0; ii < pParams->EQNB_NBands; ii++)
+            {
+                if((pParams->pEQNB_BandDefinition[ii].Frequency >= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_Low) &&
+                   (pParams->pEQNB_BandDefinition[ii].Frequency <= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_High))
+                {
+                    if(pParams->pEQNB_BandDefinition[ii].Gain > MaxGain)
+                    {
+                        MaxGain = pParams->pEQNB_BandDefinition[ii].Gain;
+                    }
+                }
+            }
+
+            if((MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset) > Headroom){
+                Headroom = (LVM_INT16)(MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset);
+            }
+        }
+
+        /* Saturate */
+        if(Headroom < 0)
+            Headroom = 0;
+    }
+    pInstance->Headroom = (LVM_UINT16)Headroom ;
+
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_ApplyNewSettings                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Applies changes to parametres. This function makes no assumptions about what        */
+/*  each module needs for initialisation and hence passes all parameters to all the     */
+/*  the modules in turn.                                                                */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_Success             Succeeded                                                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t   hInstance)
+{
+    LVM_Instance_t         *pInstance =(LVM_Instance_t *)hInstance;
+    LVM_ControlParams_t    LocalParams;
+    LVM_INT16              Count = 5;
+
+    /*
+     * Copy the new parameters but make sure they didn't change while copying
+     */
+    do
+    {
+        pInstance->ControlPending = LVM_FALSE;
+        LocalParams = pInstance->NewParams;
+        pInstance->HeadroomParams = pInstance->NewHeadroomParams;
+        Count--;
+    } while ((pInstance->ControlPending != LVM_FALSE) &&
+             (Count > 0));
+
+#ifdef SUPPORT_MC
+    pInstance->NrChannels = LocalParams.NrChannels;
+    pInstance->ChMask = LocalParams.ChMask;
+#endif
+
+    /* Clear all internal data if format change*/
+    if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
+    {
+        LVM_ClearAudioBuffers(pInstance);
+        pInstance->ControlPending = LVM_FALSE;
+    }
+
+    /*
+     * Update the treble boost if required
+     */
+    if ((pInstance->Params.SampleRate != LocalParams.SampleRate) ||
+        (pInstance->Params.TE_EffectLevel != LocalParams.TE_EffectLevel) ||
+        (pInstance->Params.TE_OperatingMode != LocalParams.TE_OperatingMode) ||
+        (pInstance->Params.OperatingMode != LocalParams.OperatingMode) ||
+        (pInstance->Params.SpeakerType != LocalParams.SpeakerType))
+    {
+        LVM_SetTrebleBoost(pInstance,
+                           &LocalParams);
+    }
+
+    /*
+     * Update the headroom if required
+     */
+        LVM_SetHeadroom(pInstance,                      /* Instance pointer */
+                        &LocalParams);                  /* New parameters */
+
+    /*
+     * Update the volume if required
+     */
+    {
+        LVM_SetVolume(pInstance,                      /* Instance pointer */
+                      &LocalParams);                  /* New parameters */
+    }
+    /* Apply balance changes*/
+    if(pInstance->Params.VC_Balance != LocalParams.VC_Balance)
+    {
+        /* Configure Mixer module for gradual changes to volume*/
+        if(LocalParams.VC_Balance < 0)
+        {
+            LVM_FLOAT Target_Float;
+            /* Drop in right channel volume*/
+            Target_Float = LVM_MAXFLOAT;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+
+            Target_Float = dB_to_LinFloat((LVM_INT16)(LocalParams.VC_Balance << 4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+        }
+        else if(LocalParams.VC_Balance >0)
+        {
+            LVM_FLOAT Target_Float;
+            /* Drop in left channel volume*/
+            Target_Float = dB_to_LinFloat((LVM_INT16)((-LocalParams.VC_Balance) << 4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+
+            Target_Float = LVM_MAXFLOAT;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
+        }
+        else
+        {
+            LVM_FLOAT Target_Float;
+            /* No drop*/
+            Target_Float = LVM_MAXFLOAT;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
+                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
+
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target_Float);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
+                                               LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
+        }
+    }
+    /*
+     * Update the bass enhancement
+     */
+    {
+        LVDBE_ReturnStatus_en       DBE_Status;
+        LVDBE_Params_t              DBE_Params;
+        LVDBE_Handle_t              *hDBEInstance = (LVDBE_Handle_t *)pInstance->hDBEInstance;
+
+        /*
+         * Set the new parameters
+         */
+        if(LocalParams.OperatingMode == LVM_MODE_OFF)
+        {
+            DBE_Params.OperatingMode = LVDBE_OFF;
+        }
+        else
+        {
+            DBE_Params.OperatingMode    = (LVDBE_Mode_en)LocalParams.BE_OperatingMode;
+        }
+        DBE_Params.SampleRate       = (LVDBE_Fs_en)LocalParams.SampleRate;
+        DBE_Params.EffectLevel      = LocalParams.BE_EffectLevel;
+        DBE_Params.CentreFrequency  = (LVDBE_CentreFreq_en)LocalParams.BE_CentreFreq;
+        DBE_Params.HPFSelect        = (LVDBE_FilterSelect_en)LocalParams.BE_HPF;
+        DBE_Params.HeadroomdB       = 0;
+        DBE_Params.VolumeControl    = LVDBE_VOLUME_OFF;
+        DBE_Params.VolumedB         = 0;
+#ifdef SUPPORT_MC
+        DBE_Params.NrChannels         = LocalParams.NrChannels;
+#endif
+
+        /*
+         * Make the changes
+         */
+        DBE_Status = LVDBE_Control(hDBEInstance,
+                                   &DBE_Params);
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (DBE_Status != LVDBE_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)DBE_Status);
+        }
+
+        /*
+         * Set the control flag
+         */
+        pInstance->DBE_Active = LVM_TRUE;
+    }
+
+    /*
+     * Update the N-Band Equaliser
+     */
+    {
+        LVEQNB_ReturnStatus_en      EQNB_Status;
+        LVEQNB_Params_t             EQNB_Params;
+        LVEQNB_Handle_t             *hEQNBInstance = (LVEQNB_Handle_t *)pInstance->hEQNBInstance;
+
+        /*
+         * Set the new parameters
+         */
+
+        if(LocalParams.OperatingMode == LVM_MODE_OFF)
+        {
+            EQNB_Params.OperatingMode    = LVEQNB_BYPASS;
+        }
+        else
+        {
+            EQNB_Params.OperatingMode    = (LVEQNB_Mode_en)LocalParams.EQNB_OperatingMode;
+        }
+
+        EQNB_Params.SampleRate       = (LVEQNB_Fs_en)LocalParams.SampleRate;
+        EQNB_Params.NBands           = LocalParams.EQNB_NBands;
+        EQNB_Params.pBandDefinition  = (LVEQNB_BandDef_t *)LocalParams.pEQNB_BandDefinition;
+        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
+        {
+            EQNB_Params.SourceFormat = LVEQNB_STEREO;
+        }
+#ifdef SUPPORT_MC
+        /* Note: Currently SourceFormat field of EQNB is not been
+         *       used by the module.
+         */
+        else if (LocalParams.SourceFormat == LVM_MULTICHANNEL)
+        {
+            EQNB_Params.SourceFormat = LVEQNB_MULTICHANNEL;
+        }
+#endif
+        else
+        {
+            EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO;     /* Force to Mono-in-Stereo mode */
+        }
+#ifdef SUPPORT_MC
+        EQNB_Params.NrChannels         = LocalParams.NrChannels;
+#endif
+
+        /*
+         * Set the control flag
+         */
+        if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
+            (LocalParams.EQNB_OperatingMode == LVM_EQNB_ON))
+        {
+            pInstance->EQNB_Active = LVM_TRUE;
+        }
+        else
+        {
+            EQNB_Params.OperatingMode = LVEQNB_BYPASS;
+        }
+
+        /*
+         * Make the changes
+         */
+        EQNB_Status = LVEQNB_Control(hEQNBInstance,
+                                     &EQNB_Params);
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (EQNB_Status != LVEQNB_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)EQNB_Status);
+        }
+
+    }
+
+    /*
+     * Update concert sound
+     */
+    {
+        LVCS_ReturnStatus_en        CS_Status;
+        LVCS_Params_t               CS_Params;
+        LVCS_Handle_t               *hCSInstance = (LVCS_Handle_t *)pInstance->hCSInstance;
+        LVM_Mode_en                 CompressorMode=LVM_MODE_ON;
+
+        /*
+         * Set the new parameters
+         */
+        if(LocalParams.VirtualizerOperatingMode == LVM_MODE_ON)
+        {
+            CS_Params.OperatingMode    = LVCS_ON;
+        }
+        else
+        {
+            CS_Params.OperatingMode    = LVCS_OFF;
+        }
+
+        if((LocalParams.TE_OperatingMode == LVM_TE_ON) && (LocalParams.TE_EffectLevel == LVM_TE_LOW_MIPS))
+        {
+            CS_Params.SpeakerType  = LVCS_EX_HEADPHONES;
+        }
+        else
+        {
+            CS_Params.SpeakerType  = LVCS_HEADPHONES;
+        }
+
+#ifdef SUPPORT_MC
+        /* Concert sound module processes only the left and right channels
+         * data. So the Source Format is set to LVCS_STEREO for multichannel
+         * input also.
+         */
+        if (LocalParams.SourceFormat == LVM_STEREO ||
+            LocalParams.SourceFormat == LVM_MULTICHANNEL)
+#else
+        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
+#endif
+        {
+            CS_Params.SourceFormat = LVCS_STEREO;
+        }
+        else
+        {
+            CS_Params.SourceFormat = LVCS_MONOINSTEREO;          /* Force to Mono-in-Stereo mode */
+        }
+        CS_Params.SampleRate  = LocalParams.SampleRate;
+        CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
+        CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
+#ifdef SUPPORT_MC
+        CS_Params.NrChannels  = LocalParams.NrChannels;
+#endif
+
+        /*
+         * Set the control flag
+         */
+        if (((LVM_Mode_en)LocalParams.OperatingMode == LVM_MODE_ON) &&
+            ((LVCS_Modes_en)LocalParams.VirtualizerOperatingMode != LVCS_OFF))
+        {
+            pInstance->CS_Active = LVM_TRUE;
+        }
+        else
+        {
+            CS_Params.OperatingMode = LVCS_OFF;
+        }
+
+        CS_Params.CompressorMode=CompressorMode;
+
+        /*
+         * Make the changes
+         */
+        CS_Status = LVCS_Control(hCSInstance,
+                                 &CS_Params);
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (CS_Status != LVCS_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)CS_Status);
+        }
+
+    }
+
+    /*
+     * Update the Power Spectrum Analyser
+     */
+    {
+        LVPSA_RETURN                PSA_Status;
+        LVPSA_ControlParams_t       PSA_Params;
+        pLVPSA_Handle_t             *hPSAInstance = (pLVPSA_Handle_t *)pInstance->hPSAInstance;
+
+        /*
+         * Set the new parameters
+         */
+        PSA_Params.Fs = LocalParams.SampleRate;
+        PSA_Params.LevelDetectionSpeed = (LVPSA_LevelDetectSpeed_en)LocalParams.PSA_PeakDecayRate;
+
+        /*
+         * Make the changes
+         */
+        if(pInstance->InstParams.PSA_Included==LVM_PSA_ON)
+        {
+            PSA_Status = LVPSA_Control(hPSAInstance,
+                &PSA_Params);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en)PSA_Status);
+            }
+
+            /*
+             * Apply new settings
+             */
+            PSA_Status = LVPSA_ApplyNewSettings ((LVPSA_InstancePr_t*)hPSAInstance);
+            if(PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en)PSA_Status);
+            }
+        }
+    }
+
+    /*
+     * Update the parameters and clear the flag
+     */
+    pInstance->NoSmoothVolume = LVM_FALSE;
+    pInstance->Params =  LocalParams;
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to set the automatiuc headroom management parameters.         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_Success             Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetHeadroomParams(LVM_Handle_t              hInstance,
+                                          LVM_HeadroomParams_t      *pHeadroomParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_UINT16          ii, NBands;
+
+    /* Check for NULL pointers */
+    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+    if ((pHeadroomParams->NHeadroomBands != 0) && (pHeadroomParams->pHeadroomDefinition == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /* Consider only the LVM_HEADROOM_MAX_NBANDS first bands*/
+    if (pHeadroomParams->NHeadroomBands > LVM_HEADROOM_MAX_NBANDS)
+    {
+        NBands = LVM_HEADROOM_MAX_NBANDS;
+    }
+    else
+    {
+        NBands = pHeadroomParams->NHeadroomBands;
+    }
+    pInstance->NewHeadroomParams.NHeadroomBands = NBands;
+
+    /* Copy settings in memory */
+    for(ii = 0; ii < NBands; ii++)
+    {
+        pInstance->pHeadroom_BandDefs[ii] = pHeadroomParams->pHeadroomDefinition[ii];
+    }
+
+    pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+    pInstance->NewHeadroomParams.Headroom_OperatingMode = pHeadroomParams->Headroom_OperatingMode;
+    pInstance->ControlPending = LVM_TRUE;
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to get the automatic headroom management parameters.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure (output)            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When hInstance or pHeadroomParams are NULL                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetHeadroomParams(LVM_Handle_t          hInstance,
+                                          LVM_HeadroomParams_t  *pHeadroomParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_UINT16          ii;
+
+    /* Check for NULL pointers */
+    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    pHeadroomParams->NHeadroomBands = pInstance->NewHeadroomParams.NHeadroomBands;
+
+    /* Copy settings in memory */
+    for(ii = 0; ii < pInstance->NewHeadroomParams.NHeadroomBands; ii++)
+    {
+        pInstance->pHeadroom_UserDefs[ii] = pInstance->pHeadroom_BandDefs[ii];
+    }
+
+    pHeadroomParams->pHeadroomDefinition = pInstance->pHeadroom_UserDefs;
+    pHeadroomParams->Headroom_OperatingMode = pInstance->NewHeadroomParams.Headroom_OperatingMode;
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_AlgoCallBack                                            */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This is the callback function of the algorithm.                                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pBundleHandle           Pointer to the Instance Handle                              */
+/*  pData                   Pointer to the data                                         */
+/*  callbackId              ID of the callback                                          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVM_AlgoCallBack( void          *pBundleHandle,
+                            void          *pData,
+                            LVM_INT16     callbackId)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)pBundleHandle;
+
+    (void) pData;
+
+    switch(callbackId & 0xFF00){
+        case ALGORITHM_CS_ID:
+            switch(callbackId & 0x00FF)
+            {
+                case LVCS_EVENT_ALGOFF:
+                    pInstance->CS_Active = LVM_FALSE;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        case ALGORITHM_EQNB_ID:
+            switch(callbackId & 0x00FF)
+            {
+                case LVEQNB_EVENT_ALGOFF:
+                    pInstance->EQNB_Active = LVM_FALSE;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_VCCallBack                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This is the callback function of the Volume control.                                */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pBundleHandle           Pointer to the Instance Handle                              */
+/*  pGeneralPurpose         Pointer to the data                                         */
+/*  CallBackParam           ID of the callback                                          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32    LVM_VCCallBack(void*   pBundleHandle,
+                            void*   pGeneralPurpose,
+                            short   CallBackParam)
+{
+    LVM_Instance_t *pInstance =(LVM_Instance_t  *)pBundleHandle;
+    LVM_FLOAT    Target;
+
+    (void) pGeneralPurpose;
+    (void) CallBackParam;
+
+    /* When volume mixer has reached 0 dB target then stop it to avoid
+       unnecessary processing. */
+    Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
+    if(Target == 1.0f)
+    {
+        pInstance->VC_Active = LVM_FALSE;
+    }
+    return 1;
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
deleted file mode 100644
index c57498e..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVM_Private.h"
-#include "LVM_Tables.h"
-#include "VectorArithmetic.h"
-#include "InstAlloc.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_GetMemoryTable                                          */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used for memory allocation and free. It can be called in           */
-/*  two ways:                                                                           */
-/*                                                                                      */
-/*      hInstance = NULL                Returns the memory requirements                 */
-/*      hInstance = Instance handle     Returns the memory requirements and             */
-/*                                      allocated base addresses for the instance       */
-/*                                                                                      */
-/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
-/*  base address pointers are NULL on return.                                           */
-/*                                                                                      */
-/*  When the function is called for free (hInstance = Instance Handle) the memory       */
-/*  table returns the allocated memory and base addresses used during initialisation.   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pMemoryTable            Pointer to an empty memory definition table                 */
-/*  pCapabilities           Pointer to the default capabilities                         */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Succeeded                                                   */
-/*  LVM_NULLADDRESS         When one of pMemoryTable or pInstParams is NULL             */
-/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVM_Process function                    */
-/*  2.  The scratch memory is the largest required by any of the sub-modules plus any   */
-/*      additional scratch requirements of the bundle                                   */
-/*                                                                                      */
-/****************************************************************************************/
-
-/*
- * 4 Types of Memory Regions of LVM
- * TODO: Allocate on the fly.
- * i)   LVM_MEMREGION_PERSISTENT_SLOW_DATA - For Instance Handles
- * ii)  LVM_MEMREGION_PERSISTENT_FAST_DATA - Persistent Buffers
- * iii) LVM_MEMREGION_PERSISTENT_FAST_COEF - For Holding Structure values
- * iv)  LVM_MEMREGION_TEMPORARY_FAST       - For Holding Structure values
- *
- * LVM_MEMREGION_PERSISTENT_SLOW_DATA:
- *   Total Memory size:
- *     sizeof(LVM_Instance_t) + \
- *     sizeof(LVM_Buffer_t) + \
- *     sizeof(LVPSA_InstancePr_t) + \
- *     sizeof(LVM_Buffer_t) - needed if buffer mode is LVM_MANAGED_BUFFER
- *
- * LVM_MEMREGION_PERSISTENT_FAST_DATA:
- *   Total Memory size:
- *     sizeof(LVM_TE_Data_t) + \
- *     2 * pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t) + \
- *     sizeof(LVCS_Data_t) + \
- *     sizeof(LVDBE_Data_FLOAT_t) + \
- *     sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
- *     sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
- *     pInstParams->EQNB_NumBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
- *     pInstParams->EQNB_NumBands * sizeof(LVEQNB_BandDef_t) + \
- *     pInstParams->EQNB_NumBands * sizeof(LVEQNB_BiquadType_en) + \
- *     2 * LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t) + \
- *     PSA_InitParams.nBands * sizeof(Biquad_1I_Order2_Taps_t) + \
- *     PSA_InitParams.nBands * sizeof(QPD_Taps_t)
- *
- * LVM_MEMREGION_PERSISTENT_FAST_COEF:
- *   Total Memory size:
- *     sizeof(LVM_TE_Coefs_t) + \
- *     sizeof(LVCS_Coefficient_t) + \
- *     sizeof(LVDBE_Coef_FLOAT_t) + \
- *     sizeof(Biquad_FLOAT_Instance_t) + \
- *     sizeof(Biquad_FLOAT_Instance_t) + \
- *     pInstParams->EQNB_NumBands * sizeof(Biquad_FLOAT_Instance_t) + \
- *     PSA_InitParams.nBands * sizeof(Biquad_Instance_t) + \
- *     PSA_InitParams.nBands * sizeof(QPD_State_t)
- *
- * LVM_MEMREGION_TEMPORARY_FAST (Scratch):
- *   Total Memory Size:
- *     BundleScratchSize + \
- *     MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_FLOAT) + \
- *     MaxScratchOf (CS, EQNB, DBE, PSA)
- *
- *     a)BundleScratchSize:
- *         3 * LVM_MAX_CHANNELS \
- *         * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_FLOAT)
- *       This Memory is allocated only when Buffer mode is LVM_MANAGED_BUFFER.
- *     b)MaxScratchOf (CS, EQNB, DBE, PSA)
- *       This Memory is needed for scratch usage for CS, EQNB, DBE, PSA.
- *       CS   = (LVCS_SCRATCHBUFFERS * sizeof(LVM_FLOAT)
- *               * pCapabilities->MaxBlockSize)
- *       EQNB = (LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT)
- *               * pCapabilities->MaxBlockSize)
- *       DBE  = (LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT)
- *               * pCapabilities->MaxBlockSize)
- *       PSA  = (2 * pInitParams->MaxInputBlockSize * sizeof(LVM_FLOAT))
- *              one MaxInputBlockSize for input and another for filter output
- *     c)MAX_INTERNAL_BLOCKSIZE
- *       This Memory is needed for PSAInput - Temp memory to store output
- *       from McToMono block and given as input to PSA block
- */
-
-LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t         hInstance,
-                                       LVM_MemTab_t         *pMemoryTable,
-                                       LVM_InstParams_t     *pInstParams)
-{
-
-    LVM_Instance_t      *pInstance = (LVM_Instance_t *)hInstance;
-    LVM_UINT32          AlgScratchSize;
-    LVM_UINT32          BundleScratchSize;
-    LVM_UINT16          InternalBlockSize;
-    INST_ALLOC          AllocMem[LVM_NR_MEMORY_REGIONS];
-    LVM_INT16           i;
-
-
-    /*
-     * Check parameters
-     */
-    if(pMemoryTable == LVM_NULL)
-    {
-        return LVM_NULLADDRESS;
-    }
-
-
-    /*
-     * Return memory table if the instance has already been created
-     */
-    if (hInstance != LVM_NULL)
-    {
-       /* Read back memory allocation table */
-        *pMemoryTable = pInstance->MemoryTable;
-        return(LVM_SUCCESS);
-    }
-
-    if(pInstParams == LVM_NULL)
-    {
-        return LVM_NULLADDRESS;
-    }
-
-    /*
-     *  Power Spectrum Analyser
-     */
-    if(pInstParams->PSA_Included > LVM_PSA_ON)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /*
-     * Check the instance parameters
-     */
-    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /* N-Band Equalizer */
-    if( pInstParams->EQNB_NumBands > 32 )
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
-        {
-            return (LVM_OUTOFRANGE);
-        }
-    }
-    else
-    {
-        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
-        {
-            return (LVM_OUTOFRANGE);
-        }
-    }
-
-    /*
-    * Initialise the AllocMem structures
-    */
-    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
-    {
-        InstAlloc_Init(&AllocMem[i], LVM_NULL);
-    }
-    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
-
-    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
-    {
-        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
-    }
-
-    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
-    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
-    {
-        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
-    }
-
-    /*
-    * Bundle requirements
-    */
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-        sizeof(LVM_Instance_t));
-
-
-    /*
-     * Set the algorithm and bundle scratch requirements
-     */
-    AlgScratchSize    = 0;
-    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
-    {
-#ifdef BUILD_FLOAT
-        BundleScratchSize = 3 * LVM_MAX_CHANNELS \
-                            * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) \
-                            * sizeof(LVM_FLOAT);
-#else
-        BundleScratchSize = 6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16);
-#endif
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],        /* Scratch buffer */
-                            BundleScratchSize);
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-                            sizeof(LVM_Buffer_t));
-    }
-
-    /*
-     * Treble Enhancement requirements
-     */
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                        sizeof(LVM_TE_Data_t));
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                        sizeof(LVM_TE_Coefs_t));
-
-    /*
-     * N-Band Equalizer requirements
-     */
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* Local storage */
-                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* User storage */
-                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
-
-    /*
-     * Concert Sound requirements
-     */
-    {
-        LVCS_MemTab_t           CS_MemTab;
-        LVCS_Capabilities_t     CS_Capabilities;
-
-        /*
-         * Set the capabilities
-         */
-        CS_Capabilities.MaxBlockSize     = InternalBlockSize;
-
-        /*
-         * Get the memory requirements
-         */
-        LVCS_Memory(LVM_NULL,
-                    &CS_MemTab,
-                    &CS_Capabilities);
-
-        /*
-         * Update the memory allocation structures
-         */
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
-        if (CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
-
-    }
-
-
-    /*
-     * Dynamic Bass Enhancement requirements
-     */
-    {
-        LVDBE_MemTab_t          DBE_MemTab;
-        LVDBE_Capabilities_t    DBE_Capabilities;
-
-        /*
-         * Set the capabilities
-         */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
-                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
-                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
-                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
-                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
-                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
-                                           LVDBE_CAP_FS_192000;
-#else
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
-#endif
-        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
-        DBE_Capabilities.MaxBlockSize    = InternalBlockSize;
-
-        /*
-         * Get the memory requirements
-         */
-        LVDBE_Memory(LVM_NULL,
-                    &DBE_MemTab,
-
-                    &DBE_Capabilities);
-        /*
-         * Update the bundle table
-         */
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
-        if (DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
-
-    }
-
-
-    /*
-     * N-Band equaliser requirements
-     */
-    {
-        LVEQNB_MemTab_t         EQNB_MemTab;            /* For N-Band Equaliser */
-        LVEQNB_Capabilities_t   EQNB_Capabilities;
-
-        /*
-         * Set the capabilities
-         */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
-                                         LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
-                                         LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
-                                         LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
-                                         LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
-                                         LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
-                                         LVEQNB_CAP_FS_192000;
-#else
-        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
-#endif
-        EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
-        EQNB_Capabilities.MaxBlockSize = InternalBlockSize;
-        EQNB_Capabilities.MaxBands     = pInstParams->EQNB_NumBands;
-
-        /*
-         * Get the memory requirements
-         */
-        LVEQNB_Memory(LVM_NULL,
-                      &EQNB_MemTab,
-                      &EQNB_Capabilities);
-
-        /*
-         * Update the bundle table
-         */
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
-        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
-        if (EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
-
-    }
-
-    /*
-     * Headroom management memory allocation
-     */
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
-
-
-    /*
-     * Spectrum Analyzer memory requirements
-     */
-    {
-        pLVPSA_Handle_t     hPSAInst = LVM_NULL;
-        LVPSA_MemTab_t      PSA_MemTab;
-        LVPSA_InitParams_t  PSA_InitParams;
-        LVPSA_FilterParam_t FiltersParams[9];
-        LVPSA_RETURN        PSA_Status;
-
-        if(pInstParams->PSA_Included == LVM_PSA_ON)
-        {
-            PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
-            PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 1000;
-            PSA_InitParams.nBands                       = (LVM_UINT16) 9;
-
-            PSA_InitParams.pFiltersParams = &FiltersParams[0];
-            for(i = 0; i < PSA_InitParams.nBands; i++)
-            {
-                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
-                FiltersParams[i].QFactor            = (LVM_UINT16) 25;
-                FiltersParams[i].PostGain           = (LVM_INT16)  0;
-            }
-
-            /*
-            * Get the memory requirements
-            */
-            PSA_Status = LVPSA_Memory (hPSAInst,
-                                        &PSA_MemTab,
-                                        &PSA_InitParams);
-
-            if (PSA_Status != LVPSA_OK)
-            {
-                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
-            }
-
-            /*
-            * Update the bundle table
-            */
-            /* Slow Data */
-            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
-
-            /* Fast Data */
-            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
-
-            /* Fast Coef */
-            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
-
-            /* Fast Temporary */
-#ifdef BUILD_FLOAT
-            InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
-                                MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_FLOAT));
-#else
-            InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
-                                MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
-#endif
-
-            if (PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size > AlgScratchSize)
-            {
-                AlgScratchSize = PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size;
-            }
-        }
-    }
-
-    /*
-     * Return the memory table
-     */
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA]);
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA]);
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size < 4)
-    {
-        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size = 0;
-    }
-
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF]);
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
-    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size < 4)
-    {
-        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size = 0;
-    }
-
-    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
-                        AlgScratchSize);
-    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size             = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST]);
-    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Type             = LVM_TEMPORARY_FAST;
-    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].pBaseAddress     = LVM_NULL;
-    if (pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size < 4)
-    {
-        pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size = 0;
-    }
-
-    return(LVM_SUCCESS);
-
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_GetInstanceHandle                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to create a bundle instance. It returns the created instance  */
-/*  handle through phInstance. All parameters are set to their default, inactive state. */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  phInstance              pointer to the instance handle                              */
-/*  pMemoryTable            Pointer to the memory definition table                      */
-/*  pInstParams             Pointer to the initialisation capabilities                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Initialisation succeeded                                    */
-/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
-/*  LVM_NULLADDRESS         When one of phInstance, pMemoryTable or pInstParams are NULL*/
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function must not be interrupted by the LVM_Process function                */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t           *phInstance,
-                                          LVM_MemTab_t           *pMemoryTable,
-                                          LVM_InstParams_t       *pInstParams)
-{
-
-    LVM_ReturnStatus_en     Status = LVM_SUCCESS;
-    LVM_Instance_t          *pInstance;
-    INST_ALLOC              AllocMem[LVM_NR_MEMORY_REGIONS];
-    LVM_INT16               i;
-    LVM_UINT16              InternalBlockSize;
-    LVM_INT32               BundleScratchSize;
-
-
-    /*
-     * Check valid points have been given
-     */
-    if ((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstParams == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    /*
-     * Check the memory table for NULL pointers
-     */
-    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
-    {
-        if ((pMemoryTable->Region[i].Size != 0) &&
-            (pMemoryTable->Region[i].pBaseAddress==LVM_NULL))
-        {
-            return(LVM_NULLADDRESS);
-        }
-    }
-
-    /*
-     * Check the instance parameters
-     */
-    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if( pInstParams->EQNB_NumBands > 32 )
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
-        {
-            return (LVM_OUTOFRANGE);
-        }
-    }
-    else
-    {
-        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
-        {
-            return (LVM_OUTOFRANGE);
-        }
-    }
-
-    if(pInstParams->PSA_Included > LVM_PSA_ON)
-    {
-        return (LVM_OUTOFRANGE);
-    }
-
-    /*
-     * Initialise the AllocMem structures
-     */
-    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
-    {
-        InstAlloc_Init(&AllocMem[i],
-                       pMemoryTable->Region[i].pBaseAddress);
-    }
-
-
-    /*
-     * Set the instance handle
-     */
-    *phInstance  = (LVM_Handle_t)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-                                                     sizeof(LVM_Instance_t));
-    pInstance =(LVM_Instance_t  *)*phInstance;
-
-
-    /*
-     * Save the memory table, parameters and capabilities
-     */
-    pInstance->MemoryTable    = *pMemoryTable;
-    pInstance->InstParams     = *pInstParams;
-
-
-    /*
-     * Set the bundle scratch memory and initialse the buffer management
-     */
-    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
-    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
-    {
-        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
-    }
-
-    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
-    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
-    {
-        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
-    }
-    pInstance->InternalBlockSize = (LVM_INT16)InternalBlockSize;
-
-
-    /*
-     * Common settings for managed and unmanaged buffers
-     */
-    pInstance->SamplesToProcess = 0;                /* No samples left to process */
-    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
-    {
-        /*
-         * Managed buffers required
-         */
-        pInstance->pBufferManagement = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-                                                           sizeof(LVM_Buffer_t));
-#ifdef BUILD_FLOAT
-        BundleScratchSize = (LVM_INT32)
-                            (3 * LVM_MAX_CHANNELS \
-                             * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) \
-                             * sizeof(LVM_FLOAT));
-#else
-        BundleScratchSize = (LVM_INT32)(6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16));
-#endif
-        pInstance->pBufferManagement->pScratch = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],   /* Scratch 1 buffer */
-                                                                     (LVM_UINT32)BundleScratchSize);
-#ifdef BUILD_FLOAT
-        LoadConst_Float(0,                                   /* Clear the input delay buffer */
-                        (LVM_FLOAT *)&pInstance->pBufferManagement->InDelayBuffer,
-                        (LVM_INT16)(LVM_MAX_CHANNELS * MIN_INTERNAL_BLOCKSIZE));
-#else
-        LoadConst_16(0,                                                        /* Clear the input delay buffer */
-                     (LVM_INT16 *)&pInstance->pBufferManagement->InDelayBuffer,
-                     (LVM_INT16)(2 * MIN_INTERNAL_BLOCKSIZE));
-#endif
-        pInstance->pBufferManagement->InDelaySamples = MIN_INTERNAL_BLOCKSIZE; /* Set the number of delay samples */
-        pInstance->pBufferManagement->OutDelaySamples = 0;                     /* No samples in the output buffer */
-        pInstance->pBufferManagement->BufferState = LVM_FIRSTCALL;             /* Set the state ready for the first call */
-    }
-
-
-    /*
-     * Set default parameters
-     */
-    pInstance->Params.OperatingMode    = LVM_MODE_OFF;
-    pInstance->Params.SampleRate       = LVM_FS_8000;
-    pInstance->Params.SourceFormat     = LVM_MONO;
-    pInstance->Params.SpeakerType      = LVM_HEADPHONES;
-    pInstance->Params.VC_EffectLevel   = 0;
-    pInstance->Params.VC_Balance       = 0;
-
-    /*
-     * Set callback
-     */
-    pInstance->CallBack = LVM_AlgoCallBack;
-
-
-    /*
-     * DC removal filter
-     */
-#ifdef SUPPORT_MC
-    DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
-#else
-    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
-#endif
-
-    /*
-     * Treble Enhancement
-     */
-    pInstance->pTE_Taps  = (LVM_TE_Data_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                                sizeof(LVM_TE_Data_t));
-
-    pInstance->pTE_State = (LVM_TE_Coefs_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                                                                 sizeof(LVM_TE_Coefs_t));
-    pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
-    pInstance->Params.TE_EffectLevel   = 0;
-    pInstance->TE_Active               = LVM_FALSE;
-
-
-    /*
-     * Set the volume control and initialise Current to Target
-     */
-    pInstance->VC_Volume.MixerStream[0].CallbackParam      = 0;
-    pInstance->VC_Volume.MixerStream[0].CallbackSet        = 0;
-    pInstance->VC_Volume.MixerStream[0].pCallbackHandle    = pInstance;
-    pInstance->VC_Volume.MixerStream[0].pCallBack          = LVM_VCCallBack;
-
-    /* In managed buffering, start with low signal level as delay in buffer management causes a click*/
-    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
-    {
-#ifdef BUILD_FLOAT
-        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], 0, 0);
-#else
-        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],0,0);
-#endif
-    }
-    else
-    {
-#ifdef BUILD_FLOAT
-        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
-#else
-        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
-#endif
-    }
-
-#ifdef BUILD_FLOAT
-    LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,LVM_FS_8000,2);
-#else
-    LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0, LVM_FS_8000, 2);
-#endif
-
-    pInstance->VC_VolumedB                  = 0;
-    pInstance->VC_AVLFixedVolume            = 0;
-    pInstance->VC_Active                    = LVM_FALSE;
-
-    pInstance->VC_BalanceMix.MixerStream[0].CallbackParam      = 0;
-    pInstance->VC_BalanceMix.MixerStream[0].CallbackSet        = 0;
-    pInstance->VC_BalanceMix.MixerStream[0].pCallbackHandle    = pInstance;
-    pInstance->VC_BalanceMix.MixerStream[0].pCallBack          = LVM_VCCallBack;
-#ifdef BUILD_FLOAT
-    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
-#else
-    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
-#endif
-    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
-
-    pInstance->VC_BalanceMix.MixerStream[1].CallbackParam      = 0;
-    pInstance->VC_BalanceMix.MixerStream[1].CallbackSet        = 0;
-    pInstance->VC_BalanceMix.MixerStream[1].pCallbackHandle    = pInstance;
-    pInstance->VC_BalanceMix.MixerStream[1].pCallBack          = LVM_VCCallBack;
-#ifdef BUILD_FLOAT
-    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1], LVM_MAXFLOAT, LVM_MAXFLOAT);
-#else
-    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1],LVM_MAXINT_16,LVM_MAXINT_16);
-#endif
-    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
-
-    /*
-     * Set the default EQNB pre-gain and pointer to the band definitions
-     */
-    pInstance->pEQNB_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                    (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
-    pInstance->pEQNB_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                   (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
-
-
-    /*
-     * Initialise the Concert Sound module
-     */
-    {
-        LVCS_Handle_t           hCSInstance;                /* Instance handle */
-        LVCS_MemTab_t           CS_MemTab;                  /* Memory table */
-        LVCS_Capabilities_t     CS_Capabilities;            /* Initial capabilities */
-        LVCS_ReturnStatus_en    LVCS_Status;                /* Function call status */
-
-        /*
-         * Set default parameters
-         */
-        pInstance->Params.VirtualizerReverbLevel    = 100;
-        pInstance->Params.VirtualizerType           = LVM_CONCERTSOUND;
-        pInstance->Params.VirtualizerOperatingMode  = LVM_MODE_OFF;
-        pInstance->CS_Active                        = LVM_FALSE;
-
-        /*
-         * Set the initialisation capabilities
-         */
-        CS_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
-        CS_Capabilities.CallBack = pInstance->CallBack;
-        CS_Capabilities.pBundleInstance = (void*)pInstance;
-
-
-        /*
-         * Get the memory requirements and then set the address pointers, forcing alignment
-         */
-        LVCS_Status = LVCS_Memory(LVM_NULL,                /* Get the memory requirements */
-                                  &CS_MemTab,
-                                  &CS_Capabilities);
-        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = &pInstance->CS_Instance;
-        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size);
-        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size);
-        CS_MemTab.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
-                                                                                                         0);
-
-        /*
-         * Initialise the Concert Sound instance and save the instance handle
-         */
-        hCSInstance = LVM_NULL;                            /* Set to NULL to return handle */
-        LVCS_Status = LVCS_Init(&hCSInstance,              /* Initiailse */
-                                &CS_MemTab,
-                                &CS_Capabilities);
-        if (LVCS_Status != LVCS_SUCCESS) return((LVM_ReturnStatus_en)LVCS_Status);
-        pInstance->hCSInstance = hCSInstance;              /* Save the instance handle */
-
-    }
-
-    /*
-     * Initialise the Bass Enhancement module
-     */
-    {
-        LVDBE_Handle_t          hDBEInstance;               /* Instance handle */
-        LVDBE_MemTab_t          DBE_MemTab;                 /* Memory table */
-        LVDBE_Capabilities_t    DBE_Capabilities;           /* Initial capabilities */
-        LVDBE_ReturnStatus_en   LVDBE_Status;               /* Function call status */
-
-
-        /*
-         * Set the initialisation parameters
-         */
-        pInstance->Params.BE_OperatingMode = LVM_BE_OFF;
-        pInstance->Params.BE_CentreFreq    = LVM_BE_CENTRE_55Hz;
-        pInstance->Params.BE_EffectLevel   = 0;
-        pInstance->Params.BE_HPF           = LVM_BE_HPF_OFF;
-
-        pInstance->DBE_Active              = LVM_FALSE;
-
-
-
-        /*
-         * Set the initialisation capabilities
-         */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
-                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
-                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
-                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
-                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
-                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
-                                           LVDBE_CAP_FS_192000;
-#else
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
-#endif
-        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
-        DBE_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
-
-
-        /*
-         * Get the memory requirements and then set the address pointers
-         */
-        LVDBE_Status = LVDBE_Memory(LVM_NULL,               /* Get the memory requirements */
-                                    &DBE_MemTab,
-                                    &DBE_Capabilities);
-        DBE_MemTab.Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->DBE_Instance;
-        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size);
-        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size);
-        DBE_MemTab.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
-                                                                                                      0);
-
-
-        /*
-         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
-         */
-        hDBEInstance = LVM_NULL;                            /* Set to NULL to return handle */
-        LVDBE_Status = LVDBE_Init(&hDBEInstance,            /* Initiailse */
-                                  &DBE_MemTab,
-                                  &DBE_Capabilities);
-        if (LVDBE_Status != LVDBE_SUCCESS) return((LVM_ReturnStatus_en)LVDBE_Status);
-        pInstance->hDBEInstance = hDBEInstance;             /* Save the instance handle */
-    }
-
-
-    /*
-     * Initialise the N-Band Equaliser module
-     */
-    {
-        LVEQNB_Handle_t          hEQNBInstance;             /* Instance handle */
-        LVEQNB_MemTab_t          EQNB_MemTab;               /* Memory table */
-        LVEQNB_Capabilities_t    EQNB_Capabilities;         /* Initial capabilities */
-        LVEQNB_ReturnStatus_en   LVEQNB_Status;             /* Function call status */
-
-
-        /*
-         * Set the initialisation parameters
-         */
-        pInstance->Params.EQNB_OperatingMode   = LVM_EQNB_OFF;
-        pInstance->Params.EQNB_NBands          = 0;
-        pInstance->Params.pEQNB_BandDefinition = LVM_NULL;
-        pInstance->EQNB_Active                 = LVM_FALSE;
-
-
-        /*
-         * Set the initialisation capabilities
-         */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
-                                            LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
-                                            LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
-                                            LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
-                                            LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
-                                            LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
-                                            LVEQNB_CAP_FS_192000;
-#else
-        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
-#endif
-        EQNB_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
-        EQNB_Capabilities.MaxBands        = pInstParams->EQNB_NumBands;
-        EQNB_Capabilities.SourceFormat    = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
-        EQNB_Capabilities.CallBack        = pInstance->CallBack;
-        EQNB_Capabilities.pBundleInstance  = (void*)pInstance;
-
-
-        /*
-         * Get the memory requirements and then set the address pointers, forcing alignment
-         */
-        LVEQNB_Status = LVEQNB_Memory(LVM_NULL,             /* Get the memory requirements */
-                                      &EQNB_MemTab,
-                                      &EQNB_Capabilities);
-        EQNB_MemTab.Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->EQNB_Instance;
-        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size);
-        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size);
-        EQNB_MemTab.Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
-                                                                                                        0);
-
-
-        /*
-         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
-         */
-        hEQNBInstance = LVM_NULL;                           /* Set to NULL to return handle */
-        LVEQNB_Status = LVEQNB_Init(&hEQNBInstance,         /* Initiailse */
-                                    &EQNB_MemTab,
-                                    &EQNB_Capabilities);
-        if (LVEQNB_Status != LVEQNB_SUCCESS) return((LVM_ReturnStatus_en)LVEQNB_Status);
-        pInstance->hEQNBInstance = hEQNBInstance;           /* Save the instance handle */
-    }
-
-    /*
-     * Headroom management memory allocation
-     */
-    {
-        pInstance->pHeadroom_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                        (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
-        pInstance->pHeadroom_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                                                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
-
-        /* Headroom management parameters initialisation */
-        pInstance->NewHeadroomParams.NHeadroomBands = 2;
-        pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_Low          = 20;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_High         = 4999;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Headroom_Offset    = 3;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_Low          = 5000;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_High         = 24000;
-        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Headroom_Offset    = 4;
-        pInstance->NewHeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
-
-        pInstance->Headroom =0;
-    }
-
-
-    /*
-     * Initialise the PSA module
-     */
-    {
-        pLVPSA_Handle_t     hPSAInstance = LVM_NULL;   /* Instance handle */
-        LVPSA_MemTab_t      PSA_MemTab;
-        LVPSA_RETURN        PSA_Status;                 /* Function call status */
-        LVPSA_FilterParam_t FiltersParams[9];
-
-        if(pInstParams->PSA_Included==LVM_PSA_ON)
-        {
-            pInstance->PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
-            pInstance->PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 2048;
-            pInstance->PSA_InitParams.nBands                       = (LVM_UINT16) 9;
-            pInstance->PSA_InitParams.pFiltersParams               = &FiltersParams[0];
-            for(i = 0; i < pInstance->PSA_InitParams.nBands; i++)
-            {
-                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
-                FiltersParams[i].QFactor            = (LVM_UINT16) 100;
-                FiltersParams[i].PostGain           = (LVM_INT16)  0;
-            }
-
-            /*Get the memory requirements and then set the address pointers*/
-            PSA_Status = LVPSA_Memory (hPSAInstance,
-                                          &PSA_MemTab,
-                                          &pInstance->PSA_InitParams);
-
-            if (PSA_Status != LVPSA_OK)
-            {
-                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
-            }
-
-            /* Slow Data */
-            PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
-                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
-
-
-            /* Fast Data */
-            PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
-                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
-
-
-            /* Fast Coef */
-            PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
-                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
-
-            /* Fast Temporary */
-#ifdef BUILD_FLOAT
-            pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
-                                                       (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * \
-                                                       sizeof(LVM_FLOAT));
-#else
-            pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
-                                                       (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
-#endif
-            PSA_MemTab.Region[LVM_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],0);
-
-
-            /*Initialise PSA instance and save the instance handle*/
-            pInstance->PSA_ControlParams.Fs = LVM_FS_48000;
-            pInstance->PSA_ControlParams.LevelDetectionSpeed  = LVPSA_SPEED_MEDIUM;
-            PSA_Status = LVPSA_Init (&hPSAInstance,
-                                    &pInstance->PSA_InitParams,
-                                    &pInstance->PSA_ControlParams,
-                                    &PSA_MemTab);
-
-            if (PSA_Status != LVPSA_OK)
-            {
-                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
-            }
-
-            pInstance->hPSAInstance = hPSAInstance;       /* Save the instance handle */
-            pInstance->PSA_GainOffset = 0;
-        }
-        else
-        {
-            pInstance->hPSAInstance = LVM_NULL;
-        }
-
-        /*
-         * Set the initialisation parameters.
-         */
-        pInstance->Params.PSA_PeakDecayRate   = LVM_PSA_SPEED_MEDIUM;
-        pInstance->Params.PSA_Enable          = LVM_PSA_OFF;
-    }
-
-    /*
-     * Copy the initial parameters to the new parameters for correct readback of
-     * the settings.
-     */
-    pInstance->NewParams = pInstance->Params;
-
-
-    /*
-     * Create configuration number
-     */
-    pInstance->ConfigurationNumber = 0x00000000;
-    pInstance->ConfigurationNumber += LVM_CS_MASK;
-    pInstance->ConfigurationNumber += LVM_EQNB_MASK;
-    pInstance->ConfigurationNumber += LVM_DBE_MASK;
-    pInstance->ConfigurationNumber += LVM_VC_MASK;
-    pInstance->ConfigurationNumber += LVM_PSA_MASK;
-
-    if(((pInstance->ConfigurationNumber  & LVM_CS_MASK)!=0)  ||
-        ((pInstance->ConfigurationNumber & LVM_DBE_MASK)!=0) ||
-        ((pInstance->ConfigurationNumber & LVM_EQNB_MASK)!=0)||
-        ((pInstance->ConfigurationNumber & LVM_TE_MASK)!=0)  ||
-        ((pInstance->ConfigurationNumber & LVM_VC_MASK)!=0))
-    {
-        pInstance->BlickSizeMultiple    = 4;
-    }
-    else
-    {
-        pInstance->BlickSizeMultiple    = 1;
-    }
-
-    return(Status);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_ClearAudioBuffers                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to clear the internal audio buffers of the bundle.            */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS             Initialisation succeeded                                    */
-/*  LVM_NULLADDRESS         Instance or scratch memory has a NULL pointer               */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function must not be interrupted by the LVM_Process function                */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t  hInstance)
-{
-    LVM_MemTab_t            MemTab;                                     /* Memory table */
-    LVM_InstParams_t        InstParams;                                 /* Instance parameters */
-    LVM_ControlParams_t     Params;                                     /* Control Parameters */
-    LVM_Instance_t          *pInstance  = (LVM_Instance_t  *)hInstance; /* Pointer to Instance */
-    LVM_HeadroomParams_t    HeadroomParams;
-
-
-    if(hInstance == LVM_NULL){
-        return LVM_NULLADDRESS;
-    }
-
-    /* Save the control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
-    LVM_GetControlParameters(hInstance, &Params);
-
-    /*Save the headroom parameters*/
-    LVM_GetHeadroomParams(hInstance, &HeadroomParams);
-
-    /*  Retrieve allocated buffers in memtab */
-    LVM_GetMemoryTable(hInstance, &MemTab,  LVM_NULL);
-
-    /*  Save the instance parameters */
-    InstParams = pInstance->InstParams;
-
-    /*  Call  LVM_GetInstanceHandle to re-initialise the bundle */
-    LVM_GetInstanceHandle( &hInstance,
-                           &MemTab,
-                           &InstParams);
-
-    /* Restore control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
-    LVM_SetControlParameters(hInstance, &Params);
-
-    /*Restore the headroom parameters*/
-    LVM_SetHeadroomParams(hInstance, &HeadroomParams);
-
-    /* DC removal filter */
-#ifdef SUPPORT_MC
-    DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
-#else
-    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
-#endif
-
-    return LVM_SUCCESS;
-}
-
-
-
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
new file mode 100644
index 0000000..5620529
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -0,0 +1,1074 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+#include "VectorArithmetic.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetMemoryTable                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilities                         */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When one of pMemoryTable or pInstParams is NULL             */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*  2.  The scratch memory is the largest required by any of the sub-modules plus any   */
+/*      additional scratch requirements of the bundle                                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+/*
+ * 4 Types of Memory Regions of LVM
+ * TODO: Allocate on the fly.
+ * i)   LVM_MEMREGION_PERSISTENT_SLOW_DATA - For Instance Handles
+ * ii)  LVM_MEMREGION_PERSISTENT_FAST_DATA - Persistent Buffers
+ * iii) LVM_MEMREGION_PERSISTENT_FAST_COEF - For Holding Structure values
+ * iv)  LVM_MEMREGION_TEMPORARY_FAST       - For Holding Structure values
+ *
+ * LVM_MEMREGION_PERSISTENT_SLOW_DATA:
+ *   Total Memory size:
+ *     sizeof(LVM_Instance_t) + \
+ *     sizeof(LVM_Buffer_t) + \
+ *     sizeof(LVPSA_InstancePr_t) + \
+ *     sizeof(LVM_Buffer_t) - needed if buffer mode is LVM_MANAGED_BUFFER
+ *
+ * LVM_MEMREGION_PERSISTENT_FAST_DATA:
+ *   Total Memory size:
+ *     sizeof(LVM_TE_Data_t) + \
+ *     2 * pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t) + \
+ *     sizeof(LVCS_Data_t) + \
+ *     sizeof(LVDBE_Data_FLOAT_t) + \
+ *     sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
+ *     sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
+ *     pInstParams->EQNB_NumBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t) + \
+ *     pInstParams->EQNB_NumBands * sizeof(LVEQNB_BandDef_t) + \
+ *     pInstParams->EQNB_NumBands * sizeof(LVEQNB_BiquadType_en) + \
+ *     2 * LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t) + \
+ *     PSA_InitParams.nBands * sizeof(Biquad_1I_Order2_Taps_t) + \
+ *     PSA_InitParams.nBands * sizeof(QPD_Taps_t)
+ *
+ * LVM_MEMREGION_PERSISTENT_FAST_COEF:
+ *   Total Memory size:
+ *     sizeof(LVM_TE_Coefs_t) + \
+ *     sizeof(LVCS_Coefficient_t) + \
+ *     sizeof(LVDBE_Coef_FLOAT_t) + \
+ *     sizeof(Biquad_FLOAT_Instance_t) + \
+ *     sizeof(Biquad_FLOAT_Instance_t) + \
+ *     pInstParams->EQNB_NumBands * sizeof(Biquad_FLOAT_Instance_t) + \
+ *     PSA_InitParams.nBands * sizeof(Biquad_Instance_t) + \
+ *     PSA_InitParams.nBands * sizeof(QPD_State_t)
+ *
+ * LVM_MEMREGION_TEMPORARY_FAST (Scratch):
+ *   Total Memory Size:
+ *     BundleScratchSize + \
+ *     MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_FLOAT) + \
+ *     MaxScratchOf (CS, EQNB, DBE, PSA)
+ *
+ *     a)BundleScratchSize:
+ *         3 * LVM_MAX_CHANNELS \
+ *         * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_FLOAT)
+ *       This Memory is allocated only when Buffer mode is LVM_MANAGED_BUFFER.
+ *     b)MaxScratchOf (CS, EQNB, DBE, PSA)
+ *       This Memory is needed for scratch usage for CS, EQNB, DBE, PSA.
+ *       CS   = (LVCS_SCRATCHBUFFERS * sizeof(LVM_FLOAT)
+ *               * pCapabilities->MaxBlockSize)
+ *       EQNB = (LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT)
+ *               * pCapabilities->MaxBlockSize)
+ *       DBE  = (LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_FLOAT)
+ *               * pCapabilities->MaxBlockSize)
+ *       PSA  = (2 * pInitParams->MaxInputBlockSize * sizeof(LVM_FLOAT))
+ *              one MaxInputBlockSize for input and another for filter output
+ *     c)MAX_INTERNAL_BLOCKSIZE
+ *       This Memory is needed for PSAInput - Temp memory to store output
+ *       from McToMono block and given as input to PSA block
+ */
+
+LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t         hInstance,
+                                       LVM_MemTab_t         *pMemoryTable,
+                                       LVM_InstParams_t     *pInstParams)
+{
+
+    LVM_Instance_t      *pInstance = (LVM_Instance_t *)hInstance;
+    LVM_UINT32          AlgScratchSize;
+    LVM_UINT32          BundleScratchSize;
+    LVM_UINT16          InternalBlockSize;
+    INST_ALLOC          AllocMem[LVM_NR_MEMORY_REGIONS];
+    LVM_INT16           i;
+
+    /*
+     * Check parameters
+     */
+    if(pMemoryTable == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*
+     * Return memory table if the instance has already been created
+     */
+    if (hInstance != LVM_NULL)
+    {
+       /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+        return(LVM_SUCCESS);
+    }
+
+    if(pInstParams == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*
+     *  Power Spectrum Analyser
+     */
+    if(pInstParams->PSA_Included > LVM_PSA_ON)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Check the instance parameters
+     */
+    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /* N-Band Equalizer */
+    if( pInstParams->EQNB_NumBands > 32 )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+    else
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+
+    /*
+    * Initialise the AllocMem structures
+    */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        InstAlloc_Init(&AllocMem[i], LVM_NULL);
+    }
+    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+
+    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+    }
+
+    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+    }
+
+    /*
+    * Bundle requirements
+    */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+        sizeof(LVM_Instance_t));
+
+    /*
+     * Set the algorithm and bundle scratch requirements
+     */
+    AlgScratchSize    = 0;
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        BundleScratchSize = 3 * LVM_MAX_CHANNELS \
+                            * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) \
+                            * sizeof(LVM_FLOAT);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],        /* Scratch buffer */
+                            BundleScratchSize);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                            sizeof(LVM_Buffer_t));
+    }
+
+    /*
+     * Treble Enhancement requirements
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                        sizeof(LVM_TE_Data_t));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                        sizeof(LVM_TE_Coefs_t));
+
+    /*
+     * N-Band Equalizer requirements
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* Local storage */
+                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* User storage */
+                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+    /*
+     * Concert Sound requirements
+     */
+    {
+        LVCS_MemTab_t           CS_MemTab;
+        LVCS_Capabilities_t     CS_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        CS_Capabilities.MaxBlockSize     = InternalBlockSize;
+
+        /*
+         * Get the memory requirements
+         */
+        LVCS_Memory(LVM_NULL,
+                    &CS_MemTab,
+                    &CS_Capabilities);
+
+        /*
+         * Update the memory allocation structures
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+    /*
+     * Dynamic Bass Enhancement requirements
+     */
+    {
+        LVDBE_MemTab_t          DBE_MemTab;
+        LVDBE_Capabilities_t    DBE_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
+                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
+                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
+                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
+                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
+                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
+                                           LVDBE_CAP_FS_192000;
+        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+        DBE_Capabilities.MaxBlockSize    = InternalBlockSize;
+
+        /*
+         * Get the memory requirements
+         */
+        LVDBE_Memory(LVM_NULL,
+                    &DBE_MemTab,
+
+                    &DBE_Capabilities);
+        /*
+         * Update the bundle table
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+    /*
+     * N-Band equaliser requirements
+     */
+    {
+        LVEQNB_MemTab_t         EQNB_MemTab;            /* For N-Band Equaliser */
+        LVEQNB_Capabilities_t   EQNB_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
+                                         LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
+                                         LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
+                                         LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
+                                         LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
+                                         LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
+                                         LVEQNB_CAP_FS_192000;
+        EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+        EQNB_Capabilities.MaxBlockSize = InternalBlockSize;
+        EQNB_Capabilities.MaxBands     = pInstParams->EQNB_NumBands;
+
+        /*
+         * Get the memory requirements
+         */
+        LVEQNB_Memory(LVM_NULL,
+                      &EQNB_MemTab,
+                      &EQNB_Capabilities);
+
+        /*
+         * Update the bundle table
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+    /*
+     * Headroom management memory allocation
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+    /*
+     * Spectrum Analyzer memory requirements
+     */
+    {
+        pLVPSA_Handle_t     hPSAInst = LVM_NULL;
+        LVPSA_MemTab_t      PSA_MemTab;
+        LVPSA_InitParams_t  PSA_InitParams;
+        LVPSA_FilterParam_t FiltersParams[9];
+        LVPSA_RETURN        PSA_Status;
+
+        if(pInstParams->PSA_Included == LVM_PSA_ON)
+        {
+            PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
+            PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 1000;
+            PSA_InitParams.nBands                       = (LVM_UINT16) 9;
+
+            PSA_InitParams.pFiltersParams = &FiltersParams[0];
+            for(i = 0; i < PSA_InitParams.nBands; i++)
+            {
+                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
+                FiltersParams[i].QFactor            = (LVM_UINT16) 25;
+                FiltersParams[i].PostGain           = (LVM_INT16)  0;
+            }
+
+            /*
+            * Get the memory requirements
+            */
+            PSA_Status = LVPSA_Memory (hPSAInst,
+                                        &PSA_MemTab,
+                                        &PSA_InitParams);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            /*
+            * Update the bundle table
+            */
+            /* Slow Data */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+            /* Fast Data */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+            /* Fast Coef */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+            /* Fast Temporary */
+            InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+                                MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_FLOAT));
+
+            if (PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size > AlgScratchSize)
+            {
+                AlgScratchSize = PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size;
+            }
+        }
+    }
+
+    /*
+     * Return the memory table
+     */
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size = 0;
+    }
+
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size = 0;
+    }
+
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                        AlgScratchSize);
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size             = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST]);
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Type             = LVM_TEMPORARY_FAST;
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].pBaseAddress     = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size = 0;
+    }
+
+    return(LVM_SUCCESS);
+
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetInstanceHandle                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to create a bundle instance. It returns the created instance  */
+/*  handle through phInstance. All parameters are set to their default, inactive state. */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  phInstance              pointer to the instance handle                              */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pInstParams             Pointer to the initialisation capabilities                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*  LVM_NULLADDRESS         When one of phInstance, pMemoryTable or pInstParams are NULL*/
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t           *phInstance,
+                                          LVM_MemTab_t           *pMemoryTable,
+                                          LVM_InstParams_t       *pInstParams)
+{
+
+    LVM_ReturnStatus_en     Status = LVM_SUCCESS;
+    LVM_Instance_t          *pInstance;
+    INST_ALLOC              AllocMem[LVM_NR_MEMORY_REGIONS];
+    LVM_INT16               i;
+    LVM_UINT16              InternalBlockSize;
+    LVM_INT32               BundleScratchSize;
+
+    /*
+     * Check valid points have been given
+     */
+    if ((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * Check the memory table for NULL pointers
+     */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        if ((pMemoryTable->Region[i].Size != 0) &&
+            (pMemoryTable->Region[i].pBaseAddress==LVM_NULL))
+        {
+            return(LVM_NULLADDRESS);
+        }
+    }
+
+    /*
+     * Check the instance parameters
+     */
+    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if( pInstParams->EQNB_NumBands > 32 )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+    else
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+
+    if(pInstParams->PSA_Included > LVM_PSA_ON)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Initialise the AllocMem structures
+     */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        InstAlloc_Init(&AllocMem[i],
+                       pMemoryTable->Region[i].pBaseAddress);
+    }
+
+    /*
+     * Set the instance handle
+     */
+    *phInstance  = (LVM_Handle_t)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                                                     sizeof(LVM_Instance_t));
+    pInstance =(LVM_Instance_t  *)*phInstance;
+
+    /*
+     * Save the memory table, parameters and capabilities
+     */
+    pInstance->MemoryTable    = *pMemoryTable;
+    pInstance->InstParams     = *pInstParams;
+
+    /*
+     * Set the bundle scratch memory and initialse the buffer management
+     */
+    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+    }
+
+    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+    }
+    pInstance->InternalBlockSize = (LVM_INT16)InternalBlockSize;
+
+    /*
+     * Common settings for managed and unmanaged buffers
+     */
+    pInstance->SamplesToProcess = 0;                /* No samples left to process */
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        /*
+         * Managed buffers required
+         */
+        pInstance->pBufferManagement = (LVM_Buffer_t *)
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                                                           sizeof(LVM_Buffer_t));
+        BundleScratchSize = (LVM_INT32)
+                            (3 * LVM_MAX_CHANNELS \
+                             * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) \
+                             * sizeof(LVM_FLOAT));
+        pInstance->pBufferManagement->pScratch = (LVM_FLOAT *)
+            InstAlloc_AddMember(
+                         &AllocMem[LVM_MEMREGION_TEMPORARY_FAST], /* Scratch 1 buffer */
+                                                  (LVM_UINT32)BundleScratchSize);
+        LoadConst_Float(0,                                   /* Clear the input delay buffer */
+                        (LVM_FLOAT *)&pInstance->pBufferManagement->InDelayBuffer,
+                        (LVM_INT16)(LVM_MAX_CHANNELS * MIN_INTERNAL_BLOCKSIZE));
+        pInstance->pBufferManagement->InDelaySamples = MIN_INTERNAL_BLOCKSIZE; /* Set the number of delay samples */
+        pInstance->pBufferManagement->OutDelaySamples = 0;                     /* No samples in the output buffer */
+        pInstance->pBufferManagement->BufferState = LVM_FIRSTCALL;             /* Set the state ready for the first call */
+    }
+
+    /*
+     * Set default parameters
+     */
+    pInstance->Params.OperatingMode    = LVM_MODE_OFF;
+    pInstance->Params.SampleRate       = LVM_FS_8000;
+    pInstance->Params.SourceFormat     = LVM_MONO;
+    pInstance->Params.SpeakerType      = LVM_HEADPHONES;
+    pInstance->Params.VC_EffectLevel   = 0;
+    pInstance->Params.VC_Balance       = 0;
+
+    /*
+     * Set callback
+     */
+    pInstance->CallBack = LVM_AlgoCallBack;
+
+    /*
+     * DC removal filter
+     */
+#ifdef SUPPORT_MC
+    DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#else
+    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#endif
+
+    /*
+     * Treble Enhancement
+     */
+    pInstance->pTE_Taps  = (LVM_TE_Data_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                sizeof(LVM_TE_Data_t));
+
+    pInstance->pTE_State = (LVM_TE_Coefs_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                 sizeof(LVM_TE_Coefs_t));
+    pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
+    pInstance->Params.TE_EffectLevel   = 0;
+    pInstance->TE_Active               = LVM_FALSE;
+
+    /*
+     * Set the volume control and initialise Current to Target
+     */
+    pInstance->VC_Volume.MixerStream[0].CallbackParam      = 0;
+    pInstance->VC_Volume.MixerStream[0].CallbackSet        = 0;
+    pInstance->VC_Volume.MixerStream[0].pCallbackHandle    = pInstance;
+    pInstance->VC_Volume.MixerStream[0].pCallBack          = LVM_VCCallBack;
+
+    /* In managed buffering, start with low signal level as delay in buffer management causes a click*/
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], 0, 0);
+    }
+    else
+    {
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
+    }
+
+    LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,LVM_FS_8000,2);
+
+    pInstance->VC_VolumedB                  = 0;
+    pInstance->VC_AVLFixedVolume            = 0;
+    pInstance->VC_Active                    = LVM_FALSE;
+
+    pInstance->VC_BalanceMix.MixerStream[0].CallbackParam      = 0;
+    pInstance->VC_BalanceMix.MixerStream[0].CallbackSet        = 0;
+    pInstance->VC_BalanceMix.MixerStream[0].pCallbackHandle    = pInstance;
+    pInstance->VC_BalanceMix.MixerStream[0].pCallBack          = LVM_VCCallBack;
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0], LVM_MAXFLOAT, LVM_MAXFLOAT);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+
+    pInstance->VC_BalanceMix.MixerStream[1].CallbackParam      = 0;
+    pInstance->VC_BalanceMix.MixerStream[1].CallbackSet        = 0;
+    pInstance->VC_BalanceMix.MixerStream[1].pCallbackHandle    = pInstance;
+    pInstance->VC_BalanceMix.MixerStream[1].pCallBack          = LVM_VCCallBack;
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1], LVM_MAXFLOAT, LVM_MAXFLOAT);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+
+    /*
+     * Set the default EQNB pre-gain and pointer to the band definitions
+     */
+    pInstance->pEQNB_BandDefs =
+        (LVM_EQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                   (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+    pInstance->pEQNB_UserDefs =
+        (LVM_EQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                   (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+    /*
+     * Initialise the Concert Sound module
+     */
+    {
+        LVCS_Handle_t           hCSInstance;                /* Instance handle */
+        LVCS_MemTab_t           CS_MemTab;                  /* Memory table */
+        LVCS_Capabilities_t     CS_Capabilities;            /* Initial capabilities */
+        LVCS_ReturnStatus_en    LVCS_Status;                /* Function call status */
+
+        /*
+         * Set default parameters
+         */
+        pInstance->Params.VirtualizerReverbLevel    = 100;
+        pInstance->Params.VirtualizerType           = LVM_CONCERTSOUND;
+        pInstance->Params.VirtualizerOperatingMode  = LVM_MODE_OFF;
+        pInstance->CS_Active                        = LVM_FALSE;
+
+        /*
+         * Set the initialisation capabilities
+         */
+        CS_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+        CS_Capabilities.CallBack = pInstance->CallBack;
+        CS_Capabilities.pBundleInstance = (void*)pInstance;
+
+        /*
+         * Get the memory requirements and then set the address pointers, forcing alignment
+         */
+        LVCS_Status = LVCS_Memory(LVM_NULL,                /* Get the memory requirements */
+                                  &CS_MemTab,
+                                  &CS_Capabilities);
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = &pInstance->CS_Instance;
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        CS_MemTab.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                         0);
+
+        /*
+         * Initialise the Concert Sound instance and save the instance handle
+         */
+        hCSInstance = LVM_NULL;                            /* Set to NULL to return handle */
+        LVCS_Status = LVCS_Init(&hCSInstance,              /* Initiailse */
+                                &CS_MemTab,
+                                &CS_Capabilities);
+        if (LVCS_Status != LVCS_SUCCESS) return((LVM_ReturnStatus_en)LVCS_Status);
+        pInstance->hCSInstance = hCSInstance;              /* Save the instance handle */
+
+    }
+
+    /*
+     * Initialise the Bass Enhancement module
+     */
+    {
+        LVDBE_Handle_t          hDBEInstance;               /* Instance handle */
+        LVDBE_MemTab_t          DBE_MemTab;                 /* Memory table */
+        LVDBE_Capabilities_t    DBE_Capabilities;           /* Initial capabilities */
+        LVDBE_ReturnStatus_en   LVDBE_Status;               /* Function call status */
+
+        /*
+         * Set the initialisation parameters
+         */
+        pInstance->Params.BE_OperatingMode = LVM_BE_OFF;
+        pInstance->Params.BE_CentreFreq    = LVM_BE_CENTRE_55Hz;
+        pInstance->Params.BE_EffectLevel   = 0;
+        pInstance->Params.BE_HPF           = LVM_BE_HPF_OFF;
+
+        pInstance->DBE_Active              = LVM_FALSE;
+
+        /*
+         * Set the initialisation capabilities
+         */
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
+                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
+                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
+                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
+                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
+                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
+                                           LVDBE_CAP_FS_192000;
+        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+        DBE_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+
+        /*
+         * Get the memory requirements and then set the address pointers
+         */
+        LVDBE_Status = LVDBE_Memory(LVM_NULL,               /* Get the memory requirements */
+                                    &DBE_MemTab,
+                                    &DBE_Capabilities);
+        DBE_MemTab.Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->DBE_Instance;
+        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size);
+        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size);
+        DBE_MemTab.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                      0);
+
+        /*
+         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+         */
+        hDBEInstance = LVM_NULL;                            /* Set to NULL to return handle */
+        LVDBE_Status = LVDBE_Init(&hDBEInstance,            /* Initiailse */
+                                  &DBE_MemTab,
+                                  &DBE_Capabilities);
+        if (LVDBE_Status != LVDBE_SUCCESS) return((LVM_ReturnStatus_en)LVDBE_Status);
+        pInstance->hDBEInstance = hDBEInstance;             /* Save the instance handle */
+    }
+
+    /*
+     * Initialise the N-Band Equaliser module
+     */
+    {
+        LVEQNB_Handle_t          hEQNBInstance;             /* Instance handle */
+        LVEQNB_MemTab_t          EQNB_MemTab;               /* Memory table */
+        LVEQNB_Capabilities_t    EQNB_Capabilities;         /* Initial capabilities */
+        LVEQNB_ReturnStatus_en   LVEQNB_Status;             /* Function call status */
+
+        /*
+         * Set the initialisation parameters
+         */
+        pInstance->Params.EQNB_OperatingMode   = LVM_EQNB_OFF;
+        pInstance->Params.EQNB_NBands          = 0;
+        pInstance->Params.pEQNB_BandDefinition = LVM_NULL;
+        pInstance->EQNB_Active                 = LVM_FALSE;
+
+        /*
+         * Set the initialisation capabilities
+         */
+        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
+                                            LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
+                                            LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
+                                            LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
+                                            LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
+                                            LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
+                                            LVEQNB_CAP_FS_192000;
+        EQNB_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+        EQNB_Capabilities.MaxBands        = pInstParams->EQNB_NumBands;
+        EQNB_Capabilities.SourceFormat    = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+        EQNB_Capabilities.CallBack        = pInstance->CallBack;
+        EQNB_Capabilities.pBundleInstance  = (void*)pInstance;
+
+        /*
+         * Get the memory requirements and then set the address pointers, forcing alignment
+         */
+        LVEQNB_Status = LVEQNB_Memory(LVM_NULL,             /* Get the memory requirements */
+                                      &EQNB_MemTab,
+                                      &EQNB_Capabilities);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->EQNB_Instance;
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                        0);
+
+        /*
+         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+         */
+        hEQNBInstance = LVM_NULL;                           /* Set to NULL to return handle */
+        LVEQNB_Status = LVEQNB_Init(&hEQNBInstance,         /* Initiailse */
+                                    &EQNB_MemTab,
+                                    &EQNB_Capabilities);
+        if (LVEQNB_Status != LVEQNB_SUCCESS) return((LVM_ReturnStatus_en)LVEQNB_Status);
+        pInstance->hEQNBInstance = hEQNBInstance;           /* Save the instance handle */
+    }
+
+    /*
+     * Headroom management memory allocation
+     */
+    {
+        pInstance->pHeadroom_BandDefs = (LVM_HeadroomBandDef_t *)
+              InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+        pInstance->pHeadroom_UserDefs = (LVM_HeadroomBandDef_t *)
+              InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+        /* Headroom management parameters initialisation */
+        pInstance->NewHeadroomParams.NHeadroomBands = 2;
+        pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_Low          = 20;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_High         = 4999;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Headroom_Offset    = 3;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_Low          = 5000;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_High         = 24000;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Headroom_Offset    = 4;
+        pInstance->NewHeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
+
+        pInstance->Headroom =0;
+    }
+
+    /*
+     * Initialise the PSA module
+     */
+    {
+        pLVPSA_Handle_t     hPSAInstance = LVM_NULL;   /* Instance handle */
+        LVPSA_MemTab_t      PSA_MemTab;
+        LVPSA_RETURN        PSA_Status;                 /* Function call status */
+        LVPSA_FilterParam_t FiltersParams[9];
+
+        if(pInstParams->PSA_Included==LVM_PSA_ON)
+        {
+            pInstance->PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
+            pInstance->PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 2048;
+            pInstance->PSA_InitParams.nBands                       = (LVM_UINT16) 9;
+            pInstance->PSA_InitParams.pFiltersParams               = &FiltersParams[0];
+            for(i = 0; i < pInstance->PSA_InitParams.nBands; i++)
+            {
+                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
+                FiltersParams[i].QFactor            = (LVM_UINT16) 100;
+                FiltersParams[i].PostGain           = (LVM_INT16)  0;
+            }
+
+            /*Get the memory requirements and then set the address pointers*/
+            PSA_Status = LVPSA_Memory (hPSAInstance,
+                                          &PSA_MemTab,
+                                          &pInstance->PSA_InitParams);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            /* Slow Data */
+            PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+            /* Fast Data */
+            PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+            /* Fast Coef */
+            PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+            /* Fast Temporary */
+            pInstance->pPSAInput = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+                                                       (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * \
+                                                       sizeof(LVM_FLOAT));
+            PSA_MemTab.Region[LVM_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],0);
+
+            /*Initialise PSA instance and save the instance handle*/
+            pInstance->PSA_ControlParams.Fs = LVM_FS_48000;
+            pInstance->PSA_ControlParams.LevelDetectionSpeed  = LVPSA_SPEED_MEDIUM;
+            PSA_Status = LVPSA_Init (&hPSAInstance,
+                                    &pInstance->PSA_InitParams,
+                                    &pInstance->PSA_ControlParams,
+                                    &PSA_MemTab);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            pInstance->hPSAInstance = hPSAInstance;       /* Save the instance handle */
+            pInstance->PSA_GainOffset = 0;
+        }
+        else
+        {
+            pInstance->hPSAInstance = LVM_NULL;
+        }
+
+        /*
+         * Set the initialisation parameters.
+         */
+        pInstance->Params.PSA_PeakDecayRate   = LVM_PSA_SPEED_MEDIUM;
+        pInstance->Params.PSA_Enable          = LVM_PSA_OFF;
+    }
+
+    /*
+     * Copy the initial parameters to the new parameters for correct readback of
+     * the settings.
+     */
+    pInstance->NewParams = pInstance->Params;
+
+    /*
+     * Create configuration number
+     */
+    pInstance->ConfigurationNumber = 0x00000000;
+    pInstance->ConfigurationNumber += LVM_CS_MASK;
+    pInstance->ConfigurationNumber += LVM_EQNB_MASK;
+    pInstance->ConfigurationNumber += LVM_DBE_MASK;
+    pInstance->ConfigurationNumber += LVM_VC_MASK;
+    pInstance->ConfigurationNumber += LVM_PSA_MASK;
+
+    if(((pInstance->ConfigurationNumber  & LVM_CS_MASK)!=0)  ||
+        ((pInstance->ConfigurationNumber & LVM_DBE_MASK)!=0) ||
+        ((pInstance->ConfigurationNumber & LVM_EQNB_MASK)!=0)||
+        ((pInstance->ConfigurationNumber & LVM_TE_MASK)!=0)  ||
+        ((pInstance->ConfigurationNumber & LVM_VC_MASK)!=0))
+    {
+        pInstance->BlickSizeMultiple    = 4;
+    }
+    else
+    {
+        pInstance->BlickSizeMultiple    = 1;
+    }
+
+    return(Status);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_ClearAudioBuffers                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to clear the internal audio buffers of the bundle.            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_NULLADDRESS         Instance or scratch memory has a NULL pointer               */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t  hInstance)
+{
+    LVM_MemTab_t            MemTab;                                     /* Memory table */
+    LVM_InstParams_t        InstParams;                                 /* Instance parameters */
+    LVM_ControlParams_t     Params;                                     /* Control Parameters */
+    LVM_Instance_t          *pInstance  = (LVM_Instance_t  *)hInstance; /* Pointer to Instance */
+    LVM_HeadroomParams_t    HeadroomParams;
+
+    if(hInstance == LVM_NULL){
+        return LVM_NULLADDRESS;
+    }
+
+    /* Save the control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+    LVM_GetControlParameters(hInstance, &Params);
+
+    /*Save the headroom parameters*/
+    LVM_GetHeadroomParams(hInstance, &HeadroomParams);
+
+    /*  Retrieve allocated buffers in memtab */
+    LVM_GetMemoryTable(hInstance, &MemTab,  LVM_NULL);
+
+    /*  Save the instance parameters */
+    InstParams = pInstance->InstParams;
+
+    /*  Call  LVM_GetInstanceHandle to re-initialise the bundle */
+    LVM_GetInstanceHandle( &hInstance,
+                           &MemTab,
+                           &InstParams);
+
+    /* Restore control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+    LVM_SetControlParameters(hInstance, &Params);
+
+    /*Restore the headroom parameters*/
+    LVM_SetHeadroomParams(hInstance, &HeadroomParams);
+
+    /* DC removal filter */
+#ifdef SUPPORT_MC
+    DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#else
+    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#endif
+
+    return LVM_SUCCESS;
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index cdd3134..ddaac99 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -27,11 +27,6 @@
 #ifndef __LVM_PRIVATE_H__
 #define __LVM_PRIVATE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Includes                                                                        */
@@ -47,7 +42,6 @@
 #include "LVEQNB_Private.h"                     /* N-Band equaliser */
 #include "LVPSA_Private.h"                      /* Parametric Spectrum Analyzer */
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Defines                                                                         */
@@ -113,7 +107,6 @@
 #define LVM_TE_MASK                     32
 #define LVM_PSA_MASK                    2048
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Structures                                                                      */
@@ -129,16 +122,13 @@
     void                    *pBaseAddress;      /* Pointer to the region base address */
 } LVM_IntMemoryRegion_t;
 
-
 /* Memory table containing the region definitions */
 typedef struct
 {
     LVM_IntMemoryRegion_t   Region[LVM_NR_MEMORY_REGIONS];  /* One definition for each region */
 } LVM_IntMemTab_t;
 
-
 /* Buffer Management */
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT               *pScratch;          /* Bundle scratch buffer */
@@ -161,39 +151,17 @@
                                                                              left and right */
     LVM_INT16               SamplesToOutput;    /* Samples to write to the output */
 } LVM_Buffer_t;
-#else
-typedef struct
-{
-    LVM_INT16               *pScratch;          /* Bundle scratch buffer */
-
-    LVM_INT16               BufferState;        /* Buffer status */
-    LVM_INT16               InDelayBuffer[6*MIN_INTERNAL_BLOCKSIZE]; /* Input buffer delay line, left and right */
-    LVM_INT16               InDelaySamples;     /* Number of samples in the input delay buffer */
-
-    LVM_INT16               OutDelayBuffer[2*MIN_INTERNAL_BLOCKSIZE]; /* Output buffer delay line */
-    LVM_INT16               OutDelaySamples;    /* Number of samples in the output delay buffer, left and right */
-    LVM_INT16               SamplesToOutput;    /* Samples to write to the output */
-} LVM_Buffer_t;
-#endif
 
 /* Filter taps */
 typedef struct
 {
-#ifdef BUILD_FLOAT
     Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps;   /* Treble boost Taps */
-#else
-    Biquad_2I_Order1_Taps_t TrebleBoost_Taps;   /* Treble boost Taps */
-#endif
 } LVM_TE_Data_t;
 
 /* Coefficients */
 typedef struct
 {
-#ifdef BUILD_FLOAT
     Biquad_FLOAT_Instance_t       TrebleBoost_State;  /* State for the treble boost filter */
-#else
-    Biquad_Instance_t       TrebleBoost_State;  /* State for the treble boost filter */
-#endif
 } LVM_TE_Coefs_t;
 
 typedef struct
@@ -211,24 +179,15 @@
     LVM_INT16               InternalBlockSize;  /* Maximum internal block size */
     LVM_Buffer_t            *pBufferManagement; /* Buffer management variables */
     LVM_INT16               SamplesToProcess;   /* Input samples left to process */
-#ifdef BUILD_FLOAT
     LVM_FLOAT               *pInputSamples;     /* External input sample pointer */
     LVM_FLOAT               *pOutputSamples;    /* External output sample pointer */
-#else
-    LVM_INT16               *pInputSamples;     /* External input sample pointer */
-    LVM_INT16               *pOutputSamples;    /* External output sample pointer */
-#endif
 
     /* Configuration number */
     LVM_INT32               ConfigurationNumber;
     LVM_INT32               BlickSizeMultiple;
 
     /* DC removal */
-#ifdef BUILD_FLOAT
     Biquad_FLOAT_Instance_t       DC_RemovalInstance; /* DC removal filter instance */
-#else
-    Biquad_Instance_t       DC_RemovalInstance; /* DC removal filter instance */
-#endif
 
     /* Concert Sound */
     LVCS_Handle_t           hCSInstance;        /* Concert Sound instance handle */
@@ -248,16 +207,8 @@
     LVM_INT16               DBE_Active;         /* Control flag */
 
     /* Volume Control */
-#ifdef BUILD_FLOAT
     LVMixer3_1St_FLOAT_st   VC_Volume;          /* Volume scaler */
-#else
-    LVMixer3_1St_st         VC_Volume;          /* Volume scaler */
-#endif
-#ifdef BUILD_FLOAT
     LVMixer3_2St_FLOAT_st         VC_BalanceMix;      /* VC balance mixer */
-#else
-    LVMixer3_2St_st         VC_BalanceMix;      /* VC balance mixer */
-#endif
     LVM_INT16               VC_VolumedB;        /* Gain in dB */
     LVM_INT16               VC_Active;          /* Control flag */
     LVM_INT16               VC_AVLFixedVolume;  /* AVL fixed volume */
@@ -281,11 +232,7 @@
     LVPSA_ControlParams_t   PSA_ControlParams;  /* Spectrum Analyzer control parameters */
     LVM_INT16               PSA_GainOffset;     /* Tone control flag */
     LVM_Callback            CallBack;
-#ifdef BUILD_FLOAT
     LVM_FLOAT               *pPSAInput;         /* PSA input pointer */
-#else
-    LVM_INT16               *pPSAInput;         /* PSA input pointer */
-#endif
 
     LVM_INT16              NoSmoothVolume;      /* Enable or disable smooth volume changes*/
 
@@ -296,7 +243,6 @@
 
 } LVM_Instance_t;
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Function Prototypes                                                             */
@@ -317,36 +263,18 @@
 
 void    LVM_SetHeadroom(    LVM_Instance_t         *pInstance,
                             LVM_ControlParams_t    *pParams);
-#ifdef BUILD_FLOAT
 void    LVM_BufferIn(   LVM_Handle_t      hInstance,
                         const LVM_FLOAT   *pInData,
                         LVM_FLOAT         **pToProcess,
                         LVM_FLOAT         **pProcessed,
                         LVM_UINT16        *pNumSamples);
-#else
-void    LVM_BufferIn(   LVM_Handle_t      hInstance,
-                        const LVM_INT16   *pInData,
-                        LVM_INT16         **pToProcess,
-                        LVM_INT16         **pProcessed,
-                        LVM_UINT16        *pNumSamples);
-#endif
-#ifdef BUILD_FLOAT
 void    LVM_BufferOut(  LVM_Handle_t     hInstance,
                         LVM_FLOAT        *pOutData,
                         LVM_UINT16       *pNumSamples);
-#else
-void    LVM_BufferOut(  LVM_Handle_t     hInstance,
-                        LVM_INT16        *pOutData,
-                        LVM_UINT16       *pNumSamples);
-#endif
 
 LVM_INT32 LVM_AlgoCallBack(     void          *pBundleHandle,
                                 void          *pData,
                                 LVM_INT16     callbackId);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif      /* __LVM_PRIVATE_H__ */
 
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
deleted file mode 100644
index bc666a9..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include <system/audio.h>
-
-#include "LVM_Private.h"
-#include "VectorArithmetic.h"
-#include "LVM_Coeffs.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVM_Process                                                 */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Process function for the LifeVibes module.                                          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pInData                 Pointer to the input data                                   */
-/*  pOutData                Pointer to the output data                                  */
-/*  NumSamples              Number of samples in the input buffer                       */
-/*  AudioTime               Audio Time of the current input buffer in ms                */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_SUCCESS            Succeeded                                                    */
-/*  LVM_INVALIDNUMSAMPLES  When the NumSamples is not a valied multiple in unmanaged    */
-/*                         buffer mode                                                  */
-/*  LVM_ALIGNMENTERROR     When either the input our output buffers are not 32-bit      */
-/*                         aligned in unmanaged mode                                    */
-/*  LVM_NULLADDRESS        When one of hInstance, pInData or pOutData is NULL           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
-                                const LVM_FLOAT             *pInData,
-                                LVM_FLOAT                   *pOutData,
-                                LVM_UINT16                  NumSamples,
-                                LVM_UINT32                  AudioTime)
-{
-
-    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
-    LVM_UINT16          SampleCount = NumSamples;
-    LVM_FLOAT           *pInput     = (LVM_FLOAT *)pInData;
-    LVM_FLOAT           *pToProcess = (LVM_FLOAT *)pInData;
-    LVM_FLOAT           *pProcessed = pOutData;
-    LVM_ReturnStatus_en  Status;
-#ifdef SUPPORT_MC
-    LVM_INT32           NrChannels  = pInstance->NrChannels;
-    LVM_INT32           ChMask      = pInstance->ChMask;
-#define NrFrames SampleCount  // alias for clarity
-#endif
-
-    /*
-     * Check if the number of samples is zero
-     */
-    if (NumSamples == 0)
-    {
-        return(LVM_SUCCESS);
-    }
-
-
-    /*
-     * Check valid points have been given
-     */
-    if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    /*
-     * For unmanaged mode only
-     */
-    if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
-    {
-         /*
-         * Check if the number of samples is a good multiple (unmanaged mode only)
-         */
-        if((NumSamples % pInstance->BlickSizeMultiple) != 0)
-        {
-            return(LVM_INVALIDNUMSAMPLES);
-        }
-
-        /*
-         * Check the buffer alignment
-         */
-        if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
-        {
-            return(LVM_ALIGNMENTERROR);
-        }
-    }
-
-
-    /*
-     * Update new parameters if necessary
-     */
-    if (pInstance->ControlPending == LVM_TRUE)
-    {
-        Status = LVM_ApplyNewSettings(hInstance);
-#ifdef SUPPORT_MC
-        /* Update the local variable NrChannels from pInstance->NrChannels value */
-        NrChannels = pInstance->NrChannels;
-        ChMask     = pInstance->ChMask;
-#endif
-
-        if(Status != LVM_SUCCESS)
-        {
-            return Status;
-        }
-    }
-
-
-    /*
-     * Convert from Mono if necessary
-     */
-    if (pInstance->Params.SourceFormat == LVM_MONO)
-    {
-        MonoTo2I_Float(pInData,                                /* Source */
-                       pOutData,                               /* Destination */
-                       (LVM_INT16)NumSamples);                 /* Number of input samples */
-        pInput     = pOutData;
-        pToProcess = pOutData;
-#ifdef SUPPORT_MC
-        NrChannels = 2;
-        ChMask     = AUDIO_CHANNEL_OUT_STEREO;
-#endif
-    }
-
-
-    /*
-     * Process the data with managed buffers
-     */
-    while (SampleCount != 0)
-    {
-        /*
-         * Manage the input buffer and frame processing
-         */
-        LVM_BufferIn(hInstance,
-                     pInput,
-                     &pToProcess,
-                     &pProcessed,
-                     &SampleCount);
-
-        /*
-         * Only process data when SampleCount is none zero, a zero count can occur when
-         * the BufferIn routine is working in managed mode.
-         */
-        if (SampleCount != 0)
-        {
-            /*
-             * Apply ConcertSound if required
-             */
-            if (pInstance->CS_Active == LVM_TRUE)
-            {
-                (void)LVCS_Process(pInstance->hCSInstance,     /* Concert Sound instance handle */
-                                   pToProcess,
-                                   pProcessed,
-                                   SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Apply volume if required
-             */
-            if (pInstance->VC_Active!=0)
-            {
-#ifdef SUPPORT_MC
-                LVC_MixSoft_Mc_D16C31_SAT(&pInstance->VC_Volume,
-                                       pToProcess,
-                                       pProcessed,
-                                       (LVM_INT16)(NrFrames),
-                                       NrChannels);
-#else
-                LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
-                                       pToProcess,
-                                       pProcessed,
-                                       (LVM_INT16)(2 * SampleCount));     /* Left and right*/
-#endif
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Call N-Band equaliser if enabled
-             */
-            if (pInstance->EQNB_Active == LVM_TRUE)
-            {
-                LVEQNB_Process(pInstance->hEQNBInstance,    /* N-Band equaliser instance handle */
-                               pToProcess,
-                               pProcessed,
-                               SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Call bass enhancement if enabled
-             */
-            if (pInstance->DBE_Active == LVM_TRUE)
-            {
-                LVDBE_Process(pInstance->hDBEInstance,       /* Dynamic Bass Enhancement \
-                                                                instance handle */
-                              pToProcess,
-                              pProcessed,
-                              SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Bypass mode or everything off, so copy the input to the output
-             */
-            if (pToProcess != pProcessed)
-            {
-#ifdef SUPPORT_MC
-                Copy_Float(pToProcess,                             /* Source */
-                           pProcessed,                             /* Destination */
-                           (LVM_INT16)(NrChannels * NrFrames));    /* Copy all samples */
-#else
-                Copy_Float(pToProcess,                             /* Source */
-                           pProcessed,                             /* Destination */
-                           (LVM_INT16)(2 * SampleCount));          /* Left and right */
-#endif
-            }
-
-            /*
-             * Apply treble boost if required
-             */
-            if (pInstance->TE_Active == LVM_TRUE)
-            {
-                /*
-                 * Apply the filter
-                 */
-#ifdef SUPPORT_MC
-                FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
-                                           pProcessed,
-                                           pProcessed,
-                                           (LVM_INT16)NrFrames,
-                                           (LVM_INT16)NrChannels);
-#else
-                FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
-                                           pProcessed,
-                                           pProcessed,
-                                           (LVM_INT16)SampleCount);
-#endif
-
-            }
-#ifdef SUPPORT_MC
-            /*
-             * Volume balance
-             */
-            LVC_MixSoft_1St_MC_float_SAT(&pInstance->VC_BalanceMix,
-                                          pProcessed,
-                                          pProcessed,
-                                          NrFrames,
-                                          NrChannels,
-                                          ChMask);
-#else
-            /*
-             * Volume balance
-             */
-            LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
-                                          pProcessed,
-                                          pProcessed,
-                                          SampleCount);
-#endif
-
-            /*
-             * Perform Parametric Spectum Analysis
-             */
-            if ((pInstance->Params.PSA_Enable == LVM_PSA_ON) &&
-                                            (pInstance->InstParams.PSA_Included == LVM_PSA_ON))
-            {
-#ifdef SUPPORT_MC
-                FromMcToMono_Float(pProcessed,
-                                   pInstance->pPSAInput,
-                                   (LVM_INT16)(NrFrames),
-                                   NrChannels);
-#else
-                From2iToMono_Float(pProcessed,
-                                   pInstance->pPSAInput,
-                                   (LVM_INT16)(SampleCount));
-#endif
-
-                LVPSA_Process(pInstance->hPSAInstance,
-                        pInstance->pPSAInput,
-                        (LVM_UINT16)(SampleCount),
-                        AudioTime);
-            }
-
-            /*
-             * DC removal
-             */
-#ifdef SUPPORT_MC
-            DC_Mc_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
-                                 pProcessed,
-                                 pProcessed,
-                                 (LVM_INT16)NrFrames,
-                                 NrChannels);
-#else
-            DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
-                                 pProcessed,
-                                 pProcessed,
-                                 (LVM_INT16)SampleCount);
-#endif
-        }
-        /*
-         * Manage the output buffer
-         */
-        LVM_BufferOut(hInstance,
-                      pOutData,
-                      &SampleCount);
-
-    }
-
-    return(LVM_SUCCESS);
-}
-#else
-LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
-                                const LVM_INT16             *pInData,
-                                LVM_INT16                   *pOutData,
-                                LVM_UINT16                  NumSamples,
-                                LVM_UINT32                  AudioTime)
-{
-
-    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
-    LVM_UINT16          SampleCount = NumSamples;
-    LVM_INT16           *pInput     = (LVM_INT16 *)pInData;
-    LVM_INT16           *pToProcess = (LVM_INT16 *)pInData;
-    LVM_INT16           *pProcessed = pOutData;
-    LVM_ReturnStatus_en  Status;
-
-    /*
-     * Check if the number of samples is zero
-     */
-    if (NumSamples == 0)
-    {
-        return(LVM_SUCCESS);
-    }
-
-
-    /*
-     * Check valid points have been given
-     */
-    if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
-    {
-        return (LVM_NULLADDRESS);
-    }
-
-    /*
-     * For unmanaged mode only
-     */
-    if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
-    {
-         /*
-         * Check if the number of samples is a good multiple (unmanaged mode only)
-         */
-        if((NumSamples % pInstance->BlickSizeMultiple) != 0)
-        {
-            return(LVM_INVALIDNUMSAMPLES);
-        }
-
-        /*
-         * Check the buffer alignment
-         */
-        if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
-        {
-            return(LVM_ALIGNMENTERROR);
-        }
-    }
-
-
-    /*
-     * Update new parameters if necessary
-     */
-    if (pInstance->ControlPending == LVM_TRUE)
-    {
-        Status = LVM_ApplyNewSettings(hInstance);
-
-        if(Status != LVM_SUCCESS)
-        {
-            return Status;
-        }
-    }
-
-
-    /*
-     * Convert from Mono if necessary
-     */
-    if (pInstance->Params.SourceFormat == LVM_MONO)
-    {
-        MonoTo2I_16(pInData,                                /* Source */
-                    pOutData,                               /* Destination */
-                    (LVM_INT16)NumSamples);                 /* Number of input samples */
-        pInput     = pOutData;
-        pToProcess = pOutData;
-    }
-
-
-    /*
-     * Process the data with managed buffers
-     */
-    while (SampleCount != 0)
-    {
-        /*
-         * Manage the input buffer and frame processing
-         */
-        LVM_BufferIn(hInstance,
-                     pInput,
-                     &pToProcess,
-                     &pProcessed,
-                     &SampleCount);
-
-        /*
-         * Only process data when SampleCount is none zero, a zero count can occur when
-         * the BufferIn routine is working in managed mode.
-         */
-        if (SampleCount != 0)
-        {
-
-            /*
-             * Apply ConcertSound if required
-             */
-            if (pInstance->CS_Active == LVM_TRUE)
-            {
-                (void)LVCS_Process(pInstance->hCSInstance,          /* Concert Sound instance handle */
-                                   pToProcess,
-                                   pProcessed,
-                                   SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Apply volume if required
-             */
-            if (pInstance->VC_Active!=0)
-            {
-                LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
-                                       pToProcess,
-                                       pProcessed,
-                                       (LVM_INT16)(2*SampleCount));     /* Left and right*/
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Call N-Band equaliser if enabled
-             */
-            if (pInstance->EQNB_Active == LVM_TRUE)
-            {
-                LVEQNB_Process(pInstance->hEQNBInstance,        /* N-Band equaliser instance handle */
-                               pToProcess,
-                               pProcessed,
-                               SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Call bass enhancement if enabled
-             */
-            if (pInstance->DBE_Active == LVM_TRUE)
-            {
-                LVDBE_Process(pInstance->hDBEInstance,          /* Dynamic Bass Enhancement instance handle */
-                              pToProcess,
-                              pProcessed,
-                              SampleCount);
-                pToProcess = pProcessed;
-            }
-
-            /*
-             * Bypass mode or everything off, so copy the input to the output
-             */
-            if (pToProcess != pProcessed)
-            {
-                Copy_16(pToProcess,                             /* Source */
-                        pProcessed,                             /* Destination */
-                        (LVM_INT16)(2*SampleCount));            /* Left and right */
-            }
-
-            /*
-             * Apply treble boost if required
-             */
-            if (pInstance->TE_Active == LVM_TRUE)
-            {
-                /*
-                 * Apply the filter
-                 */
-                FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
-                                           pProcessed,
-                                           pProcessed,
-                                           (LVM_INT16)SampleCount);
-
-            }
-
-            /*
-             * Volume balance
-             */
-            LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
-                                            pProcessed,
-                                            pProcessed,
-                                            SampleCount);
-
-            /*
-             * Perform Parametric Spectum Analysis
-             */
-            if ((pInstance->Params.PSA_Enable == LVM_PSA_ON)&&(pInstance->InstParams.PSA_Included==LVM_PSA_ON))
-            {
-                    From2iToMono_16(pProcessed,
-                             pInstance->pPSAInput,
-                            (LVM_INT16) (SampleCount));
-
-                    LVPSA_Process(pInstance->hPSAInstance,
-                            pInstance->pPSAInput,
-                            (LVM_UINT16) (SampleCount),
-                            AudioTime);
-            }
-
-
-            /*
-             * DC removal
-             */
-            DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
-                                 pProcessed,
-                                 pProcessed,
-                                 (LVM_INT16)SampleCount);
-
-
-        }
-
-        /*
-         * Manage the output buffer
-         */
-        LVM_BufferOut(hInstance,
-                      pOutData,
-                      &SampleCount);
-
-    }
-
-    return(LVM_SUCCESS);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
new file mode 100644
index 0000000..dc86cfd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include <system/audio.h>
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+#include "LVM_Coeffs.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_Process                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LifeVibes module.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*  AudioTime               Audio Time of the current input buffer in ms                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS            Succeeded                                                    */
+/*  LVM_INVALIDNUMSAMPLES  When the NumSamples is not a valied multiple in unmanaged    */
+/*                         buffer mode                                                  */
+/*  LVM_ALIGNMENTERROR     When either the input our output buffers are not 32-bit      */
+/*                         aligned in unmanaged mode                                    */
+/*  LVM_NULLADDRESS        When one of hInstance, pInData or pOutData is NULL           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
+                                const LVM_FLOAT             *pInData,
+                                LVM_FLOAT                   *pOutData,
+                                LVM_UINT16                  NumSamples,
+                                LVM_UINT32                  AudioTime)
+{
+
+    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_UINT16          SampleCount = NumSamples;
+    LVM_FLOAT           *pInput     = (LVM_FLOAT *)pInData;
+    LVM_FLOAT           *pToProcess = (LVM_FLOAT *)pInData;
+    LVM_FLOAT           *pProcessed = pOutData;
+    LVM_ReturnStatus_en  Status;
+#ifdef SUPPORT_MC
+    LVM_INT32           NrChannels  = pInstance->NrChannels;
+    LVM_INT32           ChMask      = pInstance->ChMask;
+#define NrFrames SampleCount  // alias for clarity
+#endif
+
+    /*
+     * Check if the number of samples is zero
+     */
+    if (NumSamples == 0)
+    {
+        return(LVM_SUCCESS);
+    }
+
+    /*
+     * Check valid points have been given
+     */
+    if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * For unmanaged mode only
+     */
+    if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
+    {
+         /*
+         * Check if the number of samples is a good multiple (unmanaged mode only)
+         */
+        if((NumSamples % pInstance->BlickSizeMultiple) != 0)
+        {
+            return(LVM_INVALIDNUMSAMPLES);
+        }
+
+        /*
+         * Check the buffer alignment
+         */
+        if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
+        {
+            return(LVM_ALIGNMENTERROR);
+        }
+    }
+
+    /*
+     * Update new parameters if necessary
+     */
+    if (pInstance->ControlPending == LVM_TRUE)
+    {
+        Status = LVM_ApplyNewSettings(hInstance);
+#ifdef SUPPORT_MC
+        /* Update the local variable NrChannels from pInstance->NrChannels value */
+        NrChannels = pInstance->NrChannels;
+        ChMask     = pInstance->ChMask;
+#endif
+
+        if(Status != LVM_SUCCESS)
+        {
+            return Status;
+        }
+    }
+
+    /*
+     * Convert from Mono if necessary
+     */
+    if (pInstance->Params.SourceFormat == LVM_MONO)
+    {
+        MonoTo2I_Float(pInData,                                /* Source */
+                       pOutData,                               /* Destination */
+                       (LVM_INT16)NumSamples);                 /* Number of input samples */
+        pInput     = pOutData;
+        pToProcess = pOutData;
+#ifdef SUPPORT_MC
+        NrChannels = 2;
+        ChMask     = AUDIO_CHANNEL_OUT_STEREO;
+#endif
+    }
+
+    /*
+     * Process the data with managed buffers
+     */
+    while (SampleCount != 0)
+    {
+        /*
+         * Manage the input buffer and frame processing
+         */
+        LVM_BufferIn(hInstance,
+                     pInput,
+                     &pToProcess,
+                     &pProcessed,
+                     &SampleCount);
+
+        /*
+         * Only process data when SampleCount is none zero, a zero count can occur when
+         * the BufferIn routine is working in managed mode.
+         */
+        if (SampleCount != 0)
+        {
+            /*
+             * Apply ConcertSound if required
+             */
+            if (pInstance->CS_Active == LVM_TRUE)
+            {
+                (void)LVCS_Process(pInstance->hCSInstance,     /* Concert Sound instance handle */
+                                   pToProcess,
+                                   pProcessed,
+                                   SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Apply volume if required
+             */
+            if (pInstance->VC_Active!=0)
+            {
+#ifdef SUPPORT_MC
+                LVC_MixSoft_Mc_D16C31_SAT(&pInstance->VC_Volume,
+                                       pToProcess,
+                                       pProcessed,
+                                       (LVM_INT16)(NrFrames),
+                                       NrChannels);
+#else
+                LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
+                                       pToProcess,
+                                       pProcessed,
+                                       (LVM_INT16)(2 * SampleCount));     /* Left and right*/
+#endif
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call N-Band equaliser if enabled
+             */
+            if (pInstance->EQNB_Active == LVM_TRUE)
+            {
+                LVEQNB_Process(pInstance->hEQNBInstance,    /* N-Band equaliser instance handle */
+                               pToProcess,
+                               pProcessed,
+                               SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call bass enhancement if enabled
+             */
+            if (pInstance->DBE_Active == LVM_TRUE)
+            {
+                LVDBE_Process(pInstance->hDBEInstance,       /* Dynamic Bass Enhancement \
+                                                                instance handle */
+                              pToProcess,
+                              pProcessed,
+                              SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Bypass mode or everything off, so copy the input to the output
+             */
+            if (pToProcess != pProcessed)
+            {
+#ifdef SUPPORT_MC
+                Copy_Float(pToProcess,                             /* Source */
+                           pProcessed,                             /* Destination */
+                           (LVM_INT16)(NrChannels * NrFrames));    /* Copy all samples */
+#else
+                Copy_Float(pToProcess,                             /* Source */
+                           pProcessed,                             /* Destination */
+                           (LVM_INT16)(2 * SampleCount));          /* Left and right */
+#endif
+            }
+
+            /*
+             * Apply treble boost if required
+             */
+            if (pInstance->TE_Active == LVM_TRUE)
+            {
+                /*
+                 * Apply the filter
+                 */
+#ifdef SUPPORT_MC
+                FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+                                           pProcessed,
+                                           pProcessed,
+                                           (LVM_INT16)NrFrames,
+                                           (LVM_INT16)NrChannels);
+#else
+                FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+                                           pProcessed,
+                                           pProcessed,
+                                           (LVM_INT16)SampleCount);
+#endif
+
+            }
+#ifdef SUPPORT_MC
+            /*
+             * Volume balance
+             */
+            LVC_MixSoft_1St_MC_float_SAT(&pInstance->VC_BalanceMix,
+                                          pProcessed,
+                                          pProcessed,
+                                          NrFrames,
+                                          NrChannels,
+                                          ChMask);
+#else
+            /*
+             * Volume balance
+             */
+            LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+                                          pProcessed,
+                                          pProcessed,
+                                          SampleCount);
+#endif
+
+            /*
+             * Perform Parametric Spectum Analysis
+             */
+            if ((pInstance->Params.PSA_Enable == LVM_PSA_ON) &&
+                                            (pInstance->InstParams.PSA_Included == LVM_PSA_ON))
+            {
+#ifdef SUPPORT_MC
+                FromMcToMono_Float(pProcessed,
+                                   pInstance->pPSAInput,
+                                   (LVM_INT16)(NrFrames),
+                                   NrChannels);
+#else
+                From2iToMono_Float(pProcessed,
+                                   pInstance->pPSAInput,
+                                   (LVM_INT16)(SampleCount));
+#endif
+
+                LVPSA_Process(pInstance->hPSAInstance,
+                        pInstance->pPSAInput,
+                        (LVM_UINT16)(SampleCount),
+                        AudioTime);
+            }
+
+            /*
+             * DC removal
+             */
+#ifdef SUPPORT_MC
+            DC_Mc_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+                                 pProcessed,
+                                 pProcessed,
+                                 (LVM_INT16)NrFrames,
+                                 NrChannels);
+#else
+            DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+                                 pProcessed,
+                                 pProcessed,
+                                 (LVM_INT16)SampleCount);
+#endif
+        }
+        /*
+         * Manage the output buffer
+         */
+        LVM_BufferOut(hInstance,
+                      pOutData,
+                      &SampleCount);
+
+    }
+
+    return(LVM_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
deleted file mode 100644
index a5356d2..0000000
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Includes                                                                      */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVM_Tables.h"
-#include "LVM_Coeffs.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Treble Boost Filter Coefficients                                              */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-
-FO_FLOAT_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
-
-                    /* 22kHz sampling rate */
-                    {HPF_Fs22050_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs22050_Gain1_A0,
-                     -HPF_Fs22050_Gain1_B1},
-                    {HPF_Fs22050_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs22050_Gain2_A0,
-                     -HPF_Fs22050_Gain2_B1},
-                    {HPF_Fs22050_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs22050_Gain3_A0,
-                     -HPF_Fs22050_Gain3_B1},
-                    {HPF_Fs22050_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs22050_Gain4_A0,
-                     -HPF_Fs22050_Gain4_B1},
-                    {HPF_Fs22050_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs22050_Gain5_A0,
-                     -HPF_Fs22050_Gain5_B1},
-                    {HPF_Fs22050_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs22050_Gain6_A0,
-                     -HPF_Fs22050_Gain6_B1},
-                    {HPF_Fs22050_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs22050_Gain7_A0,
-                     -HPF_Fs22050_Gain7_B1},
-                    {HPF_Fs22050_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs22050_Gain8_A0,
-                     -HPF_Fs22050_Gain8_B1},
-                    {HPF_Fs22050_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs22050_Gain9_A0,
-                     -HPF_Fs22050_Gain9_B1},
-                    {HPF_Fs22050_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs22050_Gain10_A0,
-                     -HPF_Fs22050_Gain10_B1},
-                    {HPF_Fs22050_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs22050_Gain11_A0,
-                     -HPF_Fs22050_Gain11_B1},
-                    {HPF_Fs22050_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs22050_Gain12_A0,
-                     -HPF_Fs22050_Gain12_B1},
-                    {HPF_Fs22050_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs22050_Gain13_A0,
-                     -HPF_Fs22050_Gain13_B1},
-                    {HPF_Fs22050_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs22050_Gain14_A0,
-                     -HPF_Fs22050_Gain14_B1},
-                    {HPF_Fs22050_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs22050_Gain15_A0,
-                     -HPF_Fs22050_Gain15_B1},
-
-                    /* 24kHz sampling rate */
-                    {HPF_Fs24000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs24000_Gain1_A0,
-                     -HPF_Fs24000_Gain1_B1},
-                    {HPF_Fs24000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs24000_Gain2_A0,
-                     -HPF_Fs24000_Gain2_B1},
-                    {HPF_Fs24000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs24000_Gain3_A0,
-                     -HPF_Fs24000_Gain3_B1},
-                    {HPF_Fs24000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs24000_Gain4_A0,
-                     -HPF_Fs24000_Gain4_B1},
-                    {HPF_Fs24000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs24000_Gain5_A0,
-                     -HPF_Fs24000_Gain5_B1},
-                    {HPF_Fs24000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs24000_Gain6_A0,
-                     -HPF_Fs24000_Gain6_B1},
-                    {HPF_Fs24000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs24000_Gain7_A0,
-                     -HPF_Fs24000_Gain7_B1},
-                    {HPF_Fs24000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs24000_Gain8_A0,
-                     -HPF_Fs24000_Gain8_B1},
-                    {HPF_Fs24000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs24000_Gain9_A0,
-                     -HPF_Fs24000_Gain9_B1},
-                    {HPF_Fs24000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs24000_Gain10_A0,
-                     -HPF_Fs24000_Gain10_B1},
-                    {HPF_Fs24000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs24000_Gain11_A0,
-                     -HPF_Fs24000_Gain11_B1},
-                    {HPF_Fs24000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs24000_Gain12_A0,
-                     -HPF_Fs24000_Gain12_B1},
-                    {HPF_Fs24000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs24000_Gain13_A0,
-                     -HPF_Fs24000_Gain13_B1},
-                    {HPF_Fs24000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs24000_Gain14_A0,
-                     -HPF_Fs24000_Gain14_B1},
-                    {HPF_Fs24000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs24000_Gain15_A0,
-                     -HPF_Fs24000_Gain15_B1},
-
-                    /* 32kHz sampling rate */
-                    {HPF_Fs32000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs32000_Gain1_A0,
-                     -HPF_Fs32000_Gain1_B1},
-                    {HPF_Fs32000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs32000_Gain2_A0,
-                     -HPF_Fs32000_Gain2_B1},
-                    {HPF_Fs32000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs32000_Gain3_A0,
-                     -HPF_Fs32000_Gain3_B1},
-                    {HPF_Fs32000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs32000_Gain4_A0,
-                     -HPF_Fs32000_Gain4_B1},
-                    {HPF_Fs32000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs32000_Gain5_A0,
-                     -HPF_Fs32000_Gain5_B1},
-                    {HPF_Fs32000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs32000_Gain6_A0,
-                     -HPF_Fs32000_Gain6_B1},
-                    {HPF_Fs32000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs32000_Gain7_A0,
-                     -HPF_Fs32000_Gain7_B1},
-                    {HPF_Fs32000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs32000_Gain8_A0,
-                     -HPF_Fs32000_Gain8_B1},
-                    {HPF_Fs32000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs32000_Gain9_A0,
-                     -HPF_Fs32000_Gain9_B1},
-                    {HPF_Fs32000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs32000_Gain10_A0,
-                     -HPF_Fs32000_Gain10_B1},
-                    {HPF_Fs32000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs32000_Gain11_A0,
-                     -HPF_Fs32000_Gain11_B1},
-                    {HPF_Fs32000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs32000_Gain12_A0,
-                     -HPF_Fs32000_Gain12_B1},
-                    {HPF_Fs32000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs32000_Gain13_A0,
-                     -HPF_Fs32000_Gain13_B1},
-                    {HPF_Fs32000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs32000_Gain14_A0,
-                     -HPF_Fs32000_Gain14_B1},
-                    {HPF_Fs32000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs32000_Gain15_A0,
-                     -HPF_Fs32000_Gain15_B1},
-
-                    /* 44kHz sampling rate */
-                    {HPF_Fs44100_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs44100_Gain1_A0,
-                     -HPF_Fs44100_Gain1_B1,},
-                    {HPF_Fs44100_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs44100_Gain2_A0,
-                     -HPF_Fs44100_Gain2_B1},
-                    {HPF_Fs44100_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs44100_Gain3_A0,
-                     -HPF_Fs44100_Gain3_B1},
-                    {HPF_Fs44100_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs44100_Gain4_A0,
-                     -HPF_Fs44100_Gain4_B1},
-                    {HPF_Fs44100_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs44100_Gain5_A0,
-                     -HPF_Fs44100_Gain5_B1},
-                    {HPF_Fs44100_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs44100_Gain6_A0,
-                     -HPF_Fs44100_Gain6_B1},
-                    {HPF_Fs44100_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs44100_Gain7_A0,
-                     -HPF_Fs44100_Gain7_B1},
-                    {HPF_Fs44100_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs44100_Gain8_A0,
-                     -HPF_Fs44100_Gain8_B1},
-                    {HPF_Fs44100_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs44100_Gain9_A0,
-                     -HPF_Fs44100_Gain9_B1},
-                    {HPF_Fs44100_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs44100_Gain10_A0,
-                     -HPF_Fs44100_Gain10_B1},
-                    {HPF_Fs44100_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs44100_Gain11_A0,
-                     -HPF_Fs44100_Gain11_B1},
-                    {HPF_Fs44100_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs44100_Gain12_A0,
-                     -HPF_Fs44100_Gain12_B1},
-                    {HPF_Fs44100_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs44100_Gain13_A0,
-                     -HPF_Fs44100_Gain13_B1},
-                    {HPF_Fs44100_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs44100_Gain14_A0,
-                     -HPF_Fs44100_Gain14_B1},
-                    {HPF_Fs44100_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs44100_Gain15_A0,
-                     -HPF_Fs44100_Gain15_B1},
-
-                    /* 48kHz sampling rate */
-                    {HPF_Fs48000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs48000_Gain1_A0,
-                     -HPF_Fs48000_Gain1_B1},
-                    {HPF_Fs48000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs48000_Gain2_A0,
-                     -HPF_Fs48000_Gain2_B1},
-                    {HPF_Fs48000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs48000_Gain3_A0,
-                     -HPF_Fs48000_Gain3_B1},
-                    {HPF_Fs48000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs48000_Gain4_A0,
-                     -HPF_Fs48000_Gain4_B1},
-                    {HPF_Fs48000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs48000_Gain5_A0,
-                     -HPF_Fs48000_Gain5_B1},
-                    {HPF_Fs48000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs48000_Gain6_A0,
-                     -HPF_Fs48000_Gain6_B1},
-                    {HPF_Fs48000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs48000_Gain7_A0,
-                     -HPF_Fs48000_Gain7_B1},
-                    {HPF_Fs48000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs48000_Gain8_A0,
-                     -HPF_Fs48000_Gain8_B1},
-                    {HPF_Fs48000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs48000_Gain9_A0,
-                     -HPF_Fs48000_Gain9_B1},
-                    {HPF_Fs48000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs48000_Gain10_A0,
-                     -HPF_Fs48000_Gain10_B1},
-                    {HPF_Fs48000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs48000_Gain11_A0,
-                     -HPF_Fs48000_Gain11_B1},
-                    {HPF_Fs48000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs48000_Gain12_A0,
-                     -HPF_Fs48000_Gain12_B1},
-                    {HPF_Fs48000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs48000_Gain13_A0,
-                     -HPF_Fs48000_Gain13_B1},
-                    {HPF_Fs48000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs48000_Gain14_A0,
-                     -HPF_Fs48000_Gain14_B1},
-                    {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs48000_Gain15_A0,
-                     -HPF_Fs48000_Gain15_B1}
-#ifdef HIGHER_FS
-                    ,
-                    /* 88kHz Sampling rate */
-                    {HPF_Fs88200_Gain1_A1,             /* Gain Setting  1 */
-                    HPF_Fs88200_Gain1_A0,
-                    -HPF_Fs88200_Gain1_B1},
-                    {HPF_Fs88200_Gain2_A1,             /* Gain Setting  2 */
-                    HPF_Fs88200_Gain2_A0,
-                    -HPF_Fs88200_Gain2_B1},
-                    {HPF_Fs88200_Gain3_A1,             /* Gain Setting  3 */
-                    HPF_Fs88200_Gain3_A0,
-                    -HPF_Fs88200_Gain3_B1},
-                    {HPF_Fs88200_Gain4_A1,             /* Gain Setting  4 */
-                    HPF_Fs88200_Gain4_A0,
-                    -HPF_Fs88200_Gain4_B1},
-                    {HPF_Fs88200_Gain5_A1,             /* Gain Setting  5 */
-                    HPF_Fs88200_Gain5_A0,
-                    -HPF_Fs88200_Gain5_B1},
-                    {HPF_Fs88200_Gain6_A1,             /* Gain Setting  6 */
-                    HPF_Fs88200_Gain6_A0,
-                    -HPF_Fs88200_Gain6_B1},
-                    {HPF_Fs88200_Gain7_A1,             /* Gain Setting  7 */
-                    HPF_Fs88200_Gain7_A0,
-                    -HPF_Fs88200_Gain7_B1},
-                    {HPF_Fs88200_Gain8_A1,             /* Gain Setting  8 */
-                    HPF_Fs88200_Gain8_A0,
-                    -HPF_Fs88200_Gain8_B1},
-                    {HPF_Fs88200_Gain9_A1,             /* Gain Setting  9 */
-                    HPF_Fs88200_Gain9_A0,
-                    -HPF_Fs88200_Gain9_B1},
-                    {HPF_Fs88200_Gain10_A1,             /* Gain Setting  10 */
-                    HPF_Fs88200_Gain10_A0,
-                    -HPF_Fs88200_Gain10_B1},
-                    {HPF_Fs88200_Gain11_A1,             /* Gain Setting  11 */
-                    HPF_Fs88200_Gain11_A0,
-                    -HPF_Fs88200_Gain11_B1},
-                    {HPF_Fs88200_Gain12_A1,             /* Gain Setting  12 */
-                    HPF_Fs88200_Gain12_A0,
-                    -HPF_Fs88200_Gain12_B1},
-                    {HPF_Fs88200_Gain13_A1,             /* Gain Setting  13 */
-                    HPF_Fs88200_Gain13_A0,
-                    -HPF_Fs88200_Gain13_B1},
-                    {HPF_Fs88200_Gain14_A1,             /* Gain Setting  14 */
-                    HPF_Fs88200_Gain14_A0,
-                    -HPF_Fs88200_Gain14_B1},
-                    {HPF_Fs88200_Gain15_A1,             /* Gain Setting  15 */
-                    HPF_Fs88200_Gain15_A0,
-                    -HPF_Fs88200_Gain15_B1},
-
-                    /* 96kHz sampling rate */
-                    {HPF_Fs96000_Gain1_A1,             /* Gain setting 1 */
-                    HPF_Fs96000_Gain1_A0,
-                    -HPF_Fs96000_Gain1_B1},
-                    {HPF_Fs96000_Gain2_A1,             /* Gain setting 2 */
-                    HPF_Fs96000_Gain2_A0,
-                    -HPF_Fs96000_Gain2_B1},
-                    {HPF_Fs96000_Gain3_A1,             /* Gain setting 3 */
-                    HPF_Fs96000_Gain3_A0,
-                    -HPF_Fs96000_Gain3_B1},
-                    {HPF_Fs96000_Gain4_A1,             /* Gain setting 4 */
-                    HPF_Fs96000_Gain4_A0,
-                    -HPF_Fs96000_Gain4_B1},
-                    {HPF_Fs96000_Gain5_A1,             /* Gain setting 5 */
-                    HPF_Fs96000_Gain5_A0,
-                    -HPF_Fs96000_Gain5_B1},
-                    {HPF_Fs96000_Gain6_A1,             /* Gain setting 6 */
-                    HPF_Fs96000_Gain6_A0,
-                    -HPF_Fs96000_Gain6_B1},
-                    {HPF_Fs96000_Gain7_A1,             /* Gain setting 7 */
-                    HPF_Fs96000_Gain7_A0,
-                    -HPF_Fs96000_Gain7_B1},
-                    {HPF_Fs96000_Gain8_A1,             /* Gain setting 8 */
-                    HPF_Fs96000_Gain8_A0,
-                    -HPF_Fs96000_Gain8_B1},
-                    {HPF_Fs96000_Gain9_A1,             /* Gain setting 9 */
-                    HPF_Fs96000_Gain9_A0,
-                    -HPF_Fs96000_Gain9_B1},
-                    {HPF_Fs96000_Gain10_A1,             /* Gain setting 10 */
-                    HPF_Fs96000_Gain10_A0,
-                    -HPF_Fs96000_Gain10_B1},
-                    {HPF_Fs96000_Gain11_A1,             /* Gain setting 11 */
-                    HPF_Fs96000_Gain11_A0,
-                    -HPF_Fs96000_Gain11_B1},
-                    {HPF_Fs96000_Gain12_A1,             /* Gain setting 12 */
-                    HPF_Fs96000_Gain12_A0,
-                    -HPF_Fs96000_Gain12_B1},
-                    {HPF_Fs96000_Gain13_A1,             /* Gain setting 13 */
-                    HPF_Fs96000_Gain13_A0,
-                    -HPF_Fs96000_Gain13_B1},
-                    {HPF_Fs96000_Gain14_A1,             /* Gain setting 14 */
-                    HPF_Fs96000_Gain14_A0,
-                    -HPF_Fs96000_Gain14_B1},
-                    {HPF_Fs96000_Gain15_A1,             /* Gain setting 15 */
-                    HPF_Fs96000_Gain15_A0,
-                    -HPF_Fs96000_Gain15_B1},
-
-                    /* 176kHz Sampling rate */
-                    {HPF_Fs176400_Gain1_A1,             /* Gain Setting  1 */
-                    HPF_Fs176400_Gain1_A0,
-                    -HPF_Fs176400_Gain1_B1},
-                    {HPF_Fs176400_Gain2_A1,             /* Gain Setting  2 */
-                    HPF_Fs176400_Gain2_A0,
-                    -HPF_Fs176400_Gain2_B1},
-                    {HPF_Fs176400_Gain3_A1,             /* Gain Setting  3 */
-                    HPF_Fs176400_Gain3_A0,
-                    -HPF_Fs176400_Gain3_B1},
-                    {HPF_Fs176400_Gain4_A1,             /* Gain Setting  4 */
-                    HPF_Fs176400_Gain4_A0,
-                    -HPF_Fs176400_Gain4_B1},
-                    {HPF_Fs176400_Gain5_A1,             /* Gain Setting  5 */
-                    HPF_Fs176400_Gain5_A0,
-                    -HPF_Fs176400_Gain5_B1},
-                    {HPF_Fs176400_Gain6_A1,             /* Gain Setting  6 */
-                    HPF_Fs176400_Gain6_A0,
-                    -HPF_Fs176400_Gain6_B1},
-                    {HPF_Fs176400_Gain7_A1,             /* Gain Setting  7 */
-                    HPF_Fs176400_Gain7_A0,
-                    -HPF_Fs176400_Gain7_B1},
-                    {HPF_Fs176400_Gain8_A1,             /* Gain Setting  8 */
-                    HPF_Fs176400_Gain8_A0,
-                    -HPF_Fs176400_Gain8_B1},
-                    {HPF_Fs176400_Gain9_A1,             /* Gain Setting  9 */
-                    HPF_Fs176400_Gain9_A0,
-                    -HPF_Fs176400_Gain9_B1},
-                    {HPF_Fs176400_Gain10_A1,             /* Gain Setting  10 */
-                    HPF_Fs176400_Gain10_A0,
-                    -HPF_Fs176400_Gain10_B1},
-                    {HPF_Fs176400_Gain11_A1,             /* Gain Setting  11 */
-                    HPF_Fs176400_Gain11_A0,
-                    -HPF_Fs176400_Gain11_B1},
-                    {HPF_Fs176400_Gain12_A1,             /* Gain Setting  12 */
-                    HPF_Fs176400_Gain12_A0,
-                    -HPF_Fs176400_Gain12_B1},
-                    {HPF_Fs176400_Gain13_A1,             /* Gain Setting  13 */
-                    HPF_Fs176400_Gain13_A0,
-                    -HPF_Fs176400_Gain13_B1},
-                    {HPF_Fs176400_Gain14_A1,             /* Gain Setting  14 */
-                    HPF_Fs176400_Gain14_A0,
-                    -HPF_Fs176400_Gain14_B1},
-                    {HPF_Fs176400_Gain15_A1,             /* Gain Setting  15 */
-                    HPF_Fs176400_Gain15_A0,
-                    -HPF_Fs176400_Gain15_B1},
-
-                    /* 192kHz sampling rate */
-                    {HPF_Fs192000_Gain1_A1,             /* Gain setting 1 */
-                    HPF_Fs192000_Gain1_A0,
-                    -HPF_Fs192000_Gain1_B1},
-                    {HPF_Fs192000_Gain2_A1,             /* Gain setting 2 */
-                    HPF_Fs192000_Gain2_A0,
-                    -HPF_Fs192000_Gain2_B1},
-                    {HPF_Fs192000_Gain3_A1,             /* Gain setting 3 */
-                    HPF_Fs192000_Gain3_A0,
-                    -HPF_Fs192000_Gain3_B1},
-                    {HPF_Fs192000_Gain4_A1,             /* Gain setting 4 */
-                    HPF_Fs192000_Gain4_A0,
-                    -HPF_Fs192000_Gain4_B1},
-                    {HPF_Fs192000_Gain5_A1,             /* Gain setting 5 */
-                    HPF_Fs192000_Gain5_A0,
-                    -HPF_Fs192000_Gain5_B1},
-                    {HPF_Fs192000_Gain6_A1,             /* Gain setting 6 */
-                    HPF_Fs192000_Gain6_A0,
-                    -HPF_Fs192000_Gain6_B1},
-                    {HPF_Fs192000_Gain7_A1,             /* Gain setting 7 */
-                    HPF_Fs192000_Gain7_A0,
-                    -HPF_Fs192000_Gain7_B1},
-                    {HPF_Fs192000_Gain8_A1,             /* Gain setting 8 */
-                    HPF_Fs192000_Gain8_A0,
-                    -HPF_Fs192000_Gain8_B1},
-                    {HPF_Fs192000_Gain9_A1,             /* Gain setting 9 */
-                    HPF_Fs192000_Gain9_A0,
-                    -HPF_Fs192000_Gain9_B1},
-                    {HPF_Fs192000_Gain10_A1,             /* Gain setting 10 */
-                    HPF_Fs192000_Gain10_A0,
-                    -HPF_Fs192000_Gain10_B1},
-                    {HPF_Fs192000_Gain11_A1,             /* Gain setting 11 */
-                    HPF_Fs192000_Gain11_A0,
-                    -HPF_Fs192000_Gain11_B1},
-                    {HPF_Fs192000_Gain12_A1,             /* Gain setting 12 */
-                    HPF_Fs192000_Gain12_A0,
-                    -HPF_Fs192000_Gain12_B1},
-                    {HPF_Fs192000_Gain13_A1,             /* Gain setting 13 */
-                    HPF_Fs192000_Gain13_A0,
-                    -HPF_Fs192000_Gain13_B1},
-                    {HPF_Fs192000_Gain14_A1,             /* Gain setting 14 */
-                    HPF_Fs192000_Gain14_A0,
-                    -HPF_Fs192000_Gain14_B1},
-                    {HPF_Fs192000_Gain15_A1,             /* Gain setting 15 */
-                    HPF_Fs192000_Gain15_A0,
-                    -HPF_Fs192000_Gain15_B1}
-#endif
-                    };
-#else
-FO_C16_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
-
-                    /* 22kHz sampling rate */
-                    {HPF_Fs22050_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs22050_Gain1_A0,
-                     -HPF_Fs22050_Gain1_B1,
-                    HPF_Fs22050_Gain1_Shift},
-                    {HPF_Fs22050_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs22050_Gain2_A0,
-                     -HPF_Fs22050_Gain2_B1,
-                    HPF_Fs22050_Gain2_Shift},
-                    {HPF_Fs22050_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs22050_Gain3_A0,
-                     -HPF_Fs22050_Gain3_B1,
-                    HPF_Fs22050_Gain3_Shift},
-                    {HPF_Fs22050_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs22050_Gain4_A0,
-                     -HPF_Fs22050_Gain4_B1,
-                    HPF_Fs22050_Gain4_Shift},
-                    {HPF_Fs22050_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs22050_Gain5_A0,
-                     -HPF_Fs22050_Gain5_B1,
-                    HPF_Fs22050_Gain5_Shift},
-                    {HPF_Fs22050_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs22050_Gain6_A0,
-                     -HPF_Fs22050_Gain6_B1,
-                    HPF_Fs22050_Gain6_Shift},
-                    {HPF_Fs22050_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs22050_Gain7_A0,
-                     -HPF_Fs22050_Gain7_B1,
-                    HPF_Fs22050_Gain7_Shift},
-                    {HPF_Fs22050_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs22050_Gain8_A0,
-                     -HPF_Fs22050_Gain8_B1,
-                    HPF_Fs22050_Gain8_Shift},
-                    {HPF_Fs22050_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs22050_Gain9_A0,
-                     -HPF_Fs22050_Gain9_B1,
-                    HPF_Fs22050_Gain9_Shift},
-                    {HPF_Fs22050_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs22050_Gain10_A0,
-                     -HPF_Fs22050_Gain10_B1,
-                    HPF_Fs22050_Gain10_Shift},
-                    {HPF_Fs22050_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs22050_Gain11_A0,
-                     -HPF_Fs22050_Gain11_B1,
-                    HPF_Fs22050_Gain11_Shift},
-                    {HPF_Fs22050_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs22050_Gain12_A0,
-                     -HPF_Fs22050_Gain12_B1,
-                    HPF_Fs22050_Gain12_Shift},
-                    {HPF_Fs22050_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs22050_Gain13_A0,
-                     -HPF_Fs22050_Gain13_B1,
-                    HPF_Fs22050_Gain13_Shift},
-                    {HPF_Fs22050_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs22050_Gain14_A0,
-                     -HPF_Fs22050_Gain14_B1,
-                    HPF_Fs22050_Gain14_Shift},
-                    {HPF_Fs22050_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs22050_Gain15_A0,
-                     -HPF_Fs22050_Gain15_B1,
-                    HPF_Fs22050_Gain15_Shift},
-
-                    /* 24kHz sampling rate */
-                    {HPF_Fs24000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs24000_Gain1_A0,
-                     -HPF_Fs24000_Gain1_B1,
-                     HPF_Fs24000_Gain1_Shift},
-                    {HPF_Fs24000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs24000_Gain2_A0,
-                     -HPF_Fs24000_Gain2_B1,
-                     HPF_Fs24000_Gain2_Shift},
-                    {HPF_Fs24000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs24000_Gain3_A0,
-                     -HPF_Fs24000_Gain3_B1,
-                     HPF_Fs24000_Gain3_Shift},
-                    {HPF_Fs24000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs24000_Gain4_A0,
-                     -HPF_Fs24000_Gain4_B1,
-                     HPF_Fs24000_Gain4_Shift},
-                    {HPF_Fs24000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs24000_Gain5_A0,
-                     -HPF_Fs24000_Gain5_B1,
-                     HPF_Fs24000_Gain5_Shift},
-                    {HPF_Fs24000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs24000_Gain6_A0,
-                     -HPF_Fs24000_Gain6_B1,
-                     HPF_Fs24000_Gain6_Shift},
-                    {HPF_Fs24000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs24000_Gain7_A0,
-                     -HPF_Fs24000_Gain7_B1,
-                     HPF_Fs24000_Gain7_Shift},
-                    {HPF_Fs24000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs24000_Gain8_A0,
-                     -HPF_Fs24000_Gain8_B1,
-                     HPF_Fs24000_Gain8_Shift},
-                    {HPF_Fs24000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs24000_Gain9_A0,
-                     -HPF_Fs24000_Gain9_B1,
-                     HPF_Fs24000_Gain9_Shift},
-                    {HPF_Fs24000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs24000_Gain10_A0,
-                     -HPF_Fs24000_Gain10_B1,
-                     HPF_Fs24000_Gain10_Shift},
-                    {HPF_Fs24000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs24000_Gain11_A0,
-                     -HPF_Fs24000_Gain11_B1,
-                     HPF_Fs24000_Gain11_Shift},
-                    {HPF_Fs24000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs24000_Gain12_A0,
-                     -HPF_Fs24000_Gain12_B1,
-                     HPF_Fs24000_Gain12_Shift},
-                    {HPF_Fs24000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs24000_Gain13_A0,
-                     -HPF_Fs24000_Gain13_B1,
-                     HPF_Fs24000_Gain13_Shift},
-                    {HPF_Fs24000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs24000_Gain14_A0,
-                     -HPF_Fs24000_Gain14_B1,
-                     HPF_Fs24000_Gain14_Shift},
-                    {HPF_Fs24000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs24000_Gain15_A0,
-                     -HPF_Fs24000_Gain15_B1,
-                     HPF_Fs24000_Gain15_Shift},
-
-                    /* 32kHz sampling rate */
-                    {HPF_Fs32000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs32000_Gain1_A0,
-                     -HPF_Fs32000_Gain1_B1,
-                    HPF_Fs32000_Gain1_Shift},
-                    {HPF_Fs32000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs32000_Gain2_A0,
-                     -HPF_Fs32000_Gain2_B1,
-                    HPF_Fs32000_Gain2_Shift},
-                    {HPF_Fs32000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs32000_Gain3_A0,
-                     -HPF_Fs32000_Gain3_B1,
-                    HPF_Fs32000_Gain3_Shift},
-                    {HPF_Fs32000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs32000_Gain4_A0,
-                     -HPF_Fs32000_Gain4_B1,
-                    HPF_Fs32000_Gain4_Shift},
-                    {HPF_Fs32000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs32000_Gain5_A0,
-                     -HPF_Fs32000_Gain5_B1,
-                    HPF_Fs32000_Gain5_Shift},
-                    {HPF_Fs32000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs32000_Gain6_A0,
-                     -HPF_Fs32000_Gain6_B1,
-                    HPF_Fs32000_Gain6_Shift},
-                    {HPF_Fs32000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs32000_Gain7_A0,
-                     -HPF_Fs32000_Gain7_B1,
-                    HPF_Fs32000_Gain7_Shift},
-                    {HPF_Fs32000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs32000_Gain8_A0,
-                     -HPF_Fs32000_Gain8_B1,
-                    HPF_Fs32000_Gain8_Shift},
-                    {HPF_Fs32000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs32000_Gain9_A0,
-                     -HPF_Fs32000_Gain9_B1,
-                    HPF_Fs32000_Gain9_Shift},
-                    {HPF_Fs32000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs32000_Gain10_A0,
-                     -HPF_Fs32000_Gain10_B1,
-                    HPF_Fs32000_Gain10_Shift},
-                    {HPF_Fs32000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs32000_Gain11_A0,
-                     -HPF_Fs32000_Gain11_B1,
-                    HPF_Fs32000_Gain11_Shift},
-                    {HPF_Fs32000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs32000_Gain12_A0,
-                     -HPF_Fs32000_Gain12_B1,
-                    HPF_Fs32000_Gain12_Shift},
-                    {HPF_Fs32000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs32000_Gain13_A0,
-                     -HPF_Fs32000_Gain13_B1,
-                    HPF_Fs32000_Gain13_Shift},
-                    {HPF_Fs32000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs32000_Gain14_A0,
-                     -HPF_Fs32000_Gain14_B1,
-                    HPF_Fs32000_Gain14_Shift},
-                    {HPF_Fs32000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs32000_Gain15_A0,
-                     -HPF_Fs32000_Gain15_B1,
-                    HPF_Fs32000_Gain15_Shift},
-
-                    /* 44kHz sampling rate */
-                    {HPF_Fs44100_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs44100_Gain1_A0,
-                     -HPF_Fs44100_Gain1_B1,
-                     HPF_Fs44100_Gain1_Shift},
-                    {HPF_Fs44100_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs44100_Gain2_A0,
-                     -HPF_Fs44100_Gain2_B1,
-                     HPF_Fs44100_Gain2_Shift},
-                    {HPF_Fs44100_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs44100_Gain3_A0,
-                     -HPF_Fs44100_Gain3_B1,
-                     HPF_Fs44100_Gain3_Shift},
-                    {HPF_Fs44100_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs44100_Gain4_A0,
-                     -HPF_Fs44100_Gain4_B1,
-                     HPF_Fs44100_Gain4_Shift},
-                    {HPF_Fs44100_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs44100_Gain5_A0,
-                     -HPF_Fs44100_Gain5_B1,
-                     HPF_Fs44100_Gain5_Shift},
-                    {HPF_Fs44100_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs44100_Gain6_A0,
-                     -HPF_Fs44100_Gain6_B1,
-                     HPF_Fs44100_Gain6_Shift},
-                    {HPF_Fs44100_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs44100_Gain7_A0,
-                     -HPF_Fs44100_Gain7_B1,
-                     HPF_Fs44100_Gain7_Shift},
-                    {HPF_Fs44100_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs44100_Gain8_A0,
-                     -HPF_Fs44100_Gain8_B1,
-                     HPF_Fs44100_Gain8_Shift},
-                    {HPF_Fs44100_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs44100_Gain9_A0,
-                     -HPF_Fs44100_Gain9_B1,
-                     HPF_Fs44100_Gain9_Shift},
-                    {HPF_Fs44100_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs44100_Gain10_A0,
-                     -HPF_Fs44100_Gain10_B1,
-                     HPF_Fs44100_Gain10_Shift},
-                    {HPF_Fs44100_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs44100_Gain11_A0,
-                     -HPF_Fs44100_Gain11_B1,
-                     HPF_Fs44100_Gain11_Shift},
-                    {HPF_Fs44100_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs44100_Gain12_A0,
-                     -HPF_Fs44100_Gain12_B1,
-                     HPF_Fs44100_Gain12_Shift},
-                    {HPF_Fs44100_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs44100_Gain13_A0,
-                     -HPF_Fs44100_Gain13_B1,
-                     HPF_Fs44100_Gain13_Shift},
-                    {HPF_Fs44100_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs44100_Gain14_A0,
-                     -HPF_Fs44100_Gain14_B1,
-                     HPF_Fs44100_Gain14_Shift},
-                    {HPF_Fs44100_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs44100_Gain15_A0,
-                     -HPF_Fs44100_Gain15_B1,
-                     HPF_Fs44100_Gain15_Shift},
-
-                    /* 48kHz sampling rate */
-                    {HPF_Fs48000_Gain1_A1,             /* Gain setting 1 */
-                     HPF_Fs48000_Gain1_A0,
-                     -HPF_Fs48000_Gain1_B1,
-                     HPF_Fs48000_Gain1_Shift},
-                    {HPF_Fs48000_Gain2_A1,             /* Gain setting 2 */
-                     HPF_Fs48000_Gain2_A0,
-                     -HPF_Fs48000_Gain2_B1,
-                     HPF_Fs48000_Gain2_Shift},
-                    {HPF_Fs48000_Gain3_A1,             /* Gain setting 3 */
-                     HPF_Fs48000_Gain3_A0,
-                     -HPF_Fs48000_Gain3_B1,
-                     HPF_Fs48000_Gain3_Shift},
-                    {HPF_Fs48000_Gain4_A1,             /* Gain setting 4 */
-                     HPF_Fs48000_Gain4_A0,
-                     -HPF_Fs48000_Gain4_B1,
-                     HPF_Fs48000_Gain4_Shift},
-                    {HPF_Fs48000_Gain5_A1,             /* Gain setting 5 */
-                     HPF_Fs48000_Gain5_A0,
-                     -HPF_Fs48000_Gain5_B1,
-                     HPF_Fs48000_Gain5_Shift},
-                    {HPF_Fs48000_Gain6_A1,             /* Gain setting 6 */
-                     HPF_Fs48000_Gain6_A0,
-                     -HPF_Fs48000_Gain6_B1,
-                     HPF_Fs48000_Gain6_Shift},
-                    {HPF_Fs48000_Gain7_A1,             /* Gain setting 7 */
-                     HPF_Fs48000_Gain7_A0,
-                     -HPF_Fs48000_Gain7_B1,
-                     HPF_Fs48000_Gain7_Shift},
-                    {HPF_Fs48000_Gain8_A1,             /* Gain setting 8 */
-                     HPF_Fs48000_Gain8_A0,
-                     -HPF_Fs48000_Gain8_B1,
-                     HPF_Fs48000_Gain8_Shift},
-                    {HPF_Fs48000_Gain9_A1,             /* Gain setting 9 */
-                     HPF_Fs48000_Gain9_A0,
-                     -HPF_Fs48000_Gain9_B1,
-                     HPF_Fs48000_Gain9_Shift},
-                    {HPF_Fs48000_Gain10_A1,             /* Gain setting 10 */
-                     HPF_Fs48000_Gain10_A0,
-                     -HPF_Fs48000_Gain10_B1,
-                     HPF_Fs48000_Gain10_Shift},
-                    {HPF_Fs48000_Gain11_A1,             /* Gain setting 11 */
-                     HPF_Fs48000_Gain11_A0,
-                     -HPF_Fs48000_Gain11_B1,
-                     HPF_Fs48000_Gain11_Shift},
-                    {HPF_Fs48000_Gain12_A1,             /* Gain setting 12 */
-                     HPF_Fs48000_Gain12_A0,
-                     -HPF_Fs48000_Gain12_B1,
-                     HPF_Fs48000_Gain12_Shift},
-                    {HPF_Fs48000_Gain13_A1,             /* Gain setting 13 */
-                     HPF_Fs48000_Gain13_A0,
-                     -HPF_Fs48000_Gain13_B1,
-                     HPF_Fs48000_Gain13_Shift},
-                    {HPF_Fs48000_Gain14_A1,             /* Gain setting 14 */
-                     HPF_Fs48000_Gain14_A0,
-                     -HPF_Fs48000_Gain14_B1,
-                     HPF_Fs48000_Gain14_Shift},
-                    {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
-                     HPF_Fs48000_Gain15_A0,
-                     -HPF_Fs48000_Gain15_B1,
-                     HPF_Fs48000_Gain15_Shift}
-                    };
-#endif
-
-/************************************************************************************/
-/*                                                                                    */
-/*    Volume control gain and time constant tables                                    */
-/*                                                                                    */
-/************************************************************************************/
-
-/* dB to linear conversion table */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT LVM_VolumeTable[] = {
-    1.000f,             /*  0dB */
-    0.891f,             /* -1dB */
-    0.794f,             /* -2dB */
-    0.708f,             /* -3dB */
-    0.631f,             /* -4dB */
-    0.562f,             /* -5dB */
-    0.501f};            /* -6dB */
-#else
-const LVM_INT16 LVM_VolumeTable[] = {
-    0x7FFF,             /*  0dB */
-    0x7215,             /* -1dB */
-    0x65AD,             /* -2dB */
-    0x5A9E,             /* -3dB */
-    0x50C3,             /* -4dB */
-    0x47FB,             /* -5dB */
-    0x4000};            /* -6dB */
-#endif
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Volume mixer time constants (100ms)                                             */
-/*                                                                                  */
-/************************************************************************************/
-
-#define LVM_MIX_TC_Fs8000      32580         /* Floating point value 0.994262695 */
-#define LVM_MIX_TC_Fs11025     32632         /* Floating point value 0.995849609 */
-#define LVM_MIX_TC_Fs12000     32643         /* Floating point value 0.996185303 */
-#define LVM_MIX_TC_Fs16000     32674         /* Floating point value 0.997131348 */
-#define LVM_MIX_TC_Fs22050     32700         /* Floating point value 0.997924805 */
-#define LVM_MIX_TC_Fs24000     32705         /* Floating point value 0.998077393 */
-#define LVM_MIX_TC_Fs32000     32721         /* Floating point value 0.998565674 */
-#define LVM_MIX_TC_Fs44100     32734         /* Floating point value 0.998962402 */
-#define LVM_MIX_TC_Fs48000     32737         /* Floating point value 0.999053955 */
-
-
-const LVM_INT16 LVM_MixerTCTable[] = {
-    LVM_MIX_TC_Fs8000,
-    LVM_MIX_TC_Fs11025,
-    LVM_MIX_TC_Fs12000,
-    LVM_MIX_TC_Fs16000,
-    LVM_MIX_TC_Fs22050,
-    LVM_MIX_TC_Fs24000,
-    LVM_MIX_TC_Fs32000,
-    LVM_MIX_TC_Fs44100,
-    LVM_MIX_TC_Fs48000};
-
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.cpp
new file mode 100644
index 0000000..66392e2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.cpp
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM_Tables.h"
+#include "LVM_Coeffs.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Treble Boost Filter Coefficients                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+FO_FLOAT_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
+
+                    /* 22kHz sampling rate */
+                    {HPF_Fs22050_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs22050_Gain1_A0,
+                     -HPF_Fs22050_Gain1_B1},
+                    {HPF_Fs22050_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs22050_Gain2_A0,
+                     -HPF_Fs22050_Gain2_B1},
+                    {HPF_Fs22050_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs22050_Gain3_A0,
+                     -HPF_Fs22050_Gain3_B1},
+                    {HPF_Fs22050_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs22050_Gain4_A0,
+                     -HPF_Fs22050_Gain4_B1},
+                    {HPF_Fs22050_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs22050_Gain5_A0,
+                     -HPF_Fs22050_Gain5_B1},
+                    {HPF_Fs22050_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs22050_Gain6_A0,
+                     -HPF_Fs22050_Gain6_B1},
+                    {HPF_Fs22050_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs22050_Gain7_A0,
+                     -HPF_Fs22050_Gain7_B1},
+                    {HPF_Fs22050_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs22050_Gain8_A0,
+                     -HPF_Fs22050_Gain8_B1},
+                    {HPF_Fs22050_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs22050_Gain9_A0,
+                     -HPF_Fs22050_Gain9_B1},
+                    {HPF_Fs22050_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs22050_Gain10_A0,
+                     -HPF_Fs22050_Gain10_B1},
+                    {HPF_Fs22050_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs22050_Gain11_A0,
+                     -HPF_Fs22050_Gain11_B1},
+                    {HPF_Fs22050_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs22050_Gain12_A0,
+                     -HPF_Fs22050_Gain12_B1},
+                    {HPF_Fs22050_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs22050_Gain13_A0,
+                     -HPF_Fs22050_Gain13_B1},
+                    {HPF_Fs22050_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs22050_Gain14_A0,
+                     -HPF_Fs22050_Gain14_B1},
+                    {HPF_Fs22050_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs22050_Gain15_A0,
+                     -HPF_Fs22050_Gain15_B1},
+
+                    /* 24kHz sampling rate */
+                    {HPF_Fs24000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs24000_Gain1_A0,
+                     -HPF_Fs24000_Gain1_B1},
+                    {HPF_Fs24000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs24000_Gain2_A0,
+                     -HPF_Fs24000_Gain2_B1},
+                    {HPF_Fs24000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs24000_Gain3_A0,
+                     -HPF_Fs24000_Gain3_B1},
+                    {HPF_Fs24000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs24000_Gain4_A0,
+                     -HPF_Fs24000_Gain4_B1},
+                    {HPF_Fs24000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs24000_Gain5_A0,
+                     -HPF_Fs24000_Gain5_B1},
+                    {HPF_Fs24000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs24000_Gain6_A0,
+                     -HPF_Fs24000_Gain6_B1},
+                    {HPF_Fs24000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs24000_Gain7_A0,
+                     -HPF_Fs24000_Gain7_B1},
+                    {HPF_Fs24000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs24000_Gain8_A0,
+                     -HPF_Fs24000_Gain8_B1},
+                    {HPF_Fs24000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs24000_Gain9_A0,
+                     -HPF_Fs24000_Gain9_B1},
+                    {HPF_Fs24000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs24000_Gain10_A0,
+                     -HPF_Fs24000_Gain10_B1},
+                    {HPF_Fs24000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs24000_Gain11_A0,
+                     -HPF_Fs24000_Gain11_B1},
+                    {HPF_Fs24000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs24000_Gain12_A0,
+                     -HPF_Fs24000_Gain12_B1},
+                    {HPF_Fs24000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs24000_Gain13_A0,
+                     -HPF_Fs24000_Gain13_B1},
+                    {HPF_Fs24000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs24000_Gain14_A0,
+                     -HPF_Fs24000_Gain14_B1},
+                    {HPF_Fs24000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs24000_Gain15_A0,
+                     -HPF_Fs24000_Gain15_B1},
+
+                    /* 32kHz sampling rate */
+                    {HPF_Fs32000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs32000_Gain1_A0,
+                     -HPF_Fs32000_Gain1_B1},
+                    {HPF_Fs32000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs32000_Gain2_A0,
+                     -HPF_Fs32000_Gain2_B1},
+                    {HPF_Fs32000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs32000_Gain3_A0,
+                     -HPF_Fs32000_Gain3_B1},
+                    {HPF_Fs32000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs32000_Gain4_A0,
+                     -HPF_Fs32000_Gain4_B1},
+                    {HPF_Fs32000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs32000_Gain5_A0,
+                     -HPF_Fs32000_Gain5_B1},
+                    {HPF_Fs32000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs32000_Gain6_A0,
+                     -HPF_Fs32000_Gain6_B1},
+                    {HPF_Fs32000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs32000_Gain7_A0,
+                     -HPF_Fs32000_Gain7_B1},
+                    {HPF_Fs32000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs32000_Gain8_A0,
+                     -HPF_Fs32000_Gain8_B1},
+                    {HPF_Fs32000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs32000_Gain9_A0,
+                     -HPF_Fs32000_Gain9_B1},
+                    {HPF_Fs32000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs32000_Gain10_A0,
+                     -HPF_Fs32000_Gain10_B1},
+                    {HPF_Fs32000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs32000_Gain11_A0,
+                     -HPF_Fs32000_Gain11_B1},
+                    {HPF_Fs32000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs32000_Gain12_A0,
+                     -HPF_Fs32000_Gain12_B1},
+                    {HPF_Fs32000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs32000_Gain13_A0,
+                     -HPF_Fs32000_Gain13_B1},
+                    {HPF_Fs32000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs32000_Gain14_A0,
+                     -HPF_Fs32000_Gain14_B1},
+                    {HPF_Fs32000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs32000_Gain15_A0,
+                     -HPF_Fs32000_Gain15_B1},
+
+                    /* 44kHz sampling rate */
+                    {HPF_Fs44100_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs44100_Gain1_A0,
+                     -HPF_Fs44100_Gain1_B1,},
+                    {HPF_Fs44100_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs44100_Gain2_A0,
+                     -HPF_Fs44100_Gain2_B1},
+                    {HPF_Fs44100_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs44100_Gain3_A0,
+                     -HPF_Fs44100_Gain3_B1},
+                    {HPF_Fs44100_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs44100_Gain4_A0,
+                     -HPF_Fs44100_Gain4_B1},
+                    {HPF_Fs44100_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs44100_Gain5_A0,
+                     -HPF_Fs44100_Gain5_B1},
+                    {HPF_Fs44100_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs44100_Gain6_A0,
+                     -HPF_Fs44100_Gain6_B1},
+                    {HPF_Fs44100_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs44100_Gain7_A0,
+                     -HPF_Fs44100_Gain7_B1},
+                    {HPF_Fs44100_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs44100_Gain8_A0,
+                     -HPF_Fs44100_Gain8_B1},
+                    {HPF_Fs44100_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs44100_Gain9_A0,
+                     -HPF_Fs44100_Gain9_B1},
+                    {HPF_Fs44100_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs44100_Gain10_A0,
+                     -HPF_Fs44100_Gain10_B1},
+                    {HPF_Fs44100_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs44100_Gain11_A0,
+                     -HPF_Fs44100_Gain11_B1},
+                    {HPF_Fs44100_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs44100_Gain12_A0,
+                     -HPF_Fs44100_Gain12_B1},
+                    {HPF_Fs44100_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs44100_Gain13_A0,
+                     -HPF_Fs44100_Gain13_B1},
+                    {HPF_Fs44100_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs44100_Gain14_A0,
+                     -HPF_Fs44100_Gain14_B1},
+                    {HPF_Fs44100_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs44100_Gain15_A0,
+                     -HPF_Fs44100_Gain15_B1},
+
+                    /* 48kHz sampling rate */
+                    {HPF_Fs48000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs48000_Gain1_A0,
+                     -HPF_Fs48000_Gain1_B1},
+                    {HPF_Fs48000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs48000_Gain2_A0,
+                     -HPF_Fs48000_Gain2_B1},
+                    {HPF_Fs48000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs48000_Gain3_A0,
+                     -HPF_Fs48000_Gain3_B1},
+                    {HPF_Fs48000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs48000_Gain4_A0,
+                     -HPF_Fs48000_Gain4_B1},
+                    {HPF_Fs48000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs48000_Gain5_A0,
+                     -HPF_Fs48000_Gain5_B1},
+                    {HPF_Fs48000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs48000_Gain6_A0,
+                     -HPF_Fs48000_Gain6_B1},
+                    {HPF_Fs48000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs48000_Gain7_A0,
+                     -HPF_Fs48000_Gain7_B1},
+                    {HPF_Fs48000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs48000_Gain8_A0,
+                     -HPF_Fs48000_Gain8_B1},
+                    {HPF_Fs48000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs48000_Gain9_A0,
+                     -HPF_Fs48000_Gain9_B1},
+                    {HPF_Fs48000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs48000_Gain10_A0,
+                     -HPF_Fs48000_Gain10_B1},
+                    {HPF_Fs48000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs48000_Gain11_A0,
+                     -HPF_Fs48000_Gain11_B1},
+                    {HPF_Fs48000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs48000_Gain12_A0,
+                     -HPF_Fs48000_Gain12_B1},
+                    {HPF_Fs48000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs48000_Gain13_A0,
+                     -HPF_Fs48000_Gain13_B1},
+                    {HPF_Fs48000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs48000_Gain14_A0,
+                     -HPF_Fs48000_Gain14_B1},
+                    {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs48000_Gain15_A0,
+                     -HPF_Fs48000_Gain15_B1}
+                    ,
+                    /* 88kHz Sampling rate */
+                    {HPF_Fs88200_Gain1_A1,             /* Gain Setting  1 */
+                    HPF_Fs88200_Gain1_A0,
+                    -HPF_Fs88200_Gain1_B1},
+                    {HPF_Fs88200_Gain2_A1,             /* Gain Setting  2 */
+                    HPF_Fs88200_Gain2_A0,
+                    -HPF_Fs88200_Gain2_B1},
+                    {HPF_Fs88200_Gain3_A1,             /* Gain Setting  3 */
+                    HPF_Fs88200_Gain3_A0,
+                    -HPF_Fs88200_Gain3_B1},
+                    {HPF_Fs88200_Gain4_A1,             /* Gain Setting  4 */
+                    HPF_Fs88200_Gain4_A0,
+                    -HPF_Fs88200_Gain4_B1},
+                    {HPF_Fs88200_Gain5_A1,             /* Gain Setting  5 */
+                    HPF_Fs88200_Gain5_A0,
+                    -HPF_Fs88200_Gain5_B1},
+                    {HPF_Fs88200_Gain6_A1,             /* Gain Setting  6 */
+                    HPF_Fs88200_Gain6_A0,
+                    -HPF_Fs88200_Gain6_B1},
+                    {HPF_Fs88200_Gain7_A1,             /* Gain Setting  7 */
+                    HPF_Fs88200_Gain7_A0,
+                    -HPF_Fs88200_Gain7_B1},
+                    {HPF_Fs88200_Gain8_A1,             /* Gain Setting  8 */
+                    HPF_Fs88200_Gain8_A0,
+                    -HPF_Fs88200_Gain8_B1},
+                    {HPF_Fs88200_Gain9_A1,             /* Gain Setting  9 */
+                    HPF_Fs88200_Gain9_A0,
+                    -HPF_Fs88200_Gain9_B1},
+                    {HPF_Fs88200_Gain10_A1,             /* Gain Setting  10 */
+                    HPF_Fs88200_Gain10_A0,
+                    -HPF_Fs88200_Gain10_B1},
+                    {HPF_Fs88200_Gain11_A1,             /* Gain Setting  11 */
+                    HPF_Fs88200_Gain11_A0,
+                    -HPF_Fs88200_Gain11_B1},
+                    {HPF_Fs88200_Gain12_A1,             /* Gain Setting  12 */
+                    HPF_Fs88200_Gain12_A0,
+                    -HPF_Fs88200_Gain12_B1},
+                    {HPF_Fs88200_Gain13_A1,             /* Gain Setting  13 */
+                    HPF_Fs88200_Gain13_A0,
+                    -HPF_Fs88200_Gain13_B1},
+                    {HPF_Fs88200_Gain14_A1,             /* Gain Setting  14 */
+                    HPF_Fs88200_Gain14_A0,
+                    -HPF_Fs88200_Gain14_B1},
+                    {HPF_Fs88200_Gain15_A1,             /* Gain Setting  15 */
+                    HPF_Fs88200_Gain15_A0,
+                    -HPF_Fs88200_Gain15_B1},
+
+                    /* 96kHz sampling rate */
+                    {HPF_Fs96000_Gain1_A1,             /* Gain setting 1 */
+                    HPF_Fs96000_Gain1_A0,
+                    -HPF_Fs96000_Gain1_B1},
+                    {HPF_Fs96000_Gain2_A1,             /* Gain setting 2 */
+                    HPF_Fs96000_Gain2_A0,
+                    -HPF_Fs96000_Gain2_B1},
+                    {HPF_Fs96000_Gain3_A1,             /* Gain setting 3 */
+                    HPF_Fs96000_Gain3_A0,
+                    -HPF_Fs96000_Gain3_B1},
+                    {HPF_Fs96000_Gain4_A1,             /* Gain setting 4 */
+                    HPF_Fs96000_Gain4_A0,
+                    -HPF_Fs96000_Gain4_B1},
+                    {HPF_Fs96000_Gain5_A1,             /* Gain setting 5 */
+                    HPF_Fs96000_Gain5_A0,
+                    -HPF_Fs96000_Gain5_B1},
+                    {HPF_Fs96000_Gain6_A1,             /* Gain setting 6 */
+                    HPF_Fs96000_Gain6_A0,
+                    -HPF_Fs96000_Gain6_B1},
+                    {HPF_Fs96000_Gain7_A1,             /* Gain setting 7 */
+                    HPF_Fs96000_Gain7_A0,
+                    -HPF_Fs96000_Gain7_B1},
+                    {HPF_Fs96000_Gain8_A1,             /* Gain setting 8 */
+                    HPF_Fs96000_Gain8_A0,
+                    -HPF_Fs96000_Gain8_B1},
+                    {HPF_Fs96000_Gain9_A1,             /* Gain setting 9 */
+                    HPF_Fs96000_Gain9_A0,
+                    -HPF_Fs96000_Gain9_B1},
+                    {HPF_Fs96000_Gain10_A1,             /* Gain setting 10 */
+                    HPF_Fs96000_Gain10_A0,
+                    -HPF_Fs96000_Gain10_B1},
+                    {HPF_Fs96000_Gain11_A1,             /* Gain setting 11 */
+                    HPF_Fs96000_Gain11_A0,
+                    -HPF_Fs96000_Gain11_B1},
+                    {HPF_Fs96000_Gain12_A1,             /* Gain setting 12 */
+                    HPF_Fs96000_Gain12_A0,
+                    -HPF_Fs96000_Gain12_B1},
+                    {HPF_Fs96000_Gain13_A1,             /* Gain setting 13 */
+                    HPF_Fs96000_Gain13_A0,
+                    -HPF_Fs96000_Gain13_B1},
+                    {HPF_Fs96000_Gain14_A1,             /* Gain setting 14 */
+                    HPF_Fs96000_Gain14_A0,
+                    -HPF_Fs96000_Gain14_B1},
+                    {HPF_Fs96000_Gain15_A1,             /* Gain setting 15 */
+                    HPF_Fs96000_Gain15_A0,
+                    -HPF_Fs96000_Gain15_B1},
+
+                    /* 176kHz Sampling rate */
+                    {HPF_Fs176400_Gain1_A1,             /* Gain Setting  1 */
+                    HPF_Fs176400_Gain1_A0,
+                    -HPF_Fs176400_Gain1_B1},
+                    {HPF_Fs176400_Gain2_A1,             /* Gain Setting  2 */
+                    HPF_Fs176400_Gain2_A0,
+                    -HPF_Fs176400_Gain2_B1},
+                    {HPF_Fs176400_Gain3_A1,             /* Gain Setting  3 */
+                    HPF_Fs176400_Gain3_A0,
+                    -HPF_Fs176400_Gain3_B1},
+                    {HPF_Fs176400_Gain4_A1,             /* Gain Setting  4 */
+                    HPF_Fs176400_Gain4_A0,
+                    -HPF_Fs176400_Gain4_B1},
+                    {HPF_Fs176400_Gain5_A1,             /* Gain Setting  5 */
+                    HPF_Fs176400_Gain5_A0,
+                    -HPF_Fs176400_Gain5_B1},
+                    {HPF_Fs176400_Gain6_A1,             /* Gain Setting  6 */
+                    HPF_Fs176400_Gain6_A0,
+                    -HPF_Fs176400_Gain6_B1},
+                    {HPF_Fs176400_Gain7_A1,             /* Gain Setting  7 */
+                    HPF_Fs176400_Gain7_A0,
+                    -HPF_Fs176400_Gain7_B1},
+                    {HPF_Fs176400_Gain8_A1,             /* Gain Setting  8 */
+                    HPF_Fs176400_Gain8_A0,
+                    -HPF_Fs176400_Gain8_B1},
+                    {HPF_Fs176400_Gain9_A1,             /* Gain Setting  9 */
+                    HPF_Fs176400_Gain9_A0,
+                    -HPF_Fs176400_Gain9_B1},
+                    {HPF_Fs176400_Gain10_A1,             /* Gain Setting  10 */
+                    HPF_Fs176400_Gain10_A0,
+                    -HPF_Fs176400_Gain10_B1},
+                    {HPF_Fs176400_Gain11_A1,             /* Gain Setting  11 */
+                    HPF_Fs176400_Gain11_A0,
+                    -HPF_Fs176400_Gain11_B1},
+                    {HPF_Fs176400_Gain12_A1,             /* Gain Setting  12 */
+                    HPF_Fs176400_Gain12_A0,
+                    -HPF_Fs176400_Gain12_B1},
+                    {HPF_Fs176400_Gain13_A1,             /* Gain Setting  13 */
+                    HPF_Fs176400_Gain13_A0,
+                    -HPF_Fs176400_Gain13_B1},
+                    {HPF_Fs176400_Gain14_A1,             /* Gain Setting  14 */
+                    HPF_Fs176400_Gain14_A0,
+                    -HPF_Fs176400_Gain14_B1},
+                    {HPF_Fs176400_Gain15_A1,             /* Gain Setting  15 */
+                    HPF_Fs176400_Gain15_A0,
+                    -HPF_Fs176400_Gain15_B1},
+
+                    /* 192kHz sampling rate */
+                    {HPF_Fs192000_Gain1_A1,             /* Gain setting 1 */
+                    HPF_Fs192000_Gain1_A0,
+                    -HPF_Fs192000_Gain1_B1},
+                    {HPF_Fs192000_Gain2_A1,             /* Gain setting 2 */
+                    HPF_Fs192000_Gain2_A0,
+                    -HPF_Fs192000_Gain2_B1},
+                    {HPF_Fs192000_Gain3_A1,             /* Gain setting 3 */
+                    HPF_Fs192000_Gain3_A0,
+                    -HPF_Fs192000_Gain3_B1},
+                    {HPF_Fs192000_Gain4_A1,             /* Gain setting 4 */
+                    HPF_Fs192000_Gain4_A0,
+                    -HPF_Fs192000_Gain4_B1},
+                    {HPF_Fs192000_Gain5_A1,             /* Gain setting 5 */
+                    HPF_Fs192000_Gain5_A0,
+                    -HPF_Fs192000_Gain5_B1},
+                    {HPF_Fs192000_Gain6_A1,             /* Gain setting 6 */
+                    HPF_Fs192000_Gain6_A0,
+                    -HPF_Fs192000_Gain6_B1},
+                    {HPF_Fs192000_Gain7_A1,             /* Gain setting 7 */
+                    HPF_Fs192000_Gain7_A0,
+                    -HPF_Fs192000_Gain7_B1},
+                    {HPF_Fs192000_Gain8_A1,             /* Gain setting 8 */
+                    HPF_Fs192000_Gain8_A0,
+                    -HPF_Fs192000_Gain8_B1},
+                    {HPF_Fs192000_Gain9_A1,             /* Gain setting 9 */
+                    HPF_Fs192000_Gain9_A0,
+                    -HPF_Fs192000_Gain9_B1},
+                    {HPF_Fs192000_Gain10_A1,             /* Gain setting 10 */
+                    HPF_Fs192000_Gain10_A0,
+                    -HPF_Fs192000_Gain10_B1},
+                    {HPF_Fs192000_Gain11_A1,             /* Gain setting 11 */
+                    HPF_Fs192000_Gain11_A0,
+                    -HPF_Fs192000_Gain11_B1},
+                    {HPF_Fs192000_Gain12_A1,             /* Gain setting 12 */
+                    HPF_Fs192000_Gain12_A0,
+                    -HPF_Fs192000_Gain12_B1},
+                    {HPF_Fs192000_Gain13_A1,             /* Gain setting 13 */
+                    HPF_Fs192000_Gain13_A0,
+                    -HPF_Fs192000_Gain13_B1},
+                    {HPF_Fs192000_Gain14_A1,             /* Gain setting 14 */
+                    HPF_Fs192000_Gain14_A0,
+                    -HPF_Fs192000_Gain14_B1},
+                    {HPF_Fs192000_Gain15_A1,             /* Gain setting 15 */
+                    HPF_Fs192000_Gain15_A0,
+                    -HPF_Fs192000_Gain15_B1}
+                    };
+
+/************************************************************************************/
+/*                                                                                    */
+/*    Volume control gain and time constant tables                                    */
+/*                                                                                    */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_FLOAT LVM_VolumeTable[] = {
+    1.000f,             /*  0dB */
+    0.891f,             /* -1dB */
+    0.794f,             /* -2dB */
+    0.708f,             /* -3dB */
+    0.631f,             /* -4dB */
+    0.562f,             /* -5dB */
+    0.501f};            /* -6dB */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Volume mixer time constants (100ms)                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVM_MIX_TC_Fs8000      32580         /* Floating point value 0.994262695 */
+#define LVM_MIX_TC_Fs11025     32632         /* Floating point value 0.995849609 */
+#define LVM_MIX_TC_Fs12000     32643         /* Floating point value 0.996185303 */
+#define LVM_MIX_TC_Fs16000     32674         /* Floating point value 0.997131348 */
+#define LVM_MIX_TC_Fs22050     32700         /* Floating point value 0.997924805 */
+#define LVM_MIX_TC_Fs24000     32705         /* Floating point value 0.998077393 */
+#define LVM_MIX_TC_Fs32000     32721         /* Floating point value 0.998565674 */
+#define LVM_MIX_TC_Fs44100     32734         /* Floating point value 0.998962402 */
+#define LVM_MIX_TC_Fs48000     32737         /* Floating point value 0.999053955 */
+
+const LVM_INT16 LVM_MixerTCTable[] = {
+    LVM_MIX_TC_Fs8000,
+    LVM_MIX_TC_Fs11025,
+    LVM_MIX_TC_Fs12000,
+    LVM_MIX_TC_Fs16000,
+    LVM_MIX_TC_Fs22050,
+    LVM_MIX_TC_Fs24000,
+    LVM_MIX_TC_Fs32000,
+    LVM_MIX_TC_Fs44100,
+    LVM_MIX_TC_Fs48000};
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
index 4cf7119..fc82194 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
@@ -18,10 +18,6 @@
 #ifndef __LVM_TABLES_H__
 #define __LVM_TABLES_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Includes                                                                      */
@@ -37,30 +33,16 @@
 /*                                                                                  */
 /************************************************************************************/
 
-#ifdef BUILD_FLOAT
 extern FO_FLOAT_LShx_Coefs_t     LVM_TrebleBoostCoefs[];
-#else
-extern FO_C16_LShx_Coefs_t     LVM_TrebleBoostCoefs[];
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /*    Volume control gain and time constant tables                                  */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 extern const LVM_FLOAT LVM_VolumeTable[];
-#else
-extern const LVM_INT16 LVM_VolumeTable[];
-#endif
 
 extern const LVM_INT16 LVM_MixerTCTable[];
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* __LVM_TABLES_H__ */
 
-
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index 06e742e..bef7fa1 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -18,11 +18,6 @@
 #ifndef __AGC_H__
 #define __AGC_H__
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /**********************************************************************************/
 /*                                                                                */
 /*    Includes                                                                    */
@@ -31,28 +26,11 @@
 
 #include "LVM_Types.h"
 
-
 /**********************************************************************************/
 /*                                                                                */
 /*    Types                                                                       */
 /*                                                                                */
 /**********************************************************************************/
-#ifndef BUILD_FLOAT
-typedef struct
-{
-    LVM_INT32  AGC_Gain;                        /* The current AGC gain */
-    LVM_INT32  AGC_MaxGain;                     /* The maximum AGC gain */
-    LVM_INT32  Volume;                          /* The current volume setting */
-    LVM_INT32  Target;                          /* The target volume setting */
-    LVM_INT32  AGC_Target;                      /* AGC target level */
-    LVM_INT16  AGC_Attack;                      /* AGC attack scaler */
-    LVM_INT16  AGC_Decay;                       /* AGC decay scaler */
-    LVM_INT16  AGC_GainShift;                   /* The gain shift */
-    LVM_INT16  VolumeShift;                     /* Volume shift scaling */
-    LVM_INT16  VolumeTC;                        /* Volume update time constant */
-
-} AGC_MIX_VOL_2St1Mon_D32_t;
-#else
 typedef struct
 {
     LVM_FLOAT  AGC_Gain;                        /* The current AGC gain */
@@ -65,14 +43,12 @@
     LVM_FLOAT  VolumeTC;                        /* Volume update time constant */
 
 } AGC_MIX_VOL_2St1Mon_FLOAT_t;
-#endif
 
 /**********************************************************************************/
 /*                                                                                */
 /*    Function Prototypes                                                              */
 /*                                                                                */
 /**********************************************************************************/
-#ifdef BUILD_FLOAT
 void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
                                  const LVM_FLOAT            *pStSrc,        /* Stereo source */
                                  const LVM_FLOAT            *pMonoSrc,      /* Mono source */
@@ -87,26 +63,5 @@
                                  LVM_UINT16                 NrChannels);  /* Number of channels */
 #endif
 
-#else
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
-                                 const LVM_INT32            *pStSrc,        /* Stereo source */
-                                 const LVM_INT32            *pMonoSrc,      /* Mono source */
-                                 LVM_INT32                  *pDst,          /* Stereo destination */
-                                 LVM_UINT16                 n);             /* Number of samples */
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
 #endif  /* __AGC_H__ */
 
-
-
-
-
-
-
-
-
-
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index 01539b2..c050cd0 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -18,16 +18,10 @@
 #ifndef _BIQUAD_H_
 #define _BIQUAD_H_
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include "LVM_Types.h"
 /**********************************************************************************
    INSTANCE MEMORY TYPE DEFINITION
 ***********************************************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
 #ifdef SUPPORT_MC
@@ -42,19 +36,11 @@
     LVM_FLOAT Storage[6];
 #endif
 } Biquad_FLOAT_Instance_t;
-#else
-typedef struct
-{
-    LVM_INT32 Storage[6];
-
-} Biquad_Instance_t;
-#endif
 /**********************************************************************************
    COEFFICIENT TYPE DEFINITIONS
 ***********************************************************************************/
 
 /*** Biquad coefficients **********************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT  A2;   /*  a2  */
@@ -63,93 +49,31 @@
     LVM_FLOAT  B2;   /* -b2! */
     LVM_FLOAT  B1;   /* -b1! */
 } BQ_FLOAT_Coefs_t;
-#else
-typedef struct
-{
-    LVM_INT16 A2;   /*  a2  */
-    LVM_INT16 A1;   /*  a1  */
-    LVM_INT16 A0;   /*  a0  */
-    LVM_INT16 B2;   /* -b2! */
-    LVM_INT16 B1;   /* -b1! */
-} BQ_C16_Coefs_t;
-
-typedef struct
-{
-    LVM_INT32  A2;   /*  a2  */
-    LVM_INT32  A1;   /*  a1  */
-    LVM_INT32  A0;   /*  a0  */
-    LVM_INT32  B2;   /* -b2! */
-    LVM_INT32  B1;   /* -b1! */
-} BQ_C32_Coefs_t;
-#endif
 
 /*** First order coefficients *****************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT A1;   /*  a1  */
     LVM_FLOAT A0;   /*  a0  */
     LVM_FLOAT B1;   /* -b1! */
 } FO_FLOAT_Coefs_t;
-#else
-typedef struct
-{
-    LVM_INT16 A1;   /*  a1  */
-    LVM_INT16 A0;   /*  a0  */
-    LVM_INT16 B1;   /* -b1! */
-} FO_C16_Coefs_t;
-
-typedef struct
-{
-    LVM_INT32  A1;   /*  a1  */
-    LVM_INT32  A0;   /*  a0  */
-    LVM_INT32  B1;   /* -b1! */
-} FO_C32_Coefs_t;
-#endif
 
 /*** First order coefficients with Shift*****************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT A1;    /*  a1  */
     LVM_FLOAT A0;    /*  a0  */
     LVM_FLOAT B1;    /* -b1! */
 } FO_FLOAT_LShx_Coefs_t;
-#else
-typedef struct
-{
-    LVM_INT16 A1;    /*  a1  */
-    LVM_INT16 A0;    /*  a0  */
-    LVM_INT16 B1;    /* -b1! */
-    LVM_INT16 Shift; /* Shift */
-} FO_C16_LShx_Coefs_t;
-#endif
 /*** Band pass coefficients *******************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT  A0;   /*  a0  */
     LVM_FLOAT  B2;   /* -b2! */
     LVM_FLOAT  B1;   /* -b1! */
 } BP_FLOAT_Coefs_t;
-#else
-typedef struct
-{
-    LVM_INT16 A0;   /*  a0  */
-    LVM_INT16 B2;   /* -b2! */
-    LVM_INT16 B1;   /* -b1! */
-} BP_C16_Coefs_t;
-
-typedef struct
-{
-    LVM_INT32  A0;   /*  a0  */
-    LVM_INT32  B2;   /* -b2! */
-    LVM_INT32  B1;   /* -b1! */
-} BP_C32_Coefs_t;
-#endif
 
 /*** Peaking coefficients *********************************************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT A0;   /*  a0  */
@@ -157,30 +81,12 @@
     LVM_FLOAT B1;   /* -b1! */
     LVM_FLOAT  G;   /* Gain */
 } PK_FLOAT_Coefs_t;
-#else
-typedef struct
-{
-    LVM_INT16 A0;   /*  a0  */
-    LVM_INT16 B2;   /* -b2! */
-    LVM_INT16 B1;   /* -b1! */
-    LVM_INT16  G;   /* Gain */
-} PK_C16_Coefs_t;
-
-typedef struct
-{
-    LVM_INT32  A0;   /*  a0  */
-    LVM_INT32  B2;   /* -b2! */
-    LVM_INT32  B1;   /* -b1! */
-    LVM_INT16  G;   /* Gain */
-} PK_C32_Coefs_t;
-#endif
 
 /**********************************************************************************
    TAPS TYPE DEFINITIONS
 ***********************************************************************************/
 
 /*** Types used for first order and shelving filter *******************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT Storage[ (1 * 2) ];  /* One channel, two taps of size LVM_INT32 */
@@ -195,20 +101,8 @@
     LVM_FLOAT Storage[ (2 * 2) ];  /* Two channels, two taps of size LVM_FLOAT */
 #endif
 } Biquad_2I_Order1_FLOAT_Taps_t;
-#else
-typedef struct
-{
-    LVM_INT32 Storage[ (1*2) ];  /* One channel, two taps of size LVM_INT32 */
-} Biquad_1I_Order1_Taps_t;
-
-typedef struct
-{
-    LVM_INT32 Storage[ (2*2) ];  /* Two channels, two taps of size LVM_INT32 */
-} Biquad_2I_Order1_Taps_t;
-#endif
 
 /*** Types used for biquad, band pass and peaking filter **************************/
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT Storage[ (1 * 4) ];  /* One channel, four taps of size LVM_FLOAT */
@@ -223,17 +117,6 @@
     LVM_FLOAT Storage[ (2 * 4) ];  /* Two channels, four taps of size LVM_FLOAT */
 #endif
 } Biquad_2I_Order2_FLOAT_Taps_t;
-#else
-typedef struct
-{
-    LVM_INT32 Storage[ (1*4) ];  /* One channel, four taps of size LVM_INT32 */
-} Biquad_1I_Order2_Taps_t;
-
-typedef struct
-{
-    LVM_INT32 Storage[ (2*4) ];  /* Two channels, four taps of size LVM_INT32 */
-} Biquad_2I_Order2_Taps_t;
-#endif
 /* The names of the functions are changed to satisfy QAC rules: Name should be Unique withing 16 characters*/
 #define BQ_2I_D32F32Cll_TRC_WRA_01_Init  Init_BQ_2I_D32F32Cll_TRC_WRA_01
 #define BP_1I_D32F32C30_TRC_WRA_02       TWO_BP_1I_D32F32C30_TRC_WRA_02
@@ -244,140 +127,57 @@
 
 /*** 16 bit data path *************************************************************/
 
-
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
                                          Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
                                          BQ_FLOAT_Coefs_t            *pCoef);
-#else
-void BQ_2I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_2I_Order2_Taps_t *pTaps,
-                                            BQ_C16_Coefs_t          *pCoef);
-#endif
 
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
                                             LVM_FLOAT                    *pDataIn,
                                             LVM_FLOAT                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-#else
-void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
 
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
                                             LVM_FLOAT                    *pDataIn,
                                             LVM_FLOAT                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-#else
-void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
                                             LVM_FLOAT                    *pDataIn,
                                             LVM_FLOAT                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-#else
-void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
                                          Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
                                          BQ_FLOAT_Coefs_t            *pCoef);
-#else
-void BQ_2I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_2I_Order2_Taps_t *pTaps,
-                                            BQ_C16_Coefs_t          *pCoef);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
                                  LVM_FLOAT               *pDataIn,
                                  LVM_FLOAT               *pDataOut,
                                  LVM_INT16               NrSamples);
-#else
-void BQ_2I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                   *pDataIn,
-                                            LVM_INT16                   *pDataOut,
-                                            LVM_INT16                   NrSamples);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_2I_D16F16C14_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
                                  LVM_FLOAT               *pDataIn,
                                  LVM_FLOAT               *pDataOut,
                                  LVM_INT16               NrSamples);
-#else
-void BQ_2I_D16F16C14_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                   *pDataIn,
-                                            LVM_INT16                   *pDataOut,
-                                            LVM_INT16                   NrSamples);
-#endif
 
-#ifdef BUILD_FLOAT
 void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
                                          Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
                                          BQ_FLOAT_Coefs_t            *pCoef);
-#else
-void BQ_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order2_Taps_t *pTaps,
-                                            BQ_C16_Coefs_t          *pCoef);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
                                   LVM_FLOAT               *pDataIn,
                                   LVM_FLOAT               *pDataOut,
                                   LVM_INT16               NrSamples);
-#else
-void BQ_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                   *pDataIn,
-                                            LVM_INT16                   *pDataOut,
-                                            LVM_INT16                   NrSamples);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
                                          Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
                                          BQ_FLOAT_Coefs_t            *pCoef);
-#else
-void BQ_1I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order2_Taps_t *pTaps,
-                                            BQ_C16_Coefs_t          *pCoef);
 
-#endif
-
-#ifdef BUILD_FLOAT
 void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
                                   LVM_FLOAT              *pDataIn,
                                   LVM_FLOAT               *pDataOut,
                                   LVM_INT16               NrSamples);
-#else
-void BQ_1I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-
-#endif
 /*** 32 bit data path *************************************************************/
-#ifdef BUILD_FLOAT
 void BQ_2I_D32F32Cll_TRC_WRA_01_Init (      Biquad_FLOAT_Instance_t       *pInstance,
                                             Biquad_2I_Order2_FLOAT_Taps_t *pTaps,
                                             BQ_FLOAT_Coefs_t          *pCoef);
@@ -392,67 +192,30 @@
                                             LVM_INT16                    NrFrames,
                                             LVM_INT16                    NrChannels);
 #endif
-#else
-void BQ_2I_D32F32Cll_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_2I_Order2_Taps_t *pTaps,
-                                            BQ_C32_Coefs_t          *pCoef);
-
-void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT32                    *pDataIn,
-                                            LVM_INT32                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES: FIRST ORDER FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path *************************************************************/
-#ifdef BUILD_FLOAT
 void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_FLOAT_Instance_t         *pInstance,
                                          Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
                                          FO_FLOAT_Coefs_t            *pCoef);
-#else
-void FO_1I_D16F16Css_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order1_Taps_t *pTaps,
-                                            FO_C16_Coefs_t          *pCoef);
-#endif
 
-#ifdef BUILD_FLOAT
 void FO_1I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
                                  LVM_FLOAT               *pDataIn,
                                  LVM_FLOAT               *pDataOut,
                                  LVM_INT16               NrSamples);
-#else
-void FO_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                   *pDataIn,
-                                            LVM_INT16                   *pDataOut,
-                                            LVM_INT16                   NrSamples);
-#endif
 
-#ifdef BUILD_FLOAT
 void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t       *pInstance,
                                           Biquad_2I_Order1_FLOAT_Taps_t *pTaps,
                                           FO_FLOAT_LShx_Coefs_t     *pCoef);
-#else
-void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t       *pInstance,
-                                          Biquad_2I_Order1_Taps_t *pTaps,
-                                          FO_C16_LShx_Coefs_t     *pCoef);
-#endif
 
-#ifdef BUILD_FLOAT
 void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
                                      LVM_FLOAT               *pDataIn,
                                      LVM_FLOAT               *pDataOut,
                                      LVM_INT16               NrSamples);
-#else
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
-                                     LVM_INT16               *pDataIn,
-                                     LVM_INT16               *pDataOut,
-                                     LVM_INT16               NrSamples);
-#endif
 /*** 32 bit data path *************************************************************/
-#ifdef BUILD_FLOAT
 void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t       *pInstance,
                                       Biquad_1I_Order1_FLOAT_Taps_t *pTaps,
                                       FO_FLOAT_Coefs_t          *pCoef);
@@ -467,22 +230,11 @@
                                      LVM_INT16                NrFrames,
                                      LVM_INT16                NrChannels);
 #endif
-#else
-void FO_1I_D32F32Cll_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order1_Taps_t *pTaps,
-                                            FO_C32_Coefs_t          *pCoef);
-
-void FO_1I_D32F32C31_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT32               *pDataIn,
-                                            LVM_INT32               *pDataOut,
-                                            LVM_INT16               NrSamples);
-#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES: BAND PASS FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path *************************************************************/
-#ifdef BUILD_FLOAT
 void BP_1I_D16F16Css_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t       *pInstance,
                                       Biquad_1I_Order2_FLOAT_Taps_t *pTaps,
                                       BP_FLOAT_Coefs_t              *pCoef);
@@ -497,27 +249,7 @@
                                             LVM_FLOAT                    *pDataIn,
                                             LVM_FLOAT                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-#else
-void BP_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order2_Taps_t *pTaps,
-                                            BP_C16_Coefs_t          *pCoef);
-
-void BP_1I_D16F16C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-
-void BP_1I_D16F32Cll_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order2_Taps_t *pTaps,
-                                            BP_C32_Coefs_t          *pCoef);
-
-void BP_1I_D16F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
 /*** 32 bit data path *************************************************************/
-#ifdef BUILD_FLOAT
 void BP_1I_D32F32Cll_TRC_WRA_02_Init (      Biquad_FLOAT_Instance_t       *pInstance,
                                             Biquad_1I_Order2_FLOAT_Taps_t *pTaps,
                                             BP_FLOAT_Coefs_t          *pCoef);
@@ -525,37 +257,11 @@
                                             LVM_FLOAT                    *pDataIn,
                                             LVM_FLOAT                    *pDataOut,
                                             LVM_INT16                    NrSamples);
-#else
-void BP_1I_D32F32Cll_TRC_WRA_02_Init (      Biquad_Instance_t       *pInstance,
-                                            Biquad_1I_Order2_Taps_t *pTaps,
-                                            BP_C32_Coefs_t          *pCoef);
-
-void BP_1I_D32F32C30_TRC_WRA_02(            Biquad_Instance_t       *pInstance,
-                                            LVM_INT32                    *pDataIn,
-                                            LVM_INT32                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
 
 /*** 32 bit data path STEREO ******************************************************/
-#ifndef BUILD_FLOAT
-void PK_2I_D32F32CllGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
-                                            Biquad_2I_Order2_Taps_t *pTaps,
-                                            PK_C32_Coefs_t          *pCoef);
-void PK_2I_D32F32C30G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
-                                            LVM_INT32                    *pDataIn,
-                                            LVM_INT32                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
-#ifdef BUILD_FLOAT
 void PK_2I_D32F32CssGss_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t       *pInstance,
                                             Biquad_2I_Order2_FLOAT_Taps_t *pTaps,
                                             PK_FLOAT_Coefs_t          *pCoef);
-#else
-void PK_2I_D32F32CssGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
-                                            Biquad_2I_Order2_Taps_t *pTaps,
-                                            PK_C16_Coefs_t          *pCoef);
-#endif
-#ifdef BUILD_FLOAT
 void PK_2I_D32F32C14G11_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
                                     LVM_FLOAT               *pDataIn,
                                     LVM_FLOAT               *pDataOut,
@@ -567,19 +273,12 @@
                                    LVM_INT16               NrFrames,
                                    LVM_INT16               NrChannels);
 #endif
-#else
-void PK_2I_D32F32C14G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
-                                            LVM_INT32                    *pDataIn,
-                                            LVM_INT32                    *pDataOut,
-                                            LVM_INT16                    NrSamples);
-#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES: DC REMOVAL FILTERS
 ***********************************************************************************/
 
 /*** 16 bit data path STEREO ******************************************************/
-#ifdef BUILD_FLOAT
 #ifdef SUPPORT_MC
 void DC_Mc_D16_TRC_WRA_01_Init     (        Biquad_FLOAT_Instance_t       *pInstance);
 
@@ -596,18 +295,6 @@
                                             LVM_FLOAT               *pDataOut,
                                             LVM_INT16               NrSamples);
 #endif
-#else
-void DC_2I_D16_TRC_WRA_01_Init     (        Biquad_Instance_t       *pInstance);
-
-void DC_2I_D16_TRC_WRA_01          (        Biquad_Instance_t       *pInstance,
-                                            LVM_INT16               *pDataIn,
-                                            LVM_INT16               *pDataOut,
-                                            LVM_INT16               NrSamples);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 
 /**********************************************************************************/
 
diff --git a/media/libeffects/lvm/lib/Common/lib/CompLim.h b/media/libeffects/lvm/lib/Common/lib/CompLim.h
index 498faa3..5b7cb1b 100644
--- a/media/libeffects/lvm/lib/Common/lib/CompLim.h
+++ b/media/libeffects/lvm/lib/Common/lib/CompLim.h
@@ -18,11 +18,6 @@
 #ifndef _COMP_LIM_H
 #define _COMP_LIM_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Includes                                                                        */
@@ -31,7 +26,6 @@
 
 #include "LVM_Types.h"
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Structures                                                                      */
@@ -57,31 +51,17 @@
     LVM_INT32   CompIntSlow;        /* Compressor slow integrator current value */
     LVM_INT32   CompIntFast;        /* Compressor fast integrator current value */
 
-
 } CompLim_Instance_t;
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Function Prototypes                                                             */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 void NonLinComp_Float(LVM_FLOAT        Gain,
                       LVM_FLOAT        *pDataIn,
                       LVM_FLOAT        *pDataOut,
                       LVM_INT32        BlockLength);
-#else
-void NonLinComp_D16(LVM_INT16        Gain,
-                    LVM_INT16        *pSterBfIn,
-                    LVM_INT16        *pSterBfOut,
-                    LVM_INT32        BlockLength);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif /* #ifndef _COMP_LIM_H */
 
-
-
diff --git a/media/libeffects/lvm/lib/Common/lib/Filter.h b/media/libeffects/lvm/lib/Common/lib/Filter.h
index 0c8955d..1eeb321 100644
--- a/media/libeffects/lvm/lib/Common/lib/Filter.h
+++ b/media/libeffects/lvm/lib/Common/lib/Filter.h
@@ -18,39 +18,27 @@
 #ifndef _FILTER_H_
 #define _FILTER_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /**********************************************************************************
    INCLUDES
 ***********************************************************************************/
 #include "LVM_Types.h"
 #include "BIQUAD.h"
 
-
 /**********************************************************************************
    DEFINES
 ***********************************************************************************/
 #define FILTER_LOSS     32730       /* -0.01dB loss to avoid wrapping due to band ripple */
-#ifdef BUILD_FLOAT
 #define FILTER_LOSS_FLOAT    0.998849f
-#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES
 ***********************************************************************************/
-#ifdef BUILD_FLOAT
 
 LVM_FLOAT LVM_Power10(   LVM_FLOAT  X);
 
 LVM_FLOAT LVM_Polynomial(LVM_UINT16 N,
                          LVM_FLOAT  *pCoefficients,
                          LVM_FLOAT  X);
-#ifdef HIGHER_FS
 LVM_FLOAT   LVM_GetOmega(LVM_UINT32  Fc,
-#else
-LVM_FLOAT   LVM_GetOmega(LVM_UINT16  Fc,
-#endif
                          LVM_Fs_en   SampleRate);
 
 LVM_FLOAT LVM_FO_LPF(    LVM_FLOAT  w,
@@ -58,26 +46,7 @@
 
 LVM_FLOAT LVM_FO_HPF(    LVM_FLOAT  w,
                          FO_FLOAT_Coefs_t  *pCoeffs);
-#else
-LVM_INT32 LVM_Polynomial(LVM_UINT16 N,
-                         LVM_INT32  *pCoefficients,
-                         LVM_INT32  X);
-
-LVM_INT32 LVM_Power10(   LVM_INT32  X);
-
-LVM_INT32 LVM_FO_LPF(    LVM_INT32  w,
-                         FO_C32_Coefs_t  *pCoeffs);
-
-LVM_INT32 LVM_FO_HPF(    LVM_INT32  w,
-                         FO_C32_Coefs_t  *pCoeffs);
-
-LVM_INT32   LVM_GetOmega(LVM_UINT16  Fc,
-                         LVM_Fs_en   SampleRate);
-#endif
 /**********************************************************************************/
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /** _FILTER_H_ **/
 
diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
index 7f725f4..bae84e7 100644
--- a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
+++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
@@ -18,10 +18,6 @@
 #ifndef __INSTALLOC_H__
 #define __INSTALLOC_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include "LVM_Types.h"
 /*######################################################################################*/
 /*  Type declarations                                                                   */
@@ -32,7 +28,6 @@
     uintptr_t               pNextMember;    /*  Pointer to the next instance member to be allocated */
 }   INST_ALLOC;
 
-
 /*######################################################################################*/
 /*  Function prototypes                                                          */
 /*######################################################################################*/
@@ -48,7 +43,6 @@
 
 void   InstAlloc_Init( INST_ALLOC *pms, void *StartAddr );
 
-
 /****************************************************************************************
  *  Name        : InstAlloc_AddMember()
  *  Input       : pms  - Pointer to the INST_ALLOC instance
@@ -85,8 +79,4 @@
 
 void    InstAlloc_InitAll_NULL( INST_ALLOC              *pms);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* __JBS_INSTALLOC_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Common.h b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
index ceccd7b..49f16ad 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
@@ -23,15 +23,9 @@
 /*                                                                                      */
 /****************************************************************************************/
 
-
 #ifndef __LVM_COMMON_H__
 #define __LVM_COMMON_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -39,7 +33,6 @@
 /****************************************************************************************/
 #include "LVM_Types.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Definitions                                                                         */
@@ -53,9 +46,5 @@
 #define ALGORITHM_VC_ID        0x0500
 #define ALGORITHM_TE_ID        0x0600
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif      /* __LVM_COMMON_H__ */
 
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
index 97d13a5..1a15125 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
@@ -18,10 +18,6 @@
 #ifndef _LVM_MACROS_H_
 #define _LVM_MACROS_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /**********************************************************************************
    MUL32x32INTO32(A,B,C,ShiftR)
         C = (A * B) >> ShiftR
@@ -32,7 +28,6 @@
         of overflow is undefined.
 
 ***********************************************************************************/
-#ifndef MUL32x32INTO32
 #define MUL32x32INTO32(A,B,C,ShiftR)   \
         {LVM_INT32 MUL32x32INTO32_temp,MUL32x32INTO32_temp2,MUL32x32INTO32_mask,MUL32x32INTO32_HH,MUL32x32INTO32_HL,MUL32x32INTO32_LH,MUL32x32INTO32_LL;\
          LVM_INT32  shiftValue;\
@@ -58,7 +53,6 @@
        }\
        (C) = MUL32x32INTO32_temp2;\
        }
-#endif
 
 /**********************************************************************************
    MUL32x16INTO32(A,B,C,ShiftR)
@@ -71,7 +65,6 @@
         of overflow is undefined.
 
 ***********************************************************************************/
-#ifndef MUL32x16INTO32
 #define MUL32x16INTO32(A,B,C,ShiftR)   \
         {LVM_INT32 MUL32x16INTO32_mask,MUL32x16INTO32_HH,MUL32x16INTO32_LL;\
          LVM_INT32  shiftValue;\
@@ -91,7 +84,6 @@
         else {\
         (C)=MUL32x16INTO32_HH>>(shiftValue-16);}\
         }
-#endif
 
 /**********************************************************************************
    ADD2_SAT_32x32(A,B,C)
@@ -99,7 +91,6 @@
 
         A,B and C are 32 bit SIGNED numbers.
 ***********************************************************************************/
-#ifndef ADD2_SAT_32x32
 #define ADD2_SAT_32x32(A,B,C)   \
         {(C)=(A)+(B);\
          if ((((C) ^ (A)) & ((C) ^ (B))) >> 31)\
@@ -110,12 +101,6 @@
                     (C)=0x7FFFFFFFl;\
             }\
         }
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif /* _LVM_MACROS_H_ */
 
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
index a76354d..dbf9e6a 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
@@ -33,11 +33,6 @@
 /*  The timer currently does not suport changes in sampling rate while timing.          */
 /****************************************************************************************/
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /****************************************************************************************/
 /*  TYPE DEFINITIONS                                                                    */
 /****************************************************************************************/
@@ -74,17 +69,11 @@
 void LVM_Timer_Init (   LVM_Timer_Instance_t       *pInstance,
                         LVM_Timer_Params_t         *pParams     );
 
-
 void LVM_Timer      (   LVM_Timer_Instance_t       *pInstance,
                         LVM_INT16                       BlockSize );
 
-
 /****************************************************************************************/
 /*  END OF HEADER                                                                       */
 /****************************************************************************************/
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif  /* __LVM_TIMER_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index fbfdd4d..8b687f6 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -25,10 +25,6 @@
 #ifndef LVM_TYPES_H
 #define LVM_TYPES_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include <stdint.h>
 
 /****************************************************************************************/
@@ -96,32 +92,15 @@
 typedef     uint32_t            LVM_UINT32;         /* Unsigned 32-bit word */
 typedef     int64_t             LVM_INT64;          /* Signed 64-bit word */
 
-#ifdef BUILD_FLOAT
-
 #define LVM_MAXFLOAT            1.f
 
 typedef     float               LVM_FLOAT;          /* single precision floating point */
 
-// If NATIVE_FLOAT_BUFFER is defined, we expose effects as floating point format;
-// otherwise we expose as integer 16 bit and translate to float for the effect libraries.
-// Hence, NATIVE_FLOAT_BUFFER should only be enabled under BUILD_FLOAT compilation.
-
-#define NATIVE_FLOAT_BUFFER
-
-#endif // BUILD_FLOAT
-
 // Select whether we expose int16_t or float buffers.
-#ifdef NATIVE_FLOAT_BUFFER
 
 #define    EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
 typedef     float               effect_buffer_t;
 
-#else // NATIVE_FLOAT_BUFFER
-
-#define    EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
-typedef     int16_t             effect_buffer_t;
-
-#endif // NATIVE_FLOAT_BUFFER
 
 #ifdef SUPPORT_MC
 #define LVM_MAX_CHANNELS 8 // FCC_8
@@ -143,7 +122,6 @@
     LVM_MODE_DUMMY  = LVM_MAXENUM
 } LVM_Mode_en;
 
-
 /* Format */
 typedef enum
 {
@@ -156,7 +134,6 @@
     LVM_SOURCE_DUMMY    = LVM_MAXENUM
 } LVM_Format_en;
 
-
 /* LVM sampling rates */
 typedef enum
 {
@@ -169,17 +146,14 @@
     LVM_FS_32000 = 6,
     LVM_FS_44100 = 7,
     LVM_FS_48000 = 8,
-#ifdef HIGHER_FS
     LVM_FS_88200 = 9,
     LVM_FS_96000 = 10,
     LVM_FS_176400 = 11,
     LVM_FS_192000 = 12,
-#endif
     LVM_FS_INVALID = LVM_MAXENUM-1,
     LVM_FS_DUMMY = LVM_MAXENUM
 } LVM_Fs_en;
 
-
 /* Memory Types */
 typedef enum
 {
@@ -190,7 +164,6 @@
     LVM_MEMORYTYPE_DUMMY        = LVM_MAXENUM
 } LVM_MemoryTypes_en;
 
-
 /* Memory region definition */
 typedef struct
 {
@@ -199,14 +172,12 @@
     void                        *pBaseAddress;          /* Pointer to the region base address */
 } LVM_MemoryRegion_st;
 
-
 /* Memory table containing the region definitions */
 typedef struct
 {
     LVM_MemoryRegion_st         Region[LVM_NR_MEMORY_REGIONS];  /* One definition for each region */
 } LVM_MemoryTable_st;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Standard Function Prototypes                                                        */
@@ -216,15 +187,10 @@
                                   void          *pGeneralPurpose,   /* General purpose pointer (e.g. to a data structure needed in the callback) */
                                   LVM_INT16     GeneralPurpose );   /* General purpose variable (e.g. to be used as callback ID) */
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  End of file                                                                         */
 /*                                                                                      */
 /****************************************************************************************/
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif  /* LVM_TYPES_H */
diff --git a/media/libeffects/lvm/lib/Common/lib/Mixer.h b/media/libeffects/lvm/lib/Common/lib/Mixer.h
index 07c53cd..b2e0195 100644
--- a/media/libeffects/lvm/lib/Common/lib/Mixer.h
+++ b/media/libeffects/lvm/lib/Common/lib/Mixer.h
@@ -18,19 +18,12 @@
 #ifndef __MIXER_H__
 #define __MIXER_H__
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 #include "LVM_Types.h"
 
 /**********************************************************************************
    INSTANCE MEMORY TYPE DEFINITION
 ***********************************************************************************/
 
-#ifdef BUILD_FLOAT /* BUILD_FLOAT*/
 typedef struct
 {
     LVM_FLOAT   Alpha;                   /* Time constant. Set by calling application. \
@@ -66,52 +59,11 @@
     void        *pGeneralPurpose2;
     LVM_Callback pCallBack2;
 } Mix_2St_Cll_FLOAT_t;
-#else
-typedef struct
-{
-    LVM_INT32   Alpha;                    /* Time constant. Set by calling application.  Can be changed at any time */
-    LVM_INT32   Target;                   /* Target value.  Set by calling application.  Can be changed at any time */
-    LVM_INT32   Current;                  /* Current value.  Set by the mixer function. */
-    LVM_INT16   CallbackSet;              /* Boolean.  Should be set by calling application each time the target value is updated */
-    LVM_INT16   CallbackParam;            /* Parameter that will be used in the calback function */
-    void        *pCallbackHandle;         /* Pointer to the instance of the callback function */
-    void        *pGeneralPurpose;         /* Pointer for general purpose usage */
-    LVM_Callback pCallBack;               /* Pointer to the callback function */
-} Mix_1St_Cll_t;
-
-typedef struct
-{
-    LVM_INT32   Alpha1;
-    LVM_INT32   Target1;
-    LVM_INT32   Current1;
-    LVM_INT16   CallbackSet1;
-    LVM_INT16   CallbackParam1;
-    void        *pCallbackHandle1;
-    void        *pGeneralPurpose1;
-    LVM_Callback pCallBack1;
-
-    LVM_INT32   Alpha2;                   /* Warning the address of this location is passed as a pointer to Mix_1St_Cll_t in some functions */
-    LVM_INT32   Target2;
-    LVM_INT32   Current2;
-    LVM_INT16   CallbackSet2;
-    LVM_INT16   CallbackParam2;
-    void        *pCallbackHandle2;
-    void        *pGeneralPurpose2;
-    LVM_Callback pCallBack2;
-
-} Mix_2St_Cll_t;
-
-#endif
 
 /*** General functions ************************************************************/
-#ifdef BUILD_FLOAT
 
 LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32   tc,
-#ifdef HIGHER_FS
                                  LVM_UINT32   Fs,
-#else
-                                 LVM_UINT16   Fs,
-#endif
                                  LVM_UINT16   NumChannels);
 
 void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_FLOAT_t       *pInstance,
@@ -129,34 +81,10 @@
                                 const LVM_FLOAT     *src,
                                 LVM_FLOAT     *dst,
                                 LVM_INT16     n);
-#else
-LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
-                                  LVM_UINT16   Fs,
-                                  LVM_UINT16   NumChannels);
-
-
-void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_t       *pInstance,
-                                const LVM_INT32     *src,
-                                      LVM_INT32     *dst,
-                                      LVM_INT16     n);
-
-void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_t       *pInstance,
-                                const LVM_INT32     *src1,
-                                const LVM_INT32     *src2,
-                                      LVM_INT32     *dst,
-                                      LVM_INT16     n);
-
-void MixInSoft_D32C31_SAT(      Mix_1St_Cll_t       *pInstance,
-                                const LVM_INT32     *src,
-                                      LVM_INT32     *dst,
-                                      LVM_INT16     n);
-
-#endif
 
 /**********************************************************************************
    FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
 ***********************************************************************************/
-#ifdef BUILD_FLOAT
 void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_FLOAT_t       *pInstance,
                                     const LVM_FLOAT     *src,
                                     LVM_FLOAT     *dst,
@@ -170,27 +98,6 @@
                                     const LVM_FLOAT     *src,
                                     LVM_FLOAT     *dst,
                                     LVM_INT16     n);
-#else
-void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-
-void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src1,
-                                    const LVM_INT32     *src2,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-
-void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 
 /**********************************************************************************/
 
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
index cdb3837..ae54419 100644
--- a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -18,11 +18,6 @@
 #ifndef __SCALARARITHMETIC_H__
 #define __SCALARARITHMETIC_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /*######################################################################################*/
 /*  Include files                                                                       */
 /*######################################################################################*/
@@ -35,11 +30,7 @@
 
 /* Absolute value including the corner case for the extreme negative value */
 
-#ifdef BUILD_FLOAT
 LVM_FLOAT   Abs_Float(LVM_FLOAT     input);
-#else
-LVM_INT32   Abs_32(LVM_INT32     input);
-#endif
 
 /****************************************************************************************
  *  Name        : dB_to_Lin32()
@@ -53,16 +44,7 @@
  *                  (15->01) = decimal part
  *  Returns     : Lin value format 1.16.15
  ****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVM_FLOAT dB_to_LinFloat(LVM_INT16    db_fix);
-#else
-LVM_INT32 dB_to_Lin32(LVM_INT16  db_fix);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* __SCALARARITHMETIC_H__ */
 
-
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 7468a90..b27bac5 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -18,32 +18,16 @@
 #ifndef _VECTOR_ARITHMETIC_H_
 #define _VECTOR_ARITHMETIC_H_
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include "LVM_Types.h"
 
 /**********************************************************************************
     VARIOUS FUNCTIONS
 ***********************************************************************************/
 
-#ifdef BUILD_FLOAT
 void LoadConst_Float(          const LVM_FLOAT val,
                                LVM_FLOAT *dst,
                                LVM_INT16 n );
-#else
-void LoadConst_16(            const LVM_INT16 val,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n );
 
-void LoadConst_32(            const LVM_INT32 val,
-                                    LVM_INT32 *dst,
-                                    LVM_INT16 n );
-#endif
-
-#ifdef BUILD_FLOAT
 void Copy_Float(                 const LVM_FLOAT *src,
                                  LVM_FLOAT *dst,
                                  LVM_INT16 n );
@@ -53,15 +37,11 @@
                                  LVM_INT16 NrFrames,
                                  LVM_INT32 NrChannels);
 void Copy_Float_Stereo_Mc(       const LVM_FLOAT *src,
+                                 LVM_FLOAT *StereoOut,
                                  LVM_FLOAT *dst,
                                  LVM_INT16 NrFrames,
                                  LVM_INT32 NrChannels);
 #endif
-#else
-void Copy_16(                 const LVM_INT16 *src,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n );
-#endif
 
 /*********************************************************************************
  * note: In Mult3s_16x16() saturation of result is not taken care when           *
@@ -71,17 +51,10 @@
  *       This is the only case which will give wrong result.                     *
  *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
  *********************************************************************************/
-#ifdef BUILD_FLOAT
 void Mult3s_Float(            const LVM_FLOAT *src,
                               const LVM_FLOAT val,
                               LVM_FLOAT *dst,
                               LVM_INT16 n);
-#else
-void Mult3s_16x16(            const LVM_INT16 *src,
-                              const LVM_INT16 val,
-                              LVM_INT16 *dst,
-                              LVM_INT16 n);
-#endif
 
 /*********************************************************************************
  * note: In Mult3s_32x16() saturation of result is not taken care when           *
@@ -95,55 +68,24 @@
                               const LVM_INT16 val,
                                     LVM_INT32  *dst,
                                     LVM_INT16 n);
-#ifdef BUILD_FLOAT
 void DelayMix_Float(const LVM_FLOAT *src,           /* Source 1, to be delayed */
                     LVM_FLOAT *delay,         /* Delay buffer */
                     LVM_INT16 size,           /* Delay size */
                     LVM_FLOAT *dst,           /* Source/destination */
                     LVM_INT16 *pOffset,       /* Delay offset */
                     LVM_INT16 n)  ;            /* Number of stereo samples */
-#else
-void DelayMix_16x16(          const LVM_INT16 *src,
-                                    LVM_INT16 *delay,
-                                    LVM_INT16 size,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 *pOffset,
-                                    LVM_INT16 n);
-#endif
 void DelayWrite_32(           const LVM_INT32  *src,               /* Source 1, to be delayed */
                                     LVM_INT32  *delay,             /* Delay buffer */
                                     LVM_UINT16 size,               /* Delay size */
                                     LVM_UINT16 *pOffset,           /* Delay offset */
                                     LVM_INT16 n);
-#ifdef BUILD_FLOAT
 void Add2_Sat_Float(          const LVM_FLOAT *src,
                               LVM_FLOAT *dst,
                               LVM_INT16 n );
-#else
-void Add2_Sat_16x16(          const LVM_INT16 *src,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n );
-
-void Add2_Sat_32x32(          const LVM_INT32  *src,
-                                    LVM_INT32  *dst,
-                                    LVM_INT16 n );
-#endif
-#ifdef BUILD_FLOAT
 void Mac3s_Sat_Float(         const LVM_FLOAT *src,
                               const LVM_FLOAT val,
                               LVM_FLOAT *dst,
                               LVM_INT16 n);
-#else
-void Mac3s_Sat_16x16(         const LVM_INT16 *src,
-                              const LVM_INT16 val,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n);
-
-void Mac3s_Sat_32x16(         const LVM_INT32  *src,
-                              const LVM_INT16 val,
-                                    LVM_INT32  *dst,
-                                    LVM_INT16 n);
-#endif
 void DelayAllPass_Sat_32x16To32(    LVM_INT32  *delay,              /* Delay buffer */
                                     LVM_UINT16 size,                /* Delay size */
                                     LVM_INT16 coeff,                /* All pass filter coefficient */
@@ -155,39 +97,16 @@
 /**********************************************************************************
     SHIFT FUNCTIONS
 ***********************************************************************************/
-#ifdef BUILD_FLOAT
 void Shift_Sat_Float (const   LVM_INT16   val,
                       const   LVM_FLOAT   *src,
                       LVM_FLOAT   *dst,
                       LVM_INT16   n);
-#else
-void Shift_Sat_v16xv16 (      const LVM_INT16 val,
-                              const LVM_INT16 *src,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n);
-
-void Shift_Sat_v32xv32 (      const LVM_INT16 val,
-                              const LVM_INT32 *src,
-                                    LVM_INT32 *dst,
-                                    LVM_INT16 n);
-#endif
 /**********************************************************************************
     AUDIO FORMAT CONVERSION FUNCTIONS
 ***********************************************************************************/
-#ifdef BUILD_FLOAT
 void MonoTo2I_Float( const LVM_FLOAT     *src,
                      LVM_FLOAT     *dst,
                      LVM_INT16 n);
-#else
-void MonoTo2I_16(             const LVM_INT16 *src,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n);
-
-void MonoTo2I_32(             const LVM_INT32  *src,
-                                    LVM_INT32  *dst,
-                                    LVM_INT16 n);
-#endif
-#ifdef BUILD_FLOAT
 void From2iToMono_Float(         const LVM_FLOAT  *src,
                                  LVM_FLOAT  *dst,
                                  LVM_INT16 n);
@@ -197,47 +116,18 @@
                         LVM_INT16 NrFrames,
                         LVM_INT16 NrChannels);
 #endif
-#else
-void From2iToMono_32(         const LVM_INT32  *src,
-                                    LVM_INT32  *dst,
-                                    LVM_INT16 n);
-#endif
-#ifdef BUILD_FLOAT
 void MSTo2i_Sat_Float(        const LVM_FLOAT *srcM,
                               const LVM_FLOAT *srcS,
                               LVM_FLOAT *dst,
                               LVM_INT16 n );
-#else
-void MSTo2i_Sat_16x16(        const LVM_INT16 *srcM,
-                              const LVM_INT16 *srcS,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n );
-#endif
-#ifdef BUILD_FLOAT
 void From2iToMS_Float(        const LVM_FLOAT *src,
                               LVM_FLOAT *dstM,
                               LVM_FLOAT *dstS,
                               LVM_INT16 n );
-#else
-void From2iToMS_16x16(        const LVM_INT16 *src,
-                                    LVM_INT16 *dstM,
-                                    LVM_INT16 *dstS,
-                                    LVM_INT16 n );
-#endif
-#ifdef BUILD_FLOAT
 void JoinTo2i_Float(          const LVM_FLOAT  *srcL,
                               const LVM_FLOAT  *srcR,
                               LVM_FLOAT  *dst,
                               LVM_INT16 n );
-#else
-void From2iToMono_16(         const LVM_INT16 *src,
-                                    LVM_INT16 *dst,
-                                    LVM_INT16 n);
-void JoinTo2i_32x32(          const LVM_INT32  *srcL,
-                              const LVM_INT32  *srcR,
-                              LVM_INT32  *dst,
-                              LVM_INT16 n );
-#endif
 
 /**********************************************************************************
     DATA TYPE CONVERSION FUNCTIONS
@@ -253,11 +143,6 @@
                                     LVM_INT16 n,
                                     LVM_INT16 shift );
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
 /**********************************************************************************/
 
 #endif  /* _VECTOR_ARITHMETIC_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
deleted file mode 100644
index 5c8655f..0000000
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "AGC.h"
-#include "ScalarArithmetic.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Defines                                                                           */
-/*                                                                                      */
-/****************************************************************************************/
-
-#define VOL_TC_SHIFT                                        21          /* As a power of 2 */
-#define DECAY_SHIFT                                        10           /* As a power of 2 */
-#ifdef BUILD_FLOAT
-#define VOL_TC_FLOAT                                      2.0f          /* As a power of 2 */
-#define DECAY_FAC_FLOAT                                  64.0f          /* As a power of 2 */
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                  AGC_MIX_VOL_2St1Mon_D32_WRA                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Apply AGC and mix signals                                                         */
-/*                                                                                      */
-/*                                                                                      */
-/*  StSrc   ------------------|                                                         */
-/*                            |                                                         */
-/*              ______       _|_        ________                                        */
-/*             |      |     |   |      |        |                                       */
-/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
-/*             | Gain |     |___|      | Gain   |                              |        */
-/*             |______|                |________|                              |        */
-/*                /|\                               __________     ________    |        */
-/*                 |                               |          |   |        |   |        */
-/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
-/*                                                 | Update   |   | Detect |            */
-/*                                                 |__________|   |________|            */
-/*                                                                                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pInstance               Instance pointer                                            */
-/*  pStereoIn               Stereo source                                               */
-/*  pMonoIn                 Mono band pass source                                       */
-/*  pStereoOut              Stereo destination                                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  Void                                                                                */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifndef BUILD_FLOAT
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
-                                 const LVM_INT32            *pStSrc,        /* Stereo source */
-                                 const LVM_INT32            *pMonoSrc,      /* Mono source */
-                                 LVM_INT32                  *pDst,          /* Stereo destination */
-                                 LVM_UINT16                 NumSamples)     /* Number of samples */
-{
-
-    /*
-     * General variables
-     */
-    LVM_UINT16      i;                                          /* Sample index */
-    LVM_INT32       Left;                                       /* Left sample */
-    LVM_INT32       Right;                                      /* Right sample */
-    LVM_INT32       Mono;                                       /* Mono sample */
-    LVM_INT32       AbsPeak;                                    /* Absolute peak signal */
-    LVM_INT32       HighWord;                                   /* High word in intermediate calculations */
-    LVM_INT32       LowWord;                                    /* Low word in intermediate calculations */
-    LVM_INT16       AGC_Mult;                                   /* Short AGC gain */
-    LVM_INT16       Vol_Mult;                                   /* Short volume */
-
-
-    /*
-     * Instance control variables
-     */
-    LVM_INT32      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
-    LVM_INT32      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
-    LVM_INT16      AGC_GainShift = pInstance->AGC_GainShift;    /* Get the AGC shift */
-    LVM_INT16      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
-    LVM_INT16      AGC_Decay     = pInstance->AGC_Decay;        /* Decay scaler */
-    LVM_INT32      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
-    LVM_INT32      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
-    LVM_INT32      Vol_Target    = pInstance->Target;           /* Target volume setting */
-    LVM_INT16      Vol_Shift     = pInstance->VolumeShift;      /* Volume shift scaling */
-    LVM_INT16      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
-
-
-    /*
-     * Process on a sample by sample basis
-     */
-    for (i=0;i<NumSamples;i++)                                  /* For each sample */
-    {
-
-        /*
-         * Get the short scalers
-         */
-        AGC_Mult    = (LVM_INT16)(AGC_Gain >> 16);              /* Get the short AGC gain */
-        Vol_Mult    = (LVM_INT16)(Vol_Current >> 16);           /* Get the short volume gain */
-
-
-        /*
-         * Get the input samples
-         */
-        Left  = *pStSrc++;                                      /* Get the left sample */
-        Right = *pStSrc++;                                      /* Get the right sample */
-        Mono  = *pMonoSrc++;                                    /* Get the mono sample */
-
-
-        /*
-         * Apply the AGC gain to the mono input and mix with the stereo signal
-         */
-        HighWord = (AGC_Mult * (Mono >> 16));                   /* signed long (Mono) by unsigned short (AGC_Mult) multiply */
-        LowWord = (AGC_Mult * (Mono & 0xffff));
-        Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift);
-        Left  += Mono;                                          /* Mix in the mono signal */
-        Right += Mono;
-
-
-        /*
-         * Apply the volume and write to the output stream
-         */
-        HighWord = (Vol_Mult * (Left >> 16));                   /* signed long (Left) by unsigned short (Vol_Mult) multiply */
-        LowWord = (Vol_Mult * (Left & 0xffff));
-        Left = (HighWord + (LowWord >> 16)) << (Vol_Shift);
-        HighWord = (Vol_Mult * (Right >> 16));                  /* signed long (Right) by unsigned short (Vol_Mult) multiply */
-        LowWord = (Vol_Mult * (Right & 0xffff));
-        Right = (HighWord + (LowWord >> 16)) << (Vol_Shift);
-        *pDst++ = Left;                                         /* Save the results */
-        *pDst++ = Right;
-
-
-        /*
-         * Update the AGC gain
-         */
-        AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right);  /* Get the absolute peak */
-        if (AbsPeak > AGC_Target)
-        {
-            /*
-             * The signal is too large so decrease the gain
-             */
-            HighWord = (AGC_Attack * (AGC_Gain >> 16));         /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */
-            LowWord = (AGC_Attack * (AGC_Gain & 0xffff));
-            AGC_Gain = (HighWord + (LowWord >> 16)) << 1;
-        }
-        else
-        {
-            /*
-             * The signal is too small so increase the gain
-             */
-            if (AGC_Gain > AGC_MaxGain)
-            {
-                AGC_Gain -= (AGC_Decay << DECAY_SHIFT);
-            }
-            else
-            {
-                AGC_Gain += (AGC_Decay << DECAY_SHIFT);
-            }
-        }
-
-        /*
-         * Update the gain
-         */
-        Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT);
-    }
-
-
-    /*
-     * Update the parameters
-     */
-    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
-    pInstance->AGC_Gain = AGC_Gain;
-
-    return;
-}
-#else
-void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
-                                 const LVM_FLOAT            *pStSrc,        /* Stereo source */
-                                 const LVM_FLOAT            *pMonoSrc,      /* Mono source */
-                                 LVM_FLOAT                  *pDst,          /* Stereo destination */
-                                 LVM_UINT16                 NumSamples)     /* Number of samples */
-{
-
-    /*
-     * General variables
-     */
-    LVM_UINT16      i;                                          /* Sample index */
-    LVM_FLOAT       Left;                                       /* Left sample */
-    LVM_FLOAT       Right;                                      /* Right sample */
-    LVM_FLOAT       Mono;                                       /* Mono sample */
-    LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
-    LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
-    LVM_FLOAT       Vol_Mult;                                   /* Short volume */
-
-
-    /*
-     * Instance control variables
-     */
-    LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
-    LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
-    LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
-    LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));/* Decay scaler */
-    LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
-    LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
-    LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
-    LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
-
-
-    /*
-     * Process on a sample by sample basis
-     */
-    for (i = 0; i < NumSamples; i++)                                  /* For each sample */
-    {
-
-        /*
-         * Get the short scalers
-         */
-        AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the short AGC gain */
-        Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the short volume gain */
-
-
-        /*
-         * Get the input samples
-         */
-        Left  = *pStSrc++;                                      /* Get the left sample */
-        Right = *pStSrc++;                                      /* Get the right sample */
-        Mono  = *pMonoSrc++;                                    /* Get the mono sample */
-
-
-        /*
-         * Apply the AGC gain to the mono input and mix with the stereo signal
-         */
-        Left  += (Mono * AGC_Mult);                               /* Mix in the mono signal */
-        Right += (Mono * AGC_Mult);
-
-        /*
-         * Apply the volume and write to the output stream
-         */
-        Left  = Left  * Vol_Mult;
-        Right = Right * Vol_Mult;
-        *pDst++ = Left;                                         /* Save the results */
-        *pDst++ = Right;
-
-        /*
-         * Update the AGC gain
-         */
-        AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
-        if (AbsPeak > AGC_Target)
-        {
-            /*
-             * The signal is too large so decrease the gain
-             */
-            AGC_Gain = AGC_Gain * AGC_Attack;
-        }
-        else
-        {
-            /*
-             * The signal is too small so increase the gain
-             */
-            if (AGC_Gain > AGC_MaxGain)
-            {
-                AGC_Gain -= (AGC_Decay);
-            }
-            else
-            {
-                AGC_Gain += (AGC_Decay);
-            }
-        }
-
-        /*
-         * Update the gain
-         */
-        Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
-    }
-
-
-    /*
-     * Update the parameters
-     */
-    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
-    pInstance->AGC_Gain = AGC_Gain;
-
-    return;
-}
-#ifdef SUPPORT_MC
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                  AGC_MIX_VOL_Mc1Mon_D32_WRA                                */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Apply AGC and mix signals                                                         */
-/*                                                                                      */
-/*                                                                                      */
-/*  McSrc   ------------------|                                                         */
-/*                            |                                                         */
-/*              ______       _|_        ________                                        */
-/*             |      |     |   |      |        |                                       */
-/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
-/*             | Gain |     |___|      | Gain   |                              |        */
-/*             |______|                |________|                              |        */
-/*                /|\                               __________     ________    |        */
-/*                 |                               |          |   |        |   |        */
-/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
-/*                                                 | Update   |   | Detect |            */
-/*                                                 |__________|   |________|            */
-/*                                                                                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pInstance               Instance pointer                                            */
-/*  pMcSrc                  Multichannel source                                         */
-/*  pMonoSrc                Mono band pass source                                       */
-/*  pDst                    Multichannel destination                                    */
-/*  NrFrames                Number of frames                                            */
-/*  NrChannels              Number of channels                                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  Void                                                                                */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,
-                                 const LVM_FLOAT            *pMcSrc,
-                                 const LVM_FLOAT            *pMonoSrc,
-                                 LVM_FLOAT                  *pDst,
-                                 LVM_UINT16                 NrFrames,
-                                 LVM_UINT16                 NrChannels)
-{
-
-    /*
-     * General variables
-     */
-    LVM_UINT16      i, jj;                                      /* Sample index */
-    LVM_FLOAT       SampleVal;                                  /* Sample value */
-    LVM_FLOAT       Mono;                                       /* Mono sample */
-    LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
-    LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
-    LVM_FLOAT       Vol_Mult;                                   /* Short volume */
-
-
-    /*
-     * Instance control variables
-     */
-    LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
-    LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
-    LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
-    /* Decay scaler */
-    LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));
-    LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
-    LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
-    LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
-    LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
-
-
-    /*
-     * Process on a sample by sample basis
-     */
-    for (i = 0; i < NrFrames; i++)                                  /* For each frame */
-    {
-
-        /*
-         * Get the scalers
-         */
-        AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the AGC gain */
-        Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the volume gain */
-
-        AbsPeak = 0.0f;
-        /*
-         * Get the input samples
-         */
-        for (jj = 0; jj < NrChannels; jj++)
-        {
-            SampleVal  = *pMcSrc++;                       /* Get the sample value of jj Channel*/
-            Mono       = *pMonoSrc;                       /* Get the mono sample */
-
-            /*
-             * Apply the AGC gain to the mono input and mix with the input signal
-             */
-            SampleVal  += (Mono * AGC_Mult);                        /* Mix in the mono signal */
-
-            /*
-             * Apply the volume and write to the output stream
-             */
-            SampleVal  = SampleVal  * Vol_Mult;
-
-            *pDst++ = SampleVal;                                         /* Save the results */
-
-            /*
-             * Update the AGC gain
-             */
-            AbsPeak = Abs_Float(SampleVal) > AbsPeak ? Abs_Float(SampleVal) : AbsPeak;
-        }
-        if (AbsPeak > AGC_Target)
-        {
-            /*
-             * The signal is too large so decrease the gain
-             */
-            AGC_Gain = AGC_Gain * AGC_Attack;
-        }
-        else
-        {
-            /*
-             * The signal is too small so increase the gain
-             */
-            if (AGC_Gain > AGC_MaxGain)
-            {
-                AGC_Gain -= (AGC_Decay);
-            }
-            else
-            {
-                AGC_Gain += (AGC_Decay);
-            }
-        }
-        pMonoSrc++;
-        /*
-         * Update the gain
-         */
-        Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
-    }
-
-
-    /*
-     * Update the parameters
-     */
-    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
-    pInstance->AGC_Gain = AGC_Gain;
-
-    return;
-}
-#endif /*SUPPORT_MC*/
-#endif /*BUILD_FLOAT*/
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
new file mode 100644
index 0000000..e18aa78
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "AGC.h"
+#include "ScalarArithmetic.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Defines                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define VOL_TC_SHIFT                                        21          /* As a power of 2 */
+#define DECAY_SHIFT                                        10           /* As a power of 2 */
+#define VOL_TC_FLOAT                                      2.0f          /* As a power of 2 */
+#define DECAY_FAC_FLOAT                                  64.0f          /* As a power of 2 */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  AGC_MIX_VOL_2St1Mon_D32_WRA                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Apply AGC and mix signals                                                         */
+/*                                                                                      */
+/*                                                                                      */
+/*  StSrc   ------------------|                                                         */
+/*                            |                                                         */
+/*              ______       _|_        ________                                        */
+/*             |      |     |   |      |        |                                       */
+/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
+/*             | Gain |     |___|      | Gain   |                              |        */
+/*             |______|                |________|                              |        */
+/*                /|\                               __________     ________    |        */
+/*                 |                               |          |   |        |   |        */
+/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
+/*                                                 | Update   |   | Detect |            */
+/*                                                 |__________|   |________|            */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pInstance               Instance pointer                                            */
+/*  pStereoIn               Stereo source                                               */
+/*  pMonoIn                 Mono band pass source                                       */
+/*  pStereoOut              Stereo destination                                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  Void                                                                                */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,     /* Instance pointer */
+                                 const LVM_FLOAT            *pStSrc,        /* Stereo source */
+                                 const LVM_FLOAT            *pMonoSrc,      /* Mono source */
+                                 LVM_FLOAT                  *pDst,          /* Stereo destination */
+                                 LVM_UINT16                 NumSamples)     /* Number of samples */
+{
+
+    /*
+     * General variables
+     */
+    LVM_UINT16      i;                                          /* Sample index */
+    LVM_FLOAT       Left;                                       /* Left sample */
+    LVM_FLOAT       Right;                                      /* Right sample */
+    LVM_FLOAT       Mono;                                       /* Mono sample */
+    LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
+    LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
+    LVM_FLOAT       Vol_Mult;                                   /* Short volume */
+
+    /*
+     * Instance control variables
+     */
+    LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
+    LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
+    LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
+    LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));/* Decay scaler */
+    LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
+    LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
+    LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
+    LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
+
+    /*
+     * Process on a sample by sample basis
+     */
+    for (i = 0; i < NumSamples; i++)                                  /* For each sample */
+    {
+
+        /*
+         * Get the short scalers
+         */
+        AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the short AGC gain */
+        Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the short volume gain */
+
+        /*
+         * Get the input samples
+         */
+        Left  = *pStSrc++;                                      /* Get the left sample */
+        Right = *pStSrc++;                                      /* Get the right sample */
+        Mono  = *pMonoSrc++;                                    /* Get the mono sample */
+
+        /*
+         * Apply the AGC gain to the mono input and mix with the stereo signal
+         */
+        Left  += (Mono * AGC_Mult);                               /* Mix in the mono signal */
+        Right += (Mono * AGC_Mult);
+
+        /*
+         * Apply the volume and write to the output stream
+         */
+        Left  = Left  * Vol_Mult;
+        Right = Right * Vol_Mult;
+        *pDst++ = Left;                                         /* Save the results */
+        *pDst++ = Right;
+
+        /*
+         * Update the AGC gain
+         */
+        AbsPeak = Abs_Float(Left) > Abs_Float(Right) ? Abs_Float(Left) : Abs_Float(Right);
+        if (AbsPeak > AGC_Target)
+        {
+            /*
+             * The signal is too large so decrease the gain
+             */
+            AGC_Gain = AGC_Gain * AGC_Attack;
+        }
+        else
+        {
+            /*
+             * The signal is too small so increase the gain
+             */
+            if (AGC_Gain > AGC_MaxGain)
+            {
+                AGC_Gain -= (AGC_Decay);
+            }
+            else
+            {
+                AGC_Gain += (AGC_Decay);
+            }
+        }
+
+        /*
+         * Update the gain
+         */
+        Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
+    }
+
+    /*
+     * Update the parameters
+     */
+    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
+    pInstance->AGC_Gain = AGC_Gain;
+
+    return;
+}
+#ifdef SUPPORT_MC
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  AGC_MIX_VOL_Mc1Mon_D32_WRA                                */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Apply AGC and mix signals                                                         */
+/*                                                                                      */
+/*                                                                                      */
+/*  McSrc   ------------------|                                                         */
+/*                            |                                                         */
+/*              ______       _|_        ________                                        */
+/*             |      |     |   |      |        |                                       */
+/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
+/*             | Gain |     |___|      | Gain   |                              |        */
+/*             |______|                |________|                              |        */
+/*                /|\                               __________     ________    |        */
+/*                 |                               |          |   |        |   |        */
+/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
+/*                                                 | Update   |   | Detect |            */
+/*                                                 |__________|   |________|            */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pInstance               Instance pointer                                            */
+/*  pMcSrc                  Multichannel source                                         */
+/*  pMonoSrc                Mono band pass source                                       */
+/*  pDst                    Multichannel destination                                    */
+/*  NrFrames                Number of frames                                            */
+/*  NrChannels              Number of channels                                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  Void                                                                                */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t  *pInstance,
+                                 const LVM_FLOAT            *pMcSrc,
+                                 const LVM_FLOAT            *pMonoSrc,
+                                 LVM_FLOAT                  *pDst,
+                                 LVM_UINT16                 NrFrames,
+                                 LVM_UINT16                 NrChannels)
+{
+
+    /*
+     * General variables
+     */
+    LVM_UINT16      i, jj;                                      /* Sample index */
+    LVM_FLOAT       SampleVal;                                  /* Sample value */
+    LVM_FLOAT       Mono;                                       /* Mono sample */
+    LVM_FLOAT       AbsPeak;                                    /* Absolute peak signal */
+    LVM_FLOAT       AGC_Mult;                                   /* Short AGC gain */
+    LVM_FLOAT       Vol_Mult;                                   /* Short volume */
+
+    /*
+     * Instance control variables
+     */
+    LVM_FLOAT      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
+    LVM_FLOAT      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
+    LVM_FLOAT      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
+    /* Decay scaler */
+    LVM_FLOAT      AGC_Decay     = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));
+    LVM_FLOAT      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
+    LVM_FLOAT      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
+    LVM_FLOAT      Vol_Target    = pInstance->Target;           /* Target volume setting */
+    LVM_FLOAT      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
+
+    /*
+     * Process on a sample by sample basis
+     */
+    for (i = 0; i < NrFrames; i++)                                  /* For each frame */
+    {
+
+        /*
+         * Get the scalers
+         */
+        AGC_Mult    = (LVM_FLOAT)(AGC_Gain);              /* Get the AGC gain */
+        Vol_Mult    = (LVM_FLOAT)(Vol_Current);           /* Get the volume gain */
+
+        AbsPeak = 0.0f;
+        /*
+         * Get the input samples
+         */
+        for (jj = 0; jj < NrChannels; jj++)
+        {
+            SampleVal  = *pMcSrc++;                       /* Get the sample value of jj Channel*/
+            Mono       = *pMonoSrc;                       /* Get the mono sample */
+
+            /*
+             * Apply the AGC gain to the mono input and mix with the input signal
+             */
+            SampleVal  += (Mono * AGC_Mult);                        /* Mix in the mono signal */
+
+            /*
+             * Apply the volume and write to the output stream
+             */
+            SampleVal  = SampleVal  * Vol_Mult;
+
+            *pDst++ = SampleVal;                                         /* Save the results */
+
+            /*
+             * Update the AGC gain
+             */
+            AbsPeak = Abs_Float(SampleVal) > AbsPeak ? Abs_Float(SampleVal) : AbsPeak;
+        }
+        if (AbsPeak > AGC_Target)
+        {
+            /*
+             * The signal is too large so decrease the gain
+             */
+            AGC_Gain = AGC_Gain * AGC_Attack;
+        }
+        else
+        {
+            /*
+             * The signal is too small so increase the gain
+             */
+            if (AGC_Gain > AGC_MaxGain)
+            {
+                AGC_Gain -= (AGC_Decay);
+            }
+            else
+            {
+                AGC_Gain += (AGC_Decay);
+            }
+        }
+        pMonoSrc++;
+        /*
+         * Update the gain
+         */
+        Vol_Current +=  (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
+    }
+
+    /*
+     * Update the parameters
+     */
+    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
+    pInstance->AGC_Gain = AGC_Gain;
+
+    return;
+}
+#endif /*SUPPORT_MC*/
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.c b/media/libeffects/lvm/lib/Common/src/Abs_32.c
deleted file mode 100644
index 84fabd8..0000000
--- a/media/libeffects/lvm/lib/Common/src/Abs_32.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 files                                                                       */
-/*######################################################################################*/
-
-#include    "ScalarArithmetic.h"
-
-/****************************************************************************************
- *  Name        : Abs_32()
- *  Input       : Signed 32-bit integer
- *  Output      :
- *  Returns     : Absolute value
- *  Description : Absolute value with maximum negative value corner case
- *  Remarks     :
- ****************************************************************************************/
-
-LVM_INT32    Abs_32(LVM_INT32    input)
-{
-    if(input <  0)
-    {
-        if (input == (LVM_INT32)(0x80000000U))
-        {
-            /* The corner case, so set to the maximum positive value */
-            input=(LVM_INT32) 0x7fffffff;
-        }
-        else
-        {
-            /* Negative input, so invert */
-            input = (LVM_INT32)(-input);
-        }
-    }
-    return input;
-}
-#ifdef BUILD_FLOAT
-LVM_FLOAT    Abs_Float(LVM_FLOAT    input)
-{
-    if(input <  0)
-    {
-        /* Negative input, so invert */
-        input = (LVM_FLOAT)(-input);
-    }
-    return input;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.cpp b/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
new file mode 100644
index 0000000..e013809
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Abs_32.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 files                                                                       */
+/*######################################################################################*/
+
+#include    "ScalarArithmetic.h"
+
+/****************************************************************************************
+ *  Name        : Abs_32()
+ *  Input       : Signed 32-bit integer
+ *  Output      :
+ *  Returns     : Absolute value
+ *  Description : Absolute value with maximum negative value corner case
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_INT32    Abs_32(LVM_INT32    input)
+{
+    if(input <  0)
+    {
+        if (input == (LVM_INT32)(0x80000000U))
+        {
+            /* The corner case, so set to the maximum positive value */
+            input=(LVM_INT32) 0x7fffffff;
+        }
+        else
+        {
+            /* Negative input, so invert */
+            input = (LVM_INT32)(-input);
+        }
+    }
+    return input;
+}
+LVM_FLOAT    Abs_Float(LVM_FLOAT    input)
+{
+    if(input <  0)
+    {
+        /* Negative input, so invert */
+        input = (LVM_FLOAT)(-input);
+    }
+    return input;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c
rename to media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
deleted file mode 100644
index 66d6adb..0000000
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-
-/**********************************************************************************
-   FUNCTION ADD2_SAT_32X32
-***********************************************************************************/
-
-void Add2_Sat_32x32( const LVM_INT32  *src,
-                           LVM_INT32  *dst,
-                           LVM_INT16  n )
-{
-    LVM_INT32 a,b,c;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--)
-    {
-        a=*src;
-        src++;
-
-        b=*dst;
-        c=a+b;
-        if ((((c ^ a) & (c ^ b)) >> 31)!=0)     /* overflow / underflow */
-        {
-            if(a<0)
-            {
-                c=0x80000000L;
-            }
-            else
-            {
-                c=0x7FFFFFFFL;
-            }
-        }
-
-        *dst = c;
-        dst++;
-    }
-    return;
-}
-
-#ifdef BUILD_FLOAT
-void Add2_Sat_Float( const LVM_FLOAT  *src,
-                           LVM_FLOAT  *dst,
-                           LVM_INT16  n )
-{
-    LVM_FLOAT Temp;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--)
-    {
-        Temp = ((LVM_FLOAT) *src) + ((LVM_FLOAT) *dst);
-        src++;
-
-        if (Temp > 1.000000f)
-        {
-            *dst = 1.000000f;
-        }
-        else if (Temp < -1.000000f)
-        {
-            *dst = -1.000000f;
-        }
-        else
-        {
-            *dst = Temp;
-        }
-        dst++;
-    }
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
new file mode 100644
index 0000000..a48e668
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION ADD2_SAT_32X32
+***********************************************************************************/
+
+void Add2_Sat_32x32( const LVM_INT32  *src,
+                           LVM_INT32  *dst,
+                           LVM_INT16  n )
+{
+    LVM_INT32 a,b,c;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        a=*src;
+        src++;
+
+        b=*dst;
+        c=a+b;
+        if ((((c ^ a) & (c ^ b)) >> 31)!=0)     /* overflow / underflow */
+        {
+            if(a<0)
+            {
+                c=0x80000000L;
+            }
+            else
+            {
+                c=0x7FFFFFFFL;
+            }
+        }
+
+        *dst = c;
+        dst++;
+    }
+    return;
+}
+
+void Add2_Sat_Float( const LVM_FLOAT  *src,
+                           LVM_FLOAT  *dst,
+                           LVM_INT16  n )
+{
+    LVM_FLOAT Temp;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_FLOAT) *src) + ((LVM_FLOAT) *dst);
+        src++;
+
+        if (Temp > 1.000000f)
+        {
+            *dst = 1.000000f;
+        }
+        else if (Temp < -1.000000f)
+        {
+            *dst = -1.000000f;
+        }
+        else
+        {
+            *dst = Temp;
+        }
+        dst++;
+    }
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
deleted file mode 100644
index 88f9986..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-
-
-    {
-        LVM_FLOAT ynL;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
-            ynL = pBiquadState->coefs[0] * ((*pDataIn)-pBiquadState->pDelays[1]);
-
-            // ynL+= ((-B2  * y(n-2)L  ) )
-            ynL += pBiquadState->coefs[1] * pBiquadState->pDelays[3];
-
-            // ynL+= ((-B1  * y(n-1)L  ) )
-            ynL += pBiquadState->coefs[2] * pBiquadState->pDelays[2];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=ynL; // Write Left output
-
-        }
-
-    }
-#else
-void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-
-
-    {
-        LVM_INT32 ynL;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) )  in Q14
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* ((*pDataIn)-pBiquadState->pDelays[1]);
-
-            // ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) ) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[3];
-
-            // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) ) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[2];
-
-            ynL=(LVM_INT16)(ynL>>14); // ynL in Q0
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
-
-        }
-
-    }
-#endif
-
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
new file mode 100644
index 0000000..1a5e07f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+
+    {
+        LVM_FLOAT ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
+            ynL = pBiquadState->coefs[0] * ((*pDataIn)-pBiquadState->pDelays[1]);
+
+            // ynL+= ((-B2  * y(n-2)L  ) )
+            ynL += pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+
+            // ynL+= ((-B1  * y(n-1)L  ) )
+            ynL += pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=ynL; // Write Left output
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
deleted file mode 100644
index 27ab57a..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BP_1I_D16F16Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t          *pInstance,
-                                         Biquad_1I_Order2_FLOAT_Taps_t    *pTaps,
-                                         BP_FLOAT_Coefs_t                  *pCoef)
-{
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
-
-    pBiquadState->coefs[0] = pCoef->A0;
-    pBiquadState->coefs[1] = pCoef->B2;
-    pBiquadState->coefs[2] = pCoef->B1;
-}
-#else
-void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_Taps_t   *pTaps,
-                                         BP_C16_Coefs_t            *pCoef)
-{
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps;
-
-  pBiquadState->coefs[0]=pCoef->A0;
-  pBiquadState->coefs[1]=pCoef->B2;
-  pBiquadState->coefs[2]=pCoef->B1;
-  }
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..60b6c16
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t          *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t    *pTaps,
+                                         BP_FLOAT_Coefs_t                  *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] = pCoef->A0;
+    pBiquadState->coefs[1] = pCoef->B2;
+    pBiquadState->coefs[2] = pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
index e194f92..8a000b6 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -27,7 +27,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
 
@@ -35,5 +34,4 @@
     LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 #endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
deleted file mode 100644
index 3abdd43..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q16 format
- pBiquadState->pDelays[3] is y(n-2)L in Q16 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-{
-    LVM_FLOAT ynL,templ;
-    LVM_INT16 ii;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
-
-    for (ii = NrSamples; ii != 0; ii--)
-    {
-        /**************************************************************************
-                       PROCESSING OF THE LEFT CHANNEL
-        ***************************************************************************/
-        // ynL= (A0 * (x(n)L - x(n-2)L ))
-        templ = (LVM_FLOAT) *pDataIn - pBiquadState->pDelays[1];
-        ynL = pBiquadState->coefs[0] * templ;
-
-        // ynL+= ((-B2  * y(n-2)L  ) )
-        templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
-        ynL += templ;
-
-        // ynL+= ((-B1  * y(n-1)L  ))
-        templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
-        ynL += templ;
-
-        /**************************************************************************
-                        UPDATING THE DELAYS
-        ***************************************************************************/
-        pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-        pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-        pBiquadState->pDelays[2] = ynL; // Update y(n-1)L in Q16
-        pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L in Q0
-
-        /**************************************************************************
-                        WRITING THE OUTPUT
-        ***************************************************************************/
-        *pDataOut++ = (ynL); // Write Left output
-        }
-}
-#else
-void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-
-
-    {
-        LVM_INT32 ynL,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14)  in Q16
-            templ= (LVM_INT32) *pDataIn-pBiquadState->pDelays[1];
-            MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,14)
-
-            // ynL+= ((-B2 (Q30) * y(n-2)L (Q16) ) >>30) in Q16
-            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
-            ynL+=templ;
-
-            // ynL+= ((-B1 (Q30) * y(n-1)L (Q16) ) >>30) in Q16
-            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
-            ynL+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q16
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)(ynL>>16); // Write Left output in Q0
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
new file mode 100644
index 0000000..c844d03
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+{
+    LVM_FLOAT ynL,templ;
+    LVM_INT16 ii;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)pInstance;
+
+    for (ii = NrSamples; ii != 0; ii--)
+    {
+        /**************************************************************************
+                       PROCESSING OF THE LEFT CHANNEL
+        ***************************************************************************/
+        // ynL= (A0 * (x(n)L - x(n-2)L ))
+        templ = (LVM_FLOAT) *pDataIn - pBiquadState->pDelays[1];
+        ynL = pBiquadState->coefs[0] * templ;
+
+        // ynL+= ((-B2  * y(n-2)L  ) )
+        templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+        ynL += templ;
+
+        // ynL+= ((-B1  * y(n-1)L  ))
+        templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+        ynL += templ;
+
+        /**************************************************************************
+                        UPDATING THE DELAYS
+        ***************************************************************************/
+        pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+        pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+        pBiquadState->pDelays[2] = ynL; // Update y(n-1)L in Q16
+        pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L in Q0
+
+        /**************************************************************************
+                        WRITING THE OUTPUT
+        ***************************************************************************/
+        *pDataOut++ = (ynL); // Write Left output
+        }
+}
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
deleted file mode 100644
index d6e047a..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BP_1I_D16F32Cll_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a Band pass filter (BIQUAD)               */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/*                                                                         */
-/*        The coefficients are modified in the init() function such that lower               */
-/*        half word is right shifted by one and most significant bit of the lower            */
-/*        word is made to be zero.                                                           */
-/*                                                                                           */
-/*       Reason: For MIPS effciency,we are using DSP 32*16 multiplication                    */
-/*       instruction. But we have 32*32 multiplication. This can be realized by two 32*16    */
-/*       multiplication. But 16th bit in the 32 bit word is not a sign bit. So this is done  */
-/*       by putting 16th bit to zero and lossing one bit precision by division of lower      */
-/*       half word by 2.                                                                     */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BP_1I_D16F32Cll_TRC_WRA_01_Init (    Biquad_FLOAT_Instance_t         *pInstance,
-                                          Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
-                                          BP_FLOAT_Coefs_t                *pCoef)
-{
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
-
-
-    pBiquadState->coefs[0] =  pCoef->A0;
-    pBiquadState->coefs[1] =  pCoef->B2;
-    pBiquadState->coefs[2] =  pCoef->B1;
-}
-#else
-void BP_1I_D16F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_Taps_t   *pTaps,
-                                         BP_C32_Coefs_t            *pCoef)
-{
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
-
-  pBiquadState->coefs[0] =  pCoef->A0;
-  pBiquadState->coefs[1] =  pCoef->B2;
-  pBiquadState->coefs[2] =  pCoef->B1;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..eb15032
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D16F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a Band pass filter (BIQUAD)               */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/*                                                                         */
+/*        The coefficients are modified in the init() function such that lower               */
+/*        half word is right shifted by one and most significant bit of the lower            */
+/*        word is made to be zero.                                                           */
+/*                                                                                           */
+/*       Reason: For MIPS effciency,we are using DSP 32*16 multiplication                    */
+/*       instruction. But we have 32*32 multiplication. This can be realized by two 32*16    */
+/*       multiplication. But 16th bit in the 32 bit word is not a sign bit. So this is done  */
+/*       by putting 16th bit to zero and lossing one bit precision by division of lower      */
+/*       half word by 2.                                                                     */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F32Cll_TRC_WRA_01_Init (    Biquad_FLOAT_Instance_t         *pInstance,
+                                          Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                          BP_FLOAT_Coefs_t                *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] =  pCoef->A0;
+    pBiquadState->coefs[1] =  pCoef->B2;
+    pBiquadState->coefs[2] =  pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
index aa9e669..6d754e2 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -26,12 +26,10 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
     LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
 }Filter_State_Float;
 typedef Filter_State_Float * PFilter_State_FLOAT ;
-#endif
 #endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
deleted file mode 100644
index abdb2f7..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT ynL,templ;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
-            templ = (*pDataIn) - pBiquadState->pDelays[1];
-            ynL = pBiquadState->coefs[0] * templ;
-
-            // ynL+= ((-B2  * y(n-2)L  ) )
-            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
-            ynL += templ;
-
-            // ynL+= ((-B1  * y(n-1)L  ) )
-            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
-            ynL += templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = ynL; // Write Left output in Q0
-
-        }
-
-    }
-#else
-void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT32               *pDataIn,
-                                  LVM_INT32               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_INT32 ynL,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30)  in Q0
-            templ=(*pDataIn)-pBiquadState->pDelays[1];
-            MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,30)
-
-            // ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0
-            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
-            ynL+=templ;
-
-            // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0
-            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
-            ynL+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=ynL; // Write Left output in Q0
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
new file mode 100644
index 0000000..d0ba206
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT ynL,templ;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0  * (x(n)L  - x(n-2)L  ) )
+            templ = (*pDataIn) - pBiquadState->pDelays[1];
+            ynL = pBiquadState->coefs[0] * templ;
+
+            // ynL+= ((-B2  * y(n-2)L  ) )
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[3];
+            ynL += templ;
+
+            // ynL+= ((-B1  * y(n-1)L  ) )
+            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[2];
+            ynL += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = ynL; // Write Left output in Q0
+
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
deleted file mode 100644
index 5590c32..0000000
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BP_1I_D32F32Cll_TRC_WRA_02_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BP_FLOAT_Coefs_t            *pCoef)
-{
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
-
-    pBiquadState->coefs[0] = pCoef->A0;
-
-    pBiquadState->coefs[1] = pCoef->B2;
-
-    pBiquadState->coefs[2] = pCoef->B1;
-}
-#else
-void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_Taps_t   *pTaps,
-                                         BP_C32_Coefs_t            *pCoef)
-{
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
-
-  pBiquadState->coefs[0]=pCoef->A0;
-
-  pBiquadState->coefs[1]=pCoef->B2;
-
-  pBiquadState->coefs[2]=pCoef->B1;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
new file mode 100644
index 0000000..6f7d0b5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D32F32Cll_TRC_WRA_02_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BP_FLOAT_Coefs_t            *pCoef)
+{
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays       =(LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] = pCoef->A0;
+
+    pBiquadState->coefs[1] = pCoef->B2;
+
+    pBiquadState->coefs[2] = pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
index 80c3920..9f1c66a 100644
--- a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -26,13 +26,11 @@
 }Filter_State;
 
 typedef Filter_State * PFilter_State ;
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
     LVM_FLOAT         coefs[3];       /* pointer to the filter coefficients */
 }Filter_State_Float;
 typedef Filter_State_Float* PFilter_State_FLOAT ;
-#endif
 
 #endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
deleted file mode 100644
index ee9bf7a..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q0 format
- pBiquadState->pDelays[3] is y(n-2)L in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2  * x(n-2)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
-
-            // ynL+=A1 * x(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            // ynL+=A0 * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            // ynL+=  (-B2  * y(n-2)L )
-            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[3];
-
-            // ynL+= (-B1  * y(n-1)L  )
-            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[2];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
-
-
-        }
-
-    }
-#else
-void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
-
-            // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            // ynL+=  (-B2 (Q15) * y(n-2)L (Q0) ) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[3];
-
-            // ynL+= (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[2];
-
-            ynL=ynL>>15; // ynL in Q0 format
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
-
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
new file mode 100644
index 0000000..9aecc40
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
+
+            // ynL+=A1 * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0 * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+=  (-B2  * y(n-2)L )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[3];
+
+            // ynL+= (-B1  * y(n-1)L  )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[2];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
+
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
deleted file mode 100644
index 3d5befa..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BQ_1I_D16F16Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BQ_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps ;
-    temp = pCoef->A2;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A1;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[2] = temp;
-    temp = pCoef->B2;
-    pBiquadState->coefs[3] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[4] = temp;
-}
-#else
-void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_Taps_t   *pTaps,
-                                         BQ_C16_Coefs_t            *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A2;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A1;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[2]=temp;
-  temp=pCoef->B2;
-  pBiquadState->coefs[3]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[4]=temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..f0b5d06
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps ;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
index 811da8b..fad345d 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -27,7 +27,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
@@ -35,5 +34,4 @@
 
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 #endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
deleted file mode 100644
index c74a137..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-2)L in Q0 format
- pBiquadState->pDelays[2] is y(n-1)L in Q16 format
- pBiquadState->pDelays[3] is y(n-2)L in Q16 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2  * x(n-2)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
-
-            // ynL+=A1  * x(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            // ynL+=A0  * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            // ynL+= ( (-B2  * y(n-2)L )
-            ynL += pBiquadState->pDelays[3] * pBiquadState->coefs[3];
-
-            // ynL+= -B1  * y(n-1)L
-            ynL += pBiquadState->pDelays[2] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[2];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2] = ynL;                    // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)(ynL); // Write Left output
-
-        }
-    }
-#else
-void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
-
-            // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            // ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14
-            MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[3],templ,16)
-            ynL+=templ;
-
-            // ynL+= ( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14
-            MUL32x16INTO32(pBiquadState->pDelays[2],pBiquadState->coefs[4],templ,16)
-            ynL+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[2];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[1]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[2]=ynL<<2;                    // Update y(n-1)L in Q16
-            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)(ynL>>14); // Write Left output in Q0
-
-        }
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
new file mode 100644
index 0000000..043bc5f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[1];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( (-B2  * y(n-2)L )
+            ynL += pBiquadState->pDelays[3] * pBiquadState->coefs[3];
+
+            // ynL+= -B1  * y(n-1)L
+            ynL += pBiquadState->pDelays[2] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[2];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2] = ynL;                    // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)(ynL); // Write Left output
+
+        }
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
index 9812274..6a61d9a 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -27,7 +27,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *   pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
@@ -35,5 +34,4 @@
 
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 #endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
deleted file mode 100644
index feae20d..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BQ_1I_D16F32Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BQ_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
-
-    temp = pCoef->A2;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A1;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[2] = temp;
-    temp = pCoef->B2;
-    pBiquadState->coefs[3] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[4] = temp;
-}
-#else
-void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order2_Taps_t   *pTaps,
-                                         BQ_C16_Coefs_t            *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A2;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A1;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[2]=temp;
-  temp=pCoef->B2;
-  pBiquadState->coefs[3]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[4]=temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
new file mode 100644
index 0000000..2b80691
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_1I_D16F32Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
+
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
deleted file mode 100644
index 9b0fde3..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2  * x(n-2)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            // ynL+=A1  * x(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            // ynL+=A0  * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            // ynL+= ( -B2  * y(n-2)L  )
-            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
-
-            // ynL+=( -B1  * y(n-1)L )
-            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
-
-
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            // ynR=A2  * x(n-2)R
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            // ynR+=A1  * x(n-1)R
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
-            // ynR+=A0  * x(n)R
-            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
-
-            // ynR+= ( -B2  * y(n-2)R  )
-            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
-
-            // ynR+=( -B1  * y(n-1)R  )
-            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
-
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
-            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
-            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
-            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
-
-
-        }
-
-    }
-#else
-void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-            // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            // ynL+= ( -B2 (Q14) * y(n-2)L (Q0) ) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
-
-            // ynL+=( -B1 (Q14) * y(n-1)L (Q0) ) in Q14
-            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
-
-            ynL=ynL>>14; // ynL in Q0 format
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            // ynR=A2 (Q14) * x(n-2)R (Q0) in Q14
-            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
-
-            // ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
-
-            // ynR+=A0 (Q14) * x(n)R (Q0) in Q14
-            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
-
-            // ynR+= ( -B2 (Q14) * y(n-2)R (Q0) ) in Q14
-            ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
-
-            // ynR+=( -B1 (Q14) * y(n-1)R (Q0) ) in Q14
-            ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
-
-            ynR=ynR>>14; // ynL in Q0 format
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[5]=ynR;                       // Update y(n-1)R in Q0
-            pBiquadState->pDelays[4]=ynL;                       // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
-            pBiquadState->pDelays[1]=(*pDataIn++);              // Update x(n-1)R in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
-            *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
-
-
-        }
-
-    }
-
-#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
new file mode 100644
index 0000000..51cd918
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( -B2  * y(n-2)L  )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+
+            // ynL+=( -B1  * y(n-1)L )
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2  * x(n-2)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            // ynR+=A1  * x(n-1)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            // ynR+=A0  * x(n)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            // ynR+= ( -B2  * y(n-2)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+
+            // ynR+=( -B1  * y(n-1)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
+            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
+
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
deleted file mode 100644
index f24db8f..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                  LVM_FLOAT               *pDataIn,
-                                  LVM_FLOAT               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2  * x(n-2)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            // ynL+=A1  * x(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            // ynL+=A0  * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            // ynL+= ( -B2  * y(n-2)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
-
-            // ynL+=( -B1  * y(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
-
-
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            // ynR=A2  * x(n-2)R
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            // ynR+=A1  * x(n-1)R
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
-            // ynR+=A0  * x(n)R
-            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
-
-            // ynR+= ( -B2  * y(n-2)R  )
-            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
-
-            // ynR+=( -B1  * y(n-1)R  )
-            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
-
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
-            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
-            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
-            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
-
-        }
-
-    }
-#else
-void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                  LVM_INT16               *pDataIn,
-                                  LVM_INT16               *pDataOut,
-                                  LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-            // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            // ynL+= ( -B2 (Q15) * y(n-2)L (Q0) ) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
-
-            // ynL+=( -B1 (Q15) * y(n-1)L (Q0) ) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
-
-            ynL=ynL>>15; // ynL in Q0 format
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            // ynR=A2 (Q15) * x(n-2)R (Q0) in Q15
-            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
-
-            // ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
-
-            // ynR+=A0 (Q15) * x(n)R (Q0) in Q15
-            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
-
-            // ynR+= ( -B2 (Q15) * y(n-2)R (Q0) ) in Q15
-            ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
-
-            // ynR+=( -B1 (Q15) * y(n-1)R (Q0) ) in Q15
-            ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
-
-            ynR=ynR>>15; // ynL in Q0 format
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
-            pBiquadState->pDelays[5]=ynR;                       // Update y(n-1)R in Q0
-            pBiquadState->pDelays[4]=ynL;                       // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
-            pBiquadState->pDelays[1]=(*pDataIn++);              // Update x(n-1)R in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
-            *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
new file mode 100644
index 0000000..8f74749
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                  LVM_FLOAT               *pDataIn,
+                                  LVM_FLOAT               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2  * x(n-2)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            // ynL+=A1  * x(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            // ynL+= ( -B2  * y(n-2)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+
+            // ynL+=( -B1  * y(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2  * x(n-2)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            // ynR+=A1  * x(n-1)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            // ynR+=A0  * x(n)R
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            // ynR+= ( -B2  * y(n-2)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+
+            // ynR+=( -B1  * y(n-1)R  )
+            ynR += (LVM_FLOAT)pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5] = ynR;                       // Update y(n-1)R
+            pBiquadState->pDelays[4] = ynL;                       // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++);              // Update x(n-1)L
+            pBiquadState->pDelays[1] = (*pDataIn++);              // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+            *pDataOut++ = (LVM_FLOAT)ynR; // Write Right ouput
+
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
deleted file mode 100644
index 39e1bda..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BQ_2I_D16F16Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BQ_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
-
-    temp = pCoef->A2;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A1;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[2] = temp;
-    temp = pCoef->B2;
-    pBiquadState->coefs[3] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[4] = temp;
-}
-#else
-void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_Taps_t   *pTaps,
-                                         BQ_C16_Coefs_t            *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A2;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A1;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[2]=temp;
-  temp=pCoef->B2;
-  pBiquadState->coefs[3]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[4]=temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..987cbcf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
+
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
index 0691b8c..5a9a0e9 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -28,7 +28,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *   pDelays;            /* pointer to the delayed samples (data of 32 bits) */
@@ -36,6 +35,5 @@
 
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 
 #endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
deleted file mode 100644
index 61c07c7..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q13 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
-                                            LVM_FLOAT                    *pDataIn,
-                                            LVM_FLOAT                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_FLOAT  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2 * x(n-2)L */
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            /* ynL+=A1* x(n-1)L */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            /* ynL+=A0* x(n)L   */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            /* ynL+=-B2*y(n-2)L */
-            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
-            /* ynL+=-B1*y(n-1)L */
-            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2 * x(n-2)R */
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            /* ynR+=A1* x(n-1)R */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
-            /* ynR+=A0* x(n)R   */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
-
-            /* ynR+=-B2 * y(n-2)R */
-            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
-            /* ynR+=-B1 * y(n-1)R */
-            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5] = ynR;                       /* Update y(n-1)R */
-            pBiquadState->pDelays[4] = ynL;                       /* Update y(n-1)L */
-            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
-            pDataIn++;
-            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
-            pDataOut++;
-            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
-            pDataOut++;
-        }
-    }
-#else
-void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_INT32  ynL,ynR,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2 (Q13) * x(n-2)L (Q0) in Q13*/
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-            /* ynL+=A1 (Q13) * x(n-1)L (Q0) in Q13*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            /* ynL+=A0 (Q13) * x(n)L (Q0) in Q13*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            /* ynL+= ( (-B2 (Q13) * y(n-2)L (Q16) )>>16) in Q13 */
-            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
-            ynL+=templ;
-
-            /* ynL+=( (-B1 (Q13) * y(n-1)L (Q16) )>>16) in Q13 */
-            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
-            ynL+=templ;
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2 (Q13) * x(n-2)R (Q0) in Q13*/
-            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
-
-            /* ynR+=A1 (Q13) * x(n-1)R (Q0) in Q13*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
-
-            /* ynR+=A0 (Q13) * x(n)R (Q0) in Q13*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
-
-            /* ynR+= ( (-B2 (Q13) * y(n-2)R (Q16) )>>16) in Q13*/
-            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
-            ynR+=templ;
-
-            /* ynR+=( (-B1 (Q13) * y(n-1)R (Q16) )>>16) in Q13 */
-            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
-            ynR+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=ynR<<3;                    /* Update y(n-1)R in Q16*/
-            pBiquadState->pDelays[4]=ynL<<3;                    /* Update y(n-1)L in Q16*/
-            pBiquadState->pDelays[0]=(*pDataIn);                /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn);                /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=(LVM_INT16)(ynL>>13); /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=(LVM_INT16)(ynR>>13); /* Write Right ouput in Q0*/
-            pDataOut++;
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
new file mode 100644
index 0000000..331c97f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q13 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2 * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1* x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0* x(n)L   */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+=-B2*y(n-2)L */
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+            /* ynL+=-B1*y(n-1)L */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2 * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1* x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0* x(n)R   */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+=-B2 * y(n-2)R */
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+            /* ynR+=-B1 * y(n-1)R */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR;                       /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL;                       /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
+            pDataOut++;
+        }
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
deleted file mode 100644
index cf19e06..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q14 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
-                                            LVM_FLOAT                    *pDataIn,
-                                            LVM_FLOAT                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_FLOAT  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2  * x(n-2)L */
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            /* ynL+=A1  * x(n-1)L */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            /* ynL+=A0  * x(n)L */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            /* ynL+= ( (-B2  * y(n-2)L  ))*/
-            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
-
-            /* ynL+=( (-B1  * y(n-1)L  ))  */
-            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2  * x(n-2)R */
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            /* ynR+=A1  * x(n-1)R */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
-            /* ynR+=A0  * x(n)R */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
-
-            /* ynR+= ( (-B2  * y(n-2)R  ))*/
-            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
-            /* ynR+=( (-B1  * y(n-1)R  ))  */
-            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5] = ynR;                    /* Update y(n-1)R */
-            pBiquadState->pDelays[4] = ynL;                    /* Update y(n-1)L */
-            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
-            pDataIn++;
-            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
-            pDataOut++;
-            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
-            pDataOut++;
-        }
-
-    }
-#else
-void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_INT32  ynL,ynR,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2 (Q14) * x(n-2)L (Q0) in Q14*/
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-            /* ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            /* ynL+=A0 (Q14) * x(n)L (Q0) in Q14*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            /* ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14 */
-            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
-            ynL+=templ;
-
-            /* ynL+=( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14 */
-            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
-            ynL+=templ;
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2 (Q14) * x(n-2)R (Q0) in Q14*/
-            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
-
-            /* ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
-
-            /* ynR+=A0 (Q14) * x(n)R (Q0) in Q14*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
-
-            /* ynR+= ( (-B2 (Q14) * y(n-2)R (Q16) )>>16) in Q14*/
-            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
-            ynR+=templ;
-
-            /* ynR+=( (-B1 (Q14) * y(n-1)R (Q16) )>>16) in Q14 */
-            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
-            ynR+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=ynR<<2;                    /* Update y(n-1)R in Q16*/
-            pBiquadState->pDelays[4]=ynL<<2;                    /* Update y(n-1)L in Q16*/
-            pBiquadState->pDelays[0]=(*pDataIn);                /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn);                /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=(LVM_INT16)(ynL>>14); /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=(LVM_INT16)(ynR>>14); /* Write Right ouput in Q0*/
-            pDataOut++;
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
new file mode 100644
index 0000000..3a396df
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2  * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1  * x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0  * x(n)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+= ( (-B2  * y(n-2)L  ))*/
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+            /* ynL+=( (-B1  * y(n-1)L  ))  */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2  * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1  * x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0  * x(n)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+= ( (-B2  * y(n-2)R  ))*/
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+            /* ynR+=( (-B1  * y(n-1)R  ))  */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR;                    /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL;                    /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn);                /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn);                /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput */
+            pDataOut++;
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
deleted file mode 100644
index 2611b19..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q16 format
- pBiquadState->pDelays[5] is y(n-1)R in Q16 format
- pBiquadState->pDelays[6] is y(n-2)L in Q16 format
- pBiquadState->pDelays[7] is y(n-2)R in Q16 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
-                                            LVM_FLOAT                    *pDataIn,
-                                            LVM_FLOAT                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_FLOAT  ynL,ynR;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2  * x(n-2)L */
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            /* ynL+=A1  * x(n-1)L */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-
-            /* ynL+=A0  * x(n)L */
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
-
-            /* ynL+= ( (-B2  * y(n-2)L )  */
-            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
-
-
-            /* ynL+=( (-B1  * y(n-1)L  ))  */
-            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
-
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2  * x(n-2)R */
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            /* ynR+=A1  * x(n-1)R */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-
-            /* ynR+=A0  * x(n)R */
-            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
-
-            /* ynR+= ( (-B2  * y(n-2)R ) */
-            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
-
-
-            /* ynR+=( (-B1  * y(n-1)R  )) in Q15 */
-            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R*/
-            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L*/
-            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L*/
-            pDataIn++;
-            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output*/
-            pDataOut++;
-            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput*/
-            pDataOut++;
-        }
-
-    }
-#else
-void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT16                    *pDataIn,
-                                            LVM_INT16                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-    {
-        LVM_INT32  ynL,ynR,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL=A2 (Q15) * x(n-2)L (Q0) in Q15*/
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-            /* ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
-
-            /* ynL+=A0 (Q15) * x(n)L (Q0) in Q15*/
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
-
-            /* ynL+= ( (-B2 (Q15) * y(n-2)L (Q16) )>>16) in Q15 */
-            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
-            ynL+=templ;
-
-            /* ynL+=( (-B1 (Q15) * y(n-1)L (Q16) )>>16) in Q15 */
-            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
-            ynL+=templ;
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR=A2 (Q15) * x(n-2)R (Q0) in Q15*/
-            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
-
-            /* ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
-
-            /* ynR+=A0 (Q15) * x(n)R (Q0) in Q15*/
-            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
-
-            /* ynR+= ( (-B2 (Q15) * y(n-2)R (Q16) )>>16) in Q15 */
-            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
-            ynR+=templ;
-
-            /* ynR+=( (-B1 (Q15) * y(n-1)R (Q16) )>>16) in Q15 */
-            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
-            ynR+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=ynR<<1; /* Update y(n-1)R in Q16*/
-            pBiquadState->pDelays[4]=ynL<<1; /* Update y(n-1)L in Q16*/
-            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=(LVM_INT16)(ynL>>15); /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=(LVM_INT16)(ynR>>15); /* Write Right ouput in Q0*/
-            pDataOut++;
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
new file mode 100644
index 0000000..1cbff1a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_FLOAT  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2  * x(n-2)L */
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+=A1  * x(n-1)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+
+            /* ynL+=A0  * x(n)L */
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * (*pDataIn);
+
+            /* ynL+= ( (-B2  * y(n-2)L )  */
+            ynL += pBiquadState->pDelays[6] * pBiquadState->coefs[3];
+
+            /* ynL+=( (-B1  * y(n-1)L  ))  */
+            ynL += pBiquadState->pDelays[4] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2  * x(n-2)R */
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+=A1  * x(n-1)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+
+            /* ynR+=A0  * x(n)R */
+            ynR += (LVM_FLOAT)pBiquadState->coefs[2] * (*(pDataIn+1));
+
+            /* ynR+= ( (-B2  * y(n-2)R ) */
+            ynR += pBiquadState->pDelays[7] * pBiquadState->coefs[3];
+
+            /* ynR+=( (-B1  * y(n-1)R  )) in Q15 */
+            ynR += pBiquadState->pDelays[5] * pBiquadState->coefs[4];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R*/
+            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L*/
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L*/
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)(ynL); /* Write Left output*/
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)(ynR); /* Write Right ouput*/
+            pDataOut++;
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
index c0319c9..314388a 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -28,7 +28,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
@@ -36,6 +35,5 @@
     LVM_FLOAT                           coefs[5];        /* pointer to the filter coefficients */
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 
 #endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
deleted file mode 100644
index 4d9bbfe..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BQ_2I_D16F32Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BQ_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
-    temp = pCoef->A2;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A1;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[2] = temp;
-    temp = pCoef->B2;
-    pBiquadState->coefs[3] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[4] = temp;
-}
-#else
-void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_Taps_t   *pTaps,
-                                         BQ_C16_Coefs_t            *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A2;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A1;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[2]=temp;
-  temp=pCoef->B2;
-  pBiquadState->coefs[3]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[4]=temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
new file mode 100644
index 0000000..058541a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D16F32Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
deleted file mode 100644
index d63365c..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1, these are in Q30 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
-                                            LVM_FLOAT                    *pDataIn,
-                                            LVM_FLOAT                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-
-
-    {
-        LVM_FLOAT ynL,ynR,templ,tempd;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL= ( A2  * x(n-2)L  ) */
-            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-            /* ynL+= ( A1  * x(n-1)L  )*/
-            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[0];
-            ynL += templ;
-
-            /* ynL+= ( A0  * x(n)L  ) */
-            templ = pBiquadState->coefs[2] * (*pDataIn);
-            ynL += templ;
-
-             /* ynL+= (-B2  * y(n-2)L  ) */
-            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[6];
-            ynL += templ;
-
-            /* ynL+= (-B1  * y(n-1)L  )*/
-            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[4];
-            ynL += templ;
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR= ( A2  * x(n-2)R  ) */
-            ynR = pBiquadState->coefs[0] * pBiquadState->pDelays[3];
-
-            /* ynR+= ( A1  * x(n-1)R  ) */
-            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[1];
-            ynR += templ;
-
-            /* ynR+= ( A0  * x(n)R  ) */
-            tempd =* (pDataIn+1);
-            templ = pBiquadState->coefs[2] * tempd;
-            ynR += templ;
-
-            /* ynR+= (-B2  * y(n-2)R  ) */
-            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[7];
-            ynR += templ;
-
-            /* ynR+= (-B1  * y(n-1)R  )  */
-            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[5];
-            ynR += templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5] = (LVM_FLOAT)ynR; /* Update y(n-1)R */
-            pBiquadState->pDelays[4] = (LVM_FLOAT)ynL; /* Update y(n-1)L */
-            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
-            pDataIn++;
-            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut = (LVM_FLOAT)ynL; /* Write Left output */
-            pDataOut++;
-            *pDataOut = (LVM_FLOAT)ynR; /* Write Right ouput */
-            pDataOut++;
-
-
-        }
-
-    }
-
-#ifdef SUPPORT_MC
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
- pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
- pBiquadState->coefs[4] is -B1
-
- DELAYS-
- pBiquadState->pDelays[0] to
- pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
-
- pBiquadState->pDelays[NrChannels] to
- pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
-
- pBiquadState->pDelays[2*NrChannels] to
- pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
-
- pBiquadState->pDelays[3*NrChannels] to
- pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
-***************************************************************************/
-void BQ_MC_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t      *pInstance,
-                                            LVM_FLOAT                    *pDataIn,
-                                            LVM_FLOAT                    *pDataOut,
-                                            LVM_INT16                    NrFrames,
-                                            LVM_INT16                    NrChannels)
-
-
-    {
-        LVM_FLOAT yn, temp;
-        LVM_INT16 ii, jj;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrFrames; ii != 0; ii--)
-         {
-            /**************************************************************************
-                            PROCESSING CHANNEL-WISE
-            ***************************************************************************/
-            for (jj = 0; jj < NrChannels; jj++)
-            {
-                /* yn= (A2  * x(n-2)) */
-                yn = pBiquadState->coefs[0] * pBiquadState->pDelays[NrChannels + jj];
-
-                /* yn+= (A1  * x(n-1)) */
-                temp = pBiquadState->coefs[1] * pBiquadState->pDelays[jj];
-                yn += temp;
-
-                /* yn+= (A0  * x(n)) */
-                temp = pBiquadState->coefs[2] * (*pDataIn);
-                yn += temp;
-
-                 /* yn+= (-B2  * y(n-2)) */
-                temp = pBiquadState->coefs[3] * pBiquadState->pDelays[NrChannels*3 + jj];
-                yn += temp;
-
-                /* yn+= (-B1  * y(n-1)) */
-                temp = pBiquadState->coefs[4] * pBiquadState->pDelays[NrChannels*2 + jj];
-                yn += temp;
-
-                /**************************************************************************
-                                UPDATING THE DELAYS
-                ***************************************************************************/
-                pBiquadState->pDelays[NrChannels * 3 + jj] =
-                    pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
-                pBiquadState->pDelays[NrChannels * 1 + jj] =
-                    pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
-                pBiquadState->pDelays[NrChannels * 2 + jj] = (LVM_FLOAT)yn; /* Update y(n-1)*/
-                pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
-                pDataIn++;
-                /**************************************************************************
-                                WRITING THE OUTPUT
-                ***************************************************************************/
-                *pDataOut = (LVM_FLOAT)yn; /* Write jj Channel output */
-                pDataOut++;
-            }
-        }
-
-    }
-#endif /*SUPPORT_MC*/
-
-#else
-void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
-                                            LVM_INT32                    *pDataIn,
-                                            LVM_INT32                    *pDataOut,
-                                            LVM_INT16                    NrSamples)
-
-
-    {
-        LVM_INT32 ynL,ynR,templ,tempd;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL= ( A2 (Q30) * x(n-2)L (Q0) ) >>30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[2],ynL,30)
-
-            /* ynL+= ( A1 (Q30) * x(n-1)L (Q0) ) >> 30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[0],templ,30)
-            ynL+=templ;
-
-            /* ynL+= ( A0 (Q30) * x(n)L (Q0) ) >> 30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[2],*pDataIn,templ,30)
-            ynL+=templ;
-
-             /* ynL+= (-B2 (Q30) * y(n-2)L (Q0) ) >> 30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[6],templ,30)
-            ynL+=templ;
-
-            /* ynL+= (-B1 (Q30) * y(n-1)L (Q0) ) >> 30 in Q0 */
-            MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[4],templ,30)
-            ynL+=templ;
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR= ( A2 (Q30) * x(n-2)R (Q0) ) >> 30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[3],ynR,30)
-
-            /* ynR+= ( A1 (Q30) * x(n-1)R (Q0) ) >> 30  in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[1],templ,30)
-            ynR+=templ;
-
-            /* ynR+= ( A0 (Q30) * x(n)R (Q0) ) >> 30 in Q0*/
-            tempd=*(pDataIn+1);
-            MUL32x32INTO32(pBiquadState->coefs[2],tempd,templ,30)
-            ynR+=templ;
-
-            /* ynR+= (-B2 (Q30) * y(n-2)R (Q0) ) >> 30 in Q0*/
-            MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[7],templ,30)
-            ynR+=templ;
-
-            /* ynR+= (-B1 (Q30) * y(n-1)R (Q0) ) >> 30 in Q0 */
-            MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[5],templ,30)
-            ynR+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=(LVM_INT32)ynR; /* Update y(n-1)R in Q0*/
-            pBiquadState->pDelays[4]=(LVM_INT32)ynL; /* Update y(n-1)L in Q0*/
-            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=(LVM_INT32)ynL; /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=(LVM_INT32)ynR; /* Write Right ouput in Q0*/
-            pDataOut++;
-
-
-        }
-
-    }
-#endif /*BUILD_FLOAT*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
new file mode 100644
index 0000000..78d1ba1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t       *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+
+    {
+        LVM_FLOAT ynL,ynR,templ,tempd;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= ( A2  * x(n-2)L  ) */
+            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            /* ynL+= ( A1  * x(n-1)L  )*/
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[0];
+            ynL += templ;
+
+            /* ynL+= ( A0  * x(n)L  ) */
+            templ = pBiquadState->coefs[2] * (*pDataIn);
+            ynL += templ;
+
+             /* ynL+= (-B2  * y(n-2)L  ) */
+            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[6];
+            ynL += templ;
+
+            /* ynL+= (-B1  * y(n-1)L  )*/
+            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[4];
+            ynL += templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= ( A2  * x(n-2)R  ) */
+            ynR = pBiquadState->coefs[0] * pBiquadState->pDelays[3];
+
+            /* ynR+= ( A1  * x(n-1)R  ) */
+            templ = pBiquadState->coefs[1] * pBiquadState->pDelays[1];
+            ynR += templ;
+
+            /* ynR+= ( A0  * x(n)R  ) */
+            tempd =* (pDataIn+1);
+            templ = pBiquadState->coefs[2] * tempd;
+            ynR += templ;
+
+            /* ynR+= (-B2  * y(n-2)R  ) */
+            templ = pBiquadState->coefs[3] * pBiquadState->pDelays[7];
+            ynR += templ;
+
+            /* ynR+= (-B1  * y(n-1)R  )  */
+            templ = pBiquadState->coefs[4] * pBiquadState->pDelays[5];
+            ynR += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = (LVM_FLOAT)ynR; /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = (LVM_FLOAT)ynL; /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = (LVM_FLOAT)ynL; /* Write Left output */
+            pDataOut++;
+            *pDataOut = (LVM_FLOAT)ynR; /* Write Right ouput */
+            pDataOut++;
+
+        }
+
+    }
+
+#ifdef SUPPORT_MC
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1
+
+ DELAYS-
+ pBiquadState->pDelays[0] to
+ pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
+
+ pBiquadState->pDelays[NrChannels] to
+ pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
+
+ pBiquadState->pDelays[2*NrChannels] to
+ pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
+
+ pBiquadState->pDelays[3*NrChannels] to
+ pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
+***************************************************************************/
+void BQ_MC_D32F32C30_TRC_WRA_01 (           Biquad_FLOAT_Instance_t      *pInstance,
+                                            LVM_FLOAT                    *pDataIn,
+                                            LVM_FLOAT                    *pDataOut,
+                                            LVM_INT16                    NrFrames,
+                                            LVM_INT16                    NrChannels)
+
+    {
+        LVM_FLOAT yn, temp;
+        LVM_INT16 ii, jj;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrFrames; ii != 0; ii--)
+         {
+            /**************************************************************************
+                            PROCESSING CHANNEL-WISE
+            ***************************************************************************/
+            for (jj = 0; jj < NrChannels; jj++)
+            {
+                /* yn= (A2  * x(n-2)) */
+                yn = pBiquadState->coefs[0] * pBiquadState->pDelays[NrChannels + jj];
+
+                /* yn+= (A1  * x(n-1)) */
+                temp = pBiquadState->coefs[1] * pBiquadState->pDelays[jj];
+                yn += temp;
+
+                /* yn+= (A0  * x(n)) */
+                temp = pBiquadState->coefs[2] * (*pDataIn);
+                yn += temp;
+
+                 /* yn+= (-B2  * y(n-2)) */
+                temp = pBiquadState->coefs[3] * pBiquadState->pDelays[NrChannels*3 + jj];
+                yn += temp;
+
+                /* yn+= (-B1  * y(n-1)) */
+                temp = pBiquadState->coefs[4] * pBiquadState->pDelays[NrChannels*2 + jj];
+                yn += temp;
+
+                /**************************************************************************
+                                UPDATING THE DELAYS
+                ***************************************************************************/
+                pBiquadState->pDelays[NrChannels * 3 + jj] =
+                    pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
+                pBiquadState->pDelays[NrChannels * 1 + jj] =
+                    pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
+                pBiquadState->pDelays[NrChannels * 2 + jj] = (LVM_FLOAT)yn; /* Update y(n-1)*/
+                pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
+                pDataIn++;
+                /**************************************************************************
+                                WRITING THE OUTPUT
+                ***************************************************************************/
+                *pDataOut = (LVM_FLOAT)yn; /* Write jj Channel output */
+                pDataOut++;
+            }
+        }
+
+    }
+#endif /*SUPPORT_MC*/
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
deleted file mode 100644
index fff05ed..0000000
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   BQ_2I_D32F32Cll_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
-                                         BQ_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
-    temp = pCoef->A2;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A1;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[2] = temp;
-    temp = pCoef->B2;
-    pBiquadState->coefs[3] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[4] = temp;
-}
-#else
-void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_Taps_t   *pTaps,
-                                         BQ_C32_Coefs_t            *pCoef)
-{
-  LVM_INT32 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A2;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A1;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[2]=temp;
-  temp=pCoef->B2;
-  pBiquadState->coefs[3]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[4]=temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c                              */
-
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..492a9e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D32F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         BQ_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps;
+    temp = pCoef->A2;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A1;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[2] = temp;
+    temp = pCoef->B2;
+    pBiquadState->coefs[3] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[4] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
index c0f0dcc..7eb6474 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -18,7 +18,6 @@
 #ifndef _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 #define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 
-
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
 typedef struct _Filter_State_
@@ -29,7 +28,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
@@ -37,6 +35,5 @@
     LVM_FLOAT                            coefs[5];       /* pointer to the filter coefficients */
 }Filter_State_FLOAT;
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 
 #endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.c b/media/libeffects/lvm/lib/Common/src/Copy_16.c
deleted file mode 100644
index 3858450..0000000
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION COPY_16
-***********************************************************************************/
-
-void Copy_16( const LVM_INT16 *src,
-                    LVM_INT16 *dst,
-                    LVM_INT16  n )
-{
-    LVM_INT16 ii;
-
-    if (src > dst)
-    {
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = *src;
-            dst++;
-            src++;
-        }
-    }
-    else
-    {
-        src += n - 1;
-        dst += n - 1;
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = *src;
-            dst--;
-            src--;
-        }
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void Copy_Float( const LVM_FLOAT *src,
-                 LVM_FLOAT *dst,
-                 LVM_INT16  n )
-{
-    LVM_INT16 ii;
-
-    if (src > dst)
-    {
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = *src;
-            dst++;
-            src++;
-        }
-    }
-    else
-    {
-        src += n - 1;
-        dst += n - 1;
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = *src;
-            dst--;
-            src--;
-        }
-    }
-
-    return;
-}
-#ifdef SUPPORT_MC
-// Extract out the stereo channel pair from multichannel source.
-void Copy_Float_Mc_Stereo(const LVM_FLOAT *src,
-                 LVM_FLOAT *dst,
-                 LVM_INT16 NrFrames, /* Number of frames */
-                 LVM_INT32 NrChannels)
-{
-    LVM_INT16 ii;
-
-    if (NrChannels >= 2)
-    {
-        for (ii = NrFrames; ii != 0; ii--)
-        {
-            dst[0] = src[0];
-            dst[1] = src[1];
-            dst += 2;
-            src += NrChannels;
-        }
-    }
-    else if (NrChannels == 1)
-    {   // not expected to occur, provided for completeness.
-        src += (NrFrames - 1);
-        dst += 2 * (NrFrames - 1);
-        for (ii = NrFrames; ii != 0; ii--)
-        {
-            dst[0] = src[0];
-            dst[1] = src[0];
-            dst -= 2;
-            src --;
-        }
-    }
-}
-
-// Merge a multichannel source with stereo contained in dst, to dst.
-void Copy_Float_Stereo_Mc(const LVM_FLOAT *src,
-                 LVM_FLOAT *dst,
-                 LVM_INT16 NrFrames, /* Number of frames*/
-                 LVM_INT32 NrChannels)
-{
-    LVM_INT16 ii, jj;
-    LVM_FLOAT *src_st = dst + 2 * (NrFrames - 1);
-
-    // repack dst which carries stereo information
-    // together with the upper channels of src.
-    dst += NrChannels * (NrFrames - 1);
-    src += NrChannels * (NrFrames - 1);
-    for (ii = NrFrames; ii != 0; ii--)
-    {
-        dst[1] = src_st[1];
-        dst[0] = src_st[0]; // copy 1 before 0 is required for NrChannels == 3.
-        for (jj = 2; jj < NrChannels; jj++)
-        {
-            dst[jj] = src[jj];
-        }
-        dst    -= NrChannels;
-        src    -= NrChannels;
-        src_st -= 2;
-    }
-}
-#endif
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
new file mode 100644
index 0000000..3a50554
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION COPY_16
+***********************************************************************************/
+
+void Copy_16( const LVM_INT16 *src,
+                    LVM_INT16 *dst,
+                    LVM_INT16  n )
+{
+    LVM_INT16 ii;
+
+    if (src > dst)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        src += n - 1;
+        dst += n - 1;
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst--;
+            src--;
+        }
+    }
+
+    return;
+}
+void Copy_Float( const LVM_FLOAT *src,
+                 LVM_FLOAT *dst,
+                 LVM_INT16  n )
+{
+    LVM_INT16 ii;
+
+    if (src > dst)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        src += n - 1;
+        dst += n - 1;
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst--;
+            src--;
+        }
+    }
+
+    return;
+}
+#ifdef SUPPORT_MC
+// Extract out the stereo channel pair from multichannel source.
+void Copy_Float_Mc_Stereo(const LVM_FLOAT *src,
+                 LVM_FLOAT *dst,
+                 LVM_INT16 NrFrames, /* Number of frames */
+                 LVM_INT32 NrChannels)
+{
+    LVM_INT16 ii;
+
+    if (NrChannels >= 2)
+    {
+        for (ii = NrFrames; ii != 0; ii--)
+        {
+            dst[0] = src[0];
+            dst[1] = src[1];
+            dst += 2;
+            src += NrChannels;
+        }
+    }
+    else if (NrChannels == 1)
+    {   // not expected to occur, provided for completeness.
+        src += (NrFrames - 1);
+        dst += 2 * (NrFrames - 1);
+        for (ii = NrFrames; ii != 0; ii--)
+        {
+            dst[0] = src[0];
+            dst[1] = src[0];
+            dst -= 2;
+            src --;
+        }
+    }
+}
+
+// Merge a multichannel source with stereo contained in StereoOut, to dst.
+void Copy_Float_Stereo_Mc(const LVM_FLOAT *src,
+                 LVM_FLOAT *StereoOut,
+                 LVM_FLOAT *dst,
+                 LVM_INT16 NrFrames, /* Number of frames*/
+                 LVM_INT32 NrChannels)
+{
+    LVM_INT16 ii, jj;
+
+    // pack dst with stereo information of StereoOut
+    // together with the upper channels of src.
+    StereoOut += 2 * (NrFrames - 1);
+    dst += NrChannels * (NrFrames - 1);
+    src += NrChannels * (NrFrames - 1);
+    for (ii = NrFrames; ii != 0; ii--)
+    {
+        dst[1] = StereoOut[1];
+        dst[0] = StereoOut[0]; // copy 1 before 0 is required for NrChannels == 3.
+        for (jj = 2; jj < NrChannels; jj++)
+        {
+            dst[jj] = src[jj];
+        }
+        dst    -= NrChannels;
+        src    -= NrChannels;
+        StereoOut -= 2;
+    }
+}
+#endif
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
deleted file mode 100644
index ea98041..0000000
--- a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION CORE_MIXHARD_2ST_D32C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_FLOAT_t       *pInstance,
-                                    const LVM_FLOAT     *src1,
-                                    const LVM_FLOAT     *src2,
-                                    LVM_FLOAT     *dst,
-                                    LVM_INT16     n)
-{
-    LVM_FLOAT  Temp1,Temp2,Temp3;
-    LVM_INT16 ii;
-    LVM_FLOAT Current1Short;
-    LVM_FLOAT Current2Short;
-
-    Current1Short = (pInstance->Current1);
-    Current2Short = (pInstance->Current2);
-
-    for (ii = n; ii != 0; ii--){
-        Temp1 = *src1++;
-        Temp3 = Temp1 * Current1Short;
-        Temp2 = *src2++;
-        Temp1 = Temp2 * Current2Short;
-        Temp2 = (Temp1 / 2.0f) + (Temp3 / 2.0f);
-        if (Temp2 > 0.5f)
-            Temp2 = 1.0f;
-        else if (Temp2 < -0.5f )
-            Temp2 = -1.0f;
-        else
-            Temp2 = (Temp2 * 2);
-            *dst++ = Temp2;
-    }
-}
-#else
-void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src1,
-                                    const LVM_INT32     *src2,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_INT32  Temp1,Temp2,Temp3;
-    LVM_INT16 ii;
-    LVM_INT16 Current1Short;
-    LVM_INT16 Current2Short;
-
-    Current1Short = (LVM_INT16)(pInstance->Current1 >> 16);
-    Current2Short = (LVM_INT16)(pInstance->Current2 >> 16);
-
-    for (ii = n; ii != 0; ii--){
-        Temp1=*src1++;
-        MUL32x16INTO32(Temp1,Current1Short,Temp3,15)
-        Temp2=*src2++;
-        MUL32x16INTO32(Temp2,Current2Short,Temp1,15)
-        Temp2=(Temp1>>1)+(Temp3>>1);
-        if (Temp2 > 0x3FFFFFFF)
-            Temp2 = 0x7FFFFFFF;
-        else if (Temp2 < - 0x40000000)
-            Temp2 =  0x80000000;
-        else
-            Temp2=(Temp2<<1);
-            *dst++ = Temp2;
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.cpp
new file mode 100644
index 0000000..5e77335
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXHARD_2ST_D32C31_SAT
+***********************************************************************************/
+void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src1,
+                                    const LVM_FLOAT     *src2,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n)
+{
+    LVM_FLOAT  Temp1,Temp2,Temp3;
+    LVM_INT16 ii;
+    LVM_FLOAT Current1Short;
+    LVM_FLOAT Current2Short;
+
+    Current1Short = (pInstance->Current1);
+    Current2Short = (pInstance->Current2);
+
+    for (ii = n; ii != 0; ii--){
+        Temp1 = *src1++;
+        Temp3 = Temp1 * Current1Short;
+        Temp2 = *src2++;
+        Temp1 = Temp2 * Current2Short;
+        Temp2 = (Temp1 / 2.0f) + (Temp3 / 2.0f);
+        if (Temp2 > 0.5f)
+            Temp2 = 1.0f;
+        else if (Temp2 < -0.5f )
+            Temp2 = -1.0f;
+        else
+            Temp2 = (Temp2 * 2);
+            *dst++ = Temp2;
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
deleted file mode 100644
index 2814f19..0000000
--- a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
-***********************************************************************************/
-
-#ifdef BUILD_FLOAT /* BUILD_FLOAT */
-void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_FLOAT_t       *pInstance,
-                                    const LVM_FLOAT     *src,
-                                          LVM_FLOAT     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_FLOAT    Temp1,Temp2,Temp3;
-    LVM_INT16     OutLoop;
-    LVM_INT16     InLoop;
-    LVM_FLOAT    TargetTimesOneMinAlpha;
-    LVM_FLOAT    CurrentTimesAlpha;
-    LVM_INT16     ii,jj;
-
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    TargetTimesOneMinAlpha = ((1.0f -pInstance->Alpha) * pInstance->Target);
-    if (pInstance->Target >= pInstance->Current){
-        TargetTimesOneMinAlpha +=(LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
-    }
-
-    if (OutLoop){
-
-        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
-
-        for (ii = OutLoop; ii != 0; ii--){
-        Temp1 = *src++;
-        Temp2 = *dst;
-
-        Temp3 = Temp1 * (pInstance->Current);
-        Temp1 = Temp2 + Temp3;
-
-        if (Temp1 > 1.0f)
-            Temp1 = 1.0f;
-        else if (Temp1 < -1.0f)
-            Temp1 = -1.0f;
-
-        *dst++ = Temp1;
-        }
-    }
-
-    for (ii = InLoop; ii != 0; ii--){
-
-        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
-
-        for (jj = 4; jj!=0 ; jj--){
-            Temp1 = *src++;
-            Temp2 = *dst;
-
-            Temp3 = Temp1 * (pInstance->Current);
-            Temp1 = Temp2 + Temp3;
-
-            if (Temp1 > 1.0f)
-                Temp1 = 1.0f;
-            else if (Temp1 < -1.0f)
-                Temp1 = -1.0f;
-            *dst++ = Temp1;
-        }
-    }
-}
-#else
-void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_INT32    Temp1,Temp2,Temp3;
-    LVM_INT16     OutLoop;
-    LVM_INT16     InLoop;
-    LVM_INT32    TargetTimesOneMinAlpha;
-    LVM_INT32    CurrentTimesAlpha;
-    LVM_INT16     ii,jj;
-    LVM_INT16   CurrentShort;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31); /* Q31 * Q0 in Q0 */
-    if (pInstance->Target >= pInstance->Current){
-         TargetTimesOneMinAlpha +=2; /* Ceil*/
-    }
-
-    if (OutLoop){
-        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31);       /* Q0 * Q31 in Q0 */
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;                /* Q0 + Q0 into Q0*/
-        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                             /* From Q31 to Q15*/
-
-        for (ii = OutLoop; ii != 0; ii--){
-        Temp1=*src++;
-        Temp2=*dst;
-        MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
-        Temp1=(Temp2>>1)+(Temp3>>1);
-
-        if (Temp1 > 0x3FFFFFFF)
-            Temp1 = 0x7FFFFFFF;
-        else if (Temp1 < - 0x40000000)
-            Temp1 =  0x80000000;
-        else
-            Temp1=(Temp1<<1);
-            *dst++ = Temp1;
-        }
-    }
-
-    for (ii = InLoop; ii != 0; ii--){
-        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31);       /* Q0 * Q31 in Q0 */
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;                /* Q0 + Q0 into Q0*/
-        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                             /* From Q31 to Q15*/
-
-        for (jj = 4; jj!=0 ; jj--){
-        Temp1=*src++;
-        Temp2=*dst;
-        MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
-        Temp1=(Temp2>>1)+(Temp3>>1);
-
-        if (Temp1 > 0x3FFFFFFF)
-            Temp1 = 0x7FFFFFFF;
-        else if (Temp1 < - 0x40000000)
-            Temp1 =  0x80000000;
-        else
-            Temp1=(Temp1<<1);
-            *dst++ = Temp1;
-        }
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
new file mode 100644
index 0000000..8f5c0ae
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_FLOAT    Temp1,Temp2,Temp3;
+    LVM_INT16     OutLoop;
+    LVM_INT16     InLoop;
+    LVM_FLOAT    TargetTimesOneMinAlpha;
+    LVM_FLOAT    CurrentTimesAlpha;
+    LVM_INT16     ii,jj;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    TargetTimesOneMinAlpha = ((1.0f -pInstance->Alpha) * pInstance->Target);
+    if (pInstance->Target >= pInstance->Current){
+        TargetTimesOneMinAlpha +=(LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
+    }
+
+    if (OutLoop){
+
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (ii = OutLoop; ii != 0; ii--){
+        Temp1 = *src++;
+        Temp2 = *dst;
+
+        Temp3 = Temp1 * (pInstance->Current);
+        Temp1 = Temp2 + Temp3;
+
+        if (Temp1 > 1.0f)
+            Temp1 = 1.0f;
+        else if (Temp1 < -1.0f)
+            Temp1 = -1.0f;
+
+        *dst++ = Temp1;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--){
+
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (jj = 4; jj!=0 ; jj--){
+            Temp1 = *src++;
+            Temp2 = *dst;
+
+            Temp3 = Temp1 * (pInstance->Current);
+            Temp1 = Temp2 + Temp3;
+
+            if (Temp1 > 1.0f)
+                Temp1 = 1.0f;
+            else if (Temp1 < -1.0f)
+                Temp1 = -1.0f;
+            *dst++ = Temp1;
+        }
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
deleted file mode 100644
index 814ccee..0000000
--- a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_FLOAT_t       *pInstance,
-                                    const LVM_FLOAT     *src,
-                                    LVM_FLOAT     *dst,
-                                    LVM_INT16     n)
-{
-    LVM_FLOAT Temp1,Temp2;
-    LVM_INT16 OutLoop;
-    LVM_INT16 InLoop;
-    LVM_FLOAT TargetTimesOneMinAlpha;
-    LVM_FLOAT CurrentTimesAlpha;
-
-    LVM_INT16 ii;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    TargetTimesOneMinAlpha = (1.0f - pInstance->Alpha) * pInstance->Target; /* float * float in float */
-    if (pInstance->Target >= pInstance->Current)
-    {
-        TargetTimesOneMinAlpha += (LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
-    }
-
-    if (OutLoop != 0)
-    {
-        CurrentTimesAlpha = (pInstance->Current * pInstance->Alpha);
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
-
-        for (ii = OutLoop; ii != 0; ii--)
-        {
-            Temp1 = *src;
-            src++;
-
-            Temp2 = Temp1 * (pInstance->Current);
-            *dst = Temp2;
-            dst++;
-        }
-    }
-
-    for (ii = InLoop; ii != 0; ii--)
-    {
-        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
-
-            Temp1 = *src;
-            src++;
-
-            Temp2 = Temp1 * (pInstance->Current);
-            *dst = Temp2;
-            dst++;
-
-            Temp1 = *src;
-            src++;
-
-            Temp2 = Temp1 * (pInstance->Current);
-            *dst = Temp2;
-            dst++;
-
-            Temp1 = *src;
-            src++;
-
-            Temp2 = Temp1 * (pInstance->Current);
-            *dst = Temp2;
-            dst++;
-
-            Temp1 = *src;
-            src++;
-            Temp2 = Temp1 * (pInstance->Current);
-            *dst = Temp2;
-            dst++;
-    }
-}
-#else
-void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_INT32  Temp1,Temp2;
-    LVM_INT16 OutLoop;
-    LVM_INT16 InLoop;
-    LVM_INT32  TargetTimesOneMinAlpha;
-    LVM_INT32  CurrentTimesAlpha;
-    LVM_INT16 CurrentShort;
-    LVM_INT16 ii;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31) /* Q31 * Q31 in Q31 */
-    if (pInstance->Target >= pInstance->Current)
-    {
-         TargetTimesOneMinAlpha +=2; /* Ceil*/
-    }
-
-    if (OutLoop!=0)
-    {
-        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31)  /* Q31 * Q31 in Q31 */
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;          /* Q31 + Q31 into Q31*/
-        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                       /* From Q31 to Q15*/
-
-        for (ii = OutLoop; ii != 0; ii--)
-        {
-            Temp1=*src;
-            src++;
-
-            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
-            *dst = Temp2;
-            dst++;
-        }
-    }
-
-    for (ii = InLoop; ii != 0; ii--)
-    {
-        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31)  /* Q31 * Q31 in Q31 */
-        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;          /* Q31 + Q31 into Q31*/
-        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                       /* From Q31 to Q15*/
-            Temp1=*src;
-            src++;
-
-            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
-            *dst = Temp2;
-            dst++;
-
-            Temp1=*src;
-            src++;
-
-            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
-            *dst = Temp2;
-            dst++;
-
-            Temp1=*src;
-            src++;
-
-            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
-            *dst = Temp2;
-            dst++;
-
-            Temp1=*src;
-            src++;
-            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
-            *dst = Temp2;
-            dst++;
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.cpp
new file mode 100644
index 0000000..6ff7853
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_FLOAT_t       *pInstance,
+                                    const LVM_FLOAT     *src,
+                                    LVM_FLOAT     *dst,
+                                    LVM_INT16     n)
+{
+    LVM_FLOAT Temp1,Temp2;
+    LVM_INT16 OutLoop;
+    LVM_INT16 InLoop;
+    LVM_FLOAT TargetTimesOneMinAlpha;
+    LVM_FLOAT CurrentTimesAlpha;
+
+    LVM_INT16 ii;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    TargetTimesOneMinAlpha = (1.0f - pInstance->Alpha) * pInstance->Target; /* float * float in float */
+    if (pInstance->Target >= pInstance->Current)
+    {
+        TargetTimesOneMinAlpha += (LVM_FLOAT)(2.0f / 2147483647.0f); /* Ceil*/
+    }
+
+    if (OutLoop != 0)
+    {
+        CurrentTimesAlpha = (pInstance->Current * pInstance->Alpha);
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+        for (ii = OutLoop; ii != 0; ii--)
+        {
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--)
+    {
+        CurrentTimesAlpha = pInstance->Current * pInstance->Alpha;
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+
+            Temp1 = *src;
+            src++;
+            Temp2 = Temp1 * (pInstance->Current);
+            *dst = Temp2;
+            dst++;
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
deleted file mode 100644
index 13fac5e..0000000
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "DC_2I_D16_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-#ifdef BUILD_FLOAT
-void DC_2I_D16_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
-                           LVM_FLOAT               *pDataIn,
-                           LVM_FLOAT               *pDataOut,
-                           LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT LeftDC,RightDC;
-        LVM_FLOAT Diff;
-        LVM_INT32 j;
-        PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State) pInstance;
-
-        LeftDC = pBiquadState->LeftDC;
-        RightDC = pBiquadState->RightDC;
-        for(j = NrSamples-1; j >= 0; j--)
-        {
-            /* Subtract DC and saturate */
-            Diff =* (pDataIn++) - (LeftDC);
-            if (Diff > 1.0f) {
-                Diff = 1.0f; }
-            else if (Diff < -1.0f) {
-                Diff = -1.0f; }
-            *(pDataOut++) = (LVM_FLOAT)Diff;
-            if (Diff < 0) {
-                LeftDC -= DC_FLOAT_STEP; }
-            else {
-                LeftDC += DC_FLOAT_STEP; }
-
-
-            /* Subtract DC an saturate */
-            Diff =* (pDataIn++) - (RightDC);
-            if (Diff > 1.0f) {
-                Diff = 1.0f; }
-            else if (Diff < -1.0f) {
-                Diff = -1.0f; }
-            *(pDataOut++) = (LVM_FLOAT)Diff;
-            if (Diff < 0) {
-                RightDC -= DC_FLOAT_STEP; }
-            else {
-                RightDC += DC_FLOAT_STEP; }
-
-        }
-        pBiquadState->LeftDC = LeftDC;
-        pBiquadState->RightDC = RightDC;
-
-
-    }
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       DC_Mc_D16_TRC_WRA_01
- *
- * DESCRIPTION:
- *  DC removal from all channels of a multichannel input
- *
- * PARAMETERS:
- *  pInstance      Instance pointer
- *  pDataIn        Input/Source
- *  pDataOut       Output/Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void DC_Mc_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
-                          LVM_FLOAT               *pDataIn,
-                          LVM_FLOAT               *pDataOut,
-                          LVM_INT16               NrFrames,
-                          LVM_INT16               NrChannels)
-    {
-        LVM_FLOAT *ChDC;
-        LVM_FLOAT Diff;
-        LVM_INT32 j;
-        LVM_INT32 i;
-        PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc) pInstance;
-
-        ChDC = &pBiquadState->ChDC[0];
-        for (j = NrFrames - 1; j >= 0; j--)
-        {
-            /* Subtract DC and saturate */
-            for (i = NrChannels - 1; i >= 0; i--)
-            {
-                Diff = *(pDataIn++) - (ChDC[i]);
-                if (Diff > 1.0f) {
-                    Diff = 1.0f;
-                } else if (Diff < -1.0f) {
-                    Diff = -1.0f; }
-                *(pDataOut++) = (LVM_FLOAT)Diff;
-                if (Diff < 0) {
-                    ChDC[i] -= DC_FLOAT_STEP;
-                } else {
-                    ChDC[i] += DC_FLOAT_STEP; }
-            }
-
-        }
-
-    }
-#endif
-#else
-void DC_2I_D16_TRC_WRA_01( Biquad_Instance_t       *pInstance,
-                           LVM_INT16               *pDataIn,
-                           LVM_INT16               *pDataOut,
-                           LVM_INT16               NrSamples)
-    {
-        LVM_INT32 LeftDC,RightDC;
-        LVM_INT32 Diff;
-        LVM_INT32 j;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-        LeftDC  =   pBiquadState->LeftDC;
-        RightDC =   pBiquadState->RightDC;
-        for(j=NrSamples-1;j>=0;j--)
-        {
-            /* Subtract DC an saturate */
-            Diff=*(pDataIn++)-(LeftDC>>16);
-            if (Diff > 32767) {
-                Diff = 32767; }
-            else if (Diff < -32768) {
-                Diff = -32768; }
-            *(pDataOut++)=(LVM_INT16)Diff;
-            if (Diff < 0) {
-                LeftDC -= DC_D16_STEP; }
-            else {
-                LeftDC += DC_D16_STEP; }
-
-
-            /* Subtract DC an saturate */
-            Diff=*(pDataIn++)-(RightDC>>16);
-            if (Diff > 32767) {
-                Diff = 32767; }
-            else if (Diff < -32768) {
-                Diff = -32768; }
-            *(pDataOut++)=(LVM_INT16)Diff;
-            if (Diff < 0) {
-                RightDC -= DC_D16_STEP; }
-            else {
-                RightDC += DC_D16_STEP; }
-
-        }
-        pBiquadState->LeftDC    =   LeftDC;
-        pBiquadState->RightDC   =   RightDC;
-
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
new file mode 100644
index 0000000..a7ce4d3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+void DC_2I_D16_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                           LVM_FLOAT               *pDataIn,
+                           LVM_FLOAT               *pDataOut,
+                           LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT LeftDC,RightDC;
+        LVM_FLOAT Diff;
+        LVM_INT32 j;
+        PFilter_FLOAT_State pBiquadState = (PFilter_FLOAT_State) pInstance;
+
+        LeftDC = pBiquadState->LeftDC;
+        RightDC = pBiquadState->RightDC;
+        for(j = NrSamples-1; j >= 0; j--)
+        {
+            /* Subtract DC and saturate */
+            Diff =* (pDataIn++) - (LeftDC);
+            if (Diff > 1.0f) {
+                Diff = 1.0f; }
+            else if (Diff < -1.0f) {
+                Diff = -1.0f; }
+            *(pDataOut++) = (LVM_FLOAT)Diff;
+            if (Diff < 0) {
+                LeftDC -= DC_FLOAT_STEP; }
+            else {
+                LeftDC += DC_FLOAT_STEP; }
+
+            /* Subtract DC an saturate */
+            Diff =* (pDataIn++) - (RightDC);
+            if (Diff > 1.0f) {
+                Diff = 1.0f; }
+            else if (Diff < -1.0f) {
+                Diff = -1.0f; }
+            *(pDataOut++) = (LVM_FLOAT)Diff;
+            if (Diff < 0) {
+                RightDC -= DC_FLOAT_STEP; }
+            else {
+                RightDC += DC_FLOAT_STEP; }
+
+        }
+        pBiquadState->LeftDC = LeftDC;
+        pBiquadState->RightDC = RightDC;
+
+    }
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       DC_Mc_D16_TRC_WRA_01
+ *
+ * DESCRIPTION:
+ *  DC removal from all channels of a multichannel input
+ *
+ * PARAMETERS:
+ *  pInstance      Instance pointer
+ *  pDataIn        Input/Source
+ *  pDataOut       Output/Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void DC_Mc_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
+                          LVM_FLOAT               *pDataIn,
+                          LVM_FLOAT               *pDataOut,
+                          LVM_INT16               NrFrames,
+                          LVM_INT16               NrChannels)
+    {
+        LVM_FLOAT *ChDC;
+        LVM_FLOAT Diff;
+        LVM_INT32 j;
+        LVM_INT32 i;
+        PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc) pInstance;
+
+        ChDC = &pBiquadState->ChDC[0];
+        for (j = NrFrames - 1; j >= 0; j--)
+        {
+            /* Subtract DC and saturate */
+            for (i = NrChannels - 1; i >= 0; i--)
+            {
+                Diff = *(pDataIn++) - (ChDC[i]);
+                if (Diff > 1.0f) {
+                    Diff = 1.0f;
+                } else if (Diff < -1.0f) {
+                    Diff = -1.0f; }
+                *(pDataOut++) = (LVM_FLOAT)Diff;
+                if (Diff < 0) {
+                    ChDC[i] -= DC_FLOAT_STEP;
+                } else {
+                    ChDC[i] += DC_FLOAT_STEP; }
+            }
+
+        }
+
+    }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
deleted file mode 100644
index 0f941a0..0000000
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "DC_2I_D16_TRC_WRA_01_Private.h"
-#ifdef BUILD_FLOAT
-void  DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t   *pInstance)
-{
-    PFilter_FLOAT_State pBiquadState  = (PFilter_FLOAT_State) pInstance;
-    pBiquadState->LeftDC        = 0.0f;
-    pBiquadState->RightDC       = 0.0f;
-}
-#ifdef SUPPORT_MC
-void  DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t   *pInstance)
-{
-    PFilter_FLOAT_State_Mc pBiquadState  = (PFilter_FLOAT_State_Mc) pInstance;
-    LVM_INT32 i;
-    for (i = 0; i < LVM_MAX_CHANNELS; i++)
-    {
-        pBiquadState->ChDC[i] = 0.0f;
-    }
-}
-#endif
-#else
-void  DC_2I_D16_TRC_WRA_01_Init(Biquad_Instance_t   *pInstance)
-{
-    PFilter_State pBiquadState  = (PFilter_State) pInstance;
-    pBiquadState->LeftDC        = 0;
-    pBiquadState->RightDC       = 0;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..beee112
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+void  DC_2I_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t   *pInstance)
+{
+    PFilter_FLOAT_State pBiquadState  = (PFilter_FLOAT_State) pInstance;
+    pBiquadState->LeftDC        = 0.0f;
+    pBiquadState->RightDC       = 0.0f;
+}
+#ifdef SUPPORT_MC
+void  DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t   *pInstance)
+{
+    PFilter_FLOAT_State_Mc pBiquadState  = (PFilter_FLOAT_State_Mc) pInstance;
+    LVM_INT32 i;
+    for (i = 0; i < LVM_MAX_CHANNELS; i++)
+    {
+        pBiquadState->ChDC[i] = 0.0f;
+    }
+}
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
index db3a6d3..6508b73 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -18,16 +18,10 @@
 #ifndef _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 #define _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
 
-#ifdef BUILD_FLOAT
 #define DC_FLOAT_STEP   0.0000002384f;
-#else
-#define DC_D16_STEP     0x200;
-#endif
-
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.*/
-#ifdef BUILD_FLOAT
 typedef struct _Filter_FLOAT_State_
 {
     LVM_FLOAT  LeftDC;     /* LeftDC  */
@@ -41,13 +35,4 @@
 } Filter_FLOAT_State_Mc;
 typedef Filter_FLOAT_State_Mc * PFilter_FLOAT_State_Mc ;
 #endif
-#else
-typedef struct _Filter_State_
-{
-  LVM_INT32  LeftDC;     /* LeftDC  */
-  LVM_INT32  RightDC;    /* RightDC  */
-}Filter_State;
-
-typedef Filter_State * PFilter_State ;
-#endif
 #endif /* _DC_2I_D16_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
deleted file mode 100644
index b04e98e..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION DelayAllPass_32x32
-***********************************************************************************/
-
-void DelayAllPass_Sat_32x16To32(  LVM_INT32  *delay,                    /* Delay buffer */
-                                  LVM_UINT16 size,                      /* Delay size */
-                                  LVM_INT16 coeff,                      /* All pass filter coefficient */
-                                  LVM_UINT16 DelayOffset,               /* Simple delay offset */
-                                  LVM_UINT16 *pAllPassOffset,           /* All pass filter delay offset */
-                                  LVM_INT32  *dst,                      /* Source/destination */
-                                  LVM_INT16 n)                          /* Number of  samples */
-{
-    LVM_INT16   i;
-    LVM_UINT16   AllPassOffset = *pAllPassOffset;
-    LVM_INT32    temp;
-    LVM_INT32    a,b,c;
-
-    for (i = 0; i < n; i++)
-    {
-
-        MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15)
-        a = temp;
-        b = delay[DelayOffset];
-        DelayOffset++;
-
-        c = a + b;
-        if ((((c ^ a) & (c ^ b)) >> 31) != 0)  /* overflow / underflow */
-        {
-            if(a < 0)
-            {
-                c = 0x80000000L;
-            }
-            else
-            {
-                c = 0x7FFFFFFFL;
-            }
-        }
-        *dst = c;
-        dst++;
-
-
-        MUL32x16INTO32(c, -coeff, temp, 15)
-        a = temp;
-        b = delay[AllPassOffset];
-        c = a + b;
-        if ((((c ^ a) & (c ^ b)) >> 31)!=0)  /* overflow / underflow */
-        {
-            if(a < 0)
-            {
-                c = 0x80000000L;
-            }
-            else
-            {
-                c = 0x7FFFFFFFL;
-            }
-        }
-        delay[AllPassOffset] = c;
-        AllPassOffset++;
-
-        /* Make the delay buffer a circular buffer */
-        if (DelayOffset >= size)
-        {
-            DelayOffset = 0;
-        }
-
-        if (AllPassOffset >= size)
-        {
-            AllPassOffset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pAllPassOffset = AllPassOffset;
-
-    return;
-}
-
-/**********************************************************************************/
-
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
new file mode 100644
index 0000000..771fae2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION DelayAllPass_32x32
+***********************************************************************************/
+
+void DelayAllPass_Sat_32x16To32(  LVM_INT32  *delay,                    /* Delay buffer */
+                                  LVM_UINT16 size,                      /* Delay size */
+                                  LVM_INT16 coeff,                      /* All pass filter coefficient */
+                                  LVM_UINT16 DelayOffset,               /* Simple delay offset */
+                                  LVM_UINT16 *pAllPassOffset,           /* All pass filter delay offset */
+                                  LVM_INT32  *dst,                      /* Source/destination */
+                                  LVM_INT16 n)                          /* Number of  samples */
+{
+    LVM_INT16   i;
+    LVM_UINT16   AllPassOffset = *pAllPassOffset;
+    LVM_INT32    temp;
+    LVM_INT32    a,b,c;
+
+    for (i = 0; i < n; i++)
+    {
+
+        MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15)
+        a = temp;
+        b = delay[DelayOffset];
+        DelayOffset++;
+
+        c = a + b;
+        if ((((c ^ a) & (c ^ b)) >> 31) != 0)  /* overflow / underflow */
+        {
+            if(a < 0)
+            {
+                c = 0x80000000L;
+            }
+            else
+            {
+                c = 0x7FFFFFFFL;
+            }
+        }
+        *dst = c;
+        dst++;
+
+        MUL32x16INTO32(c, -coeff, temp, 15)
+        a = temp;
+        b = delay[AllPassOffset];
+        c = a + b;
+        if ((((c ^ a) & (c ^ b)) >> 31)!=0)  /* overflow / underflow */
+        {
+            if(a < 0)
+            {
+                c = 0x80000000L;
+            }
+            else
+            {
+                c = 0x7FFFFFFFL;
+            }
+        }
+        delay[AllPassOffset] = c;
+        AllPassOffset++;
+
+        /* Make the delay buffer a circular buffer */
+        if (DelayOffset >= size)
+        {
+            DelayOffset = 0;
+        }
+
+        if (AllPassOffset >= size)
+        {
+            AllPassOffset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pAllPassOffset = AllPassOffset;
+
+    return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
deleted file mode 100644
index f502716..0000000
--- a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION DelayMix_16x16
-***********************************************************************************/
-
-void DelayMix_16x16(const LVM_INT16 *src,           /* Source 1, to be delayed */
-                          LVM_INT16 *delay,         /* Delay buffer */
-                          LVM_INT16 size,           /* Delay size */
-                          LVM_INT16 *dst,           /* Source/destination */
-                          LVM_INT16 *pOffset,       /* Delay offset */
-                          LVM_INT16 n)              /* Number of stereo samples */
-{
-    LVM_INT16   i;
-    LVM_INT16   Offset  = *pOffset;
-    LVM_INT16   temp;
-
-    for (i = 0; i < n; i++)
-    {
-        /* Left channel */
-        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
-        *dst = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-
-        /* Right channel */
-        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
-        *dst = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-        /* Make the reverb delay buffer a circular buffer */
-        if (Offset >= size)
-        {
-            Offset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pOffset = Offset;
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void DelayMix_Float(const LVM_FLOAT *src,           /* Source 1, to be delayed */
-                          LVM_FLOAT *delay,         /* Delay buffer */
-                          LVM_INT16 size,           /* Delay size */
-                          LVM_FLOAT *dst,           /* Source/destination */
-                          LVM_INT16 *pOffset,       /* Delay offset */
-                          LVM_INT16 n)              /* Number of stereo samples */
-{
-    LVM_INT16   i;
-    LVM_INT16   Offset  = *pOffset;
-    LVM_FLOAT   temp;
-
-    for (i=0; i<n; i++)
-    {
-        /* Left channel */
-        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f);
-        *dst            = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-
-        /* Right channel */
-        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst - (LVM_FLOAT)delay[Offset]) / 2.0f);
-        *dst            = temp;
-        dst++;
-
-        delay[Offset] = *src;
-        Offset++;
-        src++;
-
-        /* Make the reverb delay buffer a circular buffer */
-        if (Offset >= size)
-        {
-            Offset = 0;
-        }
-    }
-
-    /* Update the offset */
-    *pOffset = Offset;
-
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
new file mode 100644
index 0000000..52d263f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION DelayMix_16x16
+***********************************************************************************/
+
+void DelayMix_16x16(const LVM_INT16 *src,           /* Source 1, to be delayed */
+                          LVM_INT16 *delay,         /* Delay buffer */
+                          LVM_INT16 size,           /* Delay size */
+                          LVM_INT16 *dst,           /* Source/destination */
+                          LVM_INT16 *pOffset,       /* Delay offset */
+                          LVM_INT16 n)              /* Number of stereo samples */
+{
+    LVM_INT16   i;
+    LVM_INT16   Offset  = *pOffset;
+    LVM_INT16   temp;
+
+    for (i = 0; i < n; i++)
+    {
+        /* Left channel */
+        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
+        *dst = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Right channel */
+        temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
+        *dst = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Make the reverb delay buffer a circular buffer */
+        if (Offset >= size)
+        {
+            Offset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pOffset = Offset;
+
+    return;
+}
+void DelayMix_Float(const LVM_FLOAT *src,           /* Source 1, to be delayed */
+                          LVM_FLOAT *delay,         /* Delay buffer */
+                          LVM_INT16 size,           /* Delay size */
+                          LVM_FLOAT *dst,           /* Source/destination */
+                          LVM_INT16 *pOffset,       /* Delay offset */
+                          LVM_INT16 n)              /* Number of stereo samples */
+{
+    LVM_INT16   i;
+    LVM_INT16   Offset  = *pOffset;
+    LVM_FLOAT   temp;
+
+    for (i=0; i<n; i++)
+    {
+        /* Left channel */
+        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst + (LVM_FLOAT)delay[Offset]) / 2.0f);
+        *dst            = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Right channel */
+        temp            = (LVM_FLOAT)((LVM_FLOAT)(*dst - (LVM_FLOAT)delay[Offset]) / 2.0f);
+        *dst            = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Make the reverb delay buffer a circular buffer */
+        if (Offset >= size)
+        {
+            Offset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pOffset = Offset;
+
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/DelayWrite_32.c
rename to media/libeffects/lvm/lib/Common/src/DelayWrite_32.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
deleted file mode 100644
index 039c88c..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A1,
- pBiquadState->coefs[1] is A0,
- pBiquadState->coefs[2] is -B1, these are in Q15 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is y(n-1)L in Q0 format
-***************************************************************************/
-
-#ifdef BUILD_FLOAT
-void FO_1I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
-                                 LVM_FLOAT               *pDataIn,
-                                 LVM_FLOAT               *pDataOut,
-                                 LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL;
-        LVM_INT16 ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A1  * x(n-1)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-
-            // ynL+=A0  * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
-
-            // ynL+=  (-B1  * y(n-1)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * pBiquadState->pDelays[1];
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
-
-        }
-
-    }
-#else
-void FO_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t       *pInstance,
-                                 LVM_INT16               *pDataIn,
-                                 LVM_INT16               *pDataOut,
-                                 LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A1 (Q15) * x(n-1)L (Q0) in Q15
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
-
-            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
-
-            // ynL+=  (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
-            ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[1];
-
-
-            ynL=(LVM_INT16)(ynL>>15); // ynL in Q0 format
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
new file mode 100644
index 0000000..bef0d62
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL;
+        LVM_INT16 ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1  * x(n-1)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
+
+            // ynL+=  (-B1  * y(n-1)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[2] * pBiquadState->pDelays[1];
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output
+
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
deleted file mode 100644
index b21b8a4..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   FO_1I_D16F16Css_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
-                                         FO_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
-    temp = pCoef->A1;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[2] = temp;
-}
-#else
-void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_Instance_t         *pInstance,
-                                         Biquad_1I_Order1_Taps_t   *pTaps,
-                                         FO_C16_Coefs_t            *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State)  pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *)     pTaps;
-
-  temp=pCoef->A1;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[2]=temp;
-}
-#endif
-/*------------------------------------------------*/
-/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
-
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..161225e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
+                                         FO_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)pTaps;
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
index 6fdb039..34f3df9 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -28,7 +28,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT
 {
     LVM_FLOAT *                          pDelays;        /* pointer to the delayed samples \
@@ -37,5 +36,4 @@
 }Filter_State_FLOAT;
 
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 #endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
deleted file mode 100644
index 416e8eb..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A1,
- pBiquadState->coefs[1] is A0,
- pBiquadState->coefs[2] is -B1, these are in Q31 format
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is y(n-1)L in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void FO_1I_D32F32C31_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
-                                 LVM_FLOAT               *pDataIn,
-                                 LVM_FLOAT               *pDataOut,
-                                 LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT  ynL,templ;
-        LVM_INT16  ii;
-        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A1  * x(n-1)L
-            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-
-            // ynL+=A0  * x(n)L
-            templ = pBiquadState->coefs[1] * (*pDataIn);
-            ynL += templ;
-
-            // ynL+=  (-B1  * y(n-1)L
-            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[1];
-            ynL += templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
-        }
-
-    }
-#else
-void FO_1I_D32F32C31_TRC_WRA_01( Biquad_Instance_t       *pInstance,
-                                 LVM_INT32               *pDataIn,
-                                 LVM_INT32               *pDataOut,
-                                 LVM_INT16               NrSamples)
-    {
-        LVM_INT32  ynL,templ;
-        LVM_INT16  ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            // ynL=A1 (Q31) * x(n-1)L (Q0) >>31 in Q0
-            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[0],ynL,31)
-
-            // ynL+=A0 (Q31) * x(n)L (Q0) >> 31 in Q0
-            MUL32x32INTO32(pBiquadState->coefs[1],*pDataIn,templ,31)
-            ynL+=templ;
-
-            // ynL+=  (-B1 (Q31) * y(n-1)L (Q0) ) >> 31 in Q0
-            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[1],templ,31)
-            ynL+=templ;
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut++=(LVM_INT32)ynL; // Write Left output in Q0
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
new file mode 100644
index 0000000..e3efad7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q31 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_FLOAT_Instance_t       *pInstance,
+                                 LVM_FLOAT               *pDataIn,
+                                 LVM_FLOAT               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT  ynL,templ;
+        LVM_INT16  ii;
+        PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1  * x(n-1)L
+            ynL = pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+
+            // ynL+=A0  * x(n)L
+            templ = pBiquadState->coefs[1] * (*pDataIn);
+            ynL += templ;
+
+            // ynL+=  (-B1  * y(n-1)L
+            templ = pBiquadState->coefs[2] * pBiquadState->pDelays[1];
+            ynL += templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++ = (LVM_FLOAT)ynL; // Write Left output in Q0
+        }
+
+    }
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
deleted file mode 100644
index f33d24d..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   FO_1I_D32F32Cll_TRC_WRA_01_Init                                       */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t         *pInstance,
-                                      Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
-                                      FO_FLOAT_Coefs_t            *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *)    pTaps;
-
-    temp = pCoef->A1;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[2] = temp;
-}
-#else
-void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t         *pInstance,
-                                      Biquad_1I_Order1_Taps_t   *pTaps,
-                                      FO_C32_Coefs_t            *pCoef)
-{
-  LVM_INT32 temp;
-  PFilter_State pBiquadState = (PFilter_State)  pInstance;
-  pBiquadState->pDelays      = (LVM_INT32 *)    pTaps;
-
-  temp=pCoef->A1;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[2]=temp;
-}
-#endif
-/*------------------------------------------------*/
-/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
-
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..bb5295c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_1I_D32F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_FLOAT_Instance_t         *pInstance,
+                                      Biquad_1I_Order1_FLOAT_Taps_t   *pTaps,
+                                      FO_FLOAT_Coefs_t            *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT)  pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *)    pTaps;
+
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
index fdb528b..67d1384 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -18,7 +18,6 @@
 #ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 #define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
 
-
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
 typedef struct _Filter_State_
@@ -29,7 +28,6 @@
 
 typedef Filter_State * PFilter_State ;
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_FLOAT_
 {
     LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
@@ -37,5 +35,4 @@
 }Filter_State_FLOAT;
 
 typedef Filter_State_FLOAT * PFilter_State_FLOAT ;
-#endif
 #endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
deleted file mode 100644
index 2a50f18..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1, these are in Q15 format
-pBiquadState->Shift    is Shift value
-DELAYS-
-pBiquadState->pDelays[0] is x(n-1)L in Q15 format
-pBiquadState->pDelays[1] is y(n-1)L in Q30 format
-pBiquadState->pDelays[2] is x(n-1)R in Q15 format
-pBiquadState->pDelays[3] is y(n-1)R in Q30 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
-                                     LVM_FLOAT               *pDataIn,
-                                     LVM_FLOAT               *pDataOut,
-                                     LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT   ynL,ynR;
-        LVM_FLOAT   Temp;
-        LVM_FLOAT   NegSatValue;
-        LVM_INT16   ii;
-
-        PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
-
-        NegSatValue = -1.0f;
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-
-            // ynL =A1  * x(n-1)L
-            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
-            // ynR =A1  * x(n-1)R
-            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
-
-
-            // ynL+=A0  * x(n)L
-            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
-            // ynR+=A0  * x(n)L
-            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn+1));
-
-
-            // ynL +=  (-B1  * y(n-1)L  )
-            Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
-            ynL += Temp;
-            // ynR +=  (-B1  * y(n-1)R ) )
-            Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
-            ynR += Temp;
-
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
-            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
-
-            pBiquadState->pDelays[3] = ynR; // Update y(n-1)R
-            pBiquadState->pDelays[2] = (*pDataIn++); // Update x(n-1)R
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-
-            /*Saturate results*/
-            if(ynL > 1.0f)
-            {
-                ynL = 1.0f;
-            }
-            else
-            {
-                if(ynL < NegSatValue)
-                {
-                    ynL = NegSatValue;
-                }
-            }
-
-            if(ynR > 1.0f)
-            {
-                ynR = 1.0f;
-            }
-            else
-            {
-                if(ynR < NegSatValue)
-                {
-                    ynR = NegSatValue;
-                }
-            }
-
-            *pDataOut++ = (LVM_FLOAT)ynL;
-            *pDataOut++ = (LVM_FLOAT)ynR;
-        }
-
-    }
-#ifdef SUPPORT_MC
-/**************************************************************************
-ASSUMPTIONS:
-COEFS-
-pBiquadState->coefs[0] is A1,
-pBiquadState->coefs[1] is A0,
-pBiquadState->coefs[2] is -B1,
-DELAYS-
-pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
-pBiquadState->pDelays[2*ch + 1] is y(n-1) of the 'ch' - channel
-The index 'ch' runs from 0 to (NrChannels - 1)
-
-PARAMETERS:
- pInstance        Pointer Instance
- pDataIn          Input/Source
- pDataOut         Output/Destination
- NrFrames         Number of frames
- NrChannels       Number of channels
-
-RETURNS:
- void
-***************************************************************************/
-void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
-                                     LVM_FLOAT               *pDataIn,
-                                     LVM_FLOAT               *pDataOut,
-                                     LVM_INT16               NrFrames,
-                                     LVM_INT16               NrChannels)
-    {
-        LVM_FLOAT   yn;
-        LVM_FLOAT   Temp;
-        LVM_INT16   ii;
-        LVM_INT16   ch;
-        PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
-
-        LVM_FLOAT   *pDelays = pBiquadState->pDelays;
-        LVM_FLOAT   *pCoefs  = &pBiquadState->coefs[0];
-        LVM_FLOAT   A0 = pCoefs[1];
-        LVM_FLOAT   A1 = pCoefs[0];
-        LVM_FLOAT   B1 = pCoefs[2];
-
-
-
-
-        for (ii = NrFrames; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE CHANNELS
-            ***************************************************************************/
-            for (ch = 0; ch < NrChannels; ch++)
-            {
-                // yn =A1  * x(n-1)
-                yn = (LVM_FLOAT)A1 * pDelays[0];
-
-                // yn+=A0  * x(n)
-                yn += (LVM_FLOAT)A0 * (*pDataIn);
-
-                // yn +=  (-B1  * y(n-1))
-                Temp = B1 * pDelays[1];
-                yn += Temp;
-
-
-                /**************************************************************************
-                                UPDATING THE DELAYS
-                ***************************************************************************/
-                pDelays[1] = yn; // Update y(n-1)
-                pDelays[0] = (*pDataIn++); // Update x(n-1)
-
-                /**************************************************************************
-                                WRITING THE OUTPUT
-                ***************************************************************************/
-
-                /*Saturate results*/
-                if (yn > 1.0f)
-                {
-                    yn = 1.0f;
-                } else if (yn < -1.0f) {
-                    yn = -1.0f;
-                }
-
-                *pDataOut++ = (LVM_FLOAT)yn;
-                pDelays += 2;
-            }
-            pDelays -= NrChannels * 2;
-        }
-    }
-#endif
-#else
-void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
-                                     LVM_INT16               *pDataIn,
-                                     LVM_INT16               *pDataOut,
-                                     LVM_INT16               NrSamples)
-    {
-        LVM_INT32   ynL,ynR;
-        LVM_INT32   Temp;
-        LVM_INT32   NegSatValue;
-        LVM_INT16   ii;
-        LVM_INT16   Shift;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-        NegSatValue = LVM_MAXINT_16 +1;
-        NegSatValue = -NegSatValue;
-
-        Shift = pBiquadState->Shift;
-
-
-        for (ii = NrSamples; ii != 0; ii--)
-        {
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-
-            // ynL =A1 (Q15) * x(n-1)L (Q15) in Q30
-            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
-            // ynR =A1 (Q15) * x(n-1)R (Q15) in Q30
-            ynR=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
-
-
-            // ynL+=A0 (Q15) * x(n)L (Q15) in Q30
-            ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
-            // ynR+=A0 (Q15) * x(n)L (Q15) in Q30
-            ynR+=(LVM_INT32)pBiquadState->coefs[1]* (*(pDataIn+1));
-
-
-            // ynL +=  (-B1 (Q15) * y(n-1)L (Q30) ) in Q30
-            MUL32x16INTO32(pBiquadState->pDelays[1],pBiquadState->coefs[2],Temp,15);
-            ynL +=Temp;
-            // ynR +=  (-B1 (Q15) * y(n-1)R (Q30) ) in Q30
-            MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[2],Temp,15);
-            ynR +=Temp;
-
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q30
-            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q15
-
-            pBiquadState->pDelays[3]=ynR; // Update y(n-1)R in Q30
-            pBiquadState->pDelays[2]=(*pDataIn++); // Update x(n-1)R in Q15
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            /*Apply shift: Instead of left shift on 16-bit result, right shift of (15-shift) is applied
-              for better SNR*/
-            ynL = ynL>>(15-Shift);
-            ynR = ynR>>(15-Shift);
-
-            /*Saturate results*/
-            if(ynL > LVM_MAXINT_16)
-            {
-                ynL = LVM_MAXINT_16;
-            }
-            else
-            {
-                if(ynL < NegSatValue)
-                {
-                    ynL = NegSatValue;
-                }
-            }
-
-            if(ynR > LVM_MAXINT_16)
-            {
-                ynR = LVM_MAXINT_16;
-            }
-            else
-            {
-                if(ynR < NegSatValue)
-                {
-                    ynR = NegSatValue;
-                }
-            }
-
-            *pDataOut++=(LVM_INT16)ynL;
-            *pDataOut++=(LVM_INT16)ynR;
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
new file mode 100644
index 0000000..6ca819a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ASSUMPTIONS:
+COEFS-
+pBiquadState->coefs[0] is A1,
+pBiquadState->coefs[1] is A0,
+pBiquadState->coefs[2] is -B1, these are in Q15 format
+pBiquadState->Shift    is Shift value
+DELAYS-
+pBiquadState->pDelays[0] is x(n-1)L in Q15 format
+pBiquadState->pDelays[1] is y(n-1)L in Q30 format
+pBiquadState->pDelays[2] is x(n-1)R in Q15 format
+pBiquadState->pDelays[3] is y(n-1)R in Q30 format
+***************************************************************************/
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t       *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT   ynL,ynR;
+        LVM_FLOAT   Temp;
+        LVM_FLOAT   NegSatValue;
+        LVM_INT16   ii;
+
+        PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+
+        NegSatValue = -1.0f;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+
+            // ynL =A1  * x(n-1)L
+            ynL = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[0];
+            // ynR =A1  * x(n-1)R
+            ynR = (LVM_FLOAT)pBiquadState->coefs[0] * pBiquadState->pDelays[2];
+
+            // ynL+=A0  * x(n)L
+            ynL += (LVM_FLOAT)pBiquadState->coefs[1] * (*pDataIn);
+            // ynR+=A0  * x(n)L
+            ynR += (LVM_FLOAT)pBiquadState->coefs[1] * (*(pDataIn+1));
+
+            // ynL +=  (-B1  * y(n-1)L  )
+            Temp = pBiquadState->pDelays[1] * pBiquadState->coefs[2];
+            ynL += Temp;
+            // ynR +=  (-B1  * y(n-1)R ) )
+            Temp = pBiquadState->pDelays[3] * pBiquadState->coefs[2];
+            ynR += Temp;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1] = ynL; // Update y(n-1)L
+            pBiquadState->pDelays[0] = (*pDataIn++); // Update x(n-1)L
+
+            pBiquadState->pDelays[3] = ynR; // Update y(n-1)R
+            pBiquadState->pDelays[2] = (*pDataIn++); // Update x(n-1)R
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+
+            /*Saturate results*/
+            if(ynL > 1.0f)
+            {
+                ynL = 1.0f;
+            }
+            else
+            {
+                if(ynL < NegSatValue)
+                {
+                    ynL = NegSatValue;
+                }
+            }
+
+            if(ynR > 1.0f)
+            {
+                ynR = 1.0f;
+            }
+            else
+            {
+                if(ynR < NegSatValue)
+                {
+                    ynR = NegSatValue;
+                }
+            }
+
+            *pDataOut++ = (LVM_FLOAT)ynL;
+            *pDataOut++ = (LVM_FLOAT)ynR;
+        }
+
+    }
+#ifdef SUPPORT_MC
+/**************************************************************************
+ASSUMPTIONS:
+COEFS-
+pBiquadState->coefs[0] is A1,
+pBiquadState->coefs[1] is A0,
+pBiquadState->coefs[2] is -B1,
+DELAYS-
+pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
+pBiquadState->pDelays[2*ch + 1] is y(n-1) of the 'ch' - channel
+The index 'ch' runs from 0 to (NrChannels - 1)
+
+PARAMETERS:
+ pInstance        Pointer Instance
+ pDataIn          Input/Source
+ pDataOut         Output/Destination
+ NrFrames         Number of frames
+ NrChannels       Number of channels
+
+RETURNS:
+ void
+***************************************************************************/
+void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrFrames,
+                                     LVM_INT16               NrChannels)
+    {
+        LVM_FLOAT   yn;
+        LVM_FLOAT   Temp;
+        LVM_INT16   ii;
+        LVM_INT16   ch;
+        PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+
+        LVM_FLOAT   *pDelays = pBiquadState->pDelays;
+        LVM_FLOAT   *pCoefs  = &pBiquadState->coefs[0];
+        LVM_FLOAT   A0 = pCoefs[1];
+        LVM_FLOAT   A1 = pCoefs[0];
+        LVM_FLOAT   B1 = pCoefs[2];
+
+        for (ii = NrFrames; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE CHANNELS
+            ***************************************************************************/
+            for (ch = 0; ch < NrChannels; ch++)
+            {
+                // yn =A1  * x(n-1)
+                yn = (LVM_FLOAT)A1 * pDelays[0];
+
+                // yn+=A0  * x(n)
+                yn += (LVM_FLOAT)A0 * (*pDataIn);
+
+                // yn +=  (-B1  * y(n-1))
+                Temp = B1 * pDelays[1];
+                yn += Temp;
+
+                /**************************************************************************
+                                UPDATING THE DELAYS
+                ***************************************************************************/
+                pDelays[1] = yn; // Update y(n-1)
+                pDelays[0] = (*pDataIn++); // Update x(n-1)
+
+                /**************************************************************************
+                                WRITING THE OUTPUT
+                ***************************************************************************/
+
+                /*Saturate results*/
+                if (yn > 1.0f)
+                {
+                    yn = 1.0f;
+                } else if (yn < -1.0f) {
+                    yn = -1.0f;
+                }
+
+                *pDataOut++ = (LVM_FLOAT)yn;
+                pDelays += 2;
+            }
+            pDelays -= NrChannels * 2;
+        }
+    }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
deleted file mode 100644
index 33ca6cf..0000000
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   FO_2I_D16F32Css_LShx_TRC_WRA_01_Init                                  */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   These functions initializes a BIQUAD filter defined as a cascade of   */
-/*   biquadratic Filter Sections.                                          */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*   pInstance    - output, returns the pointer to the State Variable      */
-/*                   This state pointer must be passed to any subsequent   */
-/*                   call to "Biquad" functions.                           */
-/*   pTaps         - input, pointer to the taps memory                     */
-/*   pCoef         - input, pointer to the coefficient structure           */
-/*   N             - M coefficient factor of QM.N                          */
-/* RETURNS:                                                                */
-/*   void return code                                                      */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
-                                          Biquad_2I_Order1_FLOAT_Taps_t   *pTaps,
-                                          FO_FLOAT_LShx_Coefs_t        *pCoef)
-{
-    LVM_FLOAT temp;
-    PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
-    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
-
-    temp = pCoef->A1;
-    pBiquadState->coefs[0] = temp;
-    temp = pCoef->A0;
-    pBiquadState->coefs[1] = temp;
-    temp = pCoef->B1;
-    pBiquadState->coefs[2] = temp;
-}
-#else
-void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
-                                          Biquad_2I_Order1_Taps_t   *pTaps,
-                                          FO_C16_LShx_Coefs_t        *pCoef)
-{
-  LVM_INT16 temp;
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
-
-  temp=pCoef->A1;
-  pBiquadState->coefs[0]=temp;
-  temp=pCoef->A0;
-  pBiquadState->coefs[1]=temp;
-  temp=pCoef->B1;
-  pBiquadState->coefs[2]=temp;
-
-  temp=pCoef->Shift;
-  pBiquadState->Shift = temp;
-}
-#endif
-/*-------------------------------------------------------------------------*/
-/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c                     */
-
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..b81b976
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_2I_D16F32Css_LShx_TRC_WRA_01_Init                                  */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
+                                          Biquad_2I_Order1_FLOAT_Taps_t   *pTaps,
+                                          FO_FLOAT_LShx_Coefs_t        *pCoef)
+{
+    LVM_FLOAT temp;
+    PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+    pBiquadState->pDelays      = (LVM_FLOAT *) pTaps            ;
+
+    temp = pCoef->A1;
+    pBiquadState->coefs[0] = temp;
+    temp = pCoef->A0;
+    pBiquadState->coefs[1] = temp;
+    temp = pCoef->B1;
+    pBiquadState->coefs[2] = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c                     */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
index 368bfce..5022500 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -20,7 +20,6 @@
 
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_
 {
     LVM_FLOAT     *pDelays;       /* pointer to the delayed samples (data of 32 bits)   */
@@ -28,14 +27,4 @@
 }Filter_Float_State;
 
 typedef Filter_Float_State * PFilter_Float_State ;
-#else
-typedef struct _Filter_State_
-{
-  LVM_INT32     *pDelays;       /* pointer to the delayed samples (data of 32 bits)   */
-  LVM_INT16     coefs[3];       /* pointer to the filter coefficients */
-  LVM_INT16     Shift;          /* Shift value*/
-}Filter_State;
-
-typedef Filter_State * PFilter_State ;
-#endif
 #endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Filters.h b/media/libeffects/lvm/lib/Common/src/Filters.h
index b1fde0c..b5db8f4 100644
--- a/media/libeffects/lvm/lib/Common/src/Filters.h
+++ b/media/libeffects/lvm/lib/Common/src/Filters.h
@@ -18,10 +18,6 @@
 #ifndef FILTERS_H
 #define FILTERS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 #include "LVM_Types.h"
 
 /************************************************************************************/
@@ -34,17 +30,6 @@
  * Biquad with coefficients A0, A1, A2, B1 and B2 coefficients
  */
 /* Single precision (16-bit) Biquad section coefficients */
-#ifndef BUILD_FLOAT
-typedef struct
-{
-        LVM_INT16   A0;
-        LVM_INT16   A1;
-        LVM_INT16   A2;
-        LVM_INT16   B1;
-        LVM_INT16   B2;
-        LVM_UINT16  Scale;
-} BiquadA012B12CoefsSP_t;
-#else
 typedef struct
 {
     LVM_FLOAT   A0;
@@ -54,20 +39,10 @@
     LVM_FLOAT   B2;
     LVM_UINT16  Scale;
 } BiquadA012B12CoefsSP_t;
-#endif
 /*
  * Biquad with coefficients A0, A1 and B1 coefficients
  */
 /* Single precision (16-bit) Biquad section coefficients */
-#ifndef BUILD_FLOAT
-typedef struct
-{
-        LVM_INT16   A0;
-        LVM_INT16   A1;
-        LVM_INT16   B1;
-        LVM_UINT16  Scale;
-} BiquadA01B1CoefsSP_t;
-#else
 typedef struct
 {
     LVM_FLOAT   A0;
@@ -75,10 +50,6 @@
     LVM_FLOAT   B1;
     LVM_UINT16  Scale;
 } BiquadA01B1CoefsSP_t;
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif      /* FILTERS_H */
 
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
deleted file mode 100644
index 2c6e6c3..0000000
--- a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION  From2iToMS_16x16
-***********************************************************************************/
-
-void From2iToMS_16x16( const LVM_INT16  *src,
-                             LVM_INT16  *dstM,
-                             LVM_INT16  *dstS,
-                             LVM_INT16  n )
-{
-    LVM_INT32 temp1,left,right;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--)
-    {
-        left = (LVM_INT32)*src;
-        src++;
-
-        right = (LVM_INT32)*src;
-        src++;
-
-        /* Compute M signal*/
-        temp1 =  (left+right)>>1;
-        *dstM = (LVM_INT16)temp1;
-        dstM++;
-
-        /* Compute S signal*/
-        temp1 =  (left-right)>>1;
-        *dstS = (LVM_INT16)temp1;
-        dstS++;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void From2iToMS_Float( const LVM_FLOAT  *src,
-                             LVM_FLOAT  *dstM,
-                             LVM_FLOAT  *dstS,
-                             LVM_INT16  n )
-{
-    LVM_FLOAT temp1,left,right;
-    LVM_INT16 ii;
-    for (ii = n; ii != 0; ii--)
-    {
-        left = (LVM_FLOAT)*src;
-        src++;
-
-        right = (LVM_FLOAT)*src;
-        src++;
-
-        /* Compute M signal*/
-        temp1 =  (left + right) / 2.0f;
-        *dstM = (LVM_FLOAT)temp1;
-        dstM++;
-
-        /* Compute S signal*/
-        temp1 =  (left - right) / 2.0f;
-        *dstS = (LVM_FLOAT)temp1;
-        dstS++;
-    }
-
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
new file mode 100644
index 0000000..c3f6648
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION  From2iToMS_16x16
+***********************************************************************************/
+
+void From2iToMS_16x16( const LVM_INT16  *src,
+                             LVM_INT16  *dstM,
+                             LVM_INT16  *dstS,
+                             LVM_INT16  n )
+{
+    LVM_INT32 temp1,left,right;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        left = (LVM_INT32)*src;
+        src++;
+
+        right = (LVM_INT32)*src;
+        src++;
+
+        /* Compute M signal*/
+        temp1 =  (left+right)>>1;
+        *dstM = (LVM_INT16)temp1;
+        dstM++;
+
+        /* Compute S signal*/
+        temp1 =  (left-right)>>1;
+        *dstS = (LVM_INT16)temp1;
+        dstS++;
+    }
+
+    return;
+}
+void From2iToMS_Float( const LVM_FLOAT  *src,
+                             LVM_FLOAT  *dstM,
+                             LVM_FLOAT  *dstS,
+                             LVM_INT16  n )
+{
+    LVM_FLOAT temp1,left,right;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        left = (LVM_FLOAT)*src;
+        src++;
+
+        right = (LVM_FLOAT)*src;
+        src++;
+
+        /* Compute M signal*/
+        temp1 =  (left + right) / 2.0f;
+        *dstM = (LVM_FLOAT)temp1;
+        dstM++;
+
+        /* Compute S signal*/
+        temp1 =  (left - right) / 2.0f;
+        *dstS = (LVM_FLOAT)temp1;
+        dstS++;
+    }
+
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
rename to media/libeffects/lvm/lib/Common/src/From2iToMono_16.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
deleted file mode 100644
index d02af88..0000000
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION From2iToMono_32
-***********************************************************************************/
-
-void From2iToMono_32( const LVM_INT32 *src,
-                            LVM_INT32 *dst,
-                            LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_INT32 Temp;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        Temp = (*src>>1);
-        src++;
-
-        Temp +=(*src>>1);
-        src++;
-
-        *dst = Temp;
-        dst++;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void From2iToMono_Float( const LVM_FLOAT *src,
-                         LVM_FLOAT *dst,
-                         LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_FLOAT Temp;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        Temp = (*src);
-        src++;
-
-        Temp += (*src);
-        src++;
-
-        *dst = Temp / 2.0f;
-        dst++;
-    }
-
-    return;
-}
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       FromMcToMono_Float
- *
- * DESCRIPTION:
- *  Creates a mono stream from a multichannel input taking the avergae of
- *  sample values of all channels
- *
- * PARAMETERS:
- *  src            Source
- *  dst            Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void FromMcToMono_Float(const LVM_FLOAT *src,
-                        LVM_FLOAT *dst,
-                        LVM_INT16 NrFrames,
-                        LVM_INT16 NrChannels)
-{
-    LVM_INT16 ii, jj;
-    LVM_FLOAT Temp;
-
-    for (ii = NrFrames; ii != 0; ii--)
-    {
-        Temp = 0.0f;
-        for (jj = NrChannels; jj !=0; jj--)
-        {
-            Temp += (*src);
-            src++;
-        }
-        *dst = Temp / NrChannels;
-        dst++;
-    }
-
-    return;
-}
-#endif
-
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
new file mode 100644
index 0000000..a8688b4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION From2iToMono_32
+***********************************************************************************/
+
+void From2iToMono_32( const LVM_INT32 *src,
+                            LVM_INT32 *dst,
+                            LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 Temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = (*src>>1);
+        src++;
+
+        Temp +=(*src>>1);
+        src++;
+
+        *dst = Temp;
+        dst++;
+    }
+
+    return;
+}
+void From2iToMono_Float( const LVM_FLOAT *src,
+                         LVM_FLOAT *dst,
+                         LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT Temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = (*src);
+        src++;
+
+        Temp += (*src);
+        src++;
+
+        *dst = Temp / 2.0f;
+        dst++;
+    }
+
+    return;
+}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       FromMcToMono_Float
+ *
+ * DESCRIPTION:
+ *  Creates a mono stream from a multichannel input taking the avergae of
+ *  sample values of all channels
+ *
+ * PARAMETERS:
+ *  src            Source
+ *  dst            Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void FromMcToMono_Float(const LVM_FLOAT *src,
+                        LVM_FLOAT *dst,
+                        LVM_INT16 NrFrames,
+                        LVM_INT16 NrChannels)
+{
+    LVM_INT16 ii, jj;
+    LVM_FLOAT Temp;
+
+    for (ii = NrFrames; ii != 0; ii--)
+    {
+        Temp = 0.0f;
+        for (jj = NrChannels; jj !=0; jj--)
+        {
+            Temp += (*src);
+            src++;
+        }
+        *dst = Temp / NrChannels;
+        dst++;
+    }
+
+    return;
+}
+#endif
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.c b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
deleted file mode 100644
index a89a5c3..0000000
--- a/media/libeffects/lvm/lib/Common/src/InstAlloc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "InstAlloc.h"
-
-/****************************************************************************************
- *  Name        : InstAlloc_Init()
- *  Input       : pms  - Pointer to the INST_ALLOC instance
-                  StartAddr - Base address of the instance memory
- *  Returns     : Error code
- *  Description : Initializes the instance distribution and memory size calculation function
- *  Remarks     :
- ****************************************************************************************/
-
-void    InstAlloc_Init( INST_ALLOC      *pms,
-                        void            *StartAddr )
-{
-    pms->TotalSize = 3;
-    pms->pNextMember = (((uintptr_t)StartAddr + 3) & (uintptr_t)~3);
-}
-
-
-/****************************************************************************************
- *  Name        : InstAlloc_AddMember()
- *  Input       : pms  - Pointer to the INST_ALLOC instance
-                  Size - The size in bytes of the new added member
- *  Returns     : A pointer to the new added member
- *  Description : Allocates space for a new member in the instance memory and returns
-                  a pointer to this new member.  The start address of all members will
-                  be 32 bit alligned.
- *  Remarks     :
- ****************************************************************************************/
-
-void*   InstAlloc_AddMember( INST_ALLOC         *pms,
-                             LVM_UINT32           Size )
-{
-    void *NewMemberAddress; /* Variable to temporarily store the return value */
-    NewMemberAddress = (void*)pms->pNextMember;
-
-    Size = ((Size + 3) & (LVM_UINT32)~3); /* Ceil the size to a multiple of four */
-
-    pms->TotalSize += Size;
-    pms->pNextMember += Size;
-
-    return(NewMemberAddress);
-}
-
-
-/****************************************************************************************
- *  Name        : InstAlloc_GetTotal()
- *  Input       : pms  - Pointer to the INST_ALLOC instance
- *  Returns     : The instance memory size
- *  Description : This functions returns the calculated instance memory size
- *  Remarks     :
- ****************************************************************************************/
-
-LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms)
-{
-    if (pms->TotalSize > 3)
-    {
-        return(pms->TotalSize);
-    }
-    else
-    {
-        return 0;           /* No memory added */
-    }
-}
-
-
-void    InstAlloc_InitAll( INST_ALLOC                      *pms,
-                           LVM_MemoryTable_st             *pMemoryTable)
-{
-    uintptr_t StartAddr;
-
-    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
-
-    pms[0].TotalSize = 3;
-    pms[0].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
-
-    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
-
-    pms[1].TotalSize = 3;
-    pms[1].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
-
-    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
-
-    pms[2].TotalSize = 3;
-    pms[2].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
-
-    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
-
-    pms[3].TotalSize = 3;
-    pms[3].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
-
-}
-
-/****************************************************************************************
- *  Name        : InstAlloc_InitAll_NULL()
- *  Input       : pms  - Pointer to array of four INST_ALLOC instances
- *  Returns     : Nothing
- *  Description : This function reserves Size of 3 bytes for all memory regions and
- *                intializes pNextMember for all regions to 0
- *  Remarks     :
- ****************************************************************************************/
-
-void    InstAlloc_InitAll_NULL( INST_ALLOC  *pms)
-{
-    pms[0].TotalSize = 3;
-    pms[0].pNextMember = 0;
-
-
-    pms[1].TotalSize = 3;
-    pms[1].pNextMember = 0;
-
-    pms[2].TotalSize = 3;
-    pms[2].pNextMember = 0;
-
-    pms[3].TotalSize = 3;
-    pms[3].pNextMember = 0;
-
-}
-
-
-void*   InstAlloc_AddMemberAll( INST_ALLOC                     *pms,
-                                 LVM_UINT32                   Size[],
-                                 LVM_MemoryTable_st           *pMemoryTable)
-{
-    void *NewMemberAddress; /* Variable to temporarily store the return value */
-
-    /* coverity[returned_pointer] Ignore coverity warning that ptr is not used */
-    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
-
-    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_SLOW_DATA]);
-    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
-    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
-    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
-
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_DATA]);
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-
-    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
-
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_COEF]);
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
-    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-
-    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
-
-    pMemoryTable->Region[LVM_TEMPORARY_FAST].Size                 = InstAlloc_GetTotal(&pms[LVM_TEMPORARY_FAST]);
-    pMemoryTable->Region[LVM_TEMPORARY_FAST].Type                 = LVM_TEMPORARY_FAST;
-    pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress         = LVM_NULL;
-
-    return(NewMemberAddress);
-}
-
-
-void*   InstAlloc_AddMemberAllRet(     INST_ALLOC                 *pms,
-                                     LVM_UINT32               Size[],
-                                     void                    **ptr)
-{
-    ptr[0] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
-    ptr[1] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
-    ptr[2] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
-    ptr[3] = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
-
-    return (ptr[0]);
-}
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp b/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp
new file mode 100644
index 0000000..a039bf5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "InstAlloc.h"
+
+/****************************************************************************************
+ *  Name        : InstAlloc_Init()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  StartAddr - Base address of the instance memory
+ *  Returns     : Error code
+ *  Description : Initializes the instance distribution and memory size calculation function
+ *  Remarks     :
+ ****************************************************************************************/
+
+void    InstAlloc_Init( INST_ALLOC      *pms,
+                        void            *StartAddr )
+{
+    pms->TotalSize = 3;
+    pms->pNextMember = (((uintptr_t)StartAddr + 3) & (uintptr_t)~3);
+}
+
+/****************************************************************************************
+ *  Name        : InstAlloc_AddMember()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  Size - The size in bytes of the new added member
+ *  Returns     : A pointer to the new added member
+ *  Description : Allocates space for a new member in the instance memory and returns
+                  a pointer to this new member.  The start address of all members will
+                  be 32 bit alligned.
+ *  Remarks     :
+ ****************************************************************************************/
+
+void*   InstAlloc_AddMember( INST_ALLOC         *pms,
+                             LVM_UINT32           Size )
+{
+    void *NewMemberAddress; /* Variable to temporarily store the return value */
+    NewMemberAddress = (void*)pms->pNextMember;
+
+    Size = ((Size + 3) & (LVM_UINT32)~3); /* Ceil the size to a multiple of four */
+
+    pms->TotalSize += Size;
+    pms->pNextMember += Size;
+
+    return(NewMemberAddress);
+}
+
+/****************************************************************************************
+ *  Name        : InstAlloc_GetTotal()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+ *  Returns     : The instance memory size
+ *  Description : This functions returns the calculated instance memory size
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms)
+{
+    if (pms->TotalSize > 3)
+    {
+        return(pms->TotalSize);
+    }
+    else
+    {
+        return 0;           /* No memory added */
+    }
+}
+
+void    InstAlloc_InitAll( INST_ALLOC                      *pms,
+                           LVM_MemoryTable_st             *pMemoryTable)
+{
+    uintptr_t StartAddr;
+
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
+
+    pms[0].TotalSize = 3;
+    pms[0].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
+
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pms[1].TotalSize = 3;
+    pms[1].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
+
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pms[2].TotalSize = 3;
+    pms[2].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
+
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
+
+    pms[3].TotalSize = 3;
+    pms[3].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
+
+}
+
+/****************************************************************************************
+ *  Name        : InstAlloc_InitAll_NULL()
+ *  Input       : pms  - Pointer to array of four INST_ALLOC instances
+ *  Returns     : Nothing
+ *  Description : This function reserves Size of 3 bytes for all memory regions and
+ *                intializes pNextMember for all regions to 0
+ *  Remarks     :
+ ****************************************************************************************/
+
+void    InstAlloc_InitAll_NULL( INST_ALLOC  *pms)
+{
+    pms[0].TotalSize = 3;
+    pms[0].pNextMember = 0;
+
+    pms[1].TotalSize = 3;
+    pms[1].pNextMember = 0;
+
+    pms[2].TotalSize = 3;
+    pms[2].pNextMember = 0;
+
+    pms[3].TotalSize = 3;
+    pms[3].pNextMember = 0;
+
+}
+
+void*   InstAlloc_AddMemberAll( INST_ALLOC                     *pms,
+                                 LVM_UINT32                   Size[],
+                                 LVM_MemoryTable_st           *pMemoryTable)
+{
+    void *NewMemberAddress; /* Variable to temporarily store the return value */
+
+    /* coverity[returned_pointer] Ignore coverity warning that ptr is not used */
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_SLOW_DATA]);
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_DATA]);
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_COEF]);
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].Size                 = InstAlloc_GetTotal(&pms[LVM_TEMPORARY_FAST]);
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].Type                 = LVM_TEMPORARY_FAST;
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress         = LVM_NULL;
+
+    return(NewMemberAddress);
+}
+
+void*   InstAlloc_AddMemberAllRet(     INST_ALLOC                 *pms,
+                                     LVM_UINT32               Size[],
+                                     void                    **ptr)
+{
+    ptr[0] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+    ptr[1] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+    ptr[2] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+    ptr[3] = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+    return (ptr[0]);
+}
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
rename to media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c
rename to media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
deleted file mode 100644
index ebc477e..0000000
--- a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION JoinTo2i_32x32
-***********************************************************************************/
-
-void JoinTo2i_32x32( const LVM_INT32    *srcL,
-                     const LVM_INT32    *srcR,
-                           LVM_INT32    *dst,
-                           LVM_INT16    n )
-{
-    LVM_INT16 ii;
-
-    srcL += n-1;
-    srcR += n-1;
-    dst  += ((2*n)-1);
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = *srcR;
-        dst--;
-        srcR--;
-
-        *dst = *srcL;
-        dst--;
-        srcL--;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void JoinTo2i_Float( const LVM_FLOAT    *srcL,
-                     const LVM_FLOAT    *srcR,
-                           LVM_FLOAT    *dst,
-                           LVM_INT16    n )
-{
-    LVM_INT16 ii;
-
-    srcL += n - 1;
-    srcR += n - 1;
-    dst  += ((2 * n) - 1);
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = *srcR;
-        dst--;
-        srcR--;
-
-        *dst = *srcL;
-        dst--;
-        srcL--;
-    }
-
-    return;
-}
-#endif
-/**********************************************************************************/
-
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
new file mode 100644
index 0000000..05df656
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION JoinTo2i_32x32
+***********************************************************************************/
+
+void JoinTo2i_32x32( const LVM_INT32    *srcL,
+                     const LVM_INT32    *srcR,
+                           LVM_INT32    *dst,
+                           LVM_INT16    n )
+{
+    LVM_INT16 ii;
+
+    srcL += n-1;
+    srcR += n-1;
+    dst  += ((2*n)-1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *srcR;
+        dst--;
+        srcR--;
+
+        *dst = *srcL;
+        dst--;
+        srcL--;
+    }
+
+    return;
+}
+void JoinTo2i_Float( const LVM_FLOAT    *srcL,
+                     const LVM_FLOAT    *srcR,
+                           LVM_FLOAT    *dst,
+                           LVM_INT16    n )
+{
+    LVM_INT16 ii;
+
+    srcL += n - 1;
+    srcR += n - 1;
+    dst  += ((2 * n) - 1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *srcR;
+        dst--;
+        srcR--;
+
+        *dst = *srcL;
+        dst--;
+        srcL--;
+    }
+
+    return;
+}
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
deleted file mode 100644
index db76cd1..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-
-
-/**********************************************************************************
-   FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_FLOAT_st        *ptrInstance1,
-                                         LVMixer3_FLOAT_st        *ptrInstance2,
-                                         const LVM_FLOAT    *src,
-                                         LVM_FLOAT          *dst,
-                                         LVM_INT16          n)
-{
-    LVM_FLOAT  Temp;
-    LVM_INT16 ii;
-    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
-    for (ii = n; ii != 0; ii--)
-    {
-        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = (LVM_FLOAT)Temp;
-
-        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance2->Current);
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = (LVM_FLOAT)Temp;
-    }
-
-
-}
-#ifdef SUPPORT_MC
-void LVC_Core_MixHard_1St_MC_float_SAT (Mix_Private_FLOAT_st **ptrInstance,
-                                         const LVM_FLOAT      *src,
-                                         LVM_FLOAT            *dst,
-                                         LVM_INT16            NrFrames,
-                                         LVM_INT16            NrChannels)
-{
-    LVM_FLOAT  Temp;
-    LVM_INT16 ii, jj;
-    for (ii = NrFrames; ii != 0; ii--)
-    {
-        for (jj = 0; jj < NrChannels; jj++)
-        {
-            Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance[jj]);
-            Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
-            if (Temp > 1.0f)
-                *dst++ = 1.0f;
-            else if (Temp < -1.0f)
-                *dst++ = -1.0f;
-            else
-                *dst++ = (LVM_FLOAT)Temp;
-        }
-    }
-}
-#endif
-#else
-void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
-                                         LVMixer3_st        *ptrInstance2,
-                                         const LVM_INT16    *src,
-                                         LVM_INT16          *dst,
-                                         LVM_INT16          n)
-{
-    LVM_INT32  Temp;
-    LVM_INT16 ii;
-    LVM_INT16 Current1Short;
-    LVM_INT16 Current2Short;
-    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
-
-
-    Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
-    Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
-
-    for (ii = n; ii != 0; ii--)
-    {
-        Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current1Short)>>15;
-        if (Temp > 0x00007FFF)
-            *dst++ = 0x7FFF;
-        else if (Temp < -0x00008000)
-            *dst++ = - 0x8000;
-        else
-            *dst++ = (LVM_INT16)Temp;
-
-        Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current2Short)>>15;
-        if (Temp > 0x00007FFF)
-            *dst++ = 0x7FFF;
-        else if (Temp < -0x00008000)
-            *dst++ = - 0x8000;
-        else
-            *dst++ = (LVM_INT16)Temp;
-    }
-
-
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
new file mode 100644
index 0000000..14d61bd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
+***********************************************************************************/
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_FLOAT  Temp;
+    LVM_INT16 ii;
+    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = (LVM_FLOAT)Temp;
+
+        Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance2->Current);
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = (LVM_FLOAT)Temp;
+    }
+
+}
+#ifdef SUPPORT_MC
+void LVC_Core_MixHard_1St_MC_float_SAT (Mix_Private_FLOAT_st **ptrInstance,
+                                         const LVM_FLOAT      *src,
+                                         LVM_FLOAT            *dst,
+                                         LVM_INT16            NrFrames,
+                                         LVM_INT16            NrChannels)
+{
+    LVM_FLOAT  Temp;
+    LVM_INT16 ii, jj;
+    for (ii = NrFrames; ii != 0; ii--)
+    {
+        for (jj = 0; jj < NrChannels; jj++)
+        {
+            Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance[jj]);
+            Temp = ((LVM_FLOAT)*(src++) * (LVM_FLOAT)pInstance1->Current);
+            if (Temp > 1.0f)
+                *dst++ = 1.0f;
+            else if (Temp < -1.0f)
+                *dst++ = -1.0f;
+            else
+                *dst++ = (LVM_FLOAT)Temp;
+        }
+    }
+}
+#endif
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
deleted file mode 100644
index ec0baaf..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-
-/**********************************************************************************
-   FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance1,
-                                    LVMixer3_FLOAT_st         *ptrInstance2,
-                                    const LVM_FLOAT     *src1,
-                                    const LVM_FLOAT     *src2,
-                                          LVM_FLOAT     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_FLOAT  Temp;
-    LVM_INT16 ii;
-    LVM_FLOAT Current1;
-    LVM_FLOAT Current2;
-    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
-
-
-    Current1 = (pInstance1->Current);
-    Current2 = (pInstance2->Current);
-
-    for (ii = n; ii != 0; ii--){
-        Temp = (((LVM_FLOAT)*(src1++) * (LVM_FLOAT)Current1)) +
-               (((LVM_FLOAT)*(src2++) * (LVM_FLOAT)Current2));
-        if (Temp > 1.0f)
-            *dst++ = 1.0f;
-        else if (Temp < -1.0f)
-            *dst++ = -1.0f;
-        else
-            *dst++ = Temp;
-    }
-}
-#else
-void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *ptrInstance1,
-                                    LVMixer3_st         *ptrInstance2,
-                                    const LVM_INT16     *src1,
-                                    const LVM_INT16     *src2,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_INT32  Temp;
-    LVM_INT16 ii;
-    LVM_INT16 Current1Short;
-    LVM_INT16 Current2Short;
-    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
-
-
-    Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
-    Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
-
-    for (ii = n; ii != 0; ii--){
-        Temp = (((LVM_INT32)*(src1++) * (LVM_INT32)Current1Short)>>15) +
-               (((LVM_INT32)*(src2++) * (LVM_INT32)Current2Short)>>15);
-        if (Temp > 0x00007FFF)
-            *dst++ = 0x7FFF;
-        else if (Temp < -0x00008000)
-            *dst++ = - 0x8000;
-        else
-            *dst++ = (LVM_INT16)Temp;
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
new file mode 100644
index 0000000..841fa1e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
+***********************************************************************************/
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance1,
+                                    LVMixer3_FLOAT_st         *ptrInstance2,
+                                    const LVM_FLOAT     *src1,
+                                    const LVM_FLOAT     *src2,
+                                          LVM_FLOAT     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_FLOAT  Temp;
+    LVM_INT16 ii;
+    LVM_FLOAT Current1;
+    LVM_FLOAT Current2;
+    Mix_Private_FLOAT_st  *pInstance1 = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
+
+    Current1 = (pInstance1->Current);
+    Current2 = (pInstance2->Current);
+
+    for (ii = n; ii != 0; ii--){
+        Temp = (((LVM_FLOAT)*(src1++) * (LVM_FLOAT)Current1)) +
+               (((LVM_FLOAT)*(src2++) * (LVM_FLOAT)Current2));
+        if (Temp > 1.0f)
+            *dst++ = 1.0f;
+        else if (Temp < -1.0f)
+            *dst++ = -1.0f;
+        else
+            *dst++ = Temp;
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
deleted file mode 100644
index 419c7c5..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
-                                   const LVM_FLOAT   *src,
-                                         LVM_FLOAT   *dst,
-                                         LVM_INT16   n)
-{
-
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT32   ii,jj;
-    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
-    LVM_FLOAT   Delta = pInstance->Delta;
-    LVM_FLOAT   Current = pInstance->Current;
-    LVM_FLOAT   Target = pInstance->Target;
-    LVM_FLOAT   Temp;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if(Current < Target){
-        if (OutLoop){
-            Temp = Current + Delta;
-            Current = Temp;
-            if (Current > Target)
-                Current = Target;
-
-           for (ii = OutLoop; ii != 0; ii--){
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            Temp = Current + Delta;
-            Current = Temp;
-            if (Current > Target)
-                Current = Target;
-
-            for (jj = 4; jj != 0 ; jj--){
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
-            }
-        }
-    }
-    else{
-        if (OutLoop){
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (ii = OutLoop; ii != 0; ii--){
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (jj = 4; jj != 0 ; jj--){
-                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = (LVM_FLOAT)Temp;
-            }
-        }
-    }
-    pInstance->Current = Current;
-}
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       LVC_Core_MixInSoft_Mc_D16C31_SAT
- *
- * DESCRIPTION:
- *  Mixer function with support for processing multichannel input.
- *
- * PARAMETERS:
- *  ptrInstance    Instance pointer
- *  src            Source
- *  dst            Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
-                                      const LVM_FLOAT   *src,
-                                            LVM_FLOAT   *dst,
-                                            LVM_INT16   NrFrames,
-                                            LVM_INT16   NrChannels)
-{
-
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT32   ii, jj;
-    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
-    LVM_FLOAT   Delta = pInstance->Delta;
-    LVM_FLOAT   Current = pInstance->Current;
-    LVM_FLOAT   Target = pInstance->Target;
-    LVM_FLOAT   Temp;
-
-    /*
-     * Same operation is performed on consecutive frames.
-     * So two frames are processed in one iteration and
-     * the loop will run only for half the NrFrames value times.
-     */
-    InLoop = (LVM_INT16)(NrFrames >> 1);
-    /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
-    OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
-
-    if (Current < Target) {
-        if (OutLoop) {
-            Temp = Current + Delta;
-            Current = Temp;
-            if (Current > Target)
-                Current = Target;
-
-           for (ii = OutLoop*NrChannels; ii != 0; ii--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--) {
-            Temp = Current + Delta;
-            Current = Temp;
-            if (Current > Target)
-                Current = Target;
-
-            for (jj = NrChannels; jj != 0 ; jj--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-
-            }
-        }
-    }
-    else{
-        if (OutLoop) {
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (ii = OutLoop*NrChannels; ii != 0; ii--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--) {
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (jj = NrChannels; jj != 0 ; jj--) {
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-
-                Temp = (*dst) + (*(src++) * Current);
-                if (Temp > 1.0f)
-                    *dst++ = 1.0f;
-                else if (Temp < -1.0f)
-                    *dst++ = -1.0f;
-                else
-                    *dst++ = Temp;
-
-            }
-        }
-    }
-    pInstance->Current = Current;
-}
-
-#endif
-#else
-void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
-                                    const LVM_INT16     *src,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n)
-{
-
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT16   CurrentShort;
-    LVM_INT32   ii,jj;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
-    LVM_INT32   Delta=pInstance->Delta;
-    LVM_INT32   Current=pInstance->Current;
-    LVM_INT32   Target=pInstance->Target;
-    LVM_INT32   Temp;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if(Current<Target){
-        if (OutLoop){
-            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (ii = OutLoop; ii != 0; ii--){
-                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
-                if (Temp > 0x00007FFF)
-                    *dst++ = 0x7FFF;
-                else if (Temp < -0x00008000)
-                    *dst++ = - 0x8000;
-                else
-                    *dst++ = (LVM_INT16)Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (jj = 4; jj!=0 ; jj--){
-                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
-                if (Temp > 0x00007FFF)
-                    *dst++ = 0x7FFF;
-                else if (Temp < -0x00008000)
-                    *dst++ = - 0x8000;
-                else
-                    *dst++ = (LVM_INT16)Temp;
-            }
-        }
-    }
-    else{
-        if (OutLoop){
-            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
-            if (Current < Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (ii = OutLoop; ii != 0; ii--){
-                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
-                if (Temp > 0x00007FFF)
-                    *dst++ = 0x7FFF;
-                else if (Temp < -0x00008000)
-                    *dst++ = - 0x8000;
-                else
-                    *dst++ = (LVM_INT16)Temp;
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
-            if (Current < Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (jj = 4; jj!=0 ; jj--){
-                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
-                if (Temp > 0x00007FFF)
-                    *dst++ = 0x7FFF;
-                else if (Temp < -0x00008000)
-                    *dst++ = - 0x8000;
-                else
-                    *dst++ = (LVM_INT16)Temp;
-            }
-        }
-    }
-    pInstance->Current=Current;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
new file mode 100644
index 0000000..318138d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+void LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
+                                   const LVM_FLOAT   *src,
+                                         LVM_FLOAT   *dst,
+                                         LVM_INT16   n)
+{
+
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii,jj;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta = pInstance->Delta;
+    LVM_FLOAT   Current = pInstance->Current;
+    LVM_FLOAT   Target = pInstance->Target;
+    LVM_FLOAT   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current < Target){
+        if (OutLoop){
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+           for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (jj = 4; jj != 0 ; jj--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (jj = 4; jj != 0 ; jj--){
+                Temp = ((LVM_FLOAT)*dst) + (((LVM_FLOAT)*(src++) * Current));
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = (LVM_FLOAT)Temp;
+            }
+        }
+    }
+    pInstance->Current = Current;
+}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       LVC_Core_MixInSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ *  Mixer function with support for processing multichannel input.
+ *
+ * PARAMETERS:
+ *  ptrInstance    Instance pointer
+ *  src            Source
+ *  dst            Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
+                                      const LVM_FLOAT   *src,
+                                            LVM_FLOAT   *dst,
+                                            LVM_INT16   NrFrames,
+                                            LVM_INT16   NrChannels)
+{
+
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii, jj;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta = pInstance->Delta;
+    LVM_FLOAT   Current = pInstance->Current;
+    LVM_FLOAT   Target = pInstance->Target;
+    LVM_FLOAT   Temp;
+
+    /*
+     * Same operation is performed on consecutive frames.
+     * So two frames are processed in one iteration and
+     * the loop will run only for half the NrFrames value times.
+     */
+    InLoop = (LVM_INT16)(NrFrames >> 1);
+    /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
+    OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
+
+    if (Current < Target) {
+        if (OutLoop) {
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+           for (ii = OutLoop*NrChannels; ii != 0; ii--) {
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--) {
+            Temp = Current + Delta;
+            Current = Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (jj = NrChannels; jj != 0 ; jj--) {
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+
+            }
+        }
+    }
+    else{
+        if (OutLoop) {
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop*NrChannels; ii != 0; ii--) {
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--) {
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (jj = NrChannels; jj != 0 ; jj--) {
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+
+                Temp = (*dst) + (*(src++) * Current);
+                if (Temp > 1.0f)
+                    *dst++ = 1.0f;
+                else if (Temp < -1.0f)
+                    *dst++ = -1.0f;
+                else
+                    *dst++ = Temp;
+
+            }
+        }
+    }
+    pInstance->Current = Current;
+}
+
+#endif
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
deleted file mode 100644
index 56b5dae..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "ScalarArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a,
-                                LVM_FLOAT b,
-                                LVM_FLOAT c)
-{
-    LVM_FLOAT temp;
-    temp = a + b ;
-    if (temp < -1.0f)
-        c = -1.0f;
-    else if (temp > 1.0f)
-        c = 1.0f;
-    else
-        c = temp;
-    return c;
-}
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_FLOAT_st        *ptrInstance1,
-                                         LVMixer3_FLOAT_st        *ptrInstance2,
-                                         const LVM_FLOAT    *src,
-                                         LVM_FLOAT          *dst,
-                                         LVM_INT16          n)
-{
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT32   ii;
-    Mix_Private_FLOAT_st  *pInstanceL = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_FLOAT_st  *pInstanceR = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
-
-    LVM_FLOAT   DeltaL = pInstanceL->Delta;
-    LVM_FLOAT   CurrentL = pInstanceL->Current;
-    LVM_FLOAT   TargetL = pInstanceL->Target;
-
-    LVM_FLOAT   DeltaR = pInstanceR->Delta;
-    LVM_FLOAT   CurrentR = pInstanceR->Current;
-    LVM_FLOAT   TargetR = pInstanceR->Target;
-
-    LVM_FLOAT   Temp = 0;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if (OutLoop)
-    {
-        if(CurrentL < TargetL)
-        {
-            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
-            CurrentL = Temp;
-            if (CurrentL > TargetL)
-                CurrentL = TargetL;
-        }
-        else
-        {
-            CurrentL -= DeltaL;
-            if (CurrentL < TargetL)
-                CurrentL = TargetL;
-        }
-
-        if(CurrentR < TargetR)
-        {
-            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
-            CurrentR = Temp;
-            if (CurrentR > TargetR)
-                CurrentR = TargetR;
-        }
-        else
-        {
-            CurrentR -= DeltaR;
-            if (CurrentR < TargetR)
-                CurrentR = TargetR;
-        }
-
-        for (ii = OutLoop * 2; ii != 0; ii -= 2)
-        {
-            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
-            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
-        }
-    }
-
-    for (ii = InLoop * 2; ii != 0; ii-=2)
-    {
-        if(CurrentL < TargetL)
-        {
-            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
-            CurrentL = Temp;
-            if (CurrentL > TargetL)
-                CurrentL = TargetL;
-        }
-        else
-        {
-            CurrentL -= DeltaL;
-            if (CurrentL < TargetL)
-                CurrentL = TargetL;
-        }
-
-        if(CurrentR < TargetR)
-        {
-            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
-            CurrentR = Temp;
-            if (CurrentR > TargetR)
-                CurrentR = TargetR;
-        }
-        else
-        {
-            CurrentR -= DeltaR;
-            if (CurrentR < TargetR)
-                CurrentR = TargetR;
-        }
-
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
-        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
-    }
-    pInstanceL->Current = CurrentL;
-    pInstanceR->Current = CurrentR;
-
-}
-#ifdef SUPPORT_MC
-void LVC_Core_MixSoft_1St_MC_float_WRA (Mix_Private_FLOAT_st **ptrInstance,
-                                         const LVM_FLOAT      *src,
-                                         LVM_FLOAT            *dst,
-                                         LVM_INT16            NrFrames,
-                                         LVM_INT16            NrChannels)
-{
-    LVM_INT32   ii, ch;
-    LVM_FLOAT   Temp =0.0f;
-    LVM_FLOAT   tempCurrent[NrChannels];
-    for (ch = 0; ch < NrChannels; ch++)
-    {
-        tempCurrent[ch] = ptrInstance[ch]->Current;
-    }
-    for (ii = NrFrames; ii > 0; ii--)
-    {
-        for (ch = 0; ch < NrChannels; ch++)
-        {
-            Mix_Private_FLOAT_st *pInstance = ptrInstance[ch];
-            const LVM_FLOAT   Delta = pInstance->Delta;
-            LVM_FLOAT         Current = tempCurrent[ch];
-            const LVM_FLOAT   Target = pInstance->Target;
-            if (Current < Target)
-            {
-                ADD2_SAT_FLOAT(Current, Delta, Temp);
-                Current = Temp;
-                if (Current > Target)
-                    Current = Target;
-            }
-            else
-            {
-                Current -= Delta;
-                if (Current < Target)
-                    Current = Target;
-            }
-            *dst++ = *src++ * Current;
-            tempCurrent[ch] = Current;
-        }
-    }
-    for (ch = 0; ch < NrChannels; ch++)
-    {
-        ptrInstance[ch]->Current = tempCurrent[ch];
-    }
-}
-#endif
-#else
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
-                                         LVMixer3_st        *ptrInstance2,
-                                         const LVM_INT16    *src,
-                                         LVM_INT16          *dst,
-                                         LVM_INT16          n)
-{
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT16   CurrentShortL;
-    LVM_INT16   CurrentShortR;
-    LVM_INT32   ii;
-    Mix_Private_st  *pInstanceL=(Mix_Private_st *)(ptrInstance1->PrivateParams);
-    Mix_Private_st  *pInstanceR=(Mix_Private_st *)(ptrInstance2->PrivateParams);
-
-    LVM_INT32   DeltaL=pInstanceL->Delta;
-    LVM_INT32   CurrentL=pInstanceL->Current;
-    LVM_INT32   TargetL=pInstanceL->Target;
-
-    LVM_INT32   DeltaR=pInstanceR->Delta;
-    LVM_INT32   CurrentR=pInstanceR->Current;
-    LVM_INT32   TargetR=pInstanceR->Target;
-
-    LVM_INT32   Temp;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if (OutLoop)
-    {
-        if(CurrentL<TargetL)
-        {
-            ADD2_SAT_32x32(CurrentL,DeltaL,Temp);                                      /* Q31 + Q31 into Q31*/
-            CurrentL=Temp;
-            if (CurrentL > TargetL)
-                CurrentL = TargetL;
-        }
-        else
-        {
-            CurrentL -= DeltaL;                                                        /* Q31 + Q31 into Q31*/
-            if (CurrentL < TargetL)
-                CurrentL = TargetL;
-        }
-
-        if(CurrentR<TargetR)
-        {
-            ADD2_SAT_32x32(CurrentR,DeltaR,Temp);                                      /* Q31 + Q31 into Q31*/
-            CurrentR=Temp;
-            if (CurrentR > TargetR)
-                CurrentR = TargetR;
-        }
-        else
-        {
-            CurrentR -= DeltaR;                                                        /* Q31 + Q31 into Q31*/
-            if (CurrentR < TargetR)
-                CurrentR = TargetR;
-        }
-
-        CurrentShortL = (LVM_INT16)(CurrentL>>16);                                 /* From Q31 to Q15*/
-        CurrentShortR = (LVM_INT16)(CurrentR>>16);                                 /* From Q31 to Q15*/
-
-        for (ii = OutLoop*2; ii != 0; ii-=2)
-        {
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);    /* Q15*Q15>>15 into Q15 */
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);    /* Q15*Q15>>15 into Q15 */
-        }
-    }
-
-    for (ii = InLoop*2; ii != 0; ii-=2)
-    {
-        if(CurrentL<TargetL)
-        {
-            ADD2_SAT_32x32(CurrentL,DeltaL,Temp);                                      /* Q31 + Q31 into Q31*/
-            CurrentL=Temp;
-            if (CurrentL > TargetL)
-                CurrentL = TargetL;
-        }
-        else
-        {
-            CurrentL -= DeltaL;                                                        /* Q31 + Q31 into Q31*/
-            if (CurrentL < TargetL)
-                CurrentL = TargetL;
-        }
-
-        if(CurrentR<TargetR)
-        {
-            ADD2_SAT_32x32(CurrentR,DeltaR,Temp);                                      /* Q31 + Q31 into Q31*/
-            CurrentR=Temp;
-            if (CurrentR > TargetR)
-                CurrentR = TargetR;
-        }
-        else
-        {
-            CurrentR -= DeltaR;                                                        /* Q31 + Q31 into Q31*/
-            if (CurrentR < TargetR)
-                CurrentR = TargetR;
-        }
-
-        CurrentShortL = (LVM_INT16)(CurrentL>>16);                                 /* From Q31 to Q15*/
-        CurrentShortR = (LVM_INT16)(CurrentR>>16);                                 /* From Q31 to Q15*/
-
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);    /* Q15*Q15>>15 into Q15 */
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);    /* Q15*Q15>>15 into Q15 */
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
-        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
-    }
-    pInstanceL->Current=CurrentL;
-    pInstanceR->Current=CurrentR;
-
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
new file mode 100644
index 0000000..1f4b08a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
+***********************************************************************************/
+static LVM_FLOAT ADD2_SAT_FLOAT(LVM_FLOAT a,
+                                LVM_FLOAT b,
+                                LVM_FLOAT c)
+{
+    LVM_FLOAT temp;
+    temp = a + b ;
+    if (temp < -1.0f)
+        c = -1.0f;
+    else if (temp > 1.0f)
+        c = 1.0f;
+    else
+        c = temp;
+    return c;
+}
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_FLOAT_st        *ptrInstance1,
+                                         LVMixer3_FLOAT_st        *ptrInstance2,
+                                         const LVM_FLOAT    *src,
+                                         LVM_FLOAT          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii;
+    Mix_Private_FLOAT_st  *pInstanceL = (Mix_Private_FLOAT_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_FLOAT_st  *pInstanceR = (Mix_Private_FLOAT_st *)(ptrInstance2->PrivateParams);
+
+    LVM_FLOAT   DeltaL = pInstanceL->Delta;
+    LVM_FLOAT   CurrentL = pInstanceL->Current;
+    LVM_FLOAT   TargetL = pInstanceL->Target;
+
+    LVM_FLOAT   DeltaR = pInstanceR->Delta;
+    LVM_FLOAT   CurrentR = pInstanceR->Current;
+    LVM_FLOAT   TargetR = pInstanceR->Target;
+
+    LVM_FLOAT   Temp = 0;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if (OutLoop)
+    {
+        if(CurrentL < TargetL)
+        {
+            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
+            CurrentL = Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR < TargetR)
+        {
+            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
+            CurrentR = Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        for (ii = OutLoop * 2; ii != 0; ii -= 2)
+        {
+            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+            *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        }
+    }
+
+    for (ii = InLoop * 2; ii != 0; ii-=2)
+    {
+        if(CurrentL < TargetL)
+        {
+            ADD2_SAT_FLOAT(CurrentL, DeltaL, Temp);
+            CurrentL = Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR < TargetR)
+        {
+            ADD2_SAT_FLOAT(CurrentR, DeltaR, Temp);
+            CurrentR = Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentL));
+        *(dst++) = (LVM_FLOAT)(((LVM_FLOAT)*(src++) * (LVM_FLOAT)CurrentR));
+    }
+    pInstanceL->Current = CurrentL;
+    pInstanceR->Current = CurrentR;
+
+}
+#ifdef SUPPORT_MC
+void LVC_Core_MixSoft_1St_MC_float_WRA (Mix_Private_FLOAT_st **ptrInstance,
+                                         const LVM_FLOAT      *src,
+                                         LVM_FLOAT            *dst,
+                                         LVM_INT16            NrFrames,
+                                         LVM_INT16            NrChannels)
+{
+    LVM_INT32   ii, ch;
+    LVM_FLOAT   Temp =0.0f;
+    LVM_FLOAT   tempCurrent[NrChannels];
+    for (ch = 0; ch < NrChannels; ch++)
+    {
+        tempCurrent[ch] = ptrInstance[ch]->Current;
+    }
+    for (ii = NrFrames; ii > 0; ii--)
+    {
+        for (ch = 0; ch < NrChannels; ch++)
+        {
+            Mix_Private_FLOAT_st *pInstance = ptrInstance[ch];
+            const LVM_FLOAT   Delta = pInstance->Delta;
+            LVM_FLOAT         Current = tempCurrent[ch];
+            const LVM_FLOAT   Target = pInstance->Target;
+            if (Current < Target)
+            {
+                ADD2_SAT_FLOAT(Current, Delta, Temp);
+                Current = Temp;
+                if (Current > Target)
+                    Current = Target;
+            }
+            else
+            {
+                Current -= Delta;
+                if (Current < Target)
+                    Current = Target;
+            }
+            *dst++ = *src++ * Current;
+            tempCurrent[ch] = Current;
+        }
+    }
+    for (ch = 0; ch < NrChannels; ch++)
+    {
+        ptrInstance[ch]->Current = tempCurrent[ch];
+    }
+}
+#endif
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
deleted file mode 100644
index 5bfdad8..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Core_MixSoft_1St_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
-                                     const LVM_FLOAT   *src,
-                                           LVM_FLOAT   *dst,
-                                           LVM_INT16   n)
-{
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT32   ii;
-    Mix_Private_FLOAT_st  *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
-    LVM_FLOAT   Delta= (LVM_FLOAT)pInstance->Delta;
-    LVM_FLOAT   Current = (LVM_FLOAT)pInstance->Current;
-    LVM_FLOAT   Target= (LVM_FLOAT)pInstance->Target;
-    LVM_FLOAT   Temp;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if(Current<Target){
-        if (OutLoop){
-
-            Temp = Current + Delta;
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            for (ii = OutLoop; ii != 0; ii--){
-                *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-
-            Temp = Current + Delta;
-
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
-        }
-    }
-    else{
-        if (OutLoop){
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (ii = OutLoop; ii != 0; ii--){
-                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-        }
-    }
-    pInstance->Current=Current;
-}
-
-
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       LVC_Core_MixSoft_Mc_D16C31_WRA
- *
- * DESCRIPTION:
- *  Mixer function with support for processing multichannel input
- *
- * PARAMETERS:
- *  ptrInstance    Instance pointer
- *  src            Source
- *  dst            Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void LVC_Core_MixSoft_Mc_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
-                                    const LVM_FLOAT   *src,
-                                          LVM_FLOAT   *dst,
-                                          LVM_INT16   NrFrames,
-                                          LVM_INT16   NrChannels)
-{
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT32   ii, jj;
-    Mix_Private_FLOAT_st  *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
-    LVM_FLOAT   Delta= (LVM_FLOAT)pInstance->Delta;
-    LVM_FLOAT   Current = (LVM_FLOAT)pInstance->Current;
-    LVM_FLOAT   Target= (LVM_FLOAT)pInstance->Target;
-    LVM_FLOAT   Temp;
-
-    /*
-     * Same operation is performed on consecutive frames.
-     * So two frames are processed in one iteration and
-     * the loop will run only for half the NrFrames value times.
-     */
-    InLoop = (LVM_INT16)(NrFrames >> 1);
-    /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
-    OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
-
-    if (Current<Target) {
-        if (OutLoop) {
-
-            Temp = Current + Delta;
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            for (ii = OutLoop; ii != 0; ii--) {
-                for (jj = NrChannels; jj !=0; jj--) {
-                    *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
-                }
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--) {
-
-            Temp = Current + Delta;
-
-            if (Temp > 1.0f)
-                Temp = 1.0f;
-            else if (Temp < -1.0f)
-                Temp = -1.0f;
-
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            for (jj = NrChannels; jj != 0 ; jj--)
-            {
-                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            }
-        }
-    }
-    else{
-        if (OutLoop) {
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (ii = OutLoop; ii != 0; ii--) {
-                for (jj = NrChannels; jj !=0; jj--) {
-                    *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
-                }
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--) {
-            Current -= Delta;
-            if (Current < Target)
-                Current = Target;
-
-            for (jj = NrChannels; jj != 0 ; jj--)
-            {
-                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
-            }
-        }
-    }
-    pInstance->Current=Current;
-}
-#endif
-
-#else
-void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *ptrInstance,
-                                    const LVM_INT16     *src,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n)
-{
-    LVM_INT16   OutLoop;
-    LVM_INT16   InLoop;
-    LVM_INT16   CurrentShort;
-    LVM_INT32   ii;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
-    LVM_INT32   Delta=pInstance->Delta;
-    LVM_INT32   Current=pInstance->Current;
-    LVM_INT32   Target=pInstance->Target;
-    LVM_INT32   Temp;
-
-    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
-    OutLoop = (LVM_INT16)(n - (InLoop << 2));
-
-    if(Current<Target){
-        if (OutLoop){
-            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (ii = OutLoop; ii != 0; ii--){
-                *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
-            Current=Temp;
-            if (Current > Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-        }
-    }
-    else{
-        if (OutLoop){
-            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
-            if (Current < Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            for (ii = OutLoop; ii != 0; ii--){
-                *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
-            }
-        }
-
-        for (ii = InLoop; ii != 0; ii--){
-            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
-            if (Current < Target)
-                Current = Target;
-
-            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
-
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
-        }
-    }
-    pInstance->Current=Current;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
new file mode 100644
index 0000000..5d8aadc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+void LVC_Core_MixSoft_1St_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
+                                     const LVM_FLOAT   *src,
+                                           LVM_FLOAT   *dst,
+                                           LVM_INT16   n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii;
+    Mix_Private_FLOAT_st  *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta= (LVM_FLOAT)pInstance->Delta;
+    LVM_FLOAT   Current = (LVM_FLOAT)pInstance->Current;
+    LVM_FLOAT   Target= (LVM_FLOAT)pInstance->Target;
+    LVM_FLOAT   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current<Target){
+        if (OutLoop){
+
+            Temp = Current + Delta;
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+
+            Temp = Current + Delta;
+
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current) );
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+        }
+    }
+    pInstance->Current=Current;
+}
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       LVC_Core_MixSoft_Mc_D16C31_WRA
+ *
+ * DESCRIPTION:
+ *  Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ *  ptrInstance    Instance pointer
+ *  src            Source
+ *  dst            Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void LVC_Core_MixSoft_Mc_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT   *src,
+                                          LVM_FLOAT   *dst,
+                                          LVM_INT16   NrFrames,
+                                          LVM_INT16   NrChannels)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT32   ii, jj;
+    Mix_Private_FLOAT_st  *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+    LVM_FLOAT   Delta= (LVM_FLOAT)pInstance->Delta;
+    LVM_FLOAT   Current = (LVM_FLOAT)pInstance->Current;
+    LVM_FLOAT   Target= (LVM_FLOAT)pInstance->Target;
+    LVM_FLOAT   Temp;
+
+    /*
+     * Same operation is performed on consecutive frames.
+     * So two frames are processed in one iteration and
+     * the loop will run only for half the NrFrames value times.
+     */
+    InLoop = (LVM_INT16)(NrFrames >> 1);
+    /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
+    OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
+
+    if (Current<Target) {
+        if (OutLoop) {
+
+            Temp = Current + Delta;
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--) {
+                for (jj = NrChannels; jj !=0; jj--) {
+                    *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+                }
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--) {
+
+            Temp = Current + Delta;
+
+            if (Temp > 1.0f)
+                Temp = 1.0f;
+            else if (Temp < -1.0f)
+                Temp = -1.0f;
+
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            for (jj = NrChannels; jj != 0 ; jj--)
+            {
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            }
+        }
+    }
+    else{
+        if (OutLoop) {
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (ii = OutLoop; ii != 0; ii--) {
+                for (jj = NrChannels; jj !=0; jj--) {
+                    *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+                }
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--) {
+            Current -= Delta;
+            if (Current < Target)
+                Current = Target;
+
+            for (jj = NrChannels; jj != 0 ; jj--)
+            {
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+                *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+            }
+        }
+    }
+    pInstance->Current=Current;
+}
+#endif
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
deleted file mode 100644
index 65956f7..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "VectorArithmetic.h"
-#include "ScalarArithmetic.h"
-
-/**********************************************************************************
-   DEFINITIONS
-***********************************************************************************/
-
-#define TRUE          1
-#define FALSE         0
-
-/**********************************************************************************
-   FUNCTION MIXINSOFT_D16C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_MixInSoft_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
-                              const LVM_FLOAT       *src,
-                                    LVM_FLOAT       *dst,
-                                    LVM_INT16       n)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  *pInstance = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Delta == 1.0f){
-            pInstance->Current = pInstance->Target;
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            LVC_Core_MixInSoft_D16C31_SAT(&(ptrInstance->MixerStream[0]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
-            if ((pInstance->Target) == 1.0f){
-                Add2_Sat_Float(src, dst, n);
-            }
-            else{
-                Mac3s_Sat_Float(src, (pInstance->Target), dst, n);
-                /* In case the LVCore function would have changed the Current value */
-                pInstance->Current = pInstance->Target;
-            }
-        }
-    }
-
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet){
-        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0){
-                (*ptrInstance->MixerStream[0].pCallBack) ( \
-                                                ptrInstance->MixerStream[0].pCallbackHandle,
-                                                ptrInstance->MixerStream[0].pGeneralPurpose,
-                                                ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-
-}
-
-
-
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       LVC_MixInSoft_Mc_D16C31_SAT
- *
- * DESCRIPTION:
- *  Mixer function with support for processing multichannel input
- *
- * PARAMETERS:
- *  ptrInstance    Instance pointer
- *  src            Source
- *  dst            Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void LVC_MixInSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
-                                 const LVM_FLOAT       *src,
-                                       LVM_FLOAT       *dst,
-                                       LVM_INT16       NrFrames,
-                                       LVM_INT16       NrChannels)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  *pInstance = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if (NrFrames <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if (pInstance->Delta == 1.0f) {
-            pInstance->Current = pInstance->Target;
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            LVC_Core_MixInSoft_Mc_D16C31_SAT(&(ptrInstance->MixerStream[0]),
-                                             src,
-                                             dst,
-                                             NrFrames,
-                                             NrChannels);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing) {
-        if (pInstance->Target != 0) { /* Nothing to do in case Target = 0 */
-            if ((pInstance->Target) == 1.0f) {
-                Add2_Sat_Float(src, dst, NrFrames*NrChannels);
-            }
-            else{
-                Mac3s_Sat_Float(src,
-                                (pInstance->Target),
-                                dst,
-                                NrFrames * NrChannels);
-                /* In case the LVCore function would have changed the Current value */
-                pInstance->Current = pInstance->Target;
-            }
-        }
-    }
-
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet) {
-        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0) {
-                (*ptrInstance->MixerStream[0].pCallBack) (\
-                                                ptrInstance->MixerStream[0].pCallbackHandle,
-                                                ptrInstance->MixerStream[0].pGeneralPurpose,
-                                                ptrInstance->MixerStream[0].CallbackParam);
-            }
-        }
-    }
-
-}
-#endif
-
-
-#else
-void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
-                                    LVM_INT16             *src,
-                                    LVM_INT16             *dst,
-                                    LVM_INT16             n)
-{
-    char        HardMixing = TRUE;
-    LVM_INT32   TargetGain;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Delta == 0x7FFFFFFF){
-            pInstance->Current = pInstance->Target;
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            if(pInstance->Shift!=0){
-                Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
-                LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
-            }
-            else
-                LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
-            if ((pInstance->Target>>16) == 0x7FFF){
-                if(pInstance->Shift!=0)
-                    Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
-                Add2_Sat_16x16( src, dst, n );
-            }
-            else{
-                if(pInstance->Shift!=0)
-                    Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
-                Mac3s_Sat_16x16(src,(LVM_INT16)(pInstance->Target>>16),dst,n);
-                pInstance->Current = pInstance->Target; /* In case the LVCore function would have changed the Current value */
-            }
-        }
-    }
-
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet){
-        if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0){
-                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.cpp
new file mode 100644
index 0000000..2bec3be
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION MIXINSOFT_D16C31_SAT
+***********************************************************************************/
+void LVC_MixInSoft_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+                              const LVM_FLOAT       *src,
+                                    LVM_FLOAT       *dst,
+                                    LVM_INT16       n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 1.0f){
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixInSoft_D16C31_SAT(&(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target) == 1.0f){
+                Add2_Sat_Float(src, dst, n);
+            }
+            else{
+                Mac3s_Sat_Float(src, (pInstance->Target), dst, n);
+                /* In case the LVCore function would have changed the Current value */
+                pInstance->Current = pInstance->Target;
+            }
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+
+}
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       LVC_MixInSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ *  Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ *  ptrInstance    Instance pointer
+ *  src            Source
+ *  dst            Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void LVC_MixInSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+                                 const LVM_FLOAT       *src,
+                                       LVM_FLOAT       *dst,
+                                       LVM_INT16       NrFrames,
+                                       LVM_INT16       NrChannels)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if (NrFrames <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if (pInstance->Delta == 1.0f) {
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixInSoft_Mc_D16C31_SAT(&(ptrInstance->MixerStream[0]),
+                                             src,
+                                             dst,
+                                             NrFrames,
+                                             NrChannels);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing) {
+        if (pInstance->Target != 0) { /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target) == 1.0f) {
+                Add2_Sat_Float(src, dst, NrFrames*NrChannels);
+            }
+            else{
+                Mac3s_Sat_Float(src,
+                                (pInstance->Target),
+                                dst,
+                                NrFrames * NrChannels);
+                /* In case the LVCore function would have changed the Current value */
+                pInstance->Current = pInstance->Target;
+            }
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet) {
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0) {
+                (*ptrInstance->MixerStream[0].pCallBack) (\
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam);
+            }
+        }
+    }
+
+}
+#endif
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
deleted file mode 100644
index a4682d3..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include <system/audio.h>
-
-#include "LVC_Mixer_Private.h"
-#include "VectorArithmetic.h"
-#include "ScalarArithmetic.h"
-
-/**********************************************************************************
-   DEFINITIONS
-***********************************************************************************/
-
-#define TRUE          1
-#define FALSE         0
-
-#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
-
-/**********************************************************************************
-   FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-#ifdef SUPPORT_MC
-/* This threshold is used to decide on the processing to be applied on
- * front center and back center channels
- */
-#define LVM_VOL_BAL_THR (0.000016f)
-void LVC_MixSoft_1St_MC_float_SAT (LVMixer3_2St_FLOAT_st *ptrInstance,
-                                    const LVM_FLOAT       *src,
-                                    LVM_FLOAT             *dst,
-                                    LVM_INT16             NrFrames,
-                                    LVM_INT32             NrChannels,
-                                    LVM_INT32             ChMask)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  Target_lfe = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
-    Mix_Private_FLOAT_st  Target_ctr = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
-    Mix_Private_FLOAT_st  *pInstance1 = \
-                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = \
-                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
-    Mix_Private_FLOAT_st  *pMixPrivInst[4] = {pInstance1, pInstance2, &Target_ctr, &Target_lfe};
-    Mix_Private_FLOAT_st  *pInstance[NrChannels];
-
-    if (audio_channel_mask_get_representation(ChMask)
-            == AUDIO_CHANNEL_REPRESENTATION_INDEX)
-    {
-        for (int i = 0; i < 2; i++)
-        {
-            pInstance[i] = pMixPrivInst[i];
-        }
-        for (int i = 2; i < NrChannels; i++)
-        {
-            pInstance[i] = pMixPrivInst[2];
-        }
-    }
-    else
-    {
-        // TODO: Combine with system/media/audio_utils/Balance.cpp
-        // Constants in system/media/audio/include/system/audio-base.h
-        // 'mixInstIdx' is used to map the appropriate mixer instance for each channel.
-        const int mixInstIdx[] = {
-            0, // AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
-            1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
-            2, // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
-            3, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
-            0, // AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
-            1, // AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
-            0, // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
-            1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
-            2, // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
-            0, // AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
-            1, // AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
-            2, // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
-            0, // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
-            2, // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
-            1, // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
-            0, // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
-            2, // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
-            1, // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
-            0, // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
-            1, // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u
-        };
-        if (pInstance1->Target <= LVM_VOL_BAL_THR ||
-            pInstance2->Target <= LVM_VOL_BAL_THR)
-        {
-            Target_ctr.Target  = 0.0f;
-            Target_ctr.Current = 0.0f;
-            Target_ctr.Delta   = 0.0f;
-        }
-        const unsigned int idxArrSize = ARRAY_SIZE(mixInstIdx);
-        for (unsigned int i = 0, channel = ChMask; channel !=0 ; ++i)
-        {
-            const unsigned int idx = __builtin_ctz(channel);
-            if (idx < idxArrSize)
-            {
-                pInstance[i] = pMixPrivInst[mixInstIdx[idx]];
-            }
-            else
-            {
-                pInstance[i] = pMixPrivInst[2];
-            }
-            channel &= ~(1 << idx);
-        }
-    }
-
-    if (NrFrames <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-
-    if ((pInstance1->Current != pInstance1->Target) ||
-        (pInstance2->Current != pInstance2->Target))
-    {
-        // TODO: combine similar checks below.
-        if (pInstance1->Delta == LVM_MAXFLOAT
-                || Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
-        {
-            /* Difference is not significant anymore. Make them equal. */
-            pInstance1->Current = pInstance1->Target;
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }
-        else
-        {
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-        }
-
-        if (HardMixing == TRUE)
-        {
-            if (pInstance2->Delta == LVM_MAXFLOAT
-                    || Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
-            {
-                /* Difference is not significant anymore. Make them equal. */
-                pInstance2->Current = pInstance2->Target;
-                TargetGain = pInstance2->Target;
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
-            }
-            else
-            {
-                /* Soft mixing has to be applied */
-                HardMixing = FALSE;
-            }
-        }
-
-        if (HardMixing == FALSE)
-        {
-             LVC_Core_MixSoft_1St_MC_float_WRA (&pInstance[0],
-                                                 src, dst, NrFrames, NrChannels);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing == TRUE)
-    {
-        if ((pInstance1->Target == LVM_MAXFLOAT) && (pInstance2->Target == LVM_MAXFLOAT))
-        {
-            if (src != dst)
-            {
-                Copy_Float(src, dst, NrFrames*NrChannels);
-            }
-        }
-        else
-        {
-            LVC_Core_MixHard_1St_MC_float_SAT(&(pInstance[0]),
-                                               src, dst, NrFrames, NrChannels);
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet)
-    {
-        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
-        {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
-                                                         Make them equal. */
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[0].pCallBack) (\
-                    ptrInstance->MixerStream[0].pCallbackHandle,
-                    ptrInstance->MixerStream[0].pGeneralPurpose,
-                    ptrInstance->MixerStream[0].CallbackParam);
-            }
-        }
-    }
-    if (ptrInstance->MixerStream[1].CallbackSet)
-    {
-        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
-        {
-            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
-                                                         Make them equal. */
-            TargetGain = pInstance2->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
-            ptrInstance->MixerStream[1].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[1].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[1].pCallBack) (\
-                    ptrInstance->MixerStream[1].pCallbackHandle,
-                    ptrInstance->MixerStream[1].pGeneralPurpose,
-                    ptrInstance->MixerStream[1].CallbackParam);
-            }
-        }
-    }
-}
-#endif
-void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
-                                    const LVM_FLOAT             *src,
-                                    LVM_FLOAT             *dst,
-                                    LVM_INT16             n)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  *pInstance1 = \
-                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = \
-                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
-    {
-        if(pInstance1->Delta == 1.0f)
-        {
-            pInstance1->Current = pInstance1->Target;
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }
-        else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
-        {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
-                                                         Make them equal. */
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }
-        else
-        {
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-        }
-
-        if(HardMixing == TRUE)
-        {
-            if(pInstance2->Delta == 1.0f)
-            {
-                pInstance2->Current = pInstance2->Target;
-                TargetGain = pInstance2->Target;
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
-            }
-            else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
-            {
-                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore. \
-                                                             Make them equal. */
-                TargetGain = pInstance2->Target;
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
-            }
-            else
-            {
-                /* Soft mixing has to be applied */
-                HardMixing = FALSE;
-            }
-        }
-
-        if(HardMixing == FALSE)
-        {
-             LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),
-                                                 &(ptrInstance->MixerStream[1]),
-                                                 src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing)
-    {
-        if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f))
-        {
-            if(src != dst)
-            {
-                Copy_Float(src, dst, n);
-            }
-        }
-        else
-        {
-            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
-                                               &(ptrInstance->MixerStream[1]),
-                                               src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet)
-    {
-        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
-        {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
-                                                         Make them equal. */
-            TargetGain = pInstance1->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[0].pCallBack) ( \
-                                                ptrInstance->MixerStream[0].pCallbackHandle,
-                                                ptrInstance->MixerStream[0].pGeneralPurpose,
-                                                ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-    if (ptrInstance->MixerStream[1].CallbackSet)
-    {
-        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
-        {
-            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
-                                                         Make them equal. */
-            TargetGain = pInstance2->Target;
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
-            ptrInstance->MixerStream[1].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[1].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[1].pCallBack) (
-                                                ptrInstance->MixerStream[1].pCallbackHandle,
-                                                ptrInstance->MixerStream[1].pGeneralPurpose,
-                                                ptrInstance->MixerStream[1].CallbackParam );
-            }
-        }
-    }
-}
-#else
-void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
-                                  const LVM_INT16             *src,
-                                        LVM_INT16             *dst,
-                                        LVM_INT16             n)
-{
-    char        HardMixing = TRUE;
-    LVM_INT32   TargetGain;
-    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current != pInstance1->Target)||(pInstance2->Current != pInstance2->Target))
-    {
-        if(pInstance1->Delta == 0x7FFFFFFF)
-        {
-            pInstance1->Current = pInstance1->Target;
-            TargetGain=pInstance1->Target>>16;  // TargetGain in Q16.15 format, no integer part
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }
-        else if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
-        {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance1->Target>>16;  // TargetGain in Q16.15 format, no integer part
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }
-        else
-        {
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-        }
-
-        if(HardMixing == TRUE)
-        {
-            if(pInstance2->Delta == 0x7FFFFFFF)
-            {
-                pInstance2->Current = pInstance2->Target;
-                TargetGain=pInstance2->Target>>16;  // TargetGain in Q16.15 format, no integer part
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
-            }
-            else if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
-            {
-                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.  Make them equal. */
-                TargetGain=pInstance2->Target>>16;  // TargetGain in Q16.15 format, no integer part
-                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
-            }
-            else
-            {
-                /* Soft mixing has to be applied */
-                HardMixing = FALSE;
-            }
-        }
-
-        if(HardMixing == FALSE)
-        {
-             LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing)
-    {
-        if (((pInstance1->Target>>16) == 0x7FFF)&&((pInstance2->Target>>16) == 0x7FFF))
-        {
-            if(src!=dst)
-            {
-                Copy_16(src, dst, n);
-            }
-        }
-        else
-        {
-            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet)
-    {
-        if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
-        {
-            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance1->Target>>(16-pInstance1->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0],TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-    if (ptrInstance->MixerStream[1].CallbackSet)
-    {
-        if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
-        {
-            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance2->Target>>(16-pInstance2->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1],TargetGain);
-            ptrInstance->MixerStream[1].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[1].pCallBack != 0)
-            {
-                (*ptrInstance->MixerStream[1].pCallBack) ( ptrInstance->MixerStream[1].pCallbackHandle, ptrInstance->MixerStream[1].pGeneralPurpose,ptrInstance->MixerStream[1].CallbackParam );
-            }
-        }
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
new file mode 100644
index 0000000..3153ada
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include <system/audio.h>
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(*(a))))
+
+/**********************************************************************************
+   FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+***********************************************************************************/
+#ifdef SUPPORT_MC
+/* This threshold is used to decide on the processing to be applied on
+ * front center and back center channels
+ */
+#define LVM_VOL_BAL_THR (0.000016f)
+void LVC_MixSoft_1St_MC_float_SAT (LVMixer3_2St_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT       *src,
+                                    LVM_FLOAT             *dst,
+                                    LVM_INT16             NrFrames,
+                                    LVM_INT32             NrChannels,
+                                    LVM_INT32             ChMask)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  Target_lfe = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
+    Mix_Private_FLOAT_st  Target_ctr = {LVM_MAXFLOAT, LVM_MAXFLOAT, LVM_MAXFLOAT};
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+    Mix_Private_FLOAT_st  *pMixPrivInst[4] = {pInstance1, pInstance2, &Target_ctr, &Target_lfe};
+    Mix_Private_FLOAT_st  *pInstance[NrChannels];
+
+    if (audio_channel_mask_get_representation(ChMask)
+            == AUDIO_CHANNEL_REPRESENTATION_INDEX)
+    {
+        for (int i = 0; i < 2; i++)
+        {
+            pInstance[i] = pMixPrivInst[i];
+        }
+        for (int i = 2; i < NrChannels; i++)
+        {
+            pInstance[i] = pMixPrivInst[2];
+        }
+    }
+    else
+    {
+        // TODO: Combine with system/media/audio_utils/Balance.cpp
+        // Constants in system/media/audio/include/system/audio-base.h
+        // 'mixInstIdx' is used to map the appropriate mixer instance for each channel.
+        const int mixInstIdx[] = {
+            0, // AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
+            1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
+            2, // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
+            3, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
+            0, // AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
+            1, // AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
+            0, // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
+            1, // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
+            2, // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
+            0, // AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
+            1, // AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
+            2, // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
+            0, // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
+            2, // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
+            1, // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
+            0, // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
+            2, // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
+            1, // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
+            0, // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
+            1, // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u
+        };
+        if (pInstance1->Target <= LVM_VOL_BAL_THR ||
+            pInstance2->Target <= LVM_VOL_BAL_THR)
+        {
+            Target_ctr.Target  = 0.0f;
+            Target_ctr.Current = 0.0f;
+            Target_ctr.Delta   = 0.0f;
+        }
+        const unsigned int idxArrSize = ARRAY_SIZE(mixInstIdx);
+        for (unsigned int i = 0, channel = ChMask; channel !=0 ; ++i)
+        {
+            const unsigned int idx = __builtin_ctz(channel);
+            if (idx < idxArrSize)
+            {
+                pInstance[i] = pMixPrivInst[mixInstIdx[idx]];
+            }
+            else
+            {
+                pInstance[i] = pMixPrivInst[2];
+            }
+            channel &= ~(1 << idx);
+        }
+    }
+
+    if (NrFrames <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+
+    if ((pInstance1->Current != pInstance1->Target) ||
+        (pInstance2->Current != pInstance2->Target))
+    {
+        // TODO: combine similar checks below.
+        if (pInstance1->Delta == LVM_MAXFLOAT
+                || Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            /* Difference is not significant anymore. Make them equal. */
+            pInstance1->Current = pInstance1->Target;
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }
+        else
+        {
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+        }
+
+        if (HardMixing == TRUE)
+        {
+            if (pInstance2->Delta == LVM_MAXFLOAT
+                    || Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+            {
+                /* Difference is not significant anymore. Make them equal. */
+                pInstance2->Current = pInstance2->Target;
+                TargetGain = pInstance2->Target;
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+            }
+            else
+            {
+                /* Soft mixing has to be applied */
+                HardMixing = FALSE;
+            }
+        }
+
+        if (HardMixing == FALSE)
+        {
+             LVC_Core_MixSoft_1St_MC_float_WRA (&pInstance[0],
+                                                 src, dst, NrFrames, NrChannels);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing == TRUE)
+    {
+        if ((pInstance1->Target == LVM_MAXFLOAT) && (pInstance2->Target == LVM_MAXFLOAT))
+        {
+            if (src != dst)
+            {
+                Copy_Float(src, dst, NrFrames*NrChannels);
+            }
+        }
+        else
+        {
+            LVC_Core_MixHard_1St_MC_float_SAT(&(pInstance[0]),
+                                               src, dst, NrFrames, NrChannels);
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet)
+    {
+        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+                                                         Make them equal. */
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[0].pCallBack) (\
+                    ptrInstance->MixerStream[0].pCallbackHandle,
+                    ptrInstance->MixerStream[0].pGeneralPurpose,
+                    ptrInstance->MixerStream[0].CallbackParam);
+            }
+        }
+    }
+    if (ptrInstance->MixerStream[1].CallbackSet)
+    {
+        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+        {
+            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
+                                                         Make them equal. */
+            TargetGain = pInstance2->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
+            ptrInstance->MixerStream[1].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[1].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[1].pCallBack) (\
+                    ptrInstance->MixerStream[1].pCallbackHandle,
+                    ptrInstance->MixerStream[1].pGeneralPurpose,
+                    ptrInstance->MixerStream[1].CallbackParam);
+            }
+        }
+    }
+}
+#endif
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
+                                    const LVM_FLOAT             *src,
+                                    LVM_FLOAT             *dst,
+                                    LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                              (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
+    {
+        if(pInstance1->Delta == 1.0f)
+        {
+            pInstance1->Current = pInstance1->Target;
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }
+        else if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+                                                         Make them equal. */
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }
+        else
+        {
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+        }
+
+        if(HardMixing == TRUE)
+        {
+            if(pInstance2->Delta == 1.0f)
+            {
+                pInstance2->Current = pInstance2->Target;
+                TargetGain = pInstance2->Target;
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+            }
+            else if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+            {
+                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore. \
+                                                             Make them equal. */
+                TargetGain = pInstance2->Target;
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]), TargetGain);
+            }
+            else
+            {
+                /* Soft mixing has to be applied */
+                HardMixing = FALSE;
+            }
+        }
+
+        if(HardMixing == FALSE)
+        {
+             LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),
+                                                 &(ptrInstance->MixerStream[1]),
+                                                 src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing)
+    {
+        if ((pInstance1->Target == 1.0f) && (pInstance2->Target == 1.0f))
+        {
+            if(src != dst)
+            {
+                Copy_Float(src, dst, n);
+            }
+        }
+        else
+        {
+            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),
+                                               &(ptrInstance->MixerStream[1]),
+                                               src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet)
+    {
+        if (Abs_Float(pInstance1->Current - pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. \
+                                                         Make them equal. */
+            TargetGain = pInstance1->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0], TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+    if (ptrInstance->MixerStream[1].CallbackSet)
+    {
+        if (Abs_Float(pInstance2->Current - pInstance2->Target) < pInstance2->Delta)
+        {
+            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.
+                                                         Make them equal. */
+            TargetGain = pInstance2->Target;
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1], TargetGain);
+            ptrInstance->MixerStream[1].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[1].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[1].pCallBack) (
+                                                ptrInstance->MixerStream[1].pCallbackHandle,
+                                                ptrInstance->MixerStream[1].pGeneralPurpose,
+                                                ptrInstance->MixerStream[1].CallbackParam );
+            }
+        }
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
deleted file mode 100644
index 0678ae0..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "VectorArithmetic.h"
-#include "ScalarArithmetic.h"
-
-/**********************************************************************************
-   DEFINITIONS
-***********************************************************************************/
-
-#define TRUE          1
-#define FALSE         0
-
-/**********************************************************************************
-   FUNCTION LVMixer3_MIXSOFT_1ST_D16C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_FLOAT_st *ptrInstance,
-                                  const LVM_FLOAT             *src,
-                                        LVM_FLOAT             *dst,
-                                        LVM_INT16             n)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  *pInstance = \
-                          (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Delta == 1.0f){
-            pInstance->Current = pInstance->Target;
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            LVC_Core_MixSoft_1St_D16C31_WRA(&(ptrInstance->MixerStream[0]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target == 0)
-            LoadConst_Float(0.0, dst, n);
-        else {
-            if ((pInstance->Target) != 1.0f)
-                Mult3s_Float(src, (pInstance->Target), dst, n);
-            else if(src != dst)
-                Copy_Float(src, dst, n);
-        }
-
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet){
-        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0){
-                (*ptrInstance->MixerStream[0].pCallBack) ( \
-                                                ptrInstance->MixerStream[0].pCallbackHandle,
-                                                ptrInstance->MixerStream[0].pGeneralPurpose,
-                                                ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-}
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       LVC_MixSoft_Mc_D16C31_SAT
- *
- * DESCRIPTION:
- *  Mixer function with support for processing multichannel input
- *
- * PARAMETERS:
- *  ptrInstance    Instance pointer
- *  src            Source
- *  dst            Destination
- *  NrFrames       Number of Frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void LVC_MixSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
-                                  const LVM_FLOAT      *src,
-                                        LVM_FLOAT      *dst,
-                                        LVM_INT16      NrFrames,
-                                        LVM_INT16      NrChannels)
-{
-    char        HardMixing = TRUE;
-    LVM_FLOAT   TargetGain;
-    Mix_Private_FLOAT_st  *pInstance = \
-                          (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if (NrFrames <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if (pInstance->Delta == 1.0f) {
-            pInstance->Current = pInstance->Target;
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            LVC_Core_MixSoft_Mc_D16C31_WRA(&(ptrInstance->MixerStream[0]),
-                                           src,
-                                           dst,
-                                           NrFrames,
-                                           NrChannels);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing) {
-        if (pInstance->Target == 0)
-            LoadConst_Float(0.0, dst, NrFrames * NrChannels);
-        else {
-            if ((pInstance->Target) != 1.0f)
-                Mult3s_Float(src, (pInstance->Target), dst, NrFrames * NrChannels);
-            else if (src != dst)
-                Copy_Float(src, dst, NrFrames * NrChannels);
-        }
-
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet) {
-        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            TargetGain = pInstance->Target;
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0) {
-                (*ptrInstance->MixerStream[0].pCallBack) (\
-                                                ptrInstance->MixerStream[0].pCallbackHandle,
-                                                ptrInstance->MixerStream[0].pGeneralPurpose,
-                                                ptrInstance->MixerStream[0].CallbackParam);
-            }
-        }
-    }
-}
-
-#endif
-
-#else
-void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
-                                  const LVM_INT16             *src,
-                                        LVM_INT16             *dst,
-                                        LVM_INT16             n)
-{
-    char        HardMixing = TRUE;
-    LVM_INT32   TargetGain;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Delta == 0x7FFFFFFF){
-            pInstance->Current = pInstance->Target;
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            if(pInstance->Shift!=0){
-                Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
-                LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), dst, dst, n);
-            }
-            else
-                LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target == 0)
-            LoadConst_16(0, dst, n);
-        else if(pInstance->Shift!=0){
-            Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
-            if ((pInstance->Target>>16) != 0x7FFF)
-                Mult3s_16x16( dst, (LVM_INT16)(pInstance->Target>>16), dst, n );
-        }
-        else {
-            if ((pInstance->Target>>16) != 0x7FFF)
-                Mult3s_16x16( src, (LVM_INT16)(pInstance->Target>>16), dst, n );
-            else if(src!=dst)
-                Copy_16(src, dst, n);
-        }
-
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (ptrInstance->MixerStream[0].CallbackSet){
-        if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-            LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
-            ptrInstance->MixerStream[0].CallbackSet = FALSE;
-            if (ptrInstance->MixerStream[0].pCallBack != 0){
-                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
-            }
-        }
-    }
-}
-#endif/*BUILD_FLOAT*/
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp
new file mode 100644
index 0000000..4d229da
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION LVMixer3_MIXSOFT_1ST_D16C31_SAT
+***********************************************************************************/
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_FLOAT_st *ptrInstance,
+                                  const LVM_FLOAT             *src,
+                                        LVM_FLOAT             *dst,
+                                        LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                          (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 1.0f){
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixSoft_1St_D16C31_WRA(&(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_Float(0.0, dst, n);
+        else {
+            if ((pInstance->Target) != 1.0f)
+                Mult3s_Float(src, (pInstance->Target), dst, n);
+            else if(src != dst)
+                Copy_Float(src, dst, n);
+        }
+
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( \
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       LVC_MixSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ *  Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ *  ptrInstance    Instance pointer
+ *  src            Source
+ *  dst            Destination
+ *  NrFrames       Number of Frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void LVC_MixSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+                                  const LVM_FLOAT      *src,
+                                        LVM_FLOAT      *dst,
+                                        LVM_INT16      NrFrames,
+                                        LVM_INT16      NrChannels)
+{
+    char        HardMixing = TRUE;
+    LVM_FLOAT   TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = \
+                          (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if (NrFrames <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if (pInstance->Delta == 1.0f) {
+            pInstance->Current = pInstance->Target;
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            LVC_Core_MixSoft_Mc_D16C31_WRA(&(ptrInstance->MixerStream[0]),
+                                           src,
+                                           dst,
+                                           NrFrames,
+                                           NrChannels);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing) {
+        if (pInstance->Target == 0)
+            LoadConst_Float(0.0, dst, NrFrames * NrChannels);
+        else {
+            if ((pInstance->Target) != 1.0f)
+                Mult3s_Float(src, (pInstance->Target), dst, NrFrames * NrChannels);
+            else if (src != dst)
+                Copy_Float(src, dst, NrFrames * NrChannels);
+        }
+
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet) {
+        if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            TargetGain = pInstance->Target;
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0) {
+                (*ptrInstance->MixerStream[0].pCallBack) (\
+                                                ptrInstance->MixerStream[0].pCallbackHandle,
+                                                ptrInstance->MixerStream[0].pGeneralPurpose,
+                                                ptrInstance->MixerStream[0].CallbackParam);
+            }
+        }
+    }
+}
+
+#endif
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
deleted file mode 100644
index 8a89de1..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "LVC_Mixer_Private.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_MixSoft_2St_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
-                                const LVM_FLOAT       *src1,
-                                const LVM_FLOAT       *src2,
-                                      LVM_FLOAT       *dst,
-                                      LVM_INT16       n)
-{
-    Mix_Private_FLOAT_st  *pInstance1 = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)){
-        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
-                                    src2, dst, n);
-    }
-    else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)){
-        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
-                                    src1, dst, n);
-    }
-    else if ((pInstance1->Current != pInstance1->Target) || \
-                                    (pInstance2->Current != pInstance2->Target))
-    {
-        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
-                                   src1, dst, n);
-        LVC_MixInSoft_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
-                                  src2, dst, n);
-    }
-    else{
-        /******************************************************************************
-           HARD MIXING
-        *******************************************************************************/
-        LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0],
-                                         &ptrInstance->MixerStream[1],
-                                         src1, src2, dst, n);
-    }
-}
-
-#ifdef SUPPORT_MC
-/*
- * FUNCTION:       LVC_MixSoft_2Mc_D16C31_SAT
- *
- * DESCRIPTION:
- *  2 stream Mixer function with support for processing multichannel input
- *
- * PARAMETERS:
- *  ptrInstance    Instance pointer
- *  src1           First multichannel source
- *  src2           Second multichannel source
- *  dst            Destination
- *  NrFrames       Number of frames
- *  NrChannels     Number of channels
- *
- * RETURNS:
- *  void
- *
- */
-void LVC_MixSoft_2Mc_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
-                                const LVM_FLOAT       *src1,
-                                const LVM_FLOAT       *src2,
-                                      LVM_FLOAT       *dst,
-                                      LVM_INT16       NrFrames,
-                                      LVM_INT16       NrChannels)
-{
-    Mix_Private_FLOAT_st  *pInstance1 = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_FLOAT_st  *pInstance2 = \
-                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if (NrFrames <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)) {
-        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
-                                    src2, dst, NrFrames, NrChannels);
-    }
-    else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)) {
-        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
-                                    src1, dst, NrFrames, NrChannels);
-    }
-    else if ((pInstance1->Current != pInstance1->Target) || \
-                                    (pInstance2->Current != pInstance2->Target))
-    {
-        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
-                                   src1, dst, NrFrames, NrChannels);
-        LVC_MixInSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
-                                   src2, dst, NrFrames, NrChannels);
-    }
-    else{
-        /******************************************************************************
-           HARD MIXING
-        *******************************************************************************/
-        LVC_Core_MixHard_2St_D16C31_SAT(&ptrInstance->MixerStream[0],
-                                        &ptrInstance->MixerStream[1],
-                                        src1, src2, dst, NrFrames * NrChannels);
-    }
-}
-#endif
-
-#else
-void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
-                                    const   LVM_INT16       *src1,
-                                            LVM_INT16       *src2,
-                                            LVM_INT16       *dst,
-                                            LVM_INT16       n)
-{
-    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
-    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance1->Current == pInstance1->Target)&&(pInstance1->Current == 0)){
-        LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
-    }
-    else if ((pInstance2->Current == pInstance2->Target)&&(pInstance2->Current == 0)){
-        LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
-    }
-    else if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
-    {
-        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
-        LVC_MixInSoft_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
-    }
-    else{
-        /******************************************************************************
-           HARD MIXING
-        *******************************************************************************/
-        if(pInstance2->Shift!=0)
-            Shift_Sat_v16xv16 ((LVM_INT16)pInstance2->Shift,src2,src2,n);
-        if(pInstance1->Shift!=0)
-        {
-            Shift_Sat_v16xv16 ((LVM_INT16)pInstance1->Shift,src1,dst,n);
-            LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], dst, src2, dst, n);
-        }
-        else
-            LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], src1, src2, dst, n);
-    }
-}
-#endif /*BUILD_FLOAT*/
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.cpp
new file mode 100644
index 0000000..54ab79d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
+***********************************************************************************/
+void LVC_MixSoft_2St_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
+                                const LVM_FLOAT       *src1,
+                                const LVM_FLOAT       *src2,
+                                      LVM_FLOAT       *dst,
+                                      LVM_INT16       n)
+{
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                    src2, dst, n);
+    }
+    else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                    src1, dst, n);
+    }
+    else if ((pInstance1->Current != pInstance1->Target) || \
+                                    (pInstance2->Current != pInstance2->Target))
+    {
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                   src1, dst, n);
+        LVC_MixInSoft_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                  src2, dst, n);
+    }
+    else{
+        /******************************************************************************
+           HARD MIXING
+        *******************************************************************************/
+        LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0],
+                                         &ptrInstance->MixerStream[1],
+                                         src1, src2, dst, n);
+    }
+}
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION:       LVC_MixSoft_2Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ *  2 stream Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ *  ptrInstance    Instance pointer
+ *  src1           First multichannel source
+ *  src2           Second multichannel source
+ *  dst            Destination
+ *  NrFrames       Number of frames
+ *  NrChannels     Number of channels
+ *
+ * RETURNS:
+ *  void
+ *
+ */
+void LVC_MixSoft_2Mc_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
+                                const LVM_FLOAT       *src1,
+                                const LVM_FLOAT       *src2,
+                                      LVM_FLOAT       *dst,
+                                      LVM_INT16       NrFrames,
+                                      LVM_INT16       NrChannels)
+{
+    Mix_Private_FLOAT_st  *pInstance1 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_FLOAT_st  *pInstance2 = \
+                             (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+    if (NrFrames <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)) {
+        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                    src2, dst, NrFrames, NrChannels);
+    }
+    else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)) {
+        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                    src1, dst, NrFrames, NrChannels);
+    }
+    else if ((pInstance1->Current != pInstance1->Target) || \
+                                    (pInstance2->Current != pInstance2->Target))
+    {
+        LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+                                   src1, dst, NrFrames, NrChannels);
+        LVC_MixInSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+                                   src2, dst, NrFrames, NrChannels);
+    }
+    else{
+        /******************************************************************************
+           HARD MIXING
+        *******************************************************************************/
+        LVC_Core_MixHard_2St_D16C31_SAT(&ptrInstance->MixerStream[0],
+                                        &ptrInstance->MixerStream[1],
+                                        src1, src2, dst, NrFrames * NrChannels);
+    }
+}
+#endif
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index 199d529..ce42d2e 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -18,12 +18,6 @@
 #ifndef __LVC_MIXER_H__
 #define __LVC_MIXER_H__
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 #include "LVM_Types.h"
 
 /**********************************************************************************
@@ -31,7 +25,6 @@
 ***********************************************************************************/
 
 /* LVMixer3_st structure stores Instance parameters for one audio stream */
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT       PrivateParams[3];   /* Private Instance params for \
@@ -43,45 +36,14 @@
     void            *pGeneralPurpose;   /* Pointer for general purpose usage */
     LVM_Callback    pCallBack;          /* Pointer to the callback function */
 } LVMixer3_FLOAT_st;
-#else
-typedef struct
-{
-    LVM_INT32       PrivateParams[4];   /* Private Instance params for Audio Stream */
-    LVM_INT16       CallbackSet;        /* Boolean.  Should be set by calling application each time the target value is updated */
-    LVM_INT16       CallbackParam;      /* Parameter that will be used in the calback function */
-    void            *pCallbackHandle;   /* Pointer to the instance of the callback function */
-    void            *pGeneralPurpose;   /* Pointer for general purpose usage */
-    LVM_Callback    pCallBack;          /* Pointer to the callback function */
-} LVMixer3_st;
-#endif
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVMixer3_FLOAT_st     MixerStream[1];    /* Instance Params for one Audio Stream */
 } LVMixer3_1St_FLOAT_st;
-#else
-typedef struct
-{
-    LVMixer3_st     MixerStream[1];    /* Instance Params for one Audio Stream */
-} LVMixer3_1St_st;
-#endif
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVMixer3_FLOAT_st     MixerStream[2];    /* Instance Params for two Audio Streams */
 } LVMixer3_2St_FLOAT_st;
-#else
-typedef struct
-{
-    LVMixer3_st     MixerStream[2];    /* Instance Params for two Audio Streams */
-} LVMixer3_2St_st;
-#endif
-#ifndef BUILD_FLOAT
-typedef struct
-{
-    LVMixer3_st     MixerStream[3];    /* Instance Params for three Audio Streams */
-} LVMixer3_3St_st;
-#endif
 /**********************************************************************************
    FUNCTION PROTOTYPES (HIGH LEVEL FUNCTIONS)
 ***********************************************************************************/
@@ -92,7 +54,6 @@
 #define    LVMixer3_MixSoft_2St_D16C31_SAT   LVMixer3_2St_D16C31_SAT_MixSoft
 #define    LVMixer3_MixSoft_3St_D16C31_SAT   LVMixer3_3St_D16C31_SAT_MixSoft
 
-
 /*** General functions ************************************************************/
 
 /**********************************************************************************/
@@ -101,62 +62,28 @@
 /* then the calculation will give an incorrect value for alpha, see the mixer     */
 /* documentation for further details.                                             */
 /* ********************************************************************************/
-#ifdef BUILD_FLOAT
 void LVC_Mixer_SetTarget( LVMixer3_FLOAT_st *pStream,
                           LVM_FLOAT        TargetGain);
-#else
-void LVC_Mixer_SetTarget( LVMixer3_st *pStream,
-                                LVM_INT32           TargetGain);
-#endif
-#ifdef BUILD_FLOAT
 LVM_FLOAT LVC_Mixer_GetTarget( LVMixer3_FLOAT_st *pStream);
-#else
-LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream);
-#endif
 
-#ifdef BUILD_FLOAT
 LVM_FLOAT LVC_Mixer_GetCurrent( LVMixer3_FLOAT_st *pStream);
-#else
-LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream);
-#endif
 
-#ifdef BUILD_FLOAT
 void LVC_Mixer_Init( LVMixer3_FLOAT_st *pStream,
                      LVM_FLOAT           TargetGain,
                      LVM_FLOAT           CurrentGain);
-#else
-void LVC_Mixer_Init( LVMixer3_st *pStream,
-                                LVM_INT32           TargetGain,
-                                LVM_INT32           CurrentGain);
-#endif
 
-#ifdef BUILD_FLOAT
 void LVC_Mixer_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
                                 LVM_INT32           Tc_millisec,
                                 LVM_Fs_en           Fs,
                                 LVM_INT16           NumChannels);
-#else
-void LVC_Mixer_SetTimeConstant( LVMixer3_st *pStream,
-                                LVM_INT32           Tc_millisec,
-                                LVM_Fs_en           Fs,
-                                LVM_INT16           NumChannels);
-#endif
 
-#ifdef BUILD_FLOAT
 void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
                                          LVM_INT32           Tc_millisec,
                                          LVM_Fs_en           Fs,
                                          LVM_INT16           NumChannels);
-#else
-void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
-                                        LVM_INT32           Tc_millisec,
-                                        LVM_Fs_en           Fs,
-                                        LVM_INT16           NumChannels);
-#endif
 
 /*** 16 bit functions *************************************************************/
 
-#ifdef BUILD_FLOAT
 void LVC_MixSoft_1St_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
                                 const LVM_FLOAT       *src,
                                       LVM_FLOAT       *dst,
@@ -169,14 +96,6 @@
                                      LVM_INT16       NrChannels);
 #endif
 
-#else
-void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *pInstance,
-                                  const LVM_INT16           *src,
-                                        LVM_INT16           *dst,
-                                        LVM_INT16           n);
-#endif
-
-#ifdef BUILD_FLOAT
 void LVC_MixInSoft_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
                               const LVM_FLOAT       *src,
                                     LVM_FLOAT       *dst,
@@ -189,14 +108,6 @@
                                        LVM_INT16       NrChannels);
 #endif
 
-#else
-void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *pInstance,
-                                        LVM_INT16           *src,
-                                        LVM_INT16           *dst,
-                                        LVM_INT16           n);
-#endif
-
-#ifdef BUILD_FLOAT
 void LVC_MixSoft_2St_D16C31_SAT(LVMixer3_2St_FLOAT_st *pInstance,
                                 const LVM_FLOAT       *src1,
                                 const LVM_FLOAT       *src2,
@@ -210,20 +121,12 @@
                                 LVM_INT16             NrFrames,
                                 LVM_INT16             NrChannels);
 #endif
-#else
-void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *pInstance,
-                                const LVM_INT16             *src1,
-                                      LVM_INT16             *src2,
-                                      LVM_INT16             *dst,  /* dst cannot be equal to src2 */
-                                      LVM_INT16             n);
-#endif
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
 /* MixerStream[0] applies to Left channel                                         */
 /* MixerStream[1] applies to Right channel                                        */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
-#ifdef BUILD_FLOAT
 #ifdef SUPPORT_MC
 void LVC_MixSoft_1St_MC_float_SAT(LVMixer3_2St_FLOAT_st *pInstance,
                                    const   LVM_FLOAT     *src,
@@ -236,15 +139,6 @@
                                    const   LVM_FLOAT     *src,
                                    LVM_FLOAT             *dst,   /* dst can be equal to src */
                                    LVM_INT16             n);     /* Number of stereo samples */
-#else
-void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st         *pInstance,
-                                const   LVM_INT16           *src,
-                                        LVM_INT16           *dst,   /* dst can be equal to src */
-                                        LVM_INT16           n);     /* Number of stereo samples */
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 /**********************************************************************************/
 
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
deleted file mode 100644
index 5990412..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_GetCurrent                                                */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function returns the CurrentGain in Q16.15 format              */
-/*                                                                      */
-/* RETURNS:                                                             */
-/*  CurrentGain      - CurrentGain value in Q 16.15 format              */
-/*                                                                      */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVC_Mixer_GetCurrent( LVMixer3_FLOAT_st *pStream)
-{
-    LVM_FLOAT       CurrentGain;
-    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-    CurrentGain = pInstance->Current;  // CurrentGain
-    return CurrentGain;
-}
-#else
-LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream)
-{
-    LVM_INT32       CurrentGain;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-    CurrentGain=pInstance->Current>>(16-pInstance->Shift);  // CurrentGain in Q16.15 format
-    return CurrentGain;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.cpp
new file mode 100644
index 0000000..d0b50e6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_GetCurrent                                                */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function returns the CurrentGain in Q16.15 format              */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  CurrentGain      - CurrentGain value in Q 16.15 format              */
+/*                                                                      */
+/************************************************************************/
+LVM_FLOAT LVC_Mixer_GetCurrent( LVMixer3_FLOAT_st *pStream)
+{
+    LVM_FLOAT       CurrentGain;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    CurrentGain = pInstance->Current;  // CurrentGain
+    return CurrentGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
deleted file mode 100644
index 507eefa..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_GetTarget                                                 */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function returns the TargetGain in Q16.15 format               */
-/*                                                                      */
-/* RETURNS:                                                             */
-/*  TargetGain      - TargetGain value in Q 16.15 format                */
-/*                                                                      */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVC_Mixer_GetTarget( LVMixer3_FLOAT_st *pStream)
-{
-    LVM_FLOAT       TargetGain;
-    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-
-    TargetGain = pInstance->Target;  // TargetGain
-    return TargetGain;
-}
-#else
-LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream)
-{
-    LVM_INT32       TargetGain;
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-
-    TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
-
-    return TargetGain;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.cpp
new file mode 100644
index 0000000..3ae5ba4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_GetTarget                                                 */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function returns the TargetGain in Q16.15 format               */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  TargetGain      - TargetGain value in Q 16.15 format                */
+/*                                                                      */
+/************************************************************************/
+LVM_FLOAT LVC_Mixer_GetTarget( LVMixer3_FLOAT_st *pStream)
+{
+    LVM_FLOAT       TargetGain;
+    Mix_Private_FLOAT_st  *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+
+    TargetGain = pInstance->Target;  // TargetGain
+    return TargetGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
deleted file mode 100644
index 737e26b..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_Init                                                      */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This intialization function intializes the private instance         */
-/*  paramters for a given Audio Stream based on TargetGain and          */
-/*  CurrentGain                                                         */
-/*  This function caclulates the "Shift" required to provide the        */
-/*  integer part of TargetGain and fractional gain values "Target" and  */
-/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
-/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
-/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
-/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
-/*  fraction gain is provided through Current=0.475 and Target=0.625    */
-/* PARAMETERS:                                                          */
-/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
-/*                Audio Stream                                          */
-/*  TargetGain  - TargetGain value in Q 16.15 format                    */
-/*  CurrentGain - CurrentGain value in Q 16.15 format                   */
-/*                                                                      */
-/* RETURNS:                                                             */
-/*  void                                                                */
-/*                                                                      */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Mixer_Init( LVMixer3_FLOAT_st *pStream,
-                     LVM_FLOAT           TargetGain,
-                     LVM_FLOAT           CurrentGain)
-{
-    LVM_FLOAT MaxGain = TargetGain;
-    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-    if(CurrentGain > MaxGain)
-        MaxGain = CurrentGain;
-    pInstance->Target = TargetGain;   // Update fractional gain Target
-    pInstance->Current = CurrentGain; // Update fractional gain Current
-}
-#else
-void LVC_Mixer_Init( LVMixer3_st *pStream,
-                    LVM_INT32           TargetGain,
-                    LVM_INT32           CurrentGain)
-{
-    LVM_INT16       Shift=0;
-    LVM_INT32       MaxGain=TargetGain;         // MaxGain is in Q16.15 format
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-    if(CurrentGain>MaxGain)
-        MaxGain=CurrentGain;                    // MaxGain=max(CurrentGain,TargetGain)
-
-    MaxGain=MaxGain>>15;                        // MaxGain in Q31.0 format i.e Integer part only
-    while(MaxGain>0){                           // Update Shift required to provide integer gain
-        Shift++;
-        MaxGain=MaxGain>>1;
-    }
-    pInstance->Target=TargetGain<<(16-Shift);   // Update fractional gain Target
-    pInstance->Current=CurrentGain<<(16-Shift); // Update fractional gain Current
-    pInstance->Shift=Shift;                     // Update Shift
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.cpp
new file mode 100644
index 0000000..c9fd344
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_Init                                                      */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This intialization function intializes the private instance         */
+/*  paramters for a given Audio Stream based on TargetGain and          */
+/*  CurrentGain                                                         */
+/*  This function caclulates the "Shift" required to provide the        */
+/*  integer part of TargetGain and fractional gain values "Target" and  */
+/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
+/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
+/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
+/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
+/*  fraction gain is provided through Current=0.475 and Target=0.625    */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  TargetGain  - TargetGain value in Q 16.15 format                    */
+/*  CurrentGain - CurrentGain value in Q 16.15 format                   */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/*                                                                      */
+/************************************************************************/
+void LVC_Mixer_Init( LVMixer3_FLOAT_st *pStream,
+                     LVM_FLOAT           TargetGain,
+                     LVM_FLOAT           CurrentGain)
+{
+    LVM_FLOAT MaxGain = TargetGain;
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    if(CurrentGain > MaxGain)
+        MaxGain = CurrentGain;
+    pInstance->Target = TargetGain;   // Update fractional gain Target
+    pInstance->Current = CurrentGain; // Update fractional gain Current
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index 453a6a5..123d22b 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -26,7 +26,6 @@
 #include "VectorArithmetic.h"
 
 /* Instance parameter structure */
-#ifdef BUILD_FLOAT
 typedef struct
 {
     /* General */
@@ -34,16 +33,6 @@
     LVM_FLOAT                       Current;          /*number specifying value of Current Gain */
     LVM_FLOAT                       Delta;            /*number specifying value of Delta Gain */
 } Mix_Private_FLOAT_st;
-#else
-typedef struct
-{
-    /* General */
-    LVM_INT32                       Target;                 /* 32 bit number specifying fractional value of Target Gain */
-    LVM_INT32                       Current;                /* 32 bit number specifying fractional valude of Current Gain */
-    LVM_INT32                       Shift;                  /* Left Shift for Integer part of Gain */
-    LVM_INT32                       Delta;                  /* 32 bit number specifying the fractional value of Delta Gain */
-} Mix_Private_st;
-#endif
 
 /**********************************************************************************
    DEFINITIONS
@@ -57,7 +46,6 @@
 ***********************************************************************************/
 
 /*** 16 bit functions *************************************************************/
-#ifdef BUILD_FLOAT
 void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance,
                                     const LVM_FLOAT     *src,
                                     LVM_FLOAT     *dst,
@@ -69,13 +57,6 @@
                                           LVM_INT16     NrFrames,
                                           LVM_INT16     NrChannels);
 #endif
-#else
-void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *pInstance,
-                                    const LVM_INT16     *src,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n);
-#endif
-#ifdef BUILD_FLOAT
 void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_FLOAT_st *ptrInstance,
                                       const LVM_FLOAT     *src,
                                       LVM_FLOAT     *dst,
@@ -87,27 +68,12 @@
                                           LVM_INT16     NrFrames,
                                           LVM_INT16     NrChannels);
 #endif
-#else
-void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *pInstance,
-                                    const LVM_INT16     *src,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n);
-#endif
-#ifdef BUILD_FLOAT
 void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_FLOAT_st *pInstance1,
                                       LVMixer3_FLOAT_st         *pInstance2,
                                       const LVM_FLOAT     *src1,
                                       const LVM_FLOAT     *src2,
                                       LVM_FLOAT     *dst,
                                       LVM_INT16     n);
-#else
-void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *pInstance1,
-                                    LVMixer3_st         *pInstance2,
-                                    const LVM_INT16     *src1,
-                                    const LVM_INT16     *src2,
-                                          LVM_INT16     *dst,
-                                          LVM_INT16     n);
-#endif
 
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
@@ -115,7 +81,6 @@
 /* ptrInstance2 applies to Right channel                                          */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
-#ifdef BUILD_FLOAT
 #ifdef SUPPORT_MC
 void LVC_Core_MixSoft_1St_MC_float_WRA(Mix_Private_FLOAT_st **ptrInstance,
                                          const LVM_FLOAT      *src,
@@ -128,13 +93,6 @@
                                          const LVM_FLOAT    *src,
                                          LVM_FLOAT          *dst,
                                          LVM_INT16          n);
-#else
-void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
-                                         LVMixer3_st        *ptrInstance2,
-                                         const LVM_INT16    *src,
-                                         LVM_INT16          *dst,   /* dst can be equal to src */
-                                         LVM_INT16          n);     /* Number of stereo samples */
-#endif
 
 /**********************************************************************************/
 /* For applying different gains to Left and right chennals                        */
@@ -142,7 +100,6 @@
 /* ptrInstance2 applies to Right channel                                          */
 /* Gain values should not be more that 1.0                                        */
 /**********************************************************************************/
-#ifdef BUILD_FLOAT
 #ifdef SUPPORT_MC
 void LVC_Core_MixHard_1St_MC_float_SAT(Mix_Private_FLOAT_st **ptrInstance,
                                          const LVM_FLOAT      *src,
@@ -155,43 +112,9 @@
                                          const LVM_FLOAT    *src,
                                          LVM_FLOAT          *dst,
                                          LVM_INT16          n);
-#else
-void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
-                                         LVMixer3_st        *ptrInstance2,
-                                         const LVM_INT16    *src,
-                                         LVM_INT16          *dst,    /* dst can be equal to src */
-                                         LVM_INT16          n);      /* Number of stereo samples */
-#endif
 
 /*** 32 bit functions *************************************************************/
-#ifndef BUILD_FLOAT
-void LVC_Core_MixInSoft_D32C31_SAT( LVMixer3_st *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-
-void LVC_Core_MixSoft_1St_D32C31_WRA( LVMixer3_st *pInstance,
-                                    const LVM_INT32     *src,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-
-void LVC_Core_MixHard_2St_D32C31_SAT( LVMixer3_st *pInstance1,
-                                    LVMixer3_st         *pInstance2,
-                                    const LVM_INT32     *src1,
-                                    const LVM_INT32     *src2,
-                                          LVM_INT32     *dst,
-                                          LVM_INT16     n);
-#endif
 /**********************************************************************************/
 
 #endif //#ifndef __LVC_MIXER_PRIVATE_H__
 
-
-
-
-
-
-
-
-
-
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
deleted file mode 100644
index 577179d..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_SetTarget                                                 */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function updates the private instance parameters: Shift,Target,*/
-/*  Current for a given Audio Stream based on new value of TargetGain   */
-/*                                                                      */
-/*  This function caclulates the "Shift" required to provide the        */
-/*  integer part of TargetGain and fractional gain values "Target" and  */
-/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
-/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
-/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
-/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
-/*  fraction gain is provided through Current=0.475 and Target=0.625    */
-/* PARAMETERS:                                                          */
-/*  pStream         - ptr to Instance Parameter Structure LVMixer3_st   */
-/*                    for an Audio Stream                               */
-/*  TargetGain      - TargetGain value in Q 16.15 format                */
-/*                                                                      */
-/* RETURNS:                                                             */
-/*  void                                                                */
-/*                                                                      */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Mixer_SetTarget(LVMixer3_FLOAT_st *pStream,
-                         LVM_FLOAT         TargetGain)
-{
-    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-    pInstance->Target = TargetGain;               // Update gain Target
-}
-#else
-void LVC_Mixer_SetTarget(LVMixer3_st *pStream,
-                        LVM_INT32           TargetGain)
-{
-    LVM_INT32       Shift=0;
-    LVM_INT32       CurrentGain;
-    LVM_INT32       MaxGain=TargetGain;                     // MaxGain is in Q16.15 format
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-    CurrentGain=pInstance->Current>>(16-pInstance->Shift);  // CurrentGain in Q16.15 format
-    if(CurrentGain>MaxGain)
-        MaxGain=CurrentGain;                                // MaxGain=max(CurrentGain,TargetGain)
-
-    MaxGain=MaxGain>>15;                                    // MaxGain in Q31.0 format i.e Integer part only
-    while(MaxGain>0){                                       // Update Shift required to provide integer gain
-        Shift++;
-        MaxGain=MaxGain>>1;
-    }
-    pInstance->Target=TargetGain<<(16-Shift);               // Update fractional gain Target
-    pInstance->Current=CurrentGain<<(16-Shift);             // Update fractional gain Current
-    pInstance->Shift=Shift;                                 // Update Shift
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.cpp
new file mode 100644
index 0000000..47b0cec
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_SetTarget                                                 */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function updates the private instance parameters: Shift,Target,*/
+/*  Current for a given Audio Stream based on new value of TargetGain   */
+/*                                                                      */
+/*  This function caclulates the "Shift" required to provide the        */
+/*  integer part of TargetGain and fractional gain values "Target" and  */
+/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
+/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
+/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
+/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
+/*  fraction gain is provided through Current=0.475 and Target=0.625    */
+/* PARAMETERS:                                                          */
+/*  pStream         - ptr to Instance Parameter Structure LVMixer3_st   */
+/*                    for an Audio Stream                               */
+/*  TargetGain      - TargetGain value in Q 16.15 format                */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/*                                                                      */
+/************************************************************************/
+void LVC_Mixer_SetTarget(LVMixer3_FLOAT_st *pStream,
+                         LVM_FLOAT         TargetGain)
+{
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    pInstance->Target = TargetGain;               // Update gain Target
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
deleted file mode 100644
index 9d3ee88..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_SetTimeConstant                                           */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function calculates the step change for fractional gain for a  */
-/*  given time constant, sample rate and num channels                   */
-/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
-/*  in Q 0.31 format                                                    */
-/*                                                                      */
-/* PARAMETERS:                                                          */
-/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
-/*                Audio Stream                                          */
-/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
-/*                go from linear fractional gain of 0 to 0.99999999     */
-/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
-/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
-/*                                                                      */
-/* UPDATES:                                                             */
-/*  Delta       - the step change for fractional gain per 4 samples     */
-/*                in Q0.31 format for a given Time Constant,            */
-/*                Sample Rate and NumChannels                           */
-/* RETURNS:                                                             */
-/*  void                                                                */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Mixer_SetTimeConstant(LVMixer3_FLOAT_st *pStream,
-                               LVM_INT32           Tc_millisec,
-                               LVM_Fs_en           Fs,
-                               LVM_INT16           NumChannels)
-{
-#ifdef HIGHER_FS
-    LVM_FLOAT   DeltaTable[13] = {0.500000f,/*8000*/
-                                  0.362812f,/*11025*/
-                                  0.333333f,/*12000*/
-                                  0.250000f,/*16000*/
-                                  0.181406f,/*22050*/
-                                  0.166666f,/*24000*/
-                                  0.125000f,/*32000*/
-                                  0.090703f,/*44100*/
-                                  0.083333f,/*48000*/
-                                  0.045352f,/*88200*/
-                                  0.041667f,/*96000*/
-                                  0.022676f,/*176400*/
-                                  0.020833f};/*192000*/
-#else
-    LVM_FLOAT   DeltaTable[9] = {0.500000f,/*8000*/
-                                 0.362812f,/*11025*/
-                                 0.333333f,/*12000*/
-                                 0.250000f,/*16000*/
-                                 0.181406f,/*22050*/
-                                 0.166666f,/*24000*/
-                                 0.125000f,/*32000*/
-                                 0.090703f,/*44100*/
-                                 0.083333f};/*48000*/
-#endif
-
-    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-    LVM_FLOAT Delta = DeltaTable[Fs];
-    Delta = Delta / (NumChannels);
-
-    if(Tc_millisec == 0)
-        Delta = 1.000000f;
-    else
-        Delta = Delta / Tc_millisec;
-
-    if(Delta == 0)
-        Delta = 0.0000000005f;  /* If Time Constant is so large that Delta is 0, \
-                                  assign minimum value to Delta */
-    pInstance->Delta = Delta;  // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
-}
-#else
-void LVC_Mixer_SetTimeConstant(LVMixer3_st *pStream,
-                            LVM_INT32           Tc_millisec,
-                            LVM_Fs_en           Fs,
-                            LVM_INT16           NumChannels)
-{
-    LVM_INT32   DeltaTable[9]={1073741824,
-                               779132389,
-                               715827882,
-                               536870912,
-                               389566194,
-                               357913941,
-                               268435456,
-                               194783097,
-                               178956971};
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-    LVM_INT32   Delta=DeltaTable[Fs];
-    Delta=Delta>>(NumChannels-1);
-
-    if(Tc_millisec==0)
-        Delta=0x7FFFFFFF;
-    else
-        Delta=Delta/Tc_millisec;
-
-    if(Delta==0)
-        Delta=1;                // If Time Constant is so large that Delta is 0, assign minimum value to Delta
-
-    pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.cpp
new file mode 100644
index 0000000..1a8da7a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_SetTimeConstant                                           */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the step change for fractional gain for a  */
+/*  given time constant, sample rate and num channels                   */
+/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
+/*  in Q 0.31 format                                                    */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
+/*                go from linear fractional gain of 0 to 0.99999999     */
+/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
+/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
+/*                                                                      */
+/* UPDATES:                                                             */
+/*  Delta       - the step change for fractional gain per 4 samples     */
+/*                in Q0.31 format for a given Time Constant,            */
+/*                Sample Rate and NumChannels                           */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/************************************************************************/
+void LVC_Mixer_SetTimeConstant(LVMixer3_FLOAT_st *pStream,
+                               LVM_INT32           Tc_millisec,
+                               LVM_Fs_en           Fs,
+                               LVM_INT16           NumChannels)
+{
+    LVM_FLOAT   DeltaTable[13] = {0.500000f,/*8000*/
+                                  0.362812f,/*11025*/
+                                  0.333333f,/*12000*/
+                                  0.250000f,/*16000*/
+                                  0.181406f,/*22050*/
+                                  0.166666f,/*24000*/
+                                  0.125000f,/*32000*/
+                                  0.090703f,/*44100*/
+                                  0.083333f,/*48000*/
+                                  0.045352f,/*88200*/
+                                  0.041667f,/*96000*/
+                                  0.022676f,/*176400*/
+                                  0.020833f};/*192000*/
+
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    LVM_FLOAT Delta = DeltaTable[Fs];
+    Delta = Delta / (NumChannels);
+
+    if(Tc_millisec == 0)
+        Delta = 1.000000f;
+    else
+        Delta = Delta / Tc_millisec;
+
+    if(Delta == 0)
+        Delta = 0.0000000005f;  /* If Time Constant is so large that Delta is 0, \
+                                  assign minimum value to Delta */
+    pInstance->Delta = Delta;  // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
deleted file mode 100644
index 0e0acf1..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "LVC_Mixer_Private.h"
-
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVMixer3_VarSlope_SetTimeConstant                                  */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function calculates the step change for fractional gain for a  */
-/*  given time constant, sample rate and num channels                   */
-/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
-/*  in Q 0.31 format                                                    */
-/*                                                                      */
-/* PARAMETERS:                                                          */
-/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
-/*                Audio Stream                                          */
-/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
-/*                go from linear fractional gain of 0 to 0.99999999     */
-/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
-/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
-/*                                                                      */
-/* UPDATES:                                                             */
-/*  Delta       - the step change for fractional gain per 4 samples     */
-/*                in Q0.31 format for a given Time Constant,            */
-/*                Sample Rate and NumChannels                           */
-/* RETURNS:                                                             */
-/*  void                                                                */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
-                                         LVM_INT32           Tc_millisec,
-                                         LVM_Fs_en           Fs,
-                                         LVM_INT16           NumChannels)
-{
-#ifdef HIGHER_FS
-     LVM_FLOAT   DeltaTable[13] = {0.500000f,/*8000*/
-                                   0.362812f,/*11025*/
-                                   0.333333f,/*12000*/
-                                   0.250000f,/*16000*/
-                                   0.181406f,/*22050*/
-                                   0.166666f,/*24000*/
-                                   0.125000f,/*32000*/
-                                   0.090703f,/*44100*/
-                                   0.083333f,/*48000*/
-                                   0.045352f,/*88200*/
-                                   0.041666f,/*96000*/
-                                   0.022676f,/*176400*/
-                                   0.020833f};/*192000*/
-#else
-    LVM_FLOAT   DeltaTable[9] = {0.500000f,/*8000*/
-                                 0.362812f,/*11025*/
-                                 0.333333f,/*12000*/
-                                 0.250000f,/*16000*/
-                                 0.181406f,/*22050*/
-                                 0.166666f,/*24000*/
-                                 0.125000f,/*32000*/
-                                 0.090703f,/*44100*/
-                                 0.083333f};/*48000*/
-#endif
-    LVM_FLOAT Tc_millisec_float;
-    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-    LVM_FLOAT Delta = DeltaTable[Fs];
-
-    LVM_FLOAT   Current;
-    LVM_FLOAT   Target;
-
-    Delta=Delta / (NumChannels);
-
-    /*  Get gain values  */
-    Current = pInstance->Current;
-    Target = pInstance->Target;
-
-    if (Current != Target)
-    {
-        Tc_millisec_float = (LVM_FLOAT)(Tc_millisec) / (Current - Target);
-        if (Tc_millisec_float < 0)
-            Tc_millisec_float = -Tc_millisec_float;
-
-        if(Tc_millisec == 0)
-            Delta = 1.000000f;
-        else
-            Delta = Delta / Tc_millisec_float;
-
-        if(Delta == 0)
-            Delta = 0.0000000005f; /* If Time Constant is so large that Delta is 0, \
-                                      assign minimum value to Delta */
-    }
-    else
-    {
-        Delta = 0.0000000005f;  /* Minimum value for proper call-backs \
-                             (setting it to zero has some problems, to be corrected) */
-    }
-
-    pInstance->Delta = Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
-}
-#else
-void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
-                                        LVM_INT32           Tc_millisec,
-                                        LVM_Fs_en           Fs,
-                                        LVM_INT16           NumChannels)
-{
-    LVM_INT32   DeltaTable[9]={1073741824,
-                               779132389,
-                               715827882,
-                               536870912,
-                               389566194,
-                               357913941,
-                               268435456,
-                               194783097,
-                               178956971};
-    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
-    LVM_INT32   Delta=DeltaTable[Fs];
-
-    LVM_INT32   Current;
-    LVM_INT32   Target;
-
-    Delta=Delta>>(NumChannels-1);
-
-    /*  Get gain values  */
-    Current = LVC_Mixer_GetCurrent( pStream );
-    Target = LVC_Mixer_GetTarget( pStream );
-
-    if (Current != Target)
-    {
-        Tc_millisec = Tc_millisec * 32767 / (Current - Target);
-        if (Tc_millisec<0) Tc_millisec = -Tc_millisec;
-
-        if(Tc_millisec==0)
-            Delta=0x7FFFFFFF;
-        else
-            Delta=Delta/Tc_millisec;
-
-        if(Delta==0)
-            Delta=1;            // If Time Constant is so large that Delta is 0, assign minimum value to Delta
-    }
-    else
-    {
-        Delta =1;               // Minimum value for proper call-backs (setting it to zero has some problems, to be corrected)
-    }
-
-
-    pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.cpp b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.cpp
new file mode 100644
index 0000000..f335a1e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_VarSlope_SetTimeConstant                                  */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the step change for fractional gain for a  */
+/*  given time constant, sample rate and num channels                   */
+/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
+/*  in Q 0.31 format                                                    */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
+/*                go from linear fractional gain of 0 to 0.99999999     */
+/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
+/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
+/*                                                                      */
+/* UPDATES:                                                             */
+/*  Delta       - the step change for fractional gain per 4 samples     */
+/*                in Q0.31 format for a given Time Constant,            */
+/*                Sample Rate and NumChannels                           */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/************************************************************************/
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_FLOAT_st *pStream,
+                                         LVM_INT32           Tc_millisec,
+                                         LVM_Fs_en           Fs,
+                                         LVM_INT16           NumChannels)
+{
+     LVM_FLOAT   DeltaTable[13] = {0.500000f,/*8000*/
+                                   0.362812f,/*11025*/
+                                   0.333333f,/*12000*/
+                                   0.250000f,/*16000*/
+                                   0.181406f,/*22050*/
+                                   0.166666f,/*24000*/
+                                   0.125000f,/*32000*/
+                                   0.090703f,/*44100*/
+                                   0.083333f,/*48000*/
+                                   0.045352f,/*88200*/
+                                   0.041666f,/*96000*/
+                                   0.022676f,/*176400*/
+                                   0.020833f};/*192000*/
+    LVM_FLOAT Tc_millisec_float;
+    Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
+    LVM_FLOAT Delta = DeltaTable[Fs];
+
+    LVM_FLOAT   Current;
+    LVM_FLOAT   Target;
+
+    Delta=Delta / (NumChannels);
+
+    /*  Get gain values  */
+    Current = pInstance->Current;
+    Target = pInstance->Target;
+
+    if (Current != Target)
+    {
+        Tc_millisec_float = (LVM_FLOAT)(Tc_millisec) / (Current - Target);
+        if (Tc_millisec_float < 0)
+            Tc_millisec_float = -Tc_millisec_float;
+
+        if(Tc_millisec == 0)
+            Delta = 1.000000f;
+        else
+            Delta = Delta / Tc_millisec_float;
+
+        if(Delta == 0)
+            Delta = 0.0000000005f; /* If Time Constant is so large that Delta is 0, \
+                                      assign minimum value to Delta */
+    }
+    else
+    {
+        Delta = 0.0000000005f;  /* Minimum value for proper call-backs \
+                             (setting it to zero has some problems, to be corrected) */
+    }
+
+    pInstance->Delta = Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
deleted file mode 100644
index 9094622..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-#include "BIQUAD.h"
-#include "Filter.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
-/*                      FO_C32_Coefs_t  *pCoeffs);                         */
-/*                                                                         */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*    This function calculates the coefficient of first order low pass     */
-/*    filter. It uses the equations:                                       */
-/*                                                                         */
-/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
-/*    A0    = (1 - B1) / 2                                                 */
-/*    A1    = A0                                                           */
-/*                                                                         */
-/*    The value of B1 is then calculated directly from the value w by a    */
-/*    polynomial expansion using a 9th order polynomial. It uses the       */
-/*    following table of 32-bit integer polynomial coefficients:           */
-/*                                                                         */
-/*   Coefficient    Value                                                  */
-/*   A0             -8388571                                               */
-/*   A1             33547744                                               */
-/*   A2             -66816791                                              */
-/*   A3             173375308                                              */
-/*   A4             -388437573                                             */
-/*   A5             752975383                                              */
-/*   A6             -1103016663                                            */
-/*   A7             1121848567                                             */
-/*   A8             -688078159                                             */
-/*   A9             194669577                                              */
-/*   A10            8                                                      */
-/*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
-/*                                                                         */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*                                                                         */
-/*  w               Sample rate in radians,  where:                        */
-/*                  w = 2 * Pi * Fc / Fs                                   */
-/*                  Fc   is the corner frequency in Hz                     */
-/*                  Fs   is the sample rate in Hz                          */
-/*                  w is in Q2.29 format and data range is [0 Pi]          */
-/*  pCoeffs         Points to the filter coefficients calculated here      */
-/*                  in Q1.30 format                                        */
-/* RETURNS:                                                                */
-/*                                                                         */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVM_FO_HPF(   LVM_FLOAT       w,
-                        FO_FLOAT_Coefs_t  *pCoeffs)
-{
-    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
-                                    0.999801f,
-                                    -0.497824f,
-                                    0.322937f,
-                                    -0.180880f,
-                                    0.087658f,
-                                    -0.032102f,
-                                    0.008163f,
-                                    -0.001252f,
-                                    0.000089f,
-                                    0,
-                                    0,
-                                    0};
-    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
-
-    pCoeffs->B1 = -Y;         /* Store -B1 in filter structure instead of B1!*/
-                            /* A0=(1-B1)/2= B1/2 - 0.5*/
-    Y = Y / 2.0f;                 /* A0=Y=B1/2*/
-    Y = Y - 0.5f;         /* A0=Y=(B1/2 - 0.5)*/
-
-    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;                  /* Apply loss to avoid overflow*/
-    pCoeffs->A1 = -pCoeffs->A0;                           /* Store A1=-A0*/
-
-    return 1;
-}
-#else
-LVM_INT32 LVM_FO_HPF(   LVM_INT32       w,
-                        FO_C32_Coefs_t  *pCoeffs)
-{
-    LVM_INT32 Y,Coefficients[13]={  -8388571,
-                                    33547744,
-                                    -66816791,
-                                    173375308,
-                                    -388437573,
-                                    752975383,
-                                    -1103016663,
-                                    1121848567,
-                                    -688078159,
-                                    194669577,
-                                    8,
-                                    0,
-                                    0};
-    Y=LVM_Polynomial(           (LVM_UINT16)9,
-                                 Coefficients,
-                                 w);
-    pCoeffs->B1=-Y;         /* Store -B1 in filter structure instead of B1!*/
-                            /* A0=(1-B1)/2= B1/2 - 0.5*/
-    Y=Y>>1;                 /* A0=Y=B1/2*/
-    Y=Y-0x40000000;         /* A0=Y=(B1/2 - 0.5)*/
-    MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15)     /* Apply loss to avoid overflow*/
-    pCoeffs->A1=-pCoeffs->A0;                           /* Store A1=-A0*/
-
-    return 1;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.cpp b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.cpp
new file mode 100644
index 0000000..2497d29
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
+/*                      FO_C32_Coefs_t  *pCoeffs);                         */
+/*                                                                         */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*    This function calculates the coefficient of first order low pass     */
+/*    filter. It uses the equations:                                       */
+/*                                                                         */
+/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
+/*    A0    = (1 - B1) / 2                                                 */
+/*    A1    = A0                                                           */
+/*                                                                         */
+/*    The value of B1 is then calculated directly from the value w by a    */
+/*    polynomial expansion using a 9th order polynomial. It uses the       */
+/*    following table of 32-bit integer polynomial coefficients:           */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             -8388571                                               */
+/*   A1             33547744                                               */
+/*   A2             -66816791                                              */
+/*   A3             173375308                                              */
+/*   A4             -388437573                                             */
+/*   A5             752975383                                              */
+/*   A6             -1103016663                                            */
+/*   A7             1121848567                                             */
+/*   A8             -688078159                                             */
+/*   A9             194669577                                              */
+/*   A10            8                                                      */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  w               Sample rate in radians,  where:                        */
+/*                  w = 2 * Pi * Fc / Fs                                   */
+/*                  Fc   is the corner frequency in Hz                     */
+/*                  Fs   is the sample rate in Hz                          */
+/*                  w is in Q2.29 format and data range is [0 Pi]          */
+/*  pCoeffs         Points to the filter coefficients calculated here      */
+/*                  in Q1.30 format                                        */
+/* RETURNS:                                                                */
+/*                                                                         */
+/*-------------------------------------------------------------------------*/
+LVM_FLOAT LVM_FO_HPF(   LVM_FLOAT       w,
+                        FO_FLOAT_Coefs_t  *pCoeffs)
+{
+    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
+                                    0.999801f,
+                                    -0.497824f,
+                                    0.322937f,
+                                    -0.180880f,
+                                    0.087658f,
+                                    -0.032102f,
+                                    0.008163f,
+                                    -0.001252f,
+                                    0.000089f,
+                                    0,
+                                    0,
+                                    0};
+    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
+
+    pCoeffs->B1 = -Y;         /* Store -B1 in filter structure instead of B1!*/
+                            /* A0=(1-B1)/2= B1/2 - 0.5*/
+    Y = Y / 2.0f;                 /* A0=Y=B1/2*/
+    Y = Y - 0.5f;         /* A0=Y=(B1/2 - 0.5)*/
+
+    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;                  /* Apply loss to avoid overflow*/
+    pCoeffs->A1 = -pCoeffs->A0;                           /* Store A1=-A0*/
+
+    return 1;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
deleted file mode 100644
index 9fe67f8..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-#include "BIQUAD.h"
-#include "Filter.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
-/*                      FO_C32_Coefs_t  *pCoeffs);                         */
-/*                                                                         */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*    This function calculates the coefficient of first order low pass     */
-/*    filter. It uses the equations:                                       */
-/*                                                                         */
-/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
-/*    A0    = (1 + B1) / 2                                                 */
-/*    A1    = A0                                                           */
-/*                                                                         */
-/*    The value of B1 is then calculated directly from the value w by a    */
-/*    polynomial expansion using a 9th order polynomial. It uses the       */
-/*    following table of 32-bit integer polynomial coefficients:           */
-/*                                                                         */
-/*   Coefficient    Value                                                  */
-/*   A0             -8388571                                               */
-/*   A1             33547744                                               */
-/*   A2             -66816791                                              */
-/*   A3             173375308                                              */
-/*   A4             -388437573                                             */
-/*   A5             752975383                                              */
-/*   A6             -1103016663                                            */
-/*   A7             1121848567                                             */
-/*   A8             -688078159                                             */
-/*   A9             194669577                                              */
-/*   A10            8                                                      */
-/*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
-/*                                                                         */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*                                                                         */
-/*  w               Sample rate in radians,  where:                        */
-/*                  w = 2 * Pi * Fc / Fs                                   */
-/*                  Fc   is the corner frequency in Hz                     */
-/*                  Fs   is the sample rate in Hz                          */
-/*                  w is in Q2.29 format and data range is [0 Pi]          */
-/*  pCoeffs         Points to the filter coefficients calculated here      */
-/*                  in Q1.30 format                                        */
-/* RETURNS:                                                                */
-/*                                                                         */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVM_FO_LPF(   LVM_FLOAT       w,
-                        FO_FLOAT_Coefs_t  *pCoeffs)
-{
-    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
-                                    0.999801f,
-                                    -0.497824f,
-                                    0.322937f,
-                                    -0.180880f,
-                                    0.087658f,
-                                    -0.032102f,
-                                    0.008163f,
-                                    -0.001252f,
-                                    0.000089f,
-                                    0};
-    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
-    pCoeffs->B1 = -Y;     // Store -B1 in filter structure instead of B1!
-                        // A0=(1+B1)/2= B1/2 + 0.5
-    Y = Y / 2.0f;             // A0=Y=B1/2
-    Y = Y + 0.5f;     // A0=Y=(B1/2 + 0.5)
-
-    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;
-    pCoeffs->A1 = pCoeffs->A0;
-
-    return 1;
-}
-#else
-LVM_INT32 LVM_FO_LPF(   LVM_INT32       w,
-                        FO_C32_Coefs_t  *pCoeffs)
-{
-    LVM_INT32 Y,Coefficients[13]={  -8388571,
-                                    33547744,
-                                    -66816791,
-                                    173375308,
-                                    -388437573,
-                                    752975383,
-                                    -1103016663,
-                                    1121848567,
-                                    -688078159,
-                                    194669577,
-                                    8};
-    Y=LVM_Polynomial(           (LVM_UINT16)9,
-                                 Coefficients,
-                                 w);
-    pCoeffs->B1=-Y;     // Store -B1 in filter structure instead of B1!
-                        // A0=(1+B1)/2= B1/2 + 0.5
-    Y=Y>>1;             // A0=Y=B1/2
-    Y=Y+0x40000000;     // A0=Y=(B1/2 + 0.5)
-    MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15)    // Apply loss to avoid overflow
-    pCoeffs->A1=pCoeffs->A0;
-    return 1;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.cpp b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.cpp
new file mode 100644
index 0000000..7bc6046
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
+/*                      FO_C32_Coefs_t  *pCoeffs);                         */
+/*                                                                         */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*    This function calculates the coefficient of first order low pass     */
+/*    filter. It uses the equations:                                       */
+/*                                                                         */
+/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
+/*    A0    = (1 + B1) / 2                                                 */
+/*    A1    = A0                                                           */
+/*                                                                         */
+/*    The value of B1 is then calculated directly from the value w by a    */
+/*    polynomial expansion using a 9th order polynomial. It uses the       */
+/*    following table of 32-bit integer polynomial coefficients:           */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             -8388571                                               */
+/*   A1             33547744                                               */
+/*   A2             -66816791                                              */
+/*   A3             173375308                                              */
+/*   A4             -388437573                                             */
+/*   A5             752975383                                              */
+/*   A6             -1103016663                                            */
+/*   A7             1121848567                                             */
+/*   A8             -688078159                                             */
+/*   A9             194669577                                              */
+/*   A10            8                                                      */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  w               Sample rate in radians,  where:                        */
+/*                  w = 2 * Pi * Fc / Fs                                   */
+/*                  Fc   is the corner frequency in Hz                     */
+/*                  Fs   is the sample rate in Hz                          */
+/*                  w is in Q2.29 format and data range is [0 Pi]          */
+/*  pCoeffs         Points to the filter coefficients calculated here      */
+/*                  in Q1.30 format                                        */
+/* RETURNS:                                                                */
+/*                                                                         */
+/*-------------------------------------------------------------------------*/
+LVM_FLOAT LVM_FO_LPF(   LVM_FLOAT       w,
+                        FO_FLOAT_Coefs_t  *pCoeffs)
+{
+    LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
+                                    0.999801f,
+                                    -0.497824f,
+                                    0.322937f,
+                                    -0.180880f,
+                                    0.087658f,
+                                    -0.032102f,
+                                    0.008163f,
+                                    -0.001252f,
+                                    0.000089f,
+                                    0};
+    Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
+    pCoeffs->B1 = -Y;     // Store -B1 in filter structure instead of B1!
+                        // A0=(1+B1)/2= B1/2 + 0.5
+    Y = Y / 2.0f;             // A0=Y=B1/2
+    Y = Y + 0.5f;     // A0=Y=(B1/2 + 0.5)
+
+    pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;
+    pCoeffs->A1 = pCoeffs->A0;
+
+    return 1;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
deleted file mode 100644
index 6307e68..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "Filter.h"
-#include "LVM_Macros.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* Defines and Tables for 2*Pi/Fs                                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-#define LVVDL_2PiBy_8000        1727108826  /* In Q41 format */
-#define LVVDL_2PiBy_11025       1253230894  /* In Q41 format */
-#define LVVDL_2PiBy_12000       1151405884  /* In Q41 format */
-
-#define LVVDL_2PiByFs_SHIFT1    12          /* Qformat shift for 8kHz, 11.025kHz and 12kHz i.e. 12=41-29 */
-#define LVVDL_2PiByFs_SHIFT2    13          /* Qformat shift for 16kHz, 22.050kHz and 24kHz i.e. 13=42-29 */
-#define LVVDL_2PiByFs_SHIFT3    14          /* Qformat shift for 32kHz, 44.1kHz and 48kHz i.e. 14=43-29 */
-#ifndef BUILD_FLOAT
-const LVM_INT32     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000 , /* 8kHz in Q41, 16kHz in Q42, 32kHz in Q43 */
-                                            LVVDL_2PiBy_11025,  /* 11025 Hz in Q41, 22050Hz in Q42, 44100 Hz in Q43*/
-                                            LVVDL_2PiBy_12000}; /* 12kHz in Q41, 24kHz in Q42, 48kHz in Q43 */
-#endif
-
-const LVM_INT32     LVVDL_2PiOnFsShiftTable[]={LVVDL_2PiByFs_SHIFT1 ,         /* 8kHz, 11025Hz, 12kHz */
-                                               LVVDL_2PiByFs_SHIFT2,          /* 16kHz, 22050Hz, 24kHz*/
-                                               LVVDL_2PiByFs_SHIFT3};         /* 32kHz, 44100Hz, 48kHz */
-#ifdef BUILD_FLOAT
-#define LVVDL_2PiBy_8000_f        0.000785398f
-#define LVVDL_2PiBy_11025_f       0.000569903f
-#define LVVDL_2PiBy_12000_f       0.000523599f
-#define LVVDL_2PiBy_16000_f       0.000392700f
-#define LVVDL_2PiBy_22050_f       0.000284952f
-#define LVVDL_2PiBy_24000_f       0.000261800f
-#define LVVDL_2PiBy_32000_f       0.000196350f
-#define LVVDL_2PiBy_44100_f       0.000142476f
-#define LVVDL_2PiBy_48000_f       0.000130900f
-
-#ifdef HIGHER_FS
-#define LVVDL_2PiBy_88200_f       0.000071238f
-#define LVVDL_2PiBy_96000_f       0.000065450f
-#define LVVDL_2PiBy_176400_f      0.000035619f
-#define LVVDL_2PiBy_192000_f      0.000032725f
-#endif
-const LVM_FLOAT     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000_f,
-                                             LVVDL_2PiBy_11025_f,
-                                             LVVDL_2PiBy_12000_f,
-                                             LVVDL_2PiBy_16000_f,
-                                             LVVDL_2PiBy_22050_f,
-                                             LVVDL_2PiBy_24000_f,
-                                             LVVDL_2PiBy_32000_f,
-                                             LVVDL_2PiBy_44100_f,
-                                             LVVDL_2PiBy_48000_f
-#ifdef HIGHER_FS
-                                            ,LVVDL_2PiBy_88200_f
-                                            ,LVVDL_2PiBy_96000_f
-                                            ,LVVDL_2PiBy_176400_f
-                                            ,LVVDL_2PiBy_192000_f
-#endif
-                                           };
-#endif
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   LVM_GetOmega                                                          */
-/*                                                                         */
-/* LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,                  */
-/*                        LVM_Fs_en                   Fs)                  */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   This function calculates the value of w using Fc and Fs               */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*                                                                         */
-/*  LVM_UINT16          Fc     The corner frequency in Hz Q16.0 format     */
-/*  LVM_Fs_en           Fs     The SampleRate                              */
-/* RETURNS:                                                                */
-/*   w=2*pi*Fc/Fs in Q2.29 format                                          */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-#ifdef HIGHER_FS
-LVM_FLOAT LVM_GetOmega(LVM_UINT32                  Fc,
-                       LVM_Fs_en                   Fs)
-#else
-LVM_FLOAT LVM_GetOmega(LVM_UINT16                  Fc,
-                       LVM_Fs_en                   Fs)
-#endif
-{
-    LVM_FLOAT   w;
-    w = (LVM_FLOAT)Fc * LVVDL_2PiOnFsTable[Fs];
-    return w;
-}
-#else
-LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,
-                       LVM_Fs_en                   Fs)
-{
-    LVM_INT32   w;
-    MUL32x32INTO32((LVM_INT32)Fc,LVVDL_2PiOnFsTable[Fs%3],w,LVVDL_2PiOnFsShiftTable[Fs/3])
-    return w;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.cpp b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.cpp
new file mode 100644
index 0000000..2a7cca2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "Filter.h"
+#include "LVM_Macros.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* Defines and Tables for 2*Pi/Fs                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVVDL_2PiBy_8000        1727108826  /* In Q41 format */
+#define LVVDL_2PiBy_11025       1253230894  /* In Q41 format */
+#define LVVDL_2PiBy_12000       1151405884  /* In Q41 format */
+
+#define LVVDL_2PiByFs_SHIFT1    12          /* Qformat shift for 8kHz, 11.025kHz and 12kHz i.e. 12=41-29 */
+#define LVVDL_2PiByFs_SHIFT2    13          /* Qformat shift for 16kHz, 22.050kHz and 24kHz i.e. 13=42-29 */
+#define LVVDL_2PiByFs_SHIFT3    14          /* Qformat shift for 32kHz, 44.1kHz and 48kHz i.e. 14=43-29 */
+#define LVVDL_2PiBy_8000_f        0.000785398f
+#define LVVDL_2PiBy_11025_f       0.000569903f
+#define LVVDL_2PiBy_12000_f       0.000523599f
+#define LVVDL_2PiBy_16000_f       0.000392700f
+#define LVVDL_2PiBy_22050_f       0.000284952f
+#define LVVDL_2PiBy_24000_f       0.000261800f
+#define LVVDL_2PiBy_32000_f       0.000196350f
+#define LVVDL_2PiBy_44100_f       0.000142476f
+#define LVVDL_2PiBy_48000_f       0.000130900f
+
+#define LVVDL_2PiBy_88200_f       0.000071238f
+#define LVVDL_2PiBy_96000_f       0.000065450f
+#define LVVDL_2PiBy_176400_f      0.000035619f
+#define LVVDL_2PiBy_192000_f      0.000032725f
+const LVM_FLOAT     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000_f,
+                                             LVVDL_2PiBy_11025_f,
+                                             LVVDL_2PiBy_12000_f,
+                                             LVVDL_2PiBy_16000_f,
+                                             LVVDL_2PiBy_22050_f,
+                                             LVVDL_2PiBy_24000_f,
+                                             LVVDL_2PiBy_32000_f,
+                                             LVVDL_2PiBy_44100_f,
+                                             LVVDL_2PiBy_48000_f
+                                            ,LVVDL_2PiBy_88200_f
+                                            ,LVVDL_2PiBy_96000_f
+                                            ,LVVDL_2PiBy_176400_f
+                                            ,LVVDL_2PiBy_192000_f
+                                           };
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_GetOmega                                                          */
+/*                                                                         */
+/* LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,                  */
+/*                        LVM_Fs_en                   Fs)                  */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function calculates the value of w using Fc and Fs               */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  LVM_UINT16          Fc     The corner frequency in Hz Q16.0 format     */
+/*  LVM_Fs_en           Fs     The SampleRate                              */
+/* RETURNS:                                                                */
+/*   w=2*pi*Fc/Fs in Q2.29 format                                          */
+/*-------------------------------------------------------------------------*/
+LVM_FLOAT LVM_GetOmega(LVM_UINT32                  Fc,
+                       LVM_Fs_en                   Fs)
+{
+    LVM_FLOAT   w;
+    w = (LVM_FLOAT)Fc * LVVDL_2PiOnFsTable[Fs];
+    return w;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
index f1e45fa..244f09d 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
@@ -27,7 +27,6 @@
 #ifndef __LVM_MIXER_FILTER_COEFFS_H__
 #define __LVM_MIXER_FILTER_COEFFS_H__
 
-
 /************************************************************************************/
 /*                                                                                  */
 /* Alpha Time Constant table                                                        */
@@ -87,7 +86,6 @@
 #define ALPHA_49                                0      /* Floating point Alpha = 0.000000 */
 #define ALPHA_50                                0      /* Floating point Alpha = 0.000000 */
 
-#ifdef BUILD_FLOAT /* BUILD_FLOAT */
 #define ALPHA_Float_0                        0.999999f
 #define ALPHA_Float_1                        0.999998f
 #define ALPHA_Float_2                        0.999997f
@@ -139,6 +137,5 @@
 #define ALPHA_Float_48                       0.000000f
 #define ALPHA_Float_49                       0.000000f
 #define ALPHA_Float_50                       0.000000f
-#endif
 
 #endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
deleted file mode 100644
index 18b2782..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "Mixer.h"
-#include "LVM_Mixer_FilterCoeffs.h"
-
-
-/************************************************************************/
-/* FUNCTION:                                                            */
-/*   LVM_Mix_GetTimeConstant                                            */
-/*                                                                      */
-/* DESCRIPTION:                                                         */
-/*  This function calculates the filter coefficient using the following */
-/*  equation:                                                           */
-/*       Alpha = exp(ln(0.1)/ (tc * Update + 1.0))                      */
-/*                                                                      */
-/*  This is to be used with the follow first order filter, called at a  */
-/*  rate of Update times a second. tc is the required time constant in  */
-/*  units of 100us.                                                     */
-/*                                                                      */
-/*       Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n)      */
-/*                                                                      */
-/*  The function assumes the block size is large, i.e. the update rate  */
-/*  is approximately a fixed, and correct factor of the value of Fs     */
-/*  given in the call. This is especially not true when the block size  */
-/*  is very small, see the mixer documentation for further details.     */
-/*                                                                      */
-/*  The function does not support all possible combinations of input    */
-/*  values:                                                             */
-/*                                                                      */
-/*  1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo)     */
-/*  2. The product tc * Fs is limited approximately to the range        */
-/*      8 < (tc * Fs) < 2^35                                            */
-/*                                                                      */
-/* PARAMETERS:                                                          */
-/*  tc              - the time constant in 100us steps, i.e. 10 = 1ms   */
-/*  Fs              - the filter update rate in Hz                      */
-/*  NumChannels     - Number of channels 1=Mono, 2=Stereo               */
-/*                                                                      */
-/* RETURNS:                                                             */
-/*  Alpha   - the filter coefficient Q31 format                         */
-/*                                                                      */
-/************************************************************************/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32   tc,
-#ifdef HIGHER_FS
-                                  LVM_UINT32   Fs,
-#else
-                                  LVM_UINT16   Fs,
-#endif
-                                  LVM_UINT16   NumChannels)
-{
-
-    LVM_UINT32  Product;
-    LVM_FLOAT  ProductFloat;
-    LVM_INT16   InterpolateShort;
-    LVM_FLOAT   Interpolate;
-    LVM_UINT16  Shift;
-    LVM_FLOAT   Diff;
-    LVM_FLOAT  Table[] = {ALPHA_Float_0,             /* Log spaced look-up table */
-                          ALPHA_Float_1,
-                          ALPHA_Float_2,
-                          ALPHA_Float_3,
-                          ALPHA_Float_4,
-                          ALPHA_Float_5,
-                          ALPHA_Float_6,
-                          ALPHA_Float_7,
-                          ALPHA_Float_8,
-                          ALPHA_Float_9,
-                          ALPHA_Float_10,
-                          ALPHA_Float_11,
-                          ALPHA_Float_12,
-                          ALPHA_Float_13,
-                          ALPHA_Float_14,
-                          ALPHA_Float_15,
-                          ALPHA_Float_16,
-                          ALPHA_Float_17,
-                          ALPHA_Float_18,
-                          ALPHA_Float_19,
-                          ALPHA_Float_20,
-                          ALPHA_Float_21,
-                          ALPHA_Float_22,
-                          ALPHA_Float_23,
-                          ALPHA_Float_24,
-                          ALPHA_Float_25,
-                          ALPHA_Float_26,
-                          ALPHA_Float_27,
-                          ALPHA_Float_28,
-                          ALPHA_Float_29,
-                          ALPHA_Float_30,
-                          ALPHA_Float_31,
-                          ALPHA_Float_32,
-                          ALPHA_Float_33,
-                          ALPHA_Float_34,
-                          ALPHA_Float_35,
-                          ALPHA_Float_36,
-                          ALPHA_Float_37,
-                          ALPHA_Float_38,
-                          ALPHA_Float_39,
-                          ALPHA_Float_40,
-                          ALPHA_Float_41,
-                          ALPHA_Float_42,
-                          ALPHA_Float_43,
-                          ALPHA_Float_44,
-                          ALPHA_Float_45,
-                          ALPHA_Float_46,
-                          ALPHA_Float_47,
-                          ALPHA_Float_48,
-                          ALPHA_Float_49,
-                          ALPHA_Float_50};
-
-    /* Calculate the product of the time constant and the sample rate */
-    Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13;  /* Stereo value */
-    Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
-
-    if (NumChannels == 1)
-    {
-        Product = Product >> 1;   /* Mono value */
-    }
-
-    /* Normalize to get the table index and interpolation factor */
-    for (Shift = 0; Shift < ((Alpha_TableSize - 1) / 2); Shift++)
-    {
-        if ((Product & 0x80000000) != 0)
-        {
-            break;
-        }
-
-        Product = Product << 1;
-    }
-    Shift = (LVM_UINT16)((Shift << 1));
-
-    if ((Product & 0x40000000)==0)
-    {
-        Shift++;
-    }
-
-    InterpolateShort = (LVM_INT16)((Product >> 15) & 0x00007FFF);
-    Interpolate = (LVM_FLOAT)InterpolateShort / 32768.0f;
-
-    Diff = (Table[Shift] - Table[Shift + 1]);
-    Diff = Diff * Interpolate;
-    ProductFloat = Table[Shift + 1] + Diff;
-
-    return ProductFloat;
-}
-#else
-LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
-                                  LVM_UINT16   Fs,
-                                  LVM_UINT16   NumChannels)
-{
-
-    LVM_UINT32  Product;
-    LVM_INT16   Interpolate;
-    LVM_UINT16  Shift;
-    LVM_INT32   Diff;
-    LVM_UINT32  Table[] = {ALPHA_0,             /* Log spaced look-up table */
-                           ALPHA_1,
-                           ALPHA_2,
-                           ALPHA_3,
-                           ALPHA_4,
-                           ALPHA_5,
-                           ALPHA_6,
-                           ALPHA_7,
-                           ALPHA_8,
-                           ALPHA_9,
-                           ALPHA_10,
-                           ALPHA_11,
-                           ALPHA_12,
-                           ALPHA_13,
-                           ALPHA_14,
-                           ALPHA_15,
-                           ALPHA_16,
-                           ALPHA_17,
-                           ALPHA_18,
-                           ALPHA_19,
-                           ALPHA_20,
-                           ALPHA_21,
-                           ALPHA_22,
-                           ALPHA_23,
-                           ALPHA_24,
-                           ALPHA_25,
-                           ALPHA_26,
-                           ALPHA_27,
-                           ALPHA_28,
-                           ALPHA_29,
-                           ALPHA_30,
-                           ALPHA_31,
-                           ALPHA_32,
-                           ALPHA_33,
-                           ALPHA_34,
-                           ALPHA_35,
-                           ALPHA_36,
-                           ALPHA_37,
-                           ALPHA_38,
-                           ALPHA_39,
-                           ALPHA_40,
-                           ALPHA_41,
-                           ALPHA_42,
-                           ALPHA_43,
-                           ALPHA_44,
-                           ALPHA_45,
-                           ALPHA_46,
-                           ALPHA_47,
-                           ALPHA_48,
-                           ALPHA_49,
-                           ALPHA_50};
-
-
-    /* Calculate the product of the time constant and the sample rate */
-    Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13;  /* Stereo value */
-    Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
-
-    if (NumChannels == 1)
-    {
-        Product = Product >> 1;   /* Mono value */
-    }
-
-    /* Normalize to get the table index and interpolation factor */
-    for (Shift=0; Shift<((Alpha_TableSize-1)/2); Shift++)
-    {
-        if ((Product & 0x80000000)!=0)
-        {
-            break;
-        }
-
-        Product = Product << 1;
-    }
-    Shift = (LVM_UINT16)((Shift << 1));
-
-    if ((Product & 0x40000000)==0)
-    {
-        Shift++;
-    }
-
-    Interpolate = (LVM_INT16)((Product >> 15) & 0x00007FFF);
-
-    Diff = (LVM_INT32)(Table[Shift] - Table[Shift+1]);
-    MUL32x16INTO32(Diff,Interpolate,Diff,15)
-        Product = Table[Shift+1] + (LVM_UINT32)Diff;
-
-    return Product;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.cpp b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.cpp
new file mode 100644
index 0000000..73da2cf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "Mixer.h"
+#include "LVM_Mixer_FilterCoeffs.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVM_Mix_GetTimeConstant                                            */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the filter coefficient using the following */
+/*  equation:                                                           */
+/*       Alpha = exp(ln(0.1)/ (tc * Update + 1.0))                      */
+/*                                                                      */
+/*  This is to be used with the follow first order filter, called at a  */
+/*  rate of Update times a second. tc is the required time constant in  */
+/*  units of 100us.                                                     */
+/*                                                                      */
+/*       Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n)      */
+/*                                                                      */
+/*  The function assumes the block size is large, i.e. the update rate  */
+/*  is approximately a fixed, and correct factor of the value of Fs     */
+/*  given in the call. This is especially not true when the block size  */
+/*  is very small, see the mixer documentation for further details.     */
+/*                                                                      */
+/*  The function does not support all possible combinations of input    */
+/*  values:                                                             */
+/*                                                                      */
+/*  1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo)     */
+/*  2. The product tc * Fs is limited approximately to the range        */
+/*      8 < (tc * Fs) < 2^35                                            */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  tc              - the time constant in 100us steps, i.e. 10 = 1ms   */
+/*  Fs              - the filter update rate in Hz                      */
+/*  NumChannels     - Number of channels 1=Mono, 2=Stereo               */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  Alpha   - the filter coefficient Q31 format                         */
+/*                                                                      */
+/************************************************************************/
+LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32   tc,
+                                  LVM_UINT32   Fs,
+                                  LVM_UINT16   NumChannels)
+{
+
+    LVM_UINT32  Product;
+    LVM_FLOAT  ProductFloat;
+    LVM_INT16   InterpolateShort;
+    LVM_FLOAT   Interpolate;
+    LVM_UINT16  Shift;
+    LVM_FLOAT   Diff;
+    LVM_FLOAT  Table[] = {ALPHA_Float_0,             /* Log spaced look-up table */
+                          ALPHA_Float_1,
+                          ALPHA_Float_2,
+                          ALPHA_Float_3,
+                          ALPHA_Float_4,
+                          ALPHA_Float_5,
+                          ALPHA_Float_6,
+                          ALPHA_Float_7,
+                          ALPHA_Float_8,
+                          ALPHA_Float_9,
+                          ALPHA_Float_10,
+                          ALPHA_Float_11,
+                          ALPHA_Float_12,
+                          ALPHA_Float_13,
+                          ALPHA_Float_14,
+                          ALPHA_Float_15,
+                          ALPHA_Float_16,
+                          ALPHA_Float_17,
+                          ALPHA_Float_18,
+                          ALPHA_Float_19,
+                          ALPHA_Float_20,
+                          ALPHA_Float_21,
+                          ALPHA_Float_22,
+                          ALPHA_Float_23,
+                          ALPHA_Float_24,
+                          ALPHA_Float_25,
+                          ALPHA_Float_26,
+                          ALPHA_Float_27,
+                          ALPHA_Float_28,
+                          ALPHA_Float_29,
+                          ALPHA_Float_30,
+                          ALPHA_Float_31,
+                          ALPHA_Float_32,
+                          ALPHA_Float_33,
+                          ALPHA_Float_34,
+                          ALPHA_Float_35,
+                          ALPHA_Float_36,
+                          ALPHA_Float_37,
+                          ALPHA_Float_38,
+                          ALPHA_Float_39,
+                          ALPHA_Float_40,
+                          ALPHA_Float_41,
+                          ALPHA_Float_42,
+                          ALPHA_Float_43,
+                          ALPHA_Float_44,
+                          ALPHA_Float_45,
+                          ALPHA_Float_46,
+                          ALPHA_Float_47,
+                          ALPHA_Float_48,
+                          ALPHA_Float_49,
+                          ALPHA_Float_50};
+
+    /* Calculate the product of the time constant and the sample rate */
+    Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13;  /* Stereo value */
+    Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
+
+    if (NumChannels == 1)
+    {
+        Product = Product >> 1;   /* Mono value */
+    }
+
+    /* Normalize to get the table index and interpolation factor */
+    for (Shift = 0; Shift < ((Alpha_TableSize - 1) / 2); Shift++)
+    {
+        if ((Product & 0x80000000) != 0)
+        {
+            break;
+        }
+
+        Product = Product << 1;
+    }
+    Shift = (LVM_UINT16)((Shift << 1));
+
+    if ((Product & 0x40000000)==0)
+    {
+        Shift++;
+    }
+
+    InterpolateShort = (LVM_INT16)((Product >> 15) & 0x00007FFF);
+    Interpolate = (LVM_FLOAT)InterpolateShort / 32768.0f;
+
+    Diff = (Table[Shift] - Table[Shift + 1]);
+    Diff = Diff * Interpolate;
+    ProductFloat = Table[Shift + 1] + Diff;
+
+    return ProductFloat;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
deleted file mode 100644
index cd57767..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   LVM_Polynomial                                                        */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   This function performs polynomial expansion                           */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
-/*                                                                         */
-/*  LVM_INT32 LVM_Polynomial(LVM_UINT16    N,                              */
-/*                           LVM_INT32    *pCoefficients,                  */
-/*                           LVM_INT32    X)                               */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*                                                                         */
-/*  N                is the polynomial order                               */
-/*  pCoefficients    is the ptr to polynomial coefficients A0,A1.. in Q.31 */
-/*  X                is the input variable                                 */
-/*                                                                         */
-/* RETURNS:                                                                */
-/*   The result of the polynomial expansion in Q1.31 format                */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVM_Polynomial(LVM_UINT16    N,
-                         LVM_FLOAT    *pCoefficients,
-                         LVM_FLOAT    X)
-{
-    LVM_INT32 i;
-    LVM_FLOAT Y,A,XTemp,Temp,sign;
-
-    Y = *pCoefficients; /* Y=A0*/
-    pCoefficients++;
-
-    if(X == -1.0f)
-    {
-        Temp = -1;
-        sign = Temp;
-        for(i = 1; i <= N; i++)
-        {
-            Y += ((*pCoefficients) * sign);
-            pCoefficients++;
-            sign *= Temp;
-        }
-
-
-    }
-    else
-    {
-        XTemp = X;
-        for(i = N-1; i >= 0; i--)
-        {
-            A = *pCoefficients;
-            pCoefficients++;
-
-            Temp = A * XTemp;
-            Y += Temp;
-
-            Temp = XTemp * X;
-            XTemp = Temp;
-        }
-    }
-    return Y;
-}
-#else
-LVM_INT32 LVM_Polynomial(LVM_UINT16    N,
-                         LVM_INT32    *pCoefficients,
-                         LVM_INT32    X)
-{
-    LVM_INT32 i;
-    LVM_INT32 Y,A,XTemp,Temp,sign;
-
-    Y=*pCoefficients; /* Y=A0*/
-    pCoefficients++;
-
-    if((LVM_UINT32)X==0x80000000)
-    {
-        Temp=-1;
-        sign=Temp;
-        for(i=1;i<=N;i++)
-        {
-            Y+=((*pCoefficients)*sign);
-            pCoefficients++;
-            sign*=Temp;
-        }
-
-
-    }
-    else
-    {
-        XTemp=X;
-        for(i=N-1;i>=0;i--)
-        {
-            A=*pCoefficients;
-            pCoefficients++;
-
-            MUL32x32INTO32(A,XTemp,Temp,31)
-            Y+=Temp;
-
-            MUL32x32INTO32(XTemp,X,Temp,31)
-            XTemp=Temp;
-        }
-    }
-    A=*pCoefficients;
-    pCoefficients++;
-
-    if(A<0)
-    {
-        A=Abs_32(A);
-        Y=Y>>A;
-    }
-    else
-    {
-        Y = Y<<A;
-    }
-    return Y;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.cpp b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.cpp
new file mode 100644
index 0000000..2c3e9ec
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_Polynomial                                                        */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function performs polynomial expansion                           */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*  LVM_INT32 LVM_Polynomial(LVM_UINT16    N,                              */
+/*                           LVM_INT32    *pCoefficients,                  */
+/*                           LVM_INT32    X)                               */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  N                is the polynomial order                               */
+/*  pCoefficients    is the ptr to polynomial coefficients A0,A1.. in Q.31 */
+/*  X                is the input variable                                 */
+/*                                                                         */
+/* RETURNS:                                                                */
+/*   The result of the polynomial expansion in Q1.31 format                */
+/*-------------------------------------------------------------------------*/
+LVM_FLOAT LVM_Polynomial(LVM_UINT16    N,
+                         LVM_FLOAT    *pCoefficients,
+                         LVM_FLOAT    X)
+{
+    LVM_INT32 i;
+    LVM_FLOAT Y,A,XTemp,Temp,sign;
+
+    Y = *pCoefficients; /* Y=A0*/
+    pCoefficients++;
+
+    if(X == -1.0f)
+    {
+        Temp = -1;
+        sign = Temp;
+        for(i = 1; i <= N; i++)
+        {
+            Y += ((*pCoefficients) * sign);
+            pCoefficients++;
+            sign *= Temp;
+        }
+
+    }
+    else
+    {
+        XTemp = X;
+        for(i = N-1; i >= 0; i--)
+        {
+            A = *pCoefficients;
+            pCoefficients++;
+
+            Temp = A * XTemp;
+            Y += Temp;
+
+            Temp = XTemp * X;
+            XTemp = Temp;
+        }
+    }
+    return Y;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
deleted file mode 100644
index 8785594..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVM_Types.h"
-#include "LVM_Macros.h"
-#include "ScalarArithmetic.h"
-#include "Filter.h"
-
-
-/*-------------------------------------------------------------------------*/
-/* FUNCTION:                                                               */
-/*   LVM_Power10                                                           */
-/*                                                                         */
-/* DESCRIPTION:                                                            */
-/*   This function calculates 10X using an 11th order polynomial. It uses  */
-/*   the following table of 32-bit integer polynomial coefficients:        */
-/*                                                                         */
-/*   Coefficient    Value                                                  */
-/*   A0             67102543                                               */
-/*   A1             309032995                                              */
-/*   A2             712096127                                              */
-/*   A3             1092797331                                             */
-/*   A4             1251625137                                             */
-/*   A5             1154649460                                             */
-/*   A6             915654800                                              */
-/*   A7             597883683                                              */
-/*   A8             284378230                                              */
-/*   A9             150262097                                              */
-/*   A10            124894471                                              */
-/*   A11            50477244                                               */
-/*   A12            -2                                                     */
-/*                                                                         */
-/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
-/*                                                                         */
-/*                                                                         */
-/* PARAMETERS:                                                             */
-/*                                                                         */
-/*  X               is the input variable in Q2.30 format                  */
-/*                                                                         */
-/* RETURNS:                                                                */
-/*   The result of the 10x expansion in Q8.24 format                       */
-/*-------------------------------------------------------------------------*/
-#ifdef BUILD_FLOAT
-LVM_FLOAT LVM_Power10(LVM_FLOAT     X)
-{
-    LVM_FLOAT Y,Coefficients[13]={0.999906f,
-                                  2.302475f,
-                                  2.652765f,
-                                  2.035494f,
-                                  1.165667f,
-                                  0.537676f,
-                                  0.213192f,
-                                  0.069603f,
-                                  0.016553f,
-                                  0.004373f,
-                                  0.001817f,
-                                  0.000367f,
-                                  0};
-    Y=LVM_Polynomial((LVM_UINT16)11,
-                     Coefficients,
-                     X);
-    return Y;
-}
-#else
-LVM_INT32 LVM_Power10(LVM_INT32     X)
-{
-    LVM_INT32 Y,Coefficients[13]={  16775636,
-                                        77258249,
-                                       178024032,
-                                       273199333,
-                                       312906284,
-                                       288662365,
-                                       228913700,
-                                       149470921,
-                                        71094558,
-                                        37565524,
-                                        31223618,
-                                        12619311,
-                                     0};
-    Y=LVM_Polynomial((LVM_UINT16)11,
-                        Coefficients,
-                        X);
-    return Y;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Power10.cpp b/media/libeffects/lvm/lib/Common/src/LVM_Power10.cpp
new file mode 100644
index 0000000..ae8e9d1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Power10.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "Filter.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_Power10                                                           */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function calculates 10X using an 11th order polynomial. It uses  */
+/*   the following table of 32-bit integer polynomial coefficients:        */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             67102543                                               */
+/*   A1             309032995                                              */
+/*   A2             712096127                                              */
+/*   A3             1092797331                                             */
+/*   A4             1251625137                                             */
+/*   A5             1154649460                                             */
+/*   A6             915654800                                              */
+/*   A7             597883683                                              */
+/*   A8             284378230                                              */
+/*   A9             150262097                                              */
+/*   A10            124894471                                              */
+/*   A11            50477244                                               */
+/*   A12            -2                                                     */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  X               is the input variable in Q2.30 format                  */
+/*                                                                         */
+/* RETURNS:                                                                */
+/*   The result of the 10x expansion in Q8.24 format                       */
+/*-------------------------------------------------------------------------*/
+LVM_FLOAT LVM_Power10(LVM_FLOAT     X)
+{
+    LVM_FLOAT Y,Coefficients[13]={0.999906f,
+                                  2.302475f,
+                                  2.652765f,
+                                  2.035494f,
+                                  1.165667f,
+                                  0.537676f,
+                                  0.213192f,
+                                  0.069603f,
+                                  0.016553f,
+                                  0.004373f,
+                                  0.001817f,
+                                  0.000367f,
+                                  0};
+    Y=LVM_Polynomial((LVM_UINT16)11,
+                     Coefficients,
+                     X);
+    return Y;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/LVM_Timer.c
rename to media/libeffects/lvm/lib/Common/src/LVM_Timer.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
deleted file mode 100644
index a935cfe..0000000
--- a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES                                                                       */
-/****************************************************************************************/
-
-#include "LVM_Timer.h"
-#include "LVM_Timer_Private.h"
-#include "LVM_Macros.h"
-
-/****************************************************************************************/
-/*  DEFINITIONS                                                                         */
-/****************************************************************************************/
-
-#define OneOverThousandInQ24 16777
-
-/****************************************************************************************/
-/*  INIT FUNCTION                                                                       */
-/****************************************************************************************/
-
-void LVM_Timer_Init (   LVM_Timer_Instance_t       *pInstance,
-                        LVM_Timer_Params_t         *pParams     ){
-
-    LVM_Timer_Instance_Private_t *pInstancePr;
-    pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
-
-    pInstancePr->CallBackParam     = pParams->CallBackParam;
-    pInstancePr->pCallBackParams   = pParams->pCallBackParams;
-    pInstancePr->pCallbackInstance = pParams->pCallbackInstance;
-    pInstancePr->pCallBack         = pParams->pCallBack;
-    pInstancePr->TimerArmed        = 1;
-
-    MUL32x16INTO32(pParams->SamplingRate,OneOverThousandInQ24,pInstancePr->RemainingTimeInSamples,16);  /* (Q0 * Q24) >>16 into Q8*/
-    MUL32x16INTO32(pInstancePr->RemainingTimeInSamples,pParams->TimeInMs,pInstancePr->RemainingTimeInSamples,8);  /* (Q8 * Q0) >>8 into Q0*/
-}
-
-/****************************************************************************************/
-/*  END OF FILE                                                                         */
-/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.cpp b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.cpp
new file mode 100644
index 0000000..3015057
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES                                                                       */
+/****************************************************************************************/
+
+#include "LVM_Timer.h"
+#include "LVM_Timer_Private.h"
+#include "LVM_Macros.h"
+
+/****************************************************************************************/
+/*  DEFINITIONS                                                                         */
+/****************************************************************************************/
+
+#define OneOverThousandInQ24 16777
+
+/****************************************************************************************/
+/*  INIT FUNCTION                                                                       */
+/****************************************************************************************/
+
+void LVM_Timer_Init (   LVM_Timer_Instance_t       *pInstance,
+                        LVM_Timer_Params_t         *pParams     ){
+
+    LVM_Timer_Instance_Private_t *pInstancePr;
+    pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
+
+    pInstancePr->CallBackParam     = pParams->CallBackParam;
+    pInstancePr->pCallBackParams   = (LVM_INT32 *)pParams->pCallBackParams;
+    pInstancePr->pCallbackInstance = pParams->pCallbackInstance;
+    pInstancePr->pCallBack         = pParams->pCallBack;
+    pInstancePr->TimerArmed        = 1;
+
+    MUL32x16INTO32(pParams->SamplingRate,OneOverThousandInQ24,pInstancePr->RemainingTimeInSamples,16);  /* (Q0 * Q24) >>16 into Q8*/
+    MUL32x16INTO32(pInstancePr->RemainingTimeInSamples,pParams->TimeInMs,pInstancePr->RemainingTimeInSamples,8);  /* (Q8 * Q0) >>8 into Q0*/
+}
+
+/****************************************************************************************/
+/*  END OF FILE                                                                         */
+/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
index 480944f..a372b82 100644
--- a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
@@ -18,12 +18,6 @@
 #ifndef LVM_TIMER_PRIVATE_H
 #define LVM_TIMER_PRIVATE_H
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 #include "LVM_Types.h"
 
 /****************************************************************************************/
@@ -45,8 +39,4 @@
 /*  END OF HEADER                                                                       */
 /****************************************************************************************/
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif  /* LVM_TIMER_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.c b/media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/LoadConst_16.c
rename to media/libeffects/lvm/lib/Common/src/LoadConst_16.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
deleted file mode 100644
index 9e14c3b..0000000
--- a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION LoadConst_32
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void LoadConst_Float(const LVM_FLOAT   val,
-                     LVM_FLOAT  *dst,
-                     LVM_INT16 n )
-{
-    LVM_INT16 ii;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = val;
-        dst++;
-    }
-
-    return;
-}
-#else
-void LoadConst_32(const LVM_INT32   val,
-                        LVM_INT32  *dst,
-                        LVM_INT16 n )
-{
-    LVM_INT16 ii;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = val;
-        dst++;
-    }
-
-    return;
-}
-#endif
-
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_32.cpp b/media/libeffects/lvm/lib/Common/src/LoadConst_32.cpp
new file mode 100644
index 0000000..c789756
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_32.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LoadConst_32
+***********************************************************************************/
+void LoadConst_Float(const LVM_FLOAT   val,
+                     LVM_FLOAT  *dst,
+                     LVM_INT16 n )
+{
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = val;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
deleted file mode 100644
index 02c906a..0000000
--- a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION  MSTO2I_SAT_16X16
-***********************************************************************************/
-
-void MSTo2i_Sat_16x16(const LVM_INT16  *srcM,
-                      const LVM_INT16  *srcS,
-                      LVM_INT16  *dst,
-                      LVM_INT16  n )
-{
-    LVM_INT32 temp,mVal,sVal;
-    LVM_INT16 ii;
-
-
-    for (ii = n; ii != 0; ii--)
-    {
-        mVal=(LVM_INT32)*srcM;
-        srcM++;
-
-        sVal=(LVM_INT32)*srcS;
-        srcS++;
-
-        temp = mVal + sVal;
-
-        if (temp > 0x00007FFF)
-        {
-            *dst = 0x7FFF;
-        }
-        else if (temp < -0x00008000)
-        {
-            *dst = - 0x8000;
-        }
-        else
-        {
-            *dst = (LVM_INT16)temp;
-        }
-        dst++;
-
-        temp = mVal - sVal;
-
-        if (temp > 0x00007FFF)
-        {
-            *dst = 0x7FFF;
-        }
-        else if (temp < -0x00008000)
-        {
-            *dst = - 0x8000;
-        }
-        else
-        {
-            *dst = (LVM_INT16)temp;
-        }
-        dst++;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void MSTo2i_Sat_Float(const LVM_FLOAT  *srcM,
-                      const LVM_FLOAT  *srcS,
-                      LVM_FLOAT  *dst,
-                      LVM_INT16  n )
-{
-    LVM_FLOAT temp,mVal,sVal;
-    LVM_INT16 ii;
-
-
-    for (ii = n; ii != 0; ii--)
-    {
-        mVal = (LVM_FLOAT)*srcM;
-        srcM++;
-
-        sVal = (LVM_FLOAT)*srcS;
-        srcS++;
-
-        temp = mVal + sVal;
-
-        if (temp > 1.0f)
-        {
-            *dst = 1.0f;
-        }
-        else if (temp < -1.0f)
-        {
-            *dst = -1.0f;
-        }
-        else
-        {
-            *dst = (LVM_FLOAT)temp;
-        }
-        dst++;
-
-        temp = mVal - sVal;
-
-        if (temp > 1.0f)
-        {
-            *dst = 1.0f;
-        }
-        else if (temp < -1.0f)
-        {
-            *dst = - 1.0f;
-        }
-        else
-        {
-            *dst = (LVM_FLOAT)temp;
-        }
-        dst++;
-    }
-
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
new file mode 100644
index 0000000..1ea765a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION  MSTO2I_SAT_16X16
+***********************************************************************************/
+
+void MSTo2i_Sat_16x16(const LVM_INT16  *srcM,
+                      const LVM_INT16  *srcS,
+                      LVM_INT16  *dst,
+                      LVM_INT16  n )
+{
+    LVM_INT32 temp,mVal,sVal;
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        mVal=(LVM_INT32)*srcM;
+        srcM++;
+
+        sVal=(LVM_INT32)*srcS;
+        srcS++;
+
+        temp = mVal + sVal;
+
+        if (temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)temp;
+        }
+        dst++;
+
+        temp = mVal - sVal;
+
+        if (temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+void MSTo2i_Sat_Float(const LVM_FLOAT  *srcM,
+                      const LVM_FLOAT  *srcS,
+                      LVM_FLOAT  *dst,
+                      LVM_INT16  n )
+{
+    LVM_FLOAT temp,mVal,sVal;
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        mVal = (LVM_FLOAT)*srcM;
+        srcM++;
+
+        sVal = (LVM_FLOAT)*srcS;
+        srcS++;
+
+        temp = mVal + sVal;
+
+        if (temp > 1.0f)
+        {
+            *dst = 1.0f;
+        }
+        else if (temp < -1.0f)
+        {
+            *dst = -1.0f;
+        }
+        else
+        {
+            *dst = (LVM_FLOAT)temp;
+        }
+        dst++;
+
+        temp = mVal - sVal;
+
+        if (temp > 1.0f)
+        {
+            *dst = 1.0f;
+        }
+        else if (temp < -1.0f)
+        {
+            *dst = - 1.0f;
+        }
+        else
+        {
+            *dst = (LVM_FLOAT)temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
deleted file mode 100644
index ef04ae8..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/**********************************************************************************
-
-     %created_by:    sra % (CM/S)
-     %name:          Mac3s_Sat_16x16.c % (CM/S)
-     %version:       1 % (CM/S)
-     %date_created:  Fri Nov 13 12:07:13 2009 % (CM/S)
-
-***********************************************************************************/
-
-/**********************************************************************************
-   INCLUDE FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION Mac3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_16x16( const LVM_INT16 *src,
-                     const LVM_INT16 val,
-                     LVM_INT16 *dst,
-                     LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_INT16 srcval;
-    LVM_INT32 Temp,dInVal;
-
-
-    for (ii = n; ii != 0; ii--)
-    {
-        srcval=*src;
-        src++;
-
-        Temp = (srcval *val)>>15;
-
-        dInVal  = (LVM_INT32)*dst;
-
-        Temp = Temp + dInVal;
-
-        if (Temp > 0x00007FFF)
-        {
-            *dst = 0x7FFF;
-        }
-        else if (Temp < -0x00008000)
-        {
-            *dst = - 0x8000;
-        }
-        else
-        {
-            *dst = (LVM_INT16)Temp;
-        }
-
-        dst++;
-    }
-
-    return;
-}
-
-/**********************************************************************************/
-
-
-
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
new file mode 100644
index 0000000..6584251
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     %created_by:    sra % (CM/S)
+     %name:          Mac3s_Sat_16x16.c % (CM/S)
+     %version:       1 % (CM/S)
+     %date_created:  Fri Nov 13 12:07:13 2009 % (CM/S)
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION Mac3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_16x16( const LVM_INT16 *src,
+                     const LVM_INT16 val,
+                     LVM_INT16 *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT16 srcval;
+    LVM_INT32 Temp,dInVal;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        Temp = (srcval *val)>>15;
+
+        dInVal  = (LVM_INT32)*dst;
+
+        Temp = Temp + dInVal;
+
+        if (Temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (Temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)Temp;
+        }
+
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
deleted file mode 100644
index 17fd833..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-   FUNCTION MAC3S_16X16
-***********************************************************************************/
-
-void Mac3s_Sat_32x16(  const LVM_INT32 *src,
-                     const LVM_INT16 val,
-                     LVM_INT32 *dst,
-                     LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_INT32 srcval,temp, dInVal, dOutVal;
-
-
-    for (ii = n; ii != 0; ii--)
-    {
-        srcval=*src;
-        src++;
-
-        MUL32x16INTO32(srcval,val,temp,15)
-
-            dInVal  = *dst;
-        dOutVal = temp + dInVal;
-
-
-        if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31)!=0)     /* overflow / underflow */
-        {
-            if(temp<0)
-            {
-                dOutVal=0x80000000L;
-            }
-            else
-            {
-                dOutVal=0x7FFFFFFFL;
-            }
-        }
-
-        *dst = dOutVal;
-        dst++;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void Mac3s_Sat_Float(const LVM_FLOAT *src,
-                     const LVM_FLOAT val,
-                     LVM_FLOAT *dst,
-                     LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_FLOAT srcval;
-    LVM_FLOAT Temp,dInVal;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        srcval = *src;
-        src++;
-
-        Temp = srcval * val;
-
-        dInVal  = (LVM_FLOAT)*dst;
-        Temp = Temp + dInVal;
-
-        if (Temp > 1.000000f)
-        {
-            *dst = 1.000000f;
-        }
-        else if (Temp < -1.000000f)
-        {
-            *dst = -1.000000f;
-        }
-        else
-        {
-            *dst = Temp;
-        }
-        dst++;
-    }
-
-    return;
-}
-#endif
-/**********************************************************************************/
-
-
-
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
new file mode 100644
index 0000000..5d5564f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION MAC3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_32x16(  const LVM_INT32 *src,
+                     const LVM_INT16 val,
+                     LVM_INT32 *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 srcval,temp, dInVal, dOutVal;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        MUL32x16INTO32(srcval,val,temp,15)
+
+            dInVal  = *dst;
+        dOutVal = temp + dInVal;
+
+        if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31)!=0)     /* overflow / underflow */
+        {
+            if(temp<0)
+            {
+                dOutVal=0x80000000L;
+            }
+            else
+            {
+                dOutVal=0x7FFFFFFFL;
+            }
+        }
+
+        *dst = dOutVal;
+        dst++;
+    }
+
+    return;
+}
+void Mac3s_Sat_Float(const LVM_FLOAT *src,
+                     const LVM_FLOAT val,
+                     LVM_FLOAT *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT srcval;
+    LVM_FLOAT Temp,dInVal;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval = *src;
+        src++;
+
+        Temp = srcval * val;
+
+        dInVal  = (LVM_FLOAT)*dst;
+        Temp = Temp + dInVal;
+
+        if (Temp > 1.000000f)
+        {
+            *dst = 1.000000f;
+        }
+        else if (Temp < -1.000000f)
+        {
+            *dst = -1.000000f;
+        }
+        else
+        {
+            *dst = Temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
deleted file mode 100644
index 16e367b..0000000
--- a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   DEFINITIONS
-***********************************************************************************/
-
-#define TRUE          1
-#define FALSE         0
-
-/**********************************************************************************
-   FUNCTION MIXINSOFT_D32C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void MixInSoft_D32C31_SAT( Mix_1St_Cll_FLOAT_t        *pInstance,
-                           const LVM_FLOAT      *src,
-                           LVM_FLOAT      *dst,
-                           LVM_INT16      n)
-{
-    char HardMixing = TRUE;
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Alpha == 0){
-            pInstance->Current = pInstance->Target;
-        }else if ((pInstance->Current-pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
-                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
-            if ((pInstance->Target) == 1.0f)
-                Add2_Sat_Float(src, dst, n);
-            else{
-                Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
-                pInstance->Current = pInstance->Target; /* In case the core function would \
-                                                           have changed the Current value */
-            }
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-    /* Call back before the hard mixing, because in this case, hard mixing makes
-       use of the core soft mix function which can change the Current value!      */
-
-    if (pInstance->CallbackSet){
-        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
-            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            pInstance->CallbackSet = FALSE;
-            if (pInstance->pCallBack != 0){
-                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
-                                          pInstance->pGeneralPurpose,
-                                          pInstance->CallbackParam );
-            }
-        }
-    }
-}
-#else
-void MixInSoft_D32C31_SAT( Mix_1St_Cll_t        *pInstance,
-                           const LVM_INT32      *src,
-                                 LVM_INT32      *dst,
-                                 LVM_INT16      n)
-{
-    char HardMixing = TRUE;
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Alpha == 0){
-            pInstance->Current = pInstance->Target;
-        }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
-                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
-            if ((pInstance->Target>>16) == 0x7FFF)
-                Add2_Sat_32x32( src, dst, n );
-            else{
-                Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
-                pInstance->Current = pInstance->Target; /* In case the core function would have changed the Current value */
-            }
-        }
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-    /* Call back before the hard mixing, because in this case, hard mixing makes
-       use of the core soft mix function which can change the Current value!      */
-
-    if (pInstance->CallbackSet){
-        if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
-            (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            pInstance->CallbackSet = FALSE;
-            if (pInstance->pCallBack != 0){
-                (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
-            }
-        }
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.cpp
new file mode 100644
index 0000000..7c7b36f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION MIXINSOFT_D32C31_SAT
+***********************************************************************************/
+void MixInSoft_D32C31_SAT( Mix_1St_Cll_FLOAT_t        *pInstance,
+                           const LVM_FLOAT      *src,
+                           LVM_FLOAT      *dst,
+                           LVM_INT16      n)
+{
+    char HardMixing = TRUE;
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current-pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target) == 1.0f)
+                Add2_Sat_Float(src, dst, n);
+            else{
+                Core_MixInSoft_D32C31_SAT(pInstance, src, dst, n);
+                pInstance->Current = pInstance->Target; /* In case the core function would \
+                                                           have changed the Current value */
+            }
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+    /* Call back before the hard mixing, because in this case, hard mixing makes
+       use of the core soft mix function which can change the Current value!      */
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
+                                          pInstance->pGeneralPurpose,
+                                          pInstance->CallbackParam );
+            }
+        }
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
deleted file mode 100644
index 869293b..0000000
--- a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   DEFINITIONS
-***********************************************************************************/
-
-#define TRUE          1
-#define FALSE         0
-
-
-
-/**********************************************************************************
-   FUNCTION MIXSOFT_1ST_D32C31_WRA
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_FLOAT_t       *pInstance,
-                                const LVM_FLOAT     *src,
-                                      LVM_FLOAT     *dst,
-                                      LVM_INT16     n)
-{
-    char HardMixing = TRUE;
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Alpha == 0){
-            pInstance->Current = pInstance->Target;
-        }else if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
-                 (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            Core_MixSoft_1St_D32C31_WRA(pInstance, src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target == 0)
-            LoadConst_Float(0, dst, n);
-        else if ((pInstance->Target) == 1.0f){
-            if (src != dst)
-                Copy_Float((LVM_FLOAT*)src, (LVM_FLOAT*)dst, (LVM_INT16)(n));
-        }
-        else
-            Mult3s_Float(src, pInstance->Current, dst, n);
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (pInstance->CallbackSet){
-        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
-            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
-                                                       Make them equal. */
-            pInstance->CallbackSet = FALSE;
-            if (pInstance->pCallBack != 0){
-                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
-                                          pInstance->pGeneralPurpose,
-                                          pInstance->CallbackParam );
-            }
-        }
-    }
-}
-#else
-void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_t       *pInstance,
-                                const LVM_INT32     *src,
-                                      LVM_INT32     *dst,
-                                      LVM_INT16     n)
-{
-    char HardMixing = TRUE;
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if (pInstance->Current != pInstance->Target)
-    {
-        if(pInstance->Alpha == 0){
-            pInstance->Current = pInstance->Target;
-        }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
-                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-        }else{
-            /* Soft mixing has to be applied */
-            HardMixing = FALSE;
-            Core_MixSoft_1St_D32C31_WRA( pInstance, src, dst, n);
-        }
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    if (HardMixing){
-        if (pInstance->Target == 0)
-            LoadConst_32(0, dst, n);
-        else if ((pInstance->Target>>16) == 0x7FFF){
-            if (src != dst)
-                Copy_16((LVM_INT16*)src, (LVM_INT16*)dst, (LVM_INT16)(n * 2));
-        }
-        else
-            Mult3s_32x16( src, (LVM_INT16)(pInstance->Current>>16), dst, n );
-    }
-
-    /******************************************************************************
-       CALL BACK
-    *******************************************************************************/
-
-    if (pInstance->CallbackSet){
-        if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
-            (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
-            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
-            pInstance->CallbackSet = FALSE;
-            if (pInstance->pCallBack != 0){
-                (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
-            }
-        }
-    }
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.cpp b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.cpp
new file mode 100644
index 0000000..d3325ec
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n)
+{
+    char HardMixing = TRUE;
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+                 (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixSoft_1St_D32C31_WRA(pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_Float(0, dst, n);
+        else if ((pInstance->Target) == 1.0f){
+            if (src != dst)
+                Copy_Float((LVM_FLOAT*)src, (LVM_FLOAT*)dst, (LVM_INT16)(n));
+        }
+        else
+            Mult3s_Float(src, pInstance->Current, dst, n);
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current - pInstance->Target < POINT_ZERO_ONE_DB_FLOAT) &&
+            (pInstance->Current - pInstance->Target > -POINT_ZERO_ONE_DB_FLOAT)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+                                                       Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle,
+                                          pInstance->pGeneralPurpose,
+                                          pInstance->CallbackParam );
+            }
+        }
+    }
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
deleted file mode 100644
index 6fc1b92..0000000
--- a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "Mixer_private.h"
-#include "VectorArithmetic.h"
-
-
-/**********************************************************************************
-   FUNCTION MIXSOFT_2ST_D32C31_SAT
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_FLOAT_t       *pInstance,
-                                const LVM_FLOAT     *src1,
-                                const LVM_FLOAT     *src2,
-                                      LVM_FLOAT     *dst,
-                                      LVM_INT16     n)
-{
-
-    if(n <= 0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
-    {
-        MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*)pInstance, src1, dst, n);
-        MixInSoft_D32C31_SAT((void *)&pInstance->Alpha2, /* Cast to void: \
-                                                              no dereferencing in function*/
-                              src2, dst, n);
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    else
-    {
-        if (pInstance->Current1 == 0)
-            MixSoft_1St_D32C31_WRA((void *) &pInstance->Alpha2, /* Cast to void: no \
-                                                             dereferencing in function*/
-                                    src2, dst, n);
-        else if (pInstance->Current2 == 0)
-            MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*) pInstance, src1, dst, n);
-        else
-            Core_MixHard_2St_D32C31_SAT(pInstance, src1, src2, dst, n);
-    }
-}
-#else
-void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_t       *pInstance,
-                                const LVM_INT32     *src1,
-                                const LVM_INT32     *src2,
-                                      LVM_INT32     *dst,
-                                      LVM_INT16     n)
-{
-
-    if(n<=0)    return;
-
-    /******************************************************************************
-       SOFT MIXING
-    *******************************************************************************/
-    if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
-    {
-        MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
-        MixInSoft_D32C31_SAT( (void *) &pInstance->Alpha2,     /* Cast to void: no dereferencing in function*/
-            src2, dst, n);
-    }
-
-    /******************************************************************************
-       HARD MIXING
-    *******************************************************************************/
-
-    else
-    {
-        if (pInstance->Current1 == 0)
-            MixSoft_1St_D32C31_WRA( (void *) &pInstance->Alpha2, /* Cast to void: no dereferencing in function*/
-            src2, dst, n);
-        else if (pInstance->Current2 == 0)
-            MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
-        else
-            Core_MixHard_2St_D32C31_SAT( pInstance, src1, src2, dst, n);
-    }
-}
-#endif
-/**********************************************************************************/
-
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.cpp b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.cpp
new file mode 100644
index 0000000..b002738
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION MIXSOFT_2ST_D32C31_SAT
+***********************************************************************************/
+void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_FLOAT_t       *pInstance,
+                                const LVM_FLOAT     *src1,
+                                const LVM_FLOAT     *src2,
+                                      LVM_FLOAT     *dst,
+                                      LVM_INT16     n)
+{
+
+    if(n <= 0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
+    {
+        MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*)pInstance, src1, dst, n);
+        MixInSoft_D32C31_SAT((Mix_1St_Cll_FLOAT_t *)&pInstance->Alpha2, /* Cast to void: \
+                                                              no dereferencing in function*/
+                              src2, dst, n);
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    else
+    {
+        if (pInstance->Current1 == 0)
+            MixSoft_1St_D32C31_WRA(
+                    (Mix_1St_Cll_FLOAT_t *) &pInstance->Alpha2, /* Cast to void: no \
+                                                             dereferencing in function*/
+                                    src2, dst, n);
+        else if (pInstance->Current2 == 0)
+            MixSoft_1St_D32C31_WRA((Mix_1St_Cll_FLOAT_t*) pInstance, src1, dst, n);
+        else
+            Core_MixHard_2St_D32C31_SAT(pInstance, src1, src2, dst, n);
+    }
+}
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/Mixer_private.h b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
index 00d55ed..1d653bb 100644
--- a/media/libeffects/lvm/lib/Common/src/Mixer_private.h
+++ b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
@@ -26,10 +26,8 @@
 
 #define POINT_ZERO_ONE_DB 2473805 /* 0.01 dB on a full scale signal = (10^(0.01/20) -1) * 2^31 */
 
-#ifdef BUILD_FLOAT
 #define POINT_ZERO_ONE_DB_FLOAT 0.001152 /* 0.01 dB on a full scale \
                                             signal = (10^(0.01/20) -1) * 2^31 */
-#endif
 /**********************************************************************************
    DEFINITIONS
 ***********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
rename to media/libeffects/lvm/lib/Common/src/MonoTo2I_16.cpp
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
deleted file mode 100644
index 796a15c..0000000
--- a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION MonoTo2I_32
-***********************************************************************************/
-
-void MonoTo2I_32( const LVM_INT32  *src,
-                 LVM_INT32  *dst,
-                 LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    src += (n-1);
-    dst += ((n*2)-1);
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = *src;
-        dst--;
-
-        *dst = *src;
-        dst--;
-        src--;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void MonoTo2I_Float( const LVM_FLOAT  *src,
-                     LVM_FLOAT  *dst,
-                     LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    src += (n - 1);
-    dst += ((n * 2) - 1);
-
-    for (ii = n; ii != 0; ii--)
-    {
-        *dst = *src;
-        dst--;
-
-        *dst = *src;
-        dst--;
-        src--;
-    }
-
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
new file mode 100644
index 0000000..603d1fc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION MonoTo2I_32
+***********************************************************************************/
+
+void MonoTo2I_32( const LVM_INT32  *src,
+                 LVM_INT32  *dst,
+                 LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    src += (n-1);
+    dst += ((n*2)-1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *src;
+        dst--;
+
+        *dst = *src;
+        dst--;
+        src--;
+    }
+
+    return;
+}
+void MonoTo2I_Float( const LVM_FLOAT  *src,
+                     LVM_FLOAT  *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    src += (n - 1);
+    dst += ((n * 2) - 1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *src;
+        dst--;
+
+        *dst = *src;
+        dst--;
+        src--;
+    }
+
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
deleted file mode 100644
index c758560..0000000
--- a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-#include "LVM_Macros.h"
-
-/**********************************************************************************
-FUNCTION MULT3S_16X16
-***********************************************************************************/
-
-void Mult3s_32x16( const LVM_INT32 *src,
-                  const LVM_INT16 val,
-                  LVM_INT32 *dst,
-                  LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_INT32 srcval,temp;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        srcval=*src;
-        src++;
-
-        MUL32x16INTO32(srcval,val,temp,15)
-
-        *dst = temp;
-        dst++;
-    }
-
-    return;
-}
-#ifdef BUILD_FLOAT
-void Mult3s_Float( const LVM_FLOAT *src,
-                   const LVM_FLOAT val,
-                   LVM_FLOAT *dst,
-                   LVM_INT16 n)
-{
-    LVM_INT16 ii;
-    LVM_FLOAT temp;
-
-    for (ii = n; ii != 0; ii--)
-    {
-        temp = (*src) * val;
-        src++;
-        *dst = temp;
-        dst++;
-    }
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
new file mode 100644
index 0000000..370c39a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+FUNCTION MULT3S_16X16
+***********************************************************************************/
+
+void Mult3s_32x16( const LVM_INT32 *src,
+                  const LVM_INT16 val,
+                  LVM_INT32 *dst,
+                  LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 srcval,temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        MUL32x16INTO32(srcval,val,temp,15)
+
+        *dst = temp;
+        dst++;
+    }
+
+    return;
+}
+void Mult3s_Float( const LVM_FLOAT *src,
+                   const LVM_FLOAT val,
+                   LVM_FLOAT *dst,
+                   LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_FLOAT temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        temp = (*src) * val;
+        src++;
+        *dst = temp;
+        dst++;
+    }
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
deleted file mode 100644
index 5156edc..0000000
--- a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "CompLim_private.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 NonLinComp_D16                                             */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Non-linear compression by companding. The function works on a sample by sample      */
-/*  basis by increasing the level near the zero crossing. This gives a ttrade-off       */
-/*  between THD and compression. It uses the equation:                                  */
-/*                                                                                      */
-/*        Output = Input + K * (Input - Input^2)        if Input >  0                   */
-/*               = Input + K * (Input + Input^2)      if Input <= 0                     */
-/*                                                                                      */
-/*    The value of K controls the amount of compression and as a side effect the amount */
-/*  distortion introduced. The amount of compression is signal dependent and the values */
-/*  given below are approximate.                                                        */
-/*                                                                                      */
-/*        Gain (fractional)  Gain (integer)    Compression          Pk-Pk THD           */
-/*            1.0                 32767            +6dB            16dB                 */
-/*            0.78                25559            +5dB            19dB                 */
-/*            0.6                 19661            +4dB            21dB                 */
-/*            0.41                13435            +3dB            24dB                 */
-/*            0.26                 8520            +2dB            28dB                 */
-/*            0.12                 3932            +1dB            34dB                 */
-/*            0.0                     0            +0dB            98dB                 */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*    Gain            -    compression control parameter                                */
-/*    pDataIn         -    pointer to the input data buffer                             */
-/*    pDataOut        -    pointer to the output data buffer                            */
-/*    BlockLength     -    number of samples to process                                 */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*    None                                                                              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-
-void NonLinComp_D16(LVM_INT16        Gain,
-                      LVM_INT16        *pDataIn,
-                    LVM_INT16        *pDataOut,
-                    LVM_INT32        BlockLength)
-{
-
-    LVM_INT16            Sample;                    /* Input samples */
-    LVM_INT32            SampleNo;                /* Sample index */
-    LVM_INT16            Temp;
-
-
-    /*
-     * Process a block of samples
-     */
-    for(SampleNo = 0; SampleNo<BlockLength; SampleNo++)
-    {
-
-        /*
-         * Read the input
-         */
-        Sample = *pDataIn;
-        pDataIn++;
-
-
-        /*
-         * Apply the compander, this compresses the signal at the expense of
-         * harmonic distortion. The amount of compression is control by the
-         * gain factor
-         */
-        if ((LVM_INT32)Sample != -32768)
-        {
-            Temp = (LVM_INT16)((Sample * Sample) >> 15);
-            if(Sample >0)
-            {
-                Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
-            }
-            else
-            {
-                Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
-            }
-        }
-
-
-        /*
-         * Save the output
-         */
-        *pDataOut = Sample;
-        pDataOut++;
-
-
-    }
-
-}
-#ifdef BUILD_FLOAT
-void NonLinComp_Float(LVM_FLOAT        Gain,
-                      LVM_FLOAT        *pDataIn,
-                      LVM_FLOAT        *pDataOut,
-                      LVM_INT32        BlockLength)
-{
-
-    LVM_FLOAT            Sample;                    /* Input samples */
-    LVM_INT32            SampleNo;                /* Sample index */
-    LVM_FLOAT            Temp;
-
-
-    /*
-     * Process a block of samples
-     */
-    for(SampleNo = 0; SampleNo < BlockLength; SampleNo++)
-    {
-        /*
-         * Read the input
-         */
-        Sample = *pDataIn;
-        pDataIn++;
-
-
-        /*
-         * Apply the compander, this compresses the signal at the expense of
-         * harmonic distortion. The amount of compression is control by the
-         * gain factor
-         */
-        if (Sample != -1.0f)
-        {
-            Temp = ((Sample * Sample));
-            if(Sample > 0)
-            {
-                Sample = (Sample + ((Gain * (Sample - Temp)) ));
-            }
-            else
-            {
-                Sample = (Sample + ((Gain * (Sample + Temp)) ));
-            }
-        }
-
-
-        /*
-         * Save the output
-         */
-        *pDataOut = Sample;
-        pDataOut++;
-    }
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
new file mode 100644
index 0000000..36d1149
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "CompLim_private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 NonLinComp_D16                                             */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Non-linear compression by companding. The function works on a sample by sample      */
+/*  basis by increasing the level near the zero crossing. This gives a ttrade-off       */
+/*  between THD and compression. It uses the equation:                                  */
+/*                                                                                      */
+/*        Output = Input + K * (Input - Input^2)        if Input >  0                   */
+/*               = Input + K * (Input + Input^2)      if Input <= 0                     */
+/*                                                                                      */
+/*    The value of K controls the amount of compression and as a side effect the amount */
+/*  distortion introduced. The amount of compression is signal dependent and the values */
+/*  given below are approximate.                                                        */
+/*                                                                                      */
+/*        Gain (fractional)  Gain (integer)    Compression          Pk-Pk THD           */
+/*            1.0                 32767            +6dB            16dB                 */
+/*            0.78                25559            +5dB            19dB                 */
+/*            0.6                 19661            +4dB            21dB                 */
+/*            0.41                13435            +3dB            24dB                 */
+/*            0.26                 8520            +2dB            28dB                 */
+/*            0.12                 3932            +1dB            34dB                 */
+/*            0.0                     0            +0dB            98dB                 */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    Gain            -    compression control parameter                                */
+/*    pDataIn         -    pointer to the input data buffer                             */
+/*    pDataOut        -    pointer to the output data buffer                            */
+/*    BlockLength     -    number of samples to process                                 */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void NonLinComp_D16(LVM_INT16        Gain,
+                      LVM_INT16        *pDataIn,
+                    LVM_INT16        *pDataOut,
+                    LVM_INT32        BlockLength)
+{
+
+    LVM_INT16            Sample;                    /* Input samples */
+    LVM_INT32            SampleNo;                /* Sample index */
+    LVM_INT16            Temp;
+
+    /*
+     * Process a block of samples
+     */
+    for(SampleNo = 0; SampleNo<BlockLength; SampleNo++)
+    {
+
+        /*
+         * Read the input
+         */
+        Sample = *pDataIn;
+        pDataIn++;
+
+        /*
+         * Apply the compander, this compresses the signal at the expense of
+         * harmonic distortion. The amount of compression is control by the
+         * gain factor
+         */
+        if ((LVM_INT32)Sample != -32768)
+        {
+            Temp = (LVM_INT16)((Sample * Sample) >> 15);
+            if(Sample >0)
+            {
+                Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
+            }
+            else
+            {
+                Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
+            }
+        }
+
+        /*
+         * Save the output
+         */
+        *pDataOut = Sample;
+        pDataOut++;
+
+    }
+
+}
+void NonLinComp_Float(LVM_FLOAT        Gain,
+                      LVM_FLOAT        *pDataIn,
+                      LVM_FLOAT        *pDataOut,
+                      LVM_INT32        BlockLength)
+{
+
+    LVM_FLOAT            Sample;                    /* Input samples */
+    LVM_INT32            SampleNo;                /* Sample index */
+    LVM_FLOAT            Temp;
+
+    /*
+     * Process a block of samples
+     */
+    for(SampleNo = 0; SampleNo < BlockLength; SampleNo++)
+    {
+        /*
+         * Read the input
+         */
+        Sample = *pDataIn;
+        pDataIn++;
+
+        /*
+         * Apply the compander, this compresses the signal at the expense of
+         * harmonic distortion. The amount of compression is control by the
+         * gain factor
+         */
+        if (Sample != -1.0f)
+        {
+            Temp = ((Sample * Sample));
+            if(Sample > 0)
+            {
+                Sample = (Sample + ((Gain * (Sample - Temp)) ));
+            }
+            else
+            {
+                Sample = (Sample + ((Gain * (Sample + Temp)) ));
+            }
+        }
+
+        /*
+         * Save the output
+         */
+        *pDataOut = Sample;
+        pDataOut++;
+    }
+}
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
deleted file mode 100644
index 6c8b2db..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q14 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-#ifdef BUILD_FLOAT
-void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
-                                     LVM_FLOAT               *pDataIn,
-                                     LVM_FLOAT               *pDataOut,
-                                     LVM_INT16               NrSamples)
-    {
-        LVM_FLOAT ynL,ynR,ynLO,ynRO,templ;
-        LVM_INT16 ii;
-        PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL= (A0  * (x(n)L - x(n-2)L  ) )*/
-            templ = (*pDataIn) - pBiquadState->pDelays[2];
-            ynL = templ * pBiquadState->coefs[0];
-
-            /* ynL+= ((-B2  * y(n-2)L  )) */
-            templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
-            ynL += templ;
-
-            /* ynL+= ((-B1 * y(n-1)L  ) ) */
-            templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
-            ynL += templ;
-
-            /* ynLO= ((Gain * ynL )) */
-            ynLO = ynL * pBiquadState->coefs[3];
-
-            /* ynLO=( ynLO + x(n)L  )*/
-            ynLO += (*pDataIn);
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR= (A0  * (x(n)R  - x(n-2)R  ) ) */
-            templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
-            ynR = templ * pBiquadState->coefs[0];
-
-            /* ynR+= ((-B2  * y(n-2)R  ) )  */
-            templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
-            ynR += templ;
-
-            /* ynR+= ((-B1  * y(n-1)R  ) )   */
-            templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
-            ynR += templ;
-
-            /* ynRO= ((Gain  * ynR )) */
-            ynRO = ynR * pBiquadState->coefs[3];
-
-            /* ynRO=( ynRO + x(n)R  )*/
-            ynRO += (*(pDataIn+1));
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
-            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
-            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
-            pDataIn++;
-            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut = ynLO; /* Write Left output*/
-            pDataOut++;
-            *pDataOut = ynRO; /* Write Right ouput*/
-            pDataOut++;
-
-        }
-
-    }
-
-#ifdef SUPPORT_MC
-/**************************************************************************
-DELAYS-
-pBiquadState->pDelays[0] to
-pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
-
-pBiquadState->pDelays[NrChannels] to
-pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
-
-pBiquadState->pDelays[2*NrChannels] to
-pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
-
-pBiquadState->pDelays[3*NrChannels] to
-pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
-***************************************************************************/
-
-void PK_Mc_D32F32C14G11_TRC_WRA_01 (Biquad_FLOAT_Instance_t       *pInstance,
-                                    LVM_FLOAT               *pDataIn,
-                                    LVM_FLOAT               *pDataOut,
-                                    LVM_INT16               NrFrames,
-                                    LVM_INT16               NrChannels)
-    {
-        LVM_FLOAT yn, ynO, temp;
-        LVM_INT16 ii, jj;
-        PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
-
-         for (ii = NrFrames; ii != 0; ii--)
-         {
-
-            for (jj = 0; jj < NrChannels; jj++)
-            {
-                /**************************************************************************
-                                PROCESSING OF THE jj CHANNEL
-                ***************************************************************************/
-                /* yn= (A0  * (x(n) - x(n-2)))*/
-                temp = (*pDataIn) - pBiquadState->pDelays[NrChannels + jj];
-                yn = temp * pBiquadState->coefs[0];
-
-                /* yn+= ((-B2  * y(n-2))) */
-                temp = pBiquadState->pDelays[NrChannels*3 + jj] * pBiquadState->coefs[1];
-                yn += temp;
-
-                /* yn+= ((-B1 * y(n-1))) */
-                temp = pBiquadState->pDelays[NrChannels*2 + jj] * pBiquadState->coefs[2];
-                yn += temp;
-
-                /* ynO= ((Gain * yn)) */
-                ynO = yn * pBiquadState->coefs[3];
-
-                /* ynO=(ynO + x(n))*/
-                ynO += (*pDataIn);
-
-                /**************************************************************************
-                                UPDATING THE DELAYS
-                ***************************************************************************/
-                pBiquadState->pDelays[NrChannels * 3 + jj] =
-                    pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
-                pBiquadState->pDelays[NrChannels * 1 + jj] =
-                    pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
-                pBiquadState->pDelays[NrChannels * 2 + jj] = yn; /* Update y(n-1) */
-                pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
-                pDataIn++;
-
-                /**************************************************************************
-                                WRITING THE OUTPUT
-                ***************************************************************************/
-                *pDataOut = ynO; /* Write output*/
-                pDataOut++;
-            }
-        }
-
-    }
-#endif
-#else
-void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                     LVM_INT32               *pDataIn,
-                                     LVM_INT32               *pDataOut,
-                                     LVM_INT16               NrSamples)
-    {
-        LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14)  in Q0*/
-            templ=(*pDataIn)-pBiquadState->pDelays[2];
-            MUL32x16INTO32(templ,pBiquadState->coefs[0],ynL,14)
-
-            /* ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) >>14) in Q0*/
-            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,14)
-            ynL+=templ;
-
-            /* ynL+= ((-B1 (Q14) * y(n-1)L (Q0) ) >>14) in Q0 */
-            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,14)
-            ynL+=templ;
-
-            /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
-            MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
-
-            /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
-            ynLO+= (*pDataIn);
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR= (A0 (Q14) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>14)   in Q0*/
-            templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
-            MUL32x16INTO32(templ,pBiquadState->coefs[0],ynR,14)
-
-            /* ynR+= ((-B2 (Q14) * y(n-2)R (Q0) ) >>14)  in Q0*/
-            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,14)
-            ynR+=templ;
-
-            /* ynR+= ((-B1 (Q14) * y(n-1)R (Q0) ) >>14)  in Q0 */
-            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,14)
-            ynR+=templ;
-
-            /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
-            MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
-
-            /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
-            ynRO+= (*(pDataIn+1));
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
-            pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
-            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=ynLO; /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=ynRO; /* Write Right ouput in Q0*/
-            pDataOut++;
-
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
new file mode 100644
index 0000000..3f62f99
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_FLOAT_Instance_t       *pInstance,
+                                     LVM_FLOAT               *pDataIn,
+                                     LVM_FLOAT               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_FLOAT ynL,ynR,ynLO,ynRO,templ;
+        LVM_INT16 ii;
+        PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= (A0  * (x(n)L - x(n-2)L  ) )*/
+            templ = (*pDataIn) - pBiquadState->pDelays[2];
+            ynL = templ * pBiquadState->coefs[0];
+
+            /* ynL+= ((-B2  * y(n-2)L  )) */
+            templ = pBiquadState->pDelays[6] * pBiquadState->coefs[1];
+            ynL += templ;
+
+            /* ynL+= ((-B1 * y(n-1)L  ) ) */
+            templ = pBiquadState->pDelays[4] * pBiquadState->coefs[2];
+            ynL += templ;
+
+            /* ynLO= ((Gain * ynL )) */
+            ynLO = ynL * pBiquadState->coefs[3];
+
+            /* ynLO=( ynLO + x(n)L  )*/
+            ynLO += (*pDataIn);
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= (A0  * (x(n)R  - x(n-2)R  ) ) */
+            templ = (*(pDataIn + 1)) - pBiquadState->pDelays[3];
+            ynR = templ * pBiquadState->coefs[0];
+
+            /* ynR+= ((-B2  * y(n-2)R  ) )  */
+            templ = pBiquadState->pDelays[7] * pBiquadState->coefs[1];
+            ynR += templ;
+
+            /* ynR+= ((-B1  * y(n-1)R  ) )   */
+            templ = pBiquadState->pDelays[5] * pBiquadState->coefs[2];
+            ynR += templ;
+
+            /* ynRO= ((Gain  * ynR )) */
+            ynRO = ynR * pBiquadState->coefs[3];
+
+            /* ynRO=( ynRO + x(n)R  )*/
+            ynRO += (*(pDataIn+1));
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7] = pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6] = pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3] = pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2] = pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5] = ynR; /* Update y(n-1)R */
+            pBiquadState->pDelays[4] = ynL; /* Update y(n-1)L */
+            pBiquadState->pDelays[0] = (*pDataIn); /* Update x(n-1)L */
+            pDataIn++;
+            pBiquadState->pDelays[1] = (*pDataIn); /* Update x(n-1)R */
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut = ynLO; /* Write Left output*/
+            pDataOut++;
+            *pDataOut = ynRO; /* Write Right ouput*/
+            pDataOut++;
+
+        }
+
+    }
+
+#ifdef SUPPORT_MC
+/**************************************************************************
+DELAYS-
+pBiquadState->pDelays[0] to
+pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
+
+pBiquadState->pDelays[NrChannels] to
+pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
+
+pBiquadState->pDelays[2*NrChannels] to
+pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
+
+pBiquadState->pDelays[3*NrChannels] to
+pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
+***************************************************************************/
+
+void PK_Mc_D32F32C14G11_TRC_WRA_01 (Biquad_FLOAT_Instance_t       *pInstance,
+                                    LVM_FLOAT               *pDataIn,
+                                    LVM_FLOAT               *pDataOut,
+                                    LVM_INT16               NrFrames,
+                                    LVM_INT16               NrChannels)
+    {
+        LVM_FLOAT yn, ynO, temp;
+        LVM_INT16 ii, jj;
+        PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+
+         for (ii = NrFrames; ii != 0; ii--)
+         {
+
+            for (jj = 0; jj < NrChannels; jj++)
+            {
+                /**************************************************************************
+                                PROCESSING OF THE jj CHANNEL
+                ***************************************************************************/
+                /* yn= (A0  * (x(n) - x(n-2)))*/
+                temp = (*pDataIn) - pBiquadState->pDelays[NrChannels + jj];
+                yn = temp * pBiquadState->coefs[0];
+
+                /* yn+= ((-B2  * y(n-2))) */
+                temp = pBiquadState->pDelays[NrChannels*3 + jj] * pBiquadState->coefs[1];
+                yn += temp;
+
+                /* yn+= ((-B1 * y(n-1))) */
+                temp = pBiquadState->pDelays[NrChannels*2 + jj] * pBiquadState->coefs[2];
+                yn += temp;
+
+                /* ynO= ((Gain * yn)) */
+                ynO = yn * pBiquadState->coefs[3];
+
+                /* ynO=(ynO + x(n))*/
+                ynO += (*pDataIn);
+
+                /**************************************************************************
+                                UPDATING THE DELAYS
+                ***************************************************************************/
+                pBiquadState->pDelays[NrChannels * 3 + jj] =
+                    pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
+                pBiquadState->pDelays[NrChannels * 1 + jj] =
+                    pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
+                pBiquadState->pDelays[NrChannels * 2 + jj] = yn; /* Update y(n-1) */
+                pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
+                pDataIn++;
+
+                /**************************************************************************
+                                WRITING THE OUTPUT
+                ***************************************************************************/
+                *pDataOut = ynO; /* Write output*/
+                pDataOut++;
+            }
+        }
+
+    }
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
deleted file mode 100644
index f705cbf..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
-#include "LVM_Macros.h"
-
-/**************************************************************************
- ASSUMPTIONS:
- COEFS-
- pBiquadState->coefs[0] is A0,
- pBiquadState->coefs[1] is -B2,
- pBiquadState->coefs[2] is -B1, these are in Q30 format
- pBiquadState->coefs[3] is Gain, in Q11 format
-
-
- DELAYS-
- pBiquadState->pDelays[0] is x(n-1)L in Q0 format
- pBiquadState->pDelays[1] is x(n-1)R in Q0 format
- pBiquadState->pDelays[2] is x(n-2)L in Q0 format
- pBiquadState->pDelays[3] is x(n-2)R in Q0 format
- pBiquadState->pDelays[4] is y(n-1)L in Q0 format
- pBiquadState->pDelays[5] is y(n-1)R in Q0 format
- pBiquadState->pDelays[6] is y(n-2)L in Q0 format
- pBiquadState->pDelays[7] is y(n-2)R in Q0 format
-***************************************************************************/
-#ifndef BUILD_FLOAT
-void PK_2I_D32F32C30G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
-                                     LVM_INT32               *pDataIn,
-                                     LVM_INT32               *pDataOut,
-                                     LVM_INT16               NrSamples)
-    {
-        LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
-        LVM_INT16 ii;
-        PFilter_State pBiquadState = (PFilter_State) pInstance;
-
-         for (ii = NrSamples; ii != 0; ii--)
-         {
-
-
-            /**************************************************************************
-                            PROCESSING OF THE LEFT CHANNEL
-            ***************************************************************************/
-            /* ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30)  in Q0*/
-            templ=(*pDataIn)-pBiquadState->pDelays[2];
-            MUL32x32INTO32(templ,pBiquadState->coefs[0],ynL,30)
-
-            /* ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0*/
-            MUL32x32INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,30)
-            ynL+=templ;
-
-            /* ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0 */
-            MUL32x32INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,30)
-            ynL+=templ;
-
-            /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
-            MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
-            /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
-            ynLO+= (*pDataIn);
-
-            /**************************************************************************
-                            PROCESSING OF THE RIGHT CHANNEL
-            ***************************************************************************/
-            /* ynR= (A0 (Q30) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>30)   in Q0*/
-            templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
-            MUL32x32INTO32(templ,pBiquadState->coefs[0],ynR,30)
-
-            /* ynR+= ((-B2 (Q30) * y(n-2)R (Q0) ) >>30)  in Q0*/
-            MUL32x32INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,30)
-            ynR+=templ;
-
-            /* ynR+= ((-B1 (Q30) * y(n-1)R (Q0) ) >>30)  in Q0 */
-            MUL32x32INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,30)
-            ynR+=templ;
-
-            /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
-            MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
-
-            /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
-            ynRO+= (*(pDataIn+1));
-
-            /**************************************************************************
-                            UPDATING THE DELAYS
-            ***************************************************************************/
-            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
-            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
-            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
-            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
-            pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
-            pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
-            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
-            pDataIn++;
-            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
-            pDataIn++;
-
-            /**************************************************************************
-                            WRITING THE OUTPUT
-            ***************************************************************************/
-            *pDataOut=ynLO; /* Write Left output in Q0*/
-            pDataOut++;
-            *pDataOut=ynRO; /* Write Right ouput in Q0*/
-            pDataOut++;
-        }
-
-    }
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp
new file mode 100644
index 0000000..41de1de
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
deleted file mode 100644
index 65475a3..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
-
-#ifndef BUILD_FLOAT
-void  PK_2I_D32F32CllGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_Taps_t   *pTaps,
-                                         PK_C32_Coefs_t            *pCoef)
-{
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
-
-  pBiquadState->coefs[0]=pCoef->A0;
-
-  pBiquadState->coefs[1]=pCoef->B2;
-
-  pBiquadState->coefs[2]=pCoef->B1;
-
-  pBiquadState->coefs[3]=pCoef->G;
-
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..714aa52
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
deleted file mode 100644
index a36330e..0000000
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "BIQUAD.h"
-#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
-#ifdef BUILD_FLOAT
-void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
-                                         PK_FLOAT_Coefs_t            *pCoef)
-{
-    PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
-    pBiquadState->pDelays       = (LVM_FLOAT *) pTaps;
-
-    pBiquadState->coefs[0] = pCoef->A0;
-
-    pBiquadState->coefs[1] = pCoef->B2;
-
-    pBiquadState->coefs[2] = pCoef->B1;
-
-    pBiquadState->coefs[3] = pCoef->G;
-}
-#else
-void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
-                                         Biquad_2I_Order2_Taps_t   *pTaps,
-                                         PK_C16_Coefs_t            *pCoef)
-{
-  PFilter_State pBiquadState = (PFilter_State) pInstance;
-  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
-
-  pBiquadState->coefs[0]=pCoef->A0;
-
-  pBiquadState->coefs[1]=pCoef->B2;
-
-  pBiquadState->coefs[2]=pCoef->B1;
-
-  pBiquadState->coefs[3]=pCoef->G;
-
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
new file mode 100644
index 0000000..f6c05da
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_FLOAT_Taps_t   *pTaps,
+                                         PK_FLOAT_Coefs_t            *pCoef)
+{
+    PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+    pBiquadState->pDelays       = (LVM_FLOAT *) pTaps;
+
+    pBiquadState->coefs[0] = pCoef->A0;
+
+    pBiquadState->coefs[1] = pCoef->B2;
+
+    pBiquadState->coefs[2] = pCoef->B1;
+
+    pBiquadState->coefs[3] = pCoef->G;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
index 1e32062..cc924c4 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -18,11 +18,9 @@
 #ifndef _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
 #define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
 
-
 /* The internal state variables are implemented in a (for the user)  hidden structure */
 /* In this (private) file, the internal structure is declared fro private use.        */
 
-#ifdef BUILD_FLOAT
 typedef struct _Filter_State_Float_
 {
     LVM_FLOAT *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
@@ -30,7 +28,6 @@
 }Filter_State_Float;
 
 typedef Filter_State_Float * PFilter_State_Float ;
-#endif
 typedef struct _Filter_State_
 {
   LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
deleted file mode 100644
index 28fea65..0000000
--- a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION Shift_Sat_v16xv16
-***********************************************************************************/
-#ifndef BUILD_FLOAT
-void Shift_Sat_v16xv16 (const   LVM_INT16   val,
-                        const   LVM_INT16   *src,
-                        LVM_INT16   *dst,
-                        LVM_INT16   n)
-{
-    LVM_INT32   temp;
-    LVM_INT32   ii;
-    LVM_INT16   RShift;
-    if(val>0)
-    {
-        for (ii = n; ii != 0; ii--)
-        {
-            temp = (LVM_INT32)*src;
-            src++;
-
-            temp = temp << val;
-
-            if (temp > 0x00007FFF)
-            {
-                *dst = 0x7FFF;
-            }
-            else if (temp < -0x00008000)
-            {
-                *dst = - 0x8000;
-            }
-            else
-            {
-                *dst = (LVM_INT16)temp;
-            }
-            dst++;
-        }
-    }
-    else if(val<0)
-    {
-        RShift=(LVM_INT16)(-val);
-
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = (LVM_INT16)(*src >> RShift);
-            dst++;
-            src++;
-        }
-    }
-    else
-    {
-        if(src!=dst)
-        {
-            Copy_16(src,dst,n);
-        }
-    }
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.cpp b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.cpp
new file mode 100644
index 0000000..668a4b6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION Shift_Sat_v16xv16
+***********************************************************************************/
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
deleted file mode 100644
index fac9de7..0000000
--- a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 FILES
-***********************************************************************************/
-
-#include "VectorArithmetic.h"
-
-/**********************************************************************************
-   FUNCTION Shift_Sat_v32xv32
-***********************************************************************************/
-#ifdef BUILD_FLOAT
-void Shift_Sat_Float (const   LVM_INT16   val,
-                      const   LVM_FLOAT   *src,
-                      LVM_FLOAT   *dst,
-                      LVM_INT16   n)
-{
-    LVM_FLOAT   temp;
-    LVM_INT32   ii,ij;
-    LVM_INT16   RShift;
-
-    if(val > 0)
-    {
-        for (ii = n; ii != 0; ii--)
-        {
-            temp = (LVM_FLOAT)*src;
-            src++;
-            for(ij = 0; ij < val; ij++)
-            {
-                temp = temp * 2;
-            }
-
-            if(temp > 1.0)
-                temp = 1.0;
-            if(temp < -1.0)
-                temp = -1.0;
-
-            *dst = (LVM_FLOAT)temp;
-            dst++;
-        }
-    }
-    else if(val < 0)
-    {
-        RShift=(LVM_INT16)(-val);
-
-        for (ii = n; ii != 0; ii--)
-        {
-            temp = (LVM_FLOAT)*src;
-            src++;
-            for(ij = 0; ij < RShift; ij++)
-            {
-                temp = temp / 2;
-            }
-            *dst = (LVM_FLOAT)temp;
-            dst++;
-        }
-    }
-    else
-    {
-        if(src != dst)
-        {
-            Copy_Float(src, dst, n);
-        }
-    }
-    return;
-}
-#else
-void Shift_Sat_v32xv32 (const   LVM_INT16   val,
-                        const   LVM_INT32   *src,
-                        LVM_INT32   *dst,
-                        LVM_INT16   n)
-{
-    LVM_INT32   ii;
-    LVM_INT16   RShift;
-
-    if(val>0)
-    {
-        LVM_INT32 a,b;
-
-        for (ii = n; ii != 0; ii--)
-        {
-            a=*src;
-            src++;
-
-            b=(a<<val);
-
-            if( (b>>val) != a ) /* if overflow occured, right shift will show difference*/
-            {
-                if(a<0)
-                {
-                    b=0x80000000l;
-                }
-                else
-                {
-                    b=0x7FFFFFFFl;
-                }
-            }
-
-            *dst = b;
-            dst++;
-        }
-    }
-    else if(val<0)
-    {
-        RShift=(LVM_INT16)(-val);
-        for (ii = n; ii != 0; ii--)
-        {
-            *dst = (*src >> RShift);
-            dst++;
-            src++;
-        }
-    }
-    else
-    {
-        if(src!=dst)
-        {
-            Copy_16((LVM_INT16 *)src,(LVM_INT16 *)dst,(LVM_INT16)(n<<1));
-        }
-    }
-    return;
-}
-#endif
-/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.cpp b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.cpp
new file mode 100644
index 0000000..97a04c1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION Shift_Sat_v32xv32
+***********************************************************************************/
+void Shift_Sat_Float (const   LVM_INT16   val,
+                      const   LVM_FLOAT   *src,
+                      LVM_FLOAT   *dst,
+                      LVM_INT16   n)
+{
+    LVM_FLOAT   temp;
+    LVM_INT32   ii,ij;
+    LVM_INT16   RShift;
+
+    if(val > 0)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            temp = (LVM_FLOAT)*src;
+            src++;
+            for(ij = 0; ij < val; ij++)
+            {
+                temp = temp * 2;
+            }
+
+            if(temp > 1.0)
+                temp = 1.0;
+            if(temp < -1.0)
+                temp = -1.0;
+
+            *dst = (LVM_FLOAT)temp;
+            dst++;
+        }
+    }
+    else if(val < 0)
+    {
+        RShift=(LVM_INT16)(-val);
+
+        for (ii = n; ii != 0; ii--)
+        {
+            temp = (LVM_FLOAT)*src;
+            src++;
+            for(ij = 0; ij < RShift; ij++)
+            {
+                temp = temp / 2;
+            }
+            *dst = (LVM_FLOAT)temp;
+            dst++;
+        }
+    }
+    else
+    {
+        if(src != dst)
+        {
+            Copy_Float(src, dst, n);
+        }
+    }
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
deleted file mode 100644
index 9a726f2..0000000
--- a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************/
-/*                                                                      */
-/*     %created_by:    sra % (CM/S)*/
-/*     %name:          dB_to_Lin32.c % (CM/S)*/
-/*     %version:       2 % (CM/S)*/
-/*     %date_created:  Wed Jun 18 11:27:46 2008 % (CM/S)*/
-/*                                                                      */
-/************************************************************************/
-
-/*######################################################################################*/
-/*  Include files                                                                       */
-/*######################################################################################*/
-
-#include "ScalarArithmetic.h"
-#ifdef BUILD_FLOAT
-#include <math.h>
-#endif
-
-
-/****************************************************************************************
- *  Name        : dB_to_Lin32()
- *  Input       : Signed 16-bit integer
- *                  MSB (16) = sign bit
- *                  (15->05) = integer part
- *                  (04->01) = decimal part
- *  Output      : Signed 32-bit integer
- *                  MSB (32) = sign bit
- *                  (31->16) = integer part
- *                  (15->01) = decimal part
- *  Returns     : Lin value format 1.16.15
- *  Description :
- *  Remarks     :  Makes an approximation to the conversion by counting the number
- *                 of 6dB steps for use as shifts and then interpolates with a remainder
- *                 with the equation:
- *
- *                 Correction = (Remainder / 1.5029) - (Remainder^2 / 6)
- *
- *                 The two coefficients are scaled from 0x40000000 in 96 steps and calculated
- *                 as follows:
- *
- *                 FIRST_COEF  = 0x80000000 / (96 * 1.5029)
- *                 SECOND_COEF = 0x80000000 / (96^2 * 6)
- *
- ****************************************************************************************/
-
-#define FOUR_OVER_SIX    21846                  /* (4 / 6) * 2^15 */
-#define SIX_DB           96                     /* 6 * 16 or 6dB in Q11.4 format */
-#define FIRST_COEF_NEG   14884305
-#define FIRST_COEF_POS   7442152                /* FIRST_COEF_NEG / 2 */
-#define SECOND_COEF      38836
-#define MAX_VALUE        1536                   /* 96 * 16 */
-
-#ifdef BUILD_FLOAT
-LVM_FLOAT   dB_to_LinFloat(LVM_INT16    db_fix)
-{
-    LVM_FLOAT    dB_Float;
-    LVM_FLOAT    LinFloat;
-
-    dB_Float = (LVM_FLOAT)((LVM_FLOAT)db_fix / 16.0f);
-    LinFloat = pow(10, dB_Float / 20.0);
-
-    return LinFloat;
-}
-#else
-LVM_INT32   dB_to_Lin32(LVM_INT16    db_fix)
-{
-    LVM_INT32 Lin_val_32;
-    LVM_INT16 Shift;
-    LVM_INT32 Remain;
-
-
-    /*
-     * Check sign of the input
-     */
-    if (db_fix<0)
-    {
-        if (db_fix > -MAX_VALUE)
-        {
-            Shift  = (LVM_INT16)((((LVM_UINT32)(-db_fix) >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
-            Remain = -db_fix - (Shift * SIX_DB);
-            Remain = (0x7FFFFFFF - (Remain * FIRST_COEF_NEG)) + (Remain * Remain * SECOND_COEF);
-            Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (16 + Shift));
-        }
-        else
-        {
-            Lin_val_32 = 0;
-        }
-    }
-    else
-    {
-        if (db_fix < MAX_VALUE)
-        {
-            Shift  = (LVM_INT16)((((LVM_UINT32)db_fix >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
-            Remain = db_fix - (Shift * SIX_DB);
-            Remain = 0x3FFFFFFF + (Remain * FIRST_COEF_POS) + (Remain * Remain * SECOND_COEF);
-            Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (15 - Shift));
-        }
-        else
-        {
-            Lin_val_32 = 0x7FFFFFFF;
-        }
-    }
-
-
-    return Lin_val_32;  /* format 1.16.15 */
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.cpp b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.cpp
new file mode 100644
index 0000000..4da2013
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     %created_by:    sra % (CM/S)*/
+/*     %name:          dB_to_Lin32.c % (CM/S)*/
+/*     %version:       2 % (CM/S)*/
+/*     %date_created:  Wed Jun 18 11:27:46 2008 % (CM/S)*/
+/*                                                                      */
+/************************************************************************/
+
+/*######################################################################################*/
+/*  Include files                                                                       */
+/*######################################################################################*/
+
+#include "ScalarArithmetic.h"
+#include <math.h>
+
+/****************************************************************************************
+ *  Name        : dB_to_Lin32()
+ *  Input       : Signed 16-bit integer
+ *                  MSB (16) = sign bit
+ *                  (15->05) = integer part
+ *                  (04->01) = decimal part
+ *  Output      : Signed 32-bit integer
+ *                  MSB (32) = sign bit
+ *                  (31->16) = integer part
+ *                  (15->01) = decimal part
+ *  Returns     : Lin value format 1.16.15
+ *  Description :
+ *  Remarks     :  Makes an approximation to the conversion by counting the number
+ *                 of 6dB steps for use as shifts and then interpolates with a remainder
+ *                 with the equation:
+ *
+ *                 Correction = (Remainder / 1.5029) - (Remainder^2 / 6)
+ *
+ *                 The two coefficients are scaled from 0x40000000 in 96 steps and calculated
+ *                 as follows:
+ *
+ *                 FIRST_COEF  = 0x80000000 / (96 * 1.5029)
+ *                 SECOND_COEF = 0x80000000 / (96^2 * 6)
+ *
+ ****************************************************************************************/
+
+#define FOUR_OVER_SIX    21846                  /* (4 / 6) * 2^15 */
+#define SIX_DB           96                     /* 6 * 16 or 6dB in Q11.4 format */
+#define FIRST_COEF_NEG   14884305
+#define FIRST_COEF_POS   7442152                /* FIRST_COEF_NEG / 2 */
+#define SECOND_COEF      38836
+#define MAX_VALUE        1536                   /* 96 * 16 */
+
+LVM_FLOAT   dB_to_LinFloat(LVM_INT16    db_fix)
+{
+    LVM_FLOAT    dB_Float;
+    LVM_FLOAT    LinFloat;
+
+    dB_Float = (LVM_FLOAT)((LVM_FLOAT)db_fix / 16.0f);
+    LinFloat = pow(10, dB_Float / 20.0);
+
+    return LinFloat;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
similarity index 100%
rename from media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
rename to media/libeffects/lvm/lib/Common/src/mult3s_16x16.cpp
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
index 804f1bf..c5ddf77 100644
--- a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -68,15 +68,9 @@
 /*                                                                                      */
 /****************************************************************************************/
 
-
 #ifndef __LVEQNB_H__
 #define __LVEQNB_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -112,7 +106,6 @@
 /* Instance handle */
 typedef void *LVEQNB_Handle_t;
 
-
 /* Operating modes */
 typedef enum
 {
@@ -121,7 +114,6 @@
     LVEQNB_MODE_MAX = LVM_MAXINT_32
 } LVEQNB_Mode_en;
 
-
 /* Filter mode control */
 typedef enum
 {
@@ -130,7 +122,6 @@
     LVEQNB_FILTER_DUMMY = LVM_MAXINT_32
 } LVEQNB_FilterMode_en;
 
-
 /* Memory Types */
 typedef enum
 {
@@ -141,7 +132,6 @@
     LVEQNB_MEMORY_MAX      = LVM_MAXINT_32
 } LVEQNB_MemoryTypes_en;
 
-
 /* Function return status */
 typedef enum
 {
@@ -152,7 +142,6 @@
     LVEQNB_STATUS_MAX     = LVM_MAXINT_32
 } LVEQNB_ReturnStatus_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Linked enumerated type and capability definitions                                   */
@@ -190,7 +179,6 @@
     LVEQNB_SOURCE_MAX   = LVM_MAXINT_32
 } LVEQNB_SourceFormat_en;
 
-
 /*
  * Supported sample rates in samples per second
  */
@@ -203,12 +191,10 @@
 #define LVEQNB_CAP_FS_32000                64
 #define LVEQNB_CAP_FS_44100                128
 #define LVEQNB_CAP_FS_48000                256
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
 #define LVEQNB_CAP_FS_88200                512
 #define LVEQNB_CAP_FS_96000                1024
 #define LVEQNB_CAP_FS_176400               2048
 #define LVEQNB_CAP_FS_192000               4096
-#endif
 
 typedef enum
 {
@@ -221,16 +207,13 @@
     LVEQNB_FS_32000 = 6,
     LVEQNB_FS_44100 = 7,
     LVEQNB_FS_48000 = 8,
-#ifdef HIGHER_FS
     LVEQNB_FS_88200 = 9,
     LVEQNB_FS_96000 = 10,
     LVEQNB_FS_176400 = 11,
     LVEQNB_FS_192000 = 12,
-#endif
     LVEQNB_FS_MAX   = LVM_MAXINT_32
 } LVEQNB_Fs_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
@@ -246,14 +229,12 @@
     void                        *pBaseAddress;          /* Pointer to the region base address */
 } LVEQNB_MemoryRegion_t;
 
-
 /* Memory table containing the region definitions */
 typedef struct
 {
     LVEQNB_MemoryRegion_t       Region[LVEQNB_NR_MEMORY_REGIONS];  /* One definition for each region */
 } LVEQNB_MemTab_t;
 
-
 /* Equaliser band definition */
 typedef struct
 {
@@ -262,7 +243,6 @@
     LVM_UINT16                  QFactor;                /* Band quality factor */
 } LVEQNB_BandDef_t;
 
-
 /* Parameter structure */
 typedef struct
 {
@@ -279,7 +259,6 @@
 #endif
 } LVEQNB_Params_t;
 
-
 /* Capability structure */
 typedef struct
 {
@@ -296,7 +275,6 @@
 
 } LVEQNB_Capabilities_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Function Prototypes                                                                 */
@@ -339,7 +317,6 @@
                                      LVEQNB_MemTab_t            *pMemoryTable,
                                      LVEQNB_Capabilities_t      *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVEQNB_Init                                                 */
@@ -379,7 +356,6 @@
                                    LVEQNB_MemTab_t          *pMemoryTable,
                                    LVEQNB_Capabilities_t    *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVEQNB_GetParameters                                       */
@@ -404,7 +380,6 @@
 LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
                                             LVEQNB_Params_t     *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVEQNB_GetCapabilities                                     */
@@ -429,7 +404,6 @@
 LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
                                               LVEQNB_Capabilities_t     *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVEQNB_Control                                              */
@@ -455,7 +429,6 @@
 LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t       hInstance,
                                       LVEQNB_Params_t       *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVEQNB_Process                                              */
@@ -478,23 +451,10 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
                                       const LVM_FLOAT       *pInData,
                                       LVM_FLOAT             *pOutData,
                                       LVM_UINT16            NumSamples);
-#else
-LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
-                                      const LVM_INT16       *pInData,
-                                      LVM_INT16             *pOutData,
-                                      LVM_UINT16            NumSamples);
-#endif
-
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif      /* __LVEQNB__ */
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
deleted file mode 100644
index ff52b7f..0000000
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Includes                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVEQNB_Private.h"
-#ifdef BUILD_FLOAT
-#include <math.h>
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/*    Defines                                                                           */
-/*                                                                                      */
-/****************************************************************************************/
-
-#define PI 3.14159265358979
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                  LVEQNB_DoublePrecCoefs                                    */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Calculate double precision coefficients    for a peaking filter                   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  Fs                           Sampling frequency index                               */
-/*  pFilterDefinition          Pointer to the filter definition                         */
-/*  pCoefficients            Pointer to the coefficients                                */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS            Always succeeds                                           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The equations used are as follows:                                               */
-/*                                                                                      */
-/*      G  = 10^(GaindB/20) - 1                                                         */
-/*      t0 = 2 * Pi * Fc / Fs                                                           */
-/*      D  = 1                  if GaindB >= 0                                          */
-/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
-/*                                                                                      */
-/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
-/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
-/*      a0 = (0.5 + b2) / 2                                                             */
-/*                                                                                      */
-/*  Where:                                                                              */
-/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
-/*      Fc          is the centre frequency, DC to Fs/50                                */
-/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
-/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
-/*                                                                                      */
-/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
-/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
-/*     itself the difference from the value 1.0 is calculated, this can be done with    */
-/*     lower precision maths.                                                           */
-/*                                                                                      */
-/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
-/*     small errors in this value have a combined effect on the Q and Gain but not the  */
-/*     the frequency of the filter.                                                     */
-/*                                                                                      */
-/****************************************************************************************/
-
-
-#ifndef BUILD_FLOAT
-LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
-                                              LVEQNB_BandDef_t  *pFilterDefinition,
-                                              PK_C32_Coefs_t    *pCoefficients)
-{
-
-    extern LVM_INT16    LVEQNB_GainTable[];
-    extern LVM_INT16    LVEQNB_TwoPiOnFsTable[];
-    extern LVM_INT16    LVEQNB_DTable[];
-    extern LVM_INT16    LVEQNB_DPCosCoef[];
-
-    /*
-     * Get the filter definition
-     */
-    LVM_INT16           Gain        = pFilterDefinition->Gain;
-    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
-    LVM_UINT16          QFactor     = pFilterDefinition->QFactor;
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_INT32           T0;
-    LVM_INT16           D;
-    LVM_INT32           A0;
-    LVM_INT32           B1;
-    LVM_INT32           B2;
-    LVM_INT32           Dt0;
-    LVM_INT32           B2_Den;
-    LVM_INT32           B2_Num;
-    LVM_INT32           CosErr;
-    LVM_INT16           coef;
-    LVM_INT32           factor;
-    LVM_INT16           t0;
-    LVM_INT16           i;
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
-    if (Gain >= 0)
-    {
-        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
-    }
-    else
-    {
-        D = LVEQNB_DTable[Gain+15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
-    }
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 = D * (T0 >> 10);
-    B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
-    B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
-    B2 = (B2_Num / (B2_Den >> 16)) << 15;
-
-    /*
-     * Calculate the cosine error by a polynomial expansion using the equation:
-     *
-     *  CosErr += coef(n) * t0^n                For n = 0 to 4
-     */
-    T0 = (T0 >> 6) * 0x7f53;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
-    t0 = (LVM_INT16)(T0 >> 16);
-    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
-    CosErr = 0;                                 /* Initialise the error to zero */
-    for (i=1; i<5; i++)
-    {
-        coef = LVEQNB_DPCosCoef[i];             /* Get the nth coefficient */
-        CosErr += (factor * coef) >> 5;         /* The nth partial sum */
-        factor = (factor * t0) >> 15;           /* Calculate t0^n */
-    }
-    CosErr = CosErr << (LVEQNB_DPCosCoef[0]);   /* Correct the scaling */
-
-    /*
-     * Calculate the B1 and A0 coefficients
-     */
-    B1 = (0x40000000 - B2);                     /* B1 = (0.5 - b2/2) */
-    A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6;    /* Temporary storage for (0.5 - b2/2) * coserr(t0) */
-    B1 -= A0;                                   /* B1 = (0.5 - b2/2) * (1 - coserr(t0))  */
-    A0 = (0x40000000 + B2) >> 1;                /* A0 = (0.5 + b2) */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = A0;
-    pCoefficients->B1 = B1;
-    pCoefficients->B2 = B2;
-    pCoefficients->G  = LVEQNB_GainTable[Gain+15];
-
-    return(LVEQNB_SUCCESS);
-
-}
-#endif
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                  LVEQNB_SinglePrecCoefs                                    */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*    Calculate single precision coefficients    for a peaking filter                   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  Fs                           Sampling frequency index                               */
-/*  pFilterDefinition          Pointer to the filter definition                         */
-/*  pCoefficients            Pointer to the coefficients                                */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS            Always succeeds                                           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The equations used are as follows:                                               */
-/*                                                                                      */
-/*      G  = 10^(GaindB/20) - 1                                                         */
-/*      t0 = 2 * Pi * Fc / Fs                                                           */
-/*      D  = 1                  if GaindB >= 0                                          */
-/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
-/*                                                                                      */
-/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
-/*      b1 = (0.5 - b2) * cos(t0)                                                       */
-/*      a0 = (0.5 + b2) / 2                                                             */
-/*                                                                                      */
-/*  Where:                                                                              */
-/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
-/*      Fc          is the centre frequency, DC to Nyquist                              */
-/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
-/*      Q           is the Q factor, 0.25 to 12                                         */
-/*                                                                                      */
-/****************************************************************************************/
-
-#ifdef BUILD_FLOAT
-LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
-                                              LVEQNB_BandDef_t  *pFilterDefinition,
-                                              PK_FLOAT_Coefs_t  *pCoefficients)
-{
-
-    extern LVM_FLOAT    LVEQNB_GainTable[];
-    extern LVM_FLOAT    LVEQNB_TwoPiOnFsTable[];
-    extern LVM_FLOAT    LVEQNB_DTable[];
-
-
-    /*
-     * Get the filter definition
-     */
-    LVM_INT16           Gain        = pFilterDefinition->Gain;
-    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
-    /* As mentioned in effectbundle.h */
-    LVM_FLOAT           QFactor     = (LVM_FLOAT)pFilterDefinition->QFactor / 100.0f;
-
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_FLOAT           T0;
-    LVM_FLOAT           D;
-    LVM_FLOAT           A0;
-    LVM_FLOAT           B1;
-    LVM_FLOAT           B2;
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
-    if (Gain >= 0)
-    {
-        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
-    }
-    else
-    {
-        D = LVEQNB_DTable[Gain + 15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
-    }
-
-    /*
-     * Calculate the B2,B1,A0 coefficients
-     */
-    B2 = -0.5 * (2 * QFactor - D * T0) / (2 * QFactor + D * T0);
-    B1 = (0.5 - B2) * cos(T0);
-    A0 = (0.5 + B2) / 2.0;
-
-    /*
-     * Write coeff into the data structure
-     */
-    /* all the coefficients are multiplied with 2 to make them align with fixed point values*/
-    pCoefficients->A0 = 2 * A0;
-    pCoefficients->B1 = 2 * B1;
-    pCoefficients->B2 = 2 * B2;
-    pCoefficients->G  = LVEQNB_GainTable[Gain + 15];
-
-    return(LVEQNB_SUCCESS);
-}
-#else
-LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
-                                              LVEQNB_BandDef_t  *pFilterDefinition,
-                                              PK_C16_Coefs_t    *pCoefficients)
-{
-
-    extern LVM_INT16    LVEQNB_GainTable[];
-    extern LVM_INT16    LVEQNB_TwoPiOnFsTable[];
-    extern LVM_INT16    LVEQNB_DTable[];
-    extern LVM_INT16    LVEQNB_CosCoef[];
-
-
-    /*
-     * Get the filter definition
-     */
-    LVM_INT16           Gain        = pFilterDefinition->Gain;
-    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
-    LVM_UINT16          QFactor     = pFilterDefinition->QFactor;
-
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_INT32           T0;
-    LVM_INT16           D;
-    LVM_INT32           A0;
-    LVM_INT32           B1;
-    LVM_INT32           B2;
-    LVM_INT32           Dt0;
-    LVM_INT32           B2_Den;
-    LVM_INT32           B2_Num;
-    LVM_INT32           COS_T0;
-    LVM_INT16           coef;
-    LVM_INT32           factor;
-    LVM_INT16           t0;
-    LVM_INT16           i;
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
-    if (Gain >= 0)
-    {
-        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
-    }
-    else
-    {
-        D = LVEQNB_DTable[Gain+15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
-    }
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 = D * (T0 >> 10);
-    B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
-    B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
-    B2 = (B2_Num / (B2_Den >> 16)) << 15;
-
-    /*
-     * Calculate the cosine by a polynomial expansion using the equation:
-     *
-     *  Cos += coef(n) * t0^n                   For n = 0 to 6
-     */
-    T0 = (T0 >> 10) * 20859;                    /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
-    t0 = (LVM_INT16)(T0 >> 16);
-    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
-    COS_T0 = 0;                                 /* Initialise the error to zero */
-    for (i=1; i<7; i++)
-    {
-        coef = LVEQNB_CosCoef[i];               /* Get the nth coefficient */
-        COS_T0 += (factor * coef) >> 5;         /* The nth partial sum */
-        factor = (factor * t0) >> 15;           /* Calculate t0^n */
-    }
-    COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6);          /* Correct the scaling */
-
-
-    B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16);    /* B1 = (0.5 - b2/2) * cos(t0) */
-    A0 = (0x40000000 + B2) >> 1;                        /* A0 = (0.5 + b2/2) */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = (LVM_INT16)(A0>>16);
-    pCoefficients->B1 = (LVM_INT16)(B1>>15);
-    pCoefficients->B2 = (LVM_INT16)(B2>>16);
-    pCoefficients->G  = LVEQNB_GainTable[Gain+15];
-
-
-    return(LVEQNB_SUCCESS);
-
-}
-#endif
\ No newline at end of file
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.cpp
new file mode 100644
index 0000000..c3c0fad
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB_Private.h"
+#include <math.h>
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Defines                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define PI 3.14159265358979
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVEQNB_DoublePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Calculate double precision coefficients    for a peaking filter                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                           Sampling frequency index                               */
+/*  pFilterDefinition          Pointer to the filter definition                         */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS            Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      G  = 10^(GaindB/20) - 1                                                         */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*      D  = 1                  if GaindB >= 0                                          */
+/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
+/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
+/*      Fc          is the centre frequency, DC to Fs/50                                */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
+/*                                                                                      */
+/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
+/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
+/*     itself the difference from the value 1.0 is calculated, this can be done with    */
+/*     lower precision maths.                                                           */
+/*                                                                                      */
+/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
+/*     small errors in this value have a combined effect on the Q and Gain but not the  */
+/*     the frequency of the filter.                                                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVEQNB_SinglePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Calculate single precision coefficients    for a peaking filter                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                           Sampling frequency index                               */
+/*  pFilterDefinition          Pointer to the filter definition                         */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS            Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      G  = 10^(GaindB/20) - 1                                                         */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*      D  = 1                  if GaindB >= 0                                          */
+/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
+/*      b1 = (0.5 - b2) * cos(t0)                                                       */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
+/*      Fc          is the centre frequency, DC to Nyquist                              */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_FLOAT_Coefs_t  *pCoefficients)
+{
+
+    extern LVM_FLOAT    LVEQNB_GainTable[];
+    extern LVM_FLOAT    LVEQNB_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVEQNB_DTable[];
+
+    /*
+     * Get the filter definition
+     */
+    LVM_INT16           Gain        = pFilterDefinition->Gain;
+    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
+    /* As mentioned in effectbundle.h */
+    LVM_FLOAT           QFactor     = (LVM_FLOAT)pFilterDefinition->QFactor / 100.0f;
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
+    if (Gain >= 0)
+    {
+        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
+    }
+    else
+    {
+        D = LVEQNB_DTable[Gain + 15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
+    }
+
+    /*
+     * Calculate the B2,B1,A0 coefficients
+     */
+    B2 = -0.5 * (2 * QFactor - D * T0) / (2 * QFactor + D * T0);
+    B1 = (0.5 - B2) * cos(T0);
+    A0 = (0.5 + B2) / 2.0;
+
+    /*
+     * Write coeff into the data structure
+     */
+    /* all the coefficients are multiplied with 2 to make them align with fixed point values*/
+    pCoefficients->A0 = 2 * A0;
+    pCoefficients->B1 = 2 * B1;
+    pCoefficients->B2 = 2 * B2;
+    pCoefficients->G  = LVEQNB_GainTable[Gain + 15];
+
+    return(LVEQNB_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
index 755141e..6329181 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
@@ -15,17 +15,14 @@
  * limitations under the License.
  */
 
-
 #ifndef __LVEQNB_COEFFS_H__
 #define __LVEQNB_COEFFS_H__
 
-
 /************************************************************************************/
 /*                                                                                  */
 /* Gain table for (10^(Gain/20) - 1)                                                */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 #define LVEQNB_Gain_Neg15_dB                             (-0.822172f)
 #define LVEQNB_Gain_Neg14_dB                             (-0.800474f)
 #define LVEQNB_Gain_Neg13_dB                             (-0.776128f)
@@ -57,47 +54,12 @@
 #define LVEQNB_Gain_13_dB                                 3.466836f
 #define LVEQNB_Gain_14_dB                                 4.011872f
 #define LVEQNB_Gain_15_dB                                 4.623413f
-#else
-#define LVEQNB_GAINSHIFT                                   11         /* As a power of 2 */
-#define LVEQNB_Gain_Neg15_dB                           (-1684)        /* Floating point value -0.822172 */
-#define LVEQNB_Gain_Neg14_dB                           (-1639)        /* Floating point value -0.800474 */
-#define LVEQNB_Gain_Neg13_dB                           (-1590)        /* Floating point value -0.776128 */
-#define LVEQNB_Gain_Neg12_dB                           (-1534)        /* Floating point value -0.748811 */
-#define LVEQNB_Gain_Neg11_dB                           (-1471)        /* Floating point value -0.718162 */
-#define LVEQNB_Gain_Neg10_dB                           (-1400)        /* Floating point value -0.683772 */
-#define LVEQNB_Gain_Neg9_dB                            (-1321)        /* Floating point value -0.645187 */
-#define LVEQNB_Gain_Neg8_dB                            (-1233)        /* Floating point value -0.601893 */
-#define LVEQNB_Gain_Neg7_dB                            (-1133)        /* Floating point value -0.553316 */
-#define LVEQNB_Gain_Neg6_dB                            (-1022)        /* Floating point value -0.498813 */
-#define LVEQNB_Gain_Neg5_dB                             (-896)        /* Floating point value -0.437659 */
-#define LVEQNB_Gain_Neg4_dB                             (-756)        /* Floating point value -0.369043 */
-#define LVEQNB_Gain_Neg3_dB                             (-598)        /* Floating point value -0.292054 */
-#define LVEQNB_Gain_Neg2_dB                             (-421)        /* Floating point value -0.205672 */
-#define LVEQNB_Gain_Neg1_dB                             (-223)        /* Floating point value -0.108749 */
-#define LVEQNB_Gain_0_dB                                    0         /* Floating point value 0.000000 */
-#define LVEQNB_Gain_1_dB                                  250         /* Floating point value 0.122018 */
-#define LVEQNB_Gain_2_dB                                  530         /* Floating point value 0.258925 */
-#define LVEQNB_Gain_3_dB                                  845         /* Floating point value 0.412538 */
-#define LVEQNB_Gain_4_dB                                 1198         /* Floating point value 0.584893 */
-#define LVEQNB_Gain_5_dB                                 1594         /* Floating point value 0.778279 */
-#define LVEQNB_Gain_6_dB                                 2038         /* Floating point value 0.995262 */
-#define LVEQNB_Gain_7_dB                                 2537         /* Floating point value 1.238721 */
-#define LVEQNB_Gain_8_dB                                 3096         /* Floating point value 1.511886 */
-#define LVEQNB_Gain_9_dB                                 3724         /* Floating point value 1.818383 */
-#define LVEQNB_Gain_10_dB                                4428         /* Floating point value 2.162278 */
-#define LVEQNB_Gain_11_dB                                5219         /* Floating point value 2.548134 */
-#define LVEQNB_Gain_12_dB                                6105         /* Floating point value 2.981072 */
-#define LVEQNB_Gain_13_dB                                7100         /* Floating point value 3.466836 */
-#define LVEQNB_Gain_14_dB                                8216         /* Floating point value 4.011872 */
-#define LVEQNB_Gain_15_dB                                9469         /* Floating point value 4.623413 */
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /* Frequency table for 2*Pi/Fs                                                      */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 #define LVEQNB_2PiOn_8000                                0.000785f
 #define LVEQNB_2PiOn_11025                               0.000570f
 #define LVEQNB_2PiOn_12000                               0.000524f
@@ -108,32 +70,16 @@
 #define LVEQNB_2PiOn_44100                               0.000142f
 #define LVEQNB_2PiOn_48000                               0.000131f
 
-#ifdef HIGHER_FS
 #define LVEQNB_2PiOn_88200                               0.000071f
 #define LVEQNB_2PiOn_96000                               0.000065f
 #define LVEQNB_2PiOn_176400                              0.000036f
 #define LVEQNB_2PiOn_192000                              0.000033f
-#endif
-
-#else
-#define LVEQNB_FREQSHIFT                                   25         /* As a power of 2 */
-#define LVEQNB_2PiOn_8000                               26354         /* Floating point value 0.000785 */
-#define LVEQNB_2PiOn_11025                              19123         /* Floating point value 0.000570 */
-#define LVEQNB_2PiOn_12000                              17569         /* Floating point value 0.000524 */
-#define LVEQNB_2PiOn_16000                              13177         /* Floating point value 0.000393 */
-#define LVEQNB_2PiOn_22050                               9561         /* Floating point value 0.000285 */
-#define LVEQNB_2PiOn_24000                               8785         /* Floating point value 0.000262 */
-#define LVEQNB_2PiOn_32000                               6588         /* Floating point value 0.000196 */
-#define LVEQNB_2PiOn_44100                               4781         /* Floating point value 0.000142 */
-#define LVEQNB_2PiOn_48000                               4392         /* Floating point value 0.000131 */
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
 /* 50D table for 50 / ( 1 + Gain )                                                  */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 #define LVEQNB_100D_Neg15_dB                             5.623413f
 #define LVEQNB_100D_Neg14_dB                             5.011872f
 #define LVEQNB_100D_Neg13_dB                             4.466836f
@@ -150,24 +96,5 @@
 #define LVEQNB_100D_Neg2_dB                              1.258925f
 #define LVEQNB_100D_Neg1_dB                              1.122018f
 #define LVEQNB_100D_0_dB                                 1.000000f
-#else
-#define LVEQNB_100DSHIFT                                    5         /* As a power of 2 */
-#define LVEQNB_100D_Neg15_dB                            17995         /* Floating point value 5.623413 */
-#define LVEQNB_100D_Neg14_dB                            16038         /* Floating point value 5.011872 */
-#define LVEQNB_100D_Neg13_dB                            14294         /* Floating point value 4.466836 */
-#define LVEQNB_100D_Neg12_dB                            12739         /* Floating point value 3.981072 */
-#define LVEQNB_100D_Neg11_dB                            11354         /* Floating point value 3.548134 */
-#define LVEQNB_100D_Neg10_dB                            10119         /* Floating point value 3.162278 */
-#define LVEQNB_100D_Neg9_dB                              9019         /* Floating point value 2.818383 */
-#define LVEQNB_100D_Neg8_dB                              8038         /* Floating point value 2.511886 */
-#define LVEQNB_100D_Neg7_dB                              7164         /* Floating point value 2.238721 */
-#define LVEQNB_100D_Neg6_dB                              6385         /* Floating point value 1.995262 */
-#define LVEQNB_100D_Neg5_dB                              5690         /* Floating point value 1.778279 */
-#define LVEQNB_100D_Neg4_dB                              5072         /* Floating point value 1.584893 */
-#define LVEQNB_100D_Neg3_dB                              4520         /* Floating point value 1.412538 */
-#define LVEQNB_100D_Neg2_dB                              4029         /* Floating point value 1.258925 */
-#define LVEQNB_100D_Neg1_dB                              3590         /* Floating point value 1.122018 */
-#define LVEQNB_100D_0_dB                                 3200         /* Floating point value 1.000000 */
-#endif
 
 #endif
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
deleted file mode 100644
index 7b0f341..0000000
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVEQNB.h"
-#include "LVEQNB_Private.h"
-#include "VectorArithmetic.h"
-#include "BIQUAD.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Defines                                                                             */
-/*                                                                                      */
-/****************************************************************************************/
-
-#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
-#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVEQNB_GetParameters                                       */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Request the N-Band equaliser parameters. The current parameter set is returned via  */
-/*  the parameter pointer.                                                              */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance                Instance handle                                            */
-/*  pParams                  Pointer to an empty parameter structure                    */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS          Succeeds                                                    */
-/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
-                                            LVEQNB_Params_t     *pParams)
-{
-
-    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
-
-   /*
-     * Check for error conditions
-     */
-    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    *pParams = pInstance->Params;
-
-    return(LVEQNB_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                 LVEQNB_GetCapabilities                                 */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Get the N-Band equaliser capabilities. The current capabilities are returned    */
-/*  via the pointer.                                                                */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance                Instance handle                                        */
-/*  pCapabilities            Pointer to an empty capability structure               */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVEQNB_Success           Succeeds                                               */
-/*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                     */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  This function may be interrupted by the LVEQNB_Process function             */
-/*                                                                                  */
-/************************************************************************************/
-
-LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
-                                              LVEQNB_Capabilities_t     *pCapabilities)
-{
-
-    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
-
-    if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    *pCapabilities = pInstance->Capabilities;
-
-    return(LVEQNB_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVEQNB_SetFilters                                           */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the filter type based on the definition.                                   */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  void                Nothing                                                     */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1. To select the biquad type the follow rules are applied:                      */
-/*          Double precision    if (fc <= fs/110)                                   */
-/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
-/*          Single precision    otherwise                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
-                          LVEQNB_Params_t       *pParams)
-{
-#ifdef HIGHER_FS
-    extern const LVM_UINT32   LVEQNB_SampleRateTab[];           /* Sample rate table */
-#else
-    extern const LVM_UINT16   LVEQNB_SampleRateTab[];           /* Sample rate table */
-#endif
-
-    LVM_UINT16          i;                                      /* Filter band index */
-    LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
-    LVM_UINT32          fc;                                     /* Filter centre frequency */
-    LVM_INT16           QFactor;                                /* Filter Q factor */
-
-
-    pInstance->NBands = pParams->NBands;
-
-    for (i=0; i<pParams->NBands; i++)
-    {
-        /*
-         * Get the filter settings
-         */
-        fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
-        QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
-
-#ifdef BUILD_FLOAT
-        pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
-#else
-        /*
-         * For each filter set the type of biquad required
-         */
-        pInstance->pBiquadType[i] = LVEQNB_SinglePrecision;         /* Default to single precision */
-#endif
-#ifndef BUILD_FLOAT
-        if ((fc << 15) <= (LOW_FREQ * fs))
-        {
-            /*
-             * fc <= fs/110
-             */
-            pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
-        }
-        else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
-        {
-            /*
-             * (fs/110 < fc < fs/85) & (Q>3)
-             */
-            pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
-        }
-#endif
-
-        /*
-         * Check for out of range frequencies
-         */
-        if (fc > (fs >> 1))
-        {
-            pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
-        }
-
-
-        /*
-         * Copy the filter definition to persistant memory
-         */
-        pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
-
-    }
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVEQNB_SetCoefficients                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the filter coefficients. This uses the type to select single or double     */
-/*  precision coefficients.                                                         */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*  pParams             Initialisation parameters                                   */
-/*                                                                                  */
-/************************************************************************************/
-
-void    LVEQNB_SetCoefficients(LVEQNB_Instance_t     *pInstance)
-{
-
-    LVM_UINT16              i;                          /* Filter band index */
-    LVEQNB_BiquadType_en    BiquadType;                 /* Filter biquad type */
-
-
-    /*
-     * Set the coefficients for each band by the init function
-     */
-    for (i=0; i<pInstance->Params.NBands; i++)
-    {
-
-        /*
-         * Check band type for correct initialisation method and recalculate the coefficients
-         */
-        BiquadType = pInstance->pBiquadType[i];
-        switch  (BiquadType)
-        {
-#ifdef BUILD_FLOAT
-            case    LVEQNB_SinglePrecision_Float:
-            {
-                PK_FLOAT_Coefs_t      Coefficients;
-                /*
-                 * Calculate the single precision coefficients
-                 */
-                LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
-                                       &pInstance->pBandDefinitions[i],
-                                       &Coefficients);
-                /*
-                 * Set the coefficients
-                 */
-                PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
-                                                   &pInstance->pEQNB_Taps_Float[i],
-                                                   &Coefficients);
-                break;
-            }
-#else
-            case    LVEQNB_DoublePrecision:
-            {
-                PK_C32_Coefs_t      Coefficients;
-
-                /*
-                 * Calculate the double precision coefficients
-                 */
-                LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
-                                       &pInstance->pBandDefinitions[i],
-                                       &Coefficients);
-
-                /*
-                 * Set the coefficients
-                 */
-                PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
-                                                   &pInstance->pEQNB_Taps[i],
-                                                   &Coefficients);
-                break;
-            }
-
-            case    LVEQNB_SinglePrecision:
-            {
-                PK_C16_Coefs_t      Coefficients;
-
-                /*
-                 * Calculate the single precision coefficients
-                 */
-                LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
-                                       &pInstance->pBandDefinitions[i],
-                                       &Coefficients);
-
-                /*
-                 * Set the coefficients
-                 */
-                PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
-                                                   &pInstance->pEQNB_Taps[i],
-                                                   &Coefficients);
-                break;
-            }
-#endif
-            default:
-                break;
-        }
-    }
-
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVEQNB_ClearFilterHistory                                   */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Clears the filter data history                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInstance           Pointer to the instance                                     */
-/*                                                                                  */
-/************************************************************************************/
-#ifndef BUILD_FLOAT
-void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
-{
-    LVM_INT16       *pTapAddress;
-    LVM_INT16       NumTaps;
-
-
-    pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
-    NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
-
-    if (NumTaps != 0)
-    {
-        LoadConst_16(0,                                 /* Clear the history, value 0 */
-                     pTapAddress,                       /* Destination */
-                     NumTaps);                          /* Number of words */
-    }
-}
-#else
-void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
-{
-    LVM_FLOAT       *pTapAddress;
-    LVM_INT16       NumTaps;
-
-    pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
-    NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
-                                    sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
-
-    if (NumTaps != 0)
-    {
-        LoadConst_Float(0,                                 /* Clear the history, value 0 */
-                        pTapAddress,                       /* Destination */
-                        NumTaps);                          /* Number of words */
-    }
-}
-#endif
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_Control                                              */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Sets or changes the LifeVibes module parameters.                                    */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pParams                 Pointer to a parameter structure                            */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_Success          Always succeeds                                             */
-/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
-/*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
-/*                          number of bands is non-zero                                 */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t        hInstance,
-                                      LVEQNB_Params_t        *pParams)
-{
-
-    LVEQNB_Instance_t    *pInstance = (LVEQNB_Instance_t  *)hInstance;
-    LVM_INT16            bChange    = LVM_FALSE;
-    LVM_INT16            i = 0;
-    LVEQNB_Mode_en       OperatingModeSave ;
-
-    /*
-     * Check for error conditions
-     */
-    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    OperatingModeSave = pInstance->Params.OperatingMode;
-
-    /* Set the alpha factor of the mixer */
-    if (pParams->SampleRate != pInstance->Params.SampleRate)
-    {
-        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-    }
-
-
-    if( (pInstance->Params.NBands            !=  pParams->NBands          ) ||
-        (pInstance->Params.OperatingMode     !=  pParams->OperatingMode   ) ||
-        (pInstance->Params.pBandDefinition   !=  pParams->pBandDefinition ) ||
-        (pInstance->Params.SampleRate        !=  pParams->SampleRate      ) ||
-        (pInstance->Params.SourceFormat      !=  pParams->SourceFormat    ))
-    {
-
-        bChange = LVM_TRUE;
-    }
-    else
-    {
-        for(i = 0; i < pParams->NBands; i++)
-        {
-
-            if((pInstance->pBandDefinitions[i].Frequency  != pParams->pBandDefinition[i].Frequency )||
-                (pInstance->pBandDefinitions[i].Gain       != pParams->pBandDefinition[i].Gain      )||
-                (pInstance->pBandDefinitions[i].QFactor    != pParams->pBandDefinition[i].QFactor   ))
-            {
-
-                bChange = LVM_TRUE;
-            }
-        }
-    }
-
-
-    // During operating mode transition, there is a race condition where the mode
-    // is still LVEQNB_ON, but the effect is considered disabled in the upper layers.
-    // modeChange handles this special race condition.
-    const int /* bool */ modeChange = pParams->OperatingMode != OperatingModeSave
-            || (OperatingModeSave == LVEQNB_ON
-                    && pInstance->bInOperatingModeTransition
-                    && LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
-
-    if (bChange || modeChange) {
-
-        /*
-         * If the sample rate has changed clear the history
-         */
-        if (pInstance->Params.SampleRate != pParams->SampleRate)
-        {
-            LVEQNB_ClearFilterHistory(pInstance);           /* Clear the history */
-        }
-
-        /*
-         * Update the instance parameters
-         */
-        pInstance->Params = *pParams;
-
-
-        /*
-         * Reset the filters except if the algo is switched off
-         */
-        if(pParams->OperatingMode != LVEQNB_BYPASS){
-            /*
-             * Reset the filters as all parameters could have changed
-             */
-            LVEQNB_SetFilters(pInstance,                        /* Instance pointer */
-                              pParams);                         /* New parameters */
-
-            /*
-             * Update the filters
-             */
-            LVEQNB_SetCoefficients(pInstance);                  /* Instance pointer */
-        }
-
-        if (modeChange) {
-            if(pParams->OperatingMode == LVEQNB_ON)
-            {
-#ifdef BUILD_FLOAT
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
-#else
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
-#endif
-                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
-                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
-            }
-            else
-            {
-                /* Stay on the ON operating mode until the transition is done */
-                // This may introduce a state race condition if the effect is enabled again
-                // while in transition.  This is fixed in the modeChange logic.
-                pInstance->Params.OperatingMode = LVEQNB_ON;
-#ifdef BUILD_FLOAT
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
-#else
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
-                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
-#endif
-                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
-                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
-            }
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
-            pInstance->bInOperatingModeTransition = LVM_TRUE;
-        }
-
-    }
-    return(LVEQNB_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_BypassMixerCallBack                                  */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  CallBack function of the mixer                                                      */
-/*  transition                                                                          */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
-                                      void *pGeneralPurpose,
-                                      LVM_INT16 CallbackParam)
-{
-    LVEQNB_Instance_t      *pInstance =(LVEQNB_Instance_t  *)hInstance;
-    LVM_Callback            CallBack  = pInstance->Capabilities.CallBack;
-
-    (void) pGeneralPurpose;
-
-     /*
-      * Send an ALGOFF event if the ON->OFF switch transition is finished
-      */
-#ifdef BUILD_FLOAT
-    if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
-       (CallbackParam == 0)){
-#else
-    if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
-       (CallbackParam == 0)){
-#endif
-        pInstance->Params.OperatingMode = LVEQNB_BYPASS;
-        if (CallBack != LVM_NULL){
-            CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
-        }
-    }
-
-    /*
-     *  Exit transition state
-     */
-    pInstance->bInOperatingModeTransition = LVM_FALSE;
-
-    return 1;
-}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
new file mode 100644
index 0000000..6bb4a7e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Defines                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
+#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVEQNB_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the N-Band equaliser parameters. The current parameter set is returned via  */
+/*  the parameter pointer.                                                              */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeds                                                    */
+/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
+                                            LVEQNB_Params_t     *pParams)
+{
+
+    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
+
+   /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    *pParams = pInstance->Params;
+
+    return(LVEQNB_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                 LVEQNB_GetCapabilities                                 */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the N-Band equaliser capabilities. The current capabilities are returned    */
+/*  via the pointer.                                                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                Instance handle                                        */
+/*  pCapabilities            Pointer to an empty capability structure               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVEQNB_Success           Succeeds                                               */
+/*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function may be interrupted by the LVEQNB_Process function             */
+/*                                                                                  */
+/************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
+                                              LVEQNB_Capabilities_t     *pCapabilities)
+{
+
+    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
+
+    if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    *pCapabilities = pInstance->Capabilities;
+
+    return(LVEQNB_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_SetFilters                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter type based on the definition.                                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  void                Nothing                                                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. To select the biquad type the follow rules are applied:                      */
+/*          Double precision    if (fc <= fs/110)                                   */
+/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
+/*          Single precision    otherwise                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
+                          LVEQNB_Params_t       *pParams)
+{
+    extern const LVM_UINT32   LVEQNB_SampleRateTab[];           /* Sample rate table */
+
+    LVM_UINT16          i;                                      /* Filter band index */
+    LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
+    LVM_UINT32          fc;                                     /* Filter centre frequency */
+    LVM_INT16           QFactor;                                /* Filter Q factor */
+
+    pInstance->NBands = pParams->NBands;
+
+    for (i=0; i<pParams->NBands; i++)
+    {
+        /*
+         * Get the filter settings
+         */
+        fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
+        QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
+
+        pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
+
+        /*
+         * Check for out of range frequencies
+         */
+        if (fc > (fs >> 1))
+        {
+            pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
+        }
+
+        /*
+         * Copy the filter definition to persistant memory
+         */
+        pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
+
+    }
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_SetCoefficients                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter coefficients. This uses the type to select single or double     */
+/*  precision coefficients.                                                         */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVEQNB_SetCoefficients(LVEQNB_Instance_t     *pInstance)
+{
+
+    LVM_UINT16              i;                          /* Filter band index */
+    LVEQNB_BiquadType_en    BiquadType;                 /* Filter biquad type */
+
+    /*
+     * Set the coefficients for each band by the init function
+     */
+    for (i=0; i<pInstance->Params.NBands; i++)
+    {
+
+        /*
+         * Check band type for correct initialisation method and recalculate the coefficients
+         */
+        BiquadType = pInstance->pBiquadType[i];
+        switch  (BiquadType)
+        {
+            case    LVEQNB_SinglePrecision_Float:
+            {
+                PK_FLOAT_Coefs_t      Coefficients;
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+                                       &pInstance->pBandDefinitions[i],
+                                       &Coefficients);
+                /*
+                 * Set the coefficients
+                 */
+                PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
+                                                   &pInstance->pEQNB_Taps_Float[i],
+                                                   &Coefficients);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_ClearFilterHistory                                   */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Clears the filter data history                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*                                                                                  */
+/************************************************************************************/
+void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
+{
+    LVM_FLOAT       *pTapAddress;
+    LVM_INT16       NumTaps;
+
+    pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
+    NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
+                                    sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
+
+    if (NumTaps != 0)
+    {
+        LoadConst_Float(0,                                 /* Clear the history, value 0 */
+                        pTapAddress,                       /* Destination */
+                        NumTaps);                          /* Number of words */
+    }
+}
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Control                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LifeVibes module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_Success          Always succeeds                                             */
+/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
+/*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
+/*                          number of bands is non-zero                                 */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t        hInstance,
+                                      LVEQNB_Params_t        *pParams)
+{
+
+    LVEQNB_Instance_t    *pInstance = (LVEQNB_Instance_t  *)hInstance;
+    LVM_INT16            bChange    = LVM_FALSE;
+    LVM_INT16            i = 0;
+    LVEQNB_Mode_en       OperatingModeSave ;
+
+    /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    OperatingModeSave = pInstance->Params.OperatingMode;
+
+    /* Set the alpha factor of the mixer */
+    if (pParams->SampleRate != pInstance->Params.SampleRate)
+    {
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+    }
+
+    if( (pInstance->Params.NBands            !=  pParams->NBands          ) ||
+        (pInstance->Params.OperatingMode     !=  pParams->OperatingMode   ) ||
+        (pInstance->Params.pBandDefinition   !=  pParams->pBandDefinition ) ||
+        (pInstance->Params.SampleRate        !=  pParams->SampleRate      ) ||
+        (pInstance->Params.SourceFormat      !=  pParams->SourceFormat    ))
+    {
+
+        bChange = LVM_TRUE;
+    }
+    else
+    {
+        for(i = 0; i < pParams->NBands; i++)
+        {
+
+            if((pInstance->pBandDefinitions[i].Frequency  != pParams->pBandDefinition[i].Frequency )||
+                (pInstance->pBandDefinitions[i].Gain       != pParams->pBandDefinition[i].Gain      )||
+                (pInstance->pBandDefinitions[i].QFactor    != pParams->pBandDefinition[i].QFactor   ))
+            {
+
+                bChange = LVM_TRUE;
+            }
+        }
+    }
+
+    // During operating mode transition, there is a race condition where the mode
+    // is still LVEQNB_ON, but the effect is considered disabled in the upper layers.
+    // modeChange handles this special race condition.
+    const int /* bool */ modeChange = pParams->OperatingMode != OperatingModeSave
+            || (OperatingModeSave == LVEQNB_ON
+                    && pInstance->bInOperatingModeTransition
+                    && LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
+
+    if (bChange || modeChange) {
+
+        /*
+         * If the sample rate has changed clear the history
+         */
+        if (pInstance->Params.SampleRate != pParams->SampleRate)
+        {
+            LVEQNB_ClearFilterHistory(pInstance);           /* Clear the history */
+        }
+
+        /*
+         * Update the instance parameters
+         */
+        pInstance->Params = *pParams;
+
+        /*
+         * Reset the filters except if the algo is switched off
+         */
+        if(pParams->OperatingMode != LVEQNB_BYPASS){
+            /*
+             * Reset the filters as all parameters could have changed
+             */
+            LVEQNB_SetFilters(pInstance,                        /* Instance pointer */
+                              pParams);                         /* New parameters */
+
+            /*
+             * Update the filters
+             */
+            LVEQNB_SetCoefficients(pInstance);                  /* Instance pointer */
+        }
+
+        if (modeChange) {
+            if(pParams->OperatingMode == LVEQNB_ON)
+            {
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
+                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
+                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+            }
+            else
+            {
+                /* Stay on the ON operating mode until the transition is done */
+                // This may introduce a state race condition if the effect is enabled again
+                // while in transition.  This is fixed in the modeChange logic.
+                pInstance->Params.OperatingMode = LVEQNB_ON;
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
+                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
+                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+            }
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+            pInstance->bInOperatingModeTransition = LVM_TRUE;
+        }
+
+    }
+    return(LVEQNB_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_BypassMixerCallBack                                  */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  CallBack function of the mixer                                                      */
+/*  transition                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
+                                      void *pGeneralPurpose,
+                                      LVM_INT16 CallbackParam)
+{
+    LVEQNB_Instance_t      *pInstance =(LVEQNB_Instance_t  *)hInstance;
+    LVM_Callback            CallBack  = pInstance->Capabilities.CallBack;
+
+    (void) pGeneralPurpose;
+
+     /*
+      * Send an ALGOFF event if the ON->OFF switch transition is finished
+      */
+    if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
+       (CallbackParam == 0)){
+        pInstance->Params.OperatingMode = LVEQNB_BYPASS;
+        if (CallBack != LVM_NULL){
+            CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
+        }
+    }
+
+    /*
+     *  Exit transition state
+     */
+    pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+    return 1;
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
deleted file mode 100644
index de1bbb7..0000000
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVEQNB.h"
-#include "LVEQNB_Private.h"
-#include "InstAlloc.h"
-#include <string.h> /* For memset */
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_Memory                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used for memory allocation and free. It can be called in           */
-/*  two ways:                                                                           */
-/*                                                                                      */
-/*      hInstance = NULL                Returns the memory requirements                 */
-/*      hInstance = Instance handle     Returns the memory requirements and             */
-/*                                      allocated base addresses for the instance       */
-/*                                                                                      */
-/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
-/*  base address pointers are NULL on return.                                           */
-/*                                                                                      */
-/*  When the function is called for free (hInstance = Instance Handle) the memory       */
-/*  table returns the allocated memory and base addresses used during initialisation.   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pMemoryTable            Pointer to an empty memory definition table                 */
-/*  pCapabilities           Pointer to the instance capabilities                        */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS          Succeeded                                                   */
-/*  LVEQNB_NULLADDRESS      When any of pMemoryTable and pCapabilities is NULL address  */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t            hInstance,
-                                     LVEQNB_MemTab_t            *pMemoryTable,
-                                     LVEQNB_Capabilities_t      *pCapabilities)
-{
-
-    INST_ALLOC          AllocMem;
-    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t *)hInstance;
-
-
-    if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-
-    /*
-     * Fill in the memory table
-     */
-    if (hInstance == LVM_NULL)
-    {
-        /*
-         * Instance memory
-         */
-        InstAlloc_Init(&AllocMem,
-                       LVM_NULL);
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            sizeof(LVEQNB_Instance_t));
-        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&AllocMem);
-        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment    = LVEQNB_INSTANCE_ALIGN;
-        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type         = LVEQNB_PERSISTENT;
-        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
-
-
-        /*
-         * Persistant data memory
-         */
-        InstAlloc_Init(&AllocMem,
-                       LVM_NULL);
-#ifdef BUILD_FLOAT
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
-        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
-                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
-        /* Equaliser Biquad Taps */
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)));
-        /* Filter definitions */
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));
-        /* Biquad types */
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));
-#else
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            sizeof(Biquad_2I_Order2_Taps_t));
-        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
-                            sizeof(Biquad_2I_Order2_Taps_t));
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));        /* Filter definitions */
-        InstAlloc_AddMember(&AllocMem,
-                            (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));    /* Biquad types */
-#endif
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&AllocMem);
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment    = LVEQNB_DATA_ALIGN;
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type         = LVEQNB_PERSISTENT_DATA;
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
-
-        /*
-         * Persistant coefficient memory
-         */
-        InstAlloc_Init(&AllocMem,
-                       LVM_NULL);
-#ifdef BUILD_FLOAT
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            sizeof(Biquad_FLOAT_Instance_t));
-        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
-                            sizeof(Biquad_FLOAT_Instance_t));
-        /* Equaliser Biquad Instance */
-        InstAlloc_AddMember(&AllocMem,
-                            pCapabilities->MaxBands * sizeof(Biquad_FLOAT_Instance_t));
-#else
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            sizeof(Biquad_Instance_t));
-        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
-                            sizeof(Biquad_Instance_t));
-        InstAlloc_AddMember(&AllocMem,
-                            pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
-#endif
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&AllocMem);
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment    = LVEQNB_COEF_ALIGN;
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type         = LVEQNB_PERSISTENT_COEF;
-        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
-
-        /*
-         * Scratch memory
-         */
-        InstAlloc_Init(&AllocMem,
-                       LVM_NULL);
-#ifdef BUILD_FLOAT
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * \
-                                             pCapabilities->MaxBlockSize);
-#else
-        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
-                            LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
-#endif
-        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size              = InstAlloc_GetTotal(&AllocMem);
-        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment         = LVEQNB_SCRATCH_ALIGN;
-        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type              = LVEQNB_SCRATCH;
-        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress      = LVM_NULL;
-    }
-    else
-    {
-        /* Read back memory allocation table */
-        *pMemoryTable = pInstance->MemoryTable;
-    }
-
-    return(LVEQNB_SUCCESS);
-}
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_Init                                                 */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Create and initialisation function for the N-Band equaliser module                  */
-/*                                                                                      */
-/*  This function can be used to create an algorithm instance by calling with           */
-/*  hInstance set to NULL. In this case the algorithm returns the new instance          */
-/*  handle.                                                                             */
-/*                                                                                      */
-/*  This function can be used to force a full re-initialisation of the algorithm        */
-/*  by calling with hInstance = Instance Handle. In this case the memory table          */
-/*  should be correct for the instance, this can be ensured by calling the function     */
-/*  DBE_Memory before calling this function.                                            */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pMemoryTable            Pointer to the memory definition table                      */
-/*  pCapabilities           Pointer to the instance capabilities                        */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS          Initialisation succeeded                                    */
-/*  LVEQNB_NULLADDRESS        When pCapabilities or pMemoryTableis or phInstance are NULL */
-/*  LVEQNB_NULLADDRESS        One or more of the memory regions has a NULL base address   */
-/*                          pointer for a memory region with a non-zero size.           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  The instance handle is the pointer to the base address of the first memory      */
-/*      region.                                                                         */
-/*  2.  This function must not be interrupted by the LVEQNB_Process function            */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t          *phInstance,
-                                   LVEQNB_MemTab_t          *pMemoryTable,
-                                   LVEQNB_Capabilities_t    *pCapabilities)
-{
-
-    LVEQNB_Instance_t   *pInstance;
-    LVM_UINT32          MemSize;
-    INST_ALLOC          AllocMem;
-    LVM_INT32           i;
-
-    /*
-     * Check for NULL pointers
-     */
-    if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    /*
-     * Check the memory table for NULL pointers
-     */
-    for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
-    {
-        if (pMemoryTable->Region[i].Size!=0)
-        {
-            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
-            {
-                return(LVEQNB_NULLADDRESS);
-            }
-        }
-    }
-
-    /*
-     * Set the instance handle if not already initialised
-     */
-
-    InstAlloc_Init(&AllocMem,  pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
-
-    if (*phInstance == LVM_NULL)
-    {
-        *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
-    }
-    pInstance =(LVEQNB_Instance_t  *)*phInstance;
-
-
-
-    /*
-     * Save the memory table in the instance structure
-     */
-    pInstance->Capabilities = *pCapabilities;
-
-
-    /*
-     * Save the memory table in the instance structure and
-     * set the structure pointers
-     */
-    pInstance->MemoryTable       = *pMemoryTable;
-
-    /*
-     * Allocate coefficient memory
-     */
-    InstAlloc_Init(&AllocMem,
-                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
-
-#ifdef BUILD_FLOAT
-    /* Equaliser Biquad Instance */
-    pInstance->pEQNB_FilterState_Float = InstAlloc_AddMember(&AllocMem,
-                                                             pCapabilities->MaxBands * \
-                                                             sizeof(Biquad_FLOAT_Instance_t));
-#else
-    pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
-                                                       pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
-#endif
-
-
-
-    /*
-     * Allocate data memory
-     */
-    InstAlloc_Init(&AllocMem,
-                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
-
-#ifdef BUILD_FLOAT
-    MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
-    pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t *)InstAlloc_AddMember(&AllocMem,
-                                                                                       MemSize);
-#else
-    MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
-    pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
-                                                                           MemSize);
-#endif
-    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
-    pInstance->pBandDefinitions  = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
-                                                                           MemSize);
-    // clear all the bands, setting their gain to 0, otherwise when applying new params,
-    // it will compare against uninitialized values
-    memset(pInstance->pBandDefinitions, 0, MemSize);
-    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
-    pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
-                                                                         MemSize);
-
-
-    /*
-     * Internally map, structure and allign scratch memory
-     */
-    InstAlloc_Init(&AllocMem,
-                   pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
-
-#ifdef BUILD_FLOAT
-    pInstance->pFastTemporary = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem,
-                                                                 sizeof(LVM_FLOAT));
-#else
-    pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
-                                                                 sizeof(LVM_INT16));
-#endif
-
-    /*
-     * Update the instance parameters
-     */
-    pInstance->Params.NBands          = 0;
-    pInstance->Params.OperatingMode   = LVEQNB_BYPASS;
-    pInstance->Params.pBandDefinition = LVM_NULL;
-    pInstance->Params.SampleRate      = LVEQNB_FS_8000;
-    pInstance->Params.SourceFormat    = LVEQNB_STEREO;
-
-    /*
-     * Initialise the filters
-     */
-    LVEQNB_SetFilters(pInstance,                        /* Set the filter types */
-                      &pInstance->Params);
-
-    LVEQNB_SetCoefficients(pInstance);                  /* Set the filter coefficients */
-
-    LVEQNB_ClearFilterHistory(pInstance);               /* Clear the filter history */
-
-    /*
-     * Initialise the bypass variables
-     */
-    pInstance->BypassMixer.MixerStream[0].CallbackSet        = 0;
-    pInstance->BypassMixer.MixerStream[0].CallbackParam      = 0;
-    pInstance->BypassMixer.MixerStream[0].pCallbackHandle    = (void*)pInstance;
-    pInstance->BypassMixer.MixerStream[0].pCallBack          = LVEQNB_BypassMixerCallBack;
-
-    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
-    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
-
-
-    pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
-    pInstance->BypassMixer.MixerStream[1].CallbackParam      = 0;
-    pInstance->BypassMixer.MixerStream[1].pCallbackHandle    = LVM_NULL;
-    pInstance->BypassMixer.MixerStream[1].pCallBack          = LVM_NULL;
-#ifdef BUILD_FLOAT
-    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1], 0, 1.0f);
-    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1], 0, LVM_FS_8000, 2);
-#else
-    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
-    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
-#endif
-
-    pInstance->bInOperatingModeTransition      = LVM_FALSE;
-
-    return(LVEQNB_SUCCESS);
-}
-
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
new file mode 100644
index 0000000..271a914
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "InstAlloc.h"
+#include <string.h> /* For memset */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the instance capabilities                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When any of pMemoryTable and pCapabilities is NULL address  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t            hInstance,
+                                     LVEQNB_MemTab_t            *pMemoryTable,
+                                     LVEQNB_Capabilities_t      *pCapabilities)
+{
+
+    INST_ALLOC          AllocMem;
+    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t *)hInstance;
+
+    if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(LVEQNB_Instance_t));
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment    = LVEQNB_INSTANCE_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type         = LVEQNB_PERSISTENT;
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistant data memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+        /* Equaliser Biquad Taps */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)));
+        /* Filter definitions */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));
+        /* Biquad types */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment    = LVEQNB_DATA_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type         = LVEQNB_PERSISTENT_DATA;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistant coefficient memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_FLOAT_Instance_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_FLOAT_Instance_t));
+        /* Equaliser Biquad Instance */
+        InstAlloc_AddMember(&AllocMem,
+                            pCapabilities->MaxBands * sizeof(Biquad_FLOAT_Instance_t));
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment    = LVEQNB_COEF_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type         = LVEQNB_PERSISTENT_COEF;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * \
+                                             pCapabilities->MaxBlockSize);
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size              = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment         = LVEQNB_SCRATCH_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type              = LVEQNB_SCRATCH;
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress      = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVEQNB_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Create and initialisation function for the N-Band equaliser module                  */
+/*                                                                                      */
+/*  This function can be used to create an algorithm instance by calling with           */
+/*  hInstance set to NULL. In this case the algorithm returns the new instance          */
+/*  handle.                                                                             */
+/*                                                                                      */
+/*  This function can be used to force a full re-initialisation of the algorithm        */
+/*  by calling with hInstance = Instance Handle. In this case the memory table          */
+/*  should be correct for the instance, this can be ensured by calling the function     */
+/*  DBE_Memory before calling this function.                                            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pCapabilities           Pointer to the instance capabilities                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Initialisation succeeded                                    */
+/*  LVEQNB_NULLADDRESS        When pCapabilities or pMemoryTableis or phInstance are NULL */
+/*  LVEQNB_NULLADDRESS        One or more of the memory regions has a NULL base address   */
+/*                          pointer for a memory region with a non-zero size.           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  The instance handle is the pointer to the base address of the first memory      */
+/*      region.                                                                         */
+/*  2.  This function must not be interrupted by the LVEQNB_Process function            */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t          *phInstance,
+                                   LVEQNB_MemTab_t          *pMemoryTable,
+                                   LVEQNB_Capabilities_t    *pCapabilities)
+{
+
+    LVEQNB_Instance_t   *pInstance;
+    LVM_UINT32          MemSize;
+    INST_ALLOC          AllocMem;
+    LVM_INT32           i;
+
+    /*
+     * Check for NULL pointers
+     */
+    if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /*
+     * Check the memory table for NULL pointers
+     */
+    for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
+    {
+        if (pMemoryTable->Region[i].Size!=0)
+        {
+            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+            {
+                return(LVEQNB_NULLADDRESS);
+            }
+        }
+    }
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+
+    InstAlloc_Init(&AllocMem,  pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
+
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
+    }
+    pInstance =(LVEQNB_Instance_t  *)*phInstance;
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+    /*
+     * Save the memory table in the instance structure and
+     * set the structure pointers
+     */
+    pInstance->MemoryTable       = *pMemoryTable;
+
+    /*
+     * Allocate coefficient memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+    /* Equaliser Biquad Instance */
+    pInstance->pEQNB_FilterState_Float = (Biquad_FLOAT_Instance_t *)
+        InstAlloc_AddMember(&AllocMem, pCapabilities->MaxBands * \
+                                                       sizeof(Biquad_FLOAT_Instance_t));
+
+    /*
+     * Allocate data memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+
+    MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t));
+    pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t *)InstAlloc_AddMember(&AllocMem,
+                                                                                       MemSize);
+    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
+    pInstance->pBandDefinitions  = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
+                                                                           MemSize);
+    // clear all the bands, setting their gain to 0, otherwise when applying new params,
+    // it will compare against uninitialized values
+    memset(pInstance->pBandDefinitions, 0, MemSize);
+    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
+    pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
+                                                                         MemSize);
+
+    /*
+     * Internally map, structure and allign scratch memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
+
+    pInstance->pFastTemporary = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem,
+                                                                 sizeof(LVM_FLOAT));
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params.NBands          = 0;
+    pInstance->Params.OperatingMode   = LVEQNB_BYPASS;
+    pInstance->Params.pBandDefinition = LVM_NULL;
+    pInstance->Params.SampleRate      = LVEQNB_FS_8000;
+    pInstance->Params.SourceFormat    = LVEQNB_STEREO;
+
+    /*
+     * Initialise the filters
+     */
+    LVEQNB_SetFilters(pInstance,                        /* Set the filter types */
+                      &pInstance->Params);
+
+    LVEQNB_SetCoefficients(pInstance);                  /* Set the filter coefficients */
+
+    LVEQNB_ClearFilterHistory(pInstance);               /* Clear the filter history */
+
+    /*
+     * Initialise the bypass variables
+     */
+    pInstance->BypassMixer.MixerStream[0].CallbackSet        = 0;
+    pInstance->BypassMixer.MixerStream[0].CallbackParam      = 0;
+    pInstance->BypassMixer.MixerStream[0].pCallbackHandle    = (void*)pInstance;
+    pInstance->BypassMixer.MixerStream[0].pCallBack          = LVEQNB_BypassMixerCallBack;
+
+    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
+    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
+
+    pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+    pInstance->BypassMixer.MixerStream[1].CallbackParam      = 0;
+    pInstance->BypassMixer.MixerStream[1].pCallbackHandle    = LVM_NULL;
+    pInstance->BypassMixer.MixerStream[1].pCallBack          = LVM_NULL;
+    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1], 0, 1.0f);
+    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1], 0, LVM_FS_8000, 2);
+
+    pInstance->bInOperatingModeTransition      = LVM_FALSE;
+
+    return(LVEQNB_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index a9cd5fd..40facfb 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -18,11 +18,6 @@
 #ifndef __LVEQNB_PRIVATE_H__
 #define __LVEQNB_PRIVATE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -65,24 +60,19 @@
 /* Filter biquad types */
 typedef enum
 {
-#ifdef BUILD_FLOAT
     LVEQNB_SinglePrecision_Float = -1,
-#endif
     LVEQNB_SinglePrecision = 0,
     LVEQNB_DoublePrecision = 1,
     LVEQNB_OutOfRange      = 2,
     LVEQNB_BIQUADTYPE_MAX  = LVM_MAXINT_32
 } LVEQNB_BiquadType_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
 
-
-
 /* Instance structure */
 typedef struct
 {
@@ -92,20 +82,10 @@
     LVEQNB_Capabilities_t           Capabilities;       /* Instance capabilities */
 
     /* Aligned memory pointers */
-#ifdef BUILD_FLOAT
     LVM_FLOAT                      *pFastTemporary;        /* Fast temporary data base address */
-#else
-    LVM_INT16                      *pFastTemporary;        /* Fast temporary data base address */
-#endif
 
-#ifdef BUILD_FLOAT
     Biquad_2I_Order2_FLOAT_Taps_t   *pEQNB_Taps_Float;        /* Equaliser Taps */
     Biquad_FLOAT_Instance_t         *pEQNB_FilterState_Float; /* State for each filter band */
-#else
-    /* Process variables */
-    Biquad_2I_Order2_Taps_t         *pEQNB_Taps;        /* Equaliser Taps */
-    Biquad_Instance_t               *pEQNB_FilterState; /* State for each filter band */
-#endif
 
     /* Filter definitions and call back */
     LVM_UINT16                      NBands;             /* Number of bands */
@@ -113,17 +93,12 @@
     LVEQNB_BiquadType_en            *pBiquadType;       /* Filter biquad types */
 
     /* Bypass variable */
-#ifdef BUILD_FLOAT
     LVMixer3_2St_FLOAT_st     BypassMixer;
-#else
-    LVMixer3_2St_st           BypassMixer;              /* Bypass mixer used in transitions */
-#endif
 
     LVM_INT16               bInOperatingModeTransition; /* Operating mode transition flag */
 
 } LVEQNB_Instance_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* Function prototypes                                                                  */
@@ -136,25 +111,11 @@
 void    LVEQNB_SetCoefficients(LVEQNB_Instance_t    *pInstance);
 
 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance);
-#ifdef BUILD_FLOAT
 LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
                                               LVEQNB_BandDef_t  *pFilterDefinition,
                                               PK_FLOAT_Coefs_t    *pCoefficients);
-#else
-LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
-                                              LVEQNB_BandDef_t  *pFilterDefinition,
-                                              PK_C16_Coefs_t    *pCoefficients);
-
-LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
-                                              LVEQNB_BandDef_t  *pFilterDefinition,
-                                              PK_C32_Coefs_t    *pCoefficients);
-#endif
 
 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, void *pGeneralPurpose, LVM_INT16 CallbackParam);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* __LVEQNB_PRIVATE_H__ */
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
deleted file mode 100644
index d188c0e..0000000
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-
-#include "LVEQNB.h"
-#include "LVEQNB_Private.h"
-#include "VectorArithmetic.h"
-#include "BIQUAD.h"
-
-#include <log/log.h>
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Defines                                                                             */
-/*                                                                                      */
-/****************************************************************************************/
-
-#define SHIFT       13
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_Process                                              */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Process function for the N-Band Equaliser module.                                   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pInData                 Pointer to the input data                                   */
-/*  pOutData                Pointer to the output data                                  */
-/*  NumSamples              Number of samples in the input buffer                       */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVEQNB_SUCCESS          Succeeded                                                   */
-/*  LVEQNB_NULLADDRESS      When hInstance, pInData or pOutData are NULL                */
-/*  LVEQNB_ALIGNMENTERROR   When pInData or pOutData are not 32-bit aligned             */
-/*  LVEQNB_TOOMANYSAMPLES   NumSamples was larger than the maximum block size           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
-                                      const LVM_FLOAT       *pInData,
-                                      LVM_FLOAT             *pOutData,
-                                      const LVM_UINT16      NrFrames)
-{                                     // updated to use samples = frames * channels.
-    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
-
-#ifdef SUPPORT_MC
-    // Mono passed in as stereo
-    const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
-        ? 2 : pInstance->Params.NrChannels;
-#else
-    const LVM_INT32 NrChannels = 2; // FCC_2
-#endif
-    const LVM_INT32 NrSamples = NrChannels * NrFrames;
-
-     /* Check for NULL pointers */
-    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    /* Check if the input and output data buffers are 32-bit aligned */
-    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
-    {
-        return LVEQNB_ALIGNMENTERROR;
-    }
-
-    LVM_FLOAT * const pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
-
-    /*
-    * Check the number of frames is not too large
-    */
-    if (NrFrames > pInstance->Capabilities.MaxBlockSize)
-    {
-        return LVEQNB_TOOMANYSAMPLES;
-    }
-
-    if (pInstance->Params.OperatingMode == LVEQNB_ON)
-    {
-        /*
-         * Copy input data in to scratch buffer
-         */
-        Copy_Float(pInData,     /* Source */
-                   pScratch,    /* Destination */
-                   (LVM_INT16)NrSamples);
-
-        /*
-         * For each section execte the filter unless the gain is 0dB
-         */
-        if (pInstance->NBands != 0)
-        {
-            for (LVM_UINT16 i = 0; i < pInstance->NBands; i++)
-            {
-                /*
-                 * Check if band is non-zero dB gain
-                 */
-                if (pInstance->pBandDefinitions[i].Gain != 0)
-                {
-                    /*
-                     * Get the address of the biquad instance
-                     */
-                    Biquad_FLOAT_Instance_t *pBiquad = &pInstance->pEQNB_FilterState_Float[i];
-
-
-                    /*
-                     * Select single or double precision as required
-                     */
-                    switch (pInstance->pBiquadType[i])
-                    {
-                        case LVEQNB_SinglePrecision_Float:
-                        {
-#ifdef SUPPORT_MC
-                            PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad,
-                                                          pScratch,
-                                                          pScratch,
-                                                          (LVM_INT16)NrFrames,
-                                                          (LVM_INT16)NrChannels);
-#else
-                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
-                                                          pScratch,
-                                                          pScratch,
-                                                          (LVM_INT16)NrFrames);
-#endif
-                            break;
-                        }
-                        default:
-                            break;
-                    }
-                }
-            }
-        }
-
-
-        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
-#ifdef SUPPORT_MC
-            LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer,
-                                       pScratch,
-                                       pInData,
-                                       pScratch,
-                                       (LVM_INT16)NrFrames,
-                                       (LVM_INT16)NrChannels);
-#else
-            LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
-                                       pScratch,
-                                       pInData,
-                                       pScratch,
-                                       (LVM_INT16)NrSamples);
-#endif
-            // duplicate with else clause(s)
-            Copy_Float(pScratch,                         /* Source */
-                       pOutData,                         /* Destination */
-                       (LVM_INT16)NrSamples);            /* All channel samples */
-        }
-        else{
-            Copy_Float(pScratch,              /* Source */
-                       pOutData,              /* Destination */
-                       (LVM_INT16)NrSamples); /* All channel samples */
-        }
-    }
-    else
-    {
-        /*
-         * Mode is OFF so copy the data if necessary
-         */
-        if (pInData != pOutData)
-        {
-            Copy_Float(pInData,                          /* Source */
-                       pOutData,                         /* Destination */
-                       (LVM_INT16)NrSamples);            /* All channel samples */
-        }
-    }
-    return LVEQNB_SUCCESS;
-
-}
-#else
-LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
-                                      const LVM_INT16       *pInData,
-                                      LVM_INT16             *pOutData,
-                                      LVM_UINT16            NumSamples)
-{
-
-    LVM_UINT16          i;
-    Biquad_Instance_t   *pBiquad;
-    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
-    LVM_INT32           *pScratch;
-
-
-     /* Check for NULL pointers */
-    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
-    {
-        return LVEQNB_NULLADDRESS;
-    }
-
-    /* Check if the input and output data buffers are 32-bit aligned */
-    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
-    {
-        return LVEQNB_ALIGNMENTERROR;
-    }
-
-    pScratch  = (LVM_INT32 *)pInstance->pFastTemporary;
-
-    /*
-    * Check the number of samples is not too large
-    */
-    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
-    {
-        return(LVEQNB_TOOMANYSAMPLES);
-    }
-
-    if (pInstance->Params.OperatingMode == LVEQNB_ON)
-    {
-        /*
-         * Convert from 16-bit to 32-bit
-         */
-        Int16LShiftToInt32_16x32((LVM_INT16 *)pInData,      /* Source */
-                                 pScratch,                  /* Destination */
-                                 (LVM_INT16)(2*NumSamples), /* Left and Right */
-                                 SHIFT);                    /* Scaling shift */
-
-        /*
-         * For each section execte the filter unless the gain is 0dB
-         */
-        if (pInstance->NBands != 0)
-        {
-            for (i=0; i<pInstance->NBands; i++)
-            {
-                /*
-                 * Check if band is non-zero dB gain
-                 */
-                if (pInstance->pBandDefinitions[i].Gain != 0)
-                {
-                    /*
-                     * Get the address of the biquad instance
-                     */
-                    pBiquad = &pInstance->pEQNB_FilterState[i];
-
-
-                    /*
-                     * Select single or double precision as required
-                     */
-                    switch (pInstance->pBiquadType[i])
-                    {
-                        case LVEQNB_SinglePrecision:
-                        {
-                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
-                                                          (LVM_INT32 *)pScratch,
-                                                          (LVM_INT32 *)pScratch,
-                                                          (LVM_INT16)NumSamples);
-                            break;
-                        }
-
-                        case LVEQNB_DoublePrecision:
-                        {
-                            PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
-                                                          (LVM_INT32 *)pScratch,
-                                                          (LVM_INT32 *)pScratch,
-                                                          (LVM_INT16)NumSamples);
-                            break;
-                        }
-                        default:
-                            break;
-                    }
-                }
-            }
-        }
-
-
-        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
-                /*
-                 * Convert from 32-bit to 16- bit and saturate
-                 */
-                Int32RShiftToInt16_Sat_32x16(pScratch,                      /* Source */
-                                             (LVM_INT16 *)pScratch,         /* Destination */
-                                             (LVM_INT16)(2*NumSamples),     /* Left and Right */
-                                             SHIFT);                        /* Scaling shift */
-
-                LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
-                                                (LVM_INT16 *)pScratch,
-                                                (LVM_INT16 *)pInData,
-                                                (LVM_INT16 *)pScratch,
-                                                (LVM_INT16)(2*NumSamples));
-
-                Copy_16((LVM_INT16*)pScratch,                           /* Source */
-                        pOutData,                                       /* Destination */
-                        (LVM_INT16)(2*NumSamples));                     /* Left and Right samples */
-        }
-        else{
-
-            /*
-             * Convert from 32-bit to 16- bit and saturate
-             */
-            Int32RShiftToInt16_Sat_32x16(pScratch,              /* Source */
-                                         pOutData,              /* Destination */
-                                         (LVM_INT16 )(2*NumSamples), /* Left and Right */
-                                         SHIFT);                /* Scaling shift */
-        }
-    }
-    else
-    {
-        /*
-         * Mode is OFF so copy the data if necessary
-         */
-        if (pInData != pOutData)
-        {
-            Copy_16(pInData,                                    /* Source */
-                    pOutData,                                   /* Destination */
-                    (LVM_INT16)(2*NumSamples));                 /* Left and Right samples */
-        }
-    }
-
-
-
-    return(LVEQNB_SUCCESS);
-
-}
-#endif
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
new file mode 100644
index 0000000..65eff53
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+#include <log/log.h>
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Defines                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define SHIFT       13
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Process                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the N-Band Equaliser module.                                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When hInstance, pInData or pOutData are NULL                */
+/*  LVEQNB_ALIGNMENTERROR   When pInData or pOutData are not 32-bit aligned             */
+/*  LVEQNB_TOOMANYSAMPLES   NumSamples was larger than the maximum block size           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
+                                      const LVM_FLOAT       *pInData,
+                                      LVM_FLOAT             *pOutData,
+                                      const LVM_UINT16      NrFrames)
+{                                     // updated to use samples = frames * channels.
+    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
+
+#ifdef SUPPORT_MC
+    // Mono passed in as stereo
+    const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
+        ? 2 : pInstance->Params.NrChannels;
+#else
+    const LVM_INT32 NrChannels = 2; // FCC_2
+#endif
+    const LVM_INT32 NrSamples = NrChannels * NrFrames;
+
+     /* Check for NULL pointers */
+    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /* Check if the input and output data buffers are 32-bit aligned */
+    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
+    {
+        return LVEQNB_ALIGNMENTERROR;
+    }
+
+    LVM_FLOAT * const pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
+
+    /*
+    * Check the number of frames is not too large
+    */
+    if (NrFrames > pInstance->Capabilities.MaxBlockSize)
+    {
+        return LVEQNB_TOOMANYSAMPLES;
+    }
+
+    if (pInstance->Params.OperatingMode == LVEQNB_ON)
+    {
+        /*
+         * Copy input data in to scratch buffer
+         */
+        Copy_Float(pInData,     /* Source */
+                   pScratch,    /* Destination */
+                   (LVM_INT16)NrSamples);
+
+        /*
+         * For each section execte the filter unless the gain is 0dB
+         */
+        if (pInstance->NBands != 0)
+        {
+            for (LVM_UINT16 i = 0; i < pInstance->NBands; i++)
+            {
+                /*
+                 * Check if band is non-zero dB gain
+                 */
+                if (pInstance->pBandDefinitions[i].Gain != 0)
+                {
+                    /*
+                     * Get the address of the biquad instance
+                     */
+                    Biquad_FLOAT_Instance_t *pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+
+                    /*
+                     * Select single or double precision as required
+                     */
+                    switch (pInstance->pBiquadType[i])
+                    {
+                        case LVEQNB_SinglePrecision_Float:
+                        {
+#ifdef SUPPORT_MC
+                            PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad,
+                                                          pScratch,
+                                                          pScratch,
+                                                          (LVM_INT16)NrFrames,
+                                                          (LVM_INT16)NrChannels);
+#else
+                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
+                                                          pScratch,
+                                                          pScratch,
+                                                          (LVM_INT16)NrFrames);
+#endif
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+#ifdef SUPPORT_MC
+            LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer,
+                                       pScratch,
+                                       pInData,
+                                       pScratch,
+                                       (LVM_INT16)NrFrames,
+                                       (LVM_INT16)NrChannels);
+#else
+            LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
+                                       pScratch,
+                                       pInData,
+                                       pScratch,
+                                       (LVM_INT16)NrSamples);
+#endif
+            // duplicate with else clause(s)
+            Copy_Float(pScratch,                         /* Source */
+                       pOutData,                         /* Destination */
+                       (LVM_INT16)NrSamples);            /* All channel samples */
+        }
+        else{
+            Copy_Float(pScratch,              /* Source */
+                       pOutData,              /* Destination */
+                       (LVM_INT16)NrSamples); /* All channel samples */
+        }
+    }
+    else
+    {
+        /*
+         * Mode is OFF so copy the data if necessary
+         */
+        if (pInData != pOutData)
+        {
+            Copy_Float(pInData,                          /* Source */
+                       pOutData,                         /* Destination */
+                       (LVM_INT16)NrSamples);            /* All channel samples */
+        }
+    }
+    return LVEQNB_SUCCESS;
+
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
deleted file mode 100644
index 453c42d..0000000
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Includes                                                                      */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVEQNB.h"
-#include "LVEQNB_Coeffs.h"
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Sample rate table                                                             */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Sample rate table for converting between the enumerated type and the actual
- * frequency
- */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-const LVM_UINT32    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
-                                              11025,
-                                              12000,
-                                              16000,
-                                              22050,
-                                              24000,
-                                              32000,
-                                              44100,
-                                              48000,
-                                              88200,
-                                              96000,
-                                              176400,
-                                              192000
-};
-#else
-const LVM_UINT16    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
-                                              11025,
-                                              12000,
-                                              16000,
-                                              22050,
-                                              24000,
-                                              32000,
-                                              44100,
-                                              48000
-};
-#endif
-
-/************************************************************************************/
-/*                                                                                  */
-/*    Coefficient calculation tables                                                */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Table for 2 * Pi / Fs
- */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
-                                               LVEQNB_2PiOn_11025,
-                                               LVEQNB_2PiOn_12000,
-                                               LVEQNB_2PiOn_16000,
-                                               LVEQNB_2PiOn_22050,
-                                               LVEQNB_2PiOn_24000,
-                                               LVEQNB_2PiOn_32000,
-                                               LVEQNB_2PiOn_44100,
-                                               LVEQNB_2PiOn_48000
-#ifdef HIGHER_FS
-                                              ,LVEQNB_2PiOn_88200
-                                              ,LVEQNB_2PiOn_96000
-                                              ,LVEQNB_2PiOn_176400
-                                              ,LVEQNB_2PiOn_192000
-#endif
-                                               };
-#else
-const LVM_INT16     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
-                                               LVEQNB_2PiOn_11025,
-                                               LVEQNB_2PiOn_12000,
-                                               LVEQNB_2PiOn_16000,
-                                               LVEQNB_2PiOn_22050,
-                                               LVEQNB_2PiOn_24000,
-                                               LVEQNB_2PiOn_32000,
-                                               LVEQNB_2PiOn_44100,
-                                               LVEQNB_2PiOn_48000};    /* 48kS/s */
-#endif
-
-/*
- * Gain table
- */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
-                                          LVEQNB_Gain_Neg14_dB,
-                                          LVEQNB_Gain_Neg13_dB,
-                                          LVEQNB_Gain_Neg12_dB,
-                                          LVEQNB_Gain_Neg11_dB,
-                                          LVEQNB_Gain_Neg10_dB,
-                                          LVEQNB_Gain_Neg9_dB,
-                                          LVEQNB_Gain_Neg8_dB,
-                                          LVEQNB_Gain_Neg7_dB,
-                                          LVEQNB_Gain_Neg6_dB,
-                                          LVEQNB_Gain_Neg5_dB,
-                                          LVEQNB_Gain_Neg4_dB,
-                                          LVEQNB_Gain_Neg3_dB,
-                                          LVEQNB_Gain_Neg2_dB,
-                                          LVEQNB_Gain_Neg1_dB,
-                                          LVEQNB_Gain_0_dB,            /* 0dB gain */
-                                          LVEQNB_Gain_1_dB,
-                                          LVEQNB_Gain_2_dB,
-                                          LVEQNB_Gain_3_dB,
-                                          LVEQNB_Gain_4_dB,
-                                          LVEQNB_Gain_5_dB,
-                                          LVEQNB_Gain_6_dB,
-                                          LVEQNB_Gain_7_dB,
-                                          LVEQNB_Gain_8_dB,
-                                          LVEQNB_Gain_9_dB,
-                                          LVEQNB_Gain_10_dB,
-                                          LVEQNB_Gain_11_dB,
-                                          LVEQNB_Gain_12_dB,
-                                          LVEQNB_Gain_13_dB,
-                                          LVEQNB_Gain_14_dB,
-                                          LVEQNB_Gain_15_dB};          /* +15dB gain */
-#else
-const LVM_INT16     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
-                                          LVEQNB_Gain_Neg14_dB,
-                                          LVEQNB_Gain_Neg13_dB,
-                                          LVEQNB_Gain_Neg12_dB,
-                                          LVEQNB_Gain_Neg11_dB,
-                                          LVEQNB_Gain_Neg10_dB,
-                                          LVEQNB_Gain_Neg9_dB,
-                                          LVEQNB_Gain_Neg8_dB,
-                                          LVEQNB_Gain_Neg7_dB,
-                                          LVEQNB_Gain_Neg6_dB,
-                                          LVEQNB_Gain_Neg5_dB,
-                                          LVEQNB_Gain_Neg4_dB,
-                                          LVEQNB_Gain_Neg3_dB,
-                                          LVEQNB_Gain_Neg2_dB,
-                                          LVEQNB_Gain_Neg1_dB,
-                                          LVEQNB_Gain_0_dB,            /* 0dB gain */
-                                          LVEQNB_Gain_1_dB,
-                                          LVEQNB_Gain_2_dB,
-                                          LVEQNB_Gain_3_dB,
-                                          LVEQNB_Gain_4_dB,
-                                          LVEQNB_Gain_5_dB,
-                                          LVEQNB_Gain_6_dB,
-                                          LVEQNB_Gain_7_dB,
-                                          LVEQNB_Gain_8_dB,
-                                          LVEQNB_Gain_9_dB,
-                                          LVEQNB_Gain_10_dB,
-                                          LVEQNB_Gain_11_dB,
-                                          LVEQNB_Gain_12_dB,
-                                          LVEQNB_Gain_13_dB,
-                                          LVEQNB_Gain_14_dB,
-                                          LVEQNB_Gain_15_dB};          /* +15dB gain */
-
-#endif
-/*
- * D table for 100 / (Gain + 1)
- */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
-                                      LVEQNB_100D_Neg14_dB,
-                                      LVEQNB_100D_Neg13_dB,
-                                      LVEQNB_100D_Neg12_dB,
-                                      LVEQNB_100D_Neg11_dB,
-                                      LVEQNB_100D_Neg10_dB,
-                                      LVEQNB_100D_Neg9_dB,
-                                      LVEQNB_100D_Neg8_dB,
-                                      LVEQNB_100D_Neg7_dB,
-                                      LVEQNB_100D_Neg6_dB,
-                                      LVEQNB_100D_Neg5_dB,
-                                      LVEQNB_100D_Neg4_dB,
-                                      LVEQNB_100D_Neg3_dB,
-                                      LVEQNB_100D_Neg2_dB,
-                                      LVEQNB_100D_Neg1_dB,
-                                      LVEQNB_100D_0_dB};               /* 0dB gain */
-#else
-const LVM_INT16    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
-                                      LVEQNB_100D_Neg14_dB,
-                                      LVEQNB_100D_Neg13_dB,
-                                      LVEQNB_100D_Neg12_dB,
-                                      LVEQNB_100D_Neg11_dB,
-                                      LVEQNB_100D_Neg10_dB,
-                                      LVEQNB_100D_Neg9_dB,
-                                      LVEQNB_100D_Neg8_dB,
-                                      LVEQNB_100D_Neg7_dB,
-                                      LVEQNB_100D_Neg6_dB,
-                                      LVEQNB_100D_Neg5_dB,
-                                      LVEQNB_100D_Neg4_dB,
-                                      LVEQNB_100D_Neg3_dB,
-                                      LVEQNB_100D_Neg2_dB,
-                                      LVEQNB_100D_Neg1_dB,
-                                      LVEQNB_100D_0_dB};               /* 0dB gain */
-
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/*    Filter polynomial coefficients                                                */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Coefficients for calculating the cosine with the equation:
- *
- *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
- *
- * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
- * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
- * +1.0 to -1.0
- */
-const LVM_INT16     LVEQNB_CosCoef[] = {3,                             /* Shifts */
-                                        4096,                          /* a0 */
-                                        -36,                           /* a1 */
-                                        -19725,                        /* a2 */
-                                        -2671,                         /* a3 */
-                                        23730,                         /* a4 */
-                                        -9490};                        /* a5 */
-
-/*
- * Coefficients for calculating the cosine error with the equation:
- *
- *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
- *
- * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
- * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
- * 0.0 to 0.0078852986
- *
- * This is used to give a double precision cosine over the range 0 to Pi/25 using the
- * the equation:
- *
- * Cos(x) = 1.0 - CosErr(x)
- */
-const LVM_INT16     LVEQNB_DPCosCoef[] = {1,                           /* Shifts */
-                                          0,                           /* a0 */
-                                          -6,                          /* a1 */
-                                          16586,                       /* a2 */
-                                          -44};                        /* a3 */
-
-
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.cpp
new file mode 100644
index 0000000..0628114
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Coeffs.h"
+#include "LVEQNB_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Sample rate table                                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
+                                              11025,
+                                              12000,
+                                              16000,
+                                              22050,
+                                              24000,
+                                              32000,
+                                              44100,
+                                              48000,
+                                              88200,
+                                              96000,
+                                              176400,
+                                              192000
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficient calculation tables                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_FLOAT     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
+                                               LVEQNB_2PiOn_11025,
+                                               LVEQNB_2PiOn_12000,
+                                               LVEQNB_2PiOn_16000,
+                                               LVEQNB_2PiOn_22050,
+                                               LVEQNB_2PiOn_24000,
+                                               LVEQNB_2PiOn_32000,
+                                               LVEQNB_2PiOn_44100,
+                                               LVEQNB_2PiOn_48000
+                                              ,LVEQNB_2PiOn_88200
+                                              ,LVEQNB_2PiOn_96000
+                                              ,LVEQNB_2PiOn_176400
+                                              ,LVEQNB_2PiOn_192000
+                                               };
+
+/*
+ * Gain table
+ */
+const LVM_FLOAT     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
+                                          LVEQNB_Gain_Neg14_dB,
+                                          LVEQNB_Gain_Neg13_dB,
+                                          LVEQNB_Gain_Neg12_dB,
+                                          LVEQNB_Gain_Neg11_dB,
+                                          LVEQNB_Gain_Neg10_dB,
+                                          LVEQNB_Gain_Neg9_dB,
+                                          LVEQNB_Gain_Neg8_dB,
+                                          LVEQNB_Gain_Neg7_dB,
+                                          LVEQNB_Gain_Neg6_dB,
+                                          LVEQNB_Gain_Neg5_dB,
+                                          LVEQNB_Gain_Neg4_dB,
+                                          LVEQNB_Gain_Neg3_dB,
+                                          LVEQNB_Gain_Neg2_dB,
+                                          LVEQNB_Gain_Neg1_dB,
+                                          LVEQNB_Gain_0_dB,            /* 0dB gain */
+                                          LVEQNB_Gain_1_dB,
+                                          LVEQNB_Gain_2_dB,
+                                          LVEQNB_Gain_3_dB,
+                                          LVEQNB_Gain_4_dB,
+                                          LVEQNB_Gain_5_dB,
+                                          LVEQNB_Gain_6_dB,
+                                          LVEQNB_Gain_7_dB,
+                                          LVEQNB_Gain_8_dB,
+                                          LVEQNB_Gain_9_dB,
+                                          LVEQNB_Gain_10_dB,
+                                          LVEQNB_Gain_11_dB,
+                                          LVEQNB_Gain_12_dB,
+                                          LVEQNB_Gain_13_dB,
+                                          LVEQNB_Gain_14_dB,
+                                          LVEQNB_Gain_15_dB};          /* +15dB gain */
+/*
+ * D table for 100 / (Gain + 1)
+ */
+const LVM_FLOAT    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
+                                      LVEQNB_100D_Neg14_dB,
+                                      LVEQNB_100D_Neg13_dB,
+                                      LVEQNB_100D_Neg12_dB,
+                                      LVEQNB_100D_Neg11_dB,
+                                      LVEQNB_100D_Neg10_dB,
+                                      LVEQNB_100D_Neg9_dB,
+                                      LVEQNB_100D_Neg8_dB,
+                                      LVEQNB_100D_Neg7_dB,
+                                      LVEQNB_100D_Neg6_dB,
+                                      LVEQNB_100D_Neg5_dB,
+                                      LVEQNB_100D_Neg4_dB,
+                                      LVEQNB_100D_Neg3_dB,
+                                      LVEQNB_100D_Neg2_dB,
+                                      LVEQNB_100D_Neg1_dB,
+                                      LVEQNB_100D_0_dB};               /* 0dB gain */
+/************************************************************************************/
+/*                                                                                  */
+/*    Filter polynomial coefficients                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16     LVEQNB_CosCoef[] = {3,                             /* Shifts */
+                                        4096,                          /* a0 */
+                                        -36,                           /* a1 */
+                                        -19725,                        /* a2 */
+                                        -2671,                         /* a3 */
+                                        23730,                         /* a4 */
+                                        -9490};                        /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16     LVEQNB_DPCosCoef[] = {1,                           /* Shifts */
+                                          0,                           /* a0 */
+                                          -6,                          /* a1 */
+                                          16586,                       /* a2 */
+                                          -44};                        /* a3 */
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.h
new file mode 100644
index 0000000..a71eeb9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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 __LVEQNB_TABLES_H__
+#define __LVEQNB_TABLES_H__
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Sample rate table                                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+extern const LVM_UINT32    LVEQNB_SampleRateTab[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficient calculation tables                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+extern const LVM_FLOAT     LVEQNB_TwoPiOnFsTable[];
+
+/*
+ * Gain table
+ */
+extern const LVM_FLOAT     LVEQNB_GainTable[];
+
+/*
+ * D table for 100 / (Gain + 1)
+ */
+extern const LVM_FLOAT     LVEQNB_DTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Filter polynomial coefficients                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+extern const LVM_INT16     LVEQNB_CosCoef[];
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+extern const LVM_INT16     LVEQNB_DPCosCoef[];
+
+#endif /* __LVEQNB_TABLES_H__ */
diff --git a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
index 9c2e297..8c91ea9 100644
--- a/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
+++ b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
@@ -28,11 +28,6 @@
 #ifndef __LVREV_H__
 #define __LVREV_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -40,7 +35,6 @@
 /****************************************************************************************/
 #include "LVM_Types.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Definitions                                                                         */
@@ -53,7 +47,6 @@
 /* Memory table*/
 #define LVREV_NR_MEMORY_REGIONS                 4       /* Number of memory regions */
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Types                                                                               */
@@ -62,7 +55,6 @@
 /* Instance handle */
 typedef void *LVREV_Handle_t;
 
-
 /* Status return values */
 typedef enum
 {
@@ -73,7 +65,6 @@
     LVREV_RETURNSTATUS_DUMMY = LVM_MAXENUM
 } LVREV_ReturnStatus_en;
 
-
 /* Reverb delay lines */
 typedef enum
 {
@@ -83,7 +74,6 @@
     LVREV_DELAYLINES_DUMMY = LVM_MAXENUM
 } LVREV_NumDelayLines_en;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
@@ -96,7 +86,6 @@
     LVM_MemoryRegion_st        Region[LVREV_NR_MEMORY_REGIONS];  /* One definition for each region */
 } LVREV_MemoryTable_st;
 
-
 /* Control Parameter structure */
 typedef struct
 {
@@ -107,13 +96,8 @@
 
     /* Parameters for REV */
     LVM_UINT16                  Level;                  /* Level, 0 to 100 representing percentage of reverb */
-#ifndef HIGHER_FS
-    LVM_UINT16                  LPF;                    /* Low pass filter, in Hz */
-    LVM_UINT16                  HPF;                    /* High pass filter, in Hz */
-#else
     LVM_UINT32                  LPF;                    /* Low pass filter, in Hz */
     LVM_UINT32                  HPF;                    /* High pass filter, in Hz */
-#endif
 
     LVM_UINT16                  T60;                    /* Decay time constant, in ms */
     LVM_UINT16                  Density;                /* Echo density, 0 to 100 for minimum to maximum density */
@@ -122,7 +106,6 @@
 
 } LVREV_ControlParams_st;
 
-
 /* Instance Parameter structure */
 typedef struct
 {
@@ -135,7 +118,6 @@
 
 } LVREV_InstanceParams_st;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Function Prototypes                                                                 */
@@ -182,7 +164,6 @@
                                            LVREV_MemoryTable_st     *pMemoryTable,
                                            LVREV_InstanceParams_st  *pInstanceParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVREV_GetInstanceHandle                                     */
@@ -213,7 +194,6 @@
                                               LVREV_MemoryTable_st      *pMemoryTable,
                                               LVREV_InstanceParams_st   *pInstanceParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVXX_GetControlParameters                                   */
@@ -237,7 +217,6 @@
 LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t           hInstance,
                                                  LVREV_ControlParams_st   *pControlParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVREV_SetControlParameters                                  */
@@ -260,7 +239,6 @@
 LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t           hInstance,
                                                  LVREV_ControlParams_st   *pNewParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVREV_ClearAudioBuffers                                     */
@@ -281,7 +259,6 @@
 /****************************************************************************************/
 LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t  hInstance);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVREV_Process                                               */
@@ -303,21 +280,10 @@
 /*  1. The input and output buffers must be 32-bit aligned                              */
 /*                                                                                      */
 /****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
                                     const LVM_FLOAT     *pInData,
                                     LVM_FLOAT           *pOutData,
                                     const LVM_UINT16          NumSamples);
-#else
-LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
-                                    const LVM_INT32     *pInData,
-                                    LVM_INT32           *pOutData,
-                                    const LVM_UINT16          NumSamples);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif      /* __LVREV_H__ */
 
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
deleted file mode 100644
index e710844..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "Filter.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_ApplyNewSettings                                      */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Applies the new control parameters                                                  */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pPrivate                Pointer to the instance private parameters                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-
-#ifndef BUILD_FLOAT
-LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
-{
-
-    LVM_Mode_en  OperatingMode;
-    LVM_INT32    NumberOfDelayLines;
-
-
-    /* Check for NULL pointer */
-    if(pPrivate == LVM_NULL)
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    OperatingMode = pPrivate->NewParams.OperatingMode;
-
-    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-    {
-        NumberOfDelayLines = 4;
-    }
-    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
-    {
-        NumberOfDelayLines = 2;
-    }
-    else
-    {
-        NumberOfDelayLines = 1;
-    }
-
-    /*
-     * Update the high pass filter coefficients
-     */
-    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
-       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-       (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-        LVM_INT32       Omega;
-        FO_C32_Coefs_t  Coeffs;
-
-        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
-        LVM_FO_HPF(Omega, &Coeffs);
-        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps, &Coeffs);
-        LoadConst_32(0,
-            (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
-            sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
-    }
-
-
-    /*
-     * Update the low pass filter coefficients
-     */
-    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
-       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-       (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-        LVM_INT32       Omega;
-        FO_C32_Coefs_t  Coeffs;
-
-
-        Coeffs.A0 = 0x7FFFFFFF;
-        Coeffs.A1 = 0;
-        Coeffs.B1 = 0;
-        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
-        {
-            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
-
-            /*
-             * Do not apply filter if w =2*pi*fc/fs >= 2.9
-             */
-            if(Omega<=LVREV_2_9_INQ29)
-            {
-                LVM_FO_LPF(Omega, &Coeffs);
-            }
-        }
-        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps, &Coeffs);
-        LoadConst_32(0,
-            (void *)&pPrivate->pFastData->LPTaps,        /* Destination Cast to void: no dereferencing in function*/
-            sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
-    }
-
-
-    /*
-     * Calculate the room size parameter
-     */
-    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
-    {
-        /* Room size range is 10ms to 200ms
-         * 0%   -- 10ms
-         * 50%  -- 65ms
-         * 100% -- 120ms
-         */
-        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5)/10);
-    }
-
-
-    /*
-     * Update the T delay number of samples and the all pass delay number of samples
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_UINT32  Temp;
-        LVM_INT32   APDelaySize;
-        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
-        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
-        LVM_INT16   i;
-        LVM_INT16   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
-        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
-        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
-
-
-        /*
-         * For each delay line
-         */
-        for (i=0; i<NumberOfDelayLines; i++)
-        {
-            if (i != 0)
-            {
-                LVM_INT32 Temp1;  /* to avoid QAC warning on type conversion */
-                LVM_INT32 Temp2;  /* to avoid QAC warning on type conversion */
-
-                Temp2=(LVM_INT32)DelayLengthSamples;
-                MUL32x16INTO32(Temp2, ScaleTable[i], Temp1, 15)
-                Temp=(LVM_UINT32)Temp1;
-            }
-            else
-            {
-               Temp = DelayLengthSamples;
-            }
-            APDelaySize = Temp  / 1500;
-
-
-            /*
-             * Set the fixed delay
-             */
-            Temp                  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
-            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
-
-
-            /*
-             * Set the tap selection
-             */
-            if (pPrivate->AB_Selection)
-            {
-                /* Smooth from tap A to tap B */
-                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
-                pPrivate->B_DelaySize[i]          = APDelaySize;
-                pPrivate->Mixer_APTaps[i].Target1 = 0;
-                pPrivate->Mixer_APTaps[i].Target2 = 0x7fffffff;
-            }
-            else
-            {
-                /* Smooth from tap B to tap A */
-                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
-                pPrivate->A_DelaySize[i]          = APDelaySize;
-                pPrivate->Mixer_APTaps[i].Target2 = 0;
-                pPrivate->Mixer_APTaps[i].Target1 = 0x7fffffff;
-            }
-
-            /*
-             * Set the maximum block size to the smallest delay size
-             */
-            pPrivate->MaxBlkLen   = Temp;
-            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
-            {
-                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
-            }
-            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
-            {
-                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
-            }
-        }
-        if (pPrivate->AB_Selection)
-        {
-            pPrivate->AB_Selection = 0;
-        }
-        else
-        {
-            pPrivate->AB_Selection = 1;
-        }
-
-
-        /*
-         * Limit the maximum block length
-         */
-        pPrivate->MaxBlkLen=pPrivate->MaxBlkLen-2;                                  /* Just as a precausion, but no problem if we remove this line      */
-        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
-        {
-            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
-        }
-    }
-
-
-    /*
-     * Update the low pass filter coefficient
-     */
-    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_INT32       Temp;
-        LVM_INT32       Omega;
-        FO_C32_Coefs_t  Coeffs;
-        LVM_INT16       i;
-        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
-        LVM_INT32       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4, LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
-
-
-        /*
-         * For each filter
-         */
-        for (i=0; i<NumberOfDelayLines; i++)
-        {
-            if (i != 0)
-            {
-                MUL32x16INTO32(ScaleTable[i], Damping, Temp, 15)
-            }
-            else
-            {
-                Temp = Damping;
-            }
-            if(Temp <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
-            {
-                Omega = LVM_GetOmega((LVM_UINT16)Temp, pPrivate->NewParams.SampleRate);
-                LVM_FO_LPF(Omega, &Coeffs);
-            }
-            else
-            {
-                Coeffs.A0 = 0x7FF00000;
-                Coeffs.A1 = 0;
-                Coeffs.B1 = 0;
-            }
-            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i], &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
-        }
-    }
-
-
-    /*
-     * Update All-pass filter mixer time constants
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
-    {
-        LVM_INT16   i;
-        LVM_INT32   Alpha    = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
-        LVM_INT32   AlphaTap = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
-
-        for (i=0; i<4; i++)
-        {
-            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
-            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
-            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
-            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
-        }
-    }
-
-
-    /*
-     * Update the feed back gain
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_INT32               G[4];                       /* Feedback gain (Q7.24) */
-
-        if(pPrivate->NewParams.T60 == 0)
-        {
-            G[3] = 0;
-            G[2] = 0;
-            G[1] = 0;
-            G[0] = 0;
-        }
-        else
-        {
-            LVM_INT32   Temp1;
-            LVM_INT32   Temp2;
-            LVM_INT16   i;
-            LVM_INT16   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
-
-
-            /*
-             * For each delay line
-             */
-            for (i=0; i<NumberOfDelayLines; i++)
-            {
-                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
-                if(Temp1 >= (4 << 15))
-                {
-                    G[i] = 0;
-                }
-                else if((Temp1 >= (2 << 15)))
-                {
-                    Temp2 = LVM_Power10(-(Temp1 << 14));
-                    Temp1 = LVM_Power10(-(Temp1 << 14));
-                    MUL32x32INTO32(Temp1,Temp2,Temp1,24)
-                }
-                else
-                {
-                    Temp1 = LVM_Power10(-(Temp1 << 15));
-                }
-                if (NumberOfDelayLines == 1)
-                {
-                    G[i] = Temp1;
-                }
-                else
-                {
-                    LVM_INT32   TempG;
-                    MUL32x16INTO32(Temp1,ONE_OVER_SQRT_TWO,TempG,15)
-                    G[i]=TempG;
-                }
-            }
-        }
-
-        /* Set up the feedback mixers for four delay lines */
-        pPrivate->FeedbackMixer[0].Target=G[0]<<7;
-        pPrivate->FeedbackMixer[1].Target=G[1]<<7;
-        pPrivate->FeedbackMixer[2].Target=G[2]<<7;
-        pPrivate->FeedbackMixer[3].Target=G[3]<<7;
-    }
-
-
-    /*
-     * Calculate the gain correction
-     */
-    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
-       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
-       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
-    {
-        LVM_INT32 Index=0;
-        LVM_INT32 i=0;
-        LVM_INT32 Gain=0;
-        LVM_INT32 RoomSize=0;
-        LVM_INT32 T60;
-        LVM_INT32 Coefs[5];
-
-        if(pPrivate->NewParams.RoomSize==0)
-        {
-            RoomSize=1;
-        }
-        else
-        {
-            RoomSize=(LVM_INT32)pPrivate->NewParams.RoomSize;
-        }
-
-        if(pPrivate->NewParams.T60<100)
-        {
-            T60 = 100 * LVREV_T60_SCALE;
-        }
-        else
-        {
-            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
-        }
-
-        /* Find the nearest room size in table */
-        for(i=0;i<24;i++)
-        {
-            if(RoomSize<= LVREV_GainPolyTable[i][0])
-            {
-                Index=i;
-                break;
-            }
-        }
-
-
-        if(RoomSize==LVREV_GainPolyTable[Index][0])
-        {
-            /* Take table values if the room size is in table */
-            for(i=1;i<5;i++)
-            {
-                Coefs[i-1]=LVREV_GainPolyTable[Index][i];
-            }
-            Coefs[4]=0;
-            Gain=LVM_Polynomial(3,Coefs,T60);       /* Q.24 result */
-        }
-        else
-        {
-            /* Interpolate the gain between nearest room sizes */
-
-            LVM_INT32 Gain1,Gain2;
-            LVM_INT32 Tot_Dist,Dist;
-
-            Tot_Dist=LVREV_GainPolyTable[Index][0]-LVREV_GainPolyTable[Index-1][0];
-            Dist=RoomSize-LVREV_GainPolyTable[Index-1][0];
-
-
-            /* Get gain for first */
-            for(i=1;i<5;i++)
-            {
-                Coefs[i-1]=LVREV_GainPolyTable[Index-1][i];
-            }
-            Coefs[4]=0;
-
-            Gain1=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
-
-            /* Get gain for second */
-            for(i=1;i<5;i++)
-            {
-                Coefs[i-1]=LVREV_GainPolyTable[Index][i];
-            }
-            Coefs[4]=0;
-
-            Gain2=LVM_Polynomial(3,Coefs,T60);      /* Q.24 result */
-
-            /* Linear Interpolate the gain */
-            Gain = Gain1+ (((Gain2-Gain1)*Dist)/(Tot_Dist));
-        }
-
-
-        /*
-         * Get the inverse of gain: Q.15
-         * Gain is mostly above one except few cases, take only gains above 1
-         */
-        if(Gain < 16777216L)
-        {
-            pPrivate->Gain= 32767;
-        }
-        else
-        {
-            pPrivate->Gain=(LVM_INT16)(LVM_MAXINT_32/(Gain>>8));
-        }
-
-
-        Index=((32767*100)/(100+pPrivate->NewParams.Level));
-        pPrivate->Gain=(LVM_INT16)((pPrivate->Gain*Index)>>15);
-        pPrivate->GainMixer.Target = pPrivate->Gain*Index;
-    }
-
-
-    /*
-     * Update the all pass comb filter coefficient
-     */
-    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
-        (pPrivate->bFirstControl     == LVM_TRUE))
-    {
-        LVM_INT16   i;
-        LVM_INT32   b = pPrivate->NewParams.Density * LVREV_B_8_on_1000;
-
-        for (i=0;i<4; i++)
-        {
-            pPrivate->Mixer_SGFeedback[i].Target    = b;
-            pPrivate->Mixer_SGFeedforward[i].Target = b;
-        }
-    }
-
-
-    /*
-     * Update the bypass mixer time constant
-     */
-    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
-       (pPrivate->bFirstControl          == LVM_TRUE))
-    {
-        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
-        LVM_INT32    Alpha;
-
-        Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
-        pPrivate->FeedbackMixer[0].Alpha=Alpha;
-        pPrivate->FeedbackMixer[1].Alpha=Alpha;
-        pPrivate->FeedbackMixer[2].Alpha=Alpha;
-        pPrivate->FeedbackMixer[3].Alpha=Alpha;
-
-        NumChannels = 2;                                    /* Always stereo output */
-        pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
-        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
-        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
-    }
-
-
-    /*
-     * Update the bypass mixer targets
-     */
-    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
-        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
-    {
-        pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
-        pPrivate->BypassMixer.Target1 = 0x00000000;
-        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
-        {
-            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
-        }
-        if (pPrivate->NewParams.Level != 0)
-        {
-            pPrivate->bDisableReverb = LVM_FALSE;
-        }
-    }
-
-    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
-    {
-        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
-        {
-            pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
-            pPrivate->BypassMixer.Target1 = 0x00000000;
-
-            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
-            OperatingMode                      = LVM_MODE_ON;
-            if (pPrivate->NewParams.Level == 0)
-            {
-                pPrivate->bDisableReverb = LVM_TRUE;
-            }
-            else
-            {
-                pPrivate->bDisableReverb = LVM_FALSE;
-            }
-        }
-        else if (pPrivate->bFirstControl == LVM_FALSE)
-        {
-            pPrivate->BypassMixer.Target2 = 0x00000000;
-            pPrivate->BypassMixer.Target1 = 0x00000000;
-            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
-            pPrivate->GainMixer.Target    = 0x03FFFFFF;
-            OperatingMode = LVM_MODE_ON;
-        }
-        else
-        {
-            OperatingMode = LVM_MODE_OFF;
-        }
-    }
-
-
-    /*
-     * If it is the first call to ApplyNew settings force the current to the target to begin immediate playback of the effect
-     */
-    if(pPrivate->bFirstControl == LVM_TRUE)
-    {
-        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
-        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
-    }
-
-
-    /*
-     * Copy the new parameters
-     */
-    pPrivate->CurrentParams = pPrivate->NewParams;
-    pPrivate->CurrentParams.OperatingMode = OperatingMode;
-
-
-    /*
-     * Update flag
-     */
-    if(pPrivate->bFirstControl == LVM_TRUE)
-    {
-        pPrivate->bFirstControl = LVM_FALSE;
-    }
-
-
-    return LVREV_SUCCESS;
-}
-#else /* BUILD_FLOAT*/
-LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
-{
-
-    LVM_Mode_en  OperatingMode;
-    LVM_INT32    NumberOfDelayLines;
-
-
-    /* Check for NULL pointer */
-    if(pPrivate == LVM_NULL)
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    OperatingMode = pPrivate->NewParams.OperatingMode;
-
-    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-    {
-        NumberOfDelayLines = 4;
-    }
-    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
-    {
-        NumberOfDelayLines = 2;
-    }
-    else
-    {
-        NumberOfDelayLines = 1;
-    }
-
-    /*
-     * Update the high pass filter coefficients
-     */
-    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
-       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-       (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-        LVM_FLOAT       Omega;
-        FO_FLOAT_Coefs_t  Coeffs;
-
-        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
-        LVM_FO_HPF(Omega, &Coeffs);
-        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
-                                         &pPrivate->pFastData->HPTaps, &Coeffs);
-        LoadConst_Float(0,
-                        (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
-                                                                 no dereferencing in function*/
-                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
-    }
-
-
-    /*
-     * Update the low pass filter coefficients
-     */
-    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
-       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-       (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-        LVM_FLOAT       Omega;
-        FO_FLOAT_Coefs_t  Coeffs;
-
-        Coeffs.A0 = 1;
-        Coeffs.A1 = 0;
-        Coeffs.B1 = 0;
-        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
-        {
-            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
-
-            /*
-             * Do not apply filter if w =2*pi*fc/fs >= 2.9
-             */
-            if(Omega <= (LVM_FLOAT)LVREV_2_9_INQ29)
-            {
-                LVM_FO_LPF(Omega, &Coeffs);
-            }
-        }
-        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
-                                         &pPrivate->pFastData->LPTaps, &Coeffs);
-        LoadConst_Float(0,
-                        (void *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
-                                                                 no dereferencing in function*/
-                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
-    }
-
-
-    /*
-     * Calculate the room size parameter
-     */
-    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
-    {
-        /* Room size range is 10ms to 200ms
-         * 0%   -- 10ms
-         * 50%  -- 65ms
-         * 100% -- 120ms
-         */
-        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5) / 10);
-    }
-
-
-    /*
-     * Update the T delay number of samples and the all pass delay number of samples
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_UINT32  Temp;
-        LVM_INT32   APDelaySize;
-        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
-        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
-        LVM_INT16   i;
-        LVM_FLOAT   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, \
-                                     LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
-        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, \
-                                     LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
-        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, \
-                                     LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
-
-
-        /*
-         * For each delay line
-         */
-        for (i = 0; i < NumberOfDelayLines; i++)
-        {
-            if (i != 0)
-            {
-                LVM_FLOAT Temp1;  /* to avoid QAC warning on type conversion */
-
-                Temp1=(LVM_FLOAT)DelayLengthSamples;
-                Temp = (LVM_UINT32)(Temp1 * ScaleTable[i]);
-            }
-            else
-            {
-               Temp = DelayLengthSamples;
-            }
-            APDelaySize = Temp  / 1500;
-
-
-            /*
-             * Set the fixed delay
-             */
-
-#ifdef HIGHER_FS
-            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
-#else
-            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
-#endif
-            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
-
-
-            /*
-             * Set the tap selection
-             */
-            if (pPrivate->AB_Selection)
-            {
-                /* Smooth from tap A to tap B */
-                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
-                                                                           Temp - APDelaySize];
-                pPrivate->B_DelaySize[i]          = APDelaySize;
-                pPrivate->Mixer_APTaps[i].Target1 = 0;
-                pPrivate->Mixer_APTaps[i].Target2 = 1.0f;
-            }
-            else
-            {
-                /* Smooth from tap B to tap A */
-                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
-                                                                           Temp - APDelaySize];
-                pPrivate->A_DelaySize[i]          = APDelaySize;
-                pPrivate->Mixer_APTaps[i].Target2 = 0;
-                pPrivate->Mixer_APTaps[i].Target1 = 1.0f;
-            }
-
-            /*
-             * Set the maximum block size to the smallest delay size
-             */
-            pPrivate->MaxBlkLen   = Temp;
-            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
-            {
-                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
-            }
-            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
-            {
-                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
-            }
-        }
-        if (pPrivate->AB_Selection)
-        {
-            pPrivate->AB_Selection = 0;
-        }
-        else
-        {
-            pPrivate->AB_Selection = 1;
-        }
-
-
-        /*
-         * Limit the maximum block length
-         */
-        /* Just as a precausion, but no problem if we remove this line      */
-        pPrivate->MaxBlkLen = pPrivate->MaxBlkLen - 2;
-        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
-        {
-            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
-        }
-    }
-
-
-
-    /*
-     * Update the low pass filter coefficient
-     */
-    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_INT32       Temp;
-        LVM_FLOAT       Omega;
-        FO_FLOAT_Coefs_t  Coeffs;
-        LVM_INT16       i;
-        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
-        LVM_FLOAT       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4,
-                                        LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
-
-
-        /*
-         * For each filter
-         */
-        for (i = 0; i < NumberOfDelayLines; i++)
-        {
-            if (i != 0)
-            {
-                Temp = (LVM_INT32)(ScaleTable[i] * Damping);
-            }
-            else
-            {
-                Temp = Damping;
-            }
-            if(Temp <= (LVM_INT32)(LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
-            {
-                Omega = LVM_GetOmega(Temp, pPrivate->NewParams.SampleRate);
-                LVM_FO_LPF(Omega, &Coeffs);
-            }
-            else
-            {
-                Coeffs.A0 = 1;
-                Coeffs.A1 = 0;
-                Coeffs.B1 = 0;
-            }
-            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
-                                            &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
-        }
-    }
-
-
-    /*
-     * Update All-pass filter mixer time constants
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
-    {
-        LVM_INT16   i;
-        LVM_FLOAT   Alpha;
-        LVM_FLOAT   AlphaTap;
-
-        Alpha = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC,
-                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
-                                       1);
-
-        AlphaTap = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC,
-                                          LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
-                                          1);
-
-        for (i = 0; i < 4; i++)
-        {
-            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
-            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
-            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
-            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
-        }
-    }
-
-
-    /*
-     * Update the feed back gain
-     */
-    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
-        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
-        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
-        (pPrivate->bFirstControl        == LVM_TRUE))
-    {
-
-        LVM_FLOAT               G[4];                       /* Feedback gain (Q7.24) */
-
-        if(pPrivate->NewParams.T60 == 0)
-        {
-            G[3] = 0;
-            G[2] = 0;
-            G[1] = 0;
-            G[0] = 0;
-        }
-        else
-        {
-            LVM_FLOAT   Temp1;
-            LVM_FLOAT   Temp2;
-            LVM_INT16   i;
-            LVM_FLOAT   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
-                                        LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
-
-
-            /*
-             * For each delay line
-             */
-            for (i = 0; i < NumberOfDelayLines; i++)
-            {
-                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
-                if(Temp1 >= (4))
-                {
-                    G[i] = 0;
-                }
-                else if((Temp1 >= (2)))
-                {
-                    Temp2 = LVM_Power10(-(Temp1 / 2.0f));
-                    Temp1 = LVM_Power10(-(Temp1 / 2.0f));
-                    Temp1 = Temp1 * Temp2;
-                }
-                else
-                {
-                    Temp1 = LVM_Power10(-(Temp1));
-                }
-                if (NumberOfDelayLines == 1)
-                {
-                    G[i] = Temp1;
-                }
-                else
-                {
-                    LVM_FLOAT   TempG;
-                    TempG = Temp1 * ONE_OVER_SQRT_TWO;
-                    G[i]=TempG;
-                }
-            }
-        }
-
-        /* Set up the feedback mixers for four delay lines */
-        pPrivate->FeedbackMixer[0].Target=G[0];
-        pPrivate->FeedbackMixer[1].Target=G[1];
-        pPrivate->FeedbackMixer[2].Target=G[2];
-        pPrivate->FeedbackMixer[3].Target=G[3];
-    }
-
-
-    /*
-     * Calculate the gain correction
-     */
-    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
-       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
-       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
-    {
-        LVM_INT32 Index=0;
-        LVM_FLOAT Index_FLOAT;
-        LVM_INT32 i=0;
-        LVM_FLOAT Gain=0;
-        LVM_INT32 RoomSize=0;
-        LVM_FLOAT T60;
-        LVM_FLOAT Coefs[5];
-
-
-        if(pPrivate->NewParams.RoomSize == 0)
-        {
-            RoomSize = 1;
-        }
-        else
-        {
-            RoomSize = (LVM_INT32)pPrivate->NewParams.RoomSize;
-        }
-
-
-        if(pPrivate->NewParams.T60 < 100)
-        {
-            T60 = 100 * LVREV_T60_SCALE;
-        }
-        else
-        {
-            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
-        }
-
-        /* Find the nearest room size in table */
-        for(i = 0; i < 24; i++)
-        {
-            if(RoomSize <= LVREV_GainPolyTable[i][0])
-            {
-                Index = i;
-                break;
-            }
-        }
-
-
-        if(RoomSize == LVREV_GainPolyTable[Index][0])
-        {
-            /* Take table values if the room size is in table */
-            for(i = 1; i < 5; i++)
-            {
-                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
-            }
-            Coefs[4] = 0;
-            Gain = LVM_Polynomial(3, Coefs, T60);       /* Q.24 result */
-        }
-        else
-        {
-            /* Interpolate the gain between nearest room sizes */
-
-            LVM_FLOAT Gain1,Gain2;
-            LVM_INT32 Tot_Dist,Dist;
-
-            Tot_Dist = (LVM_UINT32)LVREV_GainPolyTable[Index][0] - \
-                                            (LVM_UINT32)LVREV_GainPolyTable[Index-1][0];
-            Dist = RoomSize - (LVM_UINT32)LVREV_GainPolyTable[Index - 1][0];
-
-
-            /* Get gain for first */
-            for(i = 1; i < 5; i++)
-            {
-                Coefs[i-1] = LVREV_GainPolyTable[Index-1][i];
-            }
-            Coefs[4] = 0;
-
-            Gain1 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
-
-            /* Get gain for second */
-            for(i = 1; i < 5; i++)
-            {
-                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
-            }
-            Coefs[4] = 0;
-
-            Gain2 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
-
-            /* Linear Interpolate the gain */
-            Gain = Gain1 + (((Gain2 - Gain1) * Dist) / (Tot_Dist));
-        }
-
-
-        /*
-         * Get the inverse of gain: Q.15
-         * Gain is mostly above one except few cases, take only gains above 1
-         */
-        if(Gain < 1)
-        {
-            pPrivate->Gain = 1;
-        }
-        else
-        {
-            pPrivate->Gain = 1 / Gain;
-        }
-
-        Index_FLOAT = 100.0f / (LVM_FLOAT)(100 + pPrivate->NewParams.Level);
-        pPrivate->Gain = pPrivate->Gain * Index_FLOAT;
-        pPrivate->GainMixer.Target = (pPrivate->Gain*Index_FLOAT) / 2;
-    }
-
-
-    /*
-     * Update the all pass comb filter coefficient
-     */
-    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
-        (pPrivate->bFirstControl     == LVM_TRUE))
-    {
-        LVM_INT16   i;
-        LVM_FLOAT   b = (LVM_FLOAT)pPrivate->NewParams.Density * LVREV_B_8_on_1000;
-
-        for (i = 0; i < 4; i++)
-        {
-            pPrivate->Mixer_SGFeedback[i].Target    = b;
-            pPrivate->Mixer_SGFeedforward[i].Target = b;
-        }
-    }
-
-
-    /*
-     * Update the bypass mixer time constant
-     */
-    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
-       (pPrivate->bFirstControl          == LVM_TRUE))
-    {
-        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
-        LVM_FLOAT    Alpha;
-
-        Alpha = LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC,
-                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
-                                       NumChannels);
-        pPrivate->FeedbackMixer[0].Alpha = Alpha;
-        pPrivate->FeedbackMixer[1].Alpha = Alpha;
-        pPrivate->FeedbackMixer[2].Alpha = Alpha;
-        pPrivate->FeedbackMixer[3].Alpha = Alpha;
-
-        NumChannels = 2;                                    /* Always stereo output */
-        pPrivate->BypassMixer.Alpha1 = LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC,
-                             LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
-        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
-        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
-    }
-
-
-    /*
-     * Update the bypass mixer targets
-     */
-    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
-        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
-    {
-        pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
-        pPrivate->BypassMixer.Target1 = 0x00000000;
-        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
-        {
-            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
-        }
-        if (pPrivate->NewParams.Level != 0)
-        {
-            pPrivate->bDisableReverb = LVM_FALSE;
-        }
-    }
-
-    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
-    {
-        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
-        {
-            pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
-            pPrivate->BypassMixer.Target1 = 0x00000000;
-
-            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
-            OperatingMode                      = LVM_MODE_ON;
-            if (pPrivate->NewParams.Level == 0)
-            {
-                pPrivate->bDisableReverb = LVM_TRUE;
-            }
-            else
-            {
-                pPrivate->bDisableReverb = LVM_FALSE;
-            }
-        }
-        else if (pPrivate->bFirstControl == LVM_FALSE)
-        {
-            pPrivate->BypassMixer.Target2 = 0x00000000;
-            pPrivate->BypassMixer.Target1 = 0x00000000;
-            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
-            pPrivate->GainMixer.Target    = 0.03125f;
-            OperatingMode = LVM_MODE_ON;
-        }
-        else
-        {
-            OperatingMode = LVM_MODE_OFF;
-        }
-    }
-
-
-    /*  If it is the first call to ApplyNew settings force the current to the target \
-        to begin immediate playback of the effect */
-    if(pPrivate->bFirstControl == LVM_TRUE)
-    {
-        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
-        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
-    }
-
-
-    /*
-     * Copy the new parameters
-     */
-    pPrivate->CurrentParams = pPrivate->NewParams;
-    pPrivate->CurrentParams.OperatingMode = OperatingMode;
-
-
-    /*
-     * Update flag
-     */
-    if(pPrivate->bFirstControl == LVM_TRUE)
-    {
-        pPrivate->bFirstControl = LVM_FALSE;
-    }
-
-
-    return LVREV_SUCCESS;
-}
-#endif /*BUILD_FLOAT*/
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                BypassMixer_Callback                                        */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Controls the On to Off operating mode transition                                    */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  pPrivate                Pointer to the instance private parameters                  */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_INT32 BypassMixer_Callback (void *pCallbackData,
-                                void *pGeneralPurpose,
-                                LVM_INT16 GeneralPurpose )
-{
-
-    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
-
-
-    /*
-     * Avoid build warnings
-     */
-    (void)pGeneralPurpose;
-    (void)GeneralPurpose;
-
-
-    /*
-     * Turn off
-     */
-    pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
-    pLVREV_Private->bDisableReverb              = LVM_TRUE;
-    LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
-
-
-    return 0;
-}
-
-/* End of file */
-
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
new file mode 100644
index 0000000..1f0d39b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "Filter.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_ApplyNewSettings                                      */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Applies the new control parameters                                                  */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pPrivate                Pointer to the instance private parameters                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st     *pPrivate)
+{
+
+    LVM_Mode_en  OperatingMode;
+    LVM_INT32    NumberOfDelayLines;
+
+    /* Check for NULL pointer */
+    if(pPrivate == LVM_NULL)
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    OperatingMode = pPrivate->NewParams.OperatingMode;
+
+    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+    {
+        NumberOfDelayLines = 4;
+    }
+    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+    {
+        NumberOfDelayLines = 2;
+    }
+    else
+    {
+        NumberOfDelayLines = 1;
+    }
+
+    /*
+     * Update the high pass filter coefficients
+     */
+    if((pPrivate->NewParams.HPF        != pPrivate->CurrentParams.HPF)        ||
+       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+       (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+
+        Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
+        LVM_FO_HPF(Omega, &Coeffs);
+        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
+                                         &pPrivate->pFastData->HPTaps, &Coeffs);
+        LoadConst_Float(0,
+                (LVM_FLOAT *)&pPrivate->pFastData->HPTaps,
+                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+    }
+
+    /*
+     * Update the low pass filter coefficients
+     */
+    if((pPrivate->NewParams.LPF        != pPrivate->CurrentParams.LPF)        ||
+       (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+       (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+
+        Coeffs.A0 = 1;
+        Coeffs.A1 = 0;
+        Coeffs.B1 = 0;
+        if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+        {
+            Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
+
+            /*
+             * Do not apply filter if w =2*pi*fc/fs >= 2.9
+             */
+            if(Omega <= (LVM_FLOAT)LVREV_2_9_INQ29)
+            {
+                LVM_FO_LPF(Omega, &Coeffs);
+            }
+        }
+        FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
+                                         &pPrivate->pFastData->LPTaps, &Coeffs);
+        LoadConst_Float(0,
+                (LVM_FLOAT *)&pPrivate->pFastData->LPTaps,
+                        sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+    }
+
+    /*
+     * Calculate the room size parameter
+     */
+    if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
+    {
+        /* Room size range is 10ms to 200ms
+         * 0%   -- 10ms
+         * 50%  -- 65ms
+         * 100% -- 120ms
+         */
+        pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5) / 10);
+    }
+
+    /*
+     * Update the T delay number of samples and the all pass delay number of samples
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_UINT32  Temp;
+        LVM_INT32   APDelaySize;
+        LVM_INT32   Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
+        LVM_UINT32  DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
+        LVM_INT16   i;
+        LVM_FLOAT   ScaleTable[]  = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, \
+                                     LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+        LVM_INT16   MaxT_Delay[]  = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, \
+                                     LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
+        LVM_INT16   MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, \
+                                     LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
+        /*
+         * For each delay line
+         */
+        for (i = 0; i < NumberOfDelayLines; i++)
+        {
+            if (i != 0)
+            {
+                LVM_FLOAT Temp1;  /* to avoid QAC warning on type conversion */
+
+                Temp1=(LVM_FLOAT)DelayLengthSamples;
+                Temp = (LVM_UINT32)(Temp1 * ScaleTable[i]);
+            }
+            else
+            {
+               Temp = DelayLengthSamples;
+            }
+            APDelaySize = Temp  / 1500;
+
+            /*
+             * Set the fixed delay
+             */
+
+            Temp  = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 192000;
+            pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
+
+            /*
+             * Set the tap selection
+             */
+            if (pPrivate->AB_Selection)
+            {
+                /* Smooth from tap A to tap B */
+                pPrivate->pOffsetB[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
+                                                                           Temp - APDelaySize];
+                pPrivate->B_DelaySize[i]          = APDelaySize;
+                pPrivate->Mixer_APTaps[i].Target1 = 0;
+                pPrivate->Mixer_APTaps[i].Target2 = 1.0f;
+            }
+            else
+            {
+                /* Smooth from tap B to tap A */
+                pPrivate->pOffsetA[i]             = &pPrivate->pDelay_T[i][pPrivate->T[i] - \
+                                                                           Temp - APDelaySize];
+                pPrivate->A_DelaySize[i]          = APDelaySize;
+                pPrivate->Mixer_APTaps[i].Target2 = 0;
+                pPrivate->Mixer_APTaps[i].Target1 = 1.0f;
+            }
+
+            /*
+             * Set the maximum block size to the smallest delay size
+             */
+            pPrivate->MaxBlkLen   = Temp;
+            if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
+            {
+                pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
+            }
+            if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
+            {
+                pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
+            }
+        }
+        if (pPrivate->AB_Selection)
+        {
+            pPrivate->AB_Selection = 0;
+        }
+        else
+        {
+            pPrivate->AB_Selection = 1;
+        }
+
+        /*
+         * Limit the maximum block length
+         */
+        /* Just as a precausion, but no problem if we remove this line      */
+        pPrivate->MaxBlkLen = pPrivate->MaxBlkLen - 2;
+        if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
+        {
+            pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
+        }
+    }
+
+    /*
+     * Update the low pass filter coefficient
+     */
+    if( (pPrivate->NewParams.Damping    != pPrivate->CurrentParams.Damping)    ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_INT32       Temp;
+        LVM_FLOAT       Omega;
+        FO_FLOAT_Coefs_t  Coeffs;
+        LVM_INT16       i;
+        LVM_INT16       Damping      = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
+        LVM_FLOAT       ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4,
+                                        LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
+
+        /*
+         * For each filter
+         */
+        for (i = 0; i < NumberOfDelayLines; i++)
+        {
+            if (i != 0)
+            {
+                Temp = (LVM_INT32)(ScaleTable[i] * Damping);
+            }
+            else
+            {
+                Temp = Damping;
+            }
+            if(Temp <= (LVM_INT32)(LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+            {
+                Omega = LVM_GetOmega(Temp, pPrivate->NewParams.SampleRate);
+                LVM_FO_LPF(Omega, &Coeffs);
+            }
+            else
+            {
+                Coeffs.A0 = 1;
+                Coeffs.A1 = 0;
+                Coeffs.B1 = 0;
+            }
+            FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
+                                            &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+        }
+    }
+
+    /*
+     * Update All-pass filter mixer time constants
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->NewParams.Density    != pPrivate->CurrentParams.Density))
+    {
+        LVM_INT16   i;
+        LVM_FLOAT   Alpha;
+        LVM_FLOAT   AlphaTap;
+
+        Alpha = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC,
+                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                       1);
+
+        AlphaTap = LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC,
+                                          LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                          1);
+
+        for (i = 0; i < 4; i++)
+        {
+            pPrivate->Mixer_APTaps[i].Alpha1       = AlphaTap;
+            pPrivate->Mixer_APTaps[i].Alpha2       = AlphaTap;
+            pPrivate->Mixer_SGFeedback[i].Alpha    = Alpha;
+            pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
+        }
+    }
+
+    /*
+     * Update the feed back gain
+     */
+    if( (pPrivate->NewParams.RoomSize   != pPrivate->CurrentParams.RoomSize)   ||
+        (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+        (pPrivate->NewParams.T60        != pPrivate->CurrentParams.T60)        ||
+        (pPrivate->bFirstControl        == LVM_TRUE))
+    {
+
+        LVM_FLOAT               G[4];                       /* Feedback gain (Q7.24) */
+
+        if(pPrivate->NewParams.T60 == 0)
+        {
+            G[3] = 0;
+            G[2] = 0;
+            G[1] = 0;
+            G[0] = 0;
+        }
+        else
+        {
+            LVM_FLOAT   Temp1;
+            LVM_FLOAT   Temp2;
+            LVM_INT16   i;
+            LVM_FLOAT   ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4,
+                                        LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+
+            /*
+             * For each delay line
+             */
+            for (i = 0; i < NumberOfDelayLines; i++)
+            {
+                Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
+                if(Temp1 >= (4))
+                {
+                    G[i] = 0;
+                }
+                else if((Temp1 >= (2)))
+                {
+                    Temp2 = LVM_Power10(-(Temp1 / 2.0f));
+                    Temp1 = LVM_Power10(-(Temp1 / 2.0f));
+                    Temp1 = Temp1 * Temp2;
+                }
+                else
+                {
+                    Temp1 = LVM_Power10(-(Temp1));
+                }
+                if (NumberOfDelayLines == 1)
+                {
+                    G[i] = Temp1;
+                }
+                else
+                {
+                    LVM_FLOAT   TempG;
+                    TempG = Temp1 * ONE_OVER_SQRT_TWO;
+                    G[i]=TempG;
+                }
+            }
+        }
+
+        /* Set up the feedback mixers for four delay lines */
+        pPrivate->FeedbackMixer[0].Target=G[0];
+        pPrivate->FeedbackMixer[1].Target=G[1];
+        pPrivate->FeedbackMixer[2].Target=G[2];
+        pPrivate->FeedbackMixer[3].Target=G[3];
+    }
+
+    /*
+     * Calculate the gain correction
+     */
+    if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+       (pPrivate->NewParams.Level    != pPrivate->CurrentParams.Level)    ||
+       (pPrivate->NewParams.T60      != pPrivate->CurrentParams.T60) )
+    {
+        LVM_INT32 Index=0;
+        LVM_FLOAT Index_FLOAT;
+        LVM_INT32 i=0;
+        LVM_FLOAT Gain=0;
+        LVM_INT32 RoomSize=0;
+        LVM_FLOAT T60;
+        LVM_FLOAT Coefs[5];
+
+        if(pPrivate->NewParams.RoomSize == 0)
+        {
+            RoomSize = 1;
+        }
+        else
+        {
+            RoomSize = (LVM_INT32)pPrivate->NewParams.RoomSize;
+        }
+
+        if(pPrivate->NewParams.T60 < 100)
+        {
+            T60 = 100 * LVREV_T60_SCALE;
+        }
+        else
+        {
+            T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
+        }
+
+        /* Find the nearest room size in table */
+        for(i = 0; i < 24; i++)
+        {
+            if(RoomSize <= LVREV_GainPolyTable[i][0])
+            {
+                Index = i;
+                break;
+            }
+        }
+
+        if(RoomSize == LVREV_GainPolyTable[Index][0])
+        {
+            /* Take table values if the room size is in table */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
+            }
+            Coefs[4] = 0;
+            Gain = LVM_Polynomial(3, Coefs, T60);       /* Q.24 result */
+        }
+        else
+        {
+            /* Interpolate the gain between nearest room sizes */
+
+            LVM_FLOAT Gain1,Gain2;
+            LVM_INT32 Tot_Dist,Dist;
+
+            Tot_Dist = (LVM_UINT32)LVREV_GainPolyTable[Index][0] - \
+                                            (LVM_UINT32)LVREV_GainPolyTable[Index-1][0];
+            Dist = RoomSize - (LVM_UINT32)LVREV_GainPolyTable[Index - 1][0];
+
+            /* Get gain for first */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index-1][i];
+            }
+            Coefs[4] = 0;
+
+            Gain1 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
+
+            /* Get gain for second */
+            for(i = 1; i < 5; i++)
+            {
+                Coefs[i-1] = LVREV_GainPolyTable[Index][i];
+            }
+            Coefs[4] = 0;
+
+            Gain2 = LVM_Polynomial(3, Coefs, T60);      /* Q.24 result */
+
+            /* Linear Interpolate the gain */
+            Gain = Gain1 + (((Gain2 - Gain1) * Dist) / (Tot_Dist));
+        }
+
+        /*
+         * Get the inverse of gain: Q.15
+         * Gain is mostly above one except few cases, take only gains above 1
+         */
+        if(Gain < 1)
+        {
+            pPrivate->Gain = 1;
+        }
+        else
+        {
+            pPrivate->Gain = 1 / Gain;
+        }
+
+        Index_FLOAT = 100.0f / (LVM_FLOAT)(100 + pPrivate->NewParams.Level);
+        pPrivate->Gain = pPrivate->Gain * Index_FLOAT;
+        pPrivate->GainMixer.Target = (pPrivate->Gain*Index_FLOAT) / 2;
+    }
+
+    /*
+     * Update the all pass comb filter coefficient
+     */
+    if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
+        (pPrivate->bFirstControl     == LVM_TRUE))
+    {
+        LVM_INT16   i;
+        LVM_FLOAT   b = (LVM_FLOAT)pPrivate->NewParams.Density * LVREV_B_8_on_1000;
+
+        for (i = 0; i < 4; i++)
+        {
+            pPrivate->Mixer_SGFeedback[i].Target    = b;
+            pPrivate->Mixer_SGFeedforward[i].Target = b;
+        }
+    }
+
+    /*
+     * Update the bypass mixer time constant
+     */
+    if((pPrivate->NewParams.SampleRate   != pPrivate->CurrentParams.SampleRate)   ||
+       (pPrivate->bFirstControl          == LVM_TRUE))
+    {
+        LVM_UINT16   NumChannels = 1;                       /* Assume MONO format */
+        LVM_FLOAT    Alpha;
+
+        Alpha = LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC,
+                                       LVM_GetFsFromTable(pPrivate->NewParams.SampleRate),
+                                       NumChannels);
+        pPrivate->FeedbackMixer[0].Alpha = Alpha;
+        pPrivate->FeedbackMixer[1].Alpha = Alpha;
+        pPrivate->FeedbackMixer[2].Alpha = Alpha;
+        pPrivate->FeedbackMixer[3].Alpha = Alpha;
+
+        NumChannels = 2;                                    /* Always stereo output */
+        pPrivate->BypassMixer.Alpha1 = LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC,
+                             LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+        pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
+        pPrivate->GainMixer.Alpha    = pPrivate->BypassMixer.Alpha1;
+    }
+
+    /*
+     * Update the bypass mixer targets
+     */
+    if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
+        (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
+    {
+        pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
+        pPrivate->BypassMixer.Target1 = 0x00000000;
+        if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
+        {
+            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+        }
+        if (pPrivate->NewParams.Level != 0)
+        {
+            pPrivate->bDisableReverb = LVM_FALSE;
+        }
+    }
+
+    if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
+    {
+        if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
+        {
+            pPrivate->BypassMixer.Target2 = (LVM_FLOAT)(pPrivate->NewParams.Level ) / 100.0f;
+            pPrivate->BypassMixer.Target1 = 0x00000000;
+
+            pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
+            OperatingMode                      = LVM_MODE_ON;
+            if (pPrivate->NewParams.Level == 0)
+            {
+                pPrivate->bDisableReverb = LVM_TRUE;
+            }
+            else
+            {
+                pPrivate->bDisableReverb = LVM_FALSE;
+            }
+        }
+        else if (pPrivate->bFirstControl == LVM_FALSE)
+        {
+            pPrivate->BypassMixer.Target2 = 0x00000000;
+            pPrivate->BypassMixer.Target1 = 0x00000000;
+            pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+            pPrivate->GainMixer.Target    = 0.03125f;
+            OperatingMode = LVM_MODE_ON;
+        }
+        else
+        {
+            OperatingMode = LVM_MODE_OFF;
+        }
+    }
+
+    /*  If it is the first call to ApplyNew settings force the current to the target \
+        to begin immediate playback of the effect */
+    if(pPrivate->bFirstControl == LVM_TRUE)
+    {
+        pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
+        pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
+    }
+
+    /*
+     * Copy the new parameters
+     */
+    pPrivate->CurrentParams = pPrivate->NewParams;
+    pPrivate->CurrentParams.OperatingMode = OperatingMode;
+
+    /*
+     * Update flag
+     */
+    if(pPrivate->bFirstControl == LVM_TRUE)
+    {
+        pPrivate->bFirstControl = LVM_FALSE;
+    }
+
+    return LVREV_SUCCESS;
+}
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                BypassMixer_Callback                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Controls the On to Off operating mode transition                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pPrivate                Pointer to the instance private parameters                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When pPrivate is NULL                                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 BypassMixer_Callback (void *pCallbackData,
+                                void *pGeneralPurpose,
+                                LVM_INT16 GeneralPurpose )
+{
+
+    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
+
+    /*
+     * Avoid build warnings
+     */
+    (void)pGeneralPurpose;
+    (void)GeneralPurpose;
+
+    /*
+     * Turn off
+     */
+    pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
+    pLVREV_Private->bDisableReverb              = LVM_TRUE;
+    LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
+
+    return 0;
+}
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
deleted file mode 100644
index 9491016..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/* Includes                                                                             */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "VectorArithmetic.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_ClearAudioBuffers                                     */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to clear the internal audio buffers of the module.            */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_SUCCESS          Initialisation succeeded                                     */
-/*  LVREV_NULLADDRESS      Instance is NULL                                             */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. This function must not be interrupted by the LVM_Process function                */
-/*                                                                                      */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t  hInstance)
-{
-
-   LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
-
-
-    /*
-     * Check for error conditions
-     */
-    /* Check for NULL pointers */
-    if(hInstance == LVM_NULL)
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    /*
-     * Clear all filter tap data, delay-lines and other signal related data
-     */
-
-#ifdef BUILD_FLOAT
-    LoadConst_Float(0,
-                    (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: \
-                                                                   no dereferencing in function*/
-                    2);
-    LoadConst_Float(0,
-                    (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: \
-                                                                   no dereferencing in function*/
-                    2);
-#else
-    LoadConst_32(0,
-        (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
-        2);
-    LoadConst_32(0,
-        (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
-        2);
-#endif
-    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-    {
-#ifndef BUILD_FLOAT
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_32(0,pLVREV_Private->pDelay_T[3], (LVM_INT16)LVREV_MAX_T3_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[2], (LVM_INT16)LVREV_MAX_T2_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-#else
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-#endif
-    }
-
-    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2)
-    {
-#ifndef BUILD_FLOAT
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-#else
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-#endif
-    }
-
-    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1)
-    {
-#ifndef BUILD_FLOAT
-        LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-#else
-        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-#endif
-    }
-    return LVREV_SUCCESS;
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
new file mode 100644
index 0000000..586539f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Includes                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_ClearAudioBuffers                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to clear the internal audio buffers of the module.            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_SUCCESS          Initialisation succeeded                                     */
+/*  LVREV_NULLADDRESS      Instance is NULL                                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t  hInstance)
+{
+
+   LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+    /*
+     * Check for error conditions
+     */
+    /* Check for NULL pointers */
+    if(hInstance == LVM_NULL)
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    /*
+     * Clear all filter tap data, delay-lines and other signal related data
+     */
+
+    LoadConst_Float(0,
+        (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps,
+        2);
+    LoadConst_Float(0,
+        (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps,
+        2);
+    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+    {
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+    }
+
+    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2)
+    {
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+    }
+
+    if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1)
+    {
+        LoadConst_Float(0, (LVM_FLOAT *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+    }
+    return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c
deleted file mode 100644
index 7cee26d..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_GetControlParameters                                  */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Request the LVREV module control parameters. The current parameter set is returned  */
-/*  via the parameter pointer.                                                          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pControlParams          Pointer to an empty parameter structure                     */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When hInstance or pControlParams is NULL                    */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVREV_Process function                  */
-/*                                                                                      */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t           hInstance,
-                                                 LVREV_ControlParams_st   *pControlParams)
-{
-
-    LVREV_Instance_st  *pLVREV_Private = (LVREV_Instance_st *)hInstance;
-
-
-    /*
-     * Check for error conditions
-     */
-    if((hInstance == LVM_NULL) || (pControlParams == LVM_NULL))
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    /*
-     * Return the current parameters
-     */
-    *pControlParams = pLVREV_Private->NewParams;
-
-    return LVREV_SUCCESS;
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.cpp
new file mode 100644
index 0000000..e0b0142
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_GetControlParameters                                  */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the LVREV module control parameters. The current parameter set is returned  */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pControlParams          Pointer to an empty parameter structure                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When hInstance or pControlParams is NULL                    */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVREV_Process function                  */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t           hInstance,
+                                                 LVREV_ControlParams_st   *pControlParams)
+{
+
+    LVREV_Instance_st  *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+    /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pControlParams == LVM_NULL))
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    /*
+     * Return the current parameters
+     */
+    *pControlParams = pLVREV_Private->NewParams;
+
+    return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
deleted file mode 100644
index 3366bcb..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "InstAlloc.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_GetInstanceHandle                                     */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used to create a LVREV module instance. It returns the created     */
-/*  instance handle through phInstance. All parameters are set to their default,        */
-/*  inactive state.                                                                     */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  phInstance              pointer to the instance handle                              */
-/*  pMemoryTable            Pointer to the memory definition table                      */
-/*  pInstanceParams         Pointer to the instance parameters                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_SUCCESS           Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When phInstance or pMemoryTable or pInstanceParams is NULL  */
-/*  LVREV_NULLADDRESS       When one of the memory regions has a NULL pointer           */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*                                                                                      */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t            *phInstance,
-                                              LVREV_MemoryTable_st      *pMemoryTable,
-                                              LVREV_InstanceParams_st   *pInstanceParams)
-{
-
-    INST_ALLOC              SlowData;
-    INST_ALLOC              FastData;
-    INST_ALLOC              FastCoef;
-    INST_ALLOC              Temporary;
-    LVREV_Instance_st       *pLVREV_Private;
-    LVM_INT16               i;
-    LVM_UINT16              MaxBlockSize;
-
-
-    /*
-     * Check for error conditions
-     */
-    /* Check for NULL pointers */
-    if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstanceParams == LVM_NULL))
-    {
-        return LVREV_NULLADDRESS;
-    }
-    /* Check the memory table for NULL pointers */
-    for (i = 0; i < LVREV_NR_MEMORY_REGIONS; i++)
-    {
-        if (pMemoryTable->Region[i].Size!=0)
-        {
-            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
-            {
-                return(LVREV_NULLADDRESS);
-            }
-        }
-    }
-
-    /*
-     * Check all instance parameters are in range
-     */
-    /* Check for a non-zero block size */
-    if (pInstanceParams->MaxBlockSize == 0)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    /* Check for a valid number of delay lines */
-    if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1)&&
-        (pInstanceParams->NumDelays != LVREV_DELAYLINES_2)&&
-        (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    /*
-     * Initialise the InstAlloc instances
-     */
-    InstAlloc_Init(&SlowData,  pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress);
-    InstAlloc_Init(&FastData,  pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress);
-    InstAlloc_Init(&FastCoef,  pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress);
-    InstAlloc_Init(&Temporary, pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress);
-
-    /*
-     * Zero all memory regions
-     */
-#ifdef BUILD_FLOAT
-    LoadConst_Float(0,
-                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress,
-                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size) / \
-                                                    sizeof(LVM_FLOAT)));
-    LoadConst_Float(0,
-                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress,
-                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size) / \
-                                                    sizeof(LVM_FLOAT)));
-    LoadConst_Float(0,
-                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress,
-                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size) / \
-                                                    sizeof(LVM_FLOAT)));
-    LoadConst_Float(0,
-                    (LVM_FLOAT *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress,
-                    (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size) / \
-                                                    sizeof(LVM_FLOAT)));
-#else
-    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size)/sizeof(LVM_INT16)));
-    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size)/sizeof(LVM_INT16)));
-    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size)/sizeof(LVM_INT16)));
-    LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size)/sizeof(LVM_INT16)));
-#endif
-    /*
-     * Set the instance handle if not already initialised
-     */
-    if (*phInstance == LVM_NULL)
-    {
-        *phInstance = InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
-    }
-    pLVREV_Private              =(LVREV_Instance_st *)*phInstance;
-    pLVREV_Private->MemoryTable = *pMemoryTable;
-
-    if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
-    {
-        MaxBlockSize = LVREV_MAX_AP3_DELAY;
-    }
-    else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
-    {
-        MaxBlockSize = LVREV_MAX_AP1_DELAY;
-    }
-    else
-    {
-        MaxBlockSize = LVREV_MAX_AP0_DELAY;
-    }
-
-    if(MaxBlockSize>pInstanceParams->MaxBlockSize)
-    {
-        MaxBlockSize=pInstanceParams->MaxBlockSize;
-    }
-
-
-    /*
-     * Set the data, coefficient and temporary memory pointers
-     */
-    pLVREV_Private->pFastData = InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));                              /* Fast data memory base address */
-#ifndef BUILD_FLOAT
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
-    {
-        pLVREV_Private->pDelay_T[3]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY  * sizeof(LVM_INT32));
-        pLVREV_Private->pDelay_T[2]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY  * sizeof(LVM_INT32));
-        pLVREV_Private->pDelay_T[1]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
-        pLVREV_Private->pDelay_T[0]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-
-        for( i = 0; i < 4; i++)
-        {
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);       /* Scratch for each delay line output */
-        }
-
-        LoadConst_32(0,pLVREV_Private->pDelay_T[3]  ,(LVM_INT16)LVREV_MAX_T3_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[2]  ,(LVM_INT16)LVREV_MAX_T2_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[1]  ,(LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0]  ,(LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
-    {
-        pLVREV_Private->pDelay_T[1]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
-        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-
-        for( i = 0; i < 2; i++)
-        {
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);       /* Scratch for each delay line output */
-        }
-
-        LoadConst_32(0,pLVREV_Private->pDelay_T[1] , (LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0] , (LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
-    {
-        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-
-        for( i = 0; i < 1; i++)
-        {
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);       /* Scratch for each delay line output */
-        }
-
-        LoadConst_32(0,pLVREV_Private->pDelay_T[0]  , (LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-#else
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
-    {
-        pLVREV_Private->pDelay_T[3]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * \
-                                                              sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[2]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * \
-                                                              sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[1]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
-                                                              sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[0]     = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
-                                                              sizeof(LVM_FLOAT));
-
-        for(i = 0; i < 4; i++)
-        {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
-                                                                       sizeof(LVM_FLOAT) * \
-                                                                       MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
-    }
-
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
-    {
-        pLVREV_Private->pDelay_T[1]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
-                                                           sizeof(LVM_FLOAT));
-        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
-                                                           sizeof(LVM_FLOAT));
-
-        for(i = 0; i < 2; i++)
-        {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
-                                                                       sizeof(LVM_FLOAT) * \
-                                                                       MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-
-    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
-    {
-        pLVREV_Private->pDelay_T[0]  = InstAlloc_AddMember(&FastData,
-                                                           LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-
-        for(i = 0; i < 1; i++)
-        {
-            /* Scratch for each delay line output */
-            pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary,
-                                                                       sizeof(LVM_FLOAT) * \
-                                                                       MaxBlockSize);
-        }
-
-        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
-    }
-#endif
-    /* All-pass delay buffer addresses and sizes */
-    pLVREV_Private->T[0]         = LVREV_MAX_T0_DELAY;
-    pLVREV_Private->T[1]         = LVREV_MAX_T1_DELAY;
-    pLVREV_Private->T[2]         = LVREV_MAX_T2_DELAY;
-    pLVREV_Private->T[3]         = LVREV_MAX_T3_DELAY;
-    pLVREV_Private->AB_Selection = 1;       /* Select smoothing A to B */
-
-
-    pLVREV_Private->pFastCoef       = InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));                        /* Fast coefficient memory base address */
-#ifndef BUILD_FLOAT
-    pLVREV_Private->pScratch        = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);                /* General purpose scratch */
-    pLVREV_Private->pInputSave      = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_INT32) * MaxBlockSize);            /* Mono->stereo input save for end mix */
-    LoadConst_32(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize*2));
-#else
-    /* General purpose scratch */
-    pLVREV_Private->pScratch        = InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * \
-                                                          MaxBlockSize);
-    /* Mono->stereo input save for end mix */
-    pLVREV_Private->pInputSave      = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * \
-                                                          MaxBlockSize);
-    LoadConst_Float(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize * 2));
-#endif
-
-    /*
-     * Save the instance parameters in the instance structure
-     */
-    pLVREV_Private->InstanceParams = *pInstanceParams;
-
-
-    /*
-     * Set the parameters to invalid
-     */
-    pLVREV_Private->CurrentParams.SampleRate    = LVM_FS_INVALID;
-    pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_DUMMY;
-    pLVREV_Private->CurrentParams.SourceFormat  = LVM_SOURCE_DUMMY;
-
-    pLVREV_Private->bControlPending             = LVM_FALSE;
-    pLVREV_Private->bFirstControl               = LVM_TRUE;
-    pLVREV_Private->bDisableReverb              = LVM_FALSE;
-
-
-    /*
-     * Set mixer parameters
-     */
-    pLVREV_Private->BypassMixer.CallbackParam2      = 0;
-    pLVREV_Private->BypassMixer.pCallbackHandle2    = pLVREV_Private;
-    pLVREV_Private->BypassMixer.pGeneralPurpose2    = LVM_NULL;
-    pLVREV_Private->BypassMixer.pCallBack2          = BypassMixer_Callback;
-    pLVREV_Private->BypassMixer.CallbackSet2        = LVM_FALSE;
-    pLVREV_Private->BypassMixer.Current2            = 0;
-    pLVREV_Private->BypassMixer.Target2             = 0;
-    pLVREV_Private->BypassMixer.CallbackParam1      = 0;
-    pLVREV_Private->BypassMixer.pCallbackHandle1    = LVM_NULL;
-    pLVREV_Private->BypassMixer.pGeneralPurpose1    = LVM_NULL;
-    pLVREV_Private->BypassMixer.pCallBack1          = LVM_NULL;
-    pLVREV_Private->BypassMixer.CallbackSet1        = LVM_FALSE;
-    pLVREV_Private->BypassMixer.Current1            = 0x00000000;
-    pLVREV_Private->BypassMixer.Target1             = 0x00000000;
-
-    pLVREV_Private->RoomSizeInms                    = 100;  // 100 msec
-
-
-    /*
-     *  Set the output gain mixer parameters
-     */
-    pLVREV_Private->GainMixer.CallbackParam      = 0;
-    pLVREV_Private->GainMixer.pCallbackHandle    = LVM_NULL;
-    pLVREV_Private->GainMixer.pGeneralPurpose    = LVM_NULL;
-    pLVREV_Private->GainMixer.pCallBack          = LVM_NULL;
-    pLVREV_Private->GainMixer.CallbackSet        = LVM_FALSE;
-#ifndef BUILD_FLOAT
-    pLVREV_Private->GainMixer.Current            = 0x03ffffff;
-    pLVREV_Private->GainMixer.Target             = 0x03ffffff;
-#else
-    pLVREV_Private->GainMixer.Current            = 0.03125f;//0x03ffffff;
-    pLVREV_Private->GainMixer.Target             = 0.03125f;//0x03ffffff;
-#endif
-
-    /*
-     * Set the All-Pass Filter mixers
-     */
-    for (i=0; i<4; i++)
-    {
-        pLVREV_Private->pOffsetA[i] = pLVREV_Private->pDelay_T[i];
-        pLVREV_Private->pOffsetB[i] = pLVREV_Private->pDelay_T[i];
-        /* Delay tap selection mixer */
-        pLVREV_Private->Mixer_APTaps[i].CallbackParam2   = 0;
-        pLVREV_Private->Mixer_APTaps[i].pCallbackHandle2 = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose2 = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].pCallBack2       = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].CallbackSet2     = LVM_FALSE;
-        pLVREV_Private->Mixer_APTaps[i].Current2         = 0;
-        pLVREV_Private->Mixer_APTaps[i].Target2          = 0;
-        pLVREV_Private->Mixer_APTaps[i].CallbackParam1   = 0;
-        pLVREV_Private->Mixer_APTaps[i].pCallbackHandle1 = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose1 = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].pCallBack1       = LVM_NULL;
-        pLVREV_Private->Mixer_APTaps[i].CallbackSet1     = LVM_FALSE;
-        pLVREV_Private->Mixer_APTaps[i].Current1         = 0;
-#ifndef BUILD_FLOAT
-        pLVREV_Private->Mixer_APTaps[i].Target1          = 0x7fffffff;
-#else
-        pLVREV_Private->Mixer_APTaps[i].Target1          = 1;
-#endif
-        /* Feedforward mixer */
-        pLVREV_Private->Mixer_SGFeedforward[i].CallbackParam   = 0;
-        pLVREV_Private->Mixer_SGFeedforward[i].pCallbackHandle = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedforward[i].pGeneralPurpose = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedforward[i].pCallBack       = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedforward[i].CallbackSet     = LVM_FALSE;
-        pLVREV_Private->Mixer_SGFeedforward[i].Current         = 0;
-        pLVREV_Private->Mixer_SGFeedforward[i].Target          = 0;
-        /* Feedback mixer */
-        pLVREV_Private->Mixer_SGFeedback[i].CallbackParam   = 0;
-        pLVREV_Private->Mixer_SGFeedback[i].pCallbackHandle = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedback[i].pGeneralPurpose = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedback[i].pCallBack       = LVM_NULL;
-        pLVREV_Private->Mixer_SGFeedback[i].CallbackSet     = LVM_FALSE;
-        pLVREV_Private->Mixer_SGFeedback[i].Current         = 0;
-        pLVREV_Private->Mixer_SGFeedback[i].Target          = 0;
-        /* Feedback gain mixer */
-        pLVREV_Private->FeedbackMixer[i].CallbackParam    = 0;
-        pLVREV_Private->FeedbackMixer[i].pCallbackHandle  = LVM_NULL;
-        pLVREV_Private->FeedbackMixer[i].pGeneralPurpose  = LVM_NULL;
-        pLVREV_Private->FeedbackMixer[i].pCallBack        = LVM_NULL;
-        pLVREV_Private->FeedbackMixer[i].CallbackSet      = LVM_FALSE;
-        pLVREV_Private->FeedbackMixer[i].Current          = 0;
-        pLVREV_Private->FeedbackMixer[i].Target           = 0;
-    }
-    /* Delay tap index */
-    pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
-    pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
-    pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
-    pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
-    pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
-    pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
-    pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
-    pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
-
-
-    LVREV_ClearAudioBuffers(*phInstance);
-
-    return LVREV_SUCCESS;
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
new file mode 100644
index 0000000..68f883a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_GetInstanceHandle                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to create a LVREV module instance. It returns the created     */
+/*  instance handle through phInstance. All parameters are set to their default,        */
+/*  inactive state.                                                                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  phInstance              pointer to the instance handle                              */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pInstanceParams         Pointer to the instance parameters                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_SUCCESS           Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When phInstance or pMemoryTable or pInstanceParams is NULL  */
+/*  LVREV_NULLADDRESS       When one of the memory regions has a NULL pointer           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t            *phInstance,
+                                              LVREV_MemoryTable_st      *pMemoryTable,
+                                              LVREV_InstanceParams_st   *pInstanceParams)
+{
+
+    INST_ALLOC              SlowData;
+    INST_ALLOC              FastData;
+    INST_ALLOC              FastCoef;
+    INST_ALLOC              Temporary;
+    LVREV_Instance_st       *pLVREV_Private;
+    LVM_INT16               i;
+    LVM_UINT16              MaxBlockSize;
+
+    /*
+     * Check for error conditions
+     */
+    /* Check for NULL pointers */
+    if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstanceParams == LVM_NULL))
+    {
+        return LVREV_NULLADDRESS;
+    }
+    /* Check the memory table for NULL pointers */
+    for (i = 0; i < LVREV_NR_MEMORY_REGIONS; i++)
+    {
+        if (pMemoryTable->Region[i].Size!=0)
+        {
+            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+            {
+                return(LVREV_NULLADDRESS);
+            }
+        }
+    }
+
+    /*
+     * Check all instance parameters are in range
+     */
+    /* Check for a non-zero block size */
+    if (pInstanceParams->MaxBlockSize == 0)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    /* Check for a valid number of delay lines */
+    if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1)&&
+        (pInstanceParams->NumDelays != LVREV_DELAYLINES_2)&&
+        (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    /*
+     * Initialise the InstAlloc instances
+     */
+    InstAlloc_Init(&SlowData,  pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress);
+    InstAlloc_Init(&FastData,  pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress);
+    InstAlloc_Init(&FastCoef,  pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress);
+    InstAlloc_Init(&Temporary, pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress);
+
+    /*
+     * Zero all memory regions
+     */
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    LoadConst_Float(0,
+                    (LVM_FLOAT *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress,
+                    (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size) / \
+                                                    sizeof(LVM_FLOAT)));
+    /*
+     * Set the instance handle if not already initialised
+     */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+    }
+    pLVREV_Private              =(LVREV_Instance_st *)*phInstance;
+    pLVREV_Private->MemoryTable = *pMemoryTable;
+
+    if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+    {
+        MaxBlockSize = LVREV_MAX_AP3_DELAY;
+    }
+    else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+    {
+        MaxBlockSize = LVREV_MAX_AP1_DELAY;
+    }
+    else
+    {
+        MaxBlockSize = LVREV_MAX_AP0_DELAY;
+    }
+
+    if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+    {
+        MaxBlockSize=pInstanceParams->MaxBlockSize;
+    }
+
+    /*
+     * Set the data, coefficient and temporary memory pointers
+     */
+    /* Fast data memory base address */
+    pLVREV_Private->pFastData = (LVREV_FastData_st *)
+        InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+    {
+        pLVREV_Private->pDelay_T[3]     =
+            (LVM_FLOAT *)InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[2]     =
+            (LVM_FLOAT *)InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[1]     =
+            (LVM_FLOAT *)InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[0]     =
+            (LVM_FLOAT *)InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
+                                                              sizeof(LVM_FLOAT));
+
+        for(i = 0; i < 4; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = (LVM_FLOAT *)InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
+    }
+
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+    {
+        pLVREV_Private->pDelay_T[1]  = (LVM_FLOAT *)
+                InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * \
+                                                           sizeof(LVM_FLOAT));
+        pLVREV_Private->pDelay_T[0]  = (LVM_FLOAT *)
+                InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * \
+                                                           sizeof(LVM_FLOAT));
+
+        for(i = 0; i < 2; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = (LVM_FLOAT *)InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+    }
+
+    if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+    {
+        pLVREV_Private->pDelay_T[0]  = (LVM_FLOAT *)InstAlloc_AddMember(&FastData,
+                                                           LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+
+        for(i = 0; i < 1; i++)
+        {
+            /* Scratch for each delay line output */
+            pLVREV_Private->pScratchDelayLine[i] = (LVM_FLOAT *)InstAlloc_AddMember(&Temporary,
+                                                                       sizeof(LVM_FLOAT) * \
+                                                                       MaxBlockSize);
+        }
+
+        LoadConst_Float(0, pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+    }
+    /* All-pass delay buffer addresses and sizes */
+    pLVREV_Private->T[0]         = LVREV_MAX_T0_DELAY;
+    pLVREV_Private->T[1]         = LVREV_MAX_T1_DELAY;
+    pLVREV_Private->T[2]         = LVREV_MAX_T2_DELAY;
+    pLVREV_Private->T[3]         = LVREV_MAX_T3_DELAY;
+    pLVREV_Private->AB_Selection = 1;       /* Select smoothing A to B */
+
+    /* Fast coefficient memory base address */
+    pLVREV_Private->pFastCoef       =
+        (LVREV_FastCoef_st *)InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+    /* General purpose scratch */
+    pLVREV_Private->pScratch        =
+            (LVM_FLOAT *)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * \
+                                                          MaxBlockSize);
+    /* Mono->stereo input save for end mix */
+    pLVREV_Private->pInputSave      =
+            (LVM_FLOAT *)InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * \
+                                                          MaxBlockSize);
+    LoadConst_Float(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize * 2));
+
+    /*
+     * Save the instance parameters in the instance structure
+     */
+    pLVREV_Private->InstanceParams = *pInstanceParams;
+
+    /*
+     * Set the parameters to invalid
+     */
+    pLVREV_Private->CurrentParams.SampleRate    = LVM_FS_INVALID;
+    pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_DUMMY;
+    pLVREV_Private->CurrentParams.SourceFormat  = LVM_SOURCE_DUMMY;
+
+    pLVREV_Private->bControlPending             = LVM_FALSE;
+    pLVREV_Private->bFirstControl               = LVM_TRUE;
+    pLVREV_Private->bDisableReverb              = LVM_FALSE;
+
+    /*
+     * Set mixer parameters
+     */
+    pLVREV_Private->BypassMixer.CallbackParam2      = 0;
+    pLVREV_Private->BypassMixer.pCallbackHandle2    = pLVREV_Private;
+    pLVREV_Private->BypassMixer.pGeneralPurpose2    = LVM_NULL;
+    pLVREV_Private->BypassMixer.pCallBack2          = BypassMixer_Callback;
+    pLVREV_Private->BypassMixer.CallbackSet2        = LVM_FALSE;
+    pLVREV_Private->BypassMixer.Current2            = 0;
+    pLVREV_Private->BypassMixer.Target2             = 0;
+    pLVREV_Private->BypassMixer.CallbackParam1      = 0;
+    pLVREV_Private->BypassMixer.pCallbackHandle1    = LVM_NULL;
+    pLVREV_Private->BypassMixer.pGeneralPurpose1    = LVM_NULL;
+    pLVREV_Private->BypassMixer.pCallBack1          = LVM_NULL;
+    pLVREV_Private->BypassMixer.CallbackSet1        = LVM_FALSE;
+    pLVREV_Private->BypassMixer.Current1            = 0x00000000;
+    pLVREV_Private->BypassMixer.Target1             = 0x00000000;
+
+    pLVREV_Private->RoomSizeInms                    = 100;  // 100 msec
+
+    /*
+     *  Set the output gain mixer parameters
+     */
+    pLVREV_Private->GainMixer.CallbackParam      = 0;
+    pLVREV_Private->GainMixer.pCallbackHandle    = LVM_NULL;
+    pLVREV_Private->GainMixer.pGeneralPurpose    = LVM_NULL;
+    pLVREV_Private->GainMixer.pCallBack          = LVM_NULL;
+    pLVREV_Private->GainMixer.CallbackSet        = LVM_FALSE;
+    pLVREV_Private->GainMixer.Current            = 0.03125f;//0x03ffffff;
+    pLVREV_Private->GainMixer.Target             = 0.03125f;//0x03ffffff;
+
+    /*
+     * Set the All-Pass Filter mixers
+     */
+    for (i=0; i<4; i++)
+    {
+        pLVREV_Private->pOffsetA[i] = pLVREV_Private->pDelay_T[i];
+        pLVREV_Private->pOffsetB[i] = pLVREV_Private->pDelay_T[i];
+        /* Delay tap selection mixer */
+        pLVREV_Private->Mixer_APTaps[i].CallbackParam2   = 0;
+        pLVREV_Private->Mixer_APTaps[i].pCallbackHandle2 = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose2 = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].pCallBack2       = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].CallbackSet2     = LVM_FALSE;
+        pLVREV_Private->Mixer_APTaps[i].Current2         = 0;
+        pLVREV_Private->Mixer_APTaps[i].Target2          = 0;
+        pLVREV_Private->Mixer_APTaps[i].CallbackParam1   = 0;
+        pLVREV_Private->Mixer_APTaps[i].pCallbackHandle1 = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose1 = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].pCallBack1       = LVM_NULL;
+        pLVREV_Private->Mixer_APTaps[i].CallbackSet1     = LVM_FALSE;
+        pLVREV_Private->Mixer_APTaps[i].Current1         = 0;
+        pLVREV_Private->Mixer_APTaps[i].Target1          = 1;
+        /* Feedforward mixer */
+        pLVREV_Private->Mixer_SGFeedforward[i].CallbackParam   = 0;
+        pLVREV_Private->Mixer_SGFeedforward[i].pCallbackHandle = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedforward[i].pGeneralPurpose = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedforward[i].pCallBack       = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedforward[i].CallbackSet     = LVM_FALSE;
+        pLVREV_Private->Mixer_SGFeedforward[i].Current         = 0;
+        pLVREV_Private->Mixer_SGFeedforward[i].Target          = 0;
+        /* Feedback mixer */
+        pLVREV_Private->Mixer_SGFeedback[i].CallbackParam   = 0;
+        pLVREV_Private->Mixer_SGFeedback[i].pCallbackHandle = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedback[i].pGeneralPurpose = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedback[i].pCallBack       = LVM_NULL;
+        pLVREV_Private->Mixer_SGFeedback[i].CallbackSet     = LVM_FALSE;
+        pLVREV_Private->Mixer_SGFeedback[i].Current         = 0;
+        pLVREV_Private->Mixer_SGFeedback[i].Target          = 0;
+        /* Feedback gain mixer */
+        pLVREV_Private->FeedbackMixer[i].CallbackParam    = 0;
+        pLVREV_Private->FeedbackMixer[i].pCallbackHandle  = LVM_NULL;
+        pLVREV_Private->FeedbackMixer[i].pGeneralPurpose  = LVM_NULL;
+        pLVREV_Private->FeedbackMixer[i].pCallBack        = LVM_NULL;
+        pLVREV_Private->FeedbackMixer[i].CallbackSet      = LVM_FALSE;
+        pLVREV_Private->FeedbackMixer[i].Current          = 0;
+        pLVREV_Private->FeedbackMixer[i].Target           = 0;
+    }
+    /* Delay tap index */
+    pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+    pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+    pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+    pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+    pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+    pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+    pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+    pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+
+    LVREV_ClearAudioBuffers(*phInstance);
+
+    return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
deleted file mode 100644
index f6d446b..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "InstAlloc.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_GetMemoryTable                                        */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used for memory allocation and free. It can be called in           */
-/*  two ways:                                                                           */
-/*                                                                                      */
-/*  hInstance = NULL                Returns the memory requirements                     */
-/*  hInstance = Instance handle     Returns the memory requirements and allocated       */
-/*                                  base addresses.                                     */
-/*                                                                                      */
-/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
-/*  base address pointers are NULL on return.                                           */
-/*                                                                                      */
-/*  When the function is called for free (hInstance = Instance Handle) the memory       */
-/*  table returns the allocated memory and base addresses used during initialisation.   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pMemoryTable            Pointer to an empty memory table                            */
-/*  pInstanceParams         Pointer to the instance parameters                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When pMemoryTable is NULL                                   */
-/*  LVREV_NULLADDRESS       When requesting memory requirements and pInstanceParams     */
-/*                          is NULL                                                     */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVREV_Process function                  */
-/*                                                                                      */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t           hInstance,
-                                           LVREV_MemoryTable_st     *pMemoryTable,
-                                           LVREV_InstanceParams_st  *pInstanceParams)
-{
-
-    INST_ALLOC              SlowData;
-    INST_ALLOC              FastData;
-    INST_ALLOC              FastCoef;
-    INST_ALLOC              Temporary;
-    LVM_INT16               i;
-    LVM_UINT16              MaxBlockSize;
-
-
-    /*
-     * Check for error conditions
-     */
-    /* Check for NULL pointer */
-    if (pMemoryTable == LVM_NULL)
-    {
-        return(LVREV_NULLADDRESS);
-    }
-
-    /*
-     * Check all instance parameters are in range
-     */
-    if (pInstanceParams != LVM_NULL)
-    {
-        /*
-         * Call for memory allocation, so check the parameters
-         */
-        /* Check for a non-zero block size */
-        if (pInstanceParams->MaxBlockSize == 0)
-        {
-            return LVREV_OUTOFRANGE;
-        }
-
-        /* Check for a valid number of delay lines */
-        if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1) &&
-            (pInstanceParams->NumDelays != LVREV_DELAYLINES_2) &&
-            (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
-        {
-            return LVREV_OUTOFRANGE;
-        }
-    }
-
-    /*
-     * Initialise the InstAlloc instances
-     */
-    InstAlloc_Init(&SlowData,  (void *)LVM_NULL);
-    InstAlloc_Init(&FastData,  (void *)LVM_NULL);
-    InstAlloc_Init(&FastCoef,  (void *)LVM_NULL);
-    InstAlloc_Init(&Temporary, (void *)LVM_NULL);
-
-
-    /*
-     * Fill in the memory table
-     */
-    if (hInstance == LVM_NULL)
-    {
-        /*
-         * Check for null pointers
-         */
-        if (pInstanceParams == LVM_NULL)
-        {
-            return(LVREV_NULLADDRESS);
-        }
-
-
-        /*
-         * Select the maximum internal block size
-         */
-        if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
-        {
-            MaxBlockSize = LVREV_MAX_AP3_DELAY;
-        }
-        else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
-        {
-            MaxBlockSize = LVREV_MAX_AP1_DELAY;
-        }
-        else
-        {
-            MaxBlockSize = LVREV_MAX_AP0_DELAY;
-        }
-
-        if(MaxBlockSize>pInstanceParams->MaxBlockSize)
-        {
-            MaxBlockSize=pInstanceParams->MaxBlockSize;
-        }
-
-
-        /*
-         * Slow data memory
-         */
-        InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
-        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&SlowData);
-        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
-        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
-
-        /*
-         * Persistent fast data memory
-         */
-        InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
-        {
-#ifndef BUILD_FLOAT
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY  * sizeof(LVM_INT32));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY  * sizeof(LVM_INT32));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-#else
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-#endif
-        }
-
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
-        {
-#ifndef BUILD_FLOAT
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-#else
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-#endif
-        }
-
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
-        {
-#ifndef BUILD_FLOAT
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
-#else
-            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
-#endif
-        }
-
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&FastData);
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-
-
-        /*
-         * Persistent fast coefficient memory
-         */
-        InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&FastCoef);
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
-        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-
-
-        /*
-         * Temporary fast memory
-         */
-#ifndef BUILD_FLOAT
-        InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);          /* General purpose scratch memory */
-        InstAlloc_AddMember(&Temporary, 2*sizeof(LVM_INT32) * MaxBlockSize);        /* Mono->stereo input saved for end mix */
-#else
-        /* General purpose scratch memory */
-        InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-        /* Mono->stereo input saved for end mix */
-        InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
-#endif
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
-        {
-            for(i=0; i<4; i++)
-            {
-#ifndef BUILD_FLOAT
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
-#else
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-#endif
-            }
-        }
-
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
-        {
-            for(i=0; i<2; i++)
-            {
-#ifndef BUILD_FLOAT
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
-#else
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-#endif
-            }
-        }
-
-        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
-        {
-            for(i=0; i<1; i++)
-            {
-#ifndef BUILD_FLOAT
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize);      /* A Scratch buffer for each delay line */
-#else
-                /* A Scratch buffer for each delay line */
-                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
-#endif
-            }
-        }
-
-        pMemoryTable->Region[LVM_TEMPORARY_FAST].Size         = InstAlloc_GetTotal(&Temporary);
-        pMemoryTable->Region[LVM_TEMPORARY_FAST].Type         = LVM_TEMPORARY_FAST;
-        pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
-
-    }
-    else
-    {
-        LVREV_Instance_st   *pLVREV_Private = (LVREV_Instance_st *)hInstance;
-
-
-        /*
-         * Read back memory allocation table
-         */
-        *pMemoryTable = pLVREV_Private->MemoryTable;
-    }
-
-
-    return(LVREV_SUCCESS);
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
new file mode 100644
index 0000000..f59933c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_GetMemoryTable                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*  hInstance = NULL                Returns the memory requirements                     */
+/*  hInstance = Instance handle     Returns the memory requirements and allocated       */
+/*                                  base addresses.                                     */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory table                            */
+/*  pInstanceParams         Pointer to the instance parameters                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When pMemoryTable is NULL                                   */
+/*  LVREV_NULLADDRESS       When requesting memory requirements and pInstanceParams     */
+/*                          is NULL                                                     */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVREV_Process function                  */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t           hInstance,
+                                           LVREV_MemoryTable_st     *pMemoryTable,
+                                           LVREV_InstanceParams_st  *pInstanceParams)
+{
+
+    INST_ALLOC              SlowData;
+    INST_ALLOC              FastData;
+    INST_ALLOC              FastCoef;
+    INST_ALLOC              Temporary;
+    LVM_INT16               i;
+    LVM_UINT16              MaxBlockSize;
+
+    /*
+     * Check for error conditions
+     */
+    /* Check for NULL pointer */
+    if (pMemoryTable == LVM_NULL)
+    {
+        return(LVREV_NULLADDRESS);
+    }
+
+    /*
+     * Check all instance parameters are in range
+     */
+    if (pInstanceParams != LVM_NULL)
+    {
+        /*
+         * Call for memory allocation, so check the parameters
+         */
+        /* Check for a non-zero block size */
+        if (pInstanceParams->MaxBlockSize == 0)
+        {
+            return LVREV_OUTOFRANGE;
+        }
+
+        /* Check for a valid number of delay lines */
+        if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1) &&
+            (pInstanceParams->NumDelays != LVREV_DELAYLINES_2) &&
+            (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+        {
+            return LVREV_OUTOFRANGE;
+        }
+    }
+
+    /*
+     * Initialise the InstAlloc instances
+     */
+    InstAlloc_Init(&SlowData,  (void *)LVM_NULL);
+    InstAlloc_Init(&FastData,  (void *)LVM_NULL);
+    InstAlloc_Init(&FastCoef,  (void *)LVM_NULL);
+    InstAlloc_Init(&Temporary, (void *)LVM_NULL);
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Check for null pointers
+         */
+        if (pInstanceParams == LVM_NULL)
+        {
+            return(LVREV_NULLADDRESS);
+        }
+
+        /*
+         * Select the maximum internal block size
+         */
+        if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+        {
+            MaxBlockSize = LVREV_MAX_AP3_DELAY;
+        }
+        else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+        {
+            MaxBlockSize = LVREV_MAX_AP1_DELAY;
+        }
+        else
+        {
+            MaxBlockSize = LVREV_MAX_AP0_DELAY;
+        }
+
+        if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+        {
+            MaxBlockSize=pInstanceParams->MaxBlockSize;
+        }
+
+        /*
+         * Slow data memory
+         */
+        InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&SlowData);
+        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
+        pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent fast data memory
+         */
+        InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+        {
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+        }
+
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+        {
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_FLOAT));
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+        }
+
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+        {
+            InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_FLOAT));
+        }
+
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&FastData);
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent fast coefficient memory
+         */
+        InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&FastCoef);
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
+        pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Temporary fast memory
+         */
+        /* General purpose scratch memory */
+        InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+        /* Mono->stereo input saved for end mix */
+        InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_FLOAT) * MaxBlockSize);
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+        {
+            for(i=0; i<4; i++)
+            {
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+            }
+        }
+
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+        {
+            for(i=0; i<2; i++)
+            {
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+            }
+        }
+
+        if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+        {
+            for(i=0; i<1; i++)
+            {
+                /* A Scratch buffer for each delay line */
+                InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
+            }
+        }
+
+        pMemoryTable->Region[LVM_TEMPORARY_FAST].Size         = InstAlloc_GetTotal(&Temporary);
+        pMemoryTable->Region[LVM_TEMPORARY_FAST].Type         = LVM_TEMPORARY_FAST;
+        pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+
+    }
+    else
+    {
+        LVREV_Instance_st   *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+        /*
+         * Read back memory allocation table
+         */
+        *pMemoryTable = pLVREV_Private->MemoryTable;
+    }
+
+    return(LVREV_SUCCESS);
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index c915ac0..2c27c6e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -18,11 +18,6 @@
 #ifndef __LVREV_PRIVATE_H__
 #define __LVREV_PRIVATE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -36,43 +31,22 @@
 #include "Mixer.h"
 #include "LVM_Macros.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Defines                                                                             */
 /*                                                                                      */
 /****************************************************************************************/
-#ifndef BUILD_FLOAT
-/* General */
-#define ONE_OVER_SQRT_TWO               23170           /* 1/sqrt(2) * 2^15 */
-#define LVREV_B_8_on_1000            17179869           /* 0.8 * 2^31 */
-#define LVREV_HEADROOM                   8192           /* -12dB * 2^15 */
-#define LVREV_2_9_INQ29           1583769190L           /* 2.9 in Q29 format */
-#define LVREV_MIN3DB                   0x5A82           /* -3dB in Q15 format */
-#else
 /* General */
 #define ONE_OVER_SQRT_TWO            0.707107f           /* 1/sqrt(2) * 2^15 */
 #define LVREV_B_8_on_1000               0.008f           /* 0.8 * 2^31 */
 #define LVREV_HEADROOM                   0.25f           /* -12dB * 2^15 */
 #define LVREV_2_9_INQ29                   2.9f           /* 2.9 in Q29 format */
 #define LVREV_MIN3DB                0.7079457f           /* -3dB in Q15 format */
-#endif
 
 /* Intenal constants */
 #define LVREV_LP_Poly_Order                 4
 #define LVREV_LP_Poly_Shift                 5
 
-#ifndef BUILD_FLOAT
-#define LVREV_T_3_Power_0_on_4          32768
-#define LVREV_T_3_Power_1_on_4          43125
-#define LVREV_T_3_Power_2_on_4          56755
-#define LVREV_T_3_Power_3_on_4          74694
-#define LVREV_T60_SCALE                306774           /*(32767/7000)<<16 */
-#define LVREV_T_3_Power_minus0_on_4     32767           /* 3^(-0/4) * 2^15 */
-#define LVREV_T_3_Power_minus1_on_4     24898           /* 3^(-1/4) * 2^15 */
-#define LVREV_T_3_Power_minus2_on_4     18919           /* 3^(-2/4) * 2^15 */
-#define LVREV_T_3_Power_minus3_on_4     14375           /* 3^(-3/4) * 2^15 */
-#else/*BUILD_FLOAT*/
 #define LVREV_T60_SCALE                0.000142f           /*(1/7000) */
 
 #define LVREV_T_3_Power_0_on_4              1.0f
@@ -83,18 +57,7 @@
 #define LVREV_T_3_Power_minus1_on_4    0.759836f        /* 3^(-1/4) * 2^15 */
 #define LVREV_T_3_Power_minus2_on_4    0.577350f        /* 3^(-2/4) * 2^15 */
 #define LVREV_T_3_Power_minus3_on_4    0.438691f        /* 3^(-3/4) * 2^15 */
-#endif
 
-#ifndef HIGHER_FS
-#define LVREV_MAX_T3_DELAY                2527           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T2_DELAY                3326           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T1_DELAY                4377           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
-#define LVREV_MAX_T0_DELAY                5760           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
-#define LVREV_MAX_AP3_DELAY               1685           /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP2_DELAY               2218           /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP1_DELAY               2918           /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
-#define LVREV_MAX_AP0_DELAY               3840           /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
-#else
     /* ((192000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
 #define LVREV_MAX_T3_DELAY               10108
     /* ((192000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
@@ -111,7 +74,6 @@
 #define LVREV_MAX_AP1_DELAY              11672
     /* ((192000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
 #define LVREV_MAX_AP0_DELAY              15360
-#endif
 
 #define LVREV_BYPASSMIXER_TC             1000           /* Bypass mixer time constant*/
 #define LVREV_ALLPASS_TC                 1000           /* All-pass filter time constant */
@@ -120,11 +82,7 @@
 #define LVREV_OUTPUTGAIN_SHIFT              5           /* Bits shift for output gain correction */
 
 /* Parameter limits */
-#ifndef HIGHER_FS
-#define LVREV_NUM_FS                        9           /* Number of supported sample rates */
-#else
 #define LVREV_NUM_FS                       13           /* Number of supported sample rates */
-#endif
 
 #define LVREV_MAXBLKSIZE_LIMIT             64           /* Maximum block size low limit */
 #define LVREV_MAX_LEVEL                   100           /* Maximum level, 100% */
@@ -137,81 +95,11 @@
 #define LVREV_MAX_DAMPING                 100           /* Maximum damping, 100% */
 #define LVREV_MAX_ROOMSIZE                100           /* Maximum room size, 100% */
 
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
 /*                                                                                      */
 /****************************************************************************************/
-#ifndef BUILD_FLOAT
-/* Fast data structure */
-typedef struct
-{
-
-    Biquad_1I_Order1_Taps_t HPTaps;                     /* High pass filter taps */
-    Biquad_1I_Order1_Taps_t LPTaps;                     /* Low pass filter taps */
-    Biquad_1I_Order1_Taps_t RevLPTaps[4];               /* Reverb low pass filters taps */
-
-} LVREV_FastData_st;
-
-
-/* Fast coefficient structure */
-typedef struct
-{
-
-    Biquad_Instance_t       HPCoefs;                    /* High pass filter coefficients */
-    Biquad_Instance_t       LPCoefs;                    /* Low pass filter coefficients */
-    Biquad_Instance_t       RevLPCoefs[4];              /* Reverb low pass filters coefficients */
-
-} LVREV_FastCoef_st;
-
-
-/* Instance parameter structure */
-typedef struct
-{
-    /* General */
-    LVREV_InstanceParams_st InstanceParams;             /* Initialisation time instance parameters */
-    LVREV_MemoryTable_st    MemoryTable;                /* Memory table */
-    LVREV_ControlParams_st  CurrentParams;              /* Parameters being used */
-    LVREV_ControlParams_st  NewParams;                  /* New parameters from the calling application */
-    LVM_CHAR                bControlPending;            /* Flag to indicate new parameters are available */
-    LVM_CHAR                bFirstControl;              /* Flag to indicate that the control function is called for the first time */
-    LVM_CHAR                bDisableReverb;             /* Flag to indicate that the mix level is 0% and the reverb can be disabled */
-    LVM_INT32               RoomSizeInms;               /* Room size in msec */
-    LVM_INT32               MaxBlkLen;                  /* Maximum block size for internal processing */
-
-    /* Aligned memory pointers */
-    LVREV_FastData_st       *pFastData;                 /* Fast data memory base address */
-    LVREV_FastCoef_st       *pFastCoef;                 /* Fast coefficient memory base address */
-    LVM_INT32               *pScratchDelayLine[4];      /* Delay line scratch memory */
-    LVM_INT32               *pScratch;                  /* Multi ussge scratch */
-    LVM_INT32               *pInputSave;                /* Reverb block input save for dry/wet mixing*/
-
-    /* Feedback matrix */
-    Mix_1St_Cll_t           FeedbackMixer[4];           /* Mixer for Pop and Click Supression caused by feedback Gain */
-
-    /* All-Pass Filter */
-    LVM_INT32               T[4];                       /* Maximum delay size of buffer */
-    LVM_INT32               *pDelay_T[4];               /* Pointer to delay buffers */
-    LVM_INT32               Delay_AP[4];                /* Offset to AP delay buffer start */
-    LVM_INT16               AB_Selection;               /* Smooth from tap A to B when 1 otherwise B to A */
-    LVM_INT32               A_DelaySize[4];             /* A delay length in samples */
-    LVM_INT32               B_DelaySize[4];             /* B delay length in samples */
-    LVM_INT32               *pOffsetA[4];               /* Offset for the A delay tap */
-    LVM_INT32               *pOffsetB[4];               /* Offset for the B delay tap */
-    Mix_2St_Cll_t           Mixer_APTaps[4];            /* Smoothed AP delay mixer */
-    Mix_1St_Cll_t           Mixer_SGFeedback[4];        /* Smoothed SAfeedback gain */
-    Mix_1St_Cll_t           Mixer_SGFeedforward[4];     /* Smoothed AP feedforward gain */
-
-    /* Output gain */
-    Mix_2St_Cll_t           BypassMixer;                /* Dry/wet mixer */
-    LVM_INT16               Gain;                       /* Gain applied to output to maintain average signal power */
-    Mix_1St_Cll_t           GainMixer;                  /* Gain smoothing */
-
-} LVREV_Instance_st;
-
-#else /* BUILD_FLOAT */
 
 /* Fast data structure */
 typedef struct
@@ -222,7 +110,6 @@
 
 } LVREV_FastData_st;
 
-
 /* Fast coefficient structure */
 typedef struct
 {
@@ -262,7 +149,6 @@
     Mix_1St_Cll_FLOAT_t     FeedbackMixer[4];         /* Mixer for Pop and Click Supression \
                                                          caused by feedback Gain */
 
-
     /* All-Pass Filter */
     LVM_INT32               T[4];                     /* Maximum delay size of buffer */
     LVM_FLOAT               *pDelay_T[4];             /* Pointer to delay buffers */
@@ -285,7 +171,6 @@
 
 } LVREV_Instance_st;
 
-#endif
 /****************************************************************************************/
 /*                                                                                      */
 /*  Function prototypes                                                                 */
@@ -293,26 +178,14 @@
 /****************************************************************************************/
 
 LVREV_ReturnStatus_en   LVREV_ApplyNewSettings(LVREV_Instance_st     *pPrivate);
-#ifdef BUILD_FLOAT
 void                    ReverbBlock(LVM_FLOAT           *pInput,
                                     LVM_FLOAT           *pOutput,
                                     LVREV_Instance_st   *pPrivate,
                                     LVM_UINT16          NumSamples);
-#else
-void                    ReverbBlock(LVM_INT32           *pInput,
-                                    LVM_INT32           *pOutput,
-                                    LVREV_Instance_st   *pPrivate,
-                                    LVM_UINT16          NumSamples);
-#endif
 LVM_INT32               BypassMixer_Callback(void       *pCallbackData,
                                              void       *pGeneralPurpose,
                                              LVM_INT16  GeneralPurpose );
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif  /** __LVREV_PRIVATE_H__ **/
 
 /* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
deleted file mode 100644
index 1d1283e..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/* Includes                                                                             */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-#include "VectorArithmetic.h"
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_Process                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Process function for the LVREV module.                                              */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pInData                 Pointer to the input data                                   */
-/*  pOutData                Pointer to the output data                                  */
-/*  NumSamples              Number of samples in the input buffer                       */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
-/*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The input and output buffers must be 32-bit aligned                              */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
-                                    const LVM_FLOAT     *pInData,
-                                    LVM_FLOAT           *pOutData,
-                                    const LVM_UINT16    NumSamples)
-#else
-LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
-                                    const LVM_INT32     *pInData,
-                                    LVM_INT32           *pOutData,
-                                    const LVM_UINT16    NumSamples)
-#endif
-{
-   LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
-#ifdef BUILD_FLOAT
-   LVM_FLOAT             *pInput  = (LVM_FLOAT *)pInData;
-   LVM_FLOAT             *pOutput = pOutData;
-#else
-   LVM_INT32             *pInput  = (LVM_INT32 *)pInData;
-   LVM_INT32             *pOutput = pOutData;
-#endif
-   LVM_INT32             SamplesToProcess, RemainingSamples;
-   LVM_INT32             format = 1;
-
-    /*
-     * Check for error conditions
-     */
-
-    /* Check for NULL pointers */
-    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    /*
-     * Apply the new controls settings if required
-     */
-    if(pLVREV_Private->bControlPending == LVM_TRUE)
-    {
-        LVREV_ReturnStatus_en   errorCode;
-
-        /*
-         * Clear the pending flag and update the control settings
-         */
-        pLVREV_Private->bControlPending = LVM_FALSE;
-
-        errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
-
-        if(errorCode != LVREV_SUCCESS)
-        {
-            return errorCode;
-        }
-    }
-
-    /*
-     * Trap the case where the number of samples is zero.
-     */
-    if (NumSamples == 0)
-    {
-        return LVREV_SUCCESS;
-    }
-
-    /*
-     * If OFF copy and reformat the data as necessary
-     */
-    if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
-    {
-        if(pInput != pOutput)
-        {
-            /*
-             * Copy the data to the output buffer, convert to stereo is required
-             */
-#ifndef BUILD_FLOAT
-            if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
-                MonoTo2I_32(pInput, pOutput, NumSamples);
-            } else {
-                Copy_16((LVM_INT16 *)pInput,
-                        (LVM_INT16 *)pOutput,
-                        (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo
-            }
-#else
-            if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
-                MonoTo2I_Float(pInput, pOutput, NumSamples);
-            } else {
-                Copy_Float(pInput,
-                           pOutput,
-                           (LVM_INT16)(NumSamples << 1)); // 32 bit data, stereo
-            }
-#endif
-        }
-
-        return LVREV_SUCCESS;
-    }
-
-    RemainingSamples = (LVM_INT32)NumSamples;
-
-    if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
-    {
-        format = 2;
-    }
-
-    while (RemainingSamples!=0)
-    {
-        /*
-         * Process the data
-         */
-
-        if(RemainingSamples >  pLVREV_Private->MaxBlkLen)
-        {
-            SamplesToProcess =  pLVREV_Private->MaxBlkLen;
-            RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
-        }
-        else
-        {
-            SamplesToProcess = RemainingSamples;
-            RemainingSamples = 0;
-        }
-
-        ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
-#ifdef BUILD_FLOAT
-        pInput  = (LVM_FLOAT *)(pInput + (SamplesToProcess * format));
-        pOutput = (LVM_FLOAT *)(pOutput + (SamplesToProcess * 2));      // Always stereo output
-#else
-        pInput  = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
-        pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2));
-#endif
-    }
-
-    return LVREV_SUCCESS;
-}
-
-
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                ReverbBlock                                                 */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Process function for the LVREV module.                                              */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pInData                 Pointer to the input data                                   */
-/*  pOutData                Pointer to the output data                                  */
-/*  NumSamples              Number of samples in the input buffer                       */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVREV_Success           Succeeded                                                   */
-/*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
-/*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The input and output buffers must be 32-bit aligned                              */
-/*                                                                                      */
-/****************************************************************************************/
-#ifndef BUILD_FLOAT
-void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
-{
-    LVM_INT16   j, size;
-    LVM_INT32   *pDelayLine;
-    LVM_INT32   *pDelayLineInput = pPrivate->pScratch;
-    LVM_INT32   *pScratch = pPrivate->pScratch;
-    LVM_INT32   *pIn;
-    LVM_INT32   *pTemp = pPrivate->pInputSave;
-    LVM_INT32   NumberOfDelayLines;
-
-    /******************************************************************************
-     * All calculations will go into the buffer pointed to by pTemp, this will    *
-     * then be mixed with the original input to create the final output.          *
-     *                                                                            *
-     * When INPLACE processing is selected this must be a temporary buffer and    *
-     * hence this is the worst case, so for simplicity this will ALWAYS be so     *
-     *                                                                            *
-     * The input buffer will remain untouched until the output of the mixer if    *
-     * INPLACE processing is selected.                                            *
-     *                                                                            *
-     * The temp buffer will always be NumSamples in size regardless of MONO or    *
-     * STEREO input. In the case of stereo input all processing is done in MONO   *
-     * and the final output is converted to STEREO after the mixer                *
-     ******************************************************************************/
-
-    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 )
-    {
-        NumberOfDelayLines = 4;
-    }
-    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 )
-    {
-        NumberOfDelayLines = 2;
-    }
-    else
-    {
-        NumberOfDelayLines = 1;
-    }
-
-    if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
-    {
-        pIn = pInput;
-    }
-    else
-    {
-        /*
-         *  Stereo to mono conversion
-         */
-
-        From2iToMono_32( pInput,
-                         pTemp,
-                         (LVM_INT16)NumSamples);
-
-        pIn = pTemp;
-    }
-
-    Mult3s_32x16(pIn,
-                 (LVM_INT16)LVREV_HEADROOM,
-                 pTemp,
-                 (LVM_INT16)NumSamples);
-
-    /*
-     *  High pass filter
-     */
-    FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs,
-                                pTemp,
-                                pTemp,
-                                (LVM_INT16)NumSamples);
-    /*
-     *  Low pass filter
-     */
-    FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs,
-                                pTemp,
-                                pTemp,
-                                (LVM_INT16)NumSamples);
-
-    /*
-     *  Process all delay lines
-     */
-
-    for(j = 0; j < NumberOfDelayLines; j++)
-    {
-        pDelayLine = pPrivate->pScratchDelayLine[j];
-
-        /*
-         * All-pass filter with pop and click suppression
-         */
-        /* Get the smoothed, delayed output. Put it in the output buffer */
-        MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
-                               pPrivate->pOffsetA[j],
-                               pPrivate->pOffsetB[j],
-                               pDelayLine,
-                               (LVM_INT16)NumSamples);
-        /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */
-        Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples],
-                (LVM_INT16 *)pPrivate->pDelay_T[j],
-                (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1));         /* 32-bit data */
-        /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
-        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
-                               pDelayLine,
-                               &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
-                               (LVM_INT16)NumSamples);
-        /* Sum into the AP delay line */
-        Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
-                        -0x7fff,                                        /* Invert since the feedback coefficient is negative */
-                        &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
-                        (LVM_INT16)NumSamples);
-        /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
-        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
-                               &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
-                               &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
-                               (LVM_INT16)NumSamples);
-        /* Sum into the AP output */
-        Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
-                        0x7fff,
-                        pDelayLine,
-                        (LVM_INT16)NumSamples);
-
-        /*
-         *  Feedback gain
-         */
-        MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
-
-        /*
-         *  Low pass filter
-         */
-        FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j],
-                                    pDelayLine,
-                                    pDelayLine,
-                                    (LVM_INT16)NumSamples);
-    }
-
-    /*
-     *  Apply rotation matrix and delay samples
-     */
-    for(j = 0; j < NumberOfDelayLines; j++)
-    {
-
-        Copy_16( (LVM_INT16*)(pTemp),
-                 (LVM_INT16*)(pDelayLineInput),
-                 (LVM_INT16)(NumSamples << 1));
-
-        /*
-         *  Rotation matrix mix
-         */
-        switch(j)
-        {
-            case 3:
-                /*
-                 *  Add delay line 1 and 2 contribution
-                 */
-                 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-                 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-
-                break;
-            case 2:
-
-                /*
-                 *  Add delay line 0 and 3 contribution
-                 */
-                 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-                 Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-
-                break;
-            case 1:
-                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-                {
-                    /*
-                     *  Add delay line 0 and 3 contribution
-                     */
-                    Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-                    Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                else
-                {
-                    /*
-                     *  Add delay line 0 and 1 contribution
-                     */
-                     Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-                     Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                break;
-            case 0:
-                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-                {
-                    /*
-                     *  Add delay line 1 and 2 contribution
-                     */
-                    Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-                    Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
-                {
-                    /*
-                     *  Add delay line 0 and 1 contribution
-                     */
-                    Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
-                    Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                else
-                {
-                    /*
-                     *  Add delay line 0 contribution
-                     */
-
-                    /*             SOURCE                          DESTINATION*/
-                    Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
-                }
-                break;
-            default:
-                break;
-        }
-
-        /*
-         *  Delay samples
-         */
-        Copy_16((LVM_INT16 *)pDelayLineInput,
-                (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
-                (LVM_INT16)(NumSamples << 1));              /* 32-bit data */
-
-    }
-
-
-    /*
-     *  Create stereo output
-     */
-    switch(pPrivate->InstanceParams.NumDelays)
-    {
-        case LVREV_DELAYLINES_4:
-             Add2_Sat_32x32(pPrivate->pScratchDelayLine[3],
-                            pPrivate->pScratchDelayLine[0],
-                            (LVM_INT16)NumSamples);
-             Add2_Sat_32x32(pPrivate->pScratchDelayLine[2],
-                            pPrivate->pScratchDelayLine[1],
-                            (LVM_INT16)NumSamples);
-
-
-            JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
-                           pPrivate->pScratchDelayLine[1],
-                           pTemp,
-                           (LVM_INT16)NumSamples);
-
-
-            break;
-        case LVREV_DELAYLINES_2:
-
-             Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1],
-                      (LVM_INT16*)pScratch,
-                      (LVM_INT16)(NumSamples << 1));
-
-            Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
-                            -0x8000,
-                            pScratch,
-                            (LVM_INT16)NumSamples);
-
-             Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
-                            pPrivate->pScratchDelayLine[0],
-                            (LVM_INT16)NumSamples);
-
-
-             JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
-                            pScratch,
-                            pTemp,
-                            (LVM_INT16)NumSamples);
-            break;
-        case LVREV_DELAYLINES_1:
-            MonoTo2I_32(pPrivate->pScratchDelayLine[0],
-                        pTemp,
-                        (LVM_INT16)NumSamples);
-            break;
-        default:
-            break;
-    }
-
-
-    /*
-     *  Dry/wet mixer
-     */
-
-    size = (LVM_INT16)(NumSamples << 1);
-    MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
-                           pTemp,
-                           pTemp,
-                           pOutput,
-                           size);
-
-    /* Apply Gain*/
-
-    Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
-                       pOutput,
-                       pOutput,
-                       size);
-
-    MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
-                           pOutput,
-                           pOutput,
-                           size);
-
-    return;
-}
-#else
-void ReverbBlock(LVM_FLOAT *pInput, LVM_FLOAT *pOutput,
-                 LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
-{
-    LVM_INT16   j, size;
-    LVM_FLOAT   *pDelayLine;
-    LVM_FLOAT   *pDelayLineInput = pPrivate->pScratch;
-    LVM_FLOAT   *pScratch = pPrivate->pScratch;
-    LVM_FLOAT   *pIn;
-    LVM_FLOAT   *pTemp = pPrivate->pInputSave;
-    LVM_INT32   NumberOfDelayLines;
-
-    /******************************************************************************
-     * All calculations will go into the buffer pointed to by pTemp, this will    *
-     * then be mixed with the original input to create the final output.          *
-     *                                                                            *
-     * When INPLACE processing is selected this must be a temporary buffer and    *
-     * hence this is the worst case, so for simplicity this will ALWAYS be so     *
-     *                                                                            *
-     * The input buffer will remain untouched until the output of the mixer if    *
-     * INPLACE processing is selected.                                            *
-     *                                                                            *
-     * The temp buffer will always be NumSamples in size regardless of MONO or    *
-     * STEREO input. In the case of stereo input all processing is done in MONO   *
-     * and the final output is converted to STEREO after the mixer                *
-     ******************************************************************************/
-
-    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-    {
-        NumberOfDelayLines = 4;
-    }
-    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
-    {
-        NumberOfDelayLines = 2;
-    }
-    else
-    {
-        NumberOfDelayLines = 1;
-    }
-
-    if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
-    {
-        pIn = pInput;
-    }
-    else
-    {
-        /*
-         *  Stereo to mono conversion
-         */
-
-        From2iToMono_Float(pInput,
-                           pTemp,
-                           (LVM_INT16)NumSamples);
-        pIn = pTemp;
-    }
-
-    Mult3s_Float(pIn,
-                 (LVM_FLOAT)LVREV_HEADROOM,
-                 pTemp,
-                 (LVM_INT16)NumSamples);
-
-    /*
-     *  High pass filter
-     */
-    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs,
-                               pTemp,
-                               pTemp,
-                               (LVM_INT16)NumSamples);
-    /*
-     *  Low pass filter
-     */
-    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs,
-                               pTemp,
-                               pTemp,
-                               (LVM_INT16)NumSamples);
-
-    /*
-     *  Process all delay lines
-     */
-
-    for(j = 0; j < NumberOfDelayLines; j++)
-    {
-        pDelayLine = pPrivate->pScratchDelayLine[j];
-
-        /*
-         * All-pass filter with pop and click suppression
-         */
-        /* Get the smoothed, delayed output. Put it in the output buffer */
-        MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
-                               pPrivate->pOffsetA[j],
-                               pPrivate->pOffsetB[j],
-                               pDelayLine,
-                               (LVM_INT16)NumSamples);
-        /* Re-align the all pass filter delay buffer and copying the fixed delay data \
-           to the AP delay in the process */
-        Copy_Float(&pPrivate->pDelay_T[j][NumSamples],
-                   pPrivate->pDelay_T[j],
-                   (LVM_INT16)(pPrivate->T[j] - NumSamples));         /* 32-bit data */
-        /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
-        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
-                               pDelayLine,
-                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
-                               (LVM_INT16)NumSamples);
-        /* Sum into the AP delay line */
-        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
-                        -1.0f,    /* Invert since the feedback coefficient is negative */
-                        &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
-                        (LVM_INT16)NumSamples);
-        /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
-        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
-                               &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
-                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
-                               (LVM_INT16)NumSamples);
-        /* Sum into the AP output */
-        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
-                        1.0f,
-                        pDelayLine,
-                        (LVM_INT16)NumSamples);
-
-        /*
-         *  Feedback gain
-         */
-        MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
-
-        /*
-         *  Low pass filter
-         */
-        FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j],
-                                   pDelayLine,
-                                   pDelayLine,
-                                   (LVM_INT16)NumSamples);
-    }
-
-    /*
-     *  Apply rotation matrix and delay samples
-     */
-    for(j = 0; j < NumberOfDelayLines; j++)
-    {
-
-        Copy_Float(pTemp,
-                   pDelayLineInput,
-                   (LVM_INT16)(NumSamples));
-        /*
-         *  Rotation matrix mix
-         */
-        switch(j)
-        {
-            case 3:
-                /*
-                 *  Add delay line 1 and 2 contribution
-                 */
-                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
-                                 pDelayLineInput, (LVM_INT16)NumSamples);
-                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[2], -1.0f,
-                                 pDelayLineInput, (LVM_INT16)NumSamples);
-
-                break;
-            case 2:
-
-                /*
-                 *  Add delay line 0 and 3 contribution
-                 */
-                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
-                                 pDelayLineInput, (LVM_INT16)NumSamples);
-                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[3], -1.0f,
-                                 pDelayLineInput, (LVM_INT16)NumSamples);
-
-                break;
-            case 1:
-                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-                {
-                    /*
-                     *  Add delay line 0 and 3 contribution
-                     */
-                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
-                                    pDelayLineInput, (LVM_INT16)NumSamples);
-                    Add2_Sat_Float(pPrivate->pScratchDelayLine[3], pDelayLineInput,
-                                   (LVM_INT16)NumSamples);
-
-                }
-                else
-                {
-                    /*
-                     *  Add delay line 0 and 1 contribution
-                     */
-                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
-                                     pDelayLineInput, (LVM_INT16)NumSamples);
-                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
-                                     pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                break;
-            case 0:
-                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
-                {
-                    /*
-                     *  Add delay line 1 and 2 contribution
-                     */
-                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
-                                    pDelayLineInput, (LVM_INT16)NumSamples);
-                    Add2_Sat_Float(pPrivate->pScratchDelayLine[2], pDelayLineInput,
-                                   (LVM_INT16)NumSamples);
-
-                }
-                else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
-                {
-                    /*
-                     *  Add delay line 0 and 1 contribution
-                     */
-                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
-                                   (LVM_INT16)NumSamples);
-                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
-                                    pDelayLineInput, (LVM_INT16)NumSamples);
-
-                }
-                else
-                {
-                    /*
-                     *  Add delay line 0 contribution
-                     */
-
-                    /*             SOURCE                          DESTINATION*/
-                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
-                                   (LVM_INT16)NumSamples);
-                }
-                break;
-            default:
-                break;
-        }
-
-        /*
-         *  Delay samples
-         */
-        Copy_Float(pDelayLineInput,
-                   &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
-                   (LVM_INT16)(NumSamples));              /* 32-bit data */
-    }
-
-
-    /*
-     *  Create stereo output
-     */
-    switch(pPrivate->InstanceParams.NumDelays)
-    {
-        case LVREV_DELAYLINES_4:
-             Add2_Sat_Float(pPrivate->pScratchDelayLine[3],
-                            pPrivate->pScratchDelayLine[0],
-                            (LVM_INT16)NumSamples);
-             Add2_Sat_Float(pPrivate->pScratchDelayLine[2],
-                            pPrivate->pScratchDelayLine[1],
-                            (LVM_INT16)NumSamples);
-
-
-            JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
-                           pPrivate->pScratchDelayLine[1],
-                           pTemp,
-                           (LVM_INT16)NumSamples);
-
-
-            break;
-        case LVREV_DELAYLINES_2:
-
-             Copy_Float(pPrivate->pScratchDelayLine[1],
-                        pScratch,
-                        (LVM_INT16)(NumSamples));
-
-             Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0],
-                            -1.0f,
-                            pScratch,
-                            (LVM_INT16)NumSamples);
-
-             Add2_Sat_Float(pPrivate->pScratchDelayLine[1],
-                            pPrivate->pScratchDelayLine[0],
-                            (LVM_INT16)NumSamples);
-
-
-             JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
-                            pScratch,
-                            pTemp,
-                            (LVM_INT16)NumSamples);
-            break;
-        case LVREV_DELAYLINES_1:
-            MonoTo2I_Float(pPrivate->pScratchDelayLine[0],
-                           pTemp,
-                           (LVM_INT16)NumSamples);
-            break;
-        default:
-            break;
-    }
-
-
-    /*
-     *  Dry/wet mixer
-     */
-
-    size = (LVM_INT16)(NumSamples << 1);
-    MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
-                           pTemp,
-                           pTemp,
-                           pOutput,
-                           size);
-
-    /* Apply Gain*/
-
-    Shift_Sat_Float(LVREV_OUTPUTGAIN_SHIFT,
-                    pOutput,
-                    pOutput,
-                    size);
-
-    MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
-                           pOutput,
-                           pOutput,
-                           size);
-
-    return;
-}
-#endif
-/* End of file */
-
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
new file mode 100644
index 0000000..35f9ad8
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Includes                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_Process                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LVREV module.                                              */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
+/*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The input and output buffers must be 32-bit aligned                              */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t      hInstance,
+                                    const LVM_FLOAT     *pInData,
+                                    LVM_FLOAT           *pOutData,
+                                    const LVM_UINT16    NumSamples)
+{
+   LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+   LVM_FLOAT             *pInput  = (LVM_FLOAT *)pInData;
+   LVM_FLOAT             *pOutput = pOutData;
+   LVM_INT32             SamplesToProcess, RemainingSamples;
+   LVM_INT32             format = 1;
+
+    /*
+     * Check for error conditions
+     */
+
+    /* Check for NULL pointers */
+    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    /*
+     * Apply the new controls settings if required
+     */
+    if(pLVREV_Private->bControlPending == LVM_TRUE)
+    {
+        LVREV_ReturnStatus_en   errorCode;
+
+        /*
+         * Clear the pending flag and update the control settings
+         */
+        pLVREV_Private->bControlPending = LVM_FALSE;
+
+        errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
+
+        if(errorCode != LVREV_SUCCESS)
+        {
+            return errorCode;
+        }
+    }
+
+    /*
+     * Trap the case where the number of samples is zero.
+     */
+    if (NumSamples == 0)
+    {
+        return LVREV_SUCCESS;
+    }
+
+    /*
+     * If OFF copy and reformat the data as necessary
+     */
+    if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+    {
+        if(pInput != pOutput)
+        {
+            /*
+             * Copy the data to the output buffer, convert to stereo is required
+             */
+            if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
+                MonoTo2I_Float(pInput, pOutput, NumSamples);
+            } else {
+                Copy_Float(pInput,
+                           pOutput,
+                           (LVM_INT16)(NumSamples << 1)); // 32 bit data, stereo
+            }
+        }
+
+        return LVREV_SUCCESS;
+    }
+
+    RemainingSamples = (LVM_INT32)NumSamples;
+
+    if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+    {
+        format = 2;
+    }
+
+    while (RemainingSamples!=0)
+    {
+        /*
+         * Process the data
+         */
+
+        if(RemainingSamples >  pLVREV_Private->MaxBlkLen)
+        {
+            SamplesToProcess =  pLVREV_Private->MaxBlkLen;
+            RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
+        }
+        else
+        {
+            SamplesToProcess = RemainingSamples;
+            RemainingSamples = 0;
+        }
+
+        ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
+        pInput  = (LVM_FLOAT *)(pInput + (SamplesToProcess * format));
+        pOutput = (LVM_FLOAT *)(pOutput + (SamplesToProcess * 2));      // Always stereo output
+    }
+
+    return LVREV_SUCCESS;
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                ReverbBlock                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LVREV module.                                              */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVREV_Success           Succeeded                                                   */
+/*  LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size           */
+/*  LVREV_NULLADDRESS       When one of hInstance, pInData or pOutData is NULL          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The input and output buffers must be 32-bit aligned                              */
+/*                                                                                      */
+/****************************************************************************************/
+void ReverbBlock(LVM_FLOAT *pInput, LVM_FLOAT *pOutput,
+                 LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
+{
+    LVM_INT16   j, size;
+    LVM_FLOAT   *pDelayLine;
+    LVM_FLOAT   *pDelayLineInput = pPrivate->pScratch;
+    LVM_FLOAT   *pScratch = pPrivate->pScratch;
+    LVM_FLOAT   *pIn;
+    LVM_FLOAT   *pTemp = pPrivate->pInputSave;
+    LVM_INT32   NumberOfDelayLines;
+
+    /******************************************************************************
+     * All calculations will go into the buffer pointed to by pTemp, this will    *
+     * then be mixed with the original input to create the final output.          *
+     *                                                                            *
+     * When INPLACE processing is selected this must be a temporary buffer and    *
+     * hence this is the worst case, so for simplicity this will ALWAYS be so     *
+     *                                                                            *
+     * The input buffer will remain untouched until the output of the mixer if    *
+     * INPLACE processing is selected.                                            *
+     *                                                                            *
+     * The temp buffer will always be NumSamples in size regardless of MONO or    *
+     * STEREO input. In the case of stereo input all processing is done in MONO   *
+     * and the final output is converted to STEREO after the mixer                *
+     ******************************************************************************/
+
+    if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+    {
+        NumberOfDelayLines = 4;
+    }
+    else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+    {
+        NumberOfDelayLines = 2;
+    }
+    else
+    {
+        NumberOfDelayLines = 1;
+    }
+
+    if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
+    {
+        pIn = pInput;
+    }
+    else
+    {
+        /*
+         *  Stereo to mono conversion
+         */
+
+        From2iToMono_Float(pInput,
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+        pIn = pTemp;
+    }
+
+    Mult3s_Float(pIn,
+                 (LVM_FLOAT)LVREV_HEADROOM,
+                 pTemp,
+                 (LVM_INT16)NumSamples);
+
+    /*
+     *  High pass filter
+     */
+    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs,
+                               pTemp,
+                               pTemp,
+                               (LVM_INT16)NumSamples);
+    /*
+     *  Low pass filter
+     */
+    FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs,
+                               pTemp,
+                               pTemp,
+                               (LVM_INT16)NumSamples);
+
+    /*
+     *  Process all delay lines
+     */
+
+    for(j = 0; j < NumberOfDelayLines; j++)
+    {
+        pDelayLine = pPrivate->pScratchDelayLine[j];
+
+        /*
+         * All-pass filter with pop and click suppression
+         */
+        /* Get the smoothed, delayed output. Put it in the output buffer */
+        MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
+                               pPrivate->pOffsetA[j],
+                               pPrivate->pOffsetB[j],
+                               pDelayLine,
+                               (LVM_INT16)NumSamples);
+        /* Re-align the all pass filter delay buffer and copying the fixed delay data \
+           to the AP delay in the process */
+        Copy_Float(&pPrivate->pDelay_T[j][NumSamples],
+                   pPrivate->pDelay_T[j],
+                   (LVM_INT16)(pPrivate->T[j] - NumSamples));         /* 32-bit data */
+        /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
+        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
+                               pDelayLine,
+                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                               (LVM_INT16)NumSamples);
+        /* Sum into the AP delay line */
+        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                        -1.0f,    /* Invert since the feedback coefficient is negative */
+                        &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
+                        (LVM_INT16)NumSamples);
+        /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
+        MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
+                               &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j] - NumSamples],
+                               &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                               (LVM_INT16)NumSamples);
+        /* Sum into the AP output */
+        Mac3s_Sat_Float(&pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                        1.0f,
+                        pDelayLine,
+                        (LVM_INT16)NumSamples);
+
+        /*
+         *  Feedback gain
+         */
+        MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
+
+        /*
+         *  Low pass filter
+         */
+        FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j],
+                                   pDelayLine,
+                                   pDelayLine,
+                                   (LVM_INT16)NumSamples);
+    }
+
+    /*
+     *  Apply rotation matrix and delay samples
+     */
+    for(j = 0; j < NumberOfDelayLines; j++)
+    {
+
+        Copy_Float(pTemp,
+                   pDelayLineInput,
+                   (LVM_INT16)(NumSamples));
+        /*
+         *  Rotation matrix mix
+         */
+        switch(j)
+        {
+            case 3:
+                /*
+                 *  Add delay line 1 and 2 contribution
+                 */
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[2], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+
+                break;
+            case 2:
+
+                /*
+                 *  Add delay line 0 and 3 contribution
+                 */
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+                 Mac3s_Sat_Float(pPrivate->pScratchDelayLine[3], -1.0f,
+                                 pDelayLineInput, (LVM_INT16)NumSamples);
+
+                break;
+            case 1:
+                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+                {
+                    /*
+                     *  Add delay line 0 and 3 contribution
+                     */
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[3], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+
+                }
+                else
+                {
+                    /*
+                     *  Add delay line 0 and 1 contribution
+                     */
+                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0], -1.0f,
+                                     pDelayLineInput, (LVM_INT16)NumSamples);
+                     Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                     pDelayLineInput, (LVM_INT16)NumSamples);
+
+                }
+                break;
+            case 0:
+                if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+                {
+                    /*
+                     *  Add delay line 1 and 2 contribution
+                     */
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[2], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+
+                }
+                else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+                {
+                    /*
+                     *  Add delay line 0 and 1 contribution
+                     */
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+                    Mac3s_Sat_Float(pPrivate->pScratchDelayLine[1], -1.0f,
+                                    pDelayLineInput, (LVM_INT16)NumSamples);
+
+                }
+                else
+                {
+                    /*
+                     *  Add delay line 0 contribution
+                     */
+
+                    /*             SOURCE                          DESTINATION*/
+                    Add2_Sat_Float(pPrivate->pScratchDelayLine[0], pDelayLineInput,
+                                   (LVM_INT16)NumSamples);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /*
+         *  Delay samples
+         */
+        Copy_Float(pDelayLineInput,
+                   &pPrivate->pDelay_T[j][pPrivate->T[j] - NumSamples],
+                   (LVM_INT16)(NumSamples));              /* 32-bit data */
+    }
+
+    /*
+     *  Create stereo output
+     */
+    switch(pPrivate->InstanceParams.NumDelays)
+    {
+        case LVREV_DELAYLINES_4:
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[3],
+                            pPrivate->pScratchDelayLine[0],
+                            (LVM_INT16)NumSamples);
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[2],
+                            pPrivate->pScratchDelayLine[1],
+                            (LVM_INT16)NumSamples);
+
+            JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
+                           pPrivate->pScratchDelayLine[1],
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+
+            break;
+        case LVREV_DELAYLINES_2:
+
+             Copy_Float(pPrivate->pScratchDelayLine[1],
+                        pScratch,
+                        (LVM_INT16)(NumSamples));
+
+             Mac3s_Sat_Float(pPrivate->pScratchDelayLine[0],
+                            -1.0f,
+                            pScratch,
+                            (LVM_INT16)NumSamples);
+
+             Add2_Sat_Float(pPrivate->pScratchDelayLine[1],
+                            pPrivate->pScratchDelayLine[0],
+                            (LVM_INT16)NumSamples);
+
+             JoinTo2i_Float(pPrivate->pScratchDelayLine[0],
+                            pScratch,
+                            pTemp,
+                            (LVM_INT16)NumSamples);
+            break;
+        case LVREV_DELAYLINES_1:
+            MonoTo2I_Float(pPrivate->pScratchDelayLine[0],
+                           pTemp,
+                           (LVM_INT16)NumSamples);
+            break;
+        default:
+            break;
+    }
+
+    /*
+     *  Dry/wet mixer
+     */
+
+    size = (LVM_INT16)(NumSamples << 1);
+    MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
+                           pTemp,
+                           pTemp,
+                           pOutput,
+                           size);
+
+    /* Apply Gain*/
+
+    Shift_Sat_Float(LVREV_OUTPUTGAIN_SHIFT,
+                    pOutput,
+                    pOutput,
+                    size);
+
+    MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
+                           pOutput,
+                           pOutput,
+                           size);
+
+    return;
+}
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
deleted file mode 100644
index dfed28e..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV_Private.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVREV_SetControlParameters                                  */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Sets or changes the LVREV module parameters.                                        */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance handle                                             */
-/*  pNewParams              Pointer to a parameter structure                            */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVM_Success             Succeeded                                                   */
-/*  LVREV_NULLADDRESS       When hInstance or pNewParams is NULL                        */
-/*  LVREV_OUTOFRANGE        When any of the new parameters is out of range              */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVREV_Process function                  */
-/*                                                                                      */
-/****************************************************************************************/
-LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t           hInstance,
-                                                 LVREV_ControlParams_st   *pNewParams)
-{
-
-    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
-
-
-    /*
-     * Check for error conditions
-     */
-    if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
-    {
-        return LVREV_NULLADDRESS;
-    }
-
-    /*
-     * Check all new control parameters are in range
-     */
-    if(    ((pNewParams->OperatingMode != LVM_MODE_OFF) && (pNewParams->OperatingMode != LVM_MODE_ON))                                         ||
-        (
-        (pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000)       &&
-        (pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000)       &&
-        (pNewParams->SampleRate != LVM_FS_32000) &&
-        (pNewParams->SampleRate != LVM_FS_44100) &&
-        (pNewParams->SampleRate != LVM_FS_48000)
-#ifdef HIGHER_FS
-        && (pNewParams->SampleRate != LVM_FS_88200) && (pNewParams->SampleRate != LVM_FS_96000)
-        && (pNewParams->SampleRate != LVM_FS_176400) && (pNewParams->SampleRate != LVM_FS_192000)
-#endif
-        )
-#ifdef SUPPORT_MC
-        || ((pNewParams->SourceFormat != LVM_STEREO)       &&
-            (pNewParams->SourceFormat != LVM_MONOINSTEREO) &&
-            (pNewParams->SourceFormat != LVM_MONO)         &&
-            (pNewParams->SourceFormat != LVM_MULTICHANNEL)))
-#else
-        || ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
-#endif
-    {
-        return (LVREV_OUTOFRANGE);
-    }
-
-
-    if (pNewParams->Level > LVREV_MAX_LEVEL)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if ((pNewParams->LPF < LVREV_MIN_LPF_CORNER) || (pNewParams->LPF > LVREV_MAX_LPF_CORNER))
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if ((pNewParams->HPF < LVREV_MIN_HPF_CORNER) || (pNewParams->HPF > LVREV_MAX_HPF_CORNER))
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if (pNewParams->T60 > LVREV_MAX_T60)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if (pNewParams->Density > LVREV_MAX_DENSITY)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if (pNewParams->Damping > LVREV_MAX_DAMPING)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-    if (pNewParams->RoomSize > LVREV_MAX_ROOMSIZE)
-    {
-        return LVREV_OUTOFRANGE;
-    }
-
-
-
-    /*
-     * Copy the new parameters and set the flag to indicate they are available
-     */
-    pLVREV_Private->NewParams       = *pNewParams;
-    pLVREV_Private->bControlPending = LVM_TRUE;
-
-    return LVREV_SUCCESS;
-}
-
-/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.cpp
new file mode 100644
index 0000000..2a75559
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVREV_SetControlParameters                                  */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LVREV module parameters.                                        */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pNewParams              Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_Success             Succeeded                                                   */
+/*  LVREV_NULLADDRESS       When hInstance or pNewParams is NULL                        */
+/*  LVREV_OUTOFRANGE        When any of the new parameters is out of range              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVREV_Process function                  */
+/*                                                                                      */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t           hInstance,
+                                                 LVREV_ControlParams_st   *pNewParams)
+{
+
+    LVREV_Instance_st     *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+    /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+    {
+        return LVREV_NULLADDRESS;
+    }
+
+    /*
+     * Check all new control parameters are in range
+     */
+    if(    ((pNewParams->OperatingMode != LVM_MODE_OFF) && (pNewParams->OperatingMode != LVM_MODE_ON))                                         ||
+        (
+        (pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000)       &&
+        (pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000)       &&
+        (pNewParams->SampleRate != LVM_FS_32000) &&
+        (pNewParams->SampleRate != LVM_FS_44100) &&
+        (pNewParams->SampleRate != LVM_FS_48000)
+        && (pNewParams->SampleRate != LVM_FS_88200) && (pNewParams->SampleRate != LVM_FS_96000)
+        && (pNewParams->SampleRate != LVM_FS_176400) && (pNewParams->SampleRate != LVM_FS_192000)
+        )
+#ifdef SUPPORT_MC
+        || ((pNewParams->SourceFormat != LVM_STEREO)       &&
+            (pNewParams->SourceFormat != LVM_MONOINSTEREO) &&
+            (pNewParams->SourceFormat != LVM_MONO)         &&
+            (pNewParams->SourceFormat != LVM_MULTICHANNEL)))
+#else
+        || ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
+#endif
+    {
+        return (LVREV_OUTOFRANGE);
+    }
+
+    if (pNewParams->Level > LVREV_MAX_LEVEL)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if ((pNewParams->LPF < LVREV_MIN_LPF_CORNER) || (pNewParams->LPF > LVREV_MAX_LPF_CORNER))
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if ((pNewParams->HPF < LVREV_MIN_HPF_CORNER) || (pNewParams->HPF > LVREV_MAX_HPF_CORNER))
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if (pNewParams->T60 > LVREV_MAX_T60)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if (pNewParams->Density > LVREV_MAX_DENSITY)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if (pNewParams->Damping > LVREV_MAX_DAMPING)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    if (pNewParams->RoomSize > LVREV_MAX_ROOMSIZE)
+    {
+        return LVREV_OUTOFRANGE;
+    }
+
+    /*
+     * Copy the new parameters and set the flag to indicate they are available
+     */
+    pLVREV_Private->NewParams       = *pNewParams;
+    pLVREV_Private->bControlPending = LVM_TRUE;
+
+    return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
deleted file mode 100644
index 1058740..0000000
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Includes                                                                            */
-/*                                                                                      */
-/****************************************************************************************/
-#include "LVREV.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Tables                                                                              */
-/*                                                                                      */
-/****************************************************************************************/
-
-/* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
-#ifndef HIGHER_FS
-const LVM_UINT16 LVM_FsTable[] = {
-    8000 ,
-    11025,
-    12000,
-    16000,
-    22050,
-    24000,
-    32000,
-    44100,
-    48000
-};
-#else
-const LVM_UINT32 LVM_FsTable[] = {
-    8000 ,
-    11025,
-    12000,
-    16000,
-    22050,
-    24000,
-    32000,
-    44100,
-    48000,
-    88200,
-    96000,
-    176400,
-    192000
-};
-#endif
-/* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
-#ifndef HIGHER_FS
-LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
-    if (FsIndex > LVM_FS_48000)
-        return 0;
-
-    return (LVM_FsTable[FsIndex]);
-}
-#else
-LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
-    if (FsIndex > LVM_FS_192000)
-        return 0;
-
-    return (LVM_FsTable[FsIndex]);
-}
-#endif
-
-/* In order to maintain consistant input and out put signal strengths
-   output gain/attenuation is applied. This gain depends on T60 and Rooms
-   size parameters. These polynomial coefficients are calculated experimentally.
-   First value in the table is room size
-   second value is  A0
-   third value is   A1
-   fourth value is  A2
-   fifth value is   A3
-   sixth value is   A4
-
-     shift value  is to be added array (to use LVM_Polynomial function)
-
-  The gain is calculated using variable x=(T60*32767/7000)*32768;
-
-   first values is used to get polynomial set for given room size,
-   For room sizes which are not in the table, linear interpolation can be used.
-
-  */
-
-/* Normalizing output including Reverb Level part (only shift up)*/
-#ifndef BUILD_FLOAT
-const LVM_INT32 LVREV_GainPolyTable[24][5]={{1,17547434,128867434,-120988896,50761228,},
-                                            {2,18256869,172666902,-193169292,88345744,},
-                                            {3,16591311,139250151,-149667234,66770059,},
-                                            {4,17379977,170835131,-173579321,76278163,},
-                                            {5,18963512,210364934,-228623519,103435022,},
-                                            {6,17796318,135756417,-144084053,64327698,},
-                                            {7,17454695,174593214,-187513064,85146582,},
-                                            {8,17229257,140715570,-145790588,65361740,},
-                                            {9,17000547,163195946,-176733969,79562130,},
-                                            {10,16711699,142476304,-133339887,58366547,},
-                                            {13,18108419,149223697,-161762020,74397589,},
-                                            {15,16682043,124844884,-134284487,60082180,},
-                                            {17,16627346,120936430,-121766674,53146421,},
-                                            {20,17338325,125432694,-126616983,56534237,},
-                                            {25,16489146,99218217,-94597467,40616506,},
-                                            {30,15582373,84479043,-75365006,30952348,},
-                                            {40,16000669,84896611,-75031127,30696306,},
-                                            {50,15087054,71695031,-59349268,23279669,},
-                                            {60,15830714,68672971,-58211201,23671158,},
-                                            {70,15536061,66657972,-55901437,22560153,},
-                                            {75,15013145,48179917,-24138354,5232074,},
-                                            {80,15688738,50195036,-34206760,11515792,},
-                                            {90,16003322,48323661,-35607378,13153872,},
-                                            {100,15955223,48558201,-33706865,11715792,},
-                                            };
-#else
-const LVM_FLOAT LVREV_GainPolyTable[24][5]={{1,1.045909f,7.681098f,-7.211500f,3.025605f,},
-                                            {2,1.088194f,10.291749f,-11.513787f,5.265817f,},
-                                            {3,0.988919f,8.299956f,-8.920862f,3.979806f,},
-                                            {4,1.035927f,10.182567f,-10.346134f,4.546533f,},
-                                            {5,1.130313f,12.538727f,-13.627023f,6.165208f,},
-                                            {6,1.060743f,8.091713f,-8.588079f,3.834230f,},
-                                            {7,1.040381f,10.406566f,-11.176650f,5.075132f,},
-                                            {8,1.026944f,8.387302f,-8.689796f,3.895863f,},
-                                            {9,1.013312f,9.727236f,-10.534165f,4.742272f,},
-                                            {10,0.996095f,8.492249f,-7.947677f,3.478917f,},
-                                            {13,1.079346f,8.894425f,-9.641768f,4.434442f,},
-                                            {15,0.994327f,7.441335f,-8.003979f,3.581177f,},
-                                            {17,0.991067f,7.208373f,-7.257859f,3.167774f,},
-                                            {20,1.033445f,7.476371f,-7.546960f,3.369703f,},
-                                            {25,0.982830f,5.913867f,-5.638448f,2.420932f,},
-                                            {30,0.928782f,5.035343f,-4.492104f,1.844904f,},
-                                            {40,0.953714f,5.060232f,-4.472204f,1.829642f,},
-                                            {50,0.899258f,4.273357f,-3.537492f,1.387576f,},
-                                            {60,0.943584f,4.093228f,-3.469658f,1.410911f,},
-                                            {70,0.926021f,3.973125f,-3.331985f,1.344690f,},
-                                            {75,0.894853f,2.871747f,-1.438758f,0.311856f,},
-                                            {80,0.935122f,2.991857f,-2.038882f,0.686395f,},
-                                            {90,0.953872f,2.880315f,-2.122365f,0.784032f,},
-                                            {100,0.951005f,2.894294f,-2.009086f,0.698316f,},
-};
-#endif
-/* End of file */
-
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
new file mode 100644
index 0000000..5cd623e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVREV.h"
+#include "LVREV_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Tables                                                                              */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
+const LVM_UINT32 LVM_FsTable[] = {
+    8000 ,
+    11025,
+    12000,
+    16000,
+    22050,
+    24000,
+    32000,
+    44100,
+    48000,
+    88200,
+    96000,
+    176400,
+    192000
+};
+/* Table with supported sampling rates.  The table can be indexed using LVM_Fs_en       */
+LVM_UINT32 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
+    if (FsIndex > LVM_FS_192000)
+        return 0;
+
+    return (LVM_FsTable[FsIndex]);
+}
+
+/* In order to maintain consistant input and out put signal strengths
+   output gain/attenuation is applied. This gain depends on T60 and Rooms
+   size parameters. These polynomial coefficients are calculated experimentally.
+   First value in the table is room size
+   second value is  A0
+   third value is   A1
+   fourth value is  A2
+   fifth value is   A3
+   sixth value is   A4
+
+     shift value  is to be added array (to use LVM_Polynomial function)
+
+  The gain is calculated using variable x=(T60*32767/7000)*32768;
+
+   first values is used to get polynomial set for given room size,
+   For room sizes which are not in the table, linear interpolation can be used.
+
+  */
+
+/* Normalizing output including Reverb Level part (only shift up)*/
+const LVM_FLOAT LVREV_GainPolyTable[24][5]={{1,1.045909f,7.681098f,-7.211500f,3.025605f,},
+                                            {2,1.088194f,10.291749f,-11.513787f,5.265817f,},
+                                            {3,0.988919f,8.299956f,-8.920862f,3.979806f,},
+                                            {4,1.035927f,10.182567f,-10.346134f,4.546533f,},
+                                            {5,1.130313f,12.538727f,-13.627023f,6.165208f,},
+                                            {6,1.060743f,8.091713f,-8.588079f,3.834230f,},
+                                            {7,1.040381f,10.406566f,-11.176650f,5.075132f,},
+                                            {8,1.026944f,8.387302f,-8.689796f,3.895863f,},
+                                            {9,1.013312f,9.727236f,-10.534165f,4.742272f,},
+                                            {10,0.996095f,8.492249f,-7.947677f,3.478917f,},
+                                            {13,1.079346f,8.894425f,-9.641768f,4.434442f,},
+                                            {15,0.994327f,7.441335f,-8.003979f,3.581177f,},
+                                            {17,0.991067f,7.208373f,-7.257859f,3.167774f,},
+                                            {20,1.033445f,7.476371f,-7.546960f,3.369703f,},
+                                            {25,0.982830f,5.913867f,-5.638448f,2.420932f,},
+                                            {30,0.928782f,5.035343f,-4.492104f,1.844904f,},
+                                            {40,0.953714f,5.060232f,-4.472204f,1.829642f,},
+                                            {50,0.899258f,4.273357f,-3.537492f,1.387576f,},
+                                            {60,0.943584f,4.093228f,-3.469658f,1.410911f,},
+                                            {70,0.926021f,3.973125f,-3.331985f,1.344690f,},
+                                            {75,0.894853f,2.871747f,-1.438758f,0.311856f,},
+                                            {80,0.935122f,2.991857f,-2.038882f,0.686395f,},
+                                            {90,0.953872f,2.880315f,-2.122365f,0.784032f,},
+                                            {100,0.951005f,2.894294f,-2.009086f,0.698316f,},
+};
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
index 0658186..e100d8a 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -15,15 +15,9 @@
  * limitations under the License.
  */
 
-
 #ifndef _LVREV_TABLES_H_
 #define _LVREV_TABLES_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -37,22 +31,10 @@
 /*                                                                                      */
 /****************************************************************************************/
 
-#ifndef HIGHER_FS
-extern const    LVM_UINT16  LVM_FsTable[];
-extern          LVM_UINT16  LVM_GetFsFromTable(LVM_Fs_en FsIndex);
-#else
 extern const    LVM_UINT32  LVM_FsTable[];
 extern          LVM_UINT32  LVM_GetFsFromTable(LVM_Fs_en FsIndex);
-#endif
 
-#ifndef BUILD_FLOAT
-extern          LVM_INT32   LVREV_GainPolyTable[24][5];
-#else
-extern          LVM_FLOAT   LVREV_GainPolyTable[24][5];
-#endif
-#ifdef __cplusplus
-}
-#endif
+extern const    LVM_FLOAT   LVREV_GainPolyTable[24][5];
 
 #endif  /** _LVREV_TABLES_H_ **/
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
index 2038fbb..c9fa7ad 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
@@ -18,14 +18,8 @@
 #ifndef _LVPSA_H_
 #define _LVPSA_H_
 
-
 #include "LVM_Types.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  CONSTANTS DEFINITIONS                                                               */
@@ -116,8 +110,6 @@
     LVPSA_RETURN_DUMMY = LVM_MAXINT_32                      /* Force 32 bits enum, don't use it!                                 */
 } LVPSA_RETURN;
 
-
-
 /*********************************************************************************************************************************
    FUNCTIONS PROTOTYPE
 **********************************************************************************************************************************/
@@ -216,17 +208,10 @@
 /*  otherwise           Error due to bad parameters                                                                              */
 /*                                                                                                                               */
 /*********************************************************************************************************************************/
-#ifdef BUILD_FLOAT
 LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
                                        LVM_FLOAT           *pLVPSA_InputSamples,
                                        LVM_UINT16           InputBlockSize,
                                        LVPSA_Time           AudioTime             );
-#else
-LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
-                                       LVM_INT16           *pLVPSA_InputSamples,
-                                       LVM_UINT16           InputBlockSize,
-                                       LVPSA_Time           AudioTime             );
-#endif
 /*********************************************************************************************************************************/
 /*                                                                                                                               */
 /* FUNCTION:            LVPSA_GetSpectrum                                                                                        */
@@ -288,9 +273,4 @@
 LVPSA_RETURN LVPSA_GetInitParams     (    pLVPSA_Handle_t            hInstance,
                                           LVPSA_InitParams_t        *pParams      );
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* _LVPSA_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
deleted file mode 100644
index f6c4ea7..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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    "LVPSA.h"
-#include    "LVPSA_Private.h"
-#include    "VectorArithmetic.h"
-
-#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
-#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
-
-LVPSA_RETURN LVPSA_SetBPFiltersType (  LVPSA_InstancePr_t        *pInst,
-                                       LVPSA_ControlParams_t      *pParams  );
-
-LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t        *pInst,
-                                       LVPSA_ControlParams_t      *pParams  );
-
-#ifdef BUILD_FLOAT
-LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
-                                       LVPSA_FilterParam_t   *pFilterParams,
-                                       BP_FLOAT_Coefs_t        *pCoefficients);
-
-LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16            Fs,
-                                       LVPSA_FilterParam_t  *pFilterParams,
-                                       BP_FLOAT_Coefs_t       *pCoefficients);
-#else
-LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
-                                       LVPSA_FilterParam_t   *pFilterParams,
-                                       BP_C16_Coefs_t        *pCoefficients);
-
-LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16            Fs,
-                                       LVPSA_FilterParam_t  *pFilterParams,
-                                       BP_C32_Coefs_t       *pCoefficients);
-
-LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16              Fs,
-                                       LVPSA_FilterParam_t     *pFilterParams,
-                                       BP_C32_Coefs_t          *pCoefficients);
-#endif
-LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t        *pInst,
-                                       LVPSA_ControlParams_t      *pParams  );
-
-LVPSA_RETURN LVPSA_ClearFilterHistory( LVPSA_InstancePr_t        *pInst);
-
-
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_Control                                               */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Give some new control parameters to the module.                                 */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance           Pointer to the instance                                     */
-/*  NewParams           Structure that contains the new parameters                  */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_Control           ( pLVPSA_Handle_t             hInstance,
-                                       LVPSA_ControlParams_t      *pNewParams     )
-{
-
-    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
-
-    if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-    if(pNewParams->Fs >= LVPSA_NR_SUPPORTED_RATE)
-    {
-        return(LVPSA_ERROR_INVALIDPARAM);
-    }
-    if(pNewParams->LevelDetectionSpeed >= LVPSA_NR_SUPPORTED_SPEED)
-    {
-        return(LVPSA_ERROR_INVALIDPARAM);
-    }
-
-    pLVPSA_Inst->NewParams = *pNewParams;
-    pLVPSA_Inst->bControlPending = LVM_TRUE;
-
-    return(LVPSA_OK);
-}
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_GetControlParams                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Get the current control parameters of the module                                */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance       Pointer to the instance                                         */
-/*  pParams         Pointer to an empty control structure                           */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_GetControlParams         (    pLVPSA_Handle_t            hInstance,
-                                                 LVPSA_ControlParams_t     *pParams )
-{
-    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
-
-    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-
-    pParams->Fs                     = pLVPSA_Inst->CurrentParams.Fs;
-    pParams->LevelDetectionSpeed    = pLVPSA_Inst->CurrentParams.LevelDetectionSpeed;
-
-    return(LVPSA_OK);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_GetInitParams                                         */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Get the initialization parameters of the module                                 */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance       Pointer to the instance                                         */
-/*  pParams         Pointer to an empty control structure                           */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_GetInitParams         (    pLVPSA_Handle_t            hInstance,
-                                              LVPSA_InitParams_t        *pParams )
-{
-    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
-
-    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-
-    pParams->SpectralDataBufferDuration   = pLVPSA_Inst->SpectralDataBufferDuration;
-    pParams->MaxInputBlockSize            = pLVPSA_Inst->MaxInputBlockSize;
-    pParams->nBands                       = pLVPSA_Inst->nBands;
-    pParams->pFiltersParams               = pLVPSA_Inst->pFiltersParams;
-
-    return(LVPSA_OK);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_ApplyNewSettings                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Reinitialize some parameters and changes filters' coefficients if               */
-/*  some control parameters have changed.                                           */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst               Pointer to the instance                                     */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t     *pInst)
-{
-    LVM_UINT16 ii;
-    LVM_UINT16 Freq;
-    LVPSA_ControlParams_t   Params;
-    extern LVM_INT16        LVPSA_nSamplesBufferUpdate[];
-#ifndef HIGHER_FS
-    extern LVM_UINT16       LVPSA_SampleRateTab[];
-#else
-    extern LVM_UINT32       LVPSA_SampleRateTab[];
-#endif
-    extern LVM_UINT16       LVPSA_DownSamplingFactor[];
-
-
-    if(pInst == 0)
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-
-    Params = pInst->NewParams;
-
-    /* Modifies filters types and coefficients, clear the taps and
-       re-initializes parameters if sample frequency has changed    */
-    if(Params.Fs != pInst->CurrentParams.Fs)
-    {
-        pInst->CurrentParams.Fs = Params.Fs;
-
-        /* Initialize the center freqeuncies as a function of the sample rate */
-        Freq = (LVM_UINT16) ((LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1) / (pInst->nBands + 1));
-        for(ii = pInst->nBands; ii > 0; ii--)
-        {
-            pInst->pFiltersParams[ii-1].CenterFrequency = (LVM_UINT16) (Freq * ii);
-        }
-
-        /* Count the number of relevant filters. If the center frequency of the filter is
-           bigger than the nyquist frequency, then the filter is not relevant and doesn't
-           need to be used */
-        for(ii = pInst->nBands; ii > 0; ii--)
-        {
-            if(pInst->pFiltersParams[ii-1].CenterFrequency < (LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1))
-            {
-                pInst->nRelevantFilters = ii;
-                break;
-            }
-        }
-        LVPSA_SetBPFiltersType(pInst, &Params);
-        LVPSA_SetBPFCoefficients(pInst, &Params);
-        LVPSA_SetQPFCoefficients(pInst, &Params);
-        LVPSA_ClearFilterHistory(pInst);
-        pInst->nSamplesBufferUpdate = (LVM_UINT16)LVPSA_nSamplesBufferUpdate[Params.Fs];
-        pInst->BufferUpdateSamplesCount = 0;
-        pInst->DownSamplingFactor = LVPSA_DownSamplingFactor[Params.Fs];
-        pInst->DownSamplingCount = 0;
-        for(ii = 0; ii < (pInst->nBands * pInst->SpectralDataBufferLength); ii++)
-        {
-            pInst->pSpectralDataBufferStart[ii] = 0;
-        }
-        for(ii = 0; ii < pInst->nBands; ii++)
-        {
-            pInst->pPreviousPeaks[ii] = 0;
-        }
-    }
-    else
-    {
-        if(Params.LevelDetectionSpeed != pInst->CurrentParams.LevelDetectionSpeed)
-        {
-            LVPSA_SetQPFCoefficients(pInst, &Params);
-        }
-    }
-
-    pInst->CurrentParams = pInst->NewParams;
-
-    return (LVPSA_OK);
-}
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_SetBPFiltersType                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the filter type based on the BPFilterType.                                 */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst               Pointer to the instance                                     */
-/*  pParams             Poniter to conrol parameters                                */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Always succeeds                                             */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1. To select the biquad type the follow rules are applied:                      */
-/*          Double precision    if (fc <= fs/110)                                   */
-/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
-/*          Single precision    otherwise                                           */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_SetBPFiltersType (   LVPSA_InstancePr_t        *pInst,
-                                        LVPSA_ControlParams_t      *pParams  )
-{
-#ifndef HIGHER_FS
-    extern LVM_UINT16   LVPSA_SampleRateTab[];                                            /* Sample rate table */
-#else
-    extern LVM_UINT32   LVPSA_SampleRateTab[];                 /* Sample rate table */
-#endif
-    LVM_UINT16          ii;                                                         /* Filter band index */
-    LVM_UINT32          fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs];      /* Sample rate */
-    LVM_UINT32          fc;                                                         /* Filter centre frequency */
-    LVM_INT16           QFactor;                                                    /* Filter Q factor */
-
-    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
-    {
-        /*
-         * Get the filter settings
-         */
-        fc = (LVM_UINT32)pInst->pFiltersParams[ii].CenterFrequency;     /* Get the band centre frequency */
-        QFactor =(LVM_INT16) pInst->pFiltersParams[ii].QFactor;                    /* Get the band Q factor */
-
-
-        /*
-         * For each filter set the type of biquad required
-         */
-        pInst->pBPFiltersPrecision[ii] = LVPSA_SimplePrecisionFilter;     /* Default to single precision */
-        if ((LOW_FREQ * fs) >= (fc << 15))
-        {
-            /*
-             * fc <= fs/110
-             */
-            pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
-        }
-        else
-        {
-            if (((LOW_FREQ * fs) < (fc << 15)) && ((fc << 15) < (HIGH_FREQ * fs)) && (QFactor > 300))
-            {
-                /*
-                * (fs/110 < fc < fs/85) & (Q>3)
-                */
-                pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
-            }
-        }
-    }
-
-    return(LVPSA_OK);
-}
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_SetBPFCoefficients                                    */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the band pass filter coefficients. This uses the type to select            */
-/*  single or double precision coefficients.                                        */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst               Pointer to the instance                                     */
-/*  Params              Initialisation parameters                                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Always succeeds                                             */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_SetBPFCoefficients(  LVPSA_InstancePr_t        *pInst,
-                                        LVPSA_ControlParams_t      *pParams)
-{
-
-    LVM_UINT16                      ii;
-
-    /*
-     * Set the coefficients for each band by the init function
-     */
-    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
-    {
-        switch  (pInst->pBPFiltersPrecision[ii])
-        {
-            case    LVPSA_DoublePrecisionFilter:
-            {
-#ifndef BUILD_FLOAT
-                BP_C32_Coefs_t      Coefficients;
-
-                /*
-                 * Calculate the double precision coefficients
-                 */
-                LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
-                                        &pInst->pFiltersParams[ii],
-                                        &Coefficients);
-                /*
-                 * Set the coefficients
-                 */
-                BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
-                                                  &pInst->pBP_Taps[ii],
-                                                  &Coefficients);
-#else
-                BP_FLOAT_Coefs_t      Coefficients;
-                /*
-                 * Calculate the double precision coefficients
-                 */
-                LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
-                                        &pInst->pFiltersParams[ii],
-                                        &Coefficients);
-                /*
-                 * Set the coefficients
-                 */
-                BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
-                                                  &pInst->pBP_Taps[ii],
-                                                  &Coefficients);
-#endif
-                break;
-            }
-
-            case    LVPSA_SimplePrecisionFilter:
-            {
-#ifndef BUILD_FLOAT
-                BP_C16_Coefs_t      Coefficients;
-
-                /*
-                 * Calculate the single precision coefficients
-                 */
-                LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
-                                       &pInst->pFiltersParams[ii],
-                                       &Coefficients);
-
-                /*
-                 * Set the coefficients
-                 */
-                BP_1I_D16F16Css_TRC_WRA_01_Init (&pInst->pBP_Instances[ii],
-                                                  &pInst->pBP_Taps[ii],
-                                                  &Coefficients);
-#else
-                BP_FLOAT_Coefs_t      Coefficients;
-
-                /*
-                 * Calculate the single precision coefficients
-                 */
-                LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
-                                        &pInst->pFiltersParams[ii],
-                                        &Coefficients);
-
-                /*
-                 * Set the coefficients
-                 */
-                BP_1I_D16F16Css_TRC_WRA_01_Init (&pInst->pBP_Instances[ii],
-                                                  &pInst->pBP_Taps[ii],
-                                                  &Coefficients);
-#endif
-                break;
-            }
-        }
-    }
-
-    return(LVPSA_OK);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_SetQPFCoefficients                                    */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets the quasi peak filters coefficients. This uses the chosen                  */
-/*  LevelDetectionSpeed from the control parameters.                                */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst               Pointer to the instance                                     */
-/*  Params              Control parameters                                          */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Always succeeds                                             */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_SetQPFCoefficients(   LVPSA_InstancePr_t        *pInst,
-                                         LVPSA_ControlParams_t      *pParams  )
-{
-    LVM_UINT16     ii;
-    LVM_Fs_en      Fs = pParams->Fs;
-#ifndef BUILD_FLOAT
-    QPD_C32_Coefs  *pCoefficients;
-    extern         QPD_C32_Coefs     LVPSA_QPD_Coefs[];
-
-    pCoefficients = &LVPSA_QPD_Coefs[(pParams->LevelDetectionSpeed * LVPSA_NR_SUPPORTED_RATE) + Fs];
-#else
-    QPD_FLOAT_Coefs  *pCoefficients;
-    extern         QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[];
-
-    pCoefficients = &LVPSA_QPD_Float_Coefs[(pParams->LevelDetectionSpeed * \
-                                    LVPSA_NR_SUPPORTED_RATE) + Fs];
-#endif
-
-
-    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
-    {
-#ifndef BUILD_FLOAT
-        LVPSA_QPD_Init (&pInst->pQPD_States[ii],
-                        &pInst->pQPD_Taps[ii],
-                        pCoefficients );
-#else
-        LVPSA_QPD_Init_Float (&pInst->pQPD_States[ii],
-                              &pInst->pQPD_Taps[ii],
-                              pCoefficients );
-#endif
-    }
-
-    return(LVPSA_OK);
-
-}
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVPSA_BPSinglePrecCoefs                                    */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Calculate single precision coefficients for a band pass filter                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  Fs                       Sampling frequency index                                   */
-/*  pFilterParams            Pointer to the filter definition                           */
-/*  pCoefficients            Pointer to the coefficients                                */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVPSA_OK         Always succeeds                                                    */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The equations used are as follows:                                               */
-/*                                                                                      */
-/*      t0 = 2 * Pi * Fc / Fs                                                           */
-/*                                                                                      */
-/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
-/*      b1 = (0.5 - b2) * cos(t0)                                                       */
-/*      a0 = (0.5 + b2) / 2                                                             */
-/*                                                                                      */
-/*  Where:                                                                              */
-/*      Fc          is the centre frequency, DC to Nyquist                              */
-/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
-/*      Q           is the Q factor, 0.25 to 12                                         */
-/*                                                                                      */
-/*  2. This function is entirely based on the LVEQNB_SinglePrecCoefs function           */
-/*     of the n bands equalizer (LVEQNB                                                 */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
-                                         LVPSA_FilterParam_t     *pFilterParams,
-                                         BP_FLOAT_Coefs_t        *pCoefficients)
-{
-
-    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
-    extern LVM_FLOAT    LVPSA_Float_CosCoef[];
-
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_FLOAT           T0;
-    LVM_FLOAT           D;
-    LVM_FLOAT           A0;
-    LVM_FLOAT           B1;
-    LVM_FLOAT           B2;
-    LVM_FLOAT           Dt0;
-    LVM_FLOAT           B2_Den;
-    LVM_FLOAT           B2_Num;
-    LVM_FLOAT           COS_T0;
-    LVM_FLOAT           coef;
-    LVM_FLOAT           factor;
-    LVM_FLOAT           t0;
-    LVM_INT16           i;
-
-
-    /*
-     * Get the filter definition
-     */
-    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
-    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
-    D = 3200;                 /* Floating point value 1.000000 (1*100*2^5) */
-                    /* Force D = 1 : the function was originally used for a peaking filter.
-                       The D parameter do not exist for a BandPass filter coefficients */
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 =  T0 / 2048 ;
-    B2_Den = QFactor + Dt0;
-    B2_Num = Dt0 - QFactor;
-    B2 = B2_Num / (2 * B2_Den);
-
-    /*
-     * Calculate the cosine by a polynomial expansion using the equation:
-     *
-     *  Cos += coef(n) * t0^n                   For n = 0 to 6
-     */
-    T0 = (T0 / 2048) * 0.63658558f;              /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
-    t0 = T0 ;
-    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
-    COS_T0 = 0.0f;                                 /* Initialise the error to zero */
-    for (i = 1; i < 7; i++)
-    {
-        coef    = LVPSA_Float_CosCoef[i];                /* Get the nth coefficient */
-        COS_T0 += (factor * coef);         /* The nth partial sum */
-        factor  = (factor * t0) ;           /* Calculate t0^n */
-    }
-    COS_T0 = COS_T0 * 8;    /*LVPSA_CosCoef_float[0]*/      /* Correct the scaling */
-
-
-    B1 = ((LVM_FLOAT)0.5 - B2) * (COS_T0);    /* B1 = (0.5 - b2) * cos(t0) */
-    A0 = ((LVM_FLOAT)0.5 + B2) / 2;                        /* A0 = (0.5 + b2) / 2 */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = A0 * 2;
-    pCoefficients->B1 = B1 * 2;
-    pCoefficients->B2 = B2 * 2;
-
-    return(LVPSA_OK);
-}
-#else
-LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
-                                         LVPSA_FilterParam_t    *pFilterParams,
-                                         BP_C16_Coefs_t         *pCoefficients)
-{
-
-    extern LVM_INT16    LVPSA_TwoPiOnFsTable[];
-    extern LVM_INT16    LVPSA_CosCoef[];
-
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_INT32           T0;
-    LVM_INT16           D;
-    LVM_INT32           A0;
-    LVM_INT32           B1;
-    LVM_INT32           B2;
-    LVM_INT32           Dt0;
-    LVM_INT32           B2_Den;
-    LVM_INT32           B2_Num;
-    LVM_INT32           COS_T0;
-    LVM_INT16           coef;
-    LVM_INT32           factor;
-    LVM_INT16           t0;
-    LVM_INT16           i;
-
-
-    /*
-     * Get the filter definition
-     */
-    LVM_UINT16          Frequency   = pFilterParams->CenterFrequency;
-    LVM_UINT16          QFactor     = pFilterParams->QFactor;
-
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
-    D = 3200;                                               /* Floating point value 1.000000 (1*100*2^5) */
-                                                            /* Force D = 1 : the function was originally used for a peaking filter.
-                                                               The D parameter do not exist for a BandPass filter coefficients */
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 = D * (T0 >> 10);
-    B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
-    B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
-    B2 = (B2_Num / (B2_Den >> 16)) << 15;
-
-    /*
-     * Calculate the cosine by a polynomial expansion using the equation:
-     *
-     *  Cos += coef(n) * t0^n                   For n = 0 to 6
-     */
-    T0 = (T0 >> 10) * 20859;                    /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
-    t0 = (LVM_INT16)(T0 >> 16);
-    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
-    COS_T0 = 0;                                 /* Initialise the error to zero */
-    for (i=1; i<7; i++)
-    {
-        coef = LVPSA_CosCoef[i];                /* Get the nth coefficient */
-        COS_T0 += (factor * coef) >> 5;         /* The nth partial sum */
-        factor = (factor * t0) >> 15;           /* Calculate t0^n */
-    }
-    COS_T0 = COS_T0 << (LVPSA_CosCoef[0]+6);          /* Correct the scaling */
-
-
-    B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16);    /* B1 = (0.5 - b2) * cos(t0) */
-    A0 = (0x40000000 + B2) >> 1;                        /* A0 = (0.5 + b2) / 2 */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = (LVM_INT16)(A0>>16);
-    pCoefficients->B1 = (LVM_INT16)(B1>>15);
-    pCoefficients->B2 = (LVM_INT16)(B2>>16);
-
-
-    return(LVPSA_OK);
-}
-#endif
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                 LVPSA_BPDoublePrecCoefs                                    */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  Calculate double precision coefficients for a band pass filter                      */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  Fs                       Sampling frequency index                                   */
-/*  pFilterParams            Pointer to the filter definition                           */
-/*  pCoefficients            Pointer to the coefficients                                */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVPSA_OK                 Always succeeds                                            */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1. The equations used are as follows:                                               */
-/*                                                                                      */
-/*      t0 = 2 * Pi * Fc / Fs                                                           */
-/*                                                                                      */
-/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
-/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
-/*      a0 = (0.5 + b2) / 2                                                             */
-/*                                                                                      */
-/*  Where:                                                                              */
-/*      Fc          is the centre frequency, DC to Fs/50                                */
-/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
-/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
-/*                                                                                      */
-/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
-/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
-/*     itself the difference from the value 1.0 is calculated, this can be done with    */
-/*     lower precision maths.                                                           */
-/*                                                                                      */
-/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
-/*     small errors in this value have a combined effect on the Q and Gain but not the  */
-/*     the frequency of the filter.                                                     */
-/*                                                                                      */
-/*  4. This function is entirely based on the LVEQNB_DoublePrecCoefs function           */
-/*     of the n bands equalizer (LVEQNB                                                 */
-/*                                                                                      */
-/****************************************************************************************/
-#ifdef BUILD_FLOAT
-LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
-                                        LVPSA_FilterParam_t   *pFilterParams,
-                                        BP_FLOAT_Coefs_t      *pCoefficients)
-{
-
-    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
-    extern LVM_FLOAT    LVPSA_Float_DPCosCoef[];
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_FLOAT           T0;
-    LVM_FLOAT           D;
-    LVM_FLOAT           A0;
-    LVM_FLOAT           B1;
-    LVM_FLOAT           B2;
-    LVM_FLOAT           Dt0;
-    LVM_FLOAT           B2_Den;
-    LVM_FLOAT           B2_Num;
-    LVM_FLOAT           CosErr;
-    LVM_FLOAT           coef;
-    LVM_FLOAT           factor;
-    LVM_FLOAT           t0;
-    LVM_INT16           i;
-
-    /*
-     * Get the filter definition
-     */
-    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
-    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
-
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
-    D = 3200;    /* Floating point value 1.000000 (1*100*2^5) */
-                 /* Force D = 1 : the function was originally used for a peaking filter.
-                    The D parameter do not exist for a BandPass filter coefficients */
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 =  T0 / 2048 ;
-    B2_Den = QFactor + Dt0;
-    B2_Num = Dt0 - QFactor;
-    B2 = B2_Num / (2 * B2_Den);
-
-    /*
-     * Calculate the cosine error by a polynomial expansion using the equation:
-     *
-     *  CosErr += coef(n) * t0^n                For n = 0 to 4
-     */
-    T0 = T0 * 0.994750f;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
-    t0 = T0;
-    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
-    CosErr = 0.0f;                                 /* Initialise the error to zero */
-    for (i = 1; i < 5; i++)
-    {
-        coef = LVPSA_Float_DPCosCoef[i];              /* Get the nth coefficient */
-        CosErr += factor * coef;         /* The nth partial sum */
-        factor = factor * t0;           /* Calculate t0^n */
-    }
-    CosErr = CosErr * 2;          /* Correct the scaling */
-
-    /*
-     * Calculate the B1 and A0 coefficients
-     */
-    B1 = ((LVM_FLOAT)0.5 - B2);                     /* B1 = (0.5 - b2) */
-    A0 = B1 * CosErr ;    /* Temporary storage for (0.5 - b2) * coserr(t0) */
-    B1 -= A0;                                   /* B1 = (0.5 - b2) * (1 - coserr(t0))  */
-    A0 = ((LVM_FLOAT)0.5  + B2) / 2;                /* A0 = (0.5 + b2) / 2 */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = A0;
-    pCoefficients->B1 = B1;
-    pCoefficients->B2 = B2;
-
-    return(LVPSA_OK);
-}
-#else
-LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
-                                        LVPSA_FilterParam_t  *pFilterParams,
-                                        BP_C32_Coefs_t       *pCoefficients)
-{
-
-    extern LVM_INT16    LVPSA_TwoPiOnFsTable[];
-    extern LVM_INT16    LVPSA_DPCosCoef[];
-
-    /*
-     * Intermediate variables and temporary values
-     */
-    LVM_INT32           T0;
-    LVM_INT16           D;
-    LVM_INT32           A0;
-    LVM_INT32           B1;
-    LVM_INT32           B2;
-    LVM_INT32           Dt0;
-    LVM_INT32           B2_Den;
-    LVM_INT32           B2_Num;
-    LVM_INT32           CosErr;
-    LVM_INT16           coef;
-    LVM_INT32           factor;
-    LVM_INT16           t0;
-    LVM_INT16           i;
-
-    /*
-     * Get the filter definition
-     */
-    LVM_UINT16          Frequency   = pFilterParams->CenterFrequency;
-    LVM_UINT16          QFactor     = pFilterParams->QFactor;
-
-
-    /*
-     * Calculating the intermediate values
-     */
-    T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
-    D = 3200;                                               /* Floating point value 1.000000 (1*100*2^5) */
-                                                            /* Force D = 1 : the function was originally used for a peaking filter.
-                                                               The D parameter do not exist for a BandPass filter coefficients */
-
-    /*
-     * Calculate the B2 coefficient
-     */
-    Dt0 = D * (T0 >> 10);
-    B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
-    B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
-    B2 = (B2_Num / (B2_Den >> 16)) << 15;
-
-    /*
-     * Calculate the cosine error by a polynomial expansion using the equation:
-     *
-     *  CosErr += coef(n) * t0^n                For n = 0 to 4
-     */
-    T0 = (T0 >> 6) * 0x7f53;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
-    t0 = (LVM_INT16)(T0 >> 16);
-    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
-    CosErr = 0;                                 /* Initialise the error to zero */
-    for (i=1; i<5; i++)
-    {
-        coef = LVPSA_DPCosCoef[i];              /* Get the nth coefficient */
-        CosErr += (factor * coef) >> 5;         /* The nth partial sum */
-        factor = (factor * t0) >> 15;           /* Calculate t0^n */
-    }
-    CosErr = CosErr << (LVPSA_DPCosCoef[0]);          /* Correct the scaling */
-
-    /*
-     * Calculate the B1 and A0 coefficients
-     */
-    B1 = (0x40000000 - B2);                     /* B1 = (0.5 - b2) */
-    A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6;    /* Temporary storage for (0.5 - b2) * coserr(t0) */
-    B1 -= A0;                                   /* B1 = (0.5 - b2) * (1 - coserr(t0))  */
-    A0 = (0x40000000 + B2) >> 1;                /* A0 = (0.5 + b2) / 2 */
-
-    /*
-     * Write coeff into the data structure
-     */
-    pCoefficients->A0 = A0;
-    pCoefficients->B1 = B1;
-    pCoefficients->B2 = B2;
-
-    return(LVPSA_OK);
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_ClearFilterHistory                                    */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Clears the filters' data history                                                */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst           Pointer to the instance                                         */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK         Always succeeds                                                */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t        *pInst)
-{
-    LVM_INT8       *pTapAddress;
-    LVM_UINT32       i;
-
-    /* Band Pass filters taps */
-    pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
-#ifdef BUILD_FLOAT
-    for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t); i++)
-    {
-        pTapAddress[i] = 0;
-    }
-#else
-    for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_Taps_t); i++)
-    {
-        pTapAddress[i] = 0;
-    }
-#endif
-    /* Quasi-peak filters taps */
-    pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
-    for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
-    {
-        pTapAddress[i] = 0;
-    }
-
-    return(LVPSA_OK);
-}
-
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
new file mode 100644
index 0000000..deafaa7
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.cpp
@@ -0,0 +1,681 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "VectorArithmetic.h"
+
+#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
+#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
+
+LVPSA_RETURN LVPSA_SetBPFiltersType (  LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
+                                       LVPSA_FilterParam_t   *pFilterParams,
+                                       BP_FLOAT_Coefs_t        *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16            Fs,
+                                       LVPSA_FilterParam_t  *pFilterParams,
+                                       BP_FLOAT_Coefs_t       *pCoefficients);
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_ClearFilterHistory( LVPSA_InstancePr_t        *pInst);
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Control                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Give some new control parameters to the module.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance           Pointer to the instance                                     */
+/*  NewParams           Structure that contains the new parameters                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Control           ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_ControlParams_t      *pNewParams     )
+{
+
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if(pNewParams->Fs >= LVPSA_NR_SUPPORTED_RATE)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+    if(pNewParams->LevelDetectionSpeed >= LVPSA_NR_SUPPORTED_SPEED)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+
+    pLVPSA_Inst->NewParams = *pNewParams;
+    pLVPSA_Inst->bControlPending = LVM_TRUE;
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetControlParams                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the current control parameters of the module                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance       Pointer to the instance                                         */
+/*  pParams         Pointer to an empty control structure                           */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams         (    pLVPSA_Handle_t            hInstance,
+                                                 LVPSA_ControlParams_t     *pParams )
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    pParams->Fs                     = pLVPSA_Inst->CurrentParams.Fs;
+    pParams->LevelDetectionSpeed    = pLVPSA_Inst->CurrentParams.LevelDetectionSpeed;
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetInitParams                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the initialization parameters of the module                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance       Pointer to the instance                                         */
+/*  pParams         Pointer to an empty control structure                           */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams         (    pLVPSA_Handle_t            hInstance,
+                                              LVPSA_InitParams_t        *pParams )
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    pParams->SpectralDataBufferDuration   = pLVPSA_Inst->SpectralDataBufferDuration;
+    pParams->MaxInputBlockSize            = pLVPSA_Inst->MaxInputBlockSize;
+    pParams->nBands                       = pLVPSA_Inst->nBands;
+    pParams->pFiltersParams               = pLVPSA_Inst->pFiltersParams;
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_ApplyNewSettings                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Reinitialize some parameters and changes filters' coefficients if               */
+/*  some control parameters have changed.                                           */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t     *pInst)
+{
+    LVM_UINT16 ii;
+    LVM_UINT16 Freq;
+    LVPSA_ControlParams_t   Params;
+    extern LVM_INT16        LVPSA_nSamplesBufferUpdate[];
+    extern LVM_UINT32       LVPSA_SampleRateTab[];
+    extern LVM_UINT16       LVPSA_DownSamplingFactor[];
+
+    if(pInst == 0)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    Params = pInst->NewParams;
+
+    /* Modifies filters types and coefficients, clear the taps and
+       re-initializes parameters if sample frequency has changed    */
+    if(Params.Fs != pInst->CurrentParams.Fs)
+    {
+        pInst->CurrentParams.Fs = Params.Fs;
+
+        /* Initialize the center freqeuncies as a function of the sample rate */
+        Freq = (LVM_UINT16) ((LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1) / (pInst->nBands + 1));
+        for(ii = pInst->nBands; ii > 0; ii--)
+        {
+            pInst->pFiltersParams[ii-1].CenterFrequency = (LVM_UINT16) (Freq * ii);
+        }
+
+        /* Count the number of relevant filters. If the center frequency of the filter is
+           bigger than the nyquist frequency, then the filter is not relevant and doesn't
+           need to be used */
+        for(ii = pInst->nBands; ii > 0; ii--)
+        {
+            if(pInst->pFiltersParams[ii-1].CenterFrequency < (LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1))
+            {
+                pInst->nRelevantFilters = ii;
+                break;
+            }
+        }
+        LVPSA_SetBPFiltersType(pInst, &Params);
+        LVPSA_SetBPFCoefficients(pInst, &Params);
+        LVPSA_SetQPFCoefficients(pInst, &Params);
+        LVPSA_ClearFilterHistory(pInst);
+        pInst->nSamplesBufferUpdate = (LVM_UINT16)LVPSA_nSamplesBufferUpdate[Params.Fs];
+        pInst->BufferUpdateSamplesCount = 0;
+        pInst->DownSamplingFactor = LVPSA_DownSamplingFactor[Params.Fs];
+        pInst->DownSamplingCount = 0;
+        for(ii = 0; ii < (pInst->nBands * pInst->SpectralDataBufferLength); ii++)
+        {
+            pInst->pSpectralDataBufferStart[ii] = 0;
+        }
+        for(ii = 0; ii < pInst->nBands; ii++)
+        {
+            pInst->pPreviousPeaks[ii] = 0;
+        }
+    }
+    else
+    {
+        if(Params.LevelDetectionSpeed != pInst->CurrentParams.LevelDetectionSpeed)
+        {
+            LVPSA_SetQPFCoefficients(pInst, &Params);
+        }
+    }
+
+    pInst->CurrentParams = pInst->NewParams;
+
+    return (LVPSA_OK);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetBPFiltersType                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter type based on the BPFilterType.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  pParams             Poniter to conrol parameters                                */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. To select the biquad type the follow rules are applied:                      */
+/*          Double precision    if (fc <= fs/110)                                   */
+/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
+/*          Single precision    otherwise                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFiltersType (   LVPSA_InstancePr_t        *pInst,
+                                        LVPSA_ControlParams_t      *pParams  )
+{
+    extern LVM_UINT32   LVPSA_SampleRateTab[];                 /* Sample rate table */
+    LVM_UINT16          ii;                                                         /* Filter band index */
+    LVM_UINT32          fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs];      /* Sample rate */
+    LVM_UINT32          fc;                                                         /* Filter centre frequency */
+    LVM_INT16           QFactor;                                                    /* Filter Q factor */
+
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+        /*
+         * Get the filter settings
+         */
+        fc = (LVM_UINT32)pInst->pFiltersParams[ii].CenterFrequency;     /* Get the band centre frequency */
+        QFactor =(LVM_INT16) pInst->pFiltersParams[ii].QFactor;                    /* Get the band Q factor */
+
+        /*
+         * For each filter set the type of biquad required
+         */
+        pInst->pBPFiltersPrecision[ii] = LVPSA_SimplePrecisionFilter;     /* Default to single precision */
+        if ((LOW_FREQ * fs) >= (fc << 15))
+        {
+            /*
+             * fc <= fs/110
+             */
+            pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+        }
+        else
+        {
+            if (((LOW_FREQ * fs) < (fc << 15)) && ((fc << 15) < (HIGH_FREQ * fs)) && (QFactor > 300))
+            {
+                /*
+                * (fs/110 < fc < fs/85) & (Q>3)
+                */
+                pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+            }
+        }
+    }
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetBPFCoefficients                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the band pass filter coefficients. This uses the type to select            */
+/*  single or double precision coefficients.                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  Params              Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFCoefficients(  LVPSA_InstancePr_t        *pInst,
+                                        LVPSA_ControlParams_t      *pParams)
+{
+
+    LVM_UINT16                      ii;
+
+    /*
+     * Set the coefficients for each band by the init function
+     */
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+        switch  (pInst->pBPFiltersPrecision[ii])
+        {
+            case    LVPSA_DoublePrecisionFilter:
+            {
+                BP_FLOAT_Coefs_t      Coefficients;
+                /*
+                 * Calculate the double precision coefficients
+                 */
+                LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
+                                        &pInst->pFiltersParams[ii],
+                                        &Coefficients);
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+                break;
+            }
+
+            case    LVPSA_SimplePrecisionFilter:
+            {
+                BP_FLOAT_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
+                                        &pInst->pFiltersParams[ii],
+                                        &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F16Css_TRC_WRA_01_Init (&pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+                break;
+            }
+        }
+    }
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetQPFCoefficients                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the quasi peak filters coefficients. This uses the chosen                  */
+/*  LevelDetectionSpeed from the control parameters.                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  Params              Control parameters                                          */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetQPFCoefficients(   LVPSA_InstancePr_t        *pInst,
+                                         LVPSA_ControlParams_t      *pParams  )
+{
+    LVM_UINT16     ii;
+    LVM_Fs_en      Fs = pParams->Fs;
+    QPD_FLOAT_Coefs  *pCoefficients;
+    extern         QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[];
+
+    pCoefficients = &LVPSA_QPD_Float_Coefs[(pParams->LevelDetectionSpeed * \
+                                    LVPSA_NR_SUPPORTED_RATE) + Fs];
+
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+        LVPSA_QPD_Init_Float (&pInst->pQPD_States[ii],
+                              &pInst->pQPD_Taps[ii],
+                              pCoefficients );
+    }
+
+    return(LVPSA_OK);
+
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVPSA_BPSinglePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Calculate single precision coefficients for a band pass filter                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                       Sampling frequency index                                   */
+/*  pFilterParams            Pointer to the filter definition                           */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK         Always succeeds                                                    */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
+/*      b1 = (0.5 - b2) * cos(t0)                                                       */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      Fc          is the centre frequency, DC to Nyquist                              */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12                                         */
+/*                                                                                      */
+/*  2. This function is entirely based on the LVEQNB_SinglePrecCoefs function           */
+/*     of the n bands equalizer (LVEQNB                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
+                                         LVPSA_FilterParam_t     *pFilterParams,
+                                         BP_FLOAT_Coefs_t        *pCoefficients)
+{
+
+    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVPSA_Float_CosCoef[];
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+    LVM_FLOAT           Dt0;
+    LVM_FLOAT           B2_Den;
+    LVM_FLOAT           B2_Num;
+    LVM_FLOAT           COS_T0;
+    LVM_FLOAT           coef;
+    LVM_FLOAT           factor;
+    LVM_FLOAT           t0;
+    LVM_INT16           i;
+
+    /*
+     * Get the filter definition
+     */
+    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
+    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;                 /* Floating point value 1.000000 (1*100*2^5) */
+                    /* Force D = 1 : the function was originally used for a peaking filter.
+                       The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 =  T0 / 2048 ;
+    B2_Den = QFactor + Dt0;
+    B2_Num = Dt0 - QFactor;
+    B2 = B2_Num / (2 * B2_Den);
+
+    /*
+     * Calculate the cosine by a polynomial expansion using the equation:
+     *
+     *  Cos += coef(n) * t0^n                   For n = 0 to 6
+     */
+    T0 = (T0 / 2048) * 0.63658558f;              /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+    t0 = T0 ;
+    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
+    COS_T0 = 0.0f;                                 /* Initialise the error to zero */
+    for (i = 1; i < 7; i++)
+    {
+        coef    = LVPSA_Float_CosCoef[i];                /* Get the nth coefficient */
+        COS_T0 += (factor * coef);         /* The nth partial sum */
+        factor  = (factor * t0) ;           /* Calculate t0^n */
+    }
+    COS_T0 = COS_T0 * 8;    /*LVPSA_CosCoef_float[0]*/      /* Correct the scaling */
+
+    B1 = ((LVM_FLOAT)0.5 - B2) * (COS_T0);    /* B1 = (0.5 - b2) * cos(t0) */
+    A0 = ((LVM_FLOAT)0.5 + B2) / 2;                        /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0 * 2;
+    pCoefficients->B1 = B1 * 2;
+    pCoefficients->B2 = B2 * 2;
+
+    return(LVPSA_OK);
+}
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVPSA_BPDoublePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Calculate double precision coefficients for a band pass filter                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                       Sampling frequency index                                   */
+/*  pFilterParams            Pointer to the filter definition                           */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK                 Always succeeds                                            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
+/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      Fc          is the centre frequency, DC to Fs/50                                */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
+/*                                                                                      */
+/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
+/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
+/*     itself the difference from the value 1.0 is calculated, this can be done with    */
+/*     lower precision maths.                                                           */
+/*                                                                                      */
+/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
+/*     small errors in this value have a combined effect on the Q and Gain but not the  */
+/*     the frequency of the filter.                                                     */
+/*                                                                                      */
+/*  4. This function is entirely based on the LVEQNB_DoublePrecCoefs function           */
+/*     of the n bands equalizer (LVEQNB                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
+                                        LVPSA_FilterParam_t   *pFilterParams,
+                                        BP_FLOAT_Coefs_t      *pCoefficients)
+{
+
+    extern LVM_FLOAT    LVPSA_Float_TwoPiOnFsTable[];
+    extern LVM_FLOAT    LVPSA_Float_DPCosCoef[];
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_FLOAT           T0;
+    LVM_FLOAT           D;
+    LVM_FLOAT           A0;
+    LVM_FLOAT           B1;
+    LVM_FLOAT           B2;
+    LVM_FLOAT           Dt0;
+    LVM_FLOAT           B2_Den;
+    LVM_FLOAT           B2_Num;
+    LVM_FLOAT           CosErr;
+    LVM_FLOAT           coef;
+    LVM_FLOAT           factor;
+    LVM_FLOAT           t0;
+    LVM_INT16           i;
+
+    /*
+     * Get the filter definition
+     */
+    LVM_FLOAT          Frequency   = (LVM_FLOAT)(pFilterParams->CenterFrequency);
+    LVM_FLOAT          QFactor     = ((LVM_FLOAT)(pFilterParams->QFactor)) / 100;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = Frequency * LVPSA_Float_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;    /* Floating point value 1.000000 (1*100*2^5) */
+                 /* Force D = 1 : the function was originally used for a peaking filter.
+                    The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 =  T0 / 2048 ;
+    B2_Den = QFactor + Dt0;
+    B2_Num = Dt0 - QFactor;
+    B2 = B2_Num / (2 * B2_Den);
+
+    /*
+     * Calculate the cosine error by a polynomial expansion using the equation:
+     *
+     *  CosErr += coef(n) * t0^n                For n = 0 to 4
+     */
+    T0 = T0 * 0.994750f;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+    t0 = T0;
+    factor = 1.0f;                            /* Initialise to 1.0 for the a0 coefficient */
+    CosErr = 0.0f;                                 /* Initialise the error to zero */
+    for (i = 1; i < 5; i++)
+    {
+        coef = LVPSA_Float_DPCosCoef[i];              /* Get the nth coefficient */
+        CosErr += factor * coef;         /* The nth partial sum */
+        factor = factor * t0;           /* Calculate t0^n */
+    }
+    CosErr = CosErr * 2;          /* Correct the scaling */
+
+    /*
+     * Calculate the B1 and A0 coefficients
+     */
+    B1 = ((LVM_FLOAT)0.5 - B2);                     /* B1 = (0.5 - b2) */
+    A0 = B1 * CosErr ;    /* Temporary storage for (0.5 - b2) * coserr(t0) */
+    B1 -= A0;                                   /* B1 = (0.5 - b2) * (1 - coserr(t0))  */
+    A0 = ((LVM_FLOAT)0.5  + B2) / 2;                /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0;
+    pCoefficients->B1 = B1;
+    pCoefficients->B2 = B2;
+
+    return(LVPSA_OK);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_ClearFilterHistory                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Clears the filters' data history                                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst           Pointer to the instance                                         */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK         Always succeeds                                                */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t        *pInst)
+{
+    LVM_INT8       *pTapAddress;
+    LVM_UINT32       i;
+
+    /* Band Pass filters taps */
+    pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
+    for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t); i++)
+    {
+        pTapAddress[i] = 0;
+    }
+    /* Quasi-peak filters taps */
+    pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
+    for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
+    {
+        pTapAddress[i] = 0;
+    }
+
+    return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
deleted file mode 100644
index 1c26860..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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    "LVPSA.h"
-#include    "LVPSA_Private.h"
-#include    "InstAlloc.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_Init                                                  */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialize the LVPSA module                                                     */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  phInstance          Pointer to pointer to the instance                          */
-/*  InitParams          Init parameters structure                                   */
-/*  ControlParams       Control parameters structure                                */
-/*  pMemoryTable        Memory table that contains memory areas definition          */
-/*                                                                                  */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_Init              ( pLVPSA_Handle_t             *phInstance,
-                                       LVPSA_InitParams_t          *pInitParams,
-                                       LVPSA_ControlParams_t       *pControlParams,
-                                       LVPSA_MemTab_t              *pMemoryTable )
-{
-    LVPSA_InstancePr_t          *pLVPSA_Inst;
-    LVPSA_RETURN                errorCode       = LVPSA_OK;
-    LVM_UINT32                  ii;
-#ifndef BUILD_FLOAT
-    extern LVM_INT16            LVPSA_GainTable[];
-#else
-    extern LVM_FLOAT            LVPSA_Float_GainTable[];
-#endif
-    LVM_UINT32                  BufferLength = 0;
-
-    /* Ints_Alloc instances, needed for memory alignment management */
-    INST_ALLOC          Instance;
-    INST_ALLOC          Scratch;
-    INST_ALLOC          Data;
-    INST_ALLOC          Coef;
-
-    /* Check parameters */
-    if((phInstance == LVM_NULL) || (pInitParams == LVM_NULL) || (pControlParams == LVM_NULL) || (pMemoryTable == LVM_NULL))
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-    if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
-        (pInitParams->SpectralDataBufferDuration == 0)                        ||
-        (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
-        (pInitParams->MaxInputBlockSize == 0)                           ||
-        (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
-        (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
-        (pInitParams->pFiltersParams == 0))
-    {
-        return(LVPSA_ERROR_INVALIDPARAM);
-    }
-    for(ii = 0; ii < pInitParams->nBands; ii++)
-    {
-        if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
-           (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
-           (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
-           (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
-           (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
-           {
-                return(LVPSA_ERROR_INVALIDPARAM);
-           }
-    }
-
-
-    /*Inst_Alloc instances initialization */
-    InstAlloc_Init( &Instance   , pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress);
-    InstAlloc_Init( &Scratch    , pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress);
-    InstAlloc_Init( &Data       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress);
-    InstAlloc_Init( &Coef       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress);
-
-
-    /* Set the instance handle if not already initialised */
-    if (*phInstance == LVM_NULL)
-    {
-        *phInstance = InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
-    }
-    pLVPSA_Inst =(LVPSA_InstancePr_t*)*phInstance;
-
-
-    /* Check the memory table for NULL pointers */
-    for (ii = 0; ii < LVPSA_NR_MEMORY_REGIONS; ii++)
-    {
-        if (pMemoryTable->Region[ii].Size!=0)
-        {
-            if (pMemoryTable->Region[ii].pBaseAddress==LVM_NULL)
-            {
-                return(LVPSA_ERROR_NULLADDRESS);
-            }
-            pLVPSA_Inst->MemoryTable.Region[ii] = pMemoryTable->Region[ii];
-        }
-    }
-
-    /* Initialize module's internal parameters */
-    pLVPSA_Inst->bControlPending = LVM_FALSE;
-    pLVPSA_Inst->nBands = pInitParams->nBands;
-    pLVPSA_Inst->MaxInputBlockSize = pInitParams->MaxInputBlockSize;
-    pLVPSA_Inst->SpectralDataBufferDuration = pInitParams->SpectralDataBufferDuration;
-    pLVPSA_Inst->CurrentParams.Fs = LVM_FS_DUMMY;
-    pLVPSA_Inst->CurrentParams.LevelDetectionSpeed = LVPSA_SPEED_DUMMY;
-
-    {   /* for avoiding QAC warnings */
-        LVM_INT32 SDBD=(LVM_INT32)pLVPSA_Inst->SpectralDataBufferDuration;
-        LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
-        LVM_INT32 BL;
-
-        MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
-
-        BufferLength=(LVM_UINT32)BL;
-    }
-
-    if((BufferLength * LVPSA_InternalRefreshTime) != pLVPSA_Inst->SpectralDataBufferDuration)
-    {
-        pLVPSA_Inst->SpectralDataBufferLength = BufferLength + 1;
-    }
-    else
-    {
-        pLVPSA_Inst->SpectralDataBufferLength = BufferLength;
-    }
-
-
-    /* Assign the pointers */
-#ifndef BUILD_FLOAT
-    pLVPSA_Inst->pPostGains                 = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
-#else
-    pLVPSA_Inst->pPostGains             = InstAlloc_AddMember( &Instance, pInitParams->nBands * \
-                                                               sizeof(LVM_FLOAT) );
-#endif
-    pLVPSA_Inst->pFiltersParams             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
-    pLVPSA_Inst->pSpectralDataBufferStart   = InstAlloc_AddMember( &Instance, pInitParams->nBands * pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8) );
-    pLVPSA_Inst->pPreviousPeaks             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
-    pLVPSA_Inst->pBPFiltersPrecision        = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
-#ifndef BUILD_FLOAT
-    pLVPSA_Inst->pBP_Instances          = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
-    pLVPSA_Inst->pQPD_States            = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
-#else
-    pLVPSA_Inst->pBP_Instances          = InstAlloc_AddMember( &Coef, pInitParams->nBands * \
-                                                               sizeof(Biquad_FLOAT_Instance_t) );
-    pLVPSA_Inst->pQPD_States            = InstAlloc_AddMember( &Coef, pInitParams->nBands * \
-                                                               sizeof(QPD_FLOAT_State_t) );
-#endif
-
-#ifndef BUILD_FLOAT
-    pLVPSA_Inst->pBP_Taps               = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
-    pLVPSA_Inst->pQPD_Taps              = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
-
-#else
-    pLVPSA_Inst->pBP_Taps               = InstAlloc_AddMember( &Data,
-                                                               pInitParams->nBands * \
-                                                               sizeof(Biquad_1I_Order2_FLOAT_Taps_t));
-    pLVPSA_Inst->pQPD_Taps              = InstAlloc_AddMember( &Data, pInitParams->nBands * \
-                                                               sizeof(QPD_FLOAT_Taps_t) );
-#endif
-
-    /* Copy filters parameters in the private instance */
-    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
-    {
-        pLVPSA_Inst->pFiltersParams[ii] = pInitParams->pFiltersParams[ii];
-    }
-
-    /* Set Post filters gains*/
-    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
-    {
-#ifndef BUILD_FLOAT
-        pLVPSA_Inst->pPostGains[ii] =(LVM_UINT16) LVPSA_GainTable[pInitParams->pFiltersParams[ii].PostGain + 15];
-#else
-        pLVPSA_Inst->pPostGains[ii] = LVPSA_Float_GainTable[15 + \
-                                                        pInitParams->pFiltersParams[ii].PostGain];
-#endif
-    }
-    pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
-
-
-    /* Initialize control dependant internal parameters */
-    errorCode = LVPSA_Control (*phInstance, pControlParams);
-
-    if(errorCode!=0)
-    {
-        return errorCode;
-    }
-
-    errorCode = LVPSA_ApplyNewSettings (pLVPSA_Inst);
-
-    if(errorCode!=0)
-    {
-        return errorCode;
-    }
-
-    return(errorCode);
-}
-
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
new file mode 100644
index 0000000..9fcd82f
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "InstAlloc.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Init                                                  */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialize the LVPSA module                                                     */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  phInstance          Pointer to pointer to the instance                          */
+/*  InitParams          Init parameters structure                                   */
+/*  ControlParams       Control parameters structure                                */
+/*  pMemoryTable        Memory table that contains memory areas definition          */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Init              ( pLVPSA_Handle_t             *phInstance,
+                                       LVPSA_InitParams_t          *pInitParams,
+                                       LVPSA_ControlParams_t       *pControlParams,
+                                       LVPSA_MemTab_t              *pMemoryTable )
+{
+    LVPSA_InstancePr_t          *pLVPSA_Inst;
+    LVPSA_RETURN                errorCode       = LVPSA_OK;
+    LVM_UINT32                  ii;
+    extern LVM_FLOAT            LVPSA_Float_GainTable[];
+    LVM_UINT32                  BufferLength = 0;
+
+    /* Ints_Alloc instances, needed for memory alignment management */
+    INST_ALLOC          Instance;
+    INST_ALLOC          Scratch;
+    INST_ALLOC          Data;
+    INST_ALLOC          Coef;
+
+    /* Check parameters */
+    if((phInstance == LVM_NULL) || (pInitParams == LVM_NULL) || (pControlParams == LVM_NULL) || (pMemoryTable == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
+        (pInitParams->SpectralDataBufferDuration == 0)                        ||
+        (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
+        (pInitParams->MaxInputBlockSize == 0)                           ||
+        (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
+        (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
+        (pInitParams->pFiltersParams == 0))
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+    for(ii = 0; ii < pInitParams->nBands; ii++)
+    {
+        if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+           (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
+           (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
+           (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
+           (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+           {
+                return(LVPSA_ERROR_INVALIDPARAM);
+           }
+    }
+
+    /*Inst_Alloc instances initialization */
+    InstAlloc_Init( &Instance   , pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress);
+    InstAlloc_Init( &Scratch    , pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress);
+    InstAlloc_Init( &Data       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+    InstAlloc_Init( &Coef       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+    /* Set the instance handle if not already initialised */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+    }
+    pLVPSA_Inst =(LVPSA_InstancePr_t*)*phInstance;
+
+    /* Check the memory table for NULL pointers */
+    for (ii = 0; ii < LVPSA_NR_MEMORY_REGIONS; ii++)
+    {
+        if (pMemoryTable->Region[ii].Size!=0)
+        {
+            if (pMemoryTable->Region[ii].pBaseAddress==LVM_NULL)
+            {
+                return(LVPSA_ERROR_NULLADDRESS);
+            }
+            pLVPSA_Inst->MemoryTable.Region[ii] = pMemoryTable->Region[ii];
+        }
+    }
+
+    /* Initialize module's internal parameters */
+    pLVPSA_Inst->bControlPending = LVM_FALSE;
+    pLVPSA_Inst->nBands = pInitParams->nBands;
+    pLVPSA_Inst->MaxInputBlockSize = pInitParams->MaxInputBlockSize;
+    pLVPSA_Inst->SpectralDataBufferDuration = pInitParams->SpectralDataBufferDuration;
+    pLVPSA_Inst->CurrentParams.Fs = LVM_FS_DUMMY;
+    pLVPSA_Inst->CurrentParams.LevelDetectionSpeed = LVPSA_SPEED_DUMMY;
+
+    {   /* for avoiding QAC warnings */
+        LVM_INT32 SDBD=(LVM_INT32)pLVPSA_Inst->SpectralDataBufferDuration;
+        LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+        LVM_INT32 BL;
+
+        MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+
+        BufferLength=(LVM_UINT32)BL;
+    }
+
+    if((BufferLength * LVPSA_InternalRefreshTime) != pLVPSA_Inst->SpectralDataBufferDuration)
+    {
+        pLVPSA_Inst->SpectralDataBufferLength = BufferLength + 1;
+    }
+    else
+    {
+        pLVPSA_Inst->SpectralDataBufferLength = BufferLength;
+    }
+
+    /* Assign the pointers */
+    pLVPSA_Inst->pPostGains             =
+        (LVM_FLOAT *)InstAlloc_AddMember(&Instance, pInitParams->nBands * sizeof(LVM_FLOAT));
+    pLVPSA_Inst->pFiltersParams             = (LVPSA_FilterParam_t *)
+        InstAlloc_AddMember(&Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t));
+    pLVPSA_Inst->pSpectralDataBufferStart   = (LVM_UINT8 *)
+        InstAlloc_AddMember(&Instance, pInitParams->nBands * \
+                                pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8));
+    pLVPSA_Inst->pPreviousPeaks             = (LVM_UINT8 *)
+                  InstAlloc_AddMember(&Instance, pInitParams->nBands * sizeof(LVM_UINT8));
+    pLVPSA_Inst->pBPFiltersPrecision        = (LVPSA_BPFilterPrecision_en *)
+                  InstAlloc_AddMember(&Instance, pInitParams->nBands * \
+                                                       sizeof(LVPSA_BPFilterPrecision_en));
+    pLVPSA_Inst->pBP_Instances          = (Biquad_FLOAT_Instance_t *)
+                  InstAlloc_AddMember(&Coef, pInitParams->nBands * \
+                                                          sizeof(Biquad_FLOAT_Instance_t));
+    pLVPSA_Inst->pQPD_States            = (QPD_FLOAT_State_t *)
+                  InstAlloc_AddMember(&Coef, pInitParams->nBands * \
+                                                                sizeof(QPD_FLOAT_State_t));
+
+    pLVPSA_Inst->pBP_Taps               = (Biquad_1I_Order2_FLOAT_Taps_t *)
+        InstAlloc_AddMember(&Data, pInitParams->nBands * \
+                                                     sizeof(Biquad_1I_Order2_FLOAT_Taps_t));
+    pLVPSA_Inst->pQPD_Taps              = (QPD_FLOAT_Taps_t *)
+        InstAlloc_AddMember(&Data, pInitParams->nBands * \
+                                                    sizeof(QPD_FLOAT_Taps_t));
+
+    /* Copy filters parameters in the private instance */
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pLVPSA_Inst->pFiltersParams[ii] = pInitParams->pFiltersParams[ii];
+    }
+
+    /* Set Post filters gains*/
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pLVPSA_Inst->pPostGains[ii] = LVPSA_Float_GainTable[15 + \
+                                                        pInitParams->pFiltersParams[ii].PostGain];
+    }
+    pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
+
+    /* Initialize control dependant internal parameters */
+    errorCode = LVPSA_Control (*phInstance, pControlParams);
+
+    if(errorCode!=0)
+    {
+        return errorCode;
+    }
+
+    errorCode = LVPSA_ApplyNewSettings (pLVPSA_Inst);
+
+    if(errorCode!=0)
+    {
+        return errorCode;
+    }
+
+    return(errorCode);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
deleted file mode 100644
index 06a8f9d..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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    "LVPSA.h"
-#include    "LVPSA_Private.h"
-#include    "InstAlloc.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVEQNB_Memory                                               */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used for memory allocation and free. It can be called in           */
-/*  two ways:                                                                           */
-/*                                                                                      */
-/*      hInstance = NULL         Returns the memory requirements                        */
-/*      hInstance = Instance handle     Returns the memory requirements and             */
-/*                                      allocated base addresses for the instance       */
-/*                                                                                      */
-/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
-/*  base address pointers are NULL on return.                                           */
-/*                                                                                      */
-/*  When the function is called for free (hInstance = Instance Handle) the memory       */
-/*  table returns the allocated memory and base addresses used during initialisation.   */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pMemoryTable            Pointer to an empty memory definition table                 */
-/*  InitParams              Pointer to the instance init parameters                     */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVPSA_OK            Succeeds                                                        */
-/*  otherwise           Error due to bad parameters                                     */
-/*                                                                                      */
-/****************************************************************************************/
-LVPSA_RETURN LVPSA_Memory            ( pLVPSA_Handle_t             hInstance,
-                                       LVPSA_MemTab_t             *pMemoryTable,
-                                       LVPSA_InitParams_t         *pInitParams    )
-{
-    LVM_UINT32          ii;
-    LVM_UINT32          BufferLength;
-    INST_ALLOC          Instance;
-    INST_ALLOC          Scratch;
-    INST_ALLOC          Data;
-    INST_ALLOC          Coef;
-    LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-
-
-    InstAlloc_Init( &Instance   , LVM_NULL);
-    InstAlloc_Init( &Scratch    , LVM_NULL);
-    InstAlloc_Init( &Data       , LVM_NULL);
-    InstAlloc_Init( &Coef       , LVM_NULL);
-
-
-    if((pMemoryTable == LVM_NULL) || (pInitParams == LVM_NULL))
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-
-
-    /*
-     * Fill in the memory table
-     */
-    if (hInstance == LVM_NULL)
-    {
-
-        /* Check init parameter */
-        if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
-            (pInitParams->SpectralDataBufferDuration == 0)                        ||
-            (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
-            (pInitParams->MaxInputBlockSize == 0)                           ||
-            (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
-            (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
-            (pInitParams->pFiltersParams == 0))
-        {
-            return(LVPSA_ERROR_INVALIDPARAM);
-        }
-        for(ii = 0; ii < pInitParams->nBands; ii++)
-        {
-            if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
-               (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
-               (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
-               (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
-               (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
-               {
-                    return(LVPSA_ERROR_INVALIDPARAM);
-               }
-        }
-
-        /*
-         * Instance memory
-         */
-
-        InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
-#ifdef BUILD_FLOAT
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_FLOAT) );
-#else
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
-#endif
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
-
-        {
-            /* for avoiding QAC warnings as MUL32x32INTO32 works on LVM_INT32 only*/
-            LVM_INT32 SDBD=(LVM_INT32)pInitParams->SpectralDataBufferDuration;
-            LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
-            LVM_INT32 BL;
-
-            MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
-            BufferLength=(LVM_UINT32)BL;
-        }
-
-
-        if((BufferLength * LVPSA_InternalRefreshTime) != pInitParams->SpectralDataBufferDuration)
-        {
-            BufferLength++;
-        }
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * BufferLength * sizeof(LVM_UINT8) );
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
-        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
-        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&Instance);
-        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Type         = LVPSA_PERSISTENT;
-        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
-
-        /*
-         * Scratch memory
-         */
-#ifndef BUILD_FLOAT
-        InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_INT16) );
-#else
-        InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_FLOAT) );
-#endif
-        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size         = InstAlloc_GetTotal(&Scratch);
-        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type         = LVPSA_SCRATCH;
-        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
-
-        /*
-         * Persistent coefficients memory
-         */
-#ifndef BUILD_FLOAT
-        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
-        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
-#else
-        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_FLOAT_Instance_t) );
-        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_FLOAT_State_t) );
-#endif
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&Coef);
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type         = LVPSA_PERSISTENT_COEF;
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
-
-        /*
-         * Persistent data memory
-         */
-#ifndef BUILD_FLOAT
-        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
-        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
-#else
-        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t) );
-        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_FLOAT_Taps_t) );
-#endif
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&Data);
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type         = LVPSA_PERSISTENT_DATA;
-        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
-
-    }
-    else
-    {
-        /* Read back memory allocation table */
-        *pMemoryTable = pLVPSA_Inst->MemoryTable;
-    }
-
-    return(LVPSA_OK);
-}
-
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.cpp
new file mode 100644
index 0000000..eafcbe6
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL         Returns the memory requirements                        */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  InitParams              Pointer to the instance init parameters                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK            Succeeds                                                        */
+/*  otherwise           Error due to bad parameters                                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_Memory            ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_MemTab_t             *pMemoryTable,
+                                       LVPSA_InitParams_t         *pInitParams    )
+{
+    LVM_UINT32          ii;
+    LVM_UINT32          BufferLength;
+    INST_ALLOC          Instance;
+    INST_ALLOC          Scratch;
+    INST_ALLOC          Data;
+    INST_ALLOC          Coef;
+    LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+    InstAlloc_Init( &Instance   , LVM_NULL);
+    InstAlloc_Init( &Scratch    , LVM_NULL);
+    InstAlloc_Init( &Data       , LVM_NULL);
+    InstAlloc_Init( &Coef       , LVM_NULL);
+
+    if((pMemoryTable == LVM_NULL) || (pInitParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+
+        /* Check init parameter */
+        if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
+            (pInitParams->SpectralDataBufferDuration == 0)                        ||
+            (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
+            (pInitParams->MaxInputBlockSize == 0)                           ||
+            (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
+            (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
+            (pInitParams->pFiltersParams == 0))
+        {
+            return(LVPSA_ERROR_INVALIDPARAM);
+        }
+        for(ii = 0; ii < pInitParams->nBands; ii++)
+        {
+            if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+               (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
+               (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
+               (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
+               (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+               {
+                    return(LVPSA_ERROR_INVALIDPARAM);
+               }
+        }
+
+        /*
+         * Instance memory
+         */
+
+        InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_FLOAT) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+
+        {
+            /* for avoiding QAC warnings as MUL32x32INTO32 works on LVM_INT32 only*/
+            LVM_INT32 SDBD=(LVM_INT32)pInitParams->SpectralDataBufferDuration;
+            LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+            LVM_INT32 BL;
+
+            MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+            BufferLength=(LVM_UINT32)BL;
+        }
+
+        if((BufferLength * LVPSA_InternalRefreshTime) != pInitParams->SpectralDataBufferDuration)
+        {
+            BufferLength++;
+        }
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * BufferLength * sizeof(LVM_UINT8) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&Instance);
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Type         = LVPSA_PERSISTENT;
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_FLOAT) );
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size         = InstAlloc_GetTotal(&Scratch);
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type         = LVPSA_SCRATCH;
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent coefficients memory
+         */
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_FLOAT_Instance_t) );
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_FLOAT_State_t) );
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&Coef);
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type         = LVPSA_PERSISTENT_COEF;
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent data memory
+         */
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_FLOAT_Taps_t) );
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_FLOAT_Taps_t) );
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&Data);
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type         = LVPSA_PERSISTENT_DATA;
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pLVPSA_Inst->MemoryTable;
+    }
+
+    return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index ee07e2e..61987b5 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -23,12 +23,6 @@
 #include "LVPSA_QPD.h"
 #include "LVM_Macros.h"
 
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /**********************************************************************************
    CONSTANT DEFINITIONS
 ***********************************************************************************/
@@ -43,11 +37,7 @@
 #define LVPSA_MEMREGION_PERSISTENT_COEF  1      /* Offset to persistent coefficients  memory region in memory table */
 #define LVPSA_MEMREGION_PERSISTENT_DATA  2      /* Offset to persistent taps  memory region in memory table         */
 #define LVPSA_MEMREGION_SCRATCH          3      /* Offset to scratch  memory region in memory table                 */
-#ifndef HIGHER_FS
-#define LVPSA_NR_SUPPORTED_RATE          9      /* From 8000Hz to 48000Hz*/
-#else
 #define LVPSA_NR_SUPPORTED_RATE          13      /* From 8000Hz to 192000Hz*/
-#endif
 #define LVPSA_NR_SUPPORTED_SPEED         3      /* LOW, MEDIUM, HIGH                                                */
 
 #define LVPSA_MAXBUFFERDURATION          4000   /* Maximum length in ms of the levels buffer                        */
@@ -77,7 +67,6 @@
 #define LVPSA_InternalRefreshTimeInv    0x0666    /* 1/20ms left shifted by 15  */
 #define LVPSA_InternalRefreshTimeShift  15
 
-
 /* Precision of the filter */
 typedef enum
 {
@@ -96,12 +85,6 @@
     LVPSA_MemTab_t              MemoryTable;
 
     LVPSA_BPFilterPrecision_en *pBPFiltersPrecision;                /* Points a nBands elements array that contains the filter precision for each band              */
-#ifndef BUILD_FLOAT
-    Biquad_Instance_t          *pBP_Instances;                      /* Points a nBands elements array that contains the band pass filter instance for each band     */
-    Biquad_1I_Order2_Taps_t    *pBP_Taps;                           /* Points a nBands elements array that contains the band pass filter taps for each band         */
-    QPD_State_t                *pQPD_States;                        /* Points a nBands elements array that contains the QPD filter instance for each band           */
-    QPD_Taps_t                 *pQPD_Taps;                          /* Points a nBands elements array that contains the QPD filter taps for each band               */
-#else
     Biquad_FLOAT_Instance_t          *pBP_Instances;
     /* Points a nBands elements array that contains the band pass filter taps for each band */
     Biquad_1I_Order2_FLOAT_Taps_t    *pBP_Taps;
@@ -109,17 +92,11 @@
     QPD_FLOAT_State_t                *pQPD_States;
     /* Points a nBands elements array that contains the QPD filter taps for each band */
     QPD_FLOAT_Taps_t                 *pQPD_Taps;
-#endif
 
-#ifndef BUILD_FLOAT
-    LVM_UINT16                 *pPostGains;                         /* Points a nBands elements array that contains the post-filter gains for each band             */
-#else
     /* Points a nBands elements array that contains the post-filter gains for each band */
     LVM_FLOAT                  *pPostGains;
-#endif
     LVPSA_FilterParam_t        *pFiltersParams;                     /* Copy of the filters parameters from the input parameters                                     */
 
-
     LVM_UINT16                  nSamplesBufferUpdate;               /* Number of samples to make 20ms                                                               */
     LVM_INT32                   BufferUpdateSamplesCount;           /* Counter used to know when to put a new value in the buffer                                   */
     LVM_UINT16                  nRelevantFilters;                   /* Number of relevent filters depending on sampling frequency and bands center frequency        */
@@ -140,8 +117,6 @@
 
 }LVPSA_InstancePr_t, *pLVPSA_InstancePr_t;
 
-
-
 /**********************************************************************************
    FUNCTIONS PROTOTYPE
 ***********************************************************************************/
@@ -162,8 +137,4 @@
 /************************************************************************************/
 LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t     *pInst);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* _LVPSA_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
deleted file mode 100644
index 61899fe..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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    "LVPSA.h"
-#include    "LVPSA_Private.h"
-#include    "LVM_Macros.h"
-#include    "VectorArithmetic.h"
-
-#define LVM_MININT_32   0x80000000
-
-static LVM_INT32 mult32x32in32_shiftr(LVM_INT32 a, LVM_INT32 b, LVM_INT32 c) {
-  LVM_INT64 result = ((LVM_INT64)a * b) >> c;
-
-  if (result >= INT32_MAX) {
-    return INT32_MAX;
-  } else if (result <= INT32_MIN) {
-    return INT32_MIN;
-  } else {
-    return (LVM_INT32)result;
-  }
-}
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_Process                                               */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  The process applies band pass filters to the signal. Each output                */
-/*  feeds a quasi peak filter for level detection.                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance           Pointer to the instance                                     */
-/*  pLVPSA_InputSamples Pointer to the input samples buffer                         */
-/*  InputBlockSize      Number of mono samples to process                           */
-/*  AudioTime           Playback time of the input samples                          */
-/*                                                                                  */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
-                                       LVM_FLOAT           *pLVPSA_InputSamples,
-                                       LVM_UINT16           InputBlockSize,
-                                       LVPSA_Time           AudioTime            )
-
-{
-    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-    LVM_FLOAT               *pScratch;
-    LVM_INT16               ii;
-    LVM_INT32               AudioTimeInc;
-    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
-    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer
-                                                     at the beginning of the process  */
-
-    /******************************************************************************
-       CHECK PARAMETERS
-    *******************************************************************************/
-    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
-    {
-        return(LVPSA_ERROR_INVALIDPARAM);
-    }
-
-    pScratch = (LVM_FLOAT*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
-    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
-
-    /******************************************************************************
-       APPLY NEW SETTINGS IF NEEDED
-    *******************************************************************************/
-    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
-    {
-        pLVPSA_Inst->bControlPending = 0;
-        LVPSA_ApplyNewSettings( pLVPSA_Inst);
-    }
-
-    /******************************************************************************
-       PROCESS SAMPLES
-    *******************************************************************************/
-    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
-    Copy_Float(pLVPSA_InputSamples, pScratch, (LVM_INT16)InputBlockSize);
-    Shift_Sat_Float(-1, pScratch, pScratch, (LVM_INT16)InputBlockSize);
-
-    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
-    {
-        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
-        {
-            case LVPSA_SimplePrecisionFilter:
-                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
-                                              pScratch,
-                                              pScratch + InputBlockSize,
-                                              (LVM_INT16)InputBlockSize);
-                break;
-
-            case LVPSA_DoublePrecisionFilter:
-                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
-                                              pScratch,
-                                              pScratch + InputBlockSize,
-                                              (LVM_INT16)InputBlockSize);
-                break;
-            default:
-                break;
-        }
-
-
-        LVPSA_QPD_Process_Float   ( pLVPSA_Inst,
-                                    pScratch + InputBlockSize,
-                                    (LVM_INT16)InputBlockSize,
-                                    ii);
-    }
-
-    /******************************************************************************
-       UPDATE SpectralDataBufferAudioTime
-    *******************************************************************************/
-
-    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
-    {
-        AudioTimeInc = mult32x32in32_shiftr(
-                (AudioTime + ((LVM_INT32)pLVPSA_Inst->LocalSamplesCount * 1000)),
-                (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
-                LVPSA_FsInvertShift);
-        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
-    }
-
-    return(LVPSA_OK);
-}
-#else
-LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
-                                       LVM_INT16           *pLVPSA_InputSamples,
-                                       LVM_UINT16           InputBlockSize,
-                                       LVPSA_Time           AudioTime            )
-
-{
-    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-    LVM_INT16               *pScratch;
-    LVM_INT16               ii;
-    LVM_INT32               AudioTimeInc;
-    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
-    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer at the beginning of the process  */
-
-    /******************************************************************************
-       CHECK PARAMETERS
-    *******************************************************************************/
-    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
-    {
-        return(LVPSA_ERROR_INVALIDPARAM);
-    }
-
-    pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
-    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
-
-    /******************************************************************************
-       APPLY NEW SETTINGS IF NEEDED
-    *******************************************************************************/
-    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
-    {
-        pLVPSA_Inst->bControlPending = 0;
-        LVPSA_ApplyNewSettings( pLVPSA_Inst);
-    }
-
-    /******************************************************************************
-       PROCESS SAMPLES
-    *******************************************************************************/
-    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
-    Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
-    Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
-
-    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
-    {
-        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
-        {
-            case LVPSA_SimplePrecisionFilter:
-                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
-                                              pScratch,
-                                              pScratch + InputBlockSize,
-                                              (LVM_INT16)InputBlockSize);
-                break;
-
-            case LVPSA_DoublePrecisionFilter:
-                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
-                                              pScratch,
-                                              pScratch + InputBlockSize,
-                                              (LVM_INT16)InputBlockSize);
-                break;
-            default:
-                break;
-        }
-
-
-        LVPSA_QPD_Process   ( pLVPSA_Inst,
-                              pScratch + InputBlockSize,
-                              (LVM_INT16)InputBlockSize,
-                              ii);
-    }
-
-    /******************************************************************************
-       UPDATE SpectralDataBufferAudioTime
-    *******************************************************************************/
-
-    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
-    {
-        MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
-                        (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
-                        AudioTimeInc,
-                        LVPSA_FsInvertShift)
-        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
-    }
-
-    return(LVPSA_OK);
-}
-#endif
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_GetSpectrum                                           */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Gets the levels values at a certain point in time                               */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance            Pointer to the instance                                    */
-/*  GetSpectrumAudioTime Retrieve the values at this time                           */
-/*  pCurrentValues       Pointer to a buffer that will contain levels' values       */
-/*  pMaxValues           Pointer to a buffer that will contain max levels' values   */
-/*                                                                                  */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVPSA_OK            Succeeds                                                    */
-/*  otherwise           Error due to bad parameters                                 */
-/*                                                                                  */
-/************************************************************************************/
-LVPSA_RETURN LVPSA_GetSpectrum       ( pLVPSA_Handle_t      hInstance,
-                                       LVPSA_Time           GetSpectrumAudioTime,
-                                       LVM_UINT8           *pCurrentValues,
-                                       LVM_UINT8           *pPeakValues           )
-
-{
-
-    LVPSA_InstancePr_t      *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-    LVM_INT32               StatusDelta, ii;
-    LVM_UINT8               *pRead;
-
-    if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
-    {
-        return(LVPSA_ERROR_NULLADDRESS);
-    }
-
-
-    /* First find the place where to look in the status buffer */
-    if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
-    {
-        MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
-        if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
-        {
-            StatusDelta += 1;
-        }
-    }
-    else
-    {
-        /* This part handles the wrap around */
-        MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
-        if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
-        {
-            StatusDelta += 1;
-        }
-    }
-    /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
-    if(
-        ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
-         ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
-         (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
-
-         ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
-         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
-          ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
-         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
-         (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
-
-        (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
-        (!StatusDelta))
-    {
-        for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
-        {
-            pCurrentValues[ii]  = 0;
-            pPeakValues[ii]      = 0;
-        }
-        return(LVPSA_OK);
-    }
-    /* Set the reading pointer */
-    if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
-    {
-        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
-    }
-    else
-    {
-        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer  - StatusDelta * pLVPSA_Inst->nBands;
-    }
-
-
-    /* Read the status buffer and fill the output buffers */
-    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
-    {
-        pCurrentValues[ii] = pRead[ii];
-        if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
-        {
-            pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
-        }
-        else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
-        {
-            LVM_INT32 temp;
-            /*Re-compute max values for decay */
-            temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
-            temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
-            /* If the gain has no effect, "help" the value to increase */
-            if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
-            {
-                temp += 1;
-            }
-            /* Saturate */
-            temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
-            /* Store new max level */
-            pLVPSA_Inst->pPreviousPeaks[ii] =  (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
-        }
-
-        pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
-    }
-
-    return(LVPSA_OK);
-}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
new file mode 100644
index 0000000..81a88c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "LVM_Macros.h"
+#include    "VectorArithmetic.h"
+
+#define LVM_MININT_32   0x80000000
+
+static LVM_INT32 mult32x32in32_shiftr(LVM_INT32 a, LVM_INT32 b, LVM_INT32 c) {
+  LVM_INT64 result = ((LVM_INT64)a * b) >> c;
+
+  if (result >= INT32_MAX) {
+    return INT32_MAX;
+  } else if (result <= INT32_MIN) {
+    return INT32_MIN;
+  } else {
+    return (LVM_INT32)result;
+  }
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Process                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  The process applies band pass filters to the signal. Each output                */
+/*  feeds a quasi peak filter for level detection.                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance           Pointer to the instance                                     */
+/*  pLVPSA_InputSamples Pointer to the input samples buffer                         */
+/*  InputBlockSize      Number of mono samples to process                           */
+/*  AudioTime           Playback time of the input samples                          */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
+                                       LVM_FLOAT           *pLVPSA_InputSamples,
+                                       LVM_UINT16           InputBlockSize,
+                                       LVPSA_Time           AudioTime            )
+
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    LVM_FLOAT               *pScratch;
+    LVM_INT16               ii;
+    LVM_INT32               AudioTimeInc;
+    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
+    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer
+                                                     at the beginning of the process  */
+
+    /******************************************************************************
+       CHECK PARAMETERS
+    *******************************************************************************/
+    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+
+    pScratch = (LVM_FLOAT*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
+    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+
+    /******************************************************************************
+       APPLY NEW SETTINGS IF NEEDED
+    *******************************************************************************/
+    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
+    {
+        pLVPSA_Inst->bControlPending = 0;
+        LVPSA_ApplyNewSettings( pLVPSA_Inst);
+    }
+
+    /******************************************************************************
+       PROCESS SAMPLES
+    *******************************************************************************/
+    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
+    Copy_Float(pLVPSA_InputSamples, pScratch, (LVM_INT16)InputBlockSize);
+    Shift_Sat_Float(-1, pScratch, pScratch, (LVM_INT16)InputBlockSize);
+
+    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
+    {
+        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
+        {
+            case LVPSA_SimplePrecisionFilter:
+                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+
+            case LVPSA_DoublePrecisionFilter:
+                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+            default:
+                break;
+        }
+
+        LVPSA_QPD_Process_Float   ( pLVPSA_Inst,
+                                    pScratch + InputBlockSize,
+                                    (LVM_INT16)InputBlockSize,
+                                    ii);
+    }
+
+    /******************************************************************************
+       UPDATE SpectralDataBufferAudioTime
+    *******************************************************************************/
+
+    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
+    {
+        AudioTimeInc = mult32x32in32_shiftr(
+                (AudioTime + ((LVM_INT32)pLVPSA_Inst->LocalSamplesCount * 1000)),
+                (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+                LVPSA_FsInvertShift);
+        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
+    }
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetSpectrum                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Gets the levels values at a certain point in time                               */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance            Pointer to the instance                                    */
+/*  GetSpectrumAudioTime Retrieve the values at this time                           */
+/*  pCurrentValues       Pointer to a buffer that will contain levels' values       */
+/*  pMaxValues           Pointer to a buffer that will contain max levels' values   */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum       ( pLVPSA_Handle_t      hInstance,
+                                       LVPSA_Time           GetSpectrumAudioTime,
+                                       LVM_UINT8           *pCurrentValues,
+                                       LVM_UINT8           *pPeakValues           )
+
+{
+
+    LVPSA_InstancePr_t      *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    LVM_INT32               StatusDelta, ii;
+    LVM_UINT8               *pRead;
+
+    if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    /* First find the place where to look in the status buffer */
+    if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
+    {
+        MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
+        if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
+        {
+            StatusDelta += 1;
+        }
+    }
+    else
+    {
+        /* This part handles the wrap around */
+        MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
+        if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
+        {
+            StatusDelta += 1;
+        }
+    }
+    /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
+    if(
+        ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+         ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
+         (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
+
+         ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
+          ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
+         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
+         (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
+
+        (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
+        (!StatusDelta))
+    {
+        for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+        {
+            pCurrentValues[ii]  = 0;
+            pPeakValues[ii]      = 0;
+        }
+        return(LVPSA_OK);
+    }
+    /* Set the reading pointer */
+    if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
+    {
+        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
+    }
+    else
+    {
+        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer  - StatusDelta * pLVPSA_Inst->nBands;
+    }
+
+    /* Read the status buffer and fill the output buffers */
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pCurrentValues[ii] = pRead[ii];
+        if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
+        {
+            pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
+        }
+        else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
+        {
+            LVM_INT32 temp;
+            /*Re-compute max values for decay */
+            temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
+            temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
+            /* If the gain has no effect, "help" the value to increase */
+            if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
+            {
+                temp += 1;
+            }
+            /* Saturate */
+            temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
+            /* Store new max level */
+            pLVPSA_Inst->pPreviousPeaks[ii] =  (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
+        }
+
+        pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
+    }
+
+    return(LVPSA_OK);
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
index 99d844b..609a485 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -20,25 +20,18 @@
 
 #include "LVM_Types.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 typedef struct
 {
   LVM_INT32                            *pDelay;        /* pointer to the delayed samples (data of 32 bits)   */
   LVM_INT32                            Coefs[2];       /* pointer to the filter coefficients */
 }QPD_State_t, *pQPD_State_t;
 
-#ifdef BUILD_FLOAT
 typedef struct
 {
     /* pointer to the delayed samples (data of 32 bits)   */
     LVM_FLOAT                            *pDelay;
     LVM_FLOAT                            Coefs[2];       /* pointer to the filter coefficients */
 }QPD_FLOAT_State_t, *pQPD_FLOAT_State_t;
-#endif
 
 typedef struct
 {
@@ -47,15 +40,12 @@
 
 } QPD_C32_Coefs, *PQPD_C32_Coefs;
 
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT KP;    /*should store a0*/
     LVM_FLOAT KM;    /*should store b2*/
 
 } QPD_FLOAT_Coefs, *PQPD_FLOAT_Coefs;
-#endif
-
 
 typedef struct
 {
@@ -63,14 +53,12 @@
 
 } QPD_Taps_t, *pQPD_Taps_t;
 
-#ifdef BUILD_FLOAT
 typedef struct
 {
     LVM_FLOAT Storage[1];
 
 } QPD_FLOAT_Taps_t, *pQPD_FLOAT_Taps_t;
 
-#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_Process                                           */
@@ -89,12 +77,10 @@
                                     LVM_INT16                           numSamples,
                                     LVM_INT16                           BandIndex);
 
-#ifdef BUILD_FLOAT
 void LVPSA_QPD_Process_Float (      void                               *hInstance,
                                     LVM_FLOAT                          *pInSamps,
                                     LVM_INT16                           numSamples,
                                     LVM_INT16                           BandIndex);
-#endif
 /************************************************************************************/
 /*                                                                                  */
 /* FUNCTION:            LVPSA_QPD_Init                                              */
@@ -113,15 +99,10 @@
 void LVPSA_QPD_Init (   QPD_State_t       *pInstance,
                         QPD_Taps_t        *pTaps,
                         QPD_C32_Coefs     *pCoef     );
-#ifdef BUILD_FLOAT
 
 void LVPSA_QPD_Init_Float (   QPD_FLOAT_State_t       *pInstance,
                               QPD_FLOAT_Taps_t        *pTaps,
                               QPD_FLOAT_Coefs         *pCoef     );
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
deleted file mode 100644
index 2cc32ab..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVPSA_QPD.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_QPD_Init                                              */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialize a quasi peak filter instance.                                        */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pQPD_State          Pointer to the filter state                                 */
-/*   pTaps               Pointer to the filter's taps                               */
-/*   pCoef               Pointer to the filter's coefficients                       */
-/*                                                                                  */
-/* RETURNS:     void                                                                */
-/*                                                                                  */
-/************************************************************************************/
-void LVPSA_QPD_Init (   pQPD_State_t       pQPD_State,
-                        QPD_Taps_t        *pTaps,
-                        QPD_C32_Coefs     *pCoef     )
-{
-    pQPD_State->pDelay  = pTaps->Storage;
-    pQPD_State->Coefs[0]  = pCoef->KP;
-    pQPD_State->Coefs[1]  = pCoef->KM;
-}
-
-#ifdef BUILD_FLOAT
-void LVPSA_QPD_Init_Float (   pQPD_FLOAT_State_t       pQPD_State,
-                              QPD_FLOAT_Taps_t         *pTaps,
-                              QPD_FLOAT_Coefs          *pCoef     )
-{
-    pQPD_State->pDelay  = pTaps->Storage;
-    pQPD_State->Coefs[0]  = ((LVM_FLOAT)pCoef->KP);
-    pQPD_State->Coefs[1]  = ((LVM_FLOAT)pCoef->KM);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.cpp
new file mode 100644
index 0000000..2dbf694
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVPSA_QPD.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Init                                              */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialize a quasi peak filter instance.                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pQPD_State          Pointer to the filter state                                 */
+/*   pTaps               Pointer to the filter's taps                               */
+/*   pCoef               Pointer to the filter's coefficients                       */
+/*                                                                                  */
+/* RETURNS:     void                                                                */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Init (   pQPD_State_t       pQPD_State,
+                        QPD_Taps_t        *pTaps,
+                        QPD_C32_Coefs     *pCoef     )
+{
+    pQPD_State->pDelay  = pTaps->Storage;
+    pQPD_State->Coefs[0]  = pCoef->KP;
+    pQPD_State->Coefs[1]  = pCoef->KM;
+}
+
+void LVPSA_QPD_Init_Float (   pQPD_FLOAT_State_t       pQPD_State,
+                              QPD_FLOAT_Taps_t         *pTaps,
+                              QPD_FLOAT_Coefs          *pCoef     )
+{
+    pQPD_State->pDelay  = pTaps->Storage;
+    pQPD_State->Coefs[0]  = ((LVM_FLOAT)pCoef->KP);
+    pQPD_State->Coefs[1]  = ((LVM_FLOAT)pCoef->KM);
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
deleted file mode 100644
index e233172..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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 "LVPSA_QPD.h"
-#include "LVPSA_Private.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Write a level value in the buffer in the corresponding band.                    */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pInst               Pointer to the LVPSA instance                               */
-/*  ppWrite             Pointer to pointer to the buffer                            */
-/*  CallNumber          Number of the band the value should be written in           */
-/*  Value               Value to write in the buffer                                */
-/*                                                                                  */
-/* RETURNS:             void                                                        */
-/*                                                                                  */
-/************************************************************************************/
-void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
-                            LVM_UINT8                 **ppWrite,
-                            LVM_INT16                 BandIndex,
-                            LVM_INT16                 Value   );
-
-#ifdef BUILD_FLOAT
-void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t       pLVPSA_Inst,
-                                  LVM_UINT8             **ppWrite,
-                                  LVM_INT16               BandIndex,
-                                  LVM_FLOAT               Value   );
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_QPD_Process                                           */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Apply downsampling, post gain, quasi peak filtering and write the levels values */
-/*  in the buffer every 20 ms.                                                      */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*                                                                                  */
-/* RETURNS:             void                                                        */
-/*                                                                                  */
-/************************************************************************************/
-#ifndef BUILD_FLOAT
-void LVPSA_QPD_Process (            void                               *hInstance,
-                                    LVM_INT16                          *pInSamps,
-                                    LVM_INT16                           numSamples,
-                                    LVM_INT16                           BandIndex)
-{
-
-    /******************************************************************************
-       PARAMETERS
-    *******************************************************************************/
-    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-    QPD_State_t *pQPDState =  (QPD_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
-
-    /* Pointer to taps */
-    LVM_INT32* pDelay  = pQPDState->pDelay;
-
-    /* Parameters needed during quasi peak calculations */
-    LVM_INT32   X0;
-    LVM_INT32   temp,temp2;
-    LVM_INT32   accu;
-    LVM_INT16   Xg0;
-    LVM_INT16   D0;
-    LVM_INT16   V0 = (LVM_INT16)(*pDelay);
-
-    /* Filter's coef */
-    LVM_INT32   Kp = pQPDState->Coefs[0];
-    LVM_INT32   Km = pQPDState->Coefs[1];
-
-    LVM_INT16   ii = numSamples;
-
-    LVM_UINT8  *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
-    LVM_INT32   BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
-    LVM_UINT16  DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
-
-    /******************************************************************************
-       INITIALIZATION
-    *******************************************************************************/
-    /* Correct the pointer to take the first down sampled signal sample */
-    pInSamps += pLVPSA_Inst->DownSamplingCount;
-    /* Correct also the number of samples */
-    ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
-
-    while (ii > 0)
-    {
-        /* Apply post gain */
-        X0 = ((*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex]) >> (LVPSA_GAINSHIFT-1); /* - 1 to compensate scaling in process function*/
-        pInSamps = pInSamps + DownSamplingFactor;
-
-        /* Saturate and take absolute value */
-        if(X0 < 0)
-            X0 = -X0;
-        if (X0 > 0x7FFF)
-            Xg0 = 0x7FFF;
-        else
-            Xg0 = (LVM_INT16)(X0);
-
-
-        /* Quasi peak filter calculation */
-        D0  = (LVM_INT16)(Xg0 - V0);
-
-        temp2 = (LVM_INT32)D0;
-        MUL32x32INTO32(temp2,Kp,accu,31);
-
-        D0    = (LVM_INT16)(D0>>1);
-        if (D0 < 0){
-            D0 = (LVM_INT16)(-D0);
-        }
-
-        temp2 = (LVM_INT32)D0;
-        MUL32x32INTO32((LVM_INT32)D0,Km,temp,31);
-        accu +=temp + Xg0;
-
-        if (accu > 0x7FFF)
-            accu = 0x7FFF;
-        else if(accu < 0)
-            accu = 0x0000;
-
-        V0 = (LVM_INT16)accu;
-
-        if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
-        {
-            LVPSA_QPD_WritePeak( pLVPSA_Inst,
-                                &pWrite,
-                                 BandIndex,
-                                 V0);
-            BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
-            pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
-        }
-        BufferUpdateSamplesCount+=DownSamplingFactor;
-
-        ii = (LVM_INT16)(ii-DownSamplingFactor);
-
-    }
-
-    /* Store last taps in memory */
-    *pDelay = (LVM_INT32)(V0);
-
-    /* If this is the last call to the function after last band processing,
-       update the parameters. */
-    if(BandIndex == (pLVPSA_Inst->nRelevantFilters-1))
-    {
-        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
-        /* Adjustment for 11025Hz input, 220,5 is normally
-           the exact number of samples for 20ms.*/
-        if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&(pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
-        {
-            if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
-            {
-                pLVPSA_Inst->nSamplesBufferUpdate = 221;
-            }
-            else
-            {
-                pLVPSA_Inst->nSamplesBufferUpdate = 220;
-            }
-        }
-        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
-        pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
-        pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
-    }
-}
-#else
-void LVPSA_QPD_Process_Float (      void                               *hInstance,
-                                    LVM_FLOAT                          *pInSamps,
-                                    LVM_INT16                           numSamples,
-                                    LVM_INT16                           BandIndex)
-{
-
-    /******************************************************************************
-       PARAMETERS
-    *******************************************************************************/
-    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
-    QPD_FLOAT_State_t *pQPDState =  (QPD_FLOAT_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
-
-    /* Pointer to taps */
-    LVM_FLOAT* pDelay  = pQPDState->pDelay;
-
-    /* Parameters needed during quasi peak calculations */
-    LVM_FLOAT   X0;
-    LVM_FLOAT   temp,temp2;
-    LVM_FLOAT   accu;
-    LVM_FLOAT   Xg0;
-    LVM_FLOAT   D0;
-    LVM_FLOAT   V0 = (LVM_FLOAT)(*pDelay);
-
-    /* Filter's coef */
-    LVM_FLOAT   Kp = ((LVM_FLOAT)(pQPDState->Coefs[0]));
-    LVM_FLOAT   Km = ((LVM_FLOAT)(pQPDState->Coefs[1]));
-
-    LVM_INT16   ii = numSamples;
-
-    LVM_UINT8  *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
-    LVM_INT32   BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
-    LVM_UINT16  DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
-
-    /******************************************************************************
-       INITIALIZATION
-    *******************************************************************************/
-    /* Correct the pointer to take the first down sampled signal sample */
-    pInSamps += pLVPSA_Inst->DownSamplingCount;
-    /* Correct also the number of samples */
-    ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
-
-    while (ii > 0)
-    {
-        /* Apply post gain */
-        /* - 1 to compensate scaling in process function*/
-        X0 = (*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex];
-        pInSamps = pInSamps + DownSamplingFactor;
-
-        /* Saturate and take absolute value */
-        if(X0 < 0.0f)
-            X0 = -X0;
-        if (X0 > 1.0f)
-            Xg0 = 1.0f;
-        else
-            Xg0 =X0;
-
-
-        /* Quasi peak filter calculation */
-        D0  = Xg0 - V0;
-
-        temp2 = D0;
-
-        accu = temp2 * Kp;
-        D0    = D0 / 2.0f;
-        if (D0 < 0.0f){
-            D0 = -D0;
-        }
-
-        temp2 = D0;
-
-        temp = D0 * Km;
-        accu += temp + Xg0;
-
-        if (accu > 1.0f)
-            accu = 1.0f;
-        else if(accu < 0.0f)
-            accu = 0.0f;
-
-        V0 = accu;
-
-        if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
-        {
-            LVPSA_QPD_WritePeak_Float( pLVPSA_Inst,
-                                       &pWrite,
-                                       BandIndex,
-                                       V0);
-
-            BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
-            pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
-        }
-        BufferUpdateSamplesCount += DownSamplingFactor;
-
-        ii = (LVM_INT16)(ii - DownSamplingFactor);
-
-    }
-
-    /* Store last taps in memory */
-    *pDelay = V0;
-
-    /* If this is the last call to the function after last band processing,
-       update the parameters. */
-    if(BandIndex == (pLVPSA_Inst->nRelevantFilters - 1))
-    {
-        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
-        /* Adjustment for 11025Hz input, 220,5 is normally
-           the exact number of samples for 20ms.*/
-        if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&
-                                        (pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
-        {
-            if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
-            {
-                pLVPSA_Inst->nSamplesBufferUpdate = 221;
-            }
-            else
-            {
-                pLVPSA_Inst->nSamplesBufferUpdate = 220;
-            }
-        }
-        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
-        pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
-        pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
-    }
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Write a level value in the spectrum data buffer in the corresponding band.      */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  pLVPSA_Inst               Pointer to the LVPSA instance                         */
-/*  ppWrite             Pointer to pointer to the buffer                            */
-/*  CallNumber          Number of the band the value should be written in           */
-/*  Value               Value to write in the spectrum data buffer                  */
-/*                                                                                  */
-/* RETURNS:             void                                                        */
-/*                                                                                  */
-/************************************************************************************/
-void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
-                            LVM_UINT8             **ppWrite,
-                            LVM_INT16               BandIndex,
-                            LVM_INT16               Value   )
-{
-    LVM_UINT8 *pWrite = *ppWrite;
-
-
-    /* Write the value and update the write pointer */
-    *(pWrite + BandIndex) = (LVM_UINT8)(Value>>7);
-    pWrite += pLVPSA_Inst->nBands;
-    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * pLVPSA_Inst->SpectralDataBufferLength))
-    {
-        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
-    }
-
-    *ppWrite = pWrite;
-
-}
-#ifdef BUILD_FLOAT
-void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t     pLVPSA_Inst,
-                                  LVM_UINT8               **ppWrite,
-                                  LVM_INT16               BandIndex,
-                                  LVM_FLOAT               Value   )
-{
-    LVM_UINT8 *pWrite = *ppWrite;
-
-    /* Write the value and update the write pointer */
-    *(pWrite + BandIndex) = (LVM_UINT8)(Value * 256);
-    pWrite += pLVPSA_Inst->nBands;
-    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * \
-                                    pLVPSA_Inst->SpectralDataBufferLength))
-    {
-        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
-    }
-
-    *ppWrite = pWrite;
-}
-#endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.cpp
new file mode 100644
index 0000000..8805420
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 "LVPSA_QPD.h"
+#include "LVPSA_Private.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Write a level value in the buffer in the corresponding band.                    */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the LVPSA instance                               */
+/*  ppWrite             Pointer to pointer to the buffer                            */
+/*  CallNumber          Number of the band the value should be written in           */
+/*  Value               Value to write in the buffer                                */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                            LVM_UINT8                 **ppWrite,
+                            LVM_INT16                 BandIndex,
+                            LVM_INT16                 Value   );
+
+void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                                  LVM_UINT8             **ppWrite,
+                                  LVM_INT16               BandIndex,
+                                  LVM_FLOAT               Value   );
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Process                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/*  in the buffer every 20 ms.                                                      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Process_Float (      void                               *hInstance,
+                                    LVM_FLOAT                          *pInSamps,
+                                    LVM_INT16                           numSamples,
+                                    LVM_INT16                           BandIndex)
+{
+
+    /******************************************************************************
+       PARAMETERS
+    *******************************************************************************/
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    QPD_FLOAT_State_t *pQPDState =  (QPD_FLOAT_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
+
+    /* Pointer to taps */
+    LVM_FLOAT* pDelay  = pQPDState->pDelay;
+
+    /* Parameters needed during quasi peak calculations */
+    LVM_FLOAT   X0;
+    LVM_FLOAT   temp,temp2;
+    LVM_FLOAT   accu;
+    LVM_FLOAT   Xg0;
+    LVM_FLOAT   D0;
+    LVM_FLOAT   V0 = (LVM_FLOAT)(*pDelay);
+
+    /* Filter's coef */
+    LVM_FLOAT   Kp = ((LVM_FLOAT)(pQPDState->Coefs[0]));
+    LVM_FLOAT   Km = ((LVM_FLOAT)(pQPDState->Coefs[1]));
+
+    LVM_INT16   ii = numSamples;
+
+    LVM_UINT8  *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+    LVM_INT32   BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
+    LVM_UINT16  DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
+
+    /******************************************************************************
+       INITIALIZATION
+    *******************************************************************************/
+    /* Correct the pointer to take the first down sampled signal sample */
+    pInSamps += pLVPSA_Inst->DownSamplingCount;
+    /* Correct also the number of samples */
+    ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
+
+    while (ii > 0)
+    {
+        /* Apply post gain */
+        /* - 1 to compensate scaling in process function*/
+        X0 = (*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex];
+        pInSamps = pInSamps + DownSamplingFactor;
+
+        /* Saturate and take absolute value */
+        if(X0 < 0.0f)
+            X0 = -X0;
+        if (X0 > 1.0f)
+            Xg0 = 1.0f;
+        else
+            Xg0 =X0;
+
+        /* Quasi peak filter calculation */
+        D0  = Xg0 - V0;
+
+        temp2 = D0;
+
+        accu = temp2 * Kp;
+        D0    = D0 / 2.0f;
+        if (D0 < 0.0f){
+            D0 = -D0;
+        }
+
+        temp2 = D0;
+
+        temp = D0 * Km;
+        accu += temp + Xg0;
+
+        if (accu > 1.0f)
+            accu = 1.0f;
+        else if(accu < 0.0f)
+            accu = 0.0f;
+
+        V0 = accu;
+
+        if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
+        {
+            LVPSA_QPD_WritePeak_Float( pLVPSA_Inst,
+                                       &pWrite,
+                                       BandIndex,
+                                       V0);
+
+            BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
+            pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
+        }
+        BufferUpdateSamplesCount += DownSamplingFactor;
+
+        ii = (LVM_INT16)(ii - DownSamplingFactor);
+
+    }
+
+    /* Store last taps in memory */
+    *pDelay = V0;
+
+    /* If this is the last call to the function after last band processing,
+       update the parameters. */
+    if(BandIndex == (pLVPSA_Inst->nRelevantFilters - 1))
+    {
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        /* Adjustment for 11025Hz input, 220,5 is normally
+           the exact number of samples for 20ms.*/
+        if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&
+                                        (pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
+        {
+            if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 221;
+            }
+            else
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 220;
+            }
+        }
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
+        pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
+    }
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Write a level value in the spectrum data buffer in the corresponding band.      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pLVPSA_Inst               Pointer to the LVPSA instance                         */
+/*  ppWrite             Pointer to pointer to the buffer                            */
+/*  CallNumber          Number of the band the value should be written in           */
+/*  Value               Value to write in the spectrum data buffer                  */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                            LVM_UINT8             **ppWrite,
+                            LVM_INT16               BandIndex,
+                            LVM_INT16               Value   )
+{
+    LVM_UINT8 *pWrite = *ppWrite;
+
+    /* Write the value and update the write pointer */
+    *(pWrite + BandIndex) = (LVM_UINT8)(Value>>7);
+    pWrite += pLVPSA_Inst->nBands;
+    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * pLVPSA_Inst->SpectralDataBufferLength))
+    {
+        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+    }
+
+    *ppWrite = pWrite;
+
+}
+void LVPSA_QPD_WritePeak_Float(   pLVPSA_InstancePr_t     pLVPSA_Inst,
+                                  LVM_UINT8               **ppWrite,
+                                  LVM_INT16               BandIndex,
+                                  LVM_FLOAT               Value   )
+{
+    LVM_UINT8 *pWrite = *ppWrite;
+
+    /* Write the value and update the write pointer */
+    *(pWrite + BandIndex) = (LVM_UINT8)(Value * 256);
+    pWrite += pLVPSA_Inst->nBands;
+    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * \
+                                    pLVPSA_Inst->SpectralDataBufferLength))
+    {
+        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+    }
+
+    *ppWrite = pWrite;
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
deleted file mode 100644
index f8af496..0000000
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVPSA.h"
-#include "LVPSA_QPD.h"
-/************************************************************************************/
-/*                                                                                  */
-/*  Sample rate table                                                               */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Sample rate table for converting between the enumerated type and the actual
- * frequency
- */
-#ifndef HIGHER_FS
-const LVM_UINT16    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
-                                                11025,
-                                                12000,
-                                                16000,
-                                                22050,
-                                                24000,
-                                                32000,
-                                                44100,
-                                                48000};                  /* 48kS/s */
-#else
-const LVM_UINT32    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
-                                                11025,
-                                                12000,
-                                                16000,
-                                                22050,
-                                                24000,
-                                                32000,
-                                                44100,
-                                                48000,
-                                                88200,
-                                                96000,
-                                               176400,
-                                               192000};                  /* 192kS/s */
-#endif
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Sample rate inverse table                                                       */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Sample rate table for converting between the enumerated type and the actual
- * frequency
- */
-const LVM_UINT32    LVPSA_SampleRateInvTab[] = {    268435,                    /* 8kS/s  */
-                                                    194783,
-                                                    178957,
-                                                    134218,
-                                                    97391,
-                                                    89478,
-                                                    67109,
-                                                    48696,
-                                                    44739
-#ifdef HIGHER_FS
-                                                    ,24348
-                                                    ,22369
-                                                    ,12174
-                                                    ,11185                  /* 192kS/s */
-#endif
-                                               };
-
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Number of samples in 20ms                                                       */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Table for converting between the enumerated type and the number of samples
- * during 20ms
- */
-const LVM_UINT16    LVPSA_nSamplesBufferUpdate[]  = {   160,                   /* 8kS/s  */
-                                                        220,
-                                                        240,
-                                                        320,
-                                                        441,
-                                                        480,
-                                                        640,
-                                                        882,
-                                                        960
-#ifdef HIGHER_FS
-                                                        ,1764
-                                                        ,1920
-                                                        ,3528
-                                                        ,3840                  /* 192kS/s */
-#endif
-                                                    };
-/************************************************************************************/
-/*                                                                                  */
-/*  Down sampling factors                                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Table for converting between the enumerated type and the down sampling factor
- */
-const LVM_UINT16    LVPSA_DownSamplingFactor[]  = {     5,                    /* 8000  S/s  */
-                                                        7,                    /* 11025 S/s  */
-                                                        8,                    /* 12000 S/s  */
-                                                        10,                   /* 16000 S/s  */
-                                                        15,                   /* 22050 S/s  */
-                                                        16,                   /* 24000 S/s  */
-                                                        21,                   /* 32000 S/s  */
-                                                        30,                   /* 44100 S/s  */
-                                                        32                    /* 48000 S/s  */
-#ifdef HIGHER_FS
-                                                       ,60                   /* 88200 S/s  */
-                                                       ,64                   /* 96000 S/s  */
-                                                       ,120                  /* 176400 S/s  */
-                                                       ,128                  /*192000 S/s  */
-#endif
-                                                  };
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Coefficient calculation tables                                                  */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Table for 2 * Pi / Fs
- */
-const LVM_INT16     LVPSA_TwoPiOnFsTable[] = {  26354,      /* 8kS/s */
-                                                19123,
-                                                17569,
-                                                13177,
-                                                 9561,
-                                                 8785,
-                                                 6588,
-                                                 4781,
-                                                 4392
-#ifdef HIGHER_FS
-                                                ,2390
-                                                ,2196
-                                                ,1195
-                                                ,1098    /* 192kS/s */
-#endif
-                                             };
-
-#ifdef BUILD_FLOAT
-const LVM_FLOAT     LVPSA_Float_TwoPiOnFsTable[] = {  0.8042847f,      /* 8kS/s */
-                                                      0.5836054f,
-                                                      0.5361796f,
-                                                      0.4021423f,
-                                                      0.2917874f,
-                                                      0.2681051f,
-                                                      0.2010559f,
-                                                      0.1459089f,
-                                                      0.1340372f
-#ifdef HIGHER_FS
-                                                     ,0.0729476f
-                                                     ,0.0670186f
-                                                     ,0.0364738f
-                                                     ,0.0335093f    /* 192kS/s */
-#endif
-                                                   };
-
-#endif
-/*
- * Gain table
- */
-const LVM_INT16     LVPSA_GainTable[] = {   364,          /* -15dB gain */
-                                            408,
-                                            458,
-                                            514,
-                                            577,
-                                            647,
-                                            726,
-                                            815,
-                                            914,
-                                            1026,
-                                            1151,
-                                            1292,
-                                            1449,
-                                            1626,
-                                            1825,
-                                            2048,         /* 0dB gain */
-                                            2297,
-                                            2578,
-                                            2892,
-                                            3245,
-                                            3641,
-                                            4096,
-                                            4584,
-                                            5144,
-                                            5772,
-                                            6476,
-                                            7266,
-                                            8153,
-                                            9148,
-                                            10264,
-                                            11576};        /* +15dB gain */
-
-#ifdef BUILD_FLOAT
-const LVM_FLOAT  LVPSA_Float_GainTable[]={  0.177734375f,          /* -15dB gain */
-                                            0.199218750f,
-                                            0.223632812f,
-                                            0.250976562f,
-                                            0.281738281f,
-                                            0.315917968f,
-                                            0.354492187f,
-                                            0.397949218f,
-                                            0.446289062f,
-                                            0.500976562f,
-                                            0.562011718f,
-                                            0.630859375f,
-                                            0.707519531f,
-                                            0.793945312f,
-                                            0.891113281f,
-                                            1.000000000f,         /* 0dB gain */
-                                            1.121582031f,
-                                            1.258789062f,
-                                            1.412109375f,
-                                            1.584472656f,
-                                            1.777832031f,
-                                            2.000000000f,
-                                            2.238281250f,
-                                            2.511718750f,
-                                            2.818359375f,
-                                            3.162109375f,
-                                            3.547851562f,
-                                            3.980957031f,
-                                            4.466796875f,
-                                            5.011718750f,
-                                            5.652343750f};        /* +15dB gain */
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/*  Cosone polynomial coefficients                                                  */
-/*                                                                                  */
-/************************************************************************************/
-
-/*
- * Coefficients for calculating the cosine with the equation:
- *
- *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
- *
- * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
- * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
- * +1.0 to -1.0
- */
-const LVM_INT16     LVPSA_CosCoef[] = { 3,                             /* Shifts */
-                                        4096,                          /* a0 */
-                                        -36,                           /* a1 */
-                                        -19725,                        /* a2 */
-                                        -2671,                         /* a3 */
-                                        23730,                         /* a4 */
-                                        -9490};                        /* a5 */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT     LVPSA_Float_CosCoef[] = { 3,                             /* Shifts */
-                                              0.1250038f,                          /* a0 */
-                                              -0.0010986f,                           /* a1 */
-                                              -0.6019775f,                        /* a2 */
-                                              -0.0815149f,                         /* a3 */
-                                              0.7242042f,                         /* a4 */
-                                              -0.2896206f};                        /* a5 */
-#endif
-/*
- * Coefficients for calculating the cosine error with the equation:
- *
- *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
- *
- * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
- * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
- * 0.0 to 0.0078852986
- *
- * This is used to give a double precision cosine over the range 0 to Pi/25 using the
- * the equation:
- *
- * Cos(x) = 1.0 - CosErr(x)
- */
-const LVM_INT16     LVPSA_DPCosCoef[] = {   1,                           /* Shifts */
-                                            0,                           /* a0 */
-                                            -6,                          /* a1 */
-                                            16586,                       /* a2 */
-                                            -44};                        /* a3 */
-#ifdef BUILD_FLOAT
-const LVM_FLOAT    LVPSA_Float_DPCosCoef[] = {1.0f,                        /* Shifts */
-                                              0.0f,                        /* a0 */
-                                              -0.00008311f,                 /* a1 */
-                                              0.50617999f,                 /* a2 */
-                                              -0.00134281f};                /* a3 */
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/*  Quasi peak filter coefficients table                                            */
-/*                                                                                  */
-/************************************************************************************/
-const QPD_C32_Coefs     LVPSA_QPD_Coefs[] = {
-
-                                         {0x80CEFD2B,0x00CB9B17},  /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
-                                         {0x80D242E7,0x00CED11D},
-                                         {0x80DCBAF5,0x00D91679},
-                                         {0x80CEFD2B,0x00CB9B17},
-                                         {0x80E13739,0x00DD7CD3},
-                                         {0x80DCBAF5,0x00D91679},
-                                         {0x80D94BAF,0x00D5B7E7},
-                                         {0x80E13739,0x00DD7CD3},
-                                         {0x80DCBAF5,0x00D91679},  /* 48kS/s */
-
-                                         {0x8587513D,0x055C22CF},  /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
-                                         {0x859D2967,0x0570F007},
-                                         {0x85E2EFAC,0x05B34D79},
-                                         {0x8587513D,0x055C22CF},
-                                         {0x8600C7B9,0x05CFA6CF},
-                                         {0x85E2EFAC,0x05B34D79},
-                                         {0x85CC1018,0x059D8F69},
-                                         {0x8600C7B9,0x05CFA6CF},//{0x8600C7B9,0x05CFA6CF},
-                                         {0x85E2EFAC,0x05B34D79},  /* 48kS/s */
-
-                                         {0xA115EA7A,0x1CDB3F5C},  /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
-                                         {0xA18475F0,0x1D2C83A2},
-                                         {0xA2E1E950,0x1E2A532E},
-                                         {0xA115EA7A,0x1CDB3F5C},
-                                         {0xA375B2C6,0x1E943BBC},
-                                         {0xA2E1E950,0x1E2A532E},
-                                         {0xA26FF6BD,0x1DD81530},
-                                         {0xA375B2C6,0x1E943BBC},
-                                         {0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
-
-#ifdef BUILD_FLOAT
-const QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[] = {
-
-                                         /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
-                                         {-0.9936831989325583f,0.0062135565094650f},
-                                         {-0.9935833332128823f,0.0063115493394434f},
-                                         {-0.9932638457976282f,0.0066249934025109f},
-                                         {-0.9936831989325583f,0.0062135565094650f},
-                                         {-0.9931269618682563f,0.0067592649720609f},
-                                         {-0.9932638457976282f,0.0066249934025109f},
-                                         {-0.9933686633594334f,0.0065221670083702f},
-                                         {-0.9931269618682563f,0.0067592649720609f},
-                                          /* 48kS/s */
-                                         {-0.9932638457976282f,0.0066249934025109f},
-#ifdef HIGHER_FS
-                                         {-0.9931269618682563f,0.0067592649720609f},
-                                         {-0.9932638457976282f,0.0066249934025109f},
-                                         {-0.9931269618682563f,0.0067592649720609f},
-                                         {-0.9932638457976282f,0.0066249934025109f},
-#endif
-                                         /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
-                                         {-0.9568079425953329f,0.0418742666952312f},
-                                         {-0.9561413046903908f,0.0425090822391212f},
-                                         {-0.9540119562298059f,0.0445343819446862f},
-                                         {-0.9568079425953329f,0.0418742666952312f},
-                                         {-0.9531011912040412f,0.0453995238058269f},
-                                         {-0.9540119562298059f,0.0445343819446862f},
-                                         {-0.9547099955379963f,0.0438708555884659f},
-                                          //{0x8600C7B9,0x05CFA6CF},
-                                         {-0.9531011912040412f,0.0453995238058269f},
-                                          /* 48kS/s */
-                                         {-0.9540119562298059f,0.0445343819446862f},
-#ifdef HIGHER_FS
-                                         {-0.9531011912040412f,0.0453995238058269f},
-                                         {-0.9540119562298059f,0.0445343819446862f},
-                                         {-0.9531011912040412f,0.0453995238058269f},
-                                         {-0.9540119562298059f,0.0445343819446862f},
-#endif
-                                          /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
-                                         {-0.7415186790749431f,0.2254409026354551f},
-                                         {-0.7381451204419136f,0.2279209652915597f},
-                                         {-0.7274807319045067f,0.2356666540727019f},
-                                         {-0.7415186790749431f,0.2254409026354551f},
-                                         {-0.7229706319049001f,0.2388987224549055f},
-                                         {-0.7274807319045067f,0.2356666540727019f},
-                                         {-0.7309581353329122f,0.2331568226218224f},
-                                         {-0.7229706319049001f,0.2388987224549055f},
-                                           /* 48kS/s */
-                                         {-0.7274807319045067f,0.2356666540727019f}
-#ifdef HIGHER_FS
-                                        ,{-0.7229706319049001f,0.2388987224549055f}
-                                        ,{-0.7274807319045067f,0.2356666540727019f}
-                                        ,{-0.7229706319049001f,0.2388987224549055f}
-                                        ,{-0.7274807319045067f,0.2356666540727019f}
-#endif
-                                        };
-#endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.cpp b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.cpp
new file mode 100644
index 0000000..9f0aa02
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVPSA.h"
+#include "LVPSA_QPD.h"
+#include "LVPSA_Tables.h"
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate table                                                               */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
+                                                11025,
+                                                12000,
+                                                16000,
+                                                22050,
+                                                24000,
+                                                32000,
+                                                44100,
+                                                48000,
+                                                88200,
+                                                96000,
+                                               176400,
+                                               192000};                  /* 192kS/s */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate inverse table                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32    LVPSA_SampleRateInvTab[] = {    268435,                    /* 8kS/s  */
+                                                    194783,
+                                                    178957,
+                                                    134218,
+                                                    97391,
+                                                    89478,
+                                                    67109,
+                                                    48696,
+                                                    44739
+                                                    ,24348
+                                                    ,22369
+                                                    ,12174
+                                                    ,11185                  /* 192kS/s */
+                                               };
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Number of samples in 20ms                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the number of samples
+ * during 20ms
+ */
+const LVM_UINT16    LVPSA_nSamplesBufferUpdate[]  = {   160,                   /* 8kS/s  */
+                                                        220,
+                                                        240,
+                                                        320,
+                                                        441,
+                                                        480,
+                                                        640,
+                                                        882,
+                                                        960
+                                                        ,1764
+                                                        ,1920
+                                                        ,3528
+                                                        ,3840                  /* 192kS/s */
+                                                    };
+/************************************************************************************/
+/*                                                                                  */
+/*  Down sampling factors                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the down sampling factor
+ */
+const LVM_UINT16    LVPSA_DownSamplingFactor[]  = {     5,                    /* 8000  S/s  */
+                                                        7,                    /* 11025 S/s  */
+                                                        8,                    /* 12000 S/s  */
+                                                        10,                   /* 16000 S/s  */
+                                                        15,                   /* 22050 S/s  */
+                                                        16,                   /* 24000 S/s  */
+                                                        21,                   /* 32000 S/s  */
+                                                        30,                   /* 44100 S/s  */
+                                                        32                    /* 48000 S/s  */
+                                                       ,60                   /* 88200 S/s  */
+                                                       ,64                   /* 96000 S/s  */
+                                                       ,120                  /* 176400 S/s  */
+                                                       ,128                  /*192000 S/s  */
+                                                  };
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Coefficient calculation tables                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16     LVPSA_TwoPiOnFsTable[] = {  26354,      /* 8kS/s */
+                                                19123,
+                                                17569,
+                                                13177,
+                                                 9561,
+                                                 8785,
+                                                 6588,
+                                                 4781,
+                                                 4392
+                                                ,2390
+                                                ,2196
+                                                ,1195
+                                                ,1098    /* 192kS/s */
+                                             };
+
+const LVM_FLOAT     LVPSA_Float_TwoPiOnFsTable[] = {  0.8042847f,      /* 8kS/s */
+                                                      0.5836054f,
+                                                      0.5361796f,
+                                                      0.4021423f,
+                                                      0.2917874f,
+                                                      0.2681051f,
+                                                      0.2010559f,
+                                                      0.1459089f,
+                                                      0.1340372f
+                                                     ,0.0729476f
+                                                     ,0.0670186f
+                                                     ,0.0364738f
+                                                     ,0.0335093f    /* 192kS/s */
+                                                   };
+
+/*
+ * Gain table
+ */
+const LVM_INT16     LVPSA_GainTable[] = {   364,          /* -15dB gain */
+                                            408,
+                                            458,
+                                            514,
+                                            577,
+                                            647,
+                                            726,
+                                            815,
+                                            914,
+                                            1026,
+                                            1151,
+                                            1292,
+                                            1449,
+                                            1626,
+                                            1825,
+                                            2048,         /* 0dB gain */
+                                            2297,
+                                            2578,
+                                            2892,
+                                            3245,
+                                            3641,
+                                            4096,
+                                            4584,
+                                            5144,
+                                            5772,
+                                            6476,
+                                            7266,
+                                            8153,
+                                            9148,
+                                            10264,
+                                            11576};        /* +15dB gain */
+
+const LVM_FLOAT  LVPSA_Float_GainTable[]={  0.177734375f,          /* -15dB gain */
+                                            0.199218750f,
+                                            0.223632812f,
+                                            0.250976562f,
+                                            0.281738281f,
+                                            0.315917968f,
+                                            0.354492187f,
+                                            0.397949218f,
+                                            0.446289062f,
+                                            0.500976562f,
+                                            0.562011718f,
+                                            0.630859375f,
+                                            0.707519531f,
+                                            0.793945312f,
+                                            0.891113281f,
+                                            1.000000000f,         /* 0dB gain */
+                                            1.121582031f,
+                                            1.258789062f,
+                                            1.412109375f,
+                                            1.584472656f,
+                                            1.777832031f,
+                                            2.000000000f,
+                                            2.238281250f,
+                                            2.511718750f,
+                                            2.818359375f,
+                                            3.162109375f,
+                                            3.547851562f,
+                                            3.980957031f,
+                                            4.466796875f,
+                                            5.011718750f,
+                                            5.652343750f};        /* +15dB gain */
+/************************************************************************************/
+/*                                                                                  */
+/*  Cosone polynomial coefficients                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16     LVPSA_CosCoef[] = { 3,                             /* Shifts */
+                                        4096,                          /* a0 */
+                                        -36,                           /* a1 */
+                                        -19725,                        /* a2 */
+                                        -2671,                         /* a3 */
+                                        23730,                         /* a4 */
+                                        -9490};                        /* a5 */
+const LVM_FLOAT     LVPSA_Float_CosCoef[] = { 3,                             /* Shifts */
+                                              0.1250038f,                          /* a0 */
+                                              -0.0010986f,                           /* a1 */
+                                              -0.6019775f,                        /* a2 */
+                                              -0.0815149f,                         /* a3 */
+                                              0.7242042f,                         /* a4 */
+                                              -0.2896206f};                        /* a5 */
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16     LVPSA_DPCosCoef[] = {   1,                           /* Shifts */
+                                            0,                           /* a0 */
+                                            -6,                          /* a1 */
+                                            16586,                       /* a2 */
+                                            -44};                        /* a3 */
+const LVM_FLOAT    LVPSA_Float_DPCosCoef[] = {1.0f,                        /* Shifts */
+                                              0.0f,                        /* a0 */
+                                              -0.00008311f,                 /* a1 */
+                                              0.50617999f,                 /* a2 */
+                                              -0.00134281f};                /* a3 */
+/************************************************************************************/
+/*                                                                                  */
+/*  Quasi peak filter coefficients table                                            */
+/*                                                                                  */
+/************************************************************************************/
+const QPD_C32_Coefs     LVPSA_QPD_Coefs[] = {
+                                         /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
+                                         {(LVM_INT32)0x80CEFD2B,0x00CB9B17},
+                                         {(LVM_INT32)0x80D242E7,0x00CED11D},
+                                         {(LVM_INT32)0x80DCBAF5,0x00D91679},
+                                         {(LVM_INT32)0x80CEFD2B,0x00CB9B17},
+                                         {(LVM_INT32)0x80E13739,0x00DD7CD3},
+                                         {(LVM_INT32)0x80DCBAF5,0x00D91679},
+                                         {(LVM_INT32)0x80D94BAF,0x00D5B7E7},
+                                         {(LVM_INT32)0x80E13739,0x00DD7CD3},
+                                         {(LVM_INT32)0x80DCBAF5,0x00D91679},  /* 48kS/s */
+
+                                         /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM */
+                                         {(LVM_INT32)0x8587513D,0x055C22CF},
+                                         {(LVM_INT32)0x859D2967,0x0570F007},
+                                         {(LVM_INT32)0x85E2EFAC,0x05B34D79},
+                                         {(LVM_INT32)0x8587513D,0x055C22CF},
+                                         {(LVM_INT32)0x8600C7B9,0x05CFA6CF},
+                                         {(LVM_INT32)0x85E2EFAC,0x05B34D79},
+                                         {(LVM_INT32)0x85CC1018,0x059D8F69},
+                                         {(LVM_INT32)0x8600C7B9,0x05CFA6CF},
+                                         {(LVM_INT32)0x85E2EFAC,0x05B34D79},  /* 48kS/s */
+
+                                         /* 8kS/s  */   /* LVPSA_SPEED_HIGH    */
+                                         {(LVM_INT32)0xA115EA7A,0x1CDB3F5C},
+                                         {(LVM_INT32)0xA18475F0,0x1D2C83A2},
+                                         {(LVM_INT32)0xA2E1E950,0x1E2A532E},
+                                         {(LVM_INT32)0xA115EA7A,0x1CDB3F5C},
+                                         {(LVM_INT32)0xA375B2C6,0x1E943BBC},
+                                         {(LVM_INT32)0xA2E1E950,0x1E2A532E},
+                                         {(LVM_INT32)0xA26FF6BD,0x1DD81530},
+                                         {(LVM_INT32)0xA375B2C6,0x1E943BBC},
+                                         {(LVM_INT32)0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
+
+const QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[] = {
+
+                                         /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
+                                         {-0.9936831989325583f,0.0062135565094650f},
+                                         {-0.9935833332128823f,0.0063115493394434f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9936831989325583f,0.0062135565094650f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9933686633594334f,0.0065221670083702f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                          /* 48kS/s */
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
+                                         {-0.9932638457976282f,0.0066249934025109f},
+                                         /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
+                                         {-0.9568079425953329f,0.0418742666952312f},
+                                         {-0.9561413046903908f,0.0425090822391212f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9568079425953329f,0.0418742666952312f},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9547099955379963f,0.0438708555884659f},
+                                          //{0x8600C7B9,0x05CFA6CF},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                          /* 48kS/s */
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9531011912040412f,0.0453995238058269f},
+                                         {-0.9540119562298059f,0.0445343819446862f},
+                                          /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
+                                         {-0.7415186790749431f,0.2254409026354551f},
+                                         {-0.7381451204419136f,0.2279209652915597f},
+                                         {-0.7274807319045067f,0.2356666540727019f},
+                                         {-0.7415186790749431f,0.2254409026354551f},
+                                         {-0.7229706319049001f,0.2388987224549055f},
+                                         {-0.7274807319045067f,0.2356666540727019f},
+                                         {-0.7309581353329122f,0.2331568226218224f},
+                                         {-0.7229706319049001f,0.2388987224549055f},
+                                           /* 48kS/s */
+                                         {-0.7274807319045067f,0.2356666540727019f}
+                                        ,{-0.7229706319049001f,0.2388987224549055f}
+                                        ,{-0.7274807319045067f,0.2356666540727019f}
+                                        ,{-0.7229706319049001f,0.2388987224549055f}
+                                        ,{-0.7274807319045067f,0.2356666540727019f}
+                                        };
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.h
new file mode 100644
index 0000000..65872fe
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 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 __LVPSA_TABLES_H__
+#define __LVPSA_TABLES_H__
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate table                                                               */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+extern const LVM_UINT32    LVPSA_SampleRateTab[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate inverse table                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+extern const LVM_UINT32    LVPSA_SampleRateInvTab[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Number of samples in 20ms                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the number of samples
+ * during 20ms
+ */
+extern const LVM_UINT16    LVPSA_nSamplesBufferUpdate[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Down sampling factors                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the down sampling factor
+ */
+extern const LVM_UINT16    LVPSA_DownSamplingFactor[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Coefficient calculation tables                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+extern const LVM_INT16     LVPSA_TwoPiOnFsTable[];
+extern const LVM_FLOAT     LVPSA_Float_TwoPiOnFsTable[];
+
+/*
+ * Gain table
+ */
+extern const LVM_INT16     LVPSA_GainTable[];
+extern const LVM_FLOAT     LVPSA_Float_GainTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Cosone polynomial coefficients                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+extern const LVM_INT16     LVPSA_CosCoef[];
+extern const LVM_FLOAT     LVPSA_Float_CosCoef[];
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+extern const LVM_INT16     LVPSA_DPCosCoef[];
+extern const LVM_FLOAT    LVPSA_Float_DPCosCoef[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Quasi peak filter coefficients table                                            */
+/*                                                                                  */
+/************************************************************************************/
+extern const QPD_C32_Coefs     LVPSA_QPD_Coefs[];
+extern const QPD_FLOAT_Coefs     LVPSA_QPD_Float_Coefs[];
+
+#endif /* __LVPSA_TABLES_H__ */
diff --git a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
index e507a7c..0adfd1b 100644
--- a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -56,11 +56,6 @@
 #ifndef LVCS_H
 #define LVCS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Includes                                                                            */
@@ -70,7 +65,6 @@
 #include "LVM_Types.h"
 #include "LVM_Common.h"
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Definitions                                                                         */
@@ -93,7 +87,6 @@
 #define LVCS_EVENT_NONE                   0x0000    /* Not a valid event */
 #define LVCS_EVENT_ALGOFF                 0x0001    /* CS has completed switch off */
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Types                                                                               */
@@ -103,7 +96,6 @@
 /* Instance handle */
 typedef void *LVCS_Handle_t;
 
-
 /* Operating modes */
 typedef enum
 {
@@ -112,7 +104,6 @@
     LVCS_MAX = LVM_MAXENUM
 } LVCS_Modes_en;
 
-
 /* Memory Types */
 typedef enum
 {
@@ -123,7 +114,6 @@
     LVCS_MEMORYTYPE_MAX = LVM_MAXENUM
 } LVCS_MemoryTypes_en;
 
-
 /* Function return status */
 typedef enum
 {
@@ -135,7 +125,6 @@
     LVCS_STATUSMAX      = LVM_MAXENUM
 } LVCS_ReturnStatus_en;
 
-
 /*
  * Source data formats
  */
@@ -146,7 +135,6 @@
     LVCS_SOURCEMAX    = LVM_MAXENUM
 } LVCS_SourceFormat_en;
 
-
 /*
  * Supported output devices
  */
@@ -172,7 +160,6 @@
     void    *pTable8;
 } LVCS_CSMS_Coef_Tables_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Structures                                                                          */
@@ -187,14 +174,12 @@
     void                    *pBaseAddress;          /* Pointer to the region base address */
 } LVCS_MemoryRegion_t;
 
-
 /* Memory table containing the region definitions */
 typedef struct
 {
     LVCS_MemoryRegion_t Region[LVCS_NR_MEMORY_REGIONS]; /* One definition for each region */
 } LVCS_MemTab_t;
 
-
 /* Concert Sound parameter structure */
 typedef struct
 {
@@ -210,7 +195,6 @@
 #endif
 } LVCS_Params_t;
 
-
 /* Concert Sound Capability structure */
 typedef struct
 {
@@ -223,7 +207,6 @@
 
 } LVCS_Capabilities_t;
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /*  Function Prototypes                                                                 */
@@ -270,7 +253,6 @@
                                  LVCS_MemTab_t          *pMemoryTable,
                                  LVCS_Capabilities_t    *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVCS_Init                                                   */
@@ -308,7 +290,6 @@
                                LVCS_MemTab_t            *pMemoryTable,
                                LVCS_Capabilities_t      *pCapabilities);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                 LVCS_GetParameters                                         */
@@ -332,7 +313,6 @@
 LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
                                         LVCS_Params_t   *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVCS_Control                                                */
@@ -355,7 +335,6 @@
 LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t     hInstance,
                                   LVCS_Params_t     *pParams);
 
-
 /****************************************************************************************/
 /*                                                                                      */
 /* FUNCTION:                LVCS_Process                                                */
@@ -377,20 +356,9 @@
 /* NOTES:                                                                               */
 /*                                                                                      */
 /****************************************************************************************/
-#ifdef BUILD_FLOAT
 LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
                                   const LVM_FLOAT           *pInData,
                                   LVM_FLOAT                 *pOutData,
                                   LVM_UINT16                NumSamples);
-#else
-LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
-                                  const LVM_INT16           *pInData,
-                                  LVM_INT16                 *pOutData,
-                                  LVM_UINT16                NumSamples);
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* LVCS_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
deleted file mode 100644
index 29e3c9e..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_BypassMix.h"
-#include "VectorArithmetic.h"
-#include "LVCS_Tables.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/*  Function Prototypes                                                                 */
-/*                                                                                      */
-/****************************************************************************************/
-LVM_INT32 LVCS_MixerCallback(   LVCS_Handle_t   hInstance,
-                                void            *pGeneralPurpose,
-                                LVM_INT16       CallbackParam);
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_BypassMixInit                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialises the bypass mixer module                                             */
-/*                                                                                  */
-/*  The overall gain of the processed path is set by the gains in the individual    */
-/*  processing blocks and by the effect level gain.                                 */
-/*                                                                                  */
-/*  The unprocessed path must have matching gain for the processed path to ensure   */
-/*  as they are mixed together the correct effect is achieved, this is the value    */
-/*  UnprocLoss.                                                                     */
-/*                                                                                  */
-/*  The overall gain is corrected by a combination of a shift with saturation and a */
-/*  linear scaler, loss. The loss ensures the sum in the mixer does not saturate    */
-/*  and also corrects for any excess gain in the shift.                             */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pParams                 Initialisation parameters                               */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
-                                        LVCS_Params_t       *pParams)
-{
-
-    LVM_UINT16          Offset;
-#ifndef BUILD_FLOAT
-    LVM_UINT32          Gain;
-    LVM_INT32           Current;
-#else
-    LVM_FLOAT           Gain;
-    LVM_FLOAT           Current;
-#endif
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_BypassMix_t    *pConfig   = (LVCS_BypassMix_t *)&pInstance->BypassMix;
-    const Gain_t        *pOutputGainTable;
-
-
-
-    /*
-     * Set the transition gain
-     */
-    if ((pParams->OperatingMode == LVCS_ON) &&
-        (pInstance->bTimerDone == LVM_TRUE)
-        && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
-        )
-    {
-#ifndef BUILD_FLOAT
-        pInstance->TransitionGain = pParams->EffectLevel;
-#else
-        pInstance->TransitionGain = ((LVM_FLOAT)pParams->EffectLevel / 32767);
-#endif
-    }
-    else
-    {
-        /* Select no effect level */
-        pInstance->TransitionGain = 0;
-    }
-
-    /*
-     * Calculate the output gain table offset
-     */
-    Offset = (LVM_UINT16)(pParams->SpeakerType + (pParams->SourceFormat*(1+LVCS_EX_HEADPHONES)));
-    pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
-
-    /*
-     * Setup the mixer gain for the processed path
-     */
-#ifndef BUILD_FLOAT
-    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
-#else
-    Gain =  (LVM_FLOAT)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
-#endif
-
-    pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
-    pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
-    pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
-    pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
-
-#ifndef BUILD_FLOAT
-    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
-    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0],(LVM_INT32)(Gain >> 15),Current);
-    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-#else
-    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
-    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0], (LVM_FLOAT)(Gain), Current);
-    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
-                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-#endif
-
-    /*
-     * Setup the mixer gain for the unprocessed path
-     */
-#ifndef BUILD_FLOAT
-    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * (0x7FFF - pInstance->TransitionGain));
-    Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
-    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
-    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1],(LVM_INT32)(Gain >> 15),Current);
-    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-#else
-    Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss * (1.0 - \
-                                    (LVM_FLOAT)pInstance->TransitionGain));
-    Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * Gain;
-    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
-    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1], (LVM_FLOAT)(Gain), Current);
-    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
-                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-#endif
-    pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
-    pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
-    pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
-    pConfig->Mixer_Instance.MixerStream[1].pCallBack = LVCS_MixerCallback;
-
-    /*
-     * Setup the output gain shift
-     */
-    pConfig->Output_Shift = pOutputGainTable[Offset].Shift;
-
-
-    /*
-     * Correct gain for the effect level
-     */
-    {
-#ifndef BUILD_FLOAT
-        LVM_INT16           GainCorrect;
-        LVM_INT32           Gain1;
-        LVM_INT32           Gain2;
-
-        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
-        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
-        /*
-         * Calculate the gain correction
-         */
-        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
-        {
-        GainCorrect = (LVM_INT16)(  pInstance->VolCorrect.GainMin
-                                    - (((LVM_INT32)pInstance->VolCorrect.GainMin * (LVM_INT32)pInstance->TransitionGain) >> 15)
-                                    + (((LVM_INT32)pInstance->VolCorrect.GainFull * (LVM_INT32)pInstance->TransitionGain) >> 15) );
-
-        /*
-         * Apply the gain correction and shift, note the result is in Q3.13 format
-         */
-        Gain1 = (Gain1 * GainCorrect) << 4;
-        Gain2 = (Gain2 * GainCorrect) << 4;
-        }
-        else
-        {
-            Gain1 = Gain1 << 16;
-            Gain2 = Gain2 << 16;
-        }
-
-
-
-        /*
-         * Set the gain values
-         */
-        pConfig->Output_Shift = pConfig->Output_Shift;
-        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1>>16);
-        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2>>16);
-        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-#else
-        LVM_FLOAT           GainCorrect;
-        LVM_FLOAT           Gain1;
-        LVM_FLOAT           Gain2;
-
-        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
-        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
-        /*
-         * Calculate the gain correction
-         */
-        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
-        {
-        GainCorrect = (LVM_FLOAT)(  pInstance->VolCorrect.GainMin
-                                    - (((LVM_FLOAT)pInstance->VolCorrect.GainMin * \
-                                                         ((LVM_FLOAT)pInstance->TransitionGain)))
-                                    + (((LVM_FLOAT)pInstance->VolCorrect.GainFull * \
-                                                        ((LVM_FLOAT)pInstance->TransitionGain))));
-
-        /*
-         * Apply the gain correction
-         */
-        Gain1 = (Gain1 * GainCorrect);
-        Gain2 = (Gain2 * GainCorrect);
-
-        }
-
-        /*
-         * Set the gain values
-         */
-        pConfig->Output_Shift = pConfig->Output_Shift;
-        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1);
-        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
-                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2);
-        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
-                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-#endif
-    }
-
-    return(LVCS_SUCCESS);
-
-}
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_BypassMixer                                        */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Apply Bypass Mix.                                                               */
-/*                                                                                  */
-/*  This mixes the processed and unprocessed data streams together to correct the   */
-/*  overall system gain and allow progressive control of the Concert Sound effect.  */
-/*                                                                                  */
-/*  When the bypass mixer is enabled the output is the processed signal only and    */
-/*  without gain correction.                                                        */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pProcessed              Pointer to the processed data                           */
-/*  pUnprocessed            Pointer to the unprocessed data                         */
-/*  pOutData                Pointer to the output data                              */
-/*  NumSamples              Number of samples to process                            */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
-#ifndef BUILD_FLOAT
-                                      const LVM_INT16       *pProcessed,
-                                      const LVM_INT16       *pUnprocessed,
-                                      LVM_INT16             *pOutData,
-#else
-                                      const LVM_FLOAT       *pProcessed,
-                                      const LVM_FLOAT       *pUnprocessed,
-                                      LVM_FLOAT             *pOutData,
-#endif
-                                      LVM_UINT16            NumSamples)
-{
-
-    LVCS_Instance_t     *pInstance      = (LVCS_Instance_t  *)hInstance;
-    LVCS_BypassMix_t    *pConfig        = (LVCS_BypassMix_t *)&pInstance->BypassMix;
-
-    /*
-     * Check if the bypass mixer is enabled
-     */
-    if ((pInstance->Params.OperatingMode & LVCS_BYPASSMIXSWITCH) != 0)
-    {
-        /*
-         * Apply the bypass mix
-         */
-#ifndef BUILD_FLOAT
-        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
-                                        pProcessed,
-                                        (LVM_INT16 *) pUnprocessed,
-                                        pOutData,
-                                        (LVM_INT16)(2*NumSamples));
-
-        /*
-         * Apply output gain correction shift
-         */
-        Shift_Sat_v16xv16 ((LVM_INT16)pConfig->Output_Shift,
-                          (LVM_INT16*)pOutData,
-                          (LVM_INT16*)pOutData,
-                          (LVM_INT16)(2*NumSamples));          /* Left and right*/
-#else
-        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
-                                   pProcessed,
-                                   (LVM_FLOAT *) pUnprocessed,
-                                   pOutData,
-                                   (LVM_INT16)(2 * NumSamples));
-        /*
-         * Apply output gain correction shift
-         */
-        Shift_Sat_Float((LVM_INT16)pConfig->Output_Shift,
-                        (LVM_FLOAT*)pOutData,
-                        (LVM_FLOAT*)pOutData,
-                        (LVM_INT16)(2 * NumSamples));          /* Left and right*/
-#endif
-    }
-
-    return(LVCS_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_MixerCallback                                      */
-/*                                                                                  */
-/************************************************************************************/
-LVM_INT32 LVCS_MixerCallback(LVCS_Handle_t      hInstance,
-                            void                *pGeneralPurpose,
-                            LVM_INT16           CallbackParam)
-{
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-
-   (void)pGeneralPurpose;
-
-    /*
-     * Off transition has completed in Headphone mode
-     */
-    if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
-        (pInstance->bInOperatingModeTransition)     &&
-        (pInstance->MSTarget0 == 0x0000)&&  /* this indicates an on->off transition */
-        (CallbackParam == 0))
-    {
-        /* Set operating mode to OFF */
-        pInstance->Params.OperatingMode = LVCS_OFF;
-
-        /* Exit transition state */
-        pInstance->bInOperatingModeTransition = LVM_FALSE;
-
-        /* Signal to the bundle */
-        if((*pInstance->Capabilities.CallBack) != LVM_NULL){
-            (*pInstance->Capabilities.CallBack)(pInstance->Capabilities.pBundleInstance,
-                                                LVM_NULL,
-                                                (ALGORITHM_CS_ID | LVCS_EVENT_ALGOFF));
-        }
-    }
-
-
-    if ((pInstance->OutputDevice == LVCS_HEADPHONE)  &&
-        (pInstance->MSTarget0 == 1) &&
-        (pInstance->bTimerDone == LVM_TRUE)){
-
-        /* Exit transition state */
-        pInstance->bInOperatingModeTransition = LVM_FALSE;
-    }
-
-    return 1;
-}
-
-
-
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp
new file mode 100644
index 0000000..ba152c0
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_BypassMix.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Function Prototypes                                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVCS_MixerCallback(   LVCS_Handle_t   hInstance,
+                                void            *pGeneralPurpose,
+                                LVM_INT16       CallbackParam);
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_BypassMixInit                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the bypass mixer module                                             */
+/*                                                                                  */
+/*  The overall gain of the processed path is set by the gains in the individual    */
+/*  processing blocks and by the effect level gain.                                 */
+/*                                                                                  */
+/*  The unprocessed path must have matching gain for the processed path to ensure   */
+/*  as they are mixed together the correct effect is achieved, this is the value    */
+/*  UnprocLoss.                                                                     */
+/*                                                                                  */
+/*  The overall gain is corrected by a combination of a shift with saturation and a */
+/*  linear scaler, loss. The loss ensures the sum in the mixer does not saturate    */
+/*  and also corrects for any excess gain in the shift.                             */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16          Offset;
+    LVM_FLOAT           Gain;
+    LVM_FLOAT           Current;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_BypassMix_t    *pConfig   = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+    const Gain_t        *pOutputGainTable;
+
+    /*
+     * Set the transition gain
+     */
+    if ((pParams->OperatingMode == LVCS_ON) &&
+        (pInstance->bTimerDone == LVM_TRUE)
+        && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
+        )
+    {
+        pInstance->TransitionGain = ((LVM_FLOAT)pParams->EffectLevel / 32767);
+    }
+    else
+    {
+        /* Select no effect level */
+        pInstance->TransitionGain = 0;
+    }
+
+    /*
+     * Calculate the output gain table offset
+     */
+    Offset = (LVM_UINT16)(pParams->SpeakerType + (pParams->SourceFormat*(1+LVCS_EX_HEADPHONES)));
+    pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+
+    /*
+     * Setup the mixer gain for the processed path
+     */
+    Gain =  (LVM_FLOAT)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
+
+    pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
+    pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
+    pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
+    pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
+
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0], (LVM_FLOAT)(Gain), Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
+                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+
+    /*
+     * Setup the mixer gain for the unprocessed path
+     */
+    Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss * (1.0 - \
+                                    (LVM_FLOAT)pInstance->TransitionGain));
+    Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * Gain;
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1], (LVM_FLOAT)(Gain), Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
+                                       LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+    pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
+    pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
+    pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
+    pConfig->Mixer_Instance.MixerStream[1].pCallBack = LVCS_MixerCallback;
+
+    /*
+     * Setup the output gain shift
+     */
+    pConfig->Output_Shift = pOutputGainTable[Offset].Shift;
+
+    /*
+     * Correct gain for the effect level
+     */
+    {
+        LVM_FLOAT           GainCorrect;
+        LVM_FLOAT           Gain1;
+        LVM_FLOAT           Gain2;
+
+        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
+        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
+        /*
+         * Calculate the gain correction
+         */
+        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
+        {
+        GainCorrect = (LVM_FLOAT)(  pInstance->VolCorrect.GainMin
+                                    - (((LVM_FLOAT)pInstance->VolCorrect.GainMin * \
+                                                         ((LVM_FLOAT)pInstance->TransitionGain)))
+                                    + (((LVM_FLOAT)pInstance->VolCorrect.GainFull * \
+                                                        ((LVM_FLOAT)pInstance->TransitionGain))));
+
+        /*
+         * Apply the gain correction
+         */
+        Gain1 = (Gain1 * GainCorrect);
+        Gain2 = (Gain2 * GainCorrect);
+
+        }
+
+        /*
+         * Set the gain values
+         */
+        pConfig->Output_Shift = pConfig->Output_Shift;
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],
+                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],
+                                           LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+    }
+
+    return(LVCS_SUCCESS);
+
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_BypassMixer                                        */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply Bypass Mix.                                                               */
+/*                                                                                  */
+/*  This mixes the processed and unprocessed data streams together to correct the   */
+/*  overall system gain and allow progressive control of the Concert Sound effect.  */
+/*                                                                                  */
+/*  When the bypass mixer is enabled the output is the processed signal only and    */
+/*  without gain correction.                                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pProcessed              Pointer to the processed data                           */
+/*  pUnprocessed            Pointer to the unprocessed data                         */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
+                                      const LVM_FLOAT       *pProcessed,
+                                      const LVM_FLOAT       *pUnprocessed,
+                                      LVM_FLOAT             *pOutData,
+                                      LVM_UINT16            NumSamples)
+{
+
+    LVCS_Instance_t     *pInstance      = (LVCS_Instance_t  *)hInstance;
+    LVCS_BypassMix_t    *pConfig        = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+
+    /*
+     * Check if the bypass mixer is enabled
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_BYPASSMIXSWITCH) != 0)
+    {
+        /*
+         * Apply the bypass mix
+         */
+        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
+                                   pProcessed,
+                                   (LVM_FLOAT *) pUnprocessed,
+                                   pOutData,
+                                   (LVM_INT16)(2 * NumSamples));
+        /*
+         * Apply output gain correction shift
+         */
+        Shift_Sat_Float((LVM_INT16)pConfig->Output_Shift,
+                        (LVM_FLOAT*)pOutData,
+                        (LVM_FLOAT*)pOutData,
+                        (LVM_INT16)(2 * NumSamples));          /* Left and right*/
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_MixerCallback                                      */
+/*                                                                                  */
+/************************************************************************************/
+LVM_INT32 LVCS_MixerCallback(LVCS_Handle_t      hInstance,
+                            void                *pGeneralPurpose,
+                            LVM_INT16           CallbackParam)
+{
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+
+   (void)pGeneralPurpose;
+
+    /*
+     * Off transition has completed in Headphone mode
+     */
+    if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
+        (pInstance->bInOperatingModeTransition)     &&
+        (pInstance->MSTarget0 == 0x0000)&&  /* this indicates an on->off transition */
+        (CallbackParam == 0))
+    {
+        /* Set operating mode to OFF */
+        pInstance->Params.OperatingMode = LVCS_OFF;
+
+        /* Exit transition state */
+        pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+        /* Signal to the bundle */
+        if((*pInstance->Capabilities.CallBack) != LVM_NULL){
+            (*pInstance->Capabilities.CallBack)(pInstance->Capabilities.pBundleInstance,
+                                                LVM_NULL,
+                                                (ALGORITHM_CS_ID | LVCS_EVENT_ALGOFF));
+        }
+    }
+
+    if ((pInstance->OutputDevice == LVCS_HEADPHONE)  &&
+        (pInstance->MSTarget0 == 1) &&
+        (pInstance->bTimerDone == LVM_TRUE)){
+
+        /* Exit transition state */
+        pInstance->bInOperatingModeTransition = LVM_FALSE;
+    }
+
+    return 1;
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
index f69ba38..fcd8ee3 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
@@ -18,11 +18,6 @@
 #ifndef __LVCS_BYPASSMIX_H__
 #define __LVCS_BYPASSMIX_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Includes                                                                      */
@@ -31,7 +26,6 @@
 
 #include "LVC_Mixer.h"
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Structures                                                                    */
@@ -42,25 +36,11 @@
 typedef struct
 {
     /* Mixer settings */
-#ifdef BUILD_FLOAT
     LVMixer3_2St_FLOAT_st   Mixer_Instance;             /* Mixer instance */
-#else
-    LVMixer3_2St_st         Mixer_Instance;             /* Mixer instance */
-#endif
     LVM_UINT16              Output_Shift;               /* Correcting gain output shift */
 
 } LVCS_BypassMix_t;
 
-#ifndef BUILD_FLOAT
-/* Output gain type */
-typedef struct
-{
-    /* Output gain settings, Gain = (Loss/32768) * 2^Shift */
-    LVM_UINT16              Shift;                      /* Left shifts required */
-    LVM_UINT16              Loss;                       /* Loss required */
-    LVM_UINT16              UnprocLoss;                 /* Unprocessed path loss */
-} Gain_t;
-#else
 typedef struct
 {
     /* Output gain settings, Gain = (Loss/32768) * 2^Shift */
@@ -68,7 +48,6 @@
     LVM_FLOAT              Loss;                       /* Loss required */
     LVM_FLOAT              UnprocLoss;                 /* Unprocessed path loss */
 } Gain_t;
-#endif
 /************************************************************************************/
 /*                                                                                    */
 /*    Function prototypes                                                                */
@@ -78,21 +57,10 @@
 LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
                                            LVCS_Params_t    *pParams);
 
-#ifndef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
-                                      const LVM_INT16       *pProcessed,
-                                      const LVM_INT16       *unProcessed,
-                                      LVM_INT16       *pOutData,
-                                      LVM_UINT16      NumSamples);
-#else
 LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
                                       const LVM_FLOAT       *pProcessed,
                                       const LVM_FLOAT       *unProcessed,
                                       LVM_FLOAT       *pOutData,
                                       LVM_UINT16      NumSamples);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* BYPASSMIX_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
deleted file mode 100644
index 3bf6ec6..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_Tables.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                 LVCS_GetParameters                                     */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Request the Concert Sound parameters. The current parameter set is returned     */
-/*  via the parameter pointer.                                                      */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance                Instance handle                                        */
-/*  pParams                  Pointer to an empty parameter structure                */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success             Always succeeds                                        */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  This function may be interrupted by the LVCS_Process function               */
-/*                                                                                  */
-/************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
-                                        LVCS_Params_t   *pParams)
-{
-
-    LVCS_Instance_t     *pInstance =(LVCS_Instance_t  *)hInstance;
-
-    *pParams = pInstance->Params;
-
-    return(LVCS_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Control                                            */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Sets or changes the Concert Sound parameters.                                   */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance handle                                         */
-/*  pParams                 Pointer to a parameter structure                        */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Succeeded                                               */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  This function must not be interrupted by the LVCS_Process function          */
-/*                                                                                  */
-/************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t      hInstance,
-                                  LVCS_Params_t      *pParams)
-{
-    LVM_INT16                   Offset;
-    LVCS_Instance_t             *pInstance =(LVCS_Instance_t  *)hInstance;
-    LVCS_ReturnStatus_en        err;
-    LVCS_Modes_en               OperatingModeSave = pInstance->Params.OperatingMode;
-
-    if (pParams->SampleRate != pInstance->Params.SampleRate)
-    {
-        pInstance->TimerParams.SamplingRate = LVCS_SampleRateTable[pParams->SampleRate];
-    }
-
-    /*
-     * If the reverb level has changed
-     */
-    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
-    {
-        err=LVCS_ReverbGeneratorInit(hInstance,pParams);
-    }
-
-    /*
-     * If the sample rate or speaker has changed then perform a full re-initialisation
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-       (pInstance->Params.SpeakerType != pParams->SpeakerType))
-    {
-        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
-
-        /*
-         * Output device
-         */
-        pInstance->OutputDevice = LVCS_HEADPHONE;
-
-        /*
-         * Get the volume correction parameters
-         */
-        /* Use internal coefficient table */
-        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
-        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
-
-        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
-
-        pInstance->CompressGain = pInstance->VolCorrect.CompMin;
-#ifdef BUILD_FLOAT
-        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0], 0, 0);
-#else
-        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
-#endif
-        {
-#ifndef BUILD_FLOAT
-            LVM_UINT32          Gain;
-            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
-            Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * LVM_MAXINT_16);
-            Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
-            Gain=Gain>>15;
-            /*
-             * Apply the gain correction and shift, note the result is in Q3.13 format
-             */
-            Gain = (Gain * pInstance->VolCorrect.GainMin) >>12;
-
-            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,Gain);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
-                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
-                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
-#else
-            LVM_FLOAT          Gain;
-            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
-            Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss);
-            Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * (Gain);
-
-            /*
-             * Apply the gain correction
-             */
-            Gain = (Gain * pInstance->VolCorrect.GainMin);
-
-            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1], 0, Gain);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
-                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
-                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
-#endif
-        }
-
-
-        err=LVCS_SEnhancerInit(hInstance,
-                           pParams);
-
-        err=LVCS_ReverbGeneratorInit(hInstance,
-                                 pParams);
-
-        err=LVCS_EqualiserInit(hInstance,
-                           pParams);
-
-        err=LVCS_BypassMixInit(hInstance,
-                           pParams);
-
-    }
-
-
-    /*
-     * Check if the effect level or source format has changed
-     */
-    else if ((pInstance->Params.EffectLevel != pParams->EffectLevel) ||
-            (pInstance->Params.SourceFormat != pParams->SourceFormat))
-    {
-        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
-
-        /*
-         * Get the volume correction parameters
-         */
-        /* Use internal coefficient table */
-        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
-        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
-
-        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
-
-        /* Update the effect level and alpha-mixer gains */
-        err=LVCS_BypassMixInit(hInstance,
-                           pParams);
-
-        if(err != LVCS_SUCCESS)
-        {
-            return err;
-        }
-    }
-    else
-    {
-        pInstance->Params = *pParams;
-    }
-
-    /*
-     * Update the instance parameters
-     */
-    pInstance->Params = *pParams;
-
-    /* Stay on the current operating mode until the transition is done */
-    if((pParams->OperatingMode != OperatingModeSave) ||
-       (pInstance->bInOperatingModeTransition == LVM_TRUE)){
-
-        /* Set the reverb delay timeout */
-        if(pInstance->bInOperatingModeTransition != LVM_TRUE){
-            pInstance->bTimerDone = LVM_FALSE;
-            pInstance->TimerParams.TimeInMs =
-            (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)
-            /pInstance->TimerParams.SamplingRate) + 1);
-            LVM_Timer_Init ( &pInstance->TimerInstance,
-                             &pInstance->TimerParams);
-        }
-
-        /* Update the effect level and alpha-mixer gains */
-        err=LVCS_BypassMixInit(hInstance,
-                           pParams);
-
-        /* Change transition bypass mixer settings if needed depending on transition type */
-        if(pParams->OperatingMode != LVCS_OFF){
-            pInstance->MSTarget0=LVM_MAXINT_16;
-            pInstance->MSTarget1=0;
-        }
-        else
-        {
-            pInstance->Params.OperatingMode = OperatingModeSave;
-            pInstance->MSTarget1=LVM_MAXINT_16;
-            pInstance->MSTarget0=0;
-        }
-
-
-        /* Set transition flag */
-        pInstance->bInOperatingModeTransition = LVM_TRUE;
-    }
-
-    return(LVCS_SUCCESS);
-}
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVCS_TimerCallBack                                          */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  CallBack function of the Timer.                                                     */
-/*                                                                                      */
-/****************************************************************************************/
-void LVCS_TimerCallBack (void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam)
-{
-    LVCS_Instance_t     *pInstance  = (LVCS_Instance_t  *)hInstance;
-
-    /* Avoid warnings because pCallBackParams and CallbackParam are not used*/
-    if((pCallBackParams != LVM_NULL) || (CallbackParam != 0)){
-        pCallBackParams = hInstance;
-        CallbackParam = 0;
-        return;
-    }
-
-    pInstance->bTimerDone = LVM_TRUE;
-
-
-    return;
-}
-
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp
new file mode 100644
index 0000000..50db03d
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                 LVCS_GetParameters                                     */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Request the Concert Sound parameters. The current parameter set is returned     */
+/*  via the parameter pointer.                                                      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                Instance handle                                        */
+/*  pParams                  Pointer to an empty parameter structure                */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success             Always succeeds                                        */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function may be interrupted by the LVCS_Process function               */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
+                                        LVCS_Params_t   *pParams)
+{
+
+    LVCS_Instance_t     *pInstance =(LVCS_Instance_t  *)hInstance;
+
+    *pParams = pInstance->Params;
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Control                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets or changes the Concert Sound parameters.                                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pParams                 Pointer to a parameter structure                        */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function must not be interrupted by the LVCS_Process function          */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t      hInstance,
+                                  LVCS_Params_t      *pParams)
+{
+    LVM_INT16                   Offset;
+    LVCS_Instance_t             *pInstance =(LVCS_Instance_t  *)hInstance;
+    LVCS_ReturnStatus_en        err;
+    LVCS_Modes_en               OperatingModeSave = pInstance->Params.OperatingMode;
+
+    if (pParams->SampleRate != pInstance->Params.SampleRate)
+    {
+        pInstance->TimerParams.SamplingRate = LVCS_SampleRateTable[pParams->SampleRate];
+    }
+
+    /*
+     * If the reverb level has changed
+     */
+    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+    {
+        err=LVCS_ReverbGeneratorInit(hInstance,pParams);
+    }
+
+    /*
+     * If the sample rate or speaker has changed then perform a full re-initialisation
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+       (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+        /*
+         * Output device
+         */
+        pInstance->OutputDevice = LVCS_HEADPHONE;
+
+        /*
+         * Get the volume correction parameters
+         */
+        /* Use internal coefficient table */
+        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+        pInstance->CompressGain = pInstance->VolCorrect.CompMin;
+        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0], 0, 0);
+        {
+            LVM_FLOAT          Gain;
+            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+            Gain = (LVM_FLOAT)(pOutputGainTable[Offset].Loss);
+            Gain = (LVM_FLOAT)pOutputGainTable[Offset].UnprocLoss * (Gain);
+
+            /*
+             * Apply the gain correction
+             */
+            Gain = (Gain * pInstance->VolCorrect.GainMin);
+
+            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1], 0, Gain);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
+                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
+                    LVCS_BYPASS_MIXER_TC, pParams->SampleRate, 2);
+        }
+
+        err=LVCS_SEnhancerInit(hInstance,
+                           pParams);
+
+        err=LVCS_ReverbGeneratorInit(hInstance,
+                                 pParams);
+
+        err=LVCS_EqualiserInit(hInstance,
+                           pParams);
+
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+    }
+
+    /*
+     * Check if the effect level or source format has changed
+     */
+    else if ((pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+            (pInstance->Params.SourceFormat != pParams->SourceFormat))
+    {
+        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+        /*
+         * Get the volume correction parameters
+         */
+        /* Use internal coefficient table */
+        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+        /* Update the effect level and alpha-mixer gains */
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+        if(err != LVCS_SUCCESS)
+        {
+            return err;
+        }
+    }
+    else
+    {
+        pInstance->Params = *pParams;
+    }
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params = *pParams;
+
+    /* Stay on the current operating mode until the transition is done */
+    if((pParams->OperatingMode != OperatingModeSave) ||
+       (pInstance->bInOperatingModeTransition == LVM_TRUE)){
+
+        /* Set the reverb delay timeout */
+        if(pInstance->bInOperatingModeTransition != LVM_TRUE){
+            pInstance->bTimerDone = LVM_FALSE;
+            pInstance->TimerParams.TimeInMs =
+            (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)
+            /pInstance->TimerParams.SamplingRate) + 1);
+            LVM_Timer_Init ( &pInstance->TimerInstance,
+                             &pInstance->TimerParams);
+        }
+
+        /* Update the effect level and alpha-mixer gains */
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+        /* Change transition bypass mixer settings if needed depending on transition type */
+        if(pParams->OperatingMode != LVCS_OFF){
+            pInstance->MSTarget0=LVM_MAXINT_16;
+            pInstance->MSTarget1=0;
+        }
+        else
+        {
+            pInstance->Params.OperatingMode = OperatingModeSave;
+            pInstance->MSTarget1=LVM_MAXINT_16;
+            pInstance->MSTarget0=0;
+        }
+
+        /* Set transition flag */
+        pInstance->bInOperatingModeTransition = LVM_TRUE;
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_TimerCallBack                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  CallBack function of the Timer.                                                     */
+/*                                                                                      */
+/****************************************************************************************/
+void LVCS_TimerCallBack (void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam)
+{
+    LVCS_Instance_t     *pInstance  = (LVCS_Instance_t  *)hInstance;
+
+    /* Avoid warnings because pCallBackParams and CallbackParam are not used*/
+    if((pCallBackParams != LVM_NULL) || (CallbackParam != 0)){
+        pCallBackParams = hInstance;
+        CallbackParam = 0;
+        return;
+    }
+
+    pInstance->bTimerDone = LVM_TRUE;
+
+    return;
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
deleted file mode 100644
index ec5312e..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_Equaliser.h"
-#include "BIQUAD.h"
-#include "VectorArithmetic.h"
-#include "LVCS_Tables.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_EqualiserInit                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialises the equaliser module                                                */
-/*                                                                                  */
-/*  The function selects the coefficients for the filters and clears the data       */
-/*  history. It is also used for re-initialisation when one of the system control   */
-/*  parameters changes but will only change the coefficients and clear the history  */
-/*  if the sample rate or speaker type has changed.                                 */
-/*                                                                                  */
-/*  To avoid excessive testing during the sample processing the biquad type is      */
-/*  set as a callback function in the init routine.                                 */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pParams                 Initialisation parameters                               */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
-                                        LVCS_Params_t       *pParams)
-{
-
-    LVM_UINT16          Offset;
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t *)&pInstance->Equaliser;
-    LVCS_Data_t         *pData;
-    LVCS_Coefficient_t  *pCoefficients;
-    BQ_FLOAT_Coefs_t      Coeffs;
-    const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
-
-    pData = (LVCS_Data_t *) \
-                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-
-    pCoefficients = (LVCS_Coefficient_t *) \
-                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    /*
-     * If the sample rate changes re-initialise the filters
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.SpeakerType != pParams->SpeakerType))
-    {
-        /*
-         * Setup the filter coefficients and clear the history
-         */
-        Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
-        pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
-
-        /* Left and right filters */
-        /* Convert incoming coefficients to the required format/ordering */
-        Coeffs.A0 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A0;
-        Coeffs.A1 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A1;
-        Coeffs.A2 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A2;
-        Coeffs.B1 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B1;
-        Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
-
-        LoadConst_Float((LVM_INT16)0,                                         /* Value */
-                        (void *)&pData->EqualiserBiquadTaps,   /* Destination Cast to void:\
-                                                                  no dereferencing in function*/
-                        /* Number of words */
-                        (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
-
-        BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
-                                        &pData->EqualiserBiquadTaps,
-                                        &Coeffs);
-
-        /* Callbacks */
-        switch(pEqualiserCoefTable[Offset].Scale)
-        {
-            case 13:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C13_TRC_WRA_01;
-                break;
-            case 14:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C14_TRC_WRA_01;
-                break;
-            case 15:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C15_TRC_WRA_01;
-                break;
-        }
-    }
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
-                                        LVCS_Params_t       *pParams)
-{
-
-    LVM_UINT16          Offset;
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t *)&pInstance->Equaliser;
-    LVCS_Data_t         *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-    LVCS_Coefficient_t  *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    BQ_C16_Coefs_t      Coeffs;
-    const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
-
-    /*
-     * If the sample rate changes re-initialise the filters
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.SpeakerType != pParams->SpeakerType))
-    {
-        /*
-         * Setup the filter coefficients and clear the history
-         */
-        Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1+LVM_FS_48000)));
-        pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
-
-        /* Left and right filters */
-        /* Convert incoming coefficients to the required format/ordering */
-        Coeffs.A0 = (LVM_INT16) pEqualiserCoefTable[Offset].A0;
-        Coeffs.A1 = (LVM_INT16) pEqualiserCoefTable[Offset].A1;
-        Coeffs.A2 = (LVM_INT16) pEqualiserCoefTable[Offset].A2;
-        Coeffs.B1 = (LVM_INT16)-pEqualiserCoefTable[Offset].B1;
-        Coeffs.B2 = (LVM_INT16)-pEqualiserCoefTable[Offset].B2;
-
-        LoadConst_16((LVM_INT16)0,                                                       /* Value */
-                     (void *)&pData->EqualiserBiquadTaps,   /* Destination Cast to void:\
-                                                               no dereferencing in function*/
-                     (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps)/sizeof(LVM_INT16)));    /* Number of words */
-
-        BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
-                                        &pData->EqualiserBiquadTaps,
-                                        &Coeffs);
-
-        /* Callbacks */
-        switch(pEqualiserCoefTable[Offset].Scale)
-        {
-            case 13:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C13_TRC_WRA_01;
-                break;
-            case 14:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C14_TRC_WRA_01;
-                break;
-            case 15:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F32C15_TRC_WRA_01;
-                break;
-        }
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Equaliser                                          */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Apply the equaliser filter.                                                     */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pInputOutput            Pointer to the input/output buffer                      */
-/*  NumSamples              The number of samples to process                        */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  Always processes in place.                                                  */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
-                                    LVM_FLOAT           *pInputOutput,
-                                    LVM_UINT16          NumSamples)
-{
-
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t  *)&pInstance->Equaliser;
-    LVCS_Coefficient_t  *pCoefficients;
-
-
-    pCoefficients = (LVCS_Coefficient_t *) \
-                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-
-    /*
-     * Check if the equaliser is required
-     */
-    if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
-    {
-        /* Apply filter to the left and right channels */
-        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*) \
-                                        &pCoefficients->EqualiserBiquadInstance,
-                                        (LVM_FLOAT *)pInputOutput,
-                                        (LVM_FLOAT *)pInputOutput,
-                                        (LVM_INT16)NumSamples);
-    }
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
-                                    LVM_INT16           *pInputOutput,
-                                    LVM_UINT16          NumSamples)
-{
-
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t  *)&pInstance->Equaliser;
-    LVCS_Coefficient_t  *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-
-    /*
-     * Check if the equaliser is required
-     */
-    if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
-    {
-        /* Apply filter to the left and right channels */
-        (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
-                                   (LVM_INT16 *)pInputOutput,
-                                   (LVM_INT16 *)pInputOutput,
-                                   (LVM_INT16)NumSamples);
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
new file mode 100644
index 0000000..431b7e3
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Equaliser.h"
+#include "BIQUAD.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_EqualiserInit                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the equaliser module                                                */
+/*                                                                                  */
+/*  The function selects the coefficients for the filters and clears the data       */
+/*  history. It is also used for re-initialisation when one of the system control   */
+/*  parameters changes but will only change the coefficients and clear the history  */
+/*  if the sample rate or speaker type has changed.                                 */
+/*                                                                                  */
+/*  To avoid excessive testing during the sample processing the biquad type is      */
+/*  set as a callback function in the init routine.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16          Offset;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t *)&pInstance->Equaliser;
+    LVCS_Data_t         *pData;
+    LVCS_Coefficient_t  *pCoefficients;
+    BQ_FLOAT_Coefs_t      Coeffs;
+    const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
+
+    pData = (LVCS_Data_t *) \
+                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    /*
+     * If the sample rate changes re-initialise the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Setup the filter coefficients and clear the history
+         */
+        Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
+        pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+
+        /* Left and right filters */
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_FLOAT) pEqualiserCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
+
+        LoadConst_Float((LVM_INT16)0,                                         /* Value */
+                        (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
+
+        BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
+                                        &pData->EqualiserBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pEqualiserCoefTable[Offset].Scale)
+        {
+            case 13:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C13_TRC_WRA_01;
+                break;
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C15_TRC_WRA_01;
+                break;
+        }
+    }
+
+    return(LVCS_SUCCESS);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Equaliser                                          */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply the equaliser filter.                                                     */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInputOutput            Pointer to the input/output buffer                      */
+/*  NumSamples              The number of samples to process                        */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  Always processes in place.                                                  */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
+                                    LVM_FLOAT           *pInputOutput,
+                                    LVM_UINT16          NumSamples)
+{
+
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t  *)&pInstance->Equaliser;
+    LVCS_Coefficient_t  *pCoefficients;
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    /*
+     * Check if the equaliser is required
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
+    {
+        /* Apply filter to the left and right channels */
+        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*) \
+                                        &pCoefficients->EqualiserBiquadInstance,
+                                        (LVM_FLOAT *)pInputOutput,
+                                        (LVM_FLOAT *)pInputOutput,
+                                        (LVM_INT16)NumSamples);
+    }
+
+    return(LVCS_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
index 0e756e7..918d931 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -18,11 +18,6 @@
 #ifndef __LVCS_EQUALISER_H__
 #define __LVCS_EQUALISER_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Structures                                                                    */
@@ -32,14 +27,9 @@
 /* Equaliser structure */
 typedef struct
 {
-#ifndef BUILD_FLOAT
-    void (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-#else
     void (*pBiquadCallBack) (Biquad_FLOAT_Instance_t*, LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
-#endif
 } LVCS_Equaliser_t;
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Function prototypes                                                           */
@@ -48,17 +38,8 @@
 
 LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
                                         LVCS_Params_t       *pParams);
-#ifndef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t            hInstance,
-                                    LVM_INT16                *pInputOutput,
-                                    LVM_UINT16                NumSamples);
-#else
 LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t            hInstance,
                                     LVM_FLOAT                *pInputOutput,
                                     LVM_UINT16                NumSamples);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* EQUALISER_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
index ba05577..c7ee232 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
@@ -18,13 +18,11 @@
 #ifndef __LVCS_HEADPHONE_COEFFS_H__
 #define __LVCS_HEADPHONE_COEFFS_H__
 
-
 /************************************************************************************/
 /*                                                                                  */
 /* The Stereo Enhancer                                                              */
 /*                                                                                  */
 /************************************************************************************/
-#ifdef BUILD_FLOAT
 /* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
 #define CS_MIDDLE_8000_A0                           0.227720
 #define CS_MIDDLE_8000_A1                          (-0.215125)
@@ -151,7 +149,6 @@
 #define CS_SIDE_48000_B2                     0.630405
 #define CS_SIDE_48000_SCALE                          14
 
-#ifdef HIGHER_FS
 /* Coefficients for 88200Hz sample rate.
  * The filter coefficients are obtained by carrying out
  * state-space analysis using the coefficients available
@@ -222,7 +219,6 @@
 #define CS_SIDE_192000_B1                    (-1.891380f)
 #define CS_SIDE_192000_B2                    0.8923460f
 #define CS_SIDE_192000_SCALE                 14
-#endif
 
 /************************************************************************************/
 /*                                                                                  */
@@ -286,7 +282,6 @@
 #define CS_REVERB_22050_B2                    (-0.290990)
 #define CS_REVERB_22050_SCALE                        15
 
-
 /* Reverb coefficients for 24000Hz sample rate, scaled with 1.038030 */
 #define CS_REVERB_24000_A0                       0.479565
 #define CS_REVERB_24000_A1                       0.000000
@@ -319,7 +314,6 @@
 #define CS_REVERB_48000_B2                       0.303347
 #define CS_REVERB_48000_SCALE                        14
 
-#ifdef HIGHER_FS
 /* Reverb coefficients for 88200Hz sample rate, scaled with 0.8 */
 /* Band pass filter with fc1=500 and fc2=8000 */
 #define CS_REVERB_88200_A0                       0.171901f
@@ -354,9 +348,6 @@
 #define CS_REVERB_192000_B2                       0.7804076
 #define CS_REVERB_192000_SCALE                        14
 
-#endif
-
-
 /* Reverb Gain Settings */
 #define LVCS_HEADPHONE_DELAYGAIN               0.800000         /* Algorithm delay path gain */
 #define LVCS_HEADPHONE_OUTPUTGAIN              1.000000         /* Algorithm output gain */
@@ -505,8 +496,6 @@
 #define CSEX_EQUALISER_48000_B2                 (-0.347332)
 #define CSEX_EQUALISER_48000_SCALE                   13
 
-
-#ifdef HIGHER_FS
 /* Equaliser coefficients for 88200Hz sample rate.
  * The filter coefficients are obtained by carrying out
  * state-space analysis using the coefficients available
@@ -567,8 +556,6 @@
 #define CSEX_EQUALISER_192000_B1                 (-1.31074)
 #define CSEX_EQUALISER_192000_B2                 0.31312
 #define CSEX_EQUALISER_192000_SCALE                   13
-#endif
-
 
 #define LVCS_HEADPHONE_SHIFT                          2              /* Output Shift */
 #define LVCS_HEADPHONE_SHIFTLOSS                  0.8477735          /* Output Shift loss */
@@ -576,376 +563,5 @@
 #define LVCS_EX_HEADPHONE_SHIFT                       3              /* EX Output Shift */
 #define LVCS_EX_HEADPHONE_SHIFTLOSS               0.569225           /* EX Output Shift loss */
 #define LVCS_EX_HEADPHONE_GAIN                    0.07794425         /* EX Unprocessed path gain */
-#else
-/* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
-#define CS_MIDDLE_8000_A0                          7462         /* Floating point value 0.227720 */
-#define CS_MIDDLE_8000_A1                        (-7049)        /* Floating point value -0.215125 */
-#define CS_MIDDLE_8000_A2                             0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_8000_B1                       (-30209)        /* Floating point value -0.921899 */
-#define CS_MIDDLE_8000_B2                             0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_8000_SCALE                         15
-#define CS_SIDE_8000_A0                           20036         /* Floating point value 0.611441 */
-#define CS_SIDE_8000_A1                         (-12463)        /* Floating point value -0.380344 */
-#define CS_SIDE_8000_A2                          (-7573)        /* Floating point value -0.231097 */
-#define CS_SIDE_8000_B1                         (-20397)        /* Floating point value -0.622470 */
-#define CS_SIDE_8000_B2                          (-4285)        /* Floating point value -0.130759 */
-#define CS_SIDE_8000_SCALE                           15
-
-/* Stereo Enhancer coefficients for 11025Hz sample rate, scaled with 0.162943 */
-#define CS_MIDDLE_11025_A0                         7564         /* Floating point value 0.230838 */
-#define CS_MIDDLE_11025_A1                       (-7260)        /* Floating point value -0.221559 */
-#define CS_MIDDLE_11025_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_11025_B1                      (-30902)        /* Floating point value -0.943056 */
-#define CS_MIDDLE_11025_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_11025_SCALE                        15
-#define CS_SIDE_11025_A0                          18264         /* Floating point value 0.557372 */
-#define CS_SIDE_11025_A1                        (-12828)        /* Floating point value -0.391490 */
-#define CS_SIDE_11025_A2                         (-5436)        /* Floating point value -0.165881 */
-#define CS_SIDE_11025_B1                        (-28856)        /* Floating point value -0.880608 */
-#define CS_SIDE_11025_B2                           1062         /* Floating point value 0.032397 */
-#define CS_SIDE_11025_SCALE                          15
-
-/* Stereo Enhancer coefficients for 12000Hz sample rate, scaled with 0.162191 */
-#define CS_MIDDLE_12000_A0                         7534         /* Floating point value 0.229932 */
-#define CS_MIDDLE_12000_A1                       (-7256)        /* Floating point value -0.221436 */
-#define CS_MIDDLE_12000_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_12000_B1                      (-31051)        /* Floating point value -0.947616 */
-#define CS_MIDDLE_12000_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_12000_SCALE                        15
-#define CS_SIDE_12000_A0                          18298         /* Floating point value 0.558398 */
-#define CS_SIDE_12000_A1                        (-12852)        /* Floating point value -0.392211 */
-#define CS_SIDE_12000_A2                         (-5446)        /* Floating point value -0.166187 */
-#define CS_SIDE_12000_B1                        (-29247)        /* Floating point value -0.892550 */
-#define CS_SIDE_12000_B2                           1077         /* Floating point value 0.032856 */
-#define CS_SIDE_12000_SCALE                          15
-
-/* Stereo Enhancer coefficients for 16000Hz sample rate, scaled with 0.162371 */
-#define CS_MIDDLE_16000_A0                         7558         /* Floating point value 0.230638 */
-#define CS_MIDDLE_16000_A1                       (-7348)        /* Floating point value -0.224232 */
-#define CS_MIDDLE_16000_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_16000_B1                      (-31475)        /* Floating point value -0.960550 */
-#define CS_MIDDLE_16000_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_16000_SCALE                        15
-#define CS_SIDE_16000_A0                           8187         /* Floating point value 0.499695 */
-#define CS_SIDE_16000_A1                         (-5825)        /* Floating point value -0.355543 */
-#define CS_SIDE_16000_A2                         (-2362)        /* Floating point value -0.144152 */
-#define CS_SIDE_16000_B1                        (-17216)        /* Floating point value -1.050788 */
-#define CS_SIDE_16000_B2                           2361         /* Floating point value 0.144104 */
-#define CS_SIDE_16000_SCALE                          14
-
-/* Stereo Enhancer coefficients for 22050Hz sample rate, scaled with 0.160781 */
-#define CS_MIDDLE_22050_A0                         7496         /* Floating point value 0.228749 */
-#define CS_MIDDLE_22050_A1                       (-7344)        /* Floating point value -0.224128 */
-#define CS_MIDDLE_22050_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_22050_B1                      (-31826)        /* Floating point value -0.971262 */
-#define CS_MIDDLE_22050_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_22050_SCALE                        15
-#define CS_SIDE_22050_A0                           7211         /* Floating point value 0.440112 */
-#define CS_SIDE_22050_A1                         (-4278)        /* Floating point value -0.261096 */
-#define CS_SIDE_22050_A2                         (-2933)        /* Floating point value -0.179016 */
-#define CS_SIDE_22050_B1                        (-18297)        /* Floating point value -1.116786 */
-#define CS_SIDE_22050_B2                           2990         /* Floating point value 0.182507 */
-#define CS_SIDE_22050_SCALE                          14
-
-/* Stereo Enhancer coefficients for 24000Hz sample rate, scaled with 0.161882 */
-#define CS_MIDDLE_24000_A0                         7550         /* Floating point value 0.230395 */
-#define CS_MIDDLE_24000_A1                       (-7409)        /* Floating point value -0.226117 */
-#define CS_MIDDLE_24000_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_24000_B1                      (-31902)        /* Floating point value -0.973573 */
-#define CS_MIDDLE_24000_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_24000_SCALE                        15
-#define CS_SIDE_24000_A0                           6796         /* Floating point value 0.414770 */
-#define CS_SIDE_24000_A1                         (-4705)        /* Floating point value -0.287182 */
-#define CS_SIDE_24000_A2                         (-2090)        /* Floating point value -0.127588 */
-#define CS_SIDE_24000_B1                        (-20147)        /* Floating point value -1.229648 */
-#define CS_SIDE_24000_B2                           4623         /* Floating point value 0.282177 */
-#define CS_SIDE_24000_SCALE                          14
-
-/* Stereo Enhancer coefficients for 32000Hz sample rate, scaled with 0.160322 */
-#define CS_MIDDLE_32000_A0                         7484         /* Floating point value 0.228400 */
-#define CS_MIDDLE_32000_A1                       (-7380)        /* Floating point value -0.225214 */
-#define CS_MIDDLE_32000_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_32000_B1                      (-32117)        /* Floating point value -0.980126 */
-#define CS_MIDDLE_32000_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_32000_SCALE                        15
-#define CS_SIDE_32000_A0                           5973         /* Floating point value 0.364579 */
-#define CS_SIDE_32000_A1                         (-3397)        /* Floating point value -0.207355 */
-#define CS_SIDE_32000_A2                         (-2576)        /* Floating point value -0.157224 */
-#define CS_SIDE_32000_B1                        (-20877)        /* Floating point value -1.274231 */
-#define CS_SIDE_32000_B2                           5120         /* Floating point value 0.312495 */
-#define CS_SIDE_32000_SCALE                          14
-
-/* Stereo Enhancer coefficients for 44100Hz sample rate, scaled with 0.163834 */
-#define CS_MIDDLE_44100_A0                         7654         /* Floating point value 0.233593 */
-#define CS_MIDDLE_44100_A1                       (-7577)        /* Floating point value -0.231225 */
-#define CS_MIDDLE_44100_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_44100_B1                      (-32294)        /* Floating point value -0.985545 */
-#define CS_MIDDLE_44100_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_44100_SCALE                        15
-#define CS_SIDE_44100_A0                           4662         /* Floating point value 0.284573 */
-#define CS_SIDE_44100_A1                         (-4242)        /* Floating point value -0.258910 */
-#define CS_SIDE_44100_A2                          (-420)        /* Floating point value -0.025662 */
-#define CS_SIDE_44100_B1                        (-25760)        /* Floating point value -1.572248 */
-#define CS_SIDE_44100_B2                           9640         /* Floating point value 0.588399 */
-#define CS_SIDE_44100_SCALE                          14
-
-/* Stereo Enhancer coefficients for 48000Hz sample rate, scaled with 0.164402 */
-#define CS_MIDDLE_48000_A0                         7682         /* Floating point value 0.234445 */
-#define CS_MIDDLE_48000_A1                       (-7611)        /* Floating point value -0.232261 */
-#define CS_MIDDLE_48000_A2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_48000_B1                      (-32333)        /* Floating point value -0.986713 */
-#define CS_MIDDLE_48000_B2                            0         /* Floating point value 0.000000 */
-#define CS_MIDDLE_48000_SCALE                        15
-#define CS_SIDE_48000_A0                           4466         /* Floating point value 0.272606 */
-#define CS_SIDE_48000_A1                         (-4374)        /* Floating point value -0.266952 */
-#define CS_SIDE_48000_A2                           (-93)        /* Floating point value -0.005654 */
-#define CS_SIDE_48000_B1                        (-26495)        /* Floating point value -1.617141 */
-#define CS_SIDE_48000_B2                          10329         /* Floating point value 0.630405 */
-#define CS_SIDE_48000_SCALE                          14
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* The Reverb Unit                                                                  */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Reverb delay settings in samples */
-#define LVCS_STEREODELAY_CS_8KHZ                     93         /* Sample rate 8kS/s */
-#define LVCS_STEREODELAY_CS_11KHZ                   128         /* Sample rate 11kS/s */
-#define LVCS_STEREODELAY_CS_12KHZ                   139         /* Sample rate 12kS/s */
-#define LVCS_STEREODELAY_CS_16KHZ                   186         /* Sample rate 16kS/s */
-#define LVCS_STEREODELAY_CS_22KHZ                   256         /* Sample rate 22kS/s */
-#define LVCS_STEREODELAY_CS_24KHZ                   279         /* Sample rate 24kS/s */
-#define LVCS_STEREODELAY_CS_32KHZ                   372         /* Sample rate 32kS/s */
-#define LVCS_STEREODELAY_CS_44KHZ                   512         /* Sample rate 44kS/s */
-#define LVCS_STEREODELAY_CS_48KHZ                   512         /* Sample rate 48kS/s */
-
-/* Reverb coefficients for 8000 Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_8000_A0                         21865         /* Floating point value 0.667271 */
-#define CS_REVERB_8000_A1                       (-21865)        /* Floating point value -0.667271 */
-#define CS_REVERB_8000_A2                             0         /* Floating point value 0.000000 */
-#define CS_REVERB_8000_B1                       (-21895)        /* Floating point value -0.668179 */
-#define CS_REVERB_8000_B2                             0         /* Floating point value 0.000000 */
-#define CS_REVERB_8000_SCALE                         15
-
-/* Reverb coefficients for 11025Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_11025_A0                        22926         /* Floating point value 0.699638 */
-#define CS_REVERB_11025_A1                      (-22926)        /* Floating point value -0.699638 */
-#define CS_REVERB_11025_A2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_11025_B1                      (-24546)        /* Floating point value -0.749096 */
-#define CS_REVERB_11025_B2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_11025_SCALE                        15
-
-/* Reverb coefficients for 12000Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_12000_A0                        23165         /* Floating point value 0.706931 */
-#define CS_REVERB_12000_A1                      (-23165)        /* Floating point value -0.706931 */
-#define CS_REVERB_12000_A2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_12000_B1                      (-25144)        /* Floating point value -0.767327 */
-#define CS_REVERB_12000_B2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_12000_SCALE                        15
-
-/* Reverb coefficients for 16000Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_16000_A0                        23864         /* Floating point value 0.728272 */
-#define CS_REVERB_16000_A1                      (-23864)        /* Floating point value -0.728272 */
-#define CS_REVERB_16000_A2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_16000_B1                      (-26892)        /* Floating point value -0.820679 */
-#define CS_REVERB_16000_B2                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_16000_SCALE                        15
-
-/* Reverb coefficients for 22050Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_22050_A0                        16921         /* Floating point value 0.516396 */
-#define CS_REVERB_22050_A1                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_22050_A2                      (-16921)        /* Floating point value -0.516396 */
-#define CS_REVERB_22050_B1                      (-16991)        /* Floating point value -0.518512 */
-#define CS_REVERB_22050_B2                       (-9535)        /* Floating point value -0.290990 */
-#define CS_REVERB_22050_SCALE                        15
-
-/* Reverb coefficients for 24000Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_24000_A0                        15714         /* Floating point value 0.479565 */
-#define CS_REVERB_24000_A1                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_24000_A2                      (-15714)        /* Floating point value -0.479565 */
-#define CS_REVERB_24000_B1                      (-20898)        /* Floating point value -0.637745 */
-#define CS_REVERB_24000_B2                       (-6518)        /* Floating point value -0.198912 */
-#define CS_REVERB_24000_SCALE                        15
-
-/* Reverb coefficients for 32000Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_32000_A0                        12463         /* Floating point value 0.380349 */
-#define CS_REVERB_32000_A1                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_32000_A2                      (-12463)        /* Floating point value -0.380349 */
-#define CS_REVERB_32000_B1                      (-31158)        /* Floating point value -0.950873 */
-#define CS_REVERB_32000_B2                         1610         /* Floating point value 0.049127 */
-#define CS_REVERB_32000_SCALE                        15
-
-/* Reverb coefficients for 44100Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_44100_A0                         4872         /* Floating point value 0.297389 */
-#define CS_REVERB_44100_A1                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_44100_A2                       (-4872)        /* Floating point value -0.297389 */
-#define CS_REVERB_44100_B1                      (-19668)        /* Floating point value -1.200423 */
-#define CS_REVERB_44100_B2                         4203         /* Floating point value 0.256529 */
-#define CS_REVERB_44100_SCALE                        14
-
-/* Reverb coefficients for 48000Hz sample rate, scaled with 1.038030 */
-#define CS_REVERB_48000_A0                         4566         /* Floating point value 0.278661 */
-#define CS_REVERB_48000_A1                            0         /* Floating point value 0.000000 */
-#define CS_REVERB_48000_A2                       (-4566)        /* Floating point value -0.278661 */
-#define CS_REVERB_48000_B1                      (-20562)        /* Floating point value -1.254993 */
-#define CS_REVERB_48000_B2                         4970         /* Floating point value 0.303347 */
-#define CS_REVERB_48000_SCALE                        14
-
-/* Reverb Gain Settings */
-#define LVCS_HEADPHONE_DELAYGAIN               0.800000         /* Algorithm delay path gain */
-#define LVCS_HEADPHONE_OUTPUTGAIN              1.000000         /* Algorithm output gain */
-#define LVCS_HEADPHONE_PROCGAIN                   18403         /* Processed path gain */
-#define LVCS_HEADPHONE_UNPROCGAIN                 18403         /* Unprocessed path gain */
-#define LVCS_HEADPHONE_GAINCORRECT             1.009343         /* Delay mixer gain correction */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* The Equaliser                                                                    */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Equaliser coefficients for 8000 Hz sample rate, CS scaled with 1.038497 and CSEX scaled with 0.775480 */
-#define CS_EQUALISER_8000_A0                      20698         /* Floating point value 1.263312 */
-#define CS_EQUALISER_8000_A1                     (-9859)        /* Floating point value -0.601748 */
-#define CS_EQUALISER_8000_A2                     (-4599)        /* Floating point value -0.280681 */
-#define CS_EQUALISER_8000_B1                     (-7797)        /* Floating point value -0.475865 */
-#define CS_EQUALISER_8000_B2                     (-6687)        /* Floating point value -0.408154 */
-#define CS_EQUALISER_8000_SCALE                      14
-#define CSEX_EQUALISER_8000_A0                    30912         /* Floating point value 0.943357 */
-#define CSEX_EQUALISER_8000_A1                  (-14724)        /* Floating point value -0.449345 */
-#define CSEX_EQUALISER_8000_A2                   (-6868)        /* Floating point value -0.209594 */
-#define CSEX_EQUALISER_8000_B1                  (-15593)        /* Floating point value -0.475865 */
-#define CSEX_EQUALISER_8000_B2                  (-13374)        /* Floating point value -0.408154 */
-#define CSEX_EQUALISER_8000_SCALE                    15
-
-/* Equaliser coefficients for 11025Hz sample rate, CS scaled with 1.027761 and CSEX scaled with 0.767463 */
-#define CS_EQUALISER_11025_A0                     18041         /* Floating point value 1.101145 */
-#define CS_EQUALISER_11025_A1                      2278         /* Floating point value 0.139020 */
-#define CS_EQUALISER_11025_A2                   (-14163)        /* Floating point value -0.864423 */
-#define CS_EQUALISER_11025_B1                       402         /* Floating point value 0.024541 */
-#define CS_EQUALISER_11025_B2                   (-14892)        /* Floating point value -0.908930 */
-#define CS_EQUALISER_11025_SCALE                     14
-#define CSEX_EQUALISER_11025_A0                   31983         /* Floating point value 0.976058 */
-#define CSEX_EQUALISER_11025_A1                 (-22784)        /* Floating point value -0.695326 */
-#define CSEX_EQUALISER_11025_A2                  (-2976)        /* Floating point value -0.090809 */
-#define CSEX_EQUALISER_11025_B1                 (-20008)        /* Floating point value -0.610594 */
-#define CSEX_EQUALISER_11025_B2                 (-10196)        /* Floating point value -0.311149 */
-#define CSEX_EQUALISER_11025_SCALE                   15
-
-/* Equaliser coefficients for 12000Hz sample rate, CS scaled with 1.032521 and CSEX scaled with 0.771017 */
-#define CS_EQUALISER_12000_A0                     20917         /* Floating point value 1.276661 */
-#define CS_EQUALISER_12000_A1                   (-16671)        /* Floating point value -1.017519 */
-#define CS_EQUALISER_12000_A2                     (-723)        /* Floating point value -0.044128 */
-#define CS_EQUALISER_12000_B1                   (-11954)        /* Floating point value -0.729616 */
-#define CS_EQUALISER_12000_B2                    (-3351)        /* Floating point value -0.204532 */
-#define CS_EQUALISER_12000_SCALE                     14
-#define CSEX_EQUALISER_12000_A0                   16500         /* Floating point value 1.007095 */
-#define CSEX_EQUALISER_12000_A1                 (-14285)        /* Floating point value -0.871912 */
-#define CSEX_EQUALISER_12000_A2                     381         /* Floating point value 0.023232 */
-#define CSEX_EQUALISER_12000_B1                 (-12220)        /* Floating point value -0.745857 */
-#define CSEX_EQUALISER_12000_B2                  (-3099)        /* Floating point value -0.189171 */
-#define CSEX_EQUALISER_12000_SCALE                   14
-
-/* Equaliser coefficients for 16000Hz sample rate, CS scaled with 1.031378 and CSEX scaled with 0.770164 */
-#define CS_EQUALISER_16000_A0                     20998         /* Floating point value 1.281629 */
-#define CS_EQUALISER_16000_A1                   (-17627)        /* Floating point value -1.075872 */
-#define CS_EQUALISER_16000_A2                     (-678)        /* Floating point value -0.041365 */
-#define CS_EQUALISER_16000_B1                   (-11882)        /* Floating point value -0.725239 */
-#define CS_EQUALISER_16000_B2                    (-3676)        /* Floating point value -0.224358 */
-#define CS_EQUALISER_16000_SCALE                     14
-#define CSEX_EQUALISER_16000_A0                   17713         /* Floating point value 1.081091 */
-#define CSEX_EQUALISER_16000_A1                 (-14208)        /* Floating point value -0.867183 */
-#define CSEX_EQUALISER_16000_A2                  (-1151)        /* Floating point value -0.070247 */
-#define CSEX_EQUALISER_16000_B1                  (-8440)        /* Floating point value -0.515121 */
-#define CSEX_EQUALISER_16000_B2                  (-6978)        /* Floating point value -0.425893 */
-#define CSEX_EQUALISER_16000_SCALE                   14
-
-/* Equaliser coefficients for 22050Hz sample rate, CS scaled with 1.041576 and CSEX scaled with 0.777779 */
-#define CS_EQUALISER_22050_A0                     22751         /* Floating point value 1.388605 */
-#define CS_EQUALISER_22050_A1                   (-21394)        /* Floating point value -1.305799 */
-#define CS_EQUALISER_22050_A2                       654         /* Floating point value 0.039922 */
-#define CS_EQUALISER_22050_B1                   (-11788)        /* Floating point value -0.719494 */
-#define CS_EQUALISER_22050_B2                    (-3985)        /* Floating point value -0.243245 */
-#define CS_EQUALISER_22050_SCALE                     14
-#define CSEX_EQUALISER_22050_A0                   20855         /* Floating point value 1.272910 */
-#define CSEX_EQUALISER_22050_A1                 (-21971)        /* Floating point value -1.341014 */
-#define CSEX_EQUALISER_22050_A2                    2744         /* Floating point value 0.167462 */
-#define CSEX_EQUALISER_22050_B1                 (-10063)        /* Floating point value -0.614219 */
-#define CSEX_EQUALISER_22050_B2                  (-5659)        /* Floating point value -0.345384 */
-#define CSEX_EQUALISER_22050_SCALE                   14
-
-/* Equaliser coefficients for 24000Hz sample rate, CS scaled with 1.034495 and CSEX scaled with 0.772491 */
-#define CS_EQUALISER_24000_A0                     23099         /* Floating point value 1.409832 */
-#define CS_EQUALISER_24000_A1                   (-23863)        /* Floating point value -1.456506 */
-#define CS_EQUALISER_24000_A2                      2481         /* Floating point value 0.151410 */
-#define CS_EQUALISER_24000_B1                   (-13176)        /* Floating point value -0.804201 */
-#define CS_EQUALISER_24000_B2                    (-2683)        /* Floating point value -0.163783 */
-#define CS_EQUALISER_24000_SCALE                     14
-#define CSEX_EQUALISER_24000_A0                   21286         /* Floating point value 1.299198 */
-#define CSEX_EQUALISER_24000_A1                 (-23797)        /* Floating point value -1.452447 */
-#define CSEX_EQUALISER_24000_A2                    3940         /* Floating point value 0.240489 */
-#define CSEX_EQUALISER_24000_B1                 (-10966)        /* Floating point value -0.669303 */
-#define CSEX_EQUALISER_24000_B2                  (-4833)        /* Floating point value -0.294984 */
-#define CSEX_EQUALISER_24000_SCALE                   14
-
-/* Equaliser coefficients for 32000Hz sample rate, CS scaled with 1.044559 and CSEX scaled with 0.780006 */
-#define CS_EQUALISER_32000_A0                     25575         /* Floating point value 1.560988 */
-#define CS_EQUALISER_32000_A1                   (-30765)        /* Floating point value -1.877724 */
-#define CS_EQUALISER_32000_A2                      6386         /* Floating point value 0.389741 */
-#define CS_EQUALISER_32000_B1                   (-14867)        /* Floating point value -0.907410 */
-#define CS_EQUALISER_32000_B2                    (-1155)        /* Floating point value -0.070489 */
-#define CS_EQUALISER_32000_SCALE                     14
-#define CSEX_EQUALISER_32000_A0                   14623         /* Floating point value 1.785049 */
-#define CSEX_EQUALISER_32000_A1                 (-18297)        /* Floating point value -2.233497 */
-#define CSEX_EQUALISER_32000_A2                    4313         /* Floating point value 0.526431 */
-#define CSEX_EQUALISER_32000_B1                  (-3653)        /* Floating point value -0.445939 */
-#define CSEX_EQUALISER_32000_B2                  (-4280)        /* Floating point value -0.522446 */
-#define CSEX_EQUALISER_32000_SCALE                   13
-
-/* Equaliser coefficients for 44100Hz sample rate, CS scaled with 1.022170 and CSEX scaled with 0.763288 */
-#define CS_EQUALISER_44100_A0                     13304         /* Floating point value 1.623993 */
-#define CS_EQUALISER_44100_A1                   (-18602)        /* Floating point value -2.270743 */
-#define CS_EQUALISER_44100_A2                      5643         /* Floating point value 0.688829 */
-#define CS_EQUALISER_44100_B1                    (-9152)        /* Floating point value -1.117190 */
-#define CS_EQUALISER_44100_B2                      1067         /* Floating point value 0.130208 */
-#define CS_EQUALISER_44100_SCALE                     13
-#define CSEX_EQUALISER_44100_A0                   16616         /* Floating point value 2.028315 */
-#define CSEX_EQUALISER_44100_A1                 (-23613)        /* Floating point value -2.882459 */
-#define CSEX_EQUALISER_44100_A2                    7410         /* Floating point value 0.904535 */
-#define CSEX_EQUALISER_44100_B1                  (-4860)        /* Floating point value -0.593308 */
-#define CSEX_EQUALISER_44100_B2                  (-3161)        /* Floating point value -0.385816 */
-#define CSEX_EQUALISER_44100_SCALE                   13
-
-/* Equaliser coefficients for 48000Hz sample rate, CS scaled with 1.018635 and CSEX scaled with 0.760648 */
-#define CS_EQUALISER_48000_A0                     13445         /* Floating point value 1.641177 */
-#define CS_EQUALISER_48000_A1                   (-19372)        /* Floating point value -2.364687 */
-#define CS_EQUALISER_48000_A2                      6225         /* Floating point value 0.759910 */
-#define CS_EQUALISER_48000_B1                    (-9558)        /* Floating point value -1.166774 */
-#define CS_EQUALISER_48000_B2                      1459         /* Floating point value 0.178074 */
-#define CS_EQUALISER_48000_SCALE                     13
-#define CSEX_EQUALISER_48000_A0                   17200         /* Floating point value 2.099655 */
-#define CSEX_EQUALISER_48000_A1                 (-25110)        /* Floating point value -3.065220 */
-#define CSEX_EQUALISER_48000_A2                    8277         /* Floating point value 1.010417 */
-#define CSEX_EQUALISER_48000_B1                  (-5194)        /* Floating point value -0.634021 */
-#define CSEX_EQUALISER_48000_B2                  (-2845)        /* Floating point value -0.347332 */
-#define CSEX_EQUALISER_48000_SCALE                   13
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* The Output Gain Correction                                                       */
-/*                                                                                  */
-/************************************************************************************/
-
-#define LVCS_HEADPHONE_SHIFT                          2              /* Output Shift */
-#define LVCS_HEADPHONE_SHIFTLOSS                  27779              /* Output Shift loss */
-#define LVCS_HEADPHONE_GAIN                        6840              /* Unprocessed path gain */
-#define LVCS_EX_HEADPHONE_SHIFT                       3              /* EX Output Shift */
-#define LVCS_EX_HEADPHONE_SHIFTLOSS               18600              /* EX Output Shift loss */
-#define LVCS_EX_HEADPHONE_GAIN                     5108              /* EX Unprocessed path gain */
-#endif
 #endif
 
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
deleted file mode 100644
index d4c7627..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_Tables.h"
-
-/****************************************************************************************/
-/*                                                                                      */
-/* FUNCTION:                LVCS_Memory                                                 */
-/*                                                                                      */
-/* DESCRIPTION:                                                                         */
-/*  This function is used for memory allocation and free. It can be called in           */
-/*  two ways:                                                                           */
-/*                                                                                      */
-/*      hInstance = NULL                Returns the memory requirements                 */
-/*      hInstance = Instance handle     Returns the memory requirements and             */
-/*                                      allocated base addresses for the instance       */
-/*                                                                                      */
-/*  When this function is called for memory allocation (hInstance=NULL) it is           */
-/*  passed the default capabilities.                                                    */
-/*                                                                                      */
-/*  When called for memory allocation the memory base address pointers are NULL on      */
-/*  return.                                                                             */
-/*                                                                                      */
-/*  When the function is called for free (hInstance = Instance Handle) the              */
-/*  capabilities are ignored and the memory table returns the allocated memory and      */
-/*  base addresses used during initialisation.                                          */
-/*                                                                                      */
-/* PARAMETERS:                                                                          */
-/*  hInstance               Instance Handle                                             */
-/*  pMemoryTable            Pointer to an empty memory definition table                 */
-/*  pCapabilities           Pointer to the default capabilites                          */
-/*                                                                                      */
-/* RETURNS:                                                                             */
-/*  LVCS_Success            Succeeded                                                   */
-/*                                                                                      */
-/* NOTES:                                                                               */
-/*  1.  This function may be interrupted by the LVCS_Process function                   */
-/*                                                                                      */
-/****************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t          hInstance,
-                                 LVCS_MemTab_t          *pMemoryTable,
-                                 LVCS_Capabilities_t    *pCapabilities)
-{
-
-    LVM_UINT32          ScratchSize;
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t *)hInstance;
-
-
-    /*
-     * Fill in the memory table
-     */
-    if (hInstance == LVM_NULL)
-    {
-        /*
-         * Instance memory
-         */
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Instance_t);
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVCS_PERSISTENT;
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
-
-        /*
-         * Data memory
-         */
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Data_t);
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVCS_DATA;
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
-
-        /*
-         * Coefficient memory
-         */
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size         = (LVM_UINT32)sizeof(LVCS_Coefficient_t);
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVCS_COEFFICIENT;
-        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
-
-        /*
-         * Scratch memory
-         */
-#ifdef BUILD_FLOAT
-        /* Inplace processing */
-        ScratchSize = (LVM_UINT32) \
-                        (LVCS_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * pCapabilities->MaxBlockSize);
-#else
-        ScratchSize = (LVM_UINT32)(LVCS_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);     /* Inplace processing */
-#endif
-        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Size         = ScratchSize;
-        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Type         = LVCS_SCRATCH;
-        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
-    }
-    else
-    {
-        /* Read back memory allocation table */
-        *pMemoryTable = pInstance->MemoryTable;
-    }
-
-    return(LVCS_SUCCESS);
-}
-
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Init                                               */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Create and initialisation function for the Concert Sound module                 */
-/*                                                                                  */
-/*  This function can be used to create an algorithm instance by calling with       */
-/*  hInstance set to LVM_NULL. In this case the algorithm returns the new instance  */
-/*  handle.                                                                         */
-/*                                                                                  */
-/*  This function can be used to force a full re-initialisation of the algorithm    */
-/*  by calling with hInstance = Instance Handle. In this case the memory table      */
-/*  should be correct for the instance, this can be ensured by calling the function */
-/*  LVCS_Memory before calling this function.                                       */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance handle                                         */
-/*  pMemoryTable            Pointer to the memory definition table                  */
-/*  pCapabilities           Pointer to the capabilities structure                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Initialisation succeeded                                */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  The instance handle is the pointer to the base address of the first memory  */
-/*      region.                                                                     */
-/*  2.  This function must not be interrupted by the LVCS_Process function          */
-/*  3.  This function must be called with the same capabilities as used for the     */
-/*      call to the memory function                                                 */
-/*                                                                                  */
-/************************************************************************************/
-
-LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t         *phInstance,
-                               LVCS_MemTab_t         *pMemoryTable,
-                               LVCS_Capabilities_t   *pCapabilities)
-{
-
-    LVCS_Instance_t                 *pInstance;
-    LVCS_VolCorrect_t               *pLVCS_VolCorrectTable;
-
-
-    /*
-     * Set the instance handle if not already initialised
-     */
-    if (*phInstance == LVM_NULL)
-    {
-        *phInstance = (LVCS_Handle_t)pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress;
-    }
-    pInstance =(LVCS_Instance_t  *)*phInstance;
-
-
-    /*
-     * Save the capabilities in the instance structure
-     */
-    pInstance->Capabilities = *pCapabilities;
-
-    /*
-     * Save the memory table in the instance structure
-     */
-    pInstance->MemoryTable = *pMemoryTable;
-
-
-    /*
-     * Set all initial parameters to invalid to force a full initialisation
-     */
-    pInstance->Params.OperatingMode  = LVCS_OFF;
-    pInstance->Params.SpeakerType    = LVCS_SPEAKERTYPE_MAX;
-    pInstance->OutputDevice          = LVCS_HEADPHONE;
-    pInstance->Params.SourceFormat   = LVCS_SOURCEMAX;
-    pInstance->Params.CompressorMode = LVM_MODE_OFF;
-    pInstance->Params.SampleRate     = LVM_FS_INVALID;
-    pInstance->Params.EffectLevel    = 0;
-    pInstance->Params.ReverbLevel    = (LVM_UINT16)0x8000;
-    pLVCS_VolCorrectTable            = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
-    pInstance->VolCorrect            = pLVCS_VolCorrectTable[0];
-    pInstance->TransitionGain        = 0;
-
-    /* These current and target values are intialized again in LVCS_Control.c */
-    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
-    /* These current and target values are intialized again in LVCS_Control.c */
-    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,0);
-
-    /*
-     * Initialise the bypass variables
-     */
-    pInstance->MSTarget0=0;
-    pInstance->MSTarget1=0;
-    pInstance->bInOperatingModeTransition          = LVM_FALSE;
-    pInstance->bTimerDone                        = LVM_FALSE;
-    pInstance->TimerParams.CallBackParam         = 0;
-    pInstance->TimerParams.pCallBack             = LVCS_TimerCallBack;
-    pInstance->TimerParams.pCallbackInstance     = pInstance;
-    pInstance->TimerParams.pCallBackParams       = LVM_NULL;
-
-    return(LVCS_SUCCESS);
-}
-
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
new file mode 100644
index 0000000..630ecf7
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Memory                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) it is           */
+/*  passed the default capabilities.                                                    */
+/*                                                                                      */
+/*  When called for memory allocation the memory base address pointers are NULL on      */
+/*  return.                                                                             */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the              */
+/*  capabilities are ignored and the memory table returns the allocated memory and      */
+/*  base addresses used during initialisation.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilites                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVCS_Process function                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t          hInstance,
+                                 LVCS_MemTab_t          *pMemoryTable,
+                                 LVCS_Capabilities_t    *pCapabilities)
+{
+
+    LVM_UINT32          ScratchSize;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t *)hInstance;
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Instance_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVCS_PERSISTENT;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Data memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Data_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVCS_DATA;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Coefficient memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size         = (LVM_UINT32)sizeof(LVCS_Coefficient_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVCS_COEFFICIENT;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        /* Inplace processing */
+        ScratchSize = (LVM_UINT32) \
+                        (LVCS_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * pCapabilities->MaxBlockSize);
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Size         = ScratchSize;
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Type         = LVCS_SCRATCH;
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Init                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Create and initialisation function for the Concert Sound module                 */
+/*                                                                                  */
+/*  This function can be used to create an algorithm instance by calling with       */
+/*  hInstance set to LVM_NULL. In this case the algorithm returns the new instance  */
+/*  handle.                                                                         */
+/*                                                                                  */
+/*  This function can be used to force a full re-initialisation of the algorithm    */
+/*  by calling with hInstance = Instance Handle. In this case the memory table      */
+/*  should be correct for the instance, this can be ensured by calling the function */
+/*  LVCS_Memory before calling this function.                                       */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pMemoryTable            Pointer to the memory definition table                  */
+/*  pCapabilities           Pointer to the capabilities structure                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Initialisation succeeded                                */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  The instance handle is the pointer to the base address of the first memory  */
+/*      region.                                                                     */
+/*  2.  This function must not be interrupted by the LVCS_Process function          */
+/*  3.  This function must be called with the same capabilities as used for the     */
+/*      call to the memory function                                                 */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t         *phInstance,
+                               LVCS_MemTab_t         *pMemoryTable,
+                               LVCS_Capabilities_t   *pCapabilities)
+{
+
+    LVCS_Instance_t                 *pInstance;
+    LVCS_VolCorrect_t               *pLVCS_VolCorrectTable;
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = (LVCS_Handle_t)pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress;
+    }
+    pInstance =(LVCS_Instance_t  *)*phInstance;
+
+    /*
+     * Save the capabilities in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->MemoryTable = *pMemoryTable;
+
+    /*
+     * Set all initial parameters to invalid to force a full initialisation
+     */
+    pInstance->Params.OperatingMode  = LVCS_OFF;
+    pInstance->Params.SpeakerType    = LVCS_SPEAKERTYPE_MAX;
+    pInstance->OutputDevice          = LVCS_HEADPHONE;
+    pInstance->Params.SourceFormat   = LVCS_SOURCEMAX;
+    pInstance->Params.CompressorMode = LVM_MODE_OFF;
+    pInstance->Params.SampleRate     = LVM_FS_INVALID;
+    pInstance->Params.EffectLevel    = 0;
+    pInstance->Params.ReverbLevel    = (LVM_UINT16)0x8000;
+    pLVCS_VolCorrectTable            = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+    pInstance->VolCorrect            = pLVCS_VolCorrectTable[0];
+    pInstance->TransitionGain        = 0;
+
+    /* These current and target values are intialized again in LVCS_Control.c */
+    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
+    /* These current and target values are intialized again in LVCS_Control.c */
+    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,0);
+
+    /*
+     * Initialise the bypass variables
+     */
+    pInstance->MSTarget0=0;
+    pInstance->MSTarget1=0;
+    pInstance->bInOperatingModeTransition          = LVM_FALSE;
+    pInstance->bTimerDone                        = LVM_FALSE;
+    pInstance->TimerParams.CallBackParam         = 0;
+    pInstance->TimerParams.pCallBack             = LVCS_TimerCallBack;
+    pInstance->TimerParams.pCallbackInstance     = pInstance;
+    pInstance->TimerParams.pCallBackParams       = LVM_NULL;
+
+    return(LVCS_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index ab8ccd1..154ea55 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -27,11 +27,6 @@
 #ifndef __LVCS_PRIVATE_H__
 #define __LVCS_PRIVATE_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Includes                                                                        */
@@ -45,7 +40,6 @@
 #include "LVCS_BypassMix.h"                     /* Bypass Mixer module definitions */
 #include "LVM_Timer.h"
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Defines                                                                         */
@@ -60,7 +54,11 @@
 #define LVCS_COMPGAINFRAME          64          /* Compressor gain update interval */
 
 /* Memory */
+#ifdef SUPPORT_MC
+#define LVCS_SCRATCHBUFFERS              8      /* Number of buffers required for inplace processing */
+#else
 #define LVCS_SCRATCHBUFFERS              6      /* Number of buffers required for inplace processing */
+#endif
 #ifdef SUPPORT_MC
 /*
  * The Concert Surround module applies processing only on the first two
@@ -79,7 +77,6 @@
 #define LVCS_NR_OF_FS                    9
 #define LVCS_NR_OF_CHAN_CFG              2
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Types                                                                           */
@@ -94,7 +91,6 @@
     LVCS_DEVICE_MAX = LVM_MAXENUM
 } LVCS_OutputDevice_en;
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Structures                                                                      */
@@ -104,17 +100,10 @@
 /* Volume correction structure */
 typedef struct
 {
-#ifdef BUILD_FLOAT
     LVM_FLOAT   CompFull;                       /* Post CS compression 100% effect */
     LVM_FLOAT   CompMin;                        /* Post CS compression 0% effect */
     LVM_FLOAT   GainFull;                       /* CS gain correct 100% effect */
     LVM_FLOAT   GainMin;                        /* CS gain correct 0% effect */
-#else
-    LVM_INT16   CompFull;                       /* Post CS compression 100% effect */
-    LVM_INT16   CompMin;                        /* Post CS compression 0% effect */
-    LVM_INT16   GainFull;                       /* CS gain correct 100% effect */
-    LVM_INT16   GainMin;                        /* CS gain correct 0% effect */
-#endif
 } LVCS_VolCorrect_t;
 
 /* Instance structure */
@@ -128,13 +117,8 @@
     /* Private parameters */
     LVCS_OutputDevice_en    OutputDevice;       /* Selected output device type */
     LVCS_VolCorrect_t       VolCorrect;         /* Volume correction settings */
-#ifndef BUILD_FLOAT
-    LVM_INT16               TransitionGain;     /* Transition gain */
-    LVM_INT16               CompressGain;       /* Last used compressor gain*/
-#else
     LVM_FLOAT               TransitionGain;     /* Transition gain */
     LVM_FLOAT               CompressGain;       /* Last used compressor gain*/
-#endif
 
     /* Sub-block configurations */
     LVCS_StereoEnhancer_t   StereoEnhancer;     /* Stereo enhancer configuration */
@@ -155,44 +139,24 @@
 /* Coefficient Structure */
 typedef struct
 {
-#ifdef BUILD_FLOAT
     Biquad_FLOAT_Instance_t       EqualiserBiquadInstance;
     Biquad_FLOAT_Instance_t       ReverbBiquadInstance;
     Biquad_FLOAT_Instance_t       SEBiquadInstanceMid;
     Biquad_FLOAT_Instance_t       SEBiquadInstanceSide;
-#else
-    Biquad_Instance_t       EqualiserBiquadInstance;
-    Biquad_Instance_t       ReverbBiquadInstance;
-    Biquad_Instance_t       SEBiquadInstanceMid;
-    Biquad_Instance_t       SEBiquadInstanceSide;
-#endif
 } LVCS_Coefficient_t;
 
 /* Data Structure */
 typedef struct
 {
-#ifdef BUILD_FLOAT
     Biquad_2I_Order2_FLOAT_Taps_t EqualiserBiquadTaps;
     Biquad_2I_Order2_FLOAT_Taps_t ReverbBiquadTaps;
     Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
     Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
-#else
-    Biquad_2I_Order2_Taps_t EqualiserBiquadTaps;
-    Biquad_2I_Order2_Taps_t ReverbBiquadTaps;
-    Biquad_1I_Order1_Taps_t SEBiquadTapsMid;
-    Biquad_1I_Order2_Taps_t SEBiquadTapsSide;
-#endif
 } LVCS_Data_t;
 
 void LVCS_TimerCallBack (   void* hInstance,
                             void* pCallBackParams,
                             LVM_INT32 CallbackParam);
 
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif      /* PRIVATE_H */
 
-
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
deleted file mode 100644
index ef1d9eb..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "VectorArithmetic.h"
-#include "CompLim.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Process_CS                                         */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Process function for the Concert Sound module based on the following block      */
-/*  diagram:                                                                        */
-/*            _________    ________    _____    _______     ___   ______            */
-/*           |         |  |        |  |     |  |       |   |   | |      |           */
-/*     ----->| Stereo  |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |---->      */
-/*        |  | Enhance |  |________|  |_____|  |_______|   |___| |______|           */
-/*        |  |_________|                                     |                      */
-/*        |                                 ___________      |                      */
-/*        |                                |           |     |                      */
-/*        |------------------------------->| 1 - Alpha |-----|                      */
-/*                                         |___________|                            */
-/*                                                                                  */
-/*  The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have    */
-/*  their gain to give a near peak to peak output (-0.1dBFS) with a worst case      */
-/*  input signal. The gains of these blocks are re-combined in the Alpha mixer and  */
-/*  the gain block folloing the sum.                                                */
-/*                                                                                  */
-/*  The processing uses the output buffer for data storage after each processing    */
-/*  block. When processing is inplace a copy of the input signal is made in scratch */
-/*  memory for the 1-Alpha path.                                                    */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance handle                                         */
-/*  pInData                 Pointer to the input data                               */
-/*  pOutData                Pointer to the output data                              */
-/*  NumSamples              Number of samples in the input buffer                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Succeeded                                               */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
-                                     const LVM_FLOAT            *pInData,
-                                     LVM_FLOAT                  *pOutData,
-                                     LVM_UINT16                 NumSamples)
-{
-    const LVM_FLOAT     *pInput;
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVM_FLOAT           *pScratch;
-    LVCS_ReturnStatus_en err;
-#ifdef SUPPORT_MC
-    LVM_FLOAT           *pStIn;
-    LVM_INT32           channels = pInstance->Params.NrChannels;
-#define NrFrames NumSamples  // alias for clarity
-
-    /*In case of mono processing, stereo input is created from mono
-     *and stored in pInData before applying any of the effects.
-     *However we do not update the value pInstance->Params.NrChannels
-     *at this point.
-     *So to treat the pInData as stereo we are setting channels to 2
-     */
-    if (channels == 1)
-    {
-        channels = 2;
-    }
-#endif
-
-    pScratch  = (LVM_FLOAT *) \
-                  pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-
-    /*
-     * Check if the processing is inplace
-     */
-#ifdef SUPPORT_MC
-    /*
-     * The pInput buffer holds the first 2 (Left, Right) channels information.
-     * Hence the memory required by this buffer is 2 * NumFrames.
-     * The Concert Surround module carries out processing only on L, R.
-     */
-    pInput = pScratch + (2 * NrFrames);
-    pStIn  = pScratch + (LVCS_SCRATCHBUFFERS * NrFrames);
-    /* The first two channel data is extracted from the input data and
-     * copied into pInput buffer
-     */
-    Copy_Float_Mc_Stereo((LVM_FLOAT *)pInData,
-                         (LVM_FLOAT *)pInput,
-                         NrFrames,
-                         channels);
-    Copy_Float((LVM_FLOAT *)pInput,
-               (LVM_FLOAT *)pStIn,
-               (LVM_INT16)(2 * NrFrames));
-#else
-    if (pInData == pOutData)
-    {
-        /* Processing inplace */
-        pInput = pScratch + (2 * NumSamples);
-        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
-                   (LVM_FLOAT *)pInput,            /* Destination */
-                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
-    }
-    else
-    {
-        /* Processing outplace */
-        pInput = pInData;
-    }
-#endif
-    /*
-     * Call the stereo enhancer
-     */
-#ifdef SUPPORT_MC
-    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
-                              pStIn,                  /* Pointer to the input data */
-                              pOutData,               /* Pointer to the output data */
-                              NrFrames);              /* Number of frames to process */
-#else
-    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
-                              pInData,                    /* Pointer to the input data */
-                              pOutData,                   /* Pointer to the output data */
-                              NumSamples);                /* Number of samples to process */
-#endif
-
-    /*
-     * Call the reverb generator
-     */
-    err = LVCS_ReverbGenerator(hInstance,             /* Instance handle */
-                               pOutData,                  /* Pointer to the input data */
-                               pOutData,                  /* Pointer to the output data */
-                               NumSamples);               /* Number of samples to process */
-
-    /*
-     * Call the equaliser
-     */
-    err = LVCS_Equaliser(hInstance,                   /* Instance handle */
-                         pOutData,                        /* Pointer to the input data */
-                         NumSamples);                     /* Number of samples to process */
-
-    /*
-     * Call the bypass mixer
-     */
-    err = LVCS_BypassMixer(hInstance,                 /* Instance handle */
-                           pOutData,                      /* Pointer to the processed data */
-                           pInput,                        /* Pointer to the input (unprocessed) data */
-                           pOutData,                      /* Pointer to the output data */
-                           NumSamples);                   /* Number of samples to process */
-
-    if(err != LVCS_SUCCESS)
-    {
-        return err;
-    }
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
-                                     const LVM_INT16            *pInData,
-                                     LVM_INT16                  *pOutData,
-                                     LVM_UINT16                 NumSamples)
-{
-    const LVM_INT16     *pInput;
-    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVM_INT16           *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-    LVCS_ReturnStatus_en err;
-
-    /*
-     * Check if the processing is inplace
-     */
-    if (pInData == pOutData)
-    {
-        /* Processing inplace */
-        pInput = pScratch + (2*NumSamples);
-        Copy_16((LVM_INT16 *)pInData,           /* Source */
-                (LVM_INT16 *)pInput,            /* Destination */
-                (LVM_INT16)(2*NumSamples));     /* Left and right */
-    }
-    else
-    {
-        /* Processing outplace */
-        pInput = pInData;
-    }
-
-    /*
-     * Call the stereo enhancer
-     */
-    err=LVCS_StereoEnhancer(hInstance,              /* Instance handle */
-                        pInData,                    /* Pointer to the input data */
-                        pOutData,                   /* Pointer to the output data */
-                        NumSamples);                /* Number of samples to process */
-
-    /*
-     * Call the reverb generator
-     */
-    err=LVCS_ReverbGenerator(hInstance,             /* Instance handle */
-                         pOutData,                  /* Pointer to the input data */
-                         pOutData,                  /* Pointer to the output data */
-                         NumSamples);               /* Number of samples to process */
-
-    /*
-     * Call the equaliser
-     */
-    err=LVCS_Equaliser(hInstance,                   /* Instance handle */
-                   pOutData,                        /* Pointer to the input data */
-                   NumSamples);                     /* Number of samples to process */
-
-    /*
-     * Call the bypass mixer
-     */
-    err=LVCS_BypassMixer(hInstance,                 /* Instance handle */
-                     pOutData,                      /* Pointer to the processed data */
-                     pInput,                        /* Pointer to the input (unprocessed) data */
-                     pOutData,                      /* Pointer to the output data */
-                     NumSamples);                   /* Number of samples to process */
-
-    if(err !=LVCS_SUCCESS)
-    {
-        return err;
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Process                                            */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Process function for the Concert Sound module. The implementation supports two  */
-/*  variants of the algorithm, one for headphones and one for mobile speakers.      */
-/*                                                                                  */
-/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono    */
-/*  format is not supported, the calling routine must convert the mono stream to    */
-/*  mono-in-stereo.                                                                 */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance handle                                         */
-/*  pInData                 Pointer to the input data                               */
-/*  pOutData                Pointer to the output data                              */
-/*  NumSamples              Number of samples in the input buffer                   */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Succeeded                                               */
-/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size       */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
-                                  const LVM_FLOAT           *pInData,
-                                  LVM_FLOAT                 *pOutData,
-                                  LVM_UINT16                NumSamples)
-{
-
-    LVCS_Instance_t *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_ReturnStatus_en err;
-#ifdef SUPPORT_MC
-    /*Extract number of Channels info*/
-    LVM_INT32 channels = pInstance->Params.NrChannels;
-#define NrFrames NumSamples  // alias for clarity
-    if (channels == 1)
-    {
-        channels = 2;
-    }
-#endif
-    /*
-     * Check the number of samples is not too large
-     */
-    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
-    {
-        return(LVCS_TOOMANYSAMPLES);
-    }
-
-    /*
-     * Check if the algorithm is enabled
-     */
-    if (pInstance->Params.OperatingMode != LVCS_OFF)
-    {
-        /*
-         * Call CS process function
-         */
-            err = LVCS_Process_CS(hInstance,
-                                  pInData,
-                                  pOutData,
-                                  NumSamples);
-
-
-        /*
-         * Compress to reduce expansion effect of Concert Sound and correct volume
-         * differences for difference settings. Not applied in test modes
-         */
-        if ((pInstance->Params.OperatingMode == LVCS_ON)&& \
-                                        (pInstance->Params.CompressorMode == LVM_MODE_ON))
-        {
-            LVM_FLOAT Gain = pInstance->VolCorrect.CompMin;
-            LVM_FLOAT Current1;
-
-            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
-            Gain = (LVM_FLOAT)(  pInstance->VolCorrect.CompMin
-                               - (((LVM_FLOAT)pInstance->VolCorrect.CompMin  * (Current1)))
-                               + (((LVM_FLOAT)pInstance->VolCorrect.CompFull * (Current1))));
-
-            if(NumSamples < LVCS_COMPGAINFRAME)
-            {
-                NonLinComp_Float(Gain,                    /* Compressor gain setting */
-                                 pOutData,
-                                 pOutData,
-                                 (LVM_INT32)(2 * NumSamples));
-            }
-            else
-            {
-                LVM_FLOAT  GainStep;
-                LVM_FLOAT  FinalGain;
-                LVM_INT16  SampleToProcess = NumSamples;
-                LVM_FLOAT  *pOutPtr;
-
-                /* Large changes in Gain can cause clicks in output
-                   Split data into small blocks and use interpolated gain values */
-
-                GainStep = (LVM_FLOAT)(((Gain-pInstance->CompressGain) * \
-                                                LVCS_COMPGAINFRAME) / NumSamples);
-
-                if((GainStep == 0) && (pInstance->CompressGain < Gain))
-                {
-                    GainStep = 1;
-                }
-                else
-                {
-                    if((GainStep == 0) && (pInstance->CompressGain > Gain))
-                    {
-                        GainStep = -1;
-                    }
-                }
-
-                FinalGain = Gain;
-                Gain = pInstance->CompressGain;
-                pOutPtr = pOutData;
-
-                while(SampleToProcess > 0)
-                {
-                    Gain = (LVM_FLOAT)(Gain + GainStep);
-                    if((GainStep > 0) && (FinalGain <= Gain))
-                    {
-                        Gain = FinalGain;
-                        GainStep = 0;
-                    }
-
-                    if((GainStep < 0) && (FinalGain > Gain))
-                    {
-                        Gain = FinalGain;
-                        GainStep = 0;
-                    }
-
-                    if(SampleToProcess > LVCS_COMPGAINFRAME)
-                    {
-                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
-                                         pOutPtr,
-                                         pOutPtr,
-                                         (LVM_INT32)(2 * LVCS_COMPGAINFRAME));
-                        pOutPtr += (2 * LVCS_COMPGAINFRAME);
-                        SampleToProcess = (LVM_INT16)(SampleToProcess - LVCS_COMPGAINFRAME);
-                    }
-                    else
-                    {
-                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
-                                         pOutPtr,
-                                         pOutPtr,
-                                         (LVM_INT32)(2 * SampleToProcess));
-                        SampleToProcess = 0;
-                    }
-
-                }
-            }
-
-            /* Store gain value*/
-            pInstance->CompressGain = Gain;
-        }
-
-
-        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
-
-            /*
-             * Re-init bypass mix when timer has completed
-             */
-            if ((pInstance->bTimerDone == LVM_TRUE) &&
-                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
-            {
-                err = LVCS_BypassMixInit(hInstance,
-                                         &pInstance->Params);
-
-                if(err != LVCS_SUCCESS)
-                {
-                    return err;
-                }
-
-            }
-            else{
-                LVM_Timer ( &pInstance->TimerInstance,
-                            (LVM_INT16)NumSamples);
-            }
-        }
-#ifdef SUPPORT_MC
-        Copy_Float_Stereo_Mc(pInData,
-                             pOutData,
-                             NrFrames,
-                             channels);
-#endif
-    }
-    else
-    {
-        if (pInData != pOutData)
-        {
-#ifdef SUPPORT_MC
-            /*
-             * The algorithm is disabled so just copy the data
-             */
-            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
-                       (LVM_FLOAT *)pOutData,                  /* Destination */
-                       (LVM_INT16)(channels * NrFrames));    /* All Channels*/
-#else
-            /*
-             * The algorithm is disabled so just copy the data
-             */
-            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
-                       (LVM_FLOAT *)pOutData,                  /* Destination */
-                       (LVM_INT16)(2 * NumSamples));             /* Left and right */
-#endif
-        }
-    }
-
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
-                                  const LVM_INT16           *pInData,
-                                  LVM_INT16                 *pOutData,
-                                  LVM_UINT16                NumSamples)
-{
-
-    LVCS_Instance_t *pInstance =(LVCS_Instance_t  *)hInstance;
-    LVCS_ReturnStatus_en err;
-
-    /*
-     * Check the number of samples is not too large
-     */
-    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
-    {
-        return(LVCS_TOOMANYSAMPLES);
-    }
-
-    /*
-     * Check if the algorithm is enabled
-     */
-    if (pInstance->Params.OperatingMode != LVCS_OFF)
-    {
-        /*
-         * Call CS process function
-         */
-            err=LVCS_Process_CS(hInstance,
-                            pInData,
-                            pOutData,
-                            NumSamples);
-
-        /*
-         * Compress to reduce expansion effect of Concert Sound and correct volume
-         * differences for difference settings. Not applied in test modes
-         */
-        if ((pInstance->Params.OperatingMode == LVCS_ON)&&(pInstance->Params.CompressorMode == LVM_MODE_ON))
-        {
-            LVM_INT16 Gain = pInstance->VolCorrect.CompMin;
-            LVM_INT32 Current1;
-
-            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
-            Gain = (LVM_INT16)(  pInstance->VolCorrect.CompMin
-                               - (((LVM_INT32)pInstance->VolCorrect.CompMin  * (Current1)) >> 15)
-                               + (((LVM_INT32)pInstance->VolCorrect.CompFull * (Current1)) >> 15) );
-
-            if(NumSamples < LVCS_COMPGAINFRAME)
-            {
-                NonLinComp_D16(Gain,                    /* Compressor gain setting */
-                    pOutData,
-                    pOutData,
-                    (LVM_INT32)(2*NumSamples));
-            }
-            else
-            {
-                LVM_INT16  GainStep;
-                LVM_INT16  FinalGain;
-                LVM_INT16  SampleToProcess = NumSamples;
-                LVM_INT16  *pOutPtr;
-
-                /* Large changes in Gain can cause clicks in output
-                   Split data into small blocks and use interpolated gain values */
-
-                GainStep = (LVM_INT16)(((Gain-pInstance->CompressGain) * LVCS_COMPGAINFRAME)/NumSamples);
-
-                if((GainStep ==0)&&(pInstance->CompressGain < Gain))
-                {
-                    GainStep=1;
-                }
-                else
-                {
-                    if((GainStep ==0)&&(pInstance->CompressGain > Gain))
-                    {
-                        GainStep=-1;
-                    }
-                }
-
-                FinalGain = Gain;
-                Gain = pInstance->CompressGain;
-                pOutPtr = pOutData;
-
-                while(SampleToProcess > 0)
-                {
-                    Gain = (LVM_INT16)(Gain + GainStep);
-                    if((GainStep > 0)&& (FinalGain <= Gain))
-                    {
-                        Gain = FinalGain;
-                        GainStep =0;
-                    }
-
-                    if((GainStep < 0)&& (FinalGain > Gain))
-                    {
-                        Gain = FinalGain;
-                        GainStep =0;
-                    }
-
-                    if(SampleToProcess > LVCS_COMPGAINFRAME)
-                    {
-                        NonLinComp_D16(Gain,                    /* Compressor gain setting */
-                            pOutPtr,
-                            pOutPtr,
-                            (LVM_INT32)(2*LVCS_COMPGAINFRAME));
-                        pOutPtr +=(2*LVCS_COMPGAINFRAME);
-                        SampleToProcess = (LVM_INT16)(SampleToProcess-LVCS_COMPGAINFRAME);
-                    }
-                    else
-                    {
-                        NonLinComp_D16(Gain,                    /* Compressor gain setting */
-                            pOutPtr,
-                            pOutPtr,
-                            (LVM_INT32)(2*SampleToProcess));
-
-                        SampleToProcess = 0;
-                    }
-
-                }
-            }
-
-            /* Store gain value*/
-            pInstance->CompressGain = Gain;
-        }
-
-
-        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
-
-            /*
-             * Re-init bypass mix when timer has completed
-             */
-            if ((pInstance->bTimerDone == LVM_TRUE) &&
-                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
-            {
-                err=LVCS_BypassMixInit(hInstance,
-                                   &pInstance->Params);
-
-                if(err != LVCS_SUCCESS)
-                {
-                    return err;
-                }
-
-            }
-            else{
-                LVM_Timer ( &pInstance->TimerInstance,
-                            (LVM_INT16)NumSamples);
-            }
-        }
-    }
-    else
-    {
-        if (pInData != pOutData)
-        {
-            /*
-             * The algorithm is disabled so just copy the data
-             */
-            Copy_16((LVM_INT16 *)pInData,               /* Source */
-                (LVM_INT16 *)pOutData,                  /* Destination */
-                (LVM_INT16)(2*NumSamples));             /* Left and right */
-        }
-    }
-
-
-    return(LVCS_SUCCESS);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp
new file mode 100644
index 0000000..8e09be2
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "VectorArithmetic.h"
+#include "CompLim.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Process_CS                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Process function for the Concert Sound module based on the following block      */
+/*  diagram:                                                                        */
+/*            _________    ________    _____    _______     ___   ______            */
+/*           |         |  |        |  |     |  |       |   |   | |      |           */
+/*     ----->| Stereo  |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |---->      */
+/*        |  | Enhance |  |________|  |_____|  |_______|   |___| |______|           */
+/*        |  |_________|                                     |                      */
+/*        |                                 ___________      |                      */
+/*        |                                |           |     |                      */
+/*        |------------------------------->| 1 - Alpha |-----|                      */
+/*                                         |___________|                            */
+/*                                                                                  */
+/*  The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have    */
+/*  their gain to give a near peak to peak output (-0.1dBFS) with a worst case      */
+/*  input signal. The gains of these blocks are re-combined in the Alpha mixer and  */
+/*  the gain block folloing the sum.                                                */
+/*                                                                                  */
+/*  The processing uses the output buffer for data storage after each processing    */
+/*  block. When processing is inplace a copy of the input signal is made in scratch */
+/*  memory for the 1-Alpha path.                                                    */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples in the input buffer                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
+                                     const LVM_FLOAT            *pInData,
+                                     LVM_FLOAT                  *pOutData,
+                                     LVM_UINT16                 NumSamples)
+{
+    const LVM_FLOAT     *pInput;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVM_FLOAT           *pScratch;
+    LVCS_ReturnStatus_en err;
+#ifdef SUPPORT_MC
+    LVM_FLOAT           *pStIn;
+    LVM_INT32           channels = pInstance->Params.NrChannels;
+#define NrFrames NumSamples  // alias for clarity
+
+    /*In case of mono processing, stereo input is created from mono
+     *and stored in pInData before applying any of the effects.
+     *However we do not update the value pInstance->Params.NrChannels
+     *at this point.
+     *So to treat the pInData as stereo we are setting channels to 2
+     */
+    if (channels == 1)
+    {
+        channels = 2;
+    }
+#endif
+
+    pScratch  = (LVM_FLOAT *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+    /*
+     * Check if the processing is inplace
+     */
+#ifdef SUPPORT_MC
+    /*
+     * The pInput buffer holds the first 2 (Left, Right) channels information.
+     * Hence the memory required by this buffer is 2 * NumFrames.
+     * The Concert Surround module carries out processing only on L, R.
+     */
+    pInput = pScratch + (2 * NrFrames);
+    pStIn  = pScratch + ((LVCS_SCRATCHBUFFERS - 2) * NrFrames);
+    /* The first two channel data is extracted from the input data and
+     * copied into pInput buffer
+     */
+    Copy_Float_Mc_Stereo((LVM_FLOAT *)pInData,
+                         (LVM_FLOAT *)pInput,
+                         NrFrames,
+                         channels);
+    Copy_Float((LVM_FLOAT *)pInput,
+               (LVM_FLOAT *)pStIn,
+               (LVM_INT16)(2 * NrFrames));
+#else
+    if (pInData == pOutData)
+    {
+        /* Processing inplace */
+        pInput = pScratch + (2 * NumSamples);
+        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
+                   (LVM_FLOAT *)pInput,            /* Destination */
+                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
+    }
+    else
+    {
+        /* Processing outplace */
+        pInput = pInData;
+    }
+#endif
+    /*
+     * Call the stereo enhancer
+     */
+#ifdef SUPPORT_MC
+    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
+                              pStIn,                  /* Pointer to the input data */
+                              pOutData,               /* Pointer to the output data */
+                              NrFrames);              /* Number of frames to process */
+#else
+    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
+                              pInData,                    /* Pointer to the input data */
+                              pOutData,                   /* Pointer to the output data */
+                              NumSamples);                /* Number of samples to process */
+#endif
+
+    /*
+     * Call the reverb generator
+     */
+    err = LVCS_ReverbGenerator(hInstance,             /* Instance handle */
+                               pOutData,                  /* Pointer to the input data */
+                               pOutData,                  /* Pointer to the output data */
+                               NumSamples);               /* Number of samples to process */
+
+    /*
+     * Call the equaliser
+     */
+    err = LVCS_Equaliser(hInstance,                   /* Instance handle */
+                         pOutData,                        /* Pointer to the input data */
+                         NumSamples);                     /* Number of samples to process */
+
+    /*
+     * Call the bypass mixer
+     */
+    err = LVCS_BypassMixer(hInstance,                 /* Instance handle */
+                           pOutData,                      /* Pointer to the processed data */
+                           pInput,                        /* Pointer to the input (unprocessed) data */
+                           pOutData,                      /* Pointer to the output data */
+                           NumSamples);                   /* Number of samples to process */
+
+    if(err != LVCS_SUCCESS)
+    {
+        return err;
+    }
+
+    return(LVCS_SUCCESS);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Process                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Process function for the Concert Sound module. The implementation supports two  */
+/*  variants of the algorithm, one for headphones and one for mobile speakers.      */
+/*                                                                                  */
+/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono    */
+/*  format is not supported, the calling routine must convert the mono stream to    */
+/*  mono-in-stereo.                                                                 */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples in the input buffer                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size       */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
+                                  const LVM_FLOAT           *pInData,
+                                  LVM_FLOAT                 *pOutData,
+                                  LVM_UINT16                NumSamples)
+{
+
+    LVCS_Instance_t *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReturnStatus_en err;
+#ifdef SUPPORT_MC
+    /*Extract number of Channels info*/
+    LVM_INT32 channels = pInstance->Params.NrChannels;
+#define NrFrames NumSamples  // alias for clarity
+    if (channels == 1)
+    {
+        channels = 2;
+    }
+#endif
+    /*
+     * Check the number of samples is not too large
+     */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVCS_TOOMANYSAMPLES);
+    }
+
+    /*
+     * Check if the algorithm is enabled
+     */
+    if (pInstance->Params.OperatingMode != LVCS_OFF)
+    {
+#ifdef SUPPORT_MC
+        LVM_FLOAT *pStereoOut;
+        /*
+         * LVCS_Process_CS uses output buffer to store intermediate outputs of StereoEnhancer,
+         * Equalizer, ReverbGenerator and BypassMixer.
+         * So, to avoid i/o data overlapping, when i/o buffers are common, use scratch buffer
+         * to store intermediate outputs.
+         */
+        if (pOutData == pInData)
+        {
+          /*
+           * Scratch memory is used in 4 chunks of (2 * NrFrames) size.
+           * First chunk of memory is used by LVCS_StereoEnhancer and LVCS_ReverbGenerator,
+           * second and fourth are used as input buffers by pInput and pStIn in LVCS_Process_CS.
+           * Hence, pStereoOut is pointed to use unused third portion of scratch memory.
+           */
+            pStereoOut = (LVM_FLOAT *) \
+                          pInstance->MemoryTable. \
+                          Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress +
+                          ((LVCS_SCRATCHBUFFERS - 4) * NrFrames);
+        }
+        else
+        {
+            pStereoOut = pOutData;
+        }
+
+        /*
+         * Call CS process function
+         */
+            err = LVCS_Process_CS(hInstance,
+                                  pInData,
+                                  pStereoOut,
+                                  NrFrames);
+#else
+            err = LVCS_Process_CS(hInstance,
+                                  pInData,
+                                  pOutData,
+                                  NumSamples);
+#endif
+
+        /*
+         * Compress to reduce expansion effect of Concert Sound and correct volume
+         * differences for difference settings. Not applied in test modes
+         */
+        if ((pInstance->Params.OperatingMode == LVCS_ON)&& \
+                                        (pInstance->Params.CompressorMode == LVM_MODE_ON))
+        {
+            LVM_FLOAT Gain = pInstance->VolCorrect.CompMin;
+            LVM_FLOAT Current1;
+
+            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
+            Gain = (LVM_FLOAT)(  pInstance->VolCorrect.CompMin
+                               - (((LVM_FLOAT)pInstance->VolCorrect.CompMin  * (Current1)))
+                               + (((LVM_FLOAT)pInstance->VolCorrect.CompFull * (Current1))));
+
+            if(NumSamples < LVCS_COMPGAINFRAME)
+            {
+#ifdef SUPPORT_MC
+                NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                 pStereoOut,
+                                 pStereoOut,
+                                 (LVM_INT32)(2 * NrFrames));
+#else
+                NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                 pOutData,
+                                 pOutData,
+                                 (LVM_INT32)(2 * NumSamples));
+#endif
+            }
+            else
+            {
+                LVM_FLOAT  GainStep;
+                LVM_FLOAT  FinalGain;
+                LVM_INT16  SampleToProcess = NumSamples;
+                LVM_FLOAT  *pOutPtr;
+
+                /* Large changes in Gain can cause clicks in output
+                   Split data into small blocks and use interpolated gain values */
+
+                GainStep = (LVM_FLOAT)(((Gain-pInstance->CompressGain) * \
+                                                LVCS_COMPGAINFRAME) / NumSamples);
+
+                if((GainStep == 0) && (pInstance->CompressGain < Gain))
+                {
+                    GainStep = 1;
+                }
+                else
+                {
+                    if((GainStep == 0) && (pInstance->CompressGain > Gain))
+                    {
+                        GainStep = -1;
+                    }
+                }
+
+                FinalGain = Gain;
+                Gain = pInstance->CompressGain;
+#ifdef SUPPORT_MC
+                pOutPtr = pStereoOut;
+#else
+                pOutPtr = pOutData;
+#endif
+
+                while(SampleToProcess > 0)
+                {
+                    Gain = (LVM_FLOAT)(Gain + GainStep);
+                    if((GainStep > 0) && (FinalGain <= Gain))
+                    {
+                        Gain = FinalGain;
+                        GainStep = 0;
+                    }
+
+                    if((GainStep < 0) && (FinalGain > Gain))
+                    {
+                        Gain = FinalGain;
+                        GainStep = 0;
+                    }
+
+                    if(SampleToProcess > LVCS_COMPGAINFRAME)
+                    {
+                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                         pOutPtr,
+                                         pOutPtr,
+                                         (LVM_INT32)(2 * LVCS_COMPGAINFRAME));
+                        pOutPtr += (2 * LVCS_COMPGAINFRAME);
+                        SampleToProcess = (LVM_INT16)(SampleToProcess - LVCS_COMPGAINFRAME);
+                    }
+                    else
+                    {
+                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
+                                         pOutPtr,
+                                         pOutPtr,
+                                         (LVM_INT32)(2 * SampleToProcess));
+                        SampleToProcess = 0;
+                    }
+
+                }
+            }
+
+            /* Store gain value*/
+            pInstance->CompressGain = Gain;
+        }
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+
+            /*
+             * Re-init bypass mix when timer has completed
+             */
+            if ((pInstance->bTimerDone == LVM_TRUE) &&
+                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
+            {
+                err = LVCS_BypassMixInit(hInstance,
+                                         &pInstance->Params);
+
+                if(err != LVCS_SUCCESS)
+                {
+                    return err;
+                }
+
+            }
+            else{
+                LVM_Timer ( &pInstance->TimerInstance,
+                            (LVM_INT16)NumSamples);
+            }
+        }
+#ifdef SUPPORT_MC
+        Copy_Float_Stereo_Mc(pInData,
+                             pStereoOut,
+                             pOutData,
+                             NrFrames,
+                             channels);
+#endif
+    }
+    else
+    {
+        if (pInData != pOutData)
+        {
+#ifdef SUPPORT_MC
+            /*
+             * The algorithm is disabled so just copy the data
+             */
+            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
+                       (LVM_FLOAT *)pOutData,                  /* Destination */
+                       (LVM_INT16)(channels * NrFrames));    /* All Channels*/
+#else
+            /*
+             * The algorithm is disabled so just copy the data
+             */
+            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
+                       (LVM_FLOAT *)pOutData,                  /* Destination */
+                       (LVM_INT16)(2 * NumSamples));             /* Left and right */
+#endif
+        }
+    }
+
+    return(LVCS_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
deleted file mode 100644
index 1085101..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_ReverbGenerator.h"
-#include "LVC_Mixer.h"
-#include "VectorArithmetic.h"
-#include "BIQUAD.h"
-#include "LVCS_Tables.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_ReverbGeneratorInit                                */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialises the reverb module. The delay buffer size is configured for the      */
-/*  sample rate and the speaker type.                                               */
-/*                                                                                  */
-/*  The routine may also be called for re-initialisation, i.e. when one of the      */
-/*  control parameters has changed. In this case the delay and filters are only     */
-/*  re-initialised if one of the following two conditions is met:                   */
-/*      -   the sample rate has changed                                             */
-/*      -   the speaker type changes to/from the mobile speaker                     */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pParams                 Pointer to the inialisation parameters                  */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  In the delay settings 'Samples' is the number of samples to the end of the  */
-/*      buffer.                                                                     */
-/*  2.  The numerator coefficients of the filter are negated to cause an inversion. */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
-                                              LVCS_Params_t     *pParams)
-{
-
-    LVM_UINT16              Delay;
-    LVM_UINT16              Offset;
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
-    LVCS_Data_t             *pData;
-    LVCS_Coefficient_t      *pCoefficients;
-    BQ_FLOAT_Coefs_t         Coeffs;
-    const BiquadA012B12CoefsSP_t  *pReverbCoefTable;
-
-
-    pData = (LVCS_Data_t *) \
-                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-
-    pCoefficients = (LVCS_Coefficient_t *) \
-                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-    /*
-     * Initialise the delay and filters if:
-     *  - the sample rate has changed
-     *  - the speaker type has changed to or from the mobile speaker
-     */
-    if(pInstance->Params.SampleRate != pParams->SampleRate )      /* Sample rate change test */
-
-    {
-        /*
-         * Setup the delay
-         */
-        Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
-
-
-        pConfig->DelaySize      = (LVM_INT16)(2 * Delay);
-        pConfig->DelayOffset    = 0;
-        LoadConst_Float(0,                                            /* Value */
-                        (LVM_FLOAT *)&pConfig->StereoSamples[0],      /* Destination */
-                        /* Number of words */
-                        (LVM_UINT16)(sizeof(pConfig->StereoSamples) / sizeof(LVM_FLOAT)));
-        /*
-         * Setup the filters
-         */
-        Offset = (LVM_UINT16)pParams->SampleRate;
-        pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
-
-        /* Convert incoming coefficients to the required format/ordering */
-        Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
-        Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
-        Coeffs.A2 = (LVM_FLOAT)pReverbCoefTable[Offset].A2;
-        Coeffs.B1 = (LVM_FLOAT)-pReverbCoefTable[Offset].B1;
-        Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
-
-        LoadConst_Float(0,                                 /* Value */
-                        (void *)&pData->ReverbBiquadTaps,  /* Destination Cast to void:
-                                                             no dereferencing in function*/
-                        /* Number of words */
-                        (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
-
-        BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
-                                        &pData->ReverbBiquadTaps,
-                                        &Coeffs);
-
-        /* Callbacks */
-        switch(pReverbCoefTable[Offset].Scale)
-        {
-            case 14:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F16C14_TRC_WRA_01;
-                break;
-            case 15:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F16C15_TRC_WRA_01;
-                break;
-        }
-
-
-        /*
-         * Setup the mixer
-         */
-        pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
-        pConfig->UnprocGain  = (LVM_UINT16)(HEADPHONEGAINUNPROC);
-    }
-
-    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
-    {
-        LVM_INT32   ReverbPercentage = 83886;      // 1 Percent Reverb i.e 1/100 in Q 23 format
-        ReverbPercentage *= pParams->ReverbLevel;  // Actual Reverb Level in Q 23 format
-        pConfig->ReverbLevel = ((LVM_FLOAT)(ReverbPercentage>>8)) / 32767.0f;
-    }
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
-                                              LVCS_Params_t     *pParams)
-{
-
-    LVM_UINT16              Delay;
-    LVM_UINT16              Offset;
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
-    LVCS_Data_t             *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-    LVCS_Coefficient_t      *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    BQ_C16_Coefs_t          Coeffs;
-    const BiquadA012B12CoefsSP_t  *pReverbCoefTable;
-
-    /*
-     * Initialise the delay and filters if:
-     *  - the sample rate has changed
-     *  - the speaker type has changed to or from the mobile speaker
-     */
-    if(pInstance->Params.SampleRate != pParams->SampleRate )      /* Sample rate change test */
-
-    {
-        /*
-         * Setup the delay
-         */
-        Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
-
-
-        pConfig->DelaySize      = (LVM_INT16)(2 * Delay);
-        pConfig->DelayOffset    = 0;
-        LoadConst_16(0,                                                                 /* Value */
-                     (LVM_INT16 *)&pConfig->StereoSamples[0],                           /* Destination */
-                     (LVM_UINT16)(sizeof(pConfig->StereoSamples)/sizeof(LVM_INT16)));   /* Number of words */
-
-        /*
-         * Setup the filters
-         */
-        Offset = (LVM_UINT16)pParams->SampleRate;
-        pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
-
-        /* Convert incoming coefficients to the required format/ordering */
-        Coeffs.A0 = (LVM_INT16)pReverbCoefTable[Offset].A0;
-        Coeffs.A1 = (LVM_INT16)pReverbCoefTable[Offset].A1;
-        Coeffs.A2 = (LVM_INT16)pReverbCoefTable[Offset].A2;
-        Coeffs.B1 = (LVM_INT16)-pReverbCoefTable[Offset].B1;
-        Coeffs.B2 = (LVM_INT16)-pReverbCoefTable[Offset].B2;
-
-        LoadConst_16(0,                                                                 /* Value */
-                     (void *)&pData->ReverbBiquadTaps,                             /* Destination Cast to void: no dereferencing in function*/
-                     (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps)/sizeof(LVM_INT16)));  /* Number of words */
-
-        BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
-                                        &pData->ReverbBiquadTaps,
-                                        &Coeffs);
-
-        /* Callbacks */
-        switch(pReverbCoefTable[Offset].Scale)
-        {
-            case 14:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F16C14_TRC_WRA_01;
-                break;
-            case 15:
-                pConfig->pBiquadCallBack  = BQ_2I_D16F16C15_TRC_WRA_01;
-                break;
-        }
-
-
-        /*
-         * Setup the mixer
-         */
-        pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
-        pConfig->UnprocGain  = (LVM_UINT16)(HEADPHONEGAINUNPROC);
-    }
-
-    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
-    {
-        LVM_INT32   ReverbPercentage=83886;                     // 1 Percent Reverb i.e 1/100 in Q 23 format
-        ReverbPercentage*=pParams->ReverbLevel;                 // Actual Reverb Level in Q 23 format
-        pConfig->ReverbLevel=(LVM_INT16)(ReverbPercentage>>8);  // Reverb Level in Q 15 format
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_Reverb                                             */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Create reverb using the block of input samples based on the following block     */
-/*  diagram:                                                                        */
-/*                           ________              ________                         */
-/*                          |        |            |        |                        */
-/*     _____     _______    |        |----------->|        |    ______     ___      */
-/*    |     |   |       |   | Stereo |            | L & R  |   |      |   |   |     */
-/* -->| LPF |-->| Delay |-->|   to   |    ____    |   to   |-->| Gain |-->| + |-->  */
-/*  | |_____|   |_______|   | L & R  |   |    |   | Stereo |   |______|   |___|     */
-/*  |                       |        |-->| -1 |-->|        |                |       */
-/*  |                       |________|   |____|   |________|                |       */
-/*  |                                                                       |       */
-/*  |-----------------------------------------------------------------------|       */
-/*                                                                                  */
-/*  The input buffer is broken in to sub-blocks of the size of the delay or less.   */
-/*  This allows the delay buffer to be treated as a circular buffer but processed   */
-/*  as a linear buffer.                                                             */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pInData                 Pointer to the input buffer                             */
-/*  pOutData                Pointer to the output buffer                            */
-/*  NumSamples              Number of samples to process                            */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  Process in blocks of samples the size of the delay where possible, if not   */
-/*      the number of samples left over                                             */
-/*  2.  The Gain is combined with the LPF and incorporated in to the coefficients   */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
-                                          const LVM_FLOAT       *pInData,
-                                          LVM_FLOAT             *pOutData,
-                                          LVM_UINT16            NumSamples)
-{
-
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
-    LVCS_Coefficient_t      *pCoefficients;
-    LVM_FLOAT               *pScratch;
-
-    pCoefficients = (LVCS_Coefficient_t *)\
-                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-    pScratch  = (LVM_FLOAT *)\
-                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-
-    /*
-     * Copy the data to the output in outplace processing
-     */
-    if (pInData != pOutData)
-    {
-        /*
-         * Reverb not required so just copy the data
-         */
-        Copy_Float((LVM_FLOAT *)pInData,                                       /* Source */
-                   (LVM_FLOAT *)pOutData,                                      /* Destination */
-                   (LVM_INT16)(2 * NumSamples));                                 /* Left and right */
-    }
-
-
-    /*
-     * Check if the reverb is required
-     */
-    /* Disable when CS4MS in stereo mode */
-    if (((pInstance->Params.SpeakerType == LVCS_HEADPHONE) || \
-         (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
-         (pInstance->Params.SourceFormat != LVCS_STEREO))  &&
-                                    /* For validation testing */
-        ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0))
-    {
-        /********************************************************************************/
-        /*                                                                              */
-        /* Copy the input data to scratch memory and filter it                          */
-        /*                                                                              */
-        /********************************************************************************/
-
-        /*
-         * Copy the input data to the scratch memory
-         */
-        Copy_Float((LVM_FLOAT *)pInData,                                     /* Source */
-                   (LVM_FLOAT *)pScratch,                                    /* Destination */
-                   (LVM_INT16)(2 * NumSamples));                               /* Left and right */
-
-        /*
-         * Filter the data
-         */
-        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
-                                   (LVM_FLOAT *)pScratch,
-                                   (LVM_FLOAT *)pScratch,
-                                   (LVM_INT16)NumSamples);
-
-        Mult3s_Float( (LVM_FLOAT *)pScratch,
-                      pConfig->ReverbLevel,
-                      (LVM_FLOAT *)pScratch,
-                      (LVM_INT16)(2 * NumSamples));
-
-
-        /*
-         * Apply the delay mix
-         */
-        DelayMix_Float((LVM_FLOAT *)pScratch,
-                       &pConfig->StereoSamples[0],
-                       pConfig->DelaySize,
-                       pOutData,
-                       &pConfig->DelayOffset,
-                       (LVM_INT16)NumSamples);
-
-
-    }
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
-                                          const LVM_INT16       *pInData,
-                                          LVM_INT16             *pOutData,
-                                          LVM_UINT16            NumSamples)
-{
-
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
-    LVCS_Coefficient_t      *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    LVM_INT16               *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-
-
-    /*
-     * Copy the data to the output in outplace processing
-     */
-    if (pInData != pOutData)
-    {
-        /*
-         * Reverb not required so just copy the data
-         */
-        Copy_16((LVM_INT16 *)pInData,                                       /* Source */
-                (LVM_INT16 *)pOutData,                                      /* Destination */
-                (LVM_INT16)(2*NumSamples));                                 /* Left and right */
-    }
-
-
-    /*
-     * Check if the reverb is required
-     */
-    if (((pInstance->Params.SpeakerType == LVCS_HEADPHONE) ||           /* Disable when CS4MS in stereo mode */
-         (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
-         (pInstance->Params.SourceFormat != LVCS_STEREO))  &&
-        ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0))    /* For validation testing */
-    {
-        /********************************************************************************/
-        /*                                                                              */
-        /* Copy the input data to scratch memory and filter it                          */
-        /*                                                                              */
-        /********************************************************************************/
-
-        /*
-         * Copy the input data to the scratch memory
-         */
-        Copy_16((LVM_INT16 *)pInData,                                     /* Source */
-                (LVM_INT16 *)pScratch,                                    /* Destination */
-                (LVM_INT16)(2*NumSamples));                               /* Left and right */
-
-
-        /*
-         * Filter the data
-         */
-        (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->ReverbBiquadInstance,
-                                   (LVM_INT16 *)pScratch,
-                                   (LVM_INT16 *)pScratch,
-                                   (LVM_INT16)NumSamples);
-
-        Mult3s_16x16( (LVM_INT16 *)pScratch,
-                      pConfig->ReverbLevel,
-                      (LVM_INT16 *)pScratch,
-                      (LVM_INT16)(2*NumSamples));
-
-
-        /*
-         * Apply the delay mix
-         */
-        DelayMix_16x16((LVM_INT16 *)pScratch,
-                       &pConfig->StereoSamples[0],
-                       pConfig->DelaySize,
-                       pOutData,
-                       &pConfig->DelayOffset,
-                       (LVM_INT16)NumSamples);
-
-
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
new file mode 100644
index 0000000..d0e6e09
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_ReverbGenerator.h"
+#include "LVC_Mixer.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_ReverbGeneratorInit                                */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the reverb module. The delay buffer size is configured for the      */
+/*  sample rate and the speaker type.                                               */
+/*                                                                                  */
+/*  The routine may also be called for re-initialisation, i.e. when one of the      */
+/*  control parameters has changed. In this case the delay and filters are only     */
+/*  re-initialised if one of the following two conditions is met:                   */
+/*      -   the sample rate has changed                                             */
+/*      -   the speaker type changes to/from the mobile speaker                     */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Pointer to the inialisation parameters                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  In the delay settings 'Samples' is the number of samples to the end of the  */
+/*      buffer.                                                                     */
+/*  2.  The numerator coefficients of the filter are negated to cause an inversion. */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
+                                              LVCS_Params_t     *pParams)
+{
+
+    LVM_UINT16              Delay;
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Data_t             *pData;
+    LVCS_Coefficient_t      *pCoefficients;
+    BQ_FLOAT_Coefs_t         Coeffs;
+    const BiquadA012B12CoefsSP_t  *pReverbCoefTable;
+
+    pData = (LVCS_Data_t *) \
+                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficients = (LVCS_Coefficient_t *) \
+                 pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    /*
+     * Initialise the delay and filters if:
+     *  - the sample rate has changed
+     *  - the speaker type has changed to or from the mobile speaker
+     */
+    if(pInstance->Params.SampleRate != pParams->SampleRate )      /* Sample rate change test */
+
+    {
+        /*
+         * Setup the delay
+         */
+        Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
+
+        pConfig->DelaySize      = (LVM_INT16)(2 * Delay);
+        pConfig->DelayOffset    = 0;
+        LoadConst_Float(0,                                            /* Value */
+                        (LVM_FLOAT *)&pConfig->StereoSamples[0],      /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pConfig->StereoSamples) / sizeof(LVM_FLOAT)));
+        /*
+         * Setup the filters
+         */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+        pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_FLOAT)pReverbCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_FLOAT)-pReverbCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
+
+        LoadConst_Float(0,                                 /* Value */
+                        (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
+
+        BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
+                                        &pData->ReverbBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pReverbCoefTable[Offset].Scale)
+        {
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+        /*
+         * Setup the mixer
+         */
+        pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
+        pConfig->UnprocGain  = (LVM_UINT16)(HEADPHONEGAINUNPROC);
+    }
+
+    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+    {
+        LVM_INT32   ReverbPercentage = 83886;      // 1 Percent Reverb i.e 1/100 in Q 23 format
+        ReverbPercentage *= pParams->ReverbLevel;  // Actual Reverb Level in Q 23 format
+        pConfig->ReverbLevel = ((LVM_FLOAT)(ReverbPercentage>>8)) / 32767.0f;
+    }
+    return(LVCS_SUCCESS);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Reverb                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Create reverb using the block of input samples based on the following block     */
+/*  diagram:                                                                        */
+/*                           ________              ________                         */
+/*                          |        |            |        |                        */
+/*     _____     _______    |        |----------->|        |    ______     ___      */
+/*    |     |   |       |   | Stereo |            | L & R  |   |      |   |   |     */
+/* -->| LPF |-->| Delay |-->|   to   |    ____    |   to   |-->| Gain |-->| + |-->  */
+/*  | |_____|   |_______|   | L & R  |   |    |   | Stereo |   |______|   |___|     */
+/*  |                       |        |-->| -1 |-->|        |                |       */
+/*  |                       |________|   |____|   |________|                |       */
+/*  |                                                                       |       */
+/*  |-----------------------------------------------------------------------|       */
+/*                                                                                  */
+/*  The input buffer is broken in to sub-blocks of the size of the delay or less.   */
+/*  This allows the delay buffer to be treated as a circular buffer but processed   */
+/*  as a linear buffer.                                                             */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInData                 Pointer to the input buffer                             */
+/*  pOutData                Pointer to the output buffer                            */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  Process in blocks of samples the size of the delay where possible, if not   */
+/*      the number of samples left over                                             */
+/*  2.  The Gain is combined with the LPF and incorporated in to the coefficients   */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
+                                          const LVM_FLOAT       *pInData,
+                                          LVM_FLOAT             *pOutData,
+                                          LVM_UINT16            NumSamples)
+{
+
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Coefficient_t      *pCoefficients;
+    LVM_FLOAT               *pScratch;
+
+    pCoefficients = (LVCS_Coefficient_t *)\
+                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pScratch  = (LVM_FLOAT *)\
+                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+    /*
+     * Copy the data to the output in outplace processing
+     */
+    if (pInData != pOutData)
+    {
+        /*
+         * Reverb not required so just copy the data
+         */
+        Copy_Float((LVM_FLOAT *)pInData,                                       /* Source */
+                   (LVM_FLOAT *)pOutData,                                      /* Destination */
+                   (LVM_INT16)(2 * NumSamples));                                 /* Left and right */
+    }
+
+    /*
+     * Check if the reverb is required
+     */
+    /* Disable when CS4MS in stereo mode */
+    if ((((LVCS_OutputDevice_en)pInstance->Params.SpeakerType == LVCS_HEADPHONE) || \
+         (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
+         (pInstance->Params.SourceFormat != LVCS_STEREO))  &&
+                                    /* For validation testing */
+        ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0))
+    {
+        /********************************************************************************/
+        /*                                                                              */
+        /* Copy the input data to scratch memory and filter it                          */
+        /*                                                                              */
+        /********************************************************************************/
+
+        /*
+         * Copy the input data to the scratch memory
+         */
+        Copy_Float((LVM_FLOAT *)pInData,                                     /* Source */
+                   (LVM_FLOAT *)pScratch,                                    /* Destination */
+                   (LVM_INT16)(2 * NumSamples));                               /* Left and right */
+
+        /*
+         * Filter the data
+         */
+        (pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
+                                   (LVM_FLOAT *)pScratch,
+                                   (LVM_FLOAT *)pScratch,
+                                   (LVM_INT16)NumSamples);
+
+        Mult3s_Float( (LVM_FLOAT *)pScratch,
+                      pConfig->ReverbLevel,
+                      (LVM_FLOAT *)pScratch,
+                      (LVM_INT16)(2 * NumSamples));
+
+        /*
+         * Apply the delay mix
+         */
+        DelayMix_Float((LVM_FLOAT *)pScratch,
+                       &pConfig->StereoSamples[0],
+                       pConfig->DelaySize,
+                       pOutData,
+                       &pConfig->DelayOffset,
+                       (LVM_INT16)NumSamples);
+
+    }
+
+    return(LVCS_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
index f94d4e4..1bc4338 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -18,11 +18,6 @@
 #ifndef __LVCS_REVERBGENERATOR_H__
 #define __LVCS_REVERBGENERATOR_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Includes                                                                      */
@@ -31,7 +26,6 @@
 
 #include "LVC_Mixer.h"
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Defines                                                                       */
@@ -41,14 +35,12 @@
 #define     HEADPHONEGAINPROC           LVCS_HEADPHONE_PROCGAIN
 #define     HEADPHONEGAINUNPROC         LVCS_HEADPHONE_UNPROCGAIN
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Structures                                                                    */
 /*                                                                                  */
 /************************************************************************************/
 
-
 /* Reverberation module structure */
 typedef struct
 {
@@ -58,23 +50,14 @@
     LVM_INT16                   DelayOffset;
     LVM_INT16                   ProcGain;
     LVM_INT16                   UnprocGain;
-#ifndef BUILD_FLOAT
-    LVM_INT16                    StereoSamples[2*LVCS_STEREODELAY_CS_48KHZ];
-    /* Reverb Level */
-    LVM_INT16                   ReverbLevel;
-    /* Filter */
-    void                        (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-#else
     LVM_FLOAT                   StereoSamples[2 * LVCS_STEREODELAY_CS_MAX_VAL];
     /* Reverb Level */
     LVM_FLOAT                   ReverbLevel;
     /* Filter */
     void                        (*pBiquadCallBack) (Biquad_FLOAT_Instance_t*,
                                                     LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
-#endif
 } LVCS_ReverbGenerator_t;
 
-
 /************************************************************************************/
 /*                                                                                    */
 /*    Function prototypes                                                                */
@@ -83,19 +66,9 @@
 
 LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
                                                  LVCS_Params_t  *pParams);
-#ifdef BUILD_FLOAT
 LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
                                           const LVM_FLOAT       *pInput,
                                           LVM_FLOAT             *pOutput,
                                           LVM_UINT16            NumSamples);
-#else
-LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
-                                          const LVM_INT16       *pInput,
-                                          LVM_INT16             *pOutput,
-                                          LVM_UINT16            NumSamples);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* REVERB_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
deleted file mode 100644
index 2992c35..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS.h"
-#include "LVCS_Private.h"
-#include "LVCS_StereoEnhancer.h"
-#include "VectorArithmetic.h"
-#include "LVCS_Tables.h"
-
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_StereoEnhanceInit                                  */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Initialises the stereo enhancement module based on the sample rate.             */
-/*                                                                                  */
-/*  The function selects the coefficients for the filters and clears the data       */
-/*  history. It is also used for re-initialisation when one of the system control   */
-/*  parameters changes but will only change the coefficients and clear the history  */
-/*  if the sample rate or speaker type has changed.                                 */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pParams                 Initialisation parameters                               */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
-                                        LVCS_Params_t       *pParams)
-{
-
-    LVM_UINT16              Offset;
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
-    LVCS_Data_t             *pData;
-    LVCS_Coefficient_t      *pCoefficient;
-    FO_FLOAT_Coefs_t          CoeffsMid;
-    BQ_FLOAT_Coefs_t          CoeffsSide;
-    const BiquadA012B12CoefsSP_t *pSESideCoefs;
-
-
-    pData     = (LVCS_Data_t *) \
-                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-
-    pCoefficient = (LVCS_Coefficient_t *) \
-                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-    /*
-     * If the sample rate or speaker type has changed update the filters
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.SpeakerType != pParams->SpeakerType))
-    {
-        /*
-         * Set the filter coefficients based on the sample rate
-         */
-        /* Mid filter */
-        Offset = (LVM_UINT16)pParams->SampleRate;
-
-        /* Convert incoming coefficients to the required format/ordering */
-        CoeffsMid.A0 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A0;
-        CoeffsMid.A1 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A1;
-        CoeffsMid.B1 = (LVM_FLOAT)-LVCS_SEMidCoefTable[Offset].B1;
-
-        /* Clear the taps */
-        LoadConst_Float(0,                                  /* Value */
-                        (void *)&pData->SEBiquadTapsMid,    /* Destination Cast to void:\
-                                                              no dereferencing in function*/
-                        /* Number of words */
-                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
-
-        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
-                                        &pData->SEBiquadTapsMid,
-                                        &CoeffsMid);
-
-        /* Callbacks */
-        if(LVCS_SEMidCoefTable[Offset].Scale == 15)
-        {
-            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
-        }
-
-        Offset = (LVM_UINT16)(pParams->SampleRate);
-        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
-
-        /* Side filter */
-        /* Convert incoming coefficients to the required format/ordering */
-        CoeffsSide.A0 = (LVM_FLOAT) pSESideCoefs[Offset].A0;
-        CoeffsSide.A1 = (LVM_FLOAT) pSESideCoefs[Offset].A1;
-        CoeffsSide.A2 = (LVM_FLOAT) pSESideCoefs[Offset].A2;
-        CoeffsSide.B1 = (LVM_FLOAT)-pSESideCoefs[Offset].B1;
-        CoeffsSide.B2 = (LVM_FLOAT)-pSESideCoefs[Offset].B2;
-
-        /* Clear the taps */
-        LoadConst_Float(0,                                /* Value */
-                        (void *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
-                                                             no dereferencing in function*/
-                        /* Number of words */
-                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
-        /* Callbacks */
-        switch(pSESideCoefs[Offset].Scale)
-        {
-            case 14:
-                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
-                                                &pData->SEBiquadTapsSide,
-                                                &CoeffsSide);
-
-                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
-                break;
-            case 15:
-                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
-                                                &pData->SEBiquadTapsSide,
-                                                &CoeffsSide);
-
-                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
-                break;
-        }
-
-    }
-
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
-                                        LVCS_Params_t       *pParams)
-{
-
-    LVM_UINT16              Offset;
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
-    LVCS_Data_t             *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
-    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    FO_C16_Coefs_t          CoeffsMid;
-    BQ_C16_Coefs_t          CoeffsSide;
-    const BiquadA012B12CoefsSP_t *pSESideCoefs;
-
-    /*
-     * If the sample rate or speaker type has changed update the filters
-     */
-    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
-        (pInstance->Params.SpeakerType != pParams->SpeakerType))
-    {
-        /*
-         * Set the filter coefficients based on the sample rate
-         */
-        /* Mid filter */
-        Offset = (LVM_UINT16)pParams->SampleRate;
-
-        /* Convert incoming coefficients to the required format/ordering */
-        CoeffsMid.A0 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A0;
-        CoeffsMid.A1 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A1;
-        CoeffsMid.B1 = (LVM_INT16)-LVCS_SEMidCoefTable[Offset].B1;
-
-        /* Clear the taps */
-        LoadConst_16(0,                                                                 /* Value */
-                     (void *)&pData->SEBiquadTapsMid,              /* Destination Cast to void:\
-                                                                      no dereferencing in function*/
-                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid)/sizeof(LVM_UINT16)));  /* Number of words */
-
-        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
-                                        &pData->SEBiquadTapsMid,
-                                        &CoeffsMid);
-
-        /* Callbacks */
-        if(LVCS_SEMidCoefTable[Offset].Scale==15)
-        {
-            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
-        }
-
-        Offset = (LVM_UINT16)(pParams->SampleRate);
-        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
-
-        /* Side filter */
-        /* Convert incoming coefficients to the required format/ordering */
-        CoeffsSide.A0 = (LVM_INT16) pSESideCoefs[Offset].A0;
-        CoeffsSide.A1 = (LVM_INT16) pSESideCoefs[Offset].A1;
-        CoeffsSide.A2 = (LVM_INT16) pSESideCoefs[Offset].A2;
-        CoeffsSide.B1 = (LVM_INT16)-pSESideCoefs[Offset].B1;
-        CoeffsSide.B2 = (LVM_INT16)-pSESideCoefs[Offset].B2;
-
-        /* Clear the taps */
-        LoadConst_16(0,                                                                 /* Value */
-                     (void *)&pData->SEBiquadTapsSide,             /* Destination Cast to void:\
-                                                                      no dereferencing in function*/
-                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide)/sizeof(LVM_UINT16))); /* Number of words */
-
-
-        /* Callbacks */
-        switch(pSESideCoefs[Offset].Scale)
-        {
-            case 14:
-                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
-                                                &pData->SEBiquadTapsSide,
-                                                &CoeffsSide);
-
-                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
-                break;
-            case 15:
-                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
-                                                &pData->SEBiquadTapsSide,
-                                                &CoeffsSide);
-
-                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
-                break;
-        }
-
-    }
-
-
-    return(LVCS_SUCCESS);
-}
-#endif
-/************************************************************************************/
-/*                                                                                  */
-/* FUNCTION:                LVCS_StereoEnhance                                      */
-/*                                                                                  */
-/* DESCRIPTION:                                                                     */
-/*  Enhance the stereo image in the input samples based on the following block      */
-/*  diagram:                                                                        */
-/*                                                                                  */
-/*                               ________                                           */
-/*          ________            |        |          ________                        */
-/*         |        |  Middle   | Treble |         |        |                       */
-/*         |        |---------->| Boost  |-------->|        |                       */
-/*         | Stereo |           |________|         | M & S  |                       */
-/*      -->|   to   |            ________          |   to   |-->                    */
-/*         | M & S  |  Side     |        |         | Stereo |                       */
-/*         |        |---------->| Side   |-------->|        |                       */
-/*         |________|           | Boost  |         |________|                       */
-/*                              |________|                                          */
-/*                                                                                  */
-/*                                                                                  */
-/*  If the input signal is a mono signal there will be no side signal and hence     */
-/*  the side filter will not be run. In mobile speaker mode the middle filter is    */
-/*  not required and the Trebble boost filter is replaced by a simple gain block.   */
-/*                                                                                  */
-/*                                                                                  */
-/* PARAMETERS:                                                                      */
-/*  hInstance               Instance Handle                                         */
-/*  pInData                 Pointer to the input data                               */
-/*  pOutData                Pointer to the output data                              */
-/*  NumSamples              Number of samples to process                            */
-/*                                                                                  */
-/* RETURNS:                                                                         */
-/*  LVCS_Success            Always succeeds                                         */
-/*                                                                                  */
-/* NOTES:                                                                           */
-/*  1.  The side filter is not used in Mobile Speaker mode                          */
-/*                                                                                  */
-/************************************************************************************/
-#ifdef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
-                                         const LVM_FLOAT        *pInData,
-                                         LVM_FLOAT              *pOutData,
-                                         LVM_UINT16             NumSamples)
-{
-
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
-    LVCS_Coefficient_t      *pCoefficient;
-    LVM_FLOAT               *pScratch;
-
-    pCoefficient = (LVCS_Coefficient_t *) \
-                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-
-    pScratch  = (LVM_FLOAT *) \
-                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-    /*
-     * Check if the Stereo Enhancer is enabled
-     */
-    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
-        {
-        /*
-         * Convert from stereo to middle and side
-         */
-        From2iToMS_Float(pInData,
-                         pScratch,
-                         pScratch + NumSamples,
-                         (LVM_INT16)NumSamples);
-
-        /*
-         * Apply filter to the middle signal
-         */
-        if (pInstance->OutputDevice == LVCS_HEADPHONE)
-        {
-            (pConfig->pBiquadCallBack_Mid)((Biquad_FLOAT_Instance_t*)\
-                                            &pCoefficient->SEBiquadInstanceMid,
-                                            (LVM_FLOAT *)pScratch,
-                                            (LVM_FLOAT *)pScratch,
-                                            (LVM_INT16)NumSamples);
-        }
-        else
-        {
-            Mult3s_Float(pScratch,              /* Source */
-                         (LVM_FLOAT)pConfig->MidGain,      /* Gain */
-                         pScratch,              /* Destination */
-                         (LVM_INT16)NumSamples);           /* Number of samples */
-        }
-
-        /*
-         * Apply the filter the side signal only in stereo mode for headphones
-         * and in all modes for mobile speakers
-         */
-        if (pInstance->Params.SourceFormat == LVCS_STEREO)
-        {
-            (pConfig->pBiquadCallBack_Side)((Biquad_FLOAT_Instance_t*) \
-                                            &pCoefficient->SEBiquadInstanceSide,
-                                            (LVM_FLOAT *)(pScratch + NumSamples),
-                                            (LVM_FLOAT *)(pScratch + NumSamples),
-                                            (LVM_INT16)NumSamples);
-        }
-
-        /*
-         * Convert from middle and side to stereo
-         */
-        MSTo2i_Sat_Float(pScratch,
-                         pScratch + NumSamples,
-                         pOutData,
-                         (LVM_INT16)NumSamples);
-
-    }
-    else
-    {
-        /*
-         * The stereo enhancer is disabled so just copy the data
-         */
-        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
-                   (LVM_FLOAT *)pOutData,          /* Destination */
-                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
-    }
-
-    return(LVCS_SUCCESS);
-}
-#else
-LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
-                                         const LVM_INT16        *pInData,
-                                         LVM_INT16              *pOutData,
-                                         LVM_UINT16             NumSamples)
-{
-
-    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
-    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
-    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
-    LVM_INT16               *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
-
-    /*
-     * Check if the Stereo Enhancer is enabled
-     */
-    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
-        {
-        /*
-         * Convert from stereo to middle and side
-         */
-        From2iToMS_16x16(pInData,
-                         pScratch,
-                         pScratch+NumSamples,
-                         (LVM_INT16)NumSamples);
-
-        /*
-         * Apply filter to the middle signal
-         */
-        if (pInstance->OutputDevice == LVCS_HEADPHONE)
-        {
-            (pConfig->pBiquadCallBack_Mid)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
-                                           (LVM_INT16 *)pScratch,
-                                           (LVM_INT16 *)pScratch,
-                                           (LVM_INT16)NumSamples);
-        }
-        else
-        {
-            Mult3s_16x16(pScratch,              /* Source */
-                         (LVM_INT16)pConfig->MidGain,      /* Gain */
-                         pScratch,              /* Destination */
-                         (LVM_INT16)NumSamples);           /* Number of samples */
-        }
-
-        /*
-         * Apply the filter the side signal only in stereo mode for headphones
-         * and in all modes for mobile speakers
-         */
-        if (pInstance->Params.SourceFormat == LVCS_STEREO)
-        {
-            (pConfig->pBiquadCallBack_Side)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
-                                            (LVM_INT16 *)(pScratch + NumSamples),
-                                            (LVM_INT16 *)(pScratch + NumSamples),
-                                            (LVM_INT16)NumSamples);
-        }
-
-        /*
-         * Convert from middle and side to stereo
-         */
-        MSTo2i_Sat_16x16(pScratch,
-                         pScratch+NumSamples,
-                         pOutData,
-                         (LVM_INT16)NumSamples);
-
-    }
-    else
-    {
-        /*
-         * The stereo enhancer is disabled so just copy the data
-         */
-        Copy_16((LVM_INT16 *)pInData,           /* Source */
-                (LVM_INT16 *)pOutData,          /* Destination */
-                (LVM_INT16)(2*NumSamples));     /* Left and right */
-
-    }
-
-    return(LVCS_SUCCESS);
-}
-#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
new file mode 100644
index 0000000..7fd8444
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_StereoEnhancer.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_StereoEnhanceInit                                  */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the stereo enhancement module based on the sample rate.             */
+/*                                                                                  */
+/*  The function selects the coefficients for the filters and clears the data       */
+/*  history. It is also used for re-initialisation when one of the system control   */
+/*  parameters changes but will only change the coefficients and clear the history  */
+/*  if the sample rate or speaker type has changed.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Data_t             *pData;
+    LVCS_Coefficient_t      *pCoefficient;
+    FO_FLOAT_Coefs_t          CoeffsMid;
+    BQ_FLOAT_Coefs_t          CoeffsSide;
+    const BiquadA012B12CoefsSP_t *pSESideCoefs;
+
+    pData     = (LVCS_Data_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pCoefficient = (LVCS_Coefficient_t *) \
+                  pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    /*
+     * If the sample rate or speaker type has changed update the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Set the filter coefficients based on the sample rate
+         */
+        /* Mid filter */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsMid.A0 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A0;
+        CoeffsMid.A1 = (LVM_FLOAT) LVCS_SEMidCoefTable[Offset].A1;
+        CoeffsMid.B1 = (LVM_FLOAT)-LVCS_SEMidCoefTable[Offset].B1;
+
+        /* Clear the taps */
+        LoadConst_Float(0,                                  /* Value */
+                        (LVM_FLOAT *)&pData->SEBiquadTapsMid,    /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
+
+        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
+                                        &pData->SEBiquadTapsMid,
+                                        &CoeffsMid);
+
+        /* Callbacks */
+        if(LVCS_SEMidCoefTable[Offset].Scale == 15)
+        {
+            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
+        }
+
+        Offset = (LVM_UINT16)(pParams->SampleRate);
+        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
+
+        /* Side filter */
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsSide.A0 = (LVM_FLOAT) pSESideCoefs[Offset].A0;
+        CoeffsSide.A1 = (LVM_FLOAT) pSESideCoefs[Offset].A1;
+        CoeffsSide.A2 = (LVM_FLOAT) pSESideCoefs[Offset].A2;
+        CoeffsSide.B1 = (LVM_FLOAT)-pSESideCoefs[Offset].B1;
+        CoeffsSide.B2 = (LVM_FLOAT)-pSESideCoefs[Offset].B2;
+
+        /* Clear the taps */
+        LoadConst_Float(0,                                /* Value */
+                        (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination */
+                        /* Number of words */
+                        (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
+        /* Callbacks */
+        switch(pSESideCoefs[Offset].Scale)
+        {
+            case 14:
+                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+    }
+
+    return(LVCS_SUCCESS);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_StereoEnhance                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Enhance the stereo image in the input samples based on the following block      */
+/*  diagram:                                                                        */
+/*                                                                                  */
+/*                               ________                                           */
+/*          ________            |        |          ________                        */
+/*         |        |  Middle   | Treble |         |        |                       */
+/*         |        |---------->| Boost  |-------->|        |                       */
+/*         | Stereo |           |________|         | M & S  |                       */
+/*      -->|   to   |            ________          |   to   |-->                    */
+/*         | M & S  |  Side     |        |         | Stereo |                       */
+/*         |        |---------->| Side   |-------->|        |                       */
+/*         |________|           | Boost  |         |________|                       */
+/*                              |________|                                          */
+/*                                                                                  */
+/*                                                                                  */
+/*  If the input signal is a mono signal there will be no side signal and hence     */
+/*  the side filter will not be run. In mobile speaker mode the middle filter is    */
+/*  not required and the Trebble boost filter is replaced by a simple gain block.   */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  The side filter is not used in Mobile Speaker mode                          */
+/*                                                                                  */
+/************************************************************************************/
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
+                                         const LVM_FLOAT        *pInData,
+                                         LVM_FLOAT              *pOutData,
+                                         LVM_UINT16             NumSamples)
+{
+
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Coefficient_t      *pCoefficient;
+    LVM_FLOAT               *pScratch;
+
+    pCoefficient = (LVCS_Coefficient_t *) \
+                   pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pScratch  = (LVM_FLOAT *) \
+                    pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+    /*
+     * Check if the Stereo Enhancer is enabled
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
+        {
+        /*
+         * Convert from stereo to middle and side
+         */
+        From2iToMS_Float(pInData,
+                         pScratch,
+                         pScratch + NumSamples,
+                         (LVM_INT16)NumSamples);
+
+        /*
+         * Apply filter to the middle signal
+         */
+        if (pInstance->OutputDevice == LVCS_HEADPHONE)
+        {
+            (pConfig->pBiquadCallBack_Mid)((Biquad_FLOAT_Instance_t*)\
+                                            &pCoefficient->SEBiquadInstanceMid,
+                                            (LVM_FLOAT *)pScratch,
+                                            (LVM_FLOAT *)pScratch,
+                                            (LVM_INT16)NumSamples);
+        }
+        else
+        {
+            Mult3s_Float(pScratch,              /* Source */
+                         (LVM_FLOAT)pConfig->MidGain,      /* Gain */
+                         pScratch,              /* Destination */
+                         (LVM_INT16)NumSamples);           /* Number of samples */
+        }
+
+        /*
+         * Apply the filter the side signal only in stereo mode for headphones
+         * and in all modes for mobile speakers
+         */
+        if (pInstance->Params.SourceFormat == LVCS_STEREO)
+        {
+            (pConfig->pBiquadCallBack_Side)((Biquad_FLOAT_Instance_t*) \
+                                            &pCoefficient->SEBiquadInstanceSide,
+                                            (LVM_FLOAT *)(pScratch + NumSamples),
+                                            (LVM_FLOAT *)(pScratch + NumSamples),
+                                            (LVM_INT16)NumSamples);
+        }
+
+        /*
+         * Convert from middle and side to stereo
+         */
+        MSTo2i_Sat_Float(pScratch,
+                         pScratch + NumSamples,
+                         pOutData,
+                         (LVM_INT16)NumSamples);
+
+    }
+    else
+    {
+        /*
+         * The stereo enhancer is disabled so just copy the data
+         */
+        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
+                   (LVM_FLOAT *)pOutData,          /* Destination */
+                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
+    }
+
+    return(LVCS_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
index 4125f24..12a5982 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -18,11 +18,6 @@
 #ifndef __LVCS_STEREOENHANCER_H__
 #define __LVCS_STEREOENHANCER_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Includes                                                                      */
@@ -33,7 +28,6 @@
 #include "LVCS_Headphone_Coeffs.h"          /* Headphone coefficients */
 #include "BIQUAD.h"
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Structures                                                                    */
@@ -44,17 +38,6 @@
 typedef struct
 {
 
-#ifndef BUILD_FLOAT
-    /*
-     * Middle filter
-     */
-    void                    (*pBiquadCallBack_Mid)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-    /*
-     * Side filter
-     */
-    void                    (*pBiquadCallBack_Side)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
-    LVM_UINT16              MidGain;            /* Middle gain in mobile speaker mode */
-#else
     /*
      * Middle filter
      */
@@ -67,10 +50,8 @@
     void                    (*pBiquadCallBack_Side)(Biquad_FLOAT_Instance_t*,
                                     LVM_FLOAT*, LVM_FLOAT*, LVM_INT16);
     LVM_FLOAT              MidGain;            /* Middle gain in mobile speaker mode */
-#endif
 } LVCS_StereoEnhancer_t;
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*    Function prototypes                                                           */
@@ -80,19 +61,9 @@
 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t        hInstance,
                                         LVCS_Params_t        *pParams);
 
-#ifndef BUILD_FLOAT
-LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t        hInstance,
-                                         const LVM_INT16    *pInData,
-                                         LVM_INT16            *pOutData,
-                                         LVM_UINT16            NumSamples);
-#else
 LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t        hInstance,
                                          const LVM_FLOAT    *pInData,
                                          LVM_FLOAT            *pOutData,
                                          LVM_UINT16            NumSamples);
-#endif
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
 #endif  /* STEREOENHANCE_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
deleted file mode 100644
index a1fb48f..0000000
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * Copyright (C) 2004-2010 NXP Software
- * Copyright (C) 2010 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.
- */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Includes                                                                        */
-/*                                                                                  */
-/************************************************************************************/
-
-#include "LVCS_Private.h"
-#include "Filters.h"                            /* Filter definitions */
-#include "BIQUAD.h"                             /* Biquad definitions */
-#include "LVCS_Headphone_Coeffs.h"              /* Headphone coefficients */
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Stereo Enhancer coefficient constant tables                                     */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Coefficient table for the middle filter */
-const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[] = {
-    {CS_MIDDLE_8000_A0,         /* 8kS/s coefficients */
-     CS_MIDDLE_8000_A1,
-     CS_MIDDLE_8000_B1,
-     (LVM_UINT16 )CS_MIDDLE_8000_SCALE},
-    {CS_MIDDLE_11025_A0,        /* 11kS/s coefficients */
-     CS_MIDDLE_11025_A1,
-     CS_MIDDLE_11025_B1,
-     (LVM_UINT16 )CS_MIDDLE_11025_SCALE},
-    {CS_MIDDLE_12000_A0,        /* 12kS/s coefficients */
-     CS_MIDDLE_12000_A1,
-     CS_MIDDLE_12000_B1,
-     (LVM_UINT16 )CS_MIDDLE_12000_SCALE},
-    {CS_MIDDLE_16000_A0,        /* 16kS/s coefficients */
-     CS_MIDDLE_16000_A1,
-     CS_MIDDLE_16000_B1,
-     (LVM_UINT16 )CS_MIDDLE_16000_SCALE},
-    {CS_MIDDLE_22050_A0,        /* 22kS/s coefficients */
-     CS_MIDDLE_22050_A1,
-     CS_MIDDLE_22050_B1,
-     (LVM_UINT16 )CS_MIDDLE_22050_SCALE},
-    {CS_MIDDLE_24000_A0,        /* 24kS/s coefficients */
-     CS_MIDDLE_24000_A1,
-     CS_MIDDLE_24000_B1,
-     (LVM_UINT16 )CS_MIDDLE_24000_SCALE},
-    {CS_MIDDLE_32000_A0,        /* 32kS/s coefficients */
-     CS_MIDDLE_32000_A1,
-     CS_MIDDLE_32000_B1,
-     (LVM_UINT16 )CS_MIDDLE_32000_SCALE},
-    {CS_MIDDLE_44100_A0,        /* 44kS/s coefficients */
-     CS_MIDDLE_44100_A1,
-     CS_MIDDLE_44100_B1,
-     (LVM_UINT16 )CS_MIDDLE_44100_SCALE},
-    {CS_MIDDLE_48000_A0,        /* 48kS/s coefficients */
-     CS_MIDDLE_48000_A1,
-     CS_MIDDLE_48000_B1,
-     (LVM_UINT16 )CS_MIDDLE_48000_SCALE}
-#ifdef HIGHER_FS
-    ,
-    {CS_MIDDLE_88200_A0,        /* 88kS/s coefficients */
-     CS_MIDDLE_88200_A1,
-     CS_MIDDLE_88200_B1,
-     (LVM_UINT16)CS_MIDDLE_88200_SCALE},
-    {CS_MIDDLE_96000_A0,        /* 96kS/s coefficients */
-     CS_MIDDLE_96000_A1,
-     CS_MIDDLE_96000_B1,
-     (LVM_UINT16 )CS_MIDDLE_96000_SCALE},
-    {CS_MIDDLE_176400_A0,        /* 176kS/s coefficients */
-     CS_MIDDLE_176400_A1,
-     CS_MIDDLE_176400_B1,
-     (LVM_UINT16)CS_MIDDLE_176400_SCALE},
-    {CS_MIDDLE_192000_A0,        /* 192kS/s coefficients */
-     CS_MIDDLE_192000_A1,
-     CS_MIDDLE_192000_B1,
-     (LVM_UINT16 )CS_MIDDLE_192000_SCALE}
-#endif
-    };
-
-/* Coefficient table for the side filter */
-const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[] = {
-    /* Headphone Side coefficients */
-    {CS_SIDE_8000_A0,           /* 8kS/s coefficients */
-     CS_SIDE_8000_A1,
-     CS_SIDE_8000_A2,
-     CS_SIDE_8000_B1,
-     CS_SIDE_8000_B2,
-     (LVM_UINT16 )CS_SIDE_8000_SCALE},
-    {CS_SIDE_11025_A0,          /* 11kS/s coefficients */
-     CS_SIDE_11025_A1,
-     CS_SIDE_11025_A2,
-     CS_SIDE_11025_B1,
-     CS_SIDE_11025_B2,
-     (LVM_UINT16 )CS_SIDE_11025_SCALE},
-    {CS_SIDE_12000_A0,          /* 12kS/s coefficients */
-     CS_SIDE_12000_A1,
-     CS_SIDE_12000_A2,
-     CS_SIDE_12000_B1,
-     CS_SIDE_12000_B2,
-     (LVM_UINT16 )CS_SIDE_12000_SCALE},
-    {CS_SIDE_16000_A0,          /* 16kS/s coefficients */
-     CS_SIDE_16000_A1,
-     CS_SIDE_16000_A2,
-     CS_SIDE_16000_B1,
-     CS_SIDE_16000_B2,
-     (LVM_UINT16 )CS_SIDE_16000_SCALE},
-    {CS_SIDE_22050_A0,          /* 22kS/s coefficients */
-     CS_SIDE_22050_A1,
-     CS_SIDE_22050_A2,
-     CS_SIDE_22050_B1,
-     CS_SIDE_22050_B2,
-     (LVM_UINT16 )CS_SIDE_22050_SCALE},
-    {CS_SIDE_24000_A0,          /* 24kS/s coefficients */
-     CS_SIDE_24000_A1,
-     CS_SIDE_24000_A2,
-     CS_SIDE_24000_B1,
-     CS_SIDE_24000_B2,
-     (LVM_UINT16 )CS_SIDE_24000_SCALE},
-    {CS_SIDE_32000_A0,          /* 32kS/s coefficients */
-     CS_SIDE_32000_A1,
-     CS_SIDE_32000_A2,
-     CS_SIDE_32000_B1,
-     CS_SIDE_32000_B2,
-     (LVM_UINT16 )CS_SIDE_32000_SCALE},
-    {CS_SIDE_44100_A0,          /* 44kS/s coefficients */
-     CS_SIDE_44100_A1,
-     CS_SIDE_44100_A2,
-     CS_SIDE_44100_B1,
-     CS_SIDE_44100_B2,
-     (LVM_UINT16 )CS_SIDE_44100_SCALE},
-    {CS_SIDE_48000_A0,          /* 48kS/s coefficients */
-     CS_SIDE_48000_A1,
-     CS_SIDE_48000_A2,
-     CS_SIDE_48000_B1,
-     CS_SIDE_48000_B2,
-     (LVM_UINT16 )CS_SIDE_48000_SCALE}
-#ifdef HIGHER_FS
-     ,
-    {CS_SIDE_88200_A0,          /* 88kS/s coefficients */
-     CS_SIDE_88200_A1,
-     CS_SIDE_88200_A2,
-     CS_SIDE_88200_B1,
-     CS_SIDE_88200_B2,
-     (LVM_UINT16)CS_SIDE_88200_SCALE},
-     {CS_SIDE_96000_A0,          /* 96kS/s coefficients */
-     CS_SIDE_96000_A1,
-     CS_SIDE_96000_A2,
-     CS_SIDE_96000_B1,
-     CS_SIDE_96000_B2,
-     (LVM_UINT16 )CS_SIDE_96000_SCALE},
-    {CS_SIDE_176400_A0,          /*176kS/s coefficients */
-     CS_SIDE_176400_A1,
-     CS_SIDE_176400_A2,
-     CS_SIDE_176400_B1,
-     CS_SIDE_176400_B2,
-     (LVM_UINT16)CS_SIDE_176400_SCALE},
-     {CS_SIDE_192000_A0,          /* 192kS/s coefficients */
-     CS_SIDE_192000_A1,
-     CS_SIDE_192000_A2,
-     CS_SIDE_192000_B1,
-     CS_SIDE_192000_B2,
-     (LVM_UINT16 )CS_SIDE_192000_SCALE}
-#endif
-};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Equaliser coefficient constant tables                                           */
-/*                                                                                  */
-/************************************************************************************/
-
-const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[] = {
-    /* Headphone coefficients */
-    {CS_EQUALISER_8000_A0,      /* 8kS/s coefficients */
-     CS_EQUALISER_8000_A1,
-     CS_EQUALISER_8000_A2,
-     CS_EQUALISER_8000_B1,
-     CS_EQUALISER_8000_B2,
-     (LVM_UINT16 )CS_EQUALISER_8000_SCALE},
-    {CS_EQUALISER_11025_A0,     /* 11kS/s coefficients */
-     CS_EQUALISER_11025_A1,
-     CS_EQUALISER_11025_A2,
-     CS_EQUALISER_11025_B1,
-     CS_EQUALISER_11025_B2,
-     (LVM_UINT16 )CS_EQUALISER_11025_SCALE},
-    {CS_EQUALISER_12000_A0,     /* 12kS/s coefficients */
-     CS_EQUALISER_12000_A1,
-     CS_EQUALISER_12000_A2,
-     CS_EQUALISER_12000_B1,
-     CS_EQUALISER_12000_B2,
-     (LVM_UINT16 )CS_EQUALISER_12000_SCALE},
-    {CS_EQUALISER_16000_A0,     /* 16kS/s coefficients */
-     CS_EQUALISER_16000_A1,
-     CS_EQUALISER_16000_A2,
-     CS_EQUALISER_16000_B1,
-     CS_EQUALISER_16000_B2,
-     (LVM_UINT16 )CS_EQUALISER_16000_SCALE},
-    {CS_EQUALISER_22050_A0,     /* 22kS/s coefficients */
-     CS_EQUALISER_22050_A1,
-     CS_EQUALISER_22050_A2,
-     CS_EQUALISER_22050_B1,
-     CS_EQUALISER_22050_B2,
-     (LVM_UINT16 )CS_EQUALISER_22050_SCALE},
-    {CS_EQUALISER_24000_A0,     /* 24kS/s coefficients */
-     CS_EQUALISER_24000_A1,
-     CS_EQUALISER_24000_A2,
-     CS_EQUALISER_24000_B1,
-     CS_EQUALISER_24000_B2,
-     (LVM_UINT16 )CS_EQUALISER_24000_SCALE},
-    {CS_EQUALISER_32000_A0,     /* 32kS/s coefficients */
-     CS_EQUALISER_32000_A1,
-     CS_EQUALISER_32000_A2,
-     CS_EQUALISER_32000_B1,
-     CS_EQUALISER_32000_B2,
-     (LVM_UINT16 )CS_EQUALISER_32000_SCALE},
-    {CS_EQUALISER_44100_A0,     /* 44kS/s coefficients */
-     CS_EQUALISER_44100_A1,
-     CS_EQUALISER_44100_A2,
-     CS_EQUALISER_44100_B1,
-     CS_EQUALISER_44100_B2,
-     (LVM_UINT16 )CS_EQUALISER_44100_SCALE},
-    {CS_EQUALISER_48000_A0,     /* 48kS/s coefficients */
-     CS_EQUALISER_48000_A1,
-     CS_EQUALISER_48000_A2,
-     CS_EQUALISER_48000_B1,
-     CS_EQUALISER_48000_B2,
-     (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
-#ifdef HIGHER_FS
-    {CS_EQUALISER_88200_A0,     /* 88kS/s coeffieients */
-     CS_EQUALISER_88200_A1,
-     CS_EQUALISER_88200_A2,
-     CS_EQUALISER_88200_B1,
-     CS_EQUALISER_88200_B2,
-     (LVM_UINT16)CS_EQUALISER_88200_SCALE},
-    {CS_EQUALISER_96000_A0,     /* 96kS/s coefficients */
-     CS_EQUALISER_96000_A1,
-     CS_EQUALISER_96000_A2,
-     CS_EQUALISER_96000_B1,
-     CS_EQUALISER_96000_B2,
-     (LVM_UINT16 )CS_EQUALISER_96000_SCALE},
-    {CS_EQUALISER_176400_A0,     /* 176kS/s coefficients */
-     CS_EQUALISER_176400_A1,
-     CS_EQUALISER_176400_A2,
-     CS_EQUALISER_176400_B1,
-     CS_EQUALISER_176400_B2,
-     (LVM_UINT16)CS_EQUALISER_176400_SCALE},
-    {CS_EQUALISER_192000_A0,     /* 192kS/s coefficients */
-     CS_EQUALISER_192000_A1,
-     CS_EQUALISER_192000_A2,
-     CS_EQUALISER_192000_B1,
-     CS_EQUALISER_192000_B2,
-     (LVM_UINT16 )CS_EQUALISER_192000_SCALE},
-#endif
-
-    /* Concert Sound EX Headphone coefficients */
-    {CSEX_EQUALISER_8000_A0,    /* 8kS/s coefficients */
-     CSEX_EQUALISER_8000_A1,
-     CSEX_EQUALISER_8000_A2,
-     CSEX_EQUALISER_8000_B1,
-     CSEX_EQUALISER_8000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_8000_SCALE},
-    {CSEX_EQUALISER_11025_A0,   /* 11kS/s coefficients */
-     CSEX_EQUALISER_11025_A1,
-     CSEX_EQUALISER_11025_A2,
-     CSEX_EQUALISER_11025_B1,
-     CSEX_EQUALISER_11025_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_11025_SCALE},
-    {CSEX_EQUALISER_12000_A0,   /* 12kS/s coefficients */
-     CSEX_EQUALISER_12000_A1,
-     CSEX_EQUALISER_12000_A2,
-     CSEX_EQUALISER_12000_B1,
-     CSEX_EQUALISER_12000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_12000_SCALE},
-    {CSEX_EQUALISER_16000_A0,   /* 16kS/s coefficients */
-     CSEX_EQUALISER_16000_A1,
-     CSEX_EQUALISER_16000_A2,
-     CSEX_EQUALISER_16000_B1,
-     CSEX_EQUALISER_16000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_16000_SCALE},
-    {CSEX_EQUALISER_22050_A0,   /* 22kS/s coefficients */
-     CSEX_EQUALISER_22050_A1,
-     CSEX_EQUALISER_22050_A2,
-     CSEX_EQUALISER_22050_B1,
-     CSEX_EQUALISER_22050_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_22050_SCALE},
-    {CSEX_EQUALISER_24000_A0,   /* 24kS/s coefficients */
-     CSEX_EQUALISER_24000_A1,
-     CSEX_EQUALISER_24000_A2,
-     CSEX_EQUALISER_24000_B1,
-     CSEX_EQUALISER_24000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_24000_SCALE},
-    {CSEX_EQUALISER_32000_A0,   /* 32kS/s coefficients */
-     CSEX_EQUALISER_32000_A1,
-     CSEX_EQUALISER_32000_A2,
-     CSEX_EQUALISER_32000_B1,
-     CSEX_EQUALISER_32000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_32000_SCALE},
-    {CSEX_EQUALISER_44100_A0,   /* 44kS/s coefficients */
-     CSEX_EQUALISER_44100_A1,
-     CSEX_EQUALISER_44100_A2,
-     CSEX_EQUALISER_44100_B1,
-     CSEX_EQUALISER_44100_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_44100_SCALE},
-    {CSEX_EQUALISER_48000_A0,   /* 48kS/s coefficients */
-     CSEX_EQUALISER_48000_A1,
-     CSEX_EQUALISER_48000_A2,
-     CSEX_EQUALISER_48000_B1,
-     CSEX_EQUALISER_48000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
-#ifdef HIGHER_FS
-    ,
-    {CSEX_EQUALISER_88200_A0,   /* 88kS/s coefficients */
-     CSEX_EQUALISER_88200_A1,
-     CSEX_EQUALISER_88200_A2,
-     CSEX_EQUALISER_88200_B1,
-     CSEX_EQUALISER_88200_B2,
-     (LVM_UINT16)CSEX_EQUALISER_88200_SCALE},
-    {CSEX_EQUALISER_96000_A0,   /* 96kS/s coefficients */
-     CSEX_EQUALISER_96000_A1,
-     CSEX_EQUALISER_96000_A2,
-     CSEX_EQUALISER_96000_B1,
-     CSEX_EQUALISER_96000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_96000_SCALE},
-    {CSEX_EQUALISER_176400_A0,   /* 176kS/s coefficients */
-     CSEX_EQUALISER_176400_A1,
-     CSEX_EQUALISER_176400_A2,
-     CSEX_EQUALISER_176400_B1,
-     CSEX_EQUALISER_176400_B2,
-     (LVM_UINT16)CSEX_EQUALISER_176400_SCALE},
-     {CSEX_EQUALISER_192000_A0,   /* 192kS/s coefficients */
-     CSEX_EQUALISER_192000_A1,
-     CSEX_EQUALISER_192000_A2,
-     CSEX_EQUALISER_192000_B1,
-     CSEX_EQUALISER_192000_B2,
-     (LVM_UINT16 )CSEX_EQUALISER_192000_SCALE}
-#endif
-};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Reverb delay constant tables                                                    */
-/*                                                                                  */
-/************************************************************************************/
-
-/* Stereo delay table for Concert Sound */
-const LVM_UINT16    LVCS_StereoDelayCS[] = {
-    LVCS_STEREODELAY_CS_8KHZ,
-    LVCS_STEREODELAY_CS_11KHZ,
-    LVCS_STEREODELAY_CS_12KHZ,
-    LVCS_STEREODELAY_CS_16KHZ,
-    LVCS_STEREODELAY_CS_22KHZ,
-    LVCS_STEREODELAY_CS_24KHZ,
-    LVCS_STEREODELAY_CS_32KHZ,
-    LVCS_STEREODELAY_CS_44KHZ,
-    LVCS_STEREODELAY_CS_48KHZ,
-    LVCS_STEREODELAY_CS_88KHZ,
-    LVCS_STEREODELAY_CS_96KHZ,
-    LVCS_STEREODELAY_CS_176KHZ,
-    LVCS_STEREODELAY_CS_192KHZ,
-};
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Reverb coefficients constant table                                              */
-/*                                                                                  */
-/************************************************************************************/
-
-const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[] = {
-    /* Headphone coefficients */
-    {CS_REVERB_8000_A0,             /* 8kS/s coefficients */
-     CS_REVERB_8000_A1,
-     CS_REVERB_8000_A2,
-     CS_REVERB_8000_B1,
-     CS_REVERB_8000_B2,
-     (LVM_UINT16 )CS_REVERB_8000_SCALE},
-    {CS_REVERB_11025_A0,            /* 11kS/s coefficients */
-     CS_REVERB_11025_A1,
-     CS_REVERB_11025_A2,
-     CS_REVERB_11025_B1,
-     CS_REVERB_11025_B2,
-     (LVM_UINT16 )CS_REVERB_11025_SCALE},
-    {CS_REVERB_12000_A0,            /* 12kS/s coefficients */
-     CS_REVERB_12000_A1,
-     CS_REVERB_12000_A2,
-     CS_REVERB_12000_B1,
-     CS_REVERB_12000_B2,
-     (LVM_UINT16 )CS_REVERB_12000_SCALE},
-    {CS_REVERB_16000_A0,            /* 16kS/s coefficients */
-     CS_REVERB_16000_A1,
-     CS_REVERB_16000_A2,
-     CS_REVERB_16000_B1,
-     CS_REVERB_16000_B2,
-     (LVM_UINT16 )CS_REVERB_16000_SCALE},
-    {CS_REVERB_22050_A0,            /* 22kS/s coefficients */
-     CS_REVERB_22050_A1,
-     CS_REVERB_22050_A2,
-     CS_REVERB_22050_B1,
-     CS_REVERB_22050_B2,
-     (LVM_UINT16 )CS_REVERB_22050_SCALE},
-    {CS_REVERB_24000_A0,            /* 24kS/s coefficients */
-     CS_REVERB_24000_A1,
-     CS_REVERB_24000_A2,
-     CS_REVERB_24000_B1,
-     CS_REVERB_24000_B2,
-     (LVM_UINT16 )CS_REVERB_24000_SCALE},
-    {CS_REVERB_32000_A0,            /* 32kS/s coefficients */
-     CS_REVERB_32000_A1,
-     CS_REVERB_32000_A2,
-     CS_REVERB_32000_B1,
-     CS_REVERB_32000_B2,
-     (LVM_UINT16 )CS_REVERB_32000_SCALE},
-    {CS_REVERB_44100_A0,            /* 44kS/s coefficients */
-     CS_REVERB_44100_A1,
-     CS_REVERB_44100_A2,
-     CS_REVERB_44100_B1,
-     CS_REVERB_44100_B2,
-     (LVM_UINT16 )CS_REVERB_44100_SCALE},
-    {CS_REVERB_48000_A0,            /* 48kS/s coefficients */
-     CS_REVERB_48000_A1,
-     CS_REVERB_48000_A2,
-     CS_REVERB_48000_B1,
-     CS_REVERB_48000_B2,
-     (LVM_UINT16 )CS_REVERB_48000_SCALE}
-#ifdef HIGHER_FS
-    ,
-    {CS_REVERB_88200_A0,            /* 88kS/s coefficients */
-     CS_REVERB_88200_A1,
-     CS_REVERB_88200_A2,
-     CS_REVERB_88200_B1,
-     CS_REVERB_88200_B2,
-     (LVM_UINT16)CS_REVERB_88200_SCALE},
-    {CS_REVERB_96000_A0,            /* 96kS/s coefficients */
-     CS_REVERB_96000_A1,
-     CS_REVERB_96000_A2,
-     CS_REVERB_96000_B1,
-     CS_REVERB_96000_B2,
-     (LVM_UINT16 )CS_REVERB_96000_SCALE},
-    {CS_REVERB_176400_A0,            /* 176kS/s coefficients */
-     CS_REVERB_176400_A1,
-     CS_REVERB_176400_A2,
-     CS_REVERB_176400_B1,
-     CS_REVERB_176400_B2,
-     (LVM_UINT16)CS_REVERB_176400_SCALE},
-     {CS_REVERB_192000_A0,            /* 192kS/s coefficients */
-     CS_REVERB_192000_A1,
-     CS_REVERB_192000_A2,
-     CS_REVERB_192000_B1,
-     CS_REVERB_192000_B2,
-     (LVM_UINT16 )CS_REVERB_192000_SCALE}
-#endif
-};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Bypass mixer constant tables                                                    */
-/*                                                                                  */
-/************************************************************************************/
-
-const Gain_t LVCS_OutputGainTable[] = {
-    {LVCS_HEADPHONE_SHIFT,         /* Headphone, stereo mode */
-     LVCS_HEADPHONE_SHIFTLOSS,
-     LVCS_HEADPHONE_GAIN},
-    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, stereo mode */
-     LVCS_EX_HEADPHONE_SHIFTLOSS,
-     LVCS_EX_HEADPHONE_GAIN},
-    {LVCS_HEADPHONE_SHIFT,         /* Headphone, mono mode */
-     LVCS_HEADPHONE_SHIFTLOSS,
-     LVCS_HEADPHONE_GAIN},
-    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, mono mode */
-     LVCS_EX_HEADPHONE_SHIFTLOSS,
-     LVCS_EX_HEADPHONE_GAIN}
-};
-
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Volume correction table                                                         */
-/*                                                                                  */
-/*  Coefficient order:                                                              */
-/*      Compression 100% effect                                                     */
-/*      Compression 0% effect                                                       */
-/*      Gain 100% effect                                                            */
-/*      Gain 0% effect                                                              */
-/*                                                                                  */
-/*  The Compression gain is represented by a Q1.15 number to give a range of 0dB    */
-/*  to +6dB, E.g.:                                                                  */
-/*          0       is 0dB compression (no effect)                                  */
-/*          5461    is 1dB compression gain                                         */
-/*          10923   is 2dB compression gain                                         */
-/*          32767   is 6dB compression gain                                         */
-/*                                                                                  */
-/*  The Gain is represented as a Q3.13 number to give a range of +8 to -infinity    */
-/*  E.g.:                                                                           */
-/*          0       is -infinity                                                    */
-/*          32767   is +18dB (x8) gain                                              */
-/*          4096    is 0dB gain                                                     */
-/*          1024    is -12dB gain                                                   */
-/*                                                                                  */
-/************************************************************************************/
-const LVCS_VolCorrect_t LVCS_VolCorrectTable[] = {
-#ifdef BUILD_FLOAT
-    {0.433362f,          /* Headphone, stereo mode */
-     0.000000f,
-     1.000024f,
-     1.412640f},
-    {0.433362f,          /* EX Headphone, stereo mode */
-     0.000000f,
-     1.000024f,
-     1.412640f},
-    {1.000000f,         /* Headphone, mono mode */
-     0.000000f,
-     1.000024f,
-     1.412640f},
-    {1.000000f,         /* EX Headphone, mono mode */
-     0.000000f,
-     1.000024f,
-     1.412640f}
-#else
-    {14200,          /* Headphone, stereo mode */
-     0,
-     4096,
-     5786},
-    {14200,          /* EX Headphone, stereo mode */
-     0,
-     4096,
-     5786},
-    {32767,         /* Headphone, mono mode */
-     0,
-     4096,
-     5786},
-    {32767,         /* EX Headphone, mono mode */
-     0,
-     4096,
-     5786}
-#endif
-};
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Mixer time constants, 100ms                                                     */
-/*                                                                                  */
-/************************************************************************************/
-
-#define LVCS_VOL_TC_Fs8000      32580       /* Floating point value 0.994262695 */
-#define LVCS_VOL_TC_Fs11025     32632       /* Floating point value 0.995849609 */
-#define LVCS_VOL_TC_Fs12000     32643       /* Floating point value 0.996185303 */
-#define LVCS_VOL_TC_Fs16000     32674       /* Floating point value 0.997131348 */
-#define LVCS_VOL_TC_Fs22050     32700       /* Floating point value 0.997924805 */
-#define LVCS_VOL_TC_Fs24000     32705       /* Floating point value 0.998077393 */
-#define LVCS_VOL_TC_Fs32000     32721       /* Floating point value 0.998565674 */
-#define LVCS_VOL_TC_Fs44100     32734       /* Floating point value 0.998962402 */
-#define LVCS_VOL_TC_Fs48000     32737       /* Floating point value 0.999053955 */
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-#define LVCS_VOL_TC_Fs88200     32751       /* Floating point value 0.999481066 */
-#define LVCS_VOL_TC_Fs96000     32751       /* Floating point value 0.999511703 */   /* Todo @ need to re check this value*/
-#define LVCS_VOL_TC_Fs176400    32759       /* Floating point value 0.999740499 */
-#define LVCS_VOL_TC_Fs192000    32763       /* Floating point value 0.999877925 */  /* Todo @ need to re check this value*/
-#endif
-
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-const LVM_INT16 LVCS_VolumeTCTable[13] = {LVCS_VOL_TC_Fs8000,
-                                          LVCS_VOL_TC_Fs11025,
-                                          LVCS_VOL_TC_Fs12000,
-                                          LVCS_VOL_TC_Fs16000,
-                                          LVCS_VOL_TC_Fs22050,
-                                          LVCS_VOL_TC_Fs24000,
-                                          LVCS_VOL_TC_Fs32000,
-                                          LVCS_VOL_TC_Fs44100,
-                                          LVCS_VOL_TC_Fs48000,
-                                          LVCS_VOL_TC_Fs88200,
-                                          LVCS_VOL_TC_Fs96000,
-                                          LVCS_VOL_TC_Fs176400,
-                                          LVCS_VOL_TC_Fs192000
-};
-#else
-const LVM_INT16 LVCS_VolumeTCTable[9] = {LVCS_VOL_TC_Fs8000,
-                                        LVCS_VOL_TC_Fs11025,
-                                        LVCS_VOL_TC_Fs12000,
-                                        LVCS_VOL_TC_Fs16000,
-                                        LVCS_VOL_TC_Fs22050,
-                                        LVCS_VOL_TC_Fs24000,
-                                        LVCS_VOL_TC_Fs32000,
-                                        LVCS_VOL_TC_Fs44100,
-                                        LVCS_VOL_TC_Fs48000
-};
-#endif
-
-/************************************************************************************/
-/*                                                                                  */
-/*  Sample rate table                                                               */
-/*                                                                                  */
-/************************************************************************************/
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-const LVM_INT32   LVCS_SampleRateTable[13] = {8000,
-                                              11025,
-                                              12000,
-                                              16000,
-                                              22050,
-                                              24000,
-                                              32000,
-                                              44100,
-                                              48000,
-                                              88200,
-                                              96000,
-                                              176400,
-                                              192000
-};
-#else
-const LVM_INT16   LVCS_SampleRateTable[9] = {8000,
-                                            11025,
-                                            12000,
-                                            16000,
-                                            22050,
-                                            24000,
-                                            32000,
-                                            44100,
-                                            48000
-};
-#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.cpp
new file mode 100644
index 0000000..d79db61
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+#include "Filters.h"                            /* Filter definitions */
+#include "BIQUAD.h"                             /* Biquad definitions */
+#include "LVCS_Headphone_Coeffs.h"              /* Headphone coefficients */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Stereo Enhancer coefficient constant tables                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Coefficient table for the middle filter */
+const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[] = {
+    {CS_MIDDLE_8000_A0,         /* 8kS/s coefficients */
+     CS_MIDDLE_8000_A1,
+     CS_MIDDLE_8000_B1,
+     (LVM_UINT16 )CS_MIDDLE_8000_SCALE},
+    {CS_MIDDLE_11025_A0,        /* 11kS/s coefficients */
+     CS_MIDDLE_11025_A1,
+     CS_MIDDLE_11025_B1,
+     (LVM_UINT16 )CS_MIDDLE_11025_SCALE},
+    {CS_MIDDLE_12000_A0,        /* 12kS/s coefficients */
+     CS_MIDDLE_12000_A1,
+     CS_MIDDLE_12000_B1,
+     (LVM_UINT16 )CS_MIDDLE_12000_SCALE},
+    {CS_MIDDLE_16000_A0,        /* 16kS/s coefficients */
+     CS_MIDDLE_16000_A1,
+     CS_MIDDLE_16000_B1,
+     (LVM_UINT16 )CS_MIDDLE_16000_SCALE},
+    {CS_MIDDLE_22050_A0,        /* 22kS/s coefficients */
+     CS_MIDDLE_22050_A1,
+     CS_MIDDLE_22050_B1,
+     (LVM_UINT16 )CS_MIDDLE_22050_SCALE},
+    {CS_MIDDLE_24000_A0,        /* 24kS/s coefficients */
+     CS_MIDDLE_24000_A1,
+     CS_MIDDLE_24000_B1,
+     (LVM_UINT16 )CS_MIDDLE_24000_SCALE},
+    {CS_MIDDLE_32000_A0,        /* 32kS/s coefficients */
+     CS_MIDDLE_32000_A1,
+     CS_MIDDLE_32000_B1,
+     (LVM_UINT16 )CS_MIDDLE_32000_SCALE},
+    {CS_MIDDLE_44100_A0,        /* 44kS/s coefficients */
+     CS_MIDDLE_44100_A1,
+     CS_MIDDLE_44100_B1,
+     (LVM_UINT16 )CS_MIDDLE_44100_SCALE},
+    {CS_MIDDLE_48000_A0,        /* 48kS/s coefficients */
+     CS_MIDDLE_48000_A1,
+     CS_MIDDLE_48000_B1,
+     (LVM_UINT16 )CS_MIDDLE_48000_SCALE}
+    ,
+    {CS_MIDDLE_88200_A0,        /* 88kS/s coefficients */
+     CS_MIDDLE_88200_A1,
+     CS_MIDDLE_88200_B1,
+     (LVM_UINT16)CS_MIDDLE_88200_SCALE},
+    {CS_MIDDLE_96000_A0,        /* 96kS/s coefficients */
+     CS_MIDDLE_96000_A1,
+     CS_MIDDLE_96000_B1,
+     (LVM_UINT16 )CS_MIDDLE_96000_SCALE},
+    {CS_MIDDLE_176400_A0,        /* 176kS/s coefficients */
+     CS_MIDDLE_176400_A1,
+     CS_MIDDLE_176400_B1,
+     (LVM_UINT16)CS_MIDDLE_176400_SCALE},
+    {CS_MIDDLE_192000_A0,        /* 192kS/s coefficients */
+     CS_MIDDLE_192000_A1,
+     CS_MIDDLE_192000_B1,
+     (LVM_UINT16 )CS_MIDDLE_192000_SCALE}
+    };
+
+/* Coefficient table for the side filter */
+const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[] = {
+    /* Headphone Side coefficients */
+    {CS_SIDE_8000_A0,           /* 8kS/s coefficients */
+     CS_SIDE_8000_A1,
+     CS_SIDE_8000_A2,
+     CS_SIDE_8000_B1,
+     CS_SIDE_8000_B2,
+     (LVM_UINT16 )CS_SIDE_8000_SCALE},
+    {CS_SIDE_11025_A0,          /* 11kS/s coefficients */
+     CS_SIDE_11025_A1,
+     CS_SIDE_11025_A2,
+     CS_SIDE_11025_B1,
+     CS_SIDE_11025_B2,
+     (LVM_UINT16 )CS_SIDE_11025_SCALE},
+    {CS_SIDE_12000_A0,          /* 12kS/s coefficients */
+     CS_SIDE_12000_A1,
+     CS_SIDE_12000_A2,
+     CS_SIDE_12000_B1,
+     CS_SIDE_12000_B2,
+     (LVM_UINT16 )CS_SIDE_12000_SCALE},
+    {CS_SIDE_16000_A0,          /* 16kS/s coefficients */
+     CS_SIDE_16000_A1,
+     CS_SIDE_16000_A2,
+     CS_SIDE_16000_B1,
+     CS_SIDE_16000_B2,
+     (LVM_UINT16 )CS_SIDE_16000_SCALE},
+    {CS_SIDE_22050_A0,          /* 22kS/s coefficients */
+     CS_SIDE_22050_A1,
+     CS_SIDE_22050_A2,
+     CS_SIDE_22050_B1,
+     CS_SIDE_22050_B2,
+     (LVM_UINT16 )CS_SIDE_22050_SCALE},
+    {CS_SIDE_24000_A0,          /* 24kS/s coefficients */
+     CS_SIDE_24000_A1,
+     CS_SIDE_24000_A2,
+     CS_SIDE_24000_B1,
+     CS_SIDE_24000_B2,
+     (LVM_UINT16 )CS_SIDE_24000_SCALE},
+    {CS_SIDE_32000_A0,          /* 32kS/s coefficients */
+     CS_SIDE_32000_A1,
+     CS_SIDE_32000_A2,
+     CS_SIDE_32000_B1,
+     CS_SIDE_32000_B2,
+     (LVM_UINT16 )CS_SIDE_32000_SCALE},
+    {CS_SIDE_44100_A0,          /* 44kS/s coefficients */
+     CS_SIDE_44100_A1,
+     CS_SIDE_44100_A2,
+     CS_SIDE_44100_B1,
+     CS_SIDE_44100_B2,
+     (LVM_UINT16 )CS_SIDE_44100_SCALE},
+    {CS_SIDE_48000_A0,          /* 48kS/s coefficients */
+     CS_SIDE_48000_A1,
+     CS_SIDE_48000_A2,
+     CS_SIDE_48000_B1,
+     CS_SIDE_48000_B2,
+     (LVM_UINT16 )CS_SIDE_48000_SCALE}
+     ,
+    {CS_SIDE_88200_A0,          /* 88kS/s coefficients */
+     CS_SIDE_88200_A1,
+     CS_SIDE_88200_A2,
+     CS_SIDE_88200_B1,
+     CS_SIDE_88200_B2,
+     (LVM_UINT16)CS_SIDE_88200_SCALE},
+     {CS_SIDE_96000_A0,          /* 96kS/s coefficients */
+     CS_SIDE_96000_A1,
+     CS_SIDE_96000_A2,
+     CS_SIDE_96000_B1,
+     CS_SIDE_96000_B2,
+     (LVM_UINT16 )CS_SIDE_96000_SCALE},
+    {CS_SIDE_176400_A0,          /*176kS/s coefficients */
+     CS_SIDE_176400_A1,
+     CS_SIDE_176400_A2,
+     CS_SIDE_176400_B1,
+     CS_SIDE_176400_B2,
+     (LVM_UINT16)CS_SIDE_176400_SCALE},
+     {CS_SIDE_192000_A0,          /* 192kS/s coefficients */
+     CS_SIDE_192000_A1,
+     CS_SIDE_192000_A2,
+     CS_SIDE_192000_B1,
+     CS_SIDE_192000_B2,
+     (LVM_UINT16 )CS_SIDE_192000_SCALE}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Equaliser coefficient constant tables                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[] = {
+    /* Headphone coefficients */
+    {CS_EQUALISER_8000_A0,      /* 8kS/s coefficients */
+     CS_EQUALISER_8000_A1,
+     CS_EQUALISER_8000_A2,
+     CS_EQUALISER_8000_B1,
+     CS_EQUALISER_8000_B2,
+     (LVM_UINT16 )CS_EQUALISER_8000_SCALE},
+    {CS_EQUALISER_11025_A0,     /* 11kS/s coefficients */
+     CS_EQUALISER_11025_A1,
+     CS_EQUALISER_11025_A2,
+     CS_EQUALISER_11025_B1,
+     CS_EQUALISER_11025_B2,
+     (LVM_UINT16 )CS_EQUALISER_11025_SCALE},
+    {CS_EQUALISER_12000_A0,     /* 12kS/s coefficients */
+     CS_EQUALISER_12000_A1,
+     CS_EQUALISER_12000_A2,
+     CS_EQUALISER_12000_B1,
+     CS_EQUALISER_12000_B2,
+     (LVM_UINT16 )CS_EQUALISER_12000_SCALE},
+    {CS_EQUALISER_16000_A0,     /* 16kS/s coefficients */
+     CS_EQUALISER_16000_A1,
+     CS_EQUALISER_16000_A2,
+     CS_EQUALISER_16000_B1,
+     CS_EQUALISER_16000_B2,
+     (LVM_UINT16 )CS_EQUALISER_16000_SCALE},
+    {CS_EQUALISER_22050_A0,     /* 22kS/s coefficients */
+     CS_EQUALISER_22050_A1,
+     CS_EQUALISER_22050_A2,
+     CS_EQUALISER_22050_B1,
+     CS_EQUALISER_22050_B2,
+     (LVM_UINT16 )CS_EQUALISER_22050_SCALE},
+    {CS_EQUALISER_24000_A0,     /* 24kS/s coefficients */
+     CS_EQUALISER_24000_A1,
+     CS_EQUALISER_24000_A2,
+     CS_EQUALISER_24000_B1,
+     CS_EQUALISER_24000_B2,
+     (LVM_UINT16 )CS_EQUALISER_24000_SCALE},
+    {CS_EQUALISER_32000_A0,     /* 32kS/s coefficients */
+     CS_EQUALISER_32000_A1,
+     CS_EQUALISER_32000_A2,
+     CS_EQUALISER_32000_B1,
+     CS_EQUALISER_32000_B2,
+     (LVM_UINT16 )CS_EQUALISER_32000_SCALE},
+    {CS_EQUALISER_44100_A0,     /* 44kS/s coefficients */
+     CS_EQUALISER_44100_A1,
+     CS_EQUALISER_44100_A2,
+     CS_EQUALISER_44100_B1,
+     CS_EQUALISER_44100_B2,
+     (LVM_UINT16 )CS_EQUALISER_44100_SCALE},
+    {CS_EQUALISER_48000_A0,     /* 48kS/s coefficients */
+     CS_EQUALISER_48000_A1,
+     CS_EQUALISER_48000_A2,
+     CS_EQUALISER_48000_B1,
+     CS_EQUALISER_48000_B2,
+     (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
+    {CS_EQUALISER_88200_A0,     /* 88kS/s coeffieients */
+     CS_EQUALISER_88200_A1,
+     CS_EQUALISER_88200_A2,
+     CS_EQUALISER_88200_B1,
+     CS_EQUALISER_88200_B2,
+     (LVM_UINT16)CS_EQUALISER_88200_SCALE},
+    {CS_EQUALISER_96000_A0,     /* 96kS/s coefficients */
+     CS_EQUALISER_96000_A1,
+     CS_EQUALISER_96000_A2,
+     CS_EQUALISER_96000_B1,
+     CS_EQUALISER_96000_B2,
+     (LVM_UINT16 )CS_EQUALISER_96000_SCALE},
+    {CS_EQUALISER_176400_A0,     /* 176kS/s coefficients */
+     CS_EQUALISER_176400_A1,
+     CS_EQUALISER_176400_A2,
+     CS_EQUALISER_176400_B1,
+     CS_EQUALISER_176400_B2,
+     (LVM_UINT16)CS_EQUALISER_176400_SCALE},
+    {CS_EQUALISER_192000_A0,     /* 192kS/s coefficients */
+     CS_EQUALISER_192000_A1,
+     CS_EQUALISER_192000_A2,
+     CS_EQUALISER_192000_B1,
+     CS_EQUALISER_192000_B2,
+     (LVM_UINT16 )CS_EQUALISER_192000_SCALE},
+
+    /* Concert Sound EX Headphone coefficients */
+    {CSEX_EQUALISER_8000_A0,    /* 8kS/s coefficients */
+     CSEX_EQUALISER_8000_A1,
+     CSEX_EQUALISER_8000_A2,
+     CSEX_EQUALISER_8000_B1,
+     CSEX_EQUALISER_8000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_8000_SCALE},
+    {CSEX_EQUALISER_11025_A0,   /* 11kS/s coefficients */
+     CSEX_EQUALISER_11025_A1,
+     CSEX_EQUALISER_11025_A2,
+     CSEX_EQUALISER_11025_B1,
+     CSEX_EQUALISER_11025_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_11025_SCALE},
+    {CSEX_EQUALISER_12000_A0,   /* 12kS/s coefficients */
+     CSEX_EQUALISER_12000_A1,
+     CSEX_EQUALISER_12000_A2,
+     CSEX_EQUALISER_12000_B1,
+     CSEX_EQUALISER_12000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_12000_SCALE},
+    {CSEX_EQUALISER_16000_A0,   /* 16kS/s coefficients */
+     CSEX_EQUALISER_16000_A1,
+     CSEX_EQUALISER_16000_A2,
+     CSEX_EQUALISER_16000_B1,
+     CSEX_EQUALISER_16000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_16000_SCALE},
+    {CSEX_EQUALISER_22050_A0,   /* 22kS/s coefficients */
+     CSEX_EQUALISER_22050_A1,
+     CSEX_EQUALISER_22050_A2,
+     CSEX_EQUALISER_22050_B1,
+     CSEX_EQUALISER_22050_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_22050_SCALE},
+    {CSEX_EQUALISER_24000_A0,   /* 24kS/s coefficients */
+     CSEX_EQUALISER_24000_A1,
+     CSEX_EQUALISER_24000_A2,
+     CSEX_EQUALISER_24000_B1,
+     CSEX_EQUALISER_24000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_24000_SCALE},
+    {CSEX_EQUALISER_32000_A0,   /* 32kS/s coefficients */
+     CSEX_EQUALISER_32000_A1,
+     CSEX_EQUALISER_32000_A2,
+     CSEX_EQUALISER_32000_B1,
+     CSEX_EQUALISER_32000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_32000_SCALE},
+    {CSEX_EQUALISER_44100_A0,   /* 44kS/s coefficients */
+     CSEX_EQUALISER_44100_A1,
+     CSEX_EQUALISER_44100_A2,
+     CSEX_EQUALISER_44100_B1,
+     CSEX_EQUALISER_44100_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_44100_SCALE},
+    {CSEX_EQUALISER_48000_A0,   /* 48kS/s coefficients */
+     CSEX_EQUALISER_48000_A1,
+     CSEX_EQUALISER_48000_A2,
+     CSEX_EQUALISER_48000_B1,
+     CSEX_EQUALISER_48000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
+    ,
+    {CSEX_EQUALISER_88200_A0,   /* 88kS/s coefficients */
+     CSEX_EQUALISER_88200_A1,
+     CSEX_EQUALISER_88200_A2,
+     CSEX_EQUALISER_88200_B1,
+     CSEX_EQUALISER_88200_B2,
+     (LVM_UINT16)CSEX_EQUALISER_88200_SCALE},
+    {CSEX_EQUALISER_96000_A0,   /* 96kS/s coefficients */
+     CSEX_EQUALISER_96000_A1,
+     CSEX_EQUALISER_96000_A2,
+     CSEX_EQUALISER_96000_B1,
+     CSEX_EQUALISER_96000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_96000_SCALE},
+    {CSEX_EQUALISER_176400_A0,   /* 176kS/s coefficients */
+     CSEX_EQUALISER_176400_A1,
+     CSEX_EQUALISER_176400_A2,
+     CSEX_EQUALISER_176400_B1,
+     CSEX_EQUALISER_176400_B2,
+     (LVM_UINT16)CSEX_EQUALISER_176400_SCALE},
+     {CSEX_EQUALISER_192000_A0,   /* 192kS/s coefficients */
+     CSEX_EQUALISER_192000_A1,
+     CSEX_EQUALISER_192000_A2,
+     CSEX_EQUALISER_192000_B1,
+     CSEX_EQUALISER_192000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_192000_SCALE}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb delay constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Stereo delay table for Concert Sound */
+const LVM_UINT16    LVCS_StereoDelayCS[] = {
+    LVCS_STEREODELAY_CS_8KHZ,
+    LVCS_STEREODELAY_CS_11KHZ,
+    LVCS_STEREODELAY_CS_12KHZ,
+    LVCS_STEREODELAY_CS_16KHZ,
+    LVCS_STEREODELAY_CS_22KHZ,
+    LVCS_STEREODELAY_CS_24KHZ,
+    LVCS_STEREODELAY_CS_32KHZ,
+    LVCS_STEREODELAY_CS_44KHZ,
+    LVCS_STEREODELAY_CS_48KHZ,
+    LVCS_STEREODELAY_CS_88KHZ,
+    LVCS_STEREODELAY_CS_96KHZ,
+    LVCS_STEREODELAY_CS_176KHZ,
+    LVCS_STEREODELAY_CS_192KHZ,
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb coefficients constant table                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[] = {
+    /* Headphone coefficients */
+    {CS_REVERB_8000_A0,             /* 8kS/s coefficients */
+     CS_REVERB_8000_A1,
+     CS_REVERB_8000_A2,
+     CS_REVERB_8000_B1,
+     CS_REVERB_8000_B2,
+     (LVM_UINT16 )CS_REVERB_8000_SCALE},
+    {CS_REVERB_11025_A0,            /* 11kS/s coefficients */
+     CS_REVERB_11025_A1,
+     CS_REVERB_11025_A2,
+     CS_REVERB_11025_B1,
+     CS_REVERB_11025_B2,
+     (LVM_UINT16 )CS_REVERB_11025_SCALE},
+    {CS_REVERB_12000_A0,            /* 12kS/s coefficients */
+     CS_REVERB_12000_A1,
+     CS_REVERB_12000_A2,
+     CS_REVERB_12000_B1,
+     CS_REVERB_12000_B2,
+     (LVM_UINT16 )CS_REVERB_12000_SCALE},
+    {CS_REVERB_16000_A0,            /* 16kS/s coefficients */
+     CS_REVERB_16000_A1,
+     CS_REVERB_16000_A2,
+     CS_REVERB_16000_B1,
+     CS_REVERB_16000_B2,
+     (LVM_UINT16 )CS_REVERB_16000_SCALE},
+    {CS_REVERB_22050_A0,            /* 22kS/s coefficients */
+     CS_REVERB_22050_A1,
+     CS_REVERB_22050_A2,
+     CS_REVERB_22050_B1,
+     CS_REVERB_22050_B2,
+     (LVM_UINT16 )CS_REVERB_22050_SCALE},
+    {CS_REVERB_24000_A0,            /* 24kS/s coefficients */
+     CS_REVERB_24000_A1,
+     CS_REVERB_24000_A2,
+     CS_REVERB_24000_B1,
+     CS_REVERB_24000_B2,
+     (LVM_UINT16 )CS_REVERB_24000_SCALE},
+    {CS_REVERB_32000_A0,            /* 32kS/s coefficients */
+     CS_REVERB_32000_A1,
+     CS_REVERB_32000_A2,
+     CS_REVERB_32000_B1,
+     CS_REVERB_32000_B2,
+     (LVM_UINT16 )CS_REVERB_32000_SCALE},
+    {CS_REVERB_44100_A0,            /* 44kS/s coefficients */
+     CS_REVERB_44100_A1,
+     CS_REVERB_44100_A2,
+     CS_REVERB_44100_B1,
+     CS_REVERB_44100_B2,
+     (LVM_UINT16 )CS_REVERB_44100_SCALE},
+    {CS_REVERB_48000_A0,            /* 48kS/s coefficients */
+     CS_REVERB_48000_A1,
+     CS_REVERB_48000_A2,
+     CS_REVERB_48000_B1,
+     CS_REVERB_48000_B2,
+     (LVM_UINT16 )CS_REVERB_48000_SCALE}
+    ,
+    {CS_REVERB_88200_A0,            /* 88kS/s coefficients */
+     CS_REVERB_88200_A1,
+     CS_REVERB_88200_A2,
+     CS_REVERB_88200_B1,
+     CS_REVERB_88200_B2,
+     (LVM_UINT16)CS_REVERB_88200_SCALE},
+    {CS_REVERB_96000_A0,            /* 96kS/s coefficients */
+     CS_REVERB_96000_A1,
+     CS_REVERB_96000_A2,
+     CS_REVERB_96000_B1,
+     CS_REVERB_96000_B2,
+     (LVM_UINT16 )CS_REVERB_96000_SCALE},
+    {CS_REVERB_176400_A0,            /* 176kS/s coefficients */
+     CS_REVERB_176400_A1,
+     CS_REVERB_176400_A2,
+     CS_REVERB_176400_B1,
+     CS_REVERB_176400_B2,
+     (LVM_UINT16)CS_REVERB_176400_SCALE},
+     {CS_REVERB_192000_A0,            /* 192kS/s coefficients */
+     CS_REVERB_192000_A1,
+     CS_REVERB_192000_A2,
+     CS_REVERB_192000_B1,
+     CS_REVERB_192000_B2,
+     (LVM_UINT16 )CS_REVERB_192000_SCALE}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Bypass mixer constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+const Gain_t LVCS_OutputGainTable[] = {
+    {LVCS_HEADPHONE_SHIFT,         /* Headphone, stereo mode */
+     LVCS_HEADPHONE_SHIFTLOSS,
+     LVCS_HEADPHONE_GAIN},
+    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, stereo mode */
+     LVCS_EX_HEADPHONE_SHIFTLOSS,
+     LVCS_EX_HEADPHONE_GAIN},
+    {LVCS_HEADPHONE_SHIFT,         /* Headphone, mono mode */
+     LVCS_HEADPHONE_SHIFTLOSS,
+     LVCS_HEADPHONE_GAIN},
+    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, mono mode */
+     LVCS_EX_HEADPHONE_SHIFTLOSS,
+     LVCS_EX_HEADPHONE_GAIN}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Volume correction table                                                         */
+/*                                                                                  */
+/*  Coefficient order:                                                              */
+/*      Compression 100% effect                                                     */
+/*      Compression 0% effect                                                       */
+/*      Gain 100% effect                                                            */
+/*      Gain 0% effect                                                              */
+/*                                                                                  */
+/*  The Compression gain is represented by a Q1.15 number to give a range of 0dB    */
+/*  to +6dB, E.g.:                                                                  */
+/*          0       is 0dB compression (no effect)                                  */
+/*          5461    is 1dB compression gain                                         */
+/*          10923   is 2dB compression gain                                         */
+/*          32767   is 6dB compression gain                                         */
+/*                                                                                  */
+/*  The Gain is represented as a Q3.13 number to give a range of +8 to -infinity    */
+/*  E.g.:                                                                           */
+/*          0       is -infinity                                                    */
+/*          32767   is +18dB (x8) gain                                              */
+/*          4096    is 0dB gain                                                     */
+/*          1024    is -12dB gain                                                   */
+/*                                                                                  */
+/************************************************************************************/
+const LVCS_VolCorrect_t LVCS_VolCorrectTable[] = {
+    {0.433362f,          /* Headphone, stereo mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {0.433362f,          /* EX Headphone, stereo mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {1.000000f,         /* Headphone, mono mode */
+     0.000000f,
+     1.000024f,
+     1.412640f},
+    {1.000000f,         /* EX Headphone, mono mode */
+     0.000000f,
+     1.000024f,
+     1.412640f}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Mixer time constants, 100ms                                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVCS_VOL_TC_Fs8000      32580       /* Floating point value 0.994262695 */
+#define LVCS_VOL_TC_Fs11025     32632       /* Floating point value 0.995849609 */
+#define LVCS_VOL_TC_Fs12000     32643       /* Floating point value 0.996185303 */
+#define LVCS_VOL_TC_Fs16000     32674       /* Floating point value 0.997131348 */
+#define LVCS_VOL_TC_Fs22050     32700       /* Floating point value 0.997924805 */
+#define LVCS_VOL_TC_Fs24000     32705       /* Floating point value 0.998077393 */
+#define LVCS_VOL_TC_Fs32000     32721       /* Floating point value 0.998565674 */
+#define LVCS_VOL_TC_Fs44100     32734       /* Floating point value 0.998962402 */
+#define LVCS_VOL_TC_Fs48000     32737       /* Floating point value 0.999053955 */
+#define LVCS_VOL_TC_Fs88200     32751       /* Floating point value 0.999481066 */
+#define LVCS_VOL_TC_Fs96000     32751       /* Floating point value 0.999511703 */   /* Todo @ need to re check this value*/
+#define LVCS_VOL_TC_Fs176400    32759       /* Floating point value 0.999740499 */
+#define LVCS_VOL_TC_Fs192000    32763       /* Floating point value 0.999877925 */  /* Todo @ need to re check this value*/
+
+const LVM_INT16 LVCS_VolumeTCTable[13] = {LVCS_VOL_TC_Fs8000,
+                                          LVCS_VOL_TC_Fs11025,
+                                          LVCS_VOL_TC_Fs12000,
+                                          LVCS_VOL_TC_Fs16000,
+                                          LVCS_VOL_TC_Fs22050,
+                                          LVCS_VOL_TC_Fs24000,
+                                          LVCS_VOL_TC_Fs32000,
+                                          LVCS_VOL_TC_Fs44100,
+                                          LVCS_VOL_TC_Fs48000,
+                                          LVCS_VOL_TC_Fs88200,
+                                          LVCS_VOL_TC_Fs96000,
+                                          LVCS_VOL_TC_Fs176400,
+                                          LVCS_VOL_TC_Fs192000
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate table                                                               */
+/*                                                                                  */
+/************************************************************************************/
+const LVM_INT32   LVCS_SampleRateTable[13] = {8000,
+                                              11025,
+                                              12000,
+                                              16000,
+                                              22050,
+                                              24000,
+                                              32000,
+                                              44100,
+                                              48000,
+                                              88200,
+                                              96000,
+                                              176400,
+                                              192000
+};
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
index 3f6c4c8..5490699 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
@@ -18,10 +18,6 @@
 #ifndef __LVCS_TABLES_H__
 #define __LVCS_TABLES_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Includes                                                                        */
@@ -104,15 +100,13 @@
 extern const LVCS_VolCorrect_t LVCS_VolCorrectTable[];
 extern const LVM_INT16 LVCS_VolumeTCTable[];
 
-
 /************************************************************************************/
 /*                                                                                  */
 /*  Sample rates                                                                    */
 /*                                                                                  */
 /************************************************************************************/
 
-extern LVM_INT32                LVCS_SampleRateTable[];
-
+extern const LVM_INT32          LVCS_SampleRateTable[];
 
 /*Speaker coeffient tables*/
 extern LVM_UINT16               LVCS_MS_Small_SEMiddleGainTable[];
@@ -142,11 +136,5 @@
 extern LVCS_VolCorrect_t        LVCS_MS_Large_VolCorrectTable[];
 extern LVM_UINT16               LVCS_MS_Large_ReverbGainTable[];
 
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* __LVCS_TABLES_H__ */
 
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index 003ce9e..674c246 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -35,8 +35,6 @@
     srcs: ["lvmtest.cpp"],
 
     cflags: [
-        "-DBUILD_FLOAT",
-        "-DHIGHER_FS",
         "-DSUPPORT_MC",
 
         "-Wall",
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 5b58dd1..a4ace6c 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -482,10 +482,6 @@
   pContext->pBundledContext->SamplesToExitCountVirt = 0;
   pContext->pBundledContext->SamplesToExitCountBb = 0;
   pContext->pBundledContext->SamplesToExitCountEq = 0;
-#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
-  pContext->pBundledContext->pInputBuffer = NULL;
-  pContext->pBundledContext->pOutputBuffer = NULL;
-#endif
   for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
     pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
   }
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index 16fa126..afc4220 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -1,6 +1,3 @@
-// The wrapper -DBUILD_FLOAT needs to match
-// the lvm library -DBUILD_FLOAT.
-
 // music bundle wrapper
 cc_library_shared {
     name: "libbundlewrapper",
@@ -14,10 +11,8 @@
     vendor: true,
     srcs: ["Bundle/EffectBundle.cpp"],
 
-    cflags: [
+    cppflags: [
         "-fvisibility=hidden",
-        "-DBUILD_FLOAT",
-        "-DHIGHER_FS",
         "-DSUPPORT_MC",
 
         "-Wall",
@@ -56,10 +51,8 @@
     vendor: true,
     srcs: ["Reverb/EffectReverb.cpp"],
 
-    cflags: [
+    cppflags: [
         "-fvisibility=hidden",
-        "-DBUILD_FLOAT",
-        "-DHIGHER_FS",
 
         "-Wall",
         "-Werror",
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 10dda19..6fca0e7 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -81,7 +81,6 @@
     }                                         \
 }
 
-
 // NXP SW BassBoost UUID
 const effect_descriptor_t gBassBoostDescriptor = {
         {0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
@@ -258,26 +257,6 @@
         pContext->pBundledContext->firstVolume              = LVM_TRUE;
         pContext->pBundledContext->volume                   = 0;
 
-        #ifdef LVM_PCM
-        char fileName[256];
-        snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_in.pcm", pContext->pBundledContext);
-        pContext->pBundledContext->PcmInPtr = fopen(fileName, "w");
-        if (pContext->pBundledContext->PcmInPtr == NULL) {
-            ALOGV("cannot open %s", fileName);
-            ret = -EINVAL;
-            goto exit;
-        }
-
-        snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_out.pcm", pContext->pBundledContext);
-        pContext->pBundledContext->PcmOutPtr = fopen(fileName, "w");
-        if (pContext->pBundledContext->PcmOutPtr == NULL) {
-            ALOGV("cannot open %s", fileName);
-            fclose(pContext->pBundledContext->PcmInPtr);
-           pContext->pBundledContext->PcmInPtr = NULL;
-           ret = -EINVAL;
-           goto exit;
-        }
-        #endif
 
         /* Saved strength is used to return the exact strength that was used in the set to the get
          * because we map the original strength range of 0:1000 to 1:15, and this will avoid
@@ -295,10 +274,6 @@
         pContext->pBundledContext->SamplesToExitCountVirt   = 0;
         pContext->pBundledContext->SamplesToExitCountBb     = 0;
         pContext->pBundledContext->SamplesToExitCountEq     = 0;
-#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
-        pContext->pBundledContext->pInputBuffer             = NULL;
-        pContext->pBundledContext->pOutputBuffer            = NULL;
-#endif
         for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
             pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
         }
@@ -443,17 +418,6 @@
             (pSessionContext->bEqualizerInstantiated ==LVM_FALSE) &&
             (pSessionContext->bVirtualizerInstantiated==LVM_FALSE))
     {
-#ifdef LVM_PCM
-        if (pContext->pBundledContext->PcmInPtr != NULL) {
-            fclose(pContext->pBundledContext->PcmInPtr);
-            pContext->pBundledContext->PcmInPtr = NULL;
-        }
-        if (pContext->pBundledContext->PcmOutPtr != NULL) {
-            fclose(pContext->pBundledContext->PcmOutPtr);
-            pContext->pBundledContext->PcmOutPtr = NULL;
-        }
-#endif
-
 
         // Clear the SessionIndex
         for(int i=0; i<LVM_MAX_SESSIONS; i++){
@@ -474,10 +438,6 @@
         if (pContext->pBundledContext->workBuffer != NULL) {
             free(pContext->pBundledContext->workBuffer);
         }
-#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
-        free(pContext->pBundledContext->pInputBuffer);
-        free(pContext->pBundledContext->pOutputBuffer);
-#endif
         delete pContext->pBundledContext;
         pContext->pBundledContext = LVM_NULL;
     }
@@ -759,7 +719,6 @@
 //  pOut:       pointer to updated stereo 16 bit output data
 //
 //----------------------------------------------------------------------------
-#ifdef BUILD_FLOAT
 int LvmBundle_process(effect_buffer_t  *pIn,
                       effect_buffer_t  *pOut,
                       int              frameCount,
@@ -769,30 +728,6 @@
     effect_buffer_t         *pOutTmp;
     const LVM_INT32 NrChannels =
         audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
-#ifndef NATIVE_FLOAT_BUFFER
-    if (pContext->pBundledContext->pInputBuffer == nullptr ||
-            pContext->pBundledContext->frameCount < frameCount) {
-        free(pContext->pBundledContext->pInputBuffer);
-        pContext->pBundledContext->pInputBuffer =
-                (LVM_FLOAT *)calloc(frameCount, sizeof(LVM_FLOAT) * NrChannels);
-    }
-
-    if (pContext->pBundledContext->pOutputBuffer == nullptr ||
-            pContext->pBundledContext->frameCount < frameCount) {
-        free(pContext->pBundledContext->pOutputBuffer);
-        pContext->pBundledContext->pOutputBuffer =
-                (LVM_FLOAT *)calloc(frameCount, sizeof(LVM_FLOAT) * NrChannels);
-    }
-
-    if (pContext->pBundledContext->pInputBuffer == nullptr ||
-            pContext->pBundledContext->pOutputBuffer == nullptr) {
-        ALOGE("LVM_ERROR : LvmBundle_process memory allocation for float buffer's failed");
-        return -EINVAL;
-    }
-
-    LVM_FLOAT * const pInputBuff = pContext->pBundledContext->pInputBuffer;
-    LVM_FLOAT * const pOutputBuff = pContext->pBundledContext->pOutputBuffer;
-#endif
 
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
         pOutTmp = pOut;
@@ -814,123 +749,25 @@
         return -EINVAL;
     }
 
-#ifdef LVM_PCM
-    fwrite(pIn,
-           frameCount * sizeof(effect_buffer_t) * NrChannels,
-           1,
-           pContext->pBundledContext->PcmInPtr);
-    fflush(pContext->pBundledContext->PcmInPtr);
-#endif
 
-#ifndef NATIVE_FLOAT_BUFFER
-    /* Converting input data from fixed point to float point */
-    memcpy_to_float_from_i16(pInputBuff, pIn, frameCount * NrChannels);
-
-    /* Process the samples */
-    LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
-                            pInputBuff,                           /* Input buffer */
-                            pOutputBuff,                          /* Output buffer */
-                            (LVM_UINT16)frameCount,               /* Number of samples to read */
-                            0);                                   /* Audio Time */
-
-    /* Converting output data from float point to fixed point */
-    memcpy_to_i16_from_float(pOutTmp, pOutputBuff, frameCount * NrChannels);
-
-#else
     /* Process the samples */
     LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
                             pIn,                                  /* Input buffer */
                             pOutTmp,                              /* Output buffer */
                             (LVM_UINT16)frameCount,               /* Number of samples to read */
                             0);                                   /* Audio Time */
-#endif
     LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
     if(LvmStatus != LVM_SUCCESS) return -EINVAL;
 
-#ifdef LVM_PCM
-    fwrite(pOutTmp,
-           frameCount * sizeof(effect_buffer_t) * NrChannels,
-           1,
-           pContext->pBundledContext->PcmOutPtr);
-    fflush(pContext->pBundledContext->PcmOutPtr);
-#endif
 
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
         for (int i = 0; i < frameCount * NrChannels; i++) {
-#ifndef NATIVE_FLOAT_BUFFER
-            pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
-#else
             pOut[i] = pOut[i] + pOutTmp[i];
-#endif
         }
     }
     return 0;
 }    /* end LvmBundle_process */
 
-#else // BUILD_FLOAT
-
-int LvmBundle_process(LVM_INT16        *pIn,
-                      LVM_INT16        *pOut,
-                      int              frameCount,
-                      EffectContext    *pContext) {
-
-    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
-    LVM_INT16               *pOutTmp;
-
-    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
-        pOutTmp = pOut;
-    } else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
-        if (pContext->pBundledContext->frameCount != frameCount) {
-            if (pContext->pBundledContext->workBuffer != NULL) {
-                free(pContext->pBundledContext->workBuffer);
-            }
-            pContext->pBundledContext->workBuffer =
-                    (effect_buffer_t *)calloc(frameCount, sizeof(effect_buffer_t) * FCC_2);
-            if (pContext->pBundledContext->workBuffer == NULL) {
-                return -ENOMEM;
-            }
-            pContext->pBundledContext->frameCount = frameCount;
-        }
-        pOutTmp = pContext->pBundledContext->workBuffer;
-    } else {
-        ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
-        return -EINVAL;
-    }
-
-#ifdef LVM_PCM
-    fwrite(pIn, frameCount * sizeof(*pIn) * FCC_2,
-            1 /* nmemb */, pContext->pBundledContext->PcmInPtr);
-    fflush(pContext->pBundledContext->PcmInPtr);
-#endif
-
-    //ALOGV("Calling LVM_Process");
-
-    /* Process the samples */
-    LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
-                            pIn,                                  /* Input buffer */
-                            pOutTmp,                              /* Output buffer */
-                            (LVM_UINT16)frameCount,               /* Number of samples to read */
-                            0);                                   /* Audio Time */
-
-    LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
-    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-
-#ifdef LVM_PCM
-    fwrite(pOutTmp, frameCount * sizeof(*pOutTmp) * FCC_2,
-            1 /* nmemb */, pContext->pBundledContext->PcmOutPtr);
-    fflush(pContext->pBundledContext->PcmOutPtr);
-#endif
-
-    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
-        for (int i=0; i<frameCount*2; i++){
-            pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
-        }
-    }
-    return 0;
-}    /* end LvmBundle_process */
-
-#endif // BUILD_FLOAT
-
 //----------------------------------------------------------------------------
 // EqualizerUpdateActiveParams()
 //----------------------------------------------------------------------------
@@ -953,7 +790,6 @@
     //ALOGV("\tEqualizerUpdateActiveParams just Got -> %d\n",
     //          ActiveParams.pEQNB_BandDefinition[band].Gain);
 
-
     for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
            ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
            ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
@@ -1290,7 +1126,6 @@
         SampleRate = LVM_FS_48000;
         pContext->pBundledContext->SamplesPerSecond = 48000 * NrChannels;
         break;
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
     case 88200:
         SampleRate = LVM_FS_88200;
         pContext->pBundledContext->SamplesPerSecond = 88200 * NrChannels;
@@ -1307,7 +1142,6 @@
         SampleRate = LVM_FS_192000;
         pContext->pBundledContext->SamplesPerSecond = 192000 * NrChannels;
         break;
-#endif
     default:
         ALOGV("\tEffect_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
         return -EINVAL;
@@ -2051,8 +1885,6 @@
     LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
     LVM_INT16               Balance = 0;
 
-
-
     pContext->pBundledContext->positionSaved = position;
     Balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
 
@@ -2097,7 +1929,6 @@
     return 0;
 }    /* end VolumeSetStereoPosition */
 
-
 //----------------------------------------------------------------------------
 // VolumeGetStereoPosition()
 //----------------------------------------------------------------------------
@@ -2710,7 +2541,7 @@
         name[*pValueSize - 1] = 0;
         *pValueSize = strlen(name) + 1;
         ALOGVV("%s EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
-                __func__, preset, gEqualizerPresets[preset].name, *pValueSize);
+               __func__, preset, name, *pValueSize);
 
     } break;
 
@@ -2970,7 +2801,6 @@
     return status;
 } /* end Volume_getParameter */
 
-
 //----------------------------------------------------------------------------
 // Volume_setParameter()
 //----------------------------------------------------------------------------
@@ -3422,17 +3252,10 @@
         pContext->pBundledContext->NumberEffectsCalled = 0;
         /* Process all the available frames, block processing is
            handled internalLY by the LVM bundle */
-#ifdef NATIVE_FLOAT_BUFFER
         processStatus = android::LvmBundle_process(inBuffer->f32,
                                                    outBuffer->f32,
                                                    outBuffer->frameCount,
                                                    pContext);
-#else
-        processStatus = android::LvmBundle_process(inBuffer->s16,
-                                                   outBuffer->s16,
-                                                   outBuffer->frameCount,
-                                                   pContext);
-#endif
         if (processStatus != 0){
             ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", processStatus);
             if (status == 0) {
@@ -3447,11 +3270,7 @@
 
         if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
             for (size_t i = 0; i < outBuffer->frameCount * NrChannels; ++i) {
-#ifdef NATIVE_FLOAT_BUFFER
                 outBuffer->f32[i] += inBuffer->f32[i];
-#else
-                outBuffer->s16[i] = clamp16((LVM_INT32)outBuffer->s16[i] + inBuffer->s16[i]);
-#endif
             }
         } else if (outBuffer->raw != inBuffer->raw) {
             memcpy(outBuffer->raw,
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index e4aacd0..524e103 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -23,10 +23,6 @@
 #include <LVM.h>
 #include <limits.h>
 
-#if __cplusplus
-extern "C" {
-#endif
-
 #define FIVEBAND_NUMBANDS          5
 #define MAX_NUM_BANDS              5
 #define MAX_CALL_SIZE              256
@@ -37,7 +33,6 @@
 #define EQUALIZER_CUP_LOAD_ARM9E   220    // Expressed in 0.1 MIPS
 #define VOLUME_CUP_LOAD_ARM9E      0      // Expressed in 0.1 MIPS
 #define BUNDLE_MEM_USAGE           25     // Expressed in kB
-//#define LVM_PCM
 
 #ifndef OPENSL_ES_H_
 static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
@@ -99,14 +94,6 @@
     int                             frameCount;
     int32_t                         bandGaindB[FIVEBAND_NUMBANDS];
     int                             volume;
-    #ifdef LVM_PCM
-    FILE                            *PcmInPtr;
-    FILE                            *PcmOutPtr;
-    #endif
-#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
-    LVM_FLOAT                       *pInputBuffer;
-    LVM_FLOAT                       *pOutputBuffer;
-#endif
 #ifdef SUPPORT_MC
     LVM_INT32                       ChMask;
 #endif
@@ -137,7 +124,6 @@
     BundledEffectContext            *pBundledContext;
 };
 
-
 /* enumerated parameter settings for Volume effect */
 typedef enum
 {
@@ -228,9 +214,4 @@
 
 static const float LimitLevel_virtualizerContribution = 1.9;
 
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
 #endif /*ANDROID_EFFECTBUNDLE_H_*/
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 602f607..39f5bb6 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -79,7 +79,6 @@
         {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
 };
 
-
 // NXP SW auxiliary environmental reverb
 const effect_descriptor_t gAuxEnvReverbDescriptor = {
         { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e } },
@@ -136,11 +135,7 @@
         &gInsertPresetReverbDescriptor
 };
 
-#ifdef BUILD_FLOAT
 typedef     float               process_buffer_t; // process in float
-#else
-typedef     int32_t             process_buffer_t; // process in Q4_27
-#endif // BUILD_FLOAT
 
 struct ReverbContext{
     const struct effect_interface_s *itfe;
@@ -154,10 +149,6 @@
     int16_t                         SavedDiffusion;
     int16_t                         SavedDensity;
     bool                            bEnabled;
-    #ifdef LVM_PCM
-    FILE                            *PcmInPtr;
-    FILE                            *PcmOutPtr;
-    #endif
     LVM_Fs_en                       SampleRate;
     process_buffer_t                *InFrames;
     process_buffer_t                *OutFrames;
@@ -183,11 +174,7 @@
 
 #define REVERB_DEFAULT_PRESET REVERB_PRESET_NONE
 
-#ifdef BUILD_FLOAT
 #define REVERB_SEND_LEVEL   0.75f // 0.75 in 4.12 format
-#else
-#define REVERB_SEND_LEVEL   (0x0C00) // 0.75 in 4.12 format
-#endif
 #define REVERB_UNIT_VOLUME  (0x1000) // 1.0 in 4.12 format
 
 //--- local function prototypes
@@ -269,18 +256,6 @@
 
     *pHandle = (effect_handle_t)pContext;
 
-#ifdef LVM_PCM
-    pContext->PcmInPtr = NULL;
-    pContext->PcmOutPtr = NULL;
-
-    pContext->PcmInPtr  = fopen("/data/tmp/reverb_pcm_in.pcm", "w");
-    pContext->PcmOutPtr = fopen("/data/tmp/reverb_pcm_out.pcm", "w");
-
-    if((pContext->PcmInPtr  == NULL)||
-       (pContext->PcmOutPtr == NULL)){
-       return -EINVAL;
-    }
-#endif
 
     int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
 
@@ -304,10 +279,6 @@
         return -EINVAL;
     }
 
-    #ifdef LVM_PCM
-    fclose(pContext->PcmInPtr);
-    fclose(pContext->PcmOutPtr);
-    #endif
     free(pContext->InFrames);
     free(pContext->OutFrames);
     pContext->bufferSizeIn = 0;
@@ -378,7 +349,6 @@
         return -EINVAL;
     }
 
-#ifdef BUILD_FLOAT
     size_t inSize = frameCount * sizeof(process_buffer_t) * channels;
     size_t outSize = frameCount * sizeof(process_buffer_t) * FCC_2;
     if (pContext->InFrames == NULL ||
@@ -394,10 +364,6 @@
         pContext->OutFrames = (process_buffer_t *)calloc(1, pContext->bufferSizeOut);
     }
 
-#ifndef NATIVE_FLOAT_BUFFER
-    effect_buffer_t * const OutFrames16 = (effect_buffer_t *)pContext->OutFrames;
-#endif
-#endif
 
     // Check for NULL pointers
     if ((pContext->InFrames == NULL) || (pContext->OutFrames == NULL)) {
@@ -405,47 +371,20 @@
         return -EINVAL;
     }
 
-#ifdef LVM_PCM
-    fwrite(pIn, frameCount * sizeof(*pIn) * channels, 1 /* nmemb */, pContext->PcmInPtr);
-    fflush(pContext->PcmInPtr);
-#endif
 
     if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
         Reverb_LoadPreset(pContext);
     }
 
     if (pContext->auxiliary) {
-#ifdef BUILD_FLOAT
-#ifdef NATIVE_FLOAT_BUFFER
         static_assert(std::is_same<decltype(*pIn), decltype(*pContext->InFrames)>::value,
                 "pIn and InFrames must be same type");
         memcpy(pContext->InFrames, pIn, frameCount * channels * sizeof(*pIn));
-#else
-        memcpy_to_float_from_i16(
-                pContext->InFrames, pIn, frameCount * channels);
-#endif
-#else //no BUILD_FLOAT
-        for (int i = 0; i < frameCount * channels; i++) {
-            pContext->InFrames[i] = (process_buffer_t)pIn[i]<<8;
-        }
-#endif
         } else {
         // insert reverb input is always stereo
         for (int i = 0; i < frameCount; i++) {
-#ifdef BUILD_FLOAT
-#ifdef NATIVE_FLOAT_BUFFER
             pContext->InFrames[2 * i] = (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL;
             pContext->InFrames[2 * i + 1] = (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL;
-#else
-            pContext->InFrames[2 * i] =
-                    (process_buffer_t)pIn[2 * i] * REVERB_SEND_LEVEL / 32768.0f;
-            pContext->InFrames[2 * i + 1] =
-                    (process_buffer_t)pIn[2 * i + 1] * REVERB_SEND_LEVEL / 32768.0f;
-#endif
-#else
-            pContext->InFrames[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
-            pContext->InFrames[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
-#endif
         }
     }
 
@@ -471,43 +410,16 @@
 
     // Convert to 16 bits
     if (pContext->auxiliary) {
-#ifdef BUILD_FLOAT
         // nothing to do here
-#ifndef NATIVE_FLOAT_BUFFER
-        // pContext->OutFrames and OutFrames16 point to the same buffer
-        // make sure the float to int conversion happens in the right order.
-        memcpy_to_i16_from_float(OutFrames16, pContext->OutFrames,
-                (size_t)frameCount * FCC_2);
-#endif
-#else
-        memcpy_to_i16_from_q4_27(OutFrames16, pContext->OutFrames, (size_t)frameCount * FCC_2);
-#endif
     } else {
-#ifdef BUILD_FLOAT
-#ifdef NATIVE_FLOAT_BUFFER
         for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
             // Mix with dry input
             pContext->OutFrames[i] += pIn[i];
         }
-#else
-        for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
-            // pOutputBuff and OutFrames16 point to the same buffer
-            // make sure the float to int conversion happens in the right order.
-            pContext->OutFrames[i] += (process_buffer_t)pIn[i] / 32768.0f;
-        }
-        memcpy_to_i16_from_float(OutFrames16, pContext->OutFrames,
-                (size_t)frameCount * FCC_2);
-#endif
-#else
-        for (int i=0; i < frameCount * FCC_2; i++) { // always stereo here
-            OutFrames16[i] = clamp16((pContext->OutFrames[i]>>8) + (process_buffer_t)pIn[i]);
-        }
-#endif
         // apply volume with ramp if needed
         if ((pContext->leftVolume != pContext->prevLeftVolume ||
                 pContext->rightVolume != pContext->prevRightVolume) &&
                 pContext->volumeMode == REVERB_VOLUME_RAMP) {
-#if defined (BUILD_FLOAT) && defined (NATIVE_FLOAT_BUFFER)
             // FIXME: still using int16 volumes.
             // For reference: REVERB_UNIT_VOLUME  (0x1000) // 1.0 in 4.12 format
             float vl = (float)pContext->prevLeftVolume / 4096;
@@ -522,37 +434,14 @@
                 vl += incl;
                 vr += incr;
             }
-#else
-            LVM_INT32 vl = (LVM_INT32)pContext->prevLeftVolume << 16;
-            LVM_INT32 incl = (((LVM_INT32)pContext->leftVolume << 16) - vl) / frameCount;
-            LVM_INT32 vr = (LVM_INT32)pContext->prevRightVolume << 16;
-            LVM_INT32 incr = (((LVM_INT32)pContext->rightVolume << 16) - vr) / frameCount;
-
-            for (int i = 0; i < frameCount; i++) {
-                OutFrames16[FCC_2 * i] =
-                        clamp16((LVM_INT32)((vl >> 16) * OutFrames16[2*i]) >> 12);
-                OutFrames16[FCC_2 * i + 1] =
-                        clamp16((LVM_INT32)((vr >> 16) * OutFrames16[2*i+1]) >> 12);
-
-                vl += incl;
-                vr += incr;
-            }
-#endif
             pContext->prevLeftVolume = pContext->leftVolume;
             pContext->prevRightVolume = pContext->rightVolume;
         } else if (pContext->volumeMode != REVERB_VOLUME_OFF) {
             if (pContext->leftVolume != REVERB_UNIT_VOLUME ||
                 pContext->rightVolume != REVERB_UNIT_VOLUME) {
                 for (int i = 0; i < frameCount; i++) {
-#if defined(BUILD_FLOAT) && defined(NATIVE_FLOAT_BUFFER)
                     pContext->OutFrames[FCC_2 * i] *= ((float)pContext->leftVolume / 4096);
                     pContext->OutFrames[FCC_2 * i + 1] *= ((float)pContext->rightVolume / 4096);
-#else
-                    OutFrames16[FCC_2 * i] =
-                            clamp16((LVM_INT32)(pContext->leftVolume * OutFrames16[2*i]) >> 12);
-                    OutFrames16[FCC_2 * i + 1] =
-                            clamp16((LVM_INT32)(pContext->rightVolume * OutFrames16[2*i+1]) >> 12);
-#endif
                 }
             }
             pContext->prevLeftVolume = pContext->leftVolume;
@@ -561,21 +450,12 @@
         }
     }
 
-#ifdef LVM_PCM
-    fwrite(pContext->OutFrames, frameCount * sizeof(*pContext->OutFrames) * FCC_2,
-            1 /* nmemb */, pContext->PcmOutPtr);
-    fflush(pContext->PcmOutPtr);
-#endif
 
     // Accumulate if required
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
         //ALOGV("\tBuffer access is ACCUMULATE");
         for (int i = 0; i < frameCount * FCC_2; i++) { // always stereo here
-#ifndef NATIVE_FLOAT_BUFFER
-            pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
-#else
             pOut[i] += pContext->OutFrames[i];
-#endif
         }
     }else{
         //ALOGV("\tBuffer access is WRITE");
@@ -654,7 +534,6 @@
     //ALOGV("\tReverb_setConfig calling memcpy");
     pContext->config = *pConfig;
 
-
     switch (pConfig->inputCfg.samplingRate) {
     case 8000:
         SampleRate = LVM_FS_8000;
@@ -674,7 +553,6 @@
     case 48000:
         SampleRate = LVM_FS_48000;
         break;
-#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
     case 88200:
         SampleRate = LVM_FS_88200;
         break;
@@ -687,7 +565,6 @@
     case 192000:
         SampleRate = LVM_FS_192000;
         break;
-#endif
     default:
         ALOGV("\rReverb_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
         return -EINVAL;
@@ -1509,7 +1386,6 @@
     //ALOGV("\tReverbGetDensity Succesfully returned from LVM_GetControlParameters\n");
     //ALOGV("\tReverbGetDensity() just Got -> %d\n", ActiveParams.RoomSize);
 
-
     Temp = (LVM_INT16)(((pContext->SavedDensity * 99) / 1000) + 1);
 
     if(Temp != ActiveParams.RoomSize){
@@ -1557,7 +1433,6 @@
     return 0;
 }
 
-
 //----------------------------------------------------------------------------
 // Reverb_getParameter()
 //----------------------------------------------------------------------------
@@ -1903,7 +1778,6 @@
     return status;
 } /* end Reverb_setParameter */
 
-
 /**
  * returns the size in bytes of the value of each environmental reverb parameter
  */
@@ -1951,17 +1825,10 @@
     }
     //ALOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
     /* Process all the available frames, block processing is handled internalLY by the LVM bundle */
-#if defined (BUILD_FLOAT) && defined (NATIVE_FLOAT_BUFFER)
     status = process(    inBuffer->f32,
                          outBuffer->f32,
                          outBuffer->frameCount,
                          pContext);
-#else
-    status = process(    inBuffer->s16,
-                         outBuffer->s16,
-                         outBuffer->frameCount,
-                         pContext);
-#endif
 
     if (pContext->bEnabled == LVM_FALSE) {
         if (pContext->SamplesToExitCount > 0) {
@@ -1986,7 +1853,6 @@
     LVREV_ControlParams_st    ActiveParams;              /* Current control Parameters */
     LVREV_ReturnStatus_en     LvmStatus=LVREV_SUCCESS;     /* Function call status */
 
-
     if (pContext == NULL){
         ALOGV("\tLVM_ERROR : Reverb_command ERROR pContext == NULL");
         return -EINVAL;
@@ -2040,11 +1906,15 @@
             //ALOGV("\tReverb_command cmdCode Case: "
             //        "EFFECT_CMD_GET_PARAM start");
             effect_param_t *p = (effect_param_t *)pCmdData;
+            if (pCmdData == nullptr) {
+                ALOGW("\tLVM_ERROR : pCmdData is NULL");
+                return -EINVAL;
+            }
             if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) {
                 android_errorWriteLog(0x534e4554, "26347509");
                 return -EINVAL;
             }
-            if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
+            if (cmdSize < sizeof(effect_param_t) ||
                     cmdSize < (sizeof(effect_param_t) + p->psize) ||
                     pReplyData == NULL || replySize == NULL ||
                     *replySize < (sizeof(effect_param_t) + p->psize)) {
@@ -2161,7 +2031,6 @@
                 return -EINVAL;
             }
 
-
             if (pReplyData != NULL) { // we have volume control
                 pContext->leftVolume = (LVM_INT16)((*(uint32_t *)pCmdData + (1 << 11)) >> 12);
                 pContext->rightVolume = (LVM_INT16)((*((uint32_t *)pCmdData + 1) + (1 << 11)) >> 12);
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
index 8165f5a..96223a8 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
@@ -20,10 +20,6 @@
 #include <audio_effects/effect_environmentalreverb.h>
 #include <audio_effects/effect_presetreverb.h>
 
-#if __cplusplus
-extern "C" {
-#endif
-
 #define MAX_NUM_BANDS           5
 #define MAX_CALL_SIZE           256
 #define LVREV_MAX_T60           7000
@@ -31,16 +27,11 @@
 #define LVREV_MAX_FRAME_SIZE    2560
 #define LVREV_CUP_LOAD_ARM9E    470    // Expressed in 0.1 MIPS
 #define LVREV_MEM_USAGE         (71+(LVREV_MAX_FRAME_SIZE>>7))     // Expressed in kB
-//#define LVM_PCM
 
 typedef struct _LPFPair_t
 {
     int16_t Room_HF;
     int16_t LPF;
 } LPFPair_t;
-#if __cplusplus
-}  // extern "C"
-#endif
-
 
 #endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index a977300..273d91c 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -21,16 +21,17 @@
 
 #include <stdio.h>
 
+#include <android/IDataSource.h>
 #include <binder/IMemory.h>
 #include <binder/MemoryDealer.h>
 #include <drm/drm_framework_common.h>
-#include <media/IDataSource.h>
 #include <media/mediametadataretriever.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <private/media/VideoFrame.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
+#include <vector>
 
 HeifDecoder* createHeifDecoder() {
     return new android::HeifDecoderImpl();
@@ -38,6 +39,22 @@
 
 namespace android {
 
+void initFrameInfo(HeifFrameInfo *info, const VideoFrame *videoFrame) {
+    info->mWidth = videoFrame->mWidth;
+    info->mHeight = videoFrame->mHeight;
+    info->mRotationAngle = videoFrame->mRotationAngle;
+    info->mBytesPerPixel = videoFrame->mBytesPerPixel;
+    info->mDurationUs = videoFrame->mDurationUs;
+    if (videoFrame->mIccSize > 0) {
+        info->mIccData.assign(
+                videoFrame->getFlattenedIccData(),
+                videoFrame->getFlattenedIccData() + videoFrame->mIccSize);
+    } else {
+        // clear old Icc data if there is no Icc data.
+        info->mIccData.clear();
+    }
+}
+
 /*
  * HeifDataSource
  *
@@ -66,9 +83,6 @@
     void close() {}
     uint32_t getFlags() override { return 0; }
     String8 toString() override { return String8("HeifDataSource"); }
-    sp<DecryptHandle> DrmInitialization(const char*) override {
-        return nullptr;
-    }
 
 private:
     enum {
@@ -156,7 +170,7 @@
 
     // copy from cache if the request falls entirely in cache
     if (offset + size <= mCachedOffset + mCachedSize) {
-        memcpy(mMemory->pointer(), mCache.get() + offset - mCachedOffset, size);
+        memcpy(mMemory->unsecurePointer(), mCache.get() + offset - mCachedOffset, size);
         return size;
     }
 
@@ -254,7 +268,7 @@
     if (bytesAvailable < (int64_t)size) {
         size = bytesAvailable;
     }
-    memcpy(mMemory->pointer(), mCache.get() + offset - mCachedOffset, size);
+    memcpy(mMemory->unsecurePointer(), mCache.get() + offset - mCachedOffset, size);
     return size;
 }
 
@@ -293,11 +307,11 @@
     // it's not, default to HAL_PIXEL_FORMAT_RGB_565.
     mOutputColor(HAL_PIXEL_FORMAT_RGB_565),
     mCurScanline(0),
-    mWidth(0),
-    mHeight(0),
+    mTotalScanline(0),
     mFrameDecoded(false),
     mHasImage(false),
     mHasVideo(false),
+    mSequenceLength(0),
     mAvailableLines(0),
     mNumSlices(1),
     mSliceHeight(0),
@@ -320,6 +334,13 @@
     }
     mDataSource = dataSource;
 
+    return reinit(frameInfo);
+}
+
+bool HeifDecoderImpl::reinit(HeifFrameInfo* frameInfo) {
+    mFrameDecoded = false;
+    mFrameMemory.clear();
+
     mRetriever = new MediaMetadataRetriever();
     status_t err = mRetriever->setDataSource(mDataSource, "image/heif");
     if (err != OK) {
@@ -336,48 +357,103 @@
 
     mHasImage = hasImage && !strcasecmp(hasImage, "yes");
     mHasVideo = hasVideo && !strcasecmp(hasVideo, "yes");
-    sp<IMemory> sharedMem;
+
+    HeifFrameInfo* defaultInfo = nullptr;
     if (mHasImage) {
         // image index < 0 to retrieve primary image
-        sharedMem = mRetriever->getImageAtIndex(
+        sp<IMemory> sharedMem = mRetriever->getImageAtIndex(
                 -1, mOutputColor, true /*metaOnly*/);
-    } else if (mHasVideo) {
-        sharedMem = mRetriever->getFrameAtTime(0,
-                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
-                mOutputColor, true /*metaOnly*/);
+
+        if (sharedMem == nullptr || sharedMem->unsecurePointer() == nullptr) {
+            ALOGE("init: videoFrame is a nullptr");
+            return false;
+        }
+
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        VideoFrame* videoFrame = static_cast<VideoFrame*>(sharedMem->unsecurePointer());
+
+        ALOGV("Image dimension %dx%d, display %dx%d, angle %d, iccSize %d",
+                videoFrame->mWidth,
+                videoFrame->mHeight,
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
+                videoFrame->mRotationAngle,
+                videoFrame->mIccSize);
+
+        initFrameInfo(&mImageInfo, videoFrame);
+
+        if (videoFrame->mTileHeight >= 512) {
+            // Try decoding in slices only if the image has tiles and is big enough.
+            mSliceHeight = videoFrame->mTileHeight;
+            ALOGV("mSliceHeight %u", mSliceHeight);
+        }
+
+        defaultInfo = &mImageInfo;
     }
 
-    if (sharedMem == nullptr || sharedMem->pointer() == nullptr) {
-        ALOGE("getFrameAtTime: videoFrame is a nullptr");
+    if (mHasVideo) {
+        sp<IMemory> sharedMem = mRetriever->getFrameAtTime(0,
+                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
+                mOutputColor, true /*metaOnly*/);
+
+        if (sharedMem == nullptr || sharedMem->unsecurePointer() == nullptr) {
+            ALOGE("init: videoFrame is a nullptr");
+            return false;
+        }
+
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        VideoFrame* videoFrame = static_cast<VideoFrame*>(
+            sharedMem->unsecurePointer());
+
+        ALOGV("Sequence dimension %dx%d, display %dx%d, angle %d, iccSize %d",
+                videoFrame->mWidth,
+                videoFrame->mHeight,
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
+                videoFrame->mRotationAngle,
+                videoFrame->mIccSize);
+
+        initFrameInfo(&mSequenceInfo, videoFrame);
+
+        mSequenceLength = atoi(mRetriever->extractMetadata(METADATA_KEY_VIDEO_FRAME_COUNT));
+
+        if (defaultInfo == nullptr) {
+            defaultInfo = &mSequenceInfo;
+        }
+    }
+
+    if (defaultInfo == nullptr) {
+        ALOGD("No valid image or sequence available");
         return false;
     }
 
-    VideoFrame* videoFrame = static_cast<VideoFrame*>(sharedMem->pointer());
-
-    ALOGV("Meta dimension %dx%d, display %dx%d, angle %d, iccSize %d",
-            videoFrame->mWidth,
-            videoFrame->mHeight,
-            videoFrame->mDisplayWidth,
-            videoFrame->mDisplayHeight,
-            videoFrame->mRotationAngle,
-            videoFrame->mIccSize);
-
     if (frameInfo != nullptr) {
-        frameInfo->set(
-                videoFrame->mWidth,
-                videoFrame->mHeight,
-                videoFrame->mRotationAngle,
-                videoFrame->mBytesPerPixel,
-                videoFrame->mIccSize,
-                videoFrame->getFlattenedIccData());
+        *frameInfo = *defaultInfo;
     }
-    mWidth = videoFrame->mWidth;
-    mHeight = videoFrame->mHeight;
-    if (mHasImage && videoFrame->mTileHeight >= 512 && mWidth >= 3000 && mHeight >= 2000 ) {
-        // Try decoding in slices only if the image has tiles and is big enough.
-        mSliceHeight = videoFrame->mTileHeight;
-        mNumSlices = (videoFrame->mHeight + mSliceHeight - 1) / mSliceHeight;
-        ALOGV("mSliceHeight %u, mNumSlices %zu", mSliceHeight, mNumSlices);
+
+    // default total scanline, this might change if decodeSequence() is used
+    mTotalScanline = defaultInfo->mHeight;
+
+    return true;
+}
+
+bool HeifDecoderImpl::getSequenceInfo(
+        HeifFrameInfo* frameInfo, size_t *frameCount) {
+    ALOGV("%s", __FUNCTION__);
+    if (!mHasVideo) {
+        return false;
+    }
+    if (frameInfo != nullptr) {
+        *frameInfo = mSequenceInfo;
+    }
+    if (frameCount != nullptr) {
+        *frameCount = mSequenceLength;
     }
     return true;
 }
@@ -388,27 +464,35 @@
 }
 
 bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
+    if (heifColor == mOutputColor) {
+        return true;
+    }
+
     switch(heifColor) {
         case kHeifColorFormat_RGB565:
         {
             mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
-            return true;
+            break;
         }
         case kHeifColorFormat_RGBA_8888:
         {
             mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
-            return true;
+            break;
         }
         case kHeifColorFormat_BGRA_8888:
         {
             mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
-            return true;
+            break;
         }
         default:
-            break;
+            ALOGE("Unsupported output color format %d", heifColor);
+            return false;
     }
-    ALOGE("Unsupported output color format %d", heifColor);
-    return false;
+
+    if (mFrameDecoded) {
+        return reinit(nullptr);
+    }
+    return true;
 }
 
 bool HeifDecoderImpl::decodeAsync() {
@@ -416,15 +500,15 @@
         ALOGV("decodeAsync(): decoding slice %zu", i);
         size_t top = i * mSliceHeight;
         size_t bottom = (i + 1) * mSliceHeight;
-        if (bottom > mHeight) {
-            bottom = mHeight;
+        if (bottom > mImageInfo.mHeight) {
+            bottom = mImageInfo.mHeight;
         }
         sp<IMemory> frameMemory = mRetriever->getImageRectAtIndex(
-                -1, mOutputColor, 0, top, mWidth, bottom);
+                -1, mOutputColor, 0, top, mImageInfo.mWidth, bottom);
         {
             Mutex::Autolock autolock(mLock);
 
-            if (frameMemory == nullptr || frameMemory->pointer() == nullptr) {
+            if (frameMemory == nullptr || frameMemory->unsecurePointer() == nullptr) {
                 mAsyncDecodeDone = true;
                 mScanlineReady.signal();
                 break;
@@ -437,7 +521,8 @@
     }
     // Aggressive clear to avoid holding on to resources
     mRetriever.clear();
-    mDataSource.clear();
+
+    // Hold on to mDataSource in case the client wants to redecode.
     return false;
 }
 
@@ -452,42 +537,48 @@
     // See if we want to decode in slices to allow client to start
     // scanline processing in parallel with decode. If this fails
     // we fallback to decoding the full frame.
-    if (mHasImage && mNumSlices > 1) {
-        // get first slice and metadata
-        sp<IMemory> frameMemory = mRetriever->getImageRectAtIndex(
-                -1, mOutputColor, 0, 0, mWidth, mSliceHeight);
-
-        if (frameMemory == nullptr || frameMemory->pointer() == nullptr) {
-            ALOGE("decode: metadata is a nullptr");
-            return false;
+    if (mHasImage) {
+        if (mSliceHeight >= 512 &&
+                mImageInfo.mWidth >= 3000 &&
+                mImageInfo.mHeight >= 2000 ) {
+            // Try decoding in slices only if the image has tiles and is big enough.
+            mNumSlices = (mImageInfo.mHeight + mSliceHeight - 1) / mSliceHeight;
+            ALOGV("mSliceHeight %u, mNumSlices %zu", mSliceHeight, mNumSlices);
         }
 
-        VideoFrame* videoFrame = static_cast<VideoFrame*>(frameMemory->pointer());
+        if (mNumSlices > 1) {
+            // get first slice and metadata
+            sp<IMemory> frameMemory = mRetriever->getImageRectAtIndex(
+                    -1, mOutputColor, 0, 0, mImageInfo.mWidth, mSliceHeight);
 
-        if (frameInfo != nullptr) {
-            frameInfo->set(
-                    videoFrame->mWidth,
-                    videoFrame->mHeight,
-                    videoFrame->mRotationAngle,
-                    videoFrame->mBytesPerPixel,
-                    videoFrame->mIccSize,
-                    videoFrame->getFlattenedIccData());
+            if (frameMemory == nullptr || frameMemory->unsecurePointer() == nullptr) {
+                ALOGE("decode: metadata is a nullptr");
+                return false;
+            }
+
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
+            VideoFrame* videoFrame = static_cast<VideoFrame*>(frameMemory->unsecurePointer());
+
+            if (frameInfo != nullptr) {
+                initFrameInfo(frameInfo, videoFrame);
+            }
+            mFrameMemory = frameMemory;
+            mAvailableLines = mSliceHeight;
+            mThread = new DecodeThread(this);
+            if (mThread->run("HeifDecode", ANDROID_PRIORITY_FOREGROUND) == OK) {
+                mFrameDecoded = true;
+                return true;
+            }
+            // Fallback to decode without slicing
+            mThread.clear();
+            mNumSlices = 1;
+            mSliceHeight = 0;
+            mAvailableLines = 0;
+            mFrameMemory.clear();
         }
-
-        mFrameMemory = frameMemory;
-        mAvailableLines = mSliceHeight;
-        mThread = new DecodeThread(this);
-        if (mThread->run("HeifDecode", ANDROID_PRIORITY_FOREGROUND) == OK) {
-            mFrameDecoded = true;
-            return true;
-        }
-
-        // Fallback to decode without slicing
-        mThread.clear();
-        mNumSlices = 1;
-        mSliceHeight = 0;
-        mAvailableLines = 0;
-        mFrameMemory.clear();
     }
 
     if (mHasImage) {
@@ -498,12 +589,16 @@
                 MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC, mOutputColor);
     }
 
-    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+    if (mFrameMemory == nullptr || mFrameMemory->unsecurePointer() == nullptr) {
         ALOGE("decode: videoFrame is a nullptr");
         return false;
     }
 
-    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->unsecurePointer());
     if (videoFrame->mSize == 0 ||
             mFrameMemory->size() < videoFrame->getFlattenedSize()) {
         ALOGE("decode: videoFrame size is invalid");
@@ -520,34 +615,82 @@
             videoFrame->mSize);
 
     if (frameInfo != nullptr) {
-        frameInfo->set(
-                videoFrame->mWidth,
-                videoFrame->mHeight,
-                videoFrame->mRotationAngle,
-                videoFrame->mBytesPerPixel,
-                videoFrame->mIccSize,
-                videoFrame->getFlattenedIccData());
+        initFrameInfo(frameInfo, videoFrame);
+
     }
     mFrameDecoded = true;
 
     // Aggressively clear to avoid holding on to resources
     mRetriever.clear();
-    mDataSource.clear();
+
+    // Hold on to mDataSource in case the client wants to redecode.
+    return true;
+}
+
+bool HeifDecoderImpl::decodeSequence(int frameIndex, HeifFrameInfo* frameInfo) {
+    ALOGV("%s: frame index %d", __FUNCTION__, frameIndex);
+    if (!mHasVideo) {
+        return false;
+    }
+
+    if (frameIndex < 0 || frameIndex >= mSequenceLength) {
+        ALOGE("invalid frame index: %d, total frames %zu", frameIndex, mSequenceLength);
+        return false;
+    }
+
+    mCurScanline = 0;
+
+    // set total scanline to sequence height now
+    mTotalScanline = mSequenceInfo.mHeight;
+
+    mFrameMemory = mRetriever->getFrameAtIndex(frameIndex, mOutputColor);
+    if (mFrameMemory == nullptr || mFrameMemory->unsecurePointer() == nullptr) {
+        ALOGE("decode: videoFrame is a nullptr");
+        return false;
+    }
+
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->unsecurePointer());
+    if (videoFrame->mSize == 0 ||
+            mFrameMemory->size() < videoFrame->getFlattenedSize()) {
+        ALOGE("decode: videoFrame size is invalid");
+        return false;
+    }
+
+    ALOGV("Decoded dimension %dx%d, display %dx%d, angle %d, rowbytes %d, size %d",
+            videoFrame->mWidth,
+            videoFrame->mHeight,
+            videoFrame->mDisplayWidth,
+            videoFrame->mDisplayHeight,
+            videoFrame->mRotationAngle,
+            videoFrame->mRowBytes,
+            videoFrame->mSize);
+
+    if (frameInfo != nullptr) {
+        initFrameInfo(frameInfo, videoFrame);
+    }
     return true;
 }
 
 bool HeifDecoderImpl::getScanlineInner(uint8_t* dst) {
-    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
+    if (mFrameMemory == nullptr || mFrameMemory->unsecurePointer() == nullptr) {
         return false;
     }
-    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       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);
     return true;
 }
 
 bool HeifDecoderImpl::getScanline(uint8_t* dst) {
-    if (mCurScanline >= mHeight) {
+    if (mCurScanline >= mTotalScanline) {
         ALOGE("no more scanline available");
         return false;
     }
@@ -567,8 +710,8 @@
 size_t HeifDecoderImpl::skipScanlines(size_t count) {
     uint32_t oldScanline = mCurScanline;
     mCurScanline += count;
-    if (mCurScanline > mHeight) {
-        mCurScanline = mHeight;
+    if (mCurScanline > mTotalScanline) {
+        mCurScanline = mTotalScanline;
     }
     return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
 }
diff --git a/media/libheif/HeifDecoderImpl.h b/media/libheif/HeifDecoderImpl.h
index 528ee3b..2b9c710 100644
--- a/media/libheif/HeifDecoderImpl.h
+++ b/media/libheif/HeifDecoderImpl.h
@@ -40,12 +40,16 @@
 
     bool init(HeifStream* stream, HeifFrameInfo* frameInfo) override;
 
+    bool getSequenceInfo(HeifFrameInfo* frameInfo, size_t *frameCount) override;
+
     bool getEncodedColor(HeifEncodedColor* outColor) const override;
 
     bool setOutputColor(HeifColorFormat heifColor) override;
 
     bool decode(HeifFrameInfo* frameInfo) override;
 
+    bool decodeSequence(int frameIndex, HeifFrameInfo* frameInfo) override;
+
     bool getScanline(uint8_t* dst) override;
 
     size_t skipScanlines(size_t count) override;
@@ -56,13 +60,15 @@
     sp<IDataSource> mDataSource;
     sp<MediaMetadataRetriever> mRetriever;
     sp<IMemory> mFrameMemory;
+    HeifFrameInfo mImageInfo;
+    HeifFrameInfo mSequenceInfo;
     android_pixel_format_t mOutputColor;
     size_t mCurScanline;
-    uint32_t mWidth;
-    uint32_t mHeight;
+    size_t mTotalScanline;
     bool mFrameDecoded;
     bool mHasImage;
     bool mHasVideo;
+    size_t mSequenceLength;
 
     // Slice decoding only
     Mutex mLock;
@@ -75,6 +81,7 @@
 
     bool decodeAsync();
     bool getScanlineInner(uint8_t* dst);
+    bool reinit(HeifFrameInfo* frameInfo);
 };
 
 } // namespace android
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
index aa10f33..9073672 100644
--- a/media/libheif/include/HeifDecoderAPI.h
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -17,7 +17,7 @@
 #ifndef _HEIF_DECODER_API_
 #define _HEIF_DECODER_API_
 
-#include <memory>
+#include <vector>
 
 /*
  * The output color pixel format of heif decoder.
@@ -40,41 +40,13 @@
 /*
  * Represents a color converted (RGB-based) video frame
  */
-struct HeifFrameInfo
-{
-    HeifFrameInfo() :
-        mWidth(0), mHeight(0), mRotationAngle(0), mBytesPerPixel(0),
-        mIccSize(0), mIccData(nullptr) {}
-
-    // update the frame info, will make a copy of |iccData| internally
-    void set(uint32_t width, uint32_t height, int32_t rotation, uint32_t bpp,
-            uint32_t iccSize, uint8_t* iccData) {
-        mWidth = width;
-        mHeight = height;
-        mRotationAngle = rotation;
-        mBytesPerPixel = bpp;
-
-        if (mIccData != nullptr) {
-            mIccData.reset(nullptr);
-        }
-        mIccSize = iccSize;
-        if (iccSize > 0) {
-            mIccData.reset(new uint8_t[iccSize]);
-            if (mIccData.get() != nullptr) {
-                memcpy(mIccData.get(), iccData, iccSize);
-            } else {
-                mIccSize = 0;
-            }
-        }
-    }
-
-    // Intentional public access modifiers:
+struct HeifFrameInfo {
     uint32_t mWidth;
     uint32_t mHeight;
     int32_t  mRotationAngle;           // Rotation angle, clockwise, should be multiple of 90
     uint32_t mBytesPerPixel;           // Number of bytes for one pixel
-    uint32_t mIccSize;                 // Number of bytes in mIccData
-    std::unique_ptr<uint8_t[]> mIccData; // Actual ICC data, memory is owned by this structure
+    int64_t mDurationUs;               // Duration of the frame in us
+    std::vector<uint8_t> mIccData;     // ICC data array
 };
 
 /*
@@ -113,8 +85,8 @@
     virtual size_t getLength() const = 0;
 
 private:
-    HeifStream(const HeifFrameInfo&) = delete;
-    HeifStream& operator=(const HeifFrameInfo&) = delete;
+    HeifStream(const HeifStream&) = delete;
+    HeifStream& operator=(const HeifStream&) = delete;
 };
 
 /*
@@ -146,6 +118,14 @@
     virtual bool init(HeifStream* stream, HeifFrameInfo* frameInfo) = 0;
 
     /*
+     * Returns true if the stream contains an image sequence and false otherwise.
+     * |frameInfo| will be filled with information of pictures in the sequence
+     * and |frameCount| the length of the sequence upon success and unmodified
+     * upon failure.
+     */
+    virtual bool getSequenceInfo(HeifFrameInfo* frameInfo, size_t *frameCount) = 0;
+
+    /*
      * Decode the picture internally, returning whether it succeeded. |frameInfo|
      * will be filled with information of the primary picture upon success and
      * unmodified upon failure.
@@ -156,6 +136,20 @@
     virtual bool decode(HeifFrameInfo* frameInfo) = 0;
 
     /*
+     * Decode the picture from the image sequence at index |frameIndex|.
+     * |frameInfo| will be filled with information of the decoded picture upon
+     * success and unmodified upon failure.
+     *
+     * |frameIndex| is the 0-based index of the video frame to retrieve. The frame
+     * index must be that of a valid frame. The total number of frames available for
+     * retrieval was reported via getSequenceInfo().
+     *
+     * After this succeeded, getScanline can be called to read the scanlines
+     * that were decoded.
+     */
+    virtual bool decodeSequence(int frameIndex, HeifFrameInfo* frameInfo) = 0;
+
+    /*
      * Read the next scanline (in top-down order), returns true upon success
      * and false otherwise.
      */
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1d33590..3fd3fc3 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -1,15 +1,10 @@
-cc_defaults {
-    name: "libmedia_defaults",
-    include_dirs: [
-        "bionic/libc/private",
-    ],
-}
-
 cc_library_headers {
     name: "libmedia_headers",
     vendor_available: true,
+    min_sdk_version: "29",
+
     export_include_dirs: ["include"],
-    header_libs:[
+    header_libs: [
         "libbase_headers",
         "libgui_headers",
         "libstagefright_headers",
@@ -22,29 +17,42 @@
     ],
 }
 
-cc_library {
-    name: "libmedia_helper",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
-    double_loadable: true,
-    srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
-    cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
+filegroup {
+    name: "libmedia_omx_aidl",
+    srcs: [
+        "aidl/android/IOMXBufferSource.aidl",
     ],
-    shared_libs: ["libutils", "liblog"],
-    header_libs: [
-        "libmedia_headers",
-        "libaudioclient_headers",
-        "libaudio_system_headers",
+    path: "aidl",
+}
+
+filegroup {
+    name: "mediaextractorservice_aidl",
+    srcs: [
+        "aidl/android/IMediaExtractorService.aidl",
     ],
-    export_header_lib_headers: [
-        "libmedia_headers",
+    path: "aidl",
+}
+
+filegroup {
+    name: "resourcemanager_aidl",
+    srcs: [
+        "aidl/android/media/IResourceManagerClient.aidl",
+        "aidl/android/media/IResourceManagerService.aidl",
+        "aidl/android/media/MediaResourceType.aidl",
+        "aidl/android/media/MediaResourceSubType.aidl",
+        "aidl/android/media/MediaResourceParcel.aidl",
+        "aidl/android/media/MediaResourcePolicyParcel.aidl",
     ],
-    clang: true,
+    path: "aidl",
+}
+
+aidl_interface {
+    name: "resourcemanager_aidl_interface",
+    unstable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        ":resourcemanager_aidl",
+    ],
 }
 
 cc_library_shared {
@@ -56,15 +64,11 @@
     double_loadable: true,
 
     srcs: [
-        "aidl/android/IGraphicBufferSource.aidl",
-        "aidl/android/IOMXBufferSource.aidl",
+        ":libmedia_omx_aidl",
 
-        "IMediaCodecList.cpp",
         "IOMX.cpp",
         "MediaCodecBuffer.cpp",
-        "MediaCodecInfo.cpp",
         "OMXBuffer.cpp",
-        "omx/1.0/WGraphicBufferSource.cpp",
         "omx/1.0/WOmxBufferSource.cpp",
         "omx/1.0/WOmxNode.cpp",
         "omx/1.0/WOmxObserver.cpp",
@@ -74,7 +78,7 @@
         local_include_dirs: ["aidl"],
         export_aidl_headers: true,
     },
-    
+
     local_include_dirs: [
         "include",
     ],
@@ -85,7 +89,6 @@
         "libbinder",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libstagefright_foundation",
         "libui",
@@ -129,7 +132,6 @@
     },
 }
 
-
 cc_library_shared {
     name: "libmedia_omx_client",
 
@@ -146,7 +148,6 @@
         "libcutils",
         "libgui",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libmedia_omx",
         "libstagefright_foundation",
@@ -193,13 +194,16 @@
 cc_library_static {
     name: "libmedia_midiiowrapper",
 
+    min_sdk_version: "29",
+
     srcs: ["MidiIoWrapper.cpp"],
 
     static_libs: [
-        "libsonivox",
+        "libsonivoxwithoutjet",
     ],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 
@@ -218,19 +222,60 @@
     },
 }
 
+cc_library_shared {
+    name: "libmedia_codeclist",
+
+    srcs: [
+        "IMediaCodecList.cpp",
+        "MediaCodecInfo.cpp",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    shared_libs: [
+        "android.hardware.media.omx@1.0",
+        "libbinder",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    include_dirs: [
+        "system/libhidl/transport/token/1.0/utils/include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
+
 cc_library {
     name: "libmedia",
 
-    defaults: [ "libmedia_defaults" ],
-
     srcs: [
+        ":mediaextractorservice_aidl",
         "IDataSource.cpp",
         "BufferingSettings.cpp",
         "mediaplayer.cpp",
         "IMediaHTTPConnection.cpp",
         "IMediaHTTPService.cpp",
         "IMediaExtractor.cpp",
-        "IMediaExtractorService.cpp",
         "IMediaPlayerService.cpp",
         "IMediaPlayerClient.cpp",
         "IMediaRecorderClient.cpp",
@@ -239,16 +284,11 @@
         "IMediaSource.cpp",
         "IRemoteDisplay.cpp",
         "IRemoteDisplayClient.cpp",
-        "IResourceManagerClient.cpp",
-        "IResourceManagerService.cpp",
         "IStreamSource.cpp",
-        "MediaUtils.cpp",
         "Metadata.cpp",
         "mediarecorder.cpp",
         "IMediaMetadataRetriever.cpp",
         "mediametadataretriever.cpp",
-        "MidiDeviceInfo.cpp",
-        "JetPlayer.cpp",
         "MediaScanner.cpp",
         "MediaScannerClient.cpp",
         "CharacterEncodingDetector.cpp",
@@ -256,7 +296,6 @@
         "MediaProfiles.cpp",
         "MediaResource.cpp",
         "MediaResourcePolicy.cpp",
-        "Visualizer.cpp",
         "StringArray.cpp",
         "NdkMediaFormatPriv.cpp",
         "NdkMediaErrorPriv.cpp",
@@ -284,15 +323,16 @@
         "libprocessgroup",
         "libutils",
         "libbinder",
-        "libsonivox",
+        "libbinder_ndk",
+        //"libsonivox",
         "libandroidicu",
         "libexpat",
         "libcamera_client",
         "libstagefright_foundation",
         "libgui",
         "libdl",
-        "libaudioutils",
         "libaudioclient",
+        "libmedia_codeclist",
         "libmedia_omx",
     ],
 
@@ -300,13 +340,16 @@
         "libaudioclient",
         "libbinder",
         "libandroidicu",
-        "libsonivox",
+        //"libsonivox",
         "libmedia_omx",
     ],
 
     static_libs: [
-        "libc_malloc_debug_backtrace",  // for memory heap analysis
-        "libmedia_midiiowrapper",
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
+    export_static_lib_headers: [
+        "resourcemanager_aidl_interface-ndk_platform",
     ],
 
     export_include_dirs: [
@@ -329,66 +372,3 @@
         cfi: true,
     },
 }
-
-cc_library_static {
-    name: "libmedia_player2_util",
-
-    defaults: [ "libmedia_defaults" ],
-
-    srcs: [
-        "AudioParameter.cpp",
-        "BufferingSettings.cpp",
-        "DataSourceDesc.cpp",
-        "MediaCodecBuffer.cpp",
-        "Metadata.cpp",
-        "NdkWrapper.cpp",
-    ],
-
-    shared_libs: [
-        "libbinder",
-        "libcutils",
-        "liblog",
-        "libmediandk",
-        "libnativewindow",
-        "libmediandk_utils",
-        "libstagefright_foundation",
-        "libui",
-        "libutils",
-    ],
-
-    export_shared_lib_headers: [
-        "libbinder",
-        "libmediandk",
-    ],
-
-    header_libs: [
-        "media_plugin_headers",
-    ],
-
-    include_dirs: [
-        "frameworks/av/media/ndk",
-    ],
-
-    static_libs: [
-        "libstagefright_rtsp",
-        "libstagefright_timedtext",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
-    ],
-
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-}
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
deleted file mode 100644
index 1c95e27..0000000
--- a/media/libmedia/AudioParameter.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2006-2011 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_TAG "AudioParameter"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-
-#include <media/AudioParameter.h>
-#include <system/audio.h>
-
-namespace android {
-
-// static
-const char * const AudioParameter::keyRouting = AUDIO_PARAMETER_STREAM_ROUTING;
-const char * const AudioParameter::keySamplingRate = AUDIO_PARAMETER_STREAM_SAMPLING_RATE;
-const char * const AudioParameter::keyFormat = AUDIO_PARAMETER_STREAM_FORMAT;
-const char * const AudioParameter::keyChannels = AUDIO_PARAMETER_STREAM_CHANNELS;
-const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
-const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
-const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
-const char * const AudioParameter::keyBtNrec = AUDIO_PARAMETER_KEY_BT_NREC;
-const char * const AudioParameter::keyHwAvSync = AUDIO_PARAMETER_HW_AV_SYNC;
-const char * const AudioParameter::keyPresentationId = AUDIO_PARAMETER_STREAM_PRESENTATION_ID;
-const char * const AudioParameter::keyProgramId = AUDIO_PARAMETER_STREAM_PROGRAM_ID;
-const char * const AudioParameter::keyAudioLanguagePreferred =
-        AUDIO_PARAMETER_KEY_AUDIO_LANGUAGE_PREFERRED;
-const char * const AudioParameter::keyMonoOutput = AUDIO_PARAMETER_MONO_OUTPUT;
-const char * const AudioParameter::keyStreamHwAvSync = AUDIO_PARAMETER_STREAM_HW_AV_SYNC;
-const char * const AudioParameter::keyStreamConnect = AUDIO_PARAMETER_DEVICE_CONNECT;
-const char * const AudioParameter::keyStreamDisconnect = AUDIO_PARAMETER_DEVICE_DISCONNECT;
-const char * const AudioParameter::keyStreamSupportedFormats = AUDIO_PARAMETER_STREAM_SUP_FORMATS;
-const char * const AudioParameter::keyStreamSupportedChannels = AUDIO_PARAMETER_STREAM_SUP_CHANNELS;
-const char * const AudioParameter::keyStreamSupportedSamplingRates =
-        AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES;
-const char * const AudioParameter::valueOn = AUDIO_PARAMETER_VALUE_ON;
-const char * const AudioParameter::valueOff = AUDIO_PARAMETER_VALUE_OFF;
-const char * const AudioParameter::valueListSeparator = AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
-const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
-const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
-
-AudioParameter::AudioParameter(const String8& keyValuePairs)
-{
-    char *str = new char[keyValuePairs.length()+1];
-    mKeyValuePairs = keyValuePairs;
-    char *last;
-
-    strcpy(str, keyValuePairs.string());
-    char *pair = strtok_r(str, ";", &last);
-    while (pair != NULL) {
-        if (strlen(pair) != 0) {
-            size_t eqIdx = strcspn(pair, "=");
-            String8 key = String8(pair, eqIdx);
-            String8 value;
-            if (eqIdx == strlen(pair)) {
-                value = String8("");
-            } else {
-                value = String8(pair + eqIdx + 1);
-            }
-            if (mParameters.indexOfKey(key) < 0) {
-                mParameters.add(key, value);
-            } else {
-                mParameters.replaceValueFor(key, value);
-            }
-        } else {
-            ALOGV("AudioParameter() cstor empty key value pair");
-        }
-        pair = strtok_r(NULL, ";", &last);
-    }
-
-    delete[] str;
-}
-
-AudioParameter::~AudioParameter()
-{
-    mParameters.clear();
-}
-
-String8 AudioParameter::toStringImpl(bool useValues) const
-{
-    String8 str = String8("");
-
-    size_t size = mParameters.size();
-    for (size_t i = 0; i < size; i++) {
-        str += mParameters.keyAt(i);
-        if (useValues) {
-            str += "=";
-            str += mParameters.valueAt(i);
-        }
-        if (i < (size - 1)) str += ";";
-    }
-    return str;
-}
-
-status_t AudioParameter::add(const String8& key, const String8& value)
-{
-    if (mParameters.indexOfKey(key) < 0) {
-        mParameters.add(key, value);
-        return NO_ERROR;
-    } else {
-        mParameters.replaceValueFor(key, value);
-        return ALREADY_EXISTS;
-    }
-}
-
-status_t AudioParameter::addKey(const String8& key)
-{
-    return add(key, String8());
-}
-
-status_t AudioParameter::addInt(const String8& key, const int value)
-{
-    char str[12];
-    if (snprintf(str, 12, "%d", value) > 0) {
-        String8 str8 = String8(str);
-        return add(key, str8);
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::addFloat(const String8& key, const float value)
-{
-    char str[23];
-    if (snprintf(str, 23, "%.10f", value) > 0) {
-        String8 str8 = String8(str);
-        return add(key, str8);
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::remove(const String8& key)
-{
-    if (mParameters.indexOfKey(key) >= 0) {
-        mParameters.removeItem(key);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::get(const String8& key, String8& value) const
-{
-    if (mParameters.indexOfKey(key) >= 0) {
-        value = mParameters.valueFor(key);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::getInt(const String8& key, int& value) const
-{
-    String8 str8;
-    status_t result = get(key, str8);
-    value = 0;
-    if (result == NO_ERROR) {
-        int val;
-        if (sscanf(str8.string(), "%d", &val) == 1) {
-            value = val;
-        } else {
-            result = INVALID_OPERATION;
-        }
-    }
-    return result;
-}
-
-status_t AudioParameter::getFloat(const String8& key, float& value) const
-{
-    String8 str8;
-    status_t result = get(key, str8);
-    value = 0;
-    if (result == NO_ERROR) {
-        float val;
-        if (sscanf(str8.string(), "%f", &val) == 1) {
-            value = val;
-        } else {
-            result = INVALID_OPERATION;
-        }
-    }
-    return result;
-}
-
-status_t AudioParameter::getAt(size_t index, String8& key) const
-{
-    if (mParameters.size() > index) {
-        key = mParameters.keyAt(index);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioParameter::getAt(size_t index, String8& key, String8& value) const
-{
-    if (mParameters.size() > index) {
-        key = mParameters.keyAt(index);
-        value = mParameters.valueAt(index);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-} // namespace android
diff --git a/media/libmedia/DataSourceDesc.cpp b/media/libmedia/DataSourceDesc.cpp
deleted file mode 100644
index b7ccbce..0000000
--- a/media/libmedia/DataSourceDesc.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 "DataSourceDesc"
-
-#include <media/DataSource.h>
-#include <media/DataSourceDesc.h>
-#include <media/MediaHTTPService.h>
-
-namespace android {
-
-static const int64_t kLongMax = 0x7ffffffffffffffL;
-
-DataSourceDesc::DataSourceDesc()
-    : mType(TYPE_NONE),
-      mFDOffset(0),
-      mFDLength(kLongMax),
-      mId(0),
-      mStartPositionMs(0),
-      mEndPositionMs(0) {
-}
-
-}  // namespace android
diff --git a/media/libmedia/IDataSource.cpp b/media/libmedia/IDataSource.cpp
index 31c85af..e96a113 100644
--- a/media/libmedia/IDataSource.cpp
+++ b/media/libmedia/IDataSource.cpp
@@ -19,11 +19,9 @@
 #include <utils/Log.h>
 #include <utils/Timers.h>
 
-#include <media/IDataSource.h>
-
+#include <android/IDataSource.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
-#include <drm/drm_framework_common.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
@@ -35,7 +33,6 @@
     CLOSE,
     GET_FLAGS,
     TO_STRING,
-    DRM_INITIALIZATION,
 };
 
 struct BpDataSource : public BpInterface<IDataSource> {
@@ -95,47 +92,6 @@
         remote()->transact(TO_STRING, data, &reply);
         return reply.readString8();
     }
-
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
-        if (mime == NULL) {
-            data.writeInt32(0);
-        } else {
-            data.writeInt32(1);
-            data.writeCString(mime);
-        }
-        remote()->transact(DRM_INITIALIZATION, data, &reply);
-        sp<DecryptHandle> handle;
-        if (reply.dataAvail() != 0) {
-            handle = new DecryptHandle();
-            handle->decryptId = reply.readInt32();
-            handle->mimeType = reply.readString8();
-            handle->decryptApiType = reply.readInt32();
-            handle->status = reply.readInt32();
-
-            const int bufferLength = data.readInt32();
-            if (bufferLength != -1) {
-                handle->decryptInfo = new DecryptInfo();
-                handle->decryptInfo->decryptBufferLength = bufferLength;
-            }
-
-            size_t size = data.readInt32();
-            for (size_t i = 0; i < size; ++i) {
-                DrmCopyControl key = (DrmCopyControl)data.readInt32();
-                int value = data.readInt32();
-                handle->copyControlVector.add(key, value);
-            }
-
-            size = data.readInt32();
-            for (size_t i = 0; i < size; ++i) {
-                String8 key = data.readString8();
-                String8 value = data.readString8();
-                handle->extendedData.add(key, value);
-            }
-        }
-        return handle;
-    }
 };
 
 IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
@@ -178,42 +134,6 @@
             reply->writeString8(toString());
             return NO_ERROR;
         } break;
-        case DRM_INITIALIZATION: {
-            CHECK_INTERFACE(IDataSource, data, reply);
-            const char *mime = NULL;
-            const int32_t flag = data.readInt32();
-            if (flag != 0) {
-                mime = data.readCString();
-            }
-            sp<DecryptHandle> handle = DrmInitialization(mime);
-            if (handle != NULL) {
-                reply->writeInt32(handle->decryptId);
-                reply->writeString8(handle->mimeType);
-                reply->writeInt32(handle->decryptApiType);
-                reply->writeInt32(handle->status);
-
-                if (handle->decryptInfo != NULL) {
-                    reply->writeInt32(handle->decryptInfo->decryptBufferLength);
-                } else {
-                    reply->writeInt32(-1);
-                }
-
-                size_t size = handle->copyControlVector.size();
-                reply->writeInt32(size);
-                for (size_t i = 0; i < size; ++i) {
-                    reply->writeInt32(handle->copyControlVector.keyAt(i));
-                    reply->writeInt32(handle->copyControlVector.valueAt(i));
-                }
-
-                size = handle->extendedData.size();
-                reply->writeInt32(size);
-                for (size_t i = 0; i < size; ++i) {
-                    reply->writeString8(handle->extendedData.keyAt(i));
-                    reply->writeString8(handle->extendedData.valueAt(i));
-                }
-            }
-            return NO_ERROR;
-        } break;
 
         default:
             return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index fb6d3a2..39caf53 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -25,7 +25,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/PermissionCache.h>
-#include <media/IMediaExtractor.h>
+#include <android/IMediaExtractor.h>
 #include <media/stagefright/MetaData.h>
 
 namespace android {
@@ -107,8 +107,15 @@
     }
 
     virtual uint32_t flags() const {
-        ALOGV("flags NOT IMPLEMENTED");
-        return 0;
+        ALOGV("flags");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        status_t ret = remote()->transact(FLAGS, data, &reply);
+        int flgs = 0;
+        if (ret == NO_ERROR) {
+            flgs = reply.readUint32();
+        }
+        return flgs;
     }
 
     virtual status_t setMediaCas(const HInterfaceToken &casToken) {
@@ -125,9 +132,15 @@
         return reply.readInt32();
     }
 
-    virtual const char * name() {
-        ALOGV("name NOT IMPLEMENTED");
-        return NULL;
+    virtual String8 name() {
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        status_t ret = remote()->transact(NAME, data, &reply);
+        String8 nm;
+        if (ret == NO_ERROR) {
+            nm = reply.readString8();
+        }
+        return nm;
     }
 };
 
@@ -192,6 +205,12 @@
             status_t ret = getMetrics(reply);
             return ret;
         }
+        case FLAGS: {
+            ALOGV("flags");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            reply->writeUint32(this->flags());
+            return NO_ERROR;
+        }
         case SETMEDIACAS: {
             ALOGV("setMediaCas");
             CHECK_INTERFACE(IMediaExtractor, data, reply);
@@ -206,6 +225,13 @@
             reply->writeInt32(setMediaCas(casToken));
             return OK;
         }
+        case NAME: {
+            ALOGV("name");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            String8 nm = name();
+            reply->writeString8(nm);
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
deleted file mode 100644
index 243b09d..0000000
--- a/media/libmedia/IMediaExtractorService.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-**
-** Copyright 2007, 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_TAG "IMediaExtractorService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <media/IMediaExtractorService.h>
-
-namespace android {
-
-enum {
-    MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
-    MAKE_IDATA_SOURCE_FD,
-    GET_SUPPORTED_TYPES,
-};
-
-class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
-{
-public:
-    explicit BpMediaExtractorService(const sp<IBinder>& impl)
-        : BpInterface<IMediaExtractorService>(impl)
-    {
-    }
-
-    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(source));
-        if (mime != NULL) {
-            data.writeCString(mime);
-        }
-        status_t ret = remote()->transact(MAKE_EXTRACTOR, data, &reply);
-        if (ret == NO_ERROR) {
-            return interface_cast<IMediaExtractor>(reply.readStrongBinder());
-        }
-        return NULL;
-    }
-
-    virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
-        data.writeFileDescriptor(fd);
-        data.writeInt64(offset);
-        data.writeInt64(length);
-        status_t ret = remote()->transact(MAKE_IDATA_SOURCE_FD, data, &reply);
-        ALOGV("fd:%d offset:%lld length:%lld ret:%d",
-                fd, (long long)offset, (long long)length, ret);
-        if (ret == NO_ERROR) {
-            return interface_cast<IDataSource>(reply.readStrongBinder());
-        }
-        return nullptr;
-    }
-
-    virtual std::unordered_set<std::string> getSupportedTypes() {
-        std::unordered_set<std::string> supportedTypes;
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
-        status_t ret = remote()->transact(GET_SUPPORTED_TYPES, data, &reply);
-        if (ret == NO_ERROR) {
-            // process reply
-            while(true) {
-                const char *ext = reply.readCString();
-                if (!ext) {
-                    break;
-                }
-                supportedTypes.insert(std::string(ext));
-            }
-        }
-        return supportedTypes;
-    }
-};
-
-IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaExtractorService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch (code) {
-
-        case MAKE_EXTRACTOR: {
-            CHECK_INTERFACE(IMediaExtractorService, data, reply);
-            sp<IBinder> b;
-            status_t ret = data.readStrongBinder(&b);
-            if (ret != NO_ERROR || b == NULL) {
-                ALOGE("Error reading source from parcel");
-                return ret;
-            }
-            // If we make an extractor through Binder, enabled shared memory
-            // for MediaBuffers for this process.
-            MediaBuffer::useSharedMemory();
-            sp<IDataSource> source = interface_cast<IDataSource>(b);
-            const char *mime = data.readCString();
-            sp<IMediaExtractor> ex = makeExtractor(source, mime);
-            reply->writeStrongBinder(IInterface::asBinder(ex));
-            return NO_ERROR;
-        }
-
-        case MAKE_IDATA_SOURCE_FD: {
-            CHECK_INTERFACE(IMediaExtractorService, data, reply);
-            const int fd = dup(data.readFileDescriptor()); // -1 fd checked in makeIDataSource
-            const int64_t offset = data.readInt64();
-            const int64_t length = data.readInt64();
-            ALOGV("fd %d  offset%lld  length:%lld", fd, (long long)offset, (long long)length);
-            sp<IDataSource> source = makeIDataSource(fd, offset, length);
-            reply->writeStrongBinder(IInterface::asBinder(source));
-            // The FileSource closes the descriptor, so if it is not created
-            // we need to close the descriptor explicitly.
-            if (source.get() == nullptr && fd != -1) {
-                close(fd);
-            }
-            return NO_ERROR;
-        }
-
-        case GET_SUPPORTED_TYPES:
-        {
-            CHECK_INTERFACE(IMediaExtractorService, data, reply);
-            std::unordered_set<std::string> supportedTypes = getSupportedTypes();
-            for (auto it = supportedTypes.begin(); it != supportedTypes.end(); ++it) {
-                reply->writeCString((*it).c_str());
-            }
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp
index 1bb8d67..8cbb4c2 100644
--- a/media/libmedia/IMediaHTTPConnection.cpp
+++ b/media/libmedia/IMediaHTTPConnection.cpp
@@ -128,12 +128,12 @@
            ALOGE("readAt got a NULL buffer");
            return UNKNOWN_ERROR;
         }
-        if (mMemory->pointer() == NULL) {
-           ALOGE("readAt got a NULL mMemory->pointer()");
+        if (mMemory->unsecurePointer() == NULL) {
+           ALOGE("readAt got a NULL mMemory->unsecurePointer()");
            return UNKNOWN_ERROR;
         }
 
-        memcpy(buffer, mMemory->pointer(), len);
+        memcpy(buffer, mMemory->unsecurePointer(), len);
 
         return len;
     }
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index f9fa86e..8a3b84e 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -19,8 +19,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <android/IDataSource.h>
 #include <binder/Parcel.h>
-#include <media/IDataSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaMetadataRetriever.h>
 #include <processgroup/sched_policy.h>
@@ -109,7 +109,7 @@
             data.writeInt32(0);
         } else {
             // serialize the headers
-            data.writeInt64(headers->size());
+            data.writeInt32(headers->size());
             for (size_t i = 0; i < headers->size(); ++i) {
                 data.writeString8(headers->keyAt(i));
                 data.writeString8(headers->valueAt(i));
@@ -213,15 +213,14 @@
         return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
-    status_t getFrameAtIndex(std::vector<sp<IMemory> > *frames,
-            int frameIndex, int numFrames, int colorFormat, bool metaOnly)
+    sp<IMemory> getFrameAtIndex(
+            int index, int colorFormat, bool metaOnly)
     {
-        ALOGV("getFrameAtIndex: frameIndex(%d), numFrames(%d), colorFormat(%d) metaOnly(%d)",
-                frameIndex, numFrames, colorFormat, metaOnly);
+        ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
+                index, colorFormat, metaOnly);
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-        data.writeInt32(frameIndex);
-        data.writeInt32(numFrames);
+        data.writeInt32(index);
         data.writeInt32(colorFormat);
         data.writeInt32(metaOnly);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
@@ -230,16 +229,9 @@
         remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
         status_t ret = reply.readInt32();
         if (ret != NO_ERROR) {
-            return ret;
+            return NULL;
         }
-        int retNumFrames = reply.readInt32();
-        if (retNumFrames < numFrames) {
-            numFrames = retNumFrames;
-        }
-        for (int i = 0; i < numFrames; i++) {
-            frames->push_back(interface_cast<IMemory>(reply.readStrongBinder()));
-        }
-        return OK;
+        return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
     sp<IMemory> extractAlbumArt()
@@ -318,11 +310,22 @@
             }
 
             KeyedVector<String8, String8> headers;
-            size_t numHeaders = (size_t) data.readInt64();
+            size_t numHeaders = (size_t) data.readInt32();
             for (size_t i = 0; i < numHeaders; ++i) {
-                String8 key = data.readString8();
-                String8 value = data.readString8();
-                headers.add(key, value);
+                String8 key;
+                String8 value;
+                status_t status;
+                status = data.readString8(&key);
+                if (status != OK) {
+                    return status;
+                }
+                status = data.readString8(&value);
+                if (status != OK) {
+                    return status;
+                }
+                if (headers.add(key, value) < 0) {
+                    return UNKNOWN_ERROR;
+                }
             }
 
             reply->writeInt32(
@@ -431,24 +434,20 @@
 
         case GET_FRAME_AT_INDEX: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-            int frameIndex = data.readInt32();
-            int numFrames = data.readInt32();
+            int index = data.readInt32();
             int colorFormat = data.readInt32();
             bool metaOnly = (data.readInt32() != 0);
-            ALOGV("getFrameAtIndex: frameIndex(%d), numFrames(%d), colorFormat(%d), metaOnly(%d)",
-                    frameIndex, numFrames, colorFormat, metaOnly);
+            ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
+                    index, colorFormat, metaOnly);
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
             setSchedPolicy(data);
 #endif
-            std::vector<sp<IMemory> > frames;
-            status_t err = getFrameAtIndex(
-                    &frames, frameIndex, numFrames, colorFormat, metaOnly);
-            reply->writeInt32(err);
-            if (OK == err) {
-                reply->writeInt32(frames.size());
-                for (size_t i = 0; i < frames.size(); i++) {
-                    reply->writeStrongBinder(IInterface::asBinder(frames[i]));
-                }
+            sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
+            if (frame != nullptr) {  // Don't send NULL across the binder interface
+                reply->writeInt32(NO_ERROR);
+                reply->writeStrongBinder(IInterface::asBinder(frame));
+            } else {
+                reply->writeInt32(UNKNOWN_ERROR);
             }
 #ifndef DISABLE_GROUP_SCHEDULE_HACK
             restoreSchedPolicy();
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index ea06665..20bc23d 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -19,18 +19,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <android/IDataSource.h>
 #include <binder/Parcel.h>
-
+#include <gui/IGraphicBufferProducer.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
 #include <media/BufferingSettings.h>
-
-#include <media/IDataSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IMediaPlayer.h>
 #include <media/IStreamSource.h>
-
-#include <gui/IGraphicBufferProducer.h>
 #include <utils/String8.h>
 
 namespace android {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a354ce1..ac86f72 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -67,7 +67,9 @@
     GET_ACTIVE_MICROPHONES,
     GET_PORT_ID,
     SET_PREFERRED_MICROPHONE_DIRECTION,
-    SET_PREFERRED_MICROPHONE_FIELD_DIMENSION
+    SET_PREFERRED_MICROPHONE_FIELD_DIMENSION,
+    SET_PRIVACY_SENSITIVE,
+    GET_PRIVACY_SENSITIVE
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -151,6 +153,36 @@
         return reply.readInt32();
     }
 
+    status_t setPrivacySensitive(bool privacySensitive)
+    {
+        ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(privacySensitive ? 1 : 0);
+        status_t status = remote()->transact(SET_PRIVACY_SENSITIVE, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return reply.readInt32();
+    }
+
+    status_t isPrivacySensitive(bool *privacySensitive) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        *privacySensitive = false;
+        status_t status = remote()->transact(GET_PRIVACY_SENSITIVE, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status == NO_ERROR) {
+            *privacySensitive = reply.readInt32() == 1;
+        }
+        ALOGV("%s status %d enabled: %s", __func__, status, *privacySensitive ? "true" : "false");
+        return status;
+    }
+
     status_t setOutputFormat(int of)
     {
         ALOGV("setOutputFormat(%d)", of);
@@ -537,6 +569,24 @@
             reply->writeInt32(setAudioSource(as));
             return NO_ERROR;
         } break;
+        case SET_PRIVACY_SENSITIVE: {
+            ALOGV("SET_PRIVACY_SENSITIVE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            bool privacySensitive = data.readInt32() == 1;
+            reply->writeInt32(setPrivacySensitive(privacySensitive));
+            return NO_ERROR;
+        } break;
+        case GET_PRIVACY_SENSITIVE: {
+            ALOGV("GET_PRIVACY_SENSITIVE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            bool privacySensitive = false;
+            status_t status = isPrivacySensitive(&privacySensitive);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(privacySensitive ? 1 : 0);
+            }
+            return NO_ERROR;
+        } break;
         case SET_OUTPUT_FORMAT: {
             ALOGV("SET_OUTPUT_FORMAT");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 50826c5..36cd73b 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -26,7 +26,7 @@
 #include <media/IMediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 
 namespace android {
@@ -107,7 +107,7 @@
         data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
         status_t ret = remote()->transact(GETFORMAT, data, &reply);
         if (ret == NO_ERROR) {
-            AutoMutex _l(mLock);
+            AutoMutex _l(mBpLock);
             mMetaData = MetaData::createFromParcel(reply);
             return mMetaData;
         }
@@ -224,7 +224,7 @@
     // XXX: could we use this for caching, or does metadata change on the fly?
     sp<MetaData> mMetaData;
     // ensure synchronize access to mMetaData
-    Mutex mLock;
+    Mutex mBpLock;
 
     // Cache all IMemory objects received from MediaExtractor.
     // We gc IMemory objects that are no longer active (referenced by a MediaBuffer).
@@ -301,6 +301,7 @@
             CHECK_INTERFACE(IMediaSource, data, reply);
             mGroup->signalBufferReturned(nullptr);
             status_t status = stop();
+            AutoMutex _l(mBnLock);
             mIndexCache.reset();
             mBuffersSinceStop = 0;
             return status;
@@ -340,6 +341,7 @@
                     && len == sizeof(opts)
                     && data.read((void *)&opts, len) == NO_ERROR;
 
+            AutoMutex _l(mBnLock);
             mGroup->signalBufferReturned(nullptr);
             mIndexCache.gc();
             size_t inlineTransferSize = 0;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index bc0c2cd..959a3d7 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -29,7 +29,6 @@
 #include <utils/NativeHandle.h>
 
 #include <media/omx/1.0/WOmxNode.h>
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
 namespace android {
diff --git a/media/libmedia/IResourceManagerClient.cpp b/media/libmedia/IResourceManagerClient.cpp
deleted file mode 100644
index 1fea479..0000000
--- a/media/libmedia/IResourceManagerClient.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-**
-** Copyright 2015, 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 <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <media/IResourceManagerClient.h>
-
-namespace android {
-
-enum {
-    RECLAIM_RESOURCE = IBinder::FIRST_CALL_TRANSACTION,
-    GET_NAME,
-};
-
-class BpResourceManagerClient: public BpInterface<IResourceManagerClient>
-{
-public:
-    explicit BpResourceManagerClient(const sp<IBinder> &impl)
-        : BpInterface<IResourceManagerClient>(impl)
-    {
-    }
-
-    virtual bool reclaimResource() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerClient::getInterfaceDescriptor());
-
-        bool ret = false;
-        status_t status = remote()->transact(RECLAIM_RESOURCE, data, &reply);
-        if (status == NO_ERROR) {
-            ret = (bool)reply.readInt32();
-        }
-        return ret;
-    }
-
-    virtual String8 getName() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerClient::getInterfaceDescriptor());
-
-        String8 ret;
-        status_t status = remote()->transact(GET_NAME, data, &reply);
-        if (status == NO_ERROR) {
-            ret = reply.readString8();
-        }
-        return ret;
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(ResourceManagerClient, "android.media.IResourceManagerClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnResourceManagerClient::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
-{
-    switch (code) {
-        case RECLAIM_RESOURCE: {
-            CHECK_INTERFACE(IResourceManagerClient, data, reply);
-            bool ret = reclaimResource();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case GET_NAME: {
-            CHECK_INTERFACE(IResourceManagerClient, data, reply);
-            String8 ret = getName();
-            reply->writeString8(ret);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}; // namespace android
diff --git a/media/libmedia/IResourceManagerService.cpp b/media/libmedia/IResourceManagerService.cpp
deleted file mode 100644
index f8a0a14..0000000
--- a/media/libmedia/IResourceManagerService.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
-**
-** Copyright 2015, 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 "IResourceManagerService"
-#include <utils/Log.h>
-
-#include <media/IResourceManagerService.h>
-
-#include <binder/Parcel.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-namespace android {
-
-enum {
-    CONFIG = IBinder::FIRST_CALL_TRANSACTION,
-    ADD_RESOURCE,
-    REMOVE_RESOURCE,
-    REMOVE_CLIENT,
-    RECLAIM_RESOURCE,
-};
-
-template <typename T>
-static void writeToParcel(Parcel *data, const Vector<T> &items) {
-    size_t size = items.size();
-    // truncates size, but should be okay for this usecase
-    data->writeUint32(static_cast<uint32_t>(size));
-    for (size_t i = 0; i < size; i++) {
-        items[i].writeToParcel(data);
-    }
-}
-
-template <typename T>
-static void readFromParcel(const Parcel &data, Vector<T> *items) {
-    size_t size = (size_t)data.readUint32();
-    for (size_t i = 0; i < size && data.dataAvail() > 0; i++) {
-        T item;
-        item.readFromParcel(data);
-        items->add(item);
-    }
-}
-
-class BpResourceManagerService : public BpInterface<IResourceManagerService>
-{
-public:
-    explicit BpResourceManagerService(const sp<IBinder> &impl)
-        : BpInterface<IResourceManagerService>(impl)
-    {
-    }
-
-    virtual void config(const Vector<MediaResourcePolicy> &policies) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor());
-        writeToParcel(&data, policies);
-        remote()->transact(CONFIG, data, &reply);
-    }
-
-    virtual void addResource(
-            int pid,
-            int uid,
-            int64_t clientId,
-            const sp<IResourceManagerClient> client,
-            const Vector<MediaResource> &resources) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor());
-        data.writeInt32(pid);
-        data.writeInt32(uid);
-        data.writeInt64(clientId);
-        data.writeStrongBinder(IInterface::asBinder(client));
-        writeToParcel(&data, resources);
-
-        remote()->transact(ADD_RESOURCE, data, &reply);
-    }
-
-    virtual void removeResource(int pid, int64_t clientId, const Vector<MediaResource> &resources) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor());
-        data.writeInt32(pid);
-        data.writeInt64(clientId);
-        writeToParcel(&data, resources);
-
-        remote()->transact(REMOVE_RESOURCE, data, &reply);
-    }
-
-    virtual void removeClient(int pid, int64_t clientId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor());
-        data.writeInt32(pid);
-        data.writeInt64(clientId);
-
-        remote()->transact(REMOVE_CLIENT, data, &reply);
-    }
-
-    virtual bool reclaimResource(int callingPid, const Vector<MediaResource> &resources) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor());
-        data.writeInt32(callingPid);
-        writeToParcel(&data, resources);
-
-        bool ret = false;
-        status_t status = remote()->transact(RECLAIM_RESOURCE, data, &reply);
-        if (status == NO_ERROR) {
-            ret = (bool)reply.readInt32();
-        }
-        return ret;
-    }
-};
-
-IMPLEMENT_META_INTERFACE(ResourceManagerService, "android.media.IResourceManagerService");
-
-// ----------------------------------------------------------------------
-
-
-status_t BnResourceManagerService::onTransact(
-    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
-{
-    switch (code) {
-        case CONFIG: {
-            CHECK_INTERFACE(IResourceManagerService, data, reply);
-            Vector<MediaResourcePolicy> policies;
-            readFromParcel(data, &policies);
-            config(policies);
-            return NO_ERROR;
-        } break;
-
-        case ADD_RESOURCE: {
-            CHECK_INTERFACE(IResourceManagerService, data, reply);
-            int pid = data.readInt32();
-            int uid = data.readInt32();
-            int64_t clientId = data.readInt64();
-            sp<IResourceManagerClient> client(
-                    interface_cast<IResourceManagerClient>(data.readStrongBinder()));
-            if (client == NULL) {
-                return NO_ERROR;
-            }
-            Vector<MediaResource> resources;
-            readFromParcel(data, &resources);
-            addResource(pid, uid, clientId, client, resources);
-            return NO_ERROR;
-        } break;
-
-        case REMOVE_RESOURCE: {
-            CHECK_INTERFACE(IResourceManagerService, data, reply);
-            int pid = data.readInt32();
-            int64_t clientId = data.readInt64();
-            Vector<MediaResource> resources;
-            readFromParcel(data, &resources);
-            removeResource(pid, clientId, resources);
-            return NO_ERROR;
-        } break;
-
-        case REMOVE_CLIENT: {
-            CHECK_INTERFACE(IResourceManagerService, data, reply);
-            int pid = data.readInt32();
-            int64_t clientId = data.readInt64();
-            removeClient(pid, clientId);
-            return NO_ERROR;
-        } break;
-
-        case RECLAIM_RESOURCE: {
-            CHECK_INTERFACE(IResourceManagerService, data, reply);
-            int callingPid = data.readInt32();
-            Vector<MediaResource> resources;
-            readFromParcel(data, &resources);
-            bool ret = reclaimResource(callingPid, resources);
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
deleted file mode 100644
index 0d3c1ba..0000000
--- a/media/libmedia/JetPlayer.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 2008 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 "JetPlayer-C"
-
-#include <utils/Log.h>
-#include <media/JetPlayer.h>
-
-
-namespace android
-{
-
-static const int MIX_NUM_BUFFERS = 4;
-static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
-
-//-------------------------------------------------------------------------------------------------
-JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
-        mEventCallback(NULL),
-        mJavaJetPlayerRef(javaJetPlayer),
-        mTid(-1),
-        mRender(false),
-        mPaused(false),
-        mMaxTracks(maxTracks),
-        mEasData(NULL),
-        mIoWrapper(NULL),
-        mTrackBufferSize(trackBufferSize)
-{
-    ALOGV("JetPlayer constructor");
-    mPreviousJetStatus.currentUserID = -1;
-    mPreviousJetStatus.segmentRepeatCount = -1;
-    mPreviousJetStatus.numQueuedSegments = -1;
-    mPreviousJetStatus.paused = true;
-}
-
-//-------------------------------------------------------------------------------------------------
-JetPlayer::~JetPlayer()
-{
-    ALOGV("~JetPlayer");
-    release();
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::init()
-{
-    //Mutex::Autolock lock(&mMutex);
-
-    EAS_RESULT result;
-
-    // retrieve the EAS library settings
-    if (pLibConfig == NULL)
-        pLibConfig = EAS_Config();
-    if (pLibConfig == NULL) {
-        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
-        return EAS_FAILURE;
-    }
-
-    // init the EAS library
-    result = EAS_Init(&mEasData);
-    if (result != EAS_SUCCESS) {
-        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
-        mState = EAS_STATE_ERROR;
-        return result;
-    }
-    // init the JET library with the default app event controller range
-    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
-    if (result != EAS_SUCCESS) {
-        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
-        mState = EAS_STATE_ERROR;
-        return result;
-    }
-
-    // create the output AudioTrack
-    mAudioTrack = new AudioTrack();
-    status_t status = mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
-            pLibConfig->sampleRate,
-            AUDIO_FORMAT_PCM_16_BIT,
-            audio_channel_out_mask_from_count(pLibConfig->numChannels),
-            (size_t) mTrackBufferSize,
-            AUDIO_OUTPUT_FLAG_NONE);
-    if (status != OK) {
-        ALOGE("JetPlayer::init(): Error initializing JET library; AudioTrack error %d", status);
-        mAudioTrack.clear();
-        mState = EAS_STATE_ERROR;
-        return EAS_FAILURE;
-    }
-
-    // create render and playback thread
-    {
-        Mutex::Autolock l(mMutex);
-        ALOGV("JetPlayer::init(): trying to start render thread");
-        mThread = new JetPlayerThread(this);
-        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
-        mCondition.wait(mMutex);
-    }
-    if (mTid > 0) {
-        // render thread started, we're ready
-        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
-        mState = EAS_STATE_READY;
-    } else {
-        ALOGE("JetPlayer::init(): failed to start render thread.");
-        mState = EAS_STATE_ERROR;
-        return EAS_FAILURE;
-    }
-
-    return EAS_SUCCESS;
-}
-
-void JetPlayer::setEventCallback(jetevent_callback eventCallback)
-{
-    Mutex::Autolock l(mMutex);
-    mEventCallback = eventCallback;
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::release()
-{
-    ALOGV("JetPlayer::release()");
-    Mutex::Autolock lock(mMutex);
-    mPaused = true;
-    mRender = false;
-    if (mEasData) {
-        JET_Pause(mEasData);
-        JET_CloseFile(mEasData);
-        JET_Shutdown(mEasData);
-        EAS_Shutdown(mEasData);
-    }
-    delete mIoWrapper;
-    mIoWrapper = NULL;
-    if (mAudioTrack != 0) {
-        mAudioTrack->stop();
-        mAudioTrack->flush();
-        mAudioTrack.clear();
-    }
-    if (mAudioBuffer) {
-        delete mAudioBuffer;
-        mAudioBuffer = NULL;
-    }
-    mEasData = NULL;
-
-    return EAS_SUCCESS;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::render() {
-    EAS_RESULT result = EAS_FAILURE;
-    EAS_I32 count;
-    int temp;
-    bool audioStarted = false;
-
-    ALOGV("JetPlayer::render(): entering");
-
-    // allocate render buffer
-    mAudioBuffer =
-        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
-
-    // signal main thread that we started
-    {
-        Mutex::Autolock l(mMutex);
-        mTid = gettid();
-        ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
-        mCondition.signal();
-    }
-
-    while (1) {
-
-        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
-
-        if (mEasData == NULL) {
-            mMutex.unlock();
-            ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
-            goto threadExit;
-        }
-
-        // nothing to render, wait for client thread to wake us up
-        while (!mRender)
-        {
-            ALOGV("JetPlayer::render(): signal wait");
-            if (audioStarted) {
-                mAudioTrack->pause();
-                // we have to restart the playback once we start rendering again
-                audioStarted = false;
-            }
-            mCondition.wait(mMutex);
-            ALOGV("JetPlayer::render(): signal rx'd");
-        }
-
-        // render midi data into the input buffer
-        int num_output = 0;
-        EAS_PCM* p = mAudioBuffer;
-        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
-            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
-            if (result != EAS_SUCCESS) {
-                ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
-            }
-            p += count * pLibConfig->numChannels;
-            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
-
-            // send events that were generated (if any) to the event callback
-            fireEventsFromJetQueue();
-        }
-
-        // update playback state
-        //ALOGV("JetPlayer::render(): updating state");
-        JET_Status(mEasData, &mJetStatus);
-        fireUpdateOnStatusChange();
-        mPaused = mJetStatus.paused;
-
-        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
-
-        // check audio output track
-        if (mAudioTrack == NULL) {
-            ALOGE("JetPlayer::render(): output AudioTrack was not created");
-            goto threadExit;
-        }
-
-        // Write data to the audio hardware
-        //ALOGV("JetPlayer::render(): writing to audio output");
-        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
-            ALOGE("JetPlayer::render(): Error in writing:%d",temp);
-            return temp;
-        }
-
-        // start audio output if necessary
-        if (!audioStarted) {
-            ALOGV("JetPlayer::render(): starting audio playback");
-            mAudioTrack->start();
-            audioStarted = true;
-        }
-
-    }//while (1)
-
-threadExit:
-    if (mAudioTrack != NULL) {
-        mAudioTrack->stop();
-        mAudioTrack->flush();
-    }
-    delete [] mAudioBuffer;
-    mAudioBuffer = NULL;
-    mMutex.lock();
-    mTid = -1;
-    mCondition.signal();
-    mMutex.unlock();
-    return result;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-// fire up an update if any of the status fields has changed
-// precondition: mMutex locked
-void JetPlayer::fireUpdateOnStatusChange()
-{
-    if ( (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
-       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
-        if (mEventCallback)  {
-            mEventCallback(
-                JetPlayer::JET_USERID_UPDATE,
-                mJetStatus.currentUserID,
-                mJetStatus.segmentRepeatCount,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
-        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
-    }
-
-    if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
-        if (mEventCallback)  {
-            mEventCallback(
-                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
-                mJetStatus.numQueuedSegments,
-                -1,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
-    }
-
-    if (mJetStatus.paused != mPreviousJetStatus.paused) {
-        if (mEventCallback)  {
-            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
-                mJetStatus.paused,
-                -1,
-                mJavaJetPlayerRef);
-        }
-        mPreviousJetStatus.paused = mJetStatus.paused;
-    }
-
-}
-
-
-//-------------------------------------------------------------------------------------------------
-// fire up all the JET events in the JET engine queue (until the queue is empty)
-// precondition: mMutex locked
-void JetPlayer::fireEventsFromJetQueue()
-{
-    if (!mEventCallback) {
-        // no callback, just empty the event queue
-        while (JET_GetEvent(mEasData, NULL, NULL)) { }
-        return;
-    }
-
-    EAS_U32 rawEvent;
-    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
-        mEventCallback(
-            JetPlayer::JET_EVENT,
-            rawEvent,
-            -1,
-            mJavaJetPlayerRef);
-    }
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::loadFromFile(const char* path)
-{
-    ALOGV("JetPlayer::loadFromFile(): path=%s", path);
-
-    Mutex::Autolock lock(mMutex);
-
-    delete mIoWrapper;
-    mIoWrapper = new MidiIoWrapper(path);
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
-    if (result != EAS_SUCCESS)
-        mState = EAS_STATE_ERROR;
-    else
-        mState = EAS_STATE_OPEN;
-    return( result );
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
-{
-    ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
-
-    Mutex::Autolock lock(mMutex);
-
-    delete mIoWrapper;
-    mIoWrapper = new MidiIoWrapper(fd, offset, length);
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
-    if (result != EAS_SUCCESS)
-        mState = EAS_STATE_ERROR;
-    else
-        mState = EAS_STATE_OPEN;
-    return( result );
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::closeFile()
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_CloseFile(mEasData);
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::play()
-{
-    ALOGV("JetPlayer::play(): entering");
-    Mutex::Autolock lock(mMutex);
-
-    EAS_RESULT result = JET_Play(mEasData);
-
-    mPaused = false;
-    mRender = true;
-
-    JET_Status(mEasData, &mJetStatus);
-    this->dumpJetStatus(&mJetStatus);
-
-    fireUpdateOnStatusChange();
-
-    // wake up render thread
-    ALOGV("JetPlayer::play(): wakeup render thread");
-    mCondition.signal();
-
-    return result;
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::pause()
-{
-    Mutex::Autolock lock(mMutex);
-    mPaused = true;
-    EAS_RESULT result = JET_Pause(mEasData);
-
-    mRender = false;
-
-    JET_Status(mEasData, &mJetStatus);
-    this->dumpJetStatus(&mJetStatus);
-    fireUpdateOnStatusChange();
-
-
-    return result;
-}
-
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
-        EAS_U32 muteFlags, EAS_U8 userID)
-{
-    ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
-        segmentNum, libNum, repeatCount, transpose);
-    Mutex::Autolock lock(mMutex);
-    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
-            userID);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_SetMuteFlags(mEasData, muteFlags, sync);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
-{
-    Mutex::Autolock lock(mMutex);
-    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::triggerClip(int clipId)
-{
-    ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
-    Mutex::Autolock lock(mMutex);
-    return JET_TriggerClip(mEasData, clipId);
-}
-
-//-------------------------------------------------------------------------------------------------
-int JetPlayer::clearQueue()
-{
-    ALOGV("JetPlayer::clearQueue");
-    Mutex::Autolock lock(mMutex);
-    return JET_Clear_Queue(mEasData);
-}
-
-//-------------------------------------------------------------------------------------------------
-void JetPlayer::dump()
-{
-}
-
-void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
-{
-    if (pJetStatus!=NULL)
-        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
-                "paused=%d",
-                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
-                pJetStatus->numQueuedSegments, pJetStatus->paused);
-    else
-        ALOGE(">> JET player status is NULL");
-}
-
-
-} // end namespace android
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 98c5497..637322f 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -29,9 +29,55 @@
 #include <OMX_Video.h>
 #include <sys/stat.h>
 
+#include <array>
+#include <string>
+#include <vector>
+
 namespace android {
 
-constexpr char const * const MediaProfiles::xmlFiles[];
+namespace /* unnamed */ {
+
+// Returns a list of possible paths for the media_profiles XML file.
+std::array<char const*, 5> const& getXmlPaths() {
+    static std::array<std::string const, 5> const paths =
+        []() -> decltype(paths) {
+            // Directories for XML file that will be searched (in this order).
+            constexpr std::array<char const*, 4> searchDirs = {
+                "product/etc/",
+                "odm/etc/",
+                "vendor/etc/",
+                "system/etc/",
+            };
+
+            // The file name may contain a variant if the vendor property
+            // ro.vendor.media_profiles_xml_variant is set.
+            char variant[PROPERTY_VALUE_MAX];
+            property_get("ro.media.xml_variant.profiles",
+                         variant,
+                         "_V1_0");
+
+            std::string fileName =
+                std::string("media_profiles") + variant + ".xml";
+
+            return { searchDirs[0] + fileName,
+                     searchDirs[1] + fileName,
+                     searchDirs[2] + fileName,
+                     searchDirs[3] + fileName,
+                     "system/etc/media_profiles_V1_0.xml" // System fallback
+                   };
+        }();
+    static std::array<char const*, 5> const cPaths = {
+            paths[0].data(),
+            paths[1].data(),
+            paths[2].data(),
+            paths[3].data(),
+            paths[4].data()
+        };
+    return cPaths;
+}
+
+} // unnamed namespace
+
 Mutex MediaProfiles::sLock;
 bool MediaProfiles::sIsInitialized = false;
 MediaProfiles *MediaProfiles::sInstance = NULL;
@@ -48,7 +94,7 @@
     {"amrwb",  AUDIO_ENCODER_AMR_WB},
     {"aac",    AUDIO_ENCODER_AAC},
     {"heaac",  AUDIO_ENCODER_HE_AAC},
-    {"aaceld", AUDIO_ENCODER_AAC_ELD}, 
+    {"aaceld", AUDIO_ENCODER_AAC_ELD},
     {"opus",   AUDIO_ENCODER_OPUS}
 };
 
@@ -610,7 +656,7 @@
         char value[PROPERTY_VALUE_MAX];
         if (property_get("media.settings.xml", value, NULL) <= 0) {
             const char* xmlFile = nullptr;
-            for (auto const& f : xmlFiles) {
+            for (auto const& f : getXmlPaths()) {
                 if (checkXmlFile(f)) {
                     xmlFile = f;
                     break;
diff --git a/media/libmedia/MediaResource.cpp b/media/libmedia/MediaResource.cpp
index e636a50..0936a99 100644
--- a/media/libmedia/MediaResource.cpp
+++ b/media/libmedia/MediaResource.cpp
@@ -19,47 +19,73 @@
 #include <utils/Log.h>
 #include <media/MediaResource.h>
 
+#include <vector>
+
 namespace android {
 
-MediaResource::MediaResource()
-        : mType(kUnspecified),
-          mSubType(kUnspecifiedSubType),
-          mValue(0) {}
-
-MediaResource::MediaResource(Type type, uint64_t value)
-        : mType(type),
-          mSubType(kUnspecifiedSubType),
-          mValue(value) {}
-
-MediaResource::MediaResource(Type type, SubType subType, uint64_t value)
-        : mType(type),
-          mSubType(subType),
-          mValue(value) {}
-
-void MediaResource::readFromParcel(const Parcel &parcel) {
-    mType = static_cast<Type>(parcel.readInt32());
-    mSubType = static_cast<SubType>(parcel.readInt32());
-    mValue = parcel.readUint64();
+MediaResource::MediaResource(Type type, int64_t value) {
+    this->type = type;
+    this->subType = SubType::kUnspecifiedSubType;
+    this->value = value;
 }
 
-void MediaResource::writeToParcel(Parcel *parcel) const {
-    parcel->writeInt32(static_cast<int32_t>(mType));
-    parcel->writeInt32(static_cast<int32_t>(mSubType));
-    parcel->writeUint64(mValue);
+MediaResource::MediaResource(Type type, SubType subType, int64_t value) {
+    this->type = type;
+    this->subType = subType;
+    this->value = value;
 }
 
-String8 MediaResource::toString() const {
+MediaResource::MediaResource(Type type, const std::vector<int8_t> &id, int64_t value) {
+    this->type = type;
+    this->subType = SubType::kUnspecifiedSubType;
+    this->id = id;
+    this->value = value;
+}
+
+//static
+MediaResource MediaResource::CodecResource(bool secure, bool video) {
+    return MediaResource(
+            secure ? Type::kSecureCodec : Type::kNonSecureCodec,
+            video ? SubType::kVideoCodec : SubType::kAudioCodec,
+            1);
+}
+
+//static
+MediaResource MediaResource::GraphicMemoryResource(int64_t value) {
+    return MediaResource(Type::kGraphicMemory, value);
+}
+
+//static
+MediaResource MediaResource::CpuBoostResource() {
+    return MediaResource(Type::kCpuBoost, 1);
+}
+
+//static
+MediaResource MediaResource::VideoBatteryResource() {
+    return MediaResource(Type::kBattery, SubType::kVideoCodec, 1);
+}
+
+//static
+MediaResource MediaResource::DrmSessionResource(const std::vector<int8_t> &id, int64_t value) {
+    return MediaResource(Type::kDrmSession, id, value);
+}
+
+static String8 bytesToHexString(const std::vector<int8_t> &bytes) {
     String8 str;
-    str.appendFormat("%s/%s:%llu", asString(mType), asString(mSubType), (unsigned long long)mValue);
+    for (auto &b : bytes) {
+        str.appendFormat("%02x", b);
+    }
     return str;
 }
 
-bool MediaResource::operator==(const MediaResource &other) const {
-    return (other.mType == mType) && (other.mSubType == mSubType) && (other.mValue == mValue);
-}
+String8 toString(const MediaResourceParcel& resource) {
+    String8 str;
 
-bool MediaResource::operator!=(const MediaResource &other) const {
-    return !(*this == other);
+    str.appendFormat("%s/%s:[%s]:%lld",
+            asString(resource.type), asString(resource.subType),
+            bytesToHexString(resource.id).c_str(),
+            (long long)resource.value);
+    return str;
 }
 
 }; // namespace android
diff --git a/media/libmedia/MediaResourcePolicy.cpp b/media/libmedia/MediaResourcePolicy.cpp
index 5210825..afa971d 100644
--- a/media/libmedia/MediaResourcePolicy.cpp
+++ b/media/libmedia/MediaResourcePolicy.cpp
@@ -16,33 +16,32 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaResourcePolicy"
-#include <utils/Log.h>
+
+#include <aidl/android/media/IResourceManagerService.h>
 #include <media/MediaResourcePolicy.h>
+#include <utils/Log.h>
 
 namespace android {
 
-const char kPolicySupportsMultipleSecureCodecs[] = "supports-multiple-secure-codecs";
-const char kPolicySupportsSecureWithNonSecureCodec[] = "supports-secure-with-non-secure-codec";
-
-MediaResourcePolicy::MediaResourcePolicy() {}
-
-MediaResourcePolicy::MediaResourcePolicy(String8 type, String8 value)
-        : mType(type),
-          mValue(value) {}
-
-void MediaResourcePolicy::readFromParcel(const Parcel &parcel) {
-    mType = parcel.readString8();
-    mValue = parcel.readString8();
+using aidl::android::media::IResourceManagerService;
+//static
+const char* MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs() {
+    return IResourceManagerService::kPolicySupportsMultipleSecureCodecs;
+}
+//static
+const char* MediaResourcePolicy::kPolicySupportsSecureWithNonSecureCodec() {
+    return IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec;
 }
 
-void MediaResourcePolicy::writeToParcel(Parcel *parcel) const {
-    parcel->writeString8(mType);
-    parcel->writeString8(mValue);
+MediaResourcePolicy::MediaResourcePolicy(
+        const std::string& type, const std::string& value) {
+    this->type = type;
+    this->value = value;
 }
 
-String8 MediaResourcePolicy::toString() const {
+String8 toString(const MediaResourcePolicyParcel &policy) {
     String8 str;
-    str.appendFormat("%s:%s", mType.string(), mValue.string());
+    str.appendFormat("%s:%s", policy.type.c_str(), policy.value.c_str());
     return str;
 }
 
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
deleted file mode 100644
index 31972fa..0000000
--- a/media/libmedia/MediaUtils.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 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_TAG "MediaUtils"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <cutils/properties.h>
-#include <sys/resource.h>
-#include <unistd.h>
-
-#include <bionic_malloc.h>
-
-#include "MediaUtils.h"
-
-extern "C" void __scudo_set_rss_limit(size_t, int) __attribute__((weak));
-
-namespace android {
-
-void limitProcessMemory(const char *property, size_t numberOfBytes,
-                        size_t percentageOfTotalMem) {
-    long pageSize = sysconf(_SC_PAGESIZE);
-    long numPages = sysconf(_SC_PHYS_PAGES);
-    size_t maxMem = SIZE_MAX;
-
-    if (pageSize > 0 && numPages > 0) {
-        if (size_t(numPages) < SIZE_MAX / size_t(pageSize)) {
-            maxMem = size_t(numPages) * size_t(pageSize);
-        }
-        ALOGV("physMem: %zu", maxMem);
-        if (percentageOfTotalMem > 100) {
-            ALOGW("requested %zu%% of total memory, using 100%%", percentageOfTotalMem);
-            percentageOfTotalMem = 100;
-        }
-        maxMem = maxMem / 100 * percentageOfTotalMem;
-        if (numberOfBytes < maxMem) {
-            maxMem = numberOfBytes;
-        }
-        ALOGV("requested limit: %zu", maxMem);
-    } else {
-        ALOGW("couldn't determine total RAM");
-    }
-
-    int64_t propVal = property_get_int64(property, maxMem);
-    if (propVal > 0 && uint64_t(propVal) <= SIZE_MAX) {
-        maxMem = propVal;
-    }
-
-    // If Scudo is in use, enforce the hard RSS limit (in MB).
-    if (maxMem != SIZE_MAX && &__scudo_set_rss_limit != 0) {
-      __scudo_set_rss_limit(maxMem >> 20, 1);
-      ALOGV("Scudo hard RSS limit set to %zu MB", maxMem >> 20);
-      return;
-    }
-
-    if (!android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &maxMem,
-                         sizeof(maxMem))) {
-      ALOGW("couldn't set allocation limit");
-    }
-}
-
-} // namespace android
diff --git a/media/libmedia/MediaUtils.h b/media/libmedia/MediaUtils.h
deleted file mode 100644
index f80dd30..0000000
--- a/media/libmedia/MediaUtils.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 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 _MEDIA_UTILS_H
-#define _MEDIA_UTILS_H
-
-namespace android {
-
-/**
-   Limit the amount of memory a process can allocate using setrlimit(RLIMIT_AS).
-   The value to use will be read from the specified system property, or if the
-   property doesn't exist it will use the specified number of bytes or the
-   specified percentage of total memory, whichever is smaller.
-*/
-void limitProcessMemory(
-    const char *property,
-    size_t numberOfBytes,
-    size_t percentageOfTotalMem);
-
-}   // namespace android
-
-#endif  // _MEDIA_UTILS_H
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
deleted file mode 100644
index 7588e00..0000000
--- a/media/libmedia/MidiDeviceInfo.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 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_TAG "MidiDeviceInfo"
-
-#include <media/MidiDeviceInfo.h>
-
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-// The constant values need to be kept in sync with MidiDeviceInfo.java.
-// static
-const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
-const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
-const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
-const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
-const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
-
-String16 MidiDeviceInfo::getProperty(const char* propertyName) {
-    String16 value;
-    if (mProperties.getString(String16(propertyName), &value)) {
-        return value;
-    } else {
-        return String16();
-    }
-}
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    {                                                                    \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    }
-
-status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->writeInt32(mType));
-    RETURN_IF_FAILED(parcel->writeInt32(mId));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
-    RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
-    RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
-    RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    // This corresponds to "extra" properties written by Java code
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    return OK;
-}
-
-status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->readInt32(&mType));
-    RETURN_IF_FAILED(parcel->readInt32(&mId));
-    int32_t inputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
-    int32_t outputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
-    int32_t isPrivate;
-    RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
-    mIsPrivate = isPrivate == 1;
-    RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
-    // Ignore "extra" properties as they may contain Java Parcelables
-    return OK;
-}
-
-status_t MidiDeviceInfo::readStringVector(
-        const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
-    std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
-    status_t result = parcel->readString16Vector(&v);
-    if (result != OK) return result;
-    vectorPtr->clear();
-    if (v.get() != nullptr) {
-        for (const auto& iter : *v) {
-            if (iter.get() != nullptr) {
-                vectorPtr->push_back(*iter);
-            } else {
-                vectorPtr->push_back(String16());
-            }
-        }
-    } else {
-        vectorPtr->resize(defaultLength);
-    }
-    return OK;
-}
-
-status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
-    std::vector<String16> v;
-    for (size_t i = 0; i < vector.size(); ++i) {
-        v.push_back(vector[i]);
-    }
-    return parcel->writeString16Vector(v);
-}
-
-// Vector does not define operator==
-static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
-    if (lhs.size() != rhs.size()) return false;
-    for (size_t i = 0; i < lhs.size(); ++i) {
-        if (lhs[i] != rhs[i]) return false;
-    }
-    return true;
-}
-
-bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-    return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
-            areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
-            areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
-            lhs.mProperties == rhs.mProperties &&
-            lhs.mIsPrivate == rhs.mIsPrivate);
-}
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index d8ef9cf..e71ea2c 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -17,7 +17,6 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MidiIoWrapper"
 #include <utils/Log.h>
-#include <utils/RefBase.h>
 
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -50,7 +49,7 @@
     mDataSource = nullptr;
 }
 
-class DataSourceUnwrapper : public DataSourceBase {
+class MidiIoWrapper::DataSourceUnwrapper {
 
 public:
     explicit DataSourceUnwrapper(CDataSource *csource) {
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
deleted file mode 100644
index c150407..0000000
--- a/media/libmedia/NdkWrapper.cpp
+++ /dev/null
@@ -1,1290 +0,0 @@
-/*
- * Copyright 2017, 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 "NdkWrapper"
-
-#include <media/NdkWrapper.h>
-
-#include <android/native_window.h>
-#include <log/log.h>
-#include <media/NdkMediaCodec.h>
-#include <media/NdkMediaCrypto.h>
-#include <media/NdkMediaDrm.h>
-#include <media/NdkMediaFormat.h>
-#include <media/NdkMediaExtractor.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <utils/Errors.h>
-
-#include "NdkMediaDataSourceCallbacksPriv.h"
-
-namespace android {
-
-static const size_t kAESBlockSize = 16;  // AES_BLOCK_SIZE
-
-static const char *AMediaFormatKeyGroupInt32[] = {
-    AMEDIAFORMAT_KEY_AAC_DRC_ATTENUATION_FACTOR,
-    AMEDIAFORMAT_KEY_AAC_DRC_BOOST_FACTOR,
-    AMEDIAFORMAT_KEY_AAC_DRC_HEAVY_COMPRESSION,
-    AMEDIAFORMAT_KEY_AAC_DRC_TARGET_REFERENCE_LEVEL,
-    AMEDIAFORMAT_KEY_AAC_ENCODED_TARGET_LEVEL,
-    AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_AAC_PROFILE,
-    AMEDIAFORMAT_KEY_AAC_SBR_MODE,
-    AMEDIAFORMAT_KEY_AUDIO_SESSION_ID,
-    AMEDIAFORMAT_KEY_BITRATE_MODE,
-    AMEDIAFORMAT_KEY_BIT_RATE,
-    AMEDIAFORMAT_KEY_CAPTURE_RATE,
-    AMEDIAFORMAT_KEY_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_CHANNEL_MASK,
-    AMEDIAFORMAT_KEY_COLOR_FORMAT,
-    AMEDIAFORMAT_KEY_COLOR_RANGE,
-    AMEDIAFORMAT_KEY_COLOR_STANDARD,
-    AMEDIAFORMAT_KEY_COLOR_TRANSFER,
-    AMEDIAFORMAT_KEY_COMPLEXITY,
-    AMEDIAFORMAT_KEY_CREATE_INPUT_SURFACE_SUSPENDED,
-    AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE,
-    AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK,
-    AMEDIAFORMAT_KEY_CRYPTO_MODE,
-    AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK,
-    AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL,
-    AMEDIAFORMAT_KEY_GRID_COLUMNS,
-    AMEDIAFORMAT_KEY_GRID_ROWS,
-    AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT,
-    AMEDIAFORMAT_KEY_HEIGHT,
-    AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD,
-    AMEDIAFORMAT_KEY_IS_ADTS,
-    AMEDIAFORMAT_KEY_IS_AUTOSELECT,
-    AMEDIAFORMAT_KEY_IS_DEFAULT,
-    AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE,
-    AMEDIAFORMAT_KEY_LATENCY,
-    AMEDIAFORMAT_KEY_LEVEL,
-    AMEDIAFORMAT_KEY_MAX_HEIGHT,
-    AMEDIAFORMAT_KEY_MAX_INPUT_SIZE,
-    AMEDIAFORMAT_KEY_MAX_WIDTH,
-    AMEDIAFORMAT_KEY_PCM_ENCODING,
-    AMEDIAFORMAT_KEY_PRIORITY,
-    AMEDIAFORMAT_KEY_PROFILE,
-    AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP,
-    AMEDIAFORMAT_KEY_ROTATION,
-    AMEDIAFORMAT_KEY_SAMPLE_RATE,
-    AMEDIAFORMAT_KEY_SLICE_HEIGHT,
-    AMEDIAFORMAT_KEY_STRIDE,
-    AMEDIAFORMAT_KEY_TRACK_ID,
-    AMEDIAFORMAT_KEY_WIDTH,
-    AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
-    AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
-    AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID,
-    AMEDIAFORMAT_KEY_TILE_HEIGHT,
-    AMEDIAFORMAT_KEY_TILE_WIDTH,
-    AMEDIAFORMAT_KEY_TRACK_INDEX,
-};
-
-static const char *AMediaFormatKeyGroupInt64[] = {
-    AMEDIAFORMAT_KEY_DURATION,
-    AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER,
-    AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER,
-    AMEDIAFORMAT_KEY_TIME_US,
-};
-
-static const char *AMediaFormatKeyGroupString[] = {
-    AMEDIAFORMAT_KEY_LANGUAGE,
-    AMEDIAFORMAT_KEY_MIME,
-    AMEDIAFORMAT_KEY_TEMPORAL_LAYERING,
-};
-
-static const char *AMediaFormatKeyGroupBuffer[] = {
-    AMEDIAFORMAT_KEY_CRYPTO_IV,
-    AMEDIAFORMAT_KEY_CRYPTO_KEY,
-    AMEDIAFORMAT_KEY_HDR_STATIC_INFO,
-    AMEDIAFORMAT_KEY_SEI,
-    AMEDIAFORMAT_KEY_MPEG_USER_DATA,
-};
-
-static const char *AMediaFormatKeyGroupCsd[] = {
-    AMEDIAFORMAT_KEY_CSD_0,
-    AMEDIAFORMAT_KEY_CSD_1,
-    AMEDIAFORMAT_KEY_CSD_2,
-};
-
-static const char *AMediaFormatKeyGroupRect[] = {
-    AMEDIAFORMAT_KEY_DISPLAY_CROP,
-};
-
-static const char *AMediaFormatKeyGroupFloatInt32[] = {
-    AMEDIAFORMAT_KEY_FRAME_RATE,
-    AMEDIAFORMAT_KEY_I_FRAME_INTERVAL,
-    AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER,
-    AMEDIAFORMAT_KEY_OPERATING_RATE,
-};
-
-static status_t translateErrorCode(media_status_t err) {
-    if (err == AMEDIA_OK) {
-        return OK;
-    } else if (err == AMEDIA_ERROR_END_OF_STREAM) {
-        return ERROR_END_OF_STREAM;
-    } else if (err == AMEDIA_ERROR_IO) {
-        return ERROR_IO;
-    } else if (err == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
-        return -EAGAIN;
-    }
-
-    ALOGE("ndk error code: %d", err);
-    return UNKNOWN_ERROR;
-}
-
-static int32_t translateActionCode(int32_t actionCode) {
-    if (AMediaCodecActionCode_isTransient(actionCode)) {
-        return ACTION_CODE_TRANSIENT;
-    } else if (AMediaCodecActionCode_isRecoverable(actionCode)) {
-        return ACTION_CODE_RECOVERABLE;
-    }
-    return ACTION_CODE_FATAL;
-}
-
-static CryptoPlugin::Mode translateToCryptoPluginMode(cryptoinfo_mode_t mode) {
-    CryptoPlugin::Mode ret = CryptoPlugin::kMode_Unencrypted;
-    switch (mode) {
-        case AMEDIACODECRYPTOINFO_MODE_AES_CTR: {
-            ret = CryptoPlugin::kMode_AES_CTR;
-            break;
-        }
-
-        case AMEDIACODECRYPTOINFO_MODE_AES_WV: {
-            ret = CryptoPlugin::kMode_AES_WV;
-            break;
-        }
-
-        case AMEDIACODECRYPTOINFO_MODE_AES_CBC: {
-            ret = CryptoPlugin::kMode_AES_CBC;
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-static cryptoinfo_mode_t translateToCryptoInfoMode(CryptoPlugin::Mode mode) {
-    cryptoinfo_mode_t ret = AMEDIACODECRYPTOINFO_MODE_CLEAR;
-    switch (mode) {
-        case CryptoPlugin::kMode_AES_CTR: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_CTR;
-            break;
-        }
-
-        case CryptoPlugin::kMode_AES_WV: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_WV;
-            break;
-        }
-
-        case CryptoPlugin::kMode_AES_CBC: {
-            ret = AMEDIACODECRYPTOINFO_MODE_AES_CBC;
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    return ret;
-}
-
-//////////// AMediaFormatWrapper
-// static
-sp<AMediaFormatWrapper> AMediaFormatWrapper::Create(const sp<AMessage> &message) {
-    sp<AMediaFormatWrapper> aMediaFormat = new AMediaFormatWrapper();
-
-    for (size_t i = 0; i < message->countEntries(); ++i) {
-        AMessage::Type valueType;
-        const char *key = message->getEntryNameAt(i, &valueType);
-
-        switch (valueType) {
-            case AMessage::kTypeInt32: {
-                int32_t val;
-                if (!message->findInt32(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setInt32(key, val);
-                break;
-            }
-
-            case AMessage::kTypeInt64: {
-                int64_t val;
-                if (!message->findInt64(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setInt64(key, val);
-                break;
-            }
-
-            case AMessage::kTypeFloat: {
-                float val;
-                if (!message->findFloat(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setFloat(key, val);
-                break;
-            }
-
-            case AMessage::kTypeDouble: {
-                double val;
-                if (!message->findDouble(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setDouble(key, val);
-                break;
-            }
-
-            case AMessage::kTypeSize: {
-                size_t val;
-                if (!message->findSize(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setSize(key, val);
-                break;
-            }
-
-            case AMessage::kTypeRect: {
-                int32_t left, top, right, bottom;
-                if (!message->findRect(key, &left, &top, &right, &bottom)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setRect(key, left, top, right, bottom);
-                break;
-            }
-
-            case AMessage::kTypeString: {
-                AString val;
-                if (!message->findString(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setString(key, val);
-                break;
-            }
-
-            case AMessage::kTypeBuffer: {
-                sp<ABuffer> val;
-                if (!message->findBuffer(key, &val)) {
-                    ALOGE("AMediaFormatWrapper::Create: error at item %zu", i);
-                    continue;
-                }
-                aMediaFormat->setBuffer(key, val->data(), val->size());
-                break;
-            }
-
-            default: {
-                break;
-            }
-        }
-    }
-
-    return aMediaFormat;
-}
-
-AMediaFormatWrapper::AMediaFormatWrapper() {
-    mAMediaFormat = AMediaFormat_new();
-}
-
-AMediaFormatWrapper::AMediaFormatWrapper(AMediaFormat *aMediaFormat)
-    : mAMediaFormat(aMediaFormat) {
-}
-
-AMediaFormatWrapper::~AMediaFormatWrapper() {
-    release();
-}
-
-status_t AMediaFormatWrapper::release() {
-    if (mAMediaFormat != NULL) {
-        media_status_t err = AMediaFormat_delete(mAMediaFormat);
-        mAMediaFormat = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaFormat *AMediaFormatWrapper::getAMediaFormat() const {
-    return mAMediaFormat;
-}
-
-sp<AMessage> AMediaFormatWrapper::toAMessage() const {
-  sp<AMessage> msg;
-  writeToAMessage(msg);
-  return msg;
-}
-
-void AMediaFormatWrapper::writeToAMessage(sp<AMessage> &msg) const {
-    if (mAMediaFormat == NULL) {
-        msg = NULL;
-    }
-
-    if (msg == NULL) {
-        msg = new AMessage;
-    }
-    for (auto& key : AMediaFormatKeyGroupInt32) {
-        int32_t val;
-        if (getInt32(key, &val)) {
-            msg->setInt32(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupInt64) {
-        int64_t val;
-        if (getInt64(key, &val)) {
-            msg->setInt64(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupString) {
-        AString val;
-        if (getString(key, &val)) {
-            msg->setString(key, val);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupBuffer) {
-        void *data;
-        size_t size;
-        if (getBuffer(key, &data, &size)) {
-            sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
-            msg->setBuffer(key, buffer);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupCsd) {
-        void *data;
-        size_t size;
-        if (getBuffer(key, &data, &size)) {
-            sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
-            buffer->meta()->setInt32(AMEDIAFORMAT_KEY_CSD, 1);
-            buffer->meta()->setInt64(AMEDIAFORMAT_KEY_TIME_US, 0);
-            msg->setBuffer(key, buffer);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupRect) {
-        int32_t left, top, right, bottom;
-        if (getRect(key, &left, &top, &right, &bottom)) {
-            msg->setRect(key, left, top, right, bottom);
-        }
-    }
-    for (auto& key : AMediaFormatKeyGroupFloatInt32) {
-        float valFloat;
-        if (getFloat(key, &valFloat)) {
-            msg->setFloat(key, valFloat);
-        } else {
-            int32_t valInt32;
-            if (getInt32(key, &valInt32)) {
-                msg->setFloat(key, (float)valInt32);
-            }
-        }
-    }
-}
-
-const char* AMediaFormatWrapper::toString() const {
-    if (mAMediaFormat == NULL) {
-        return NULL;
-    }
-    return AMediaFormat_toString(mAMediaFormat);
-}
-
-bool AMediaFormatWrapper::getInt32(const char *name, int32_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getInt32(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getInt64(const char *name, int64_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getInt64(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getFloat(const char *name, float *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getFloat(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getDouble(const char *name, double *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getDouble(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getSize(const char *name, size_t *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getSize(mAMediaFormat, name, out);
-}
-
-bool AMediaFormatWrapper::getRect(
-        const char *name, int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getRect(mAMediaFormat, name, left, top, right, bottom);
-}
-
-bool AMediaFormatWrapper::getBuffer(const char *name, void** data, size_t *outSize) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    return AMediaFormat_getBuffer(mAMediaFormat, name, data, outSize);
-}
-
-bool AMediaFormatWrapper::getString(const char *name, AString *out) const {
-    if (mAMediaFormat == NULL) {
-        return false;
-    }
-    const char *outChar = NULL;
-    bool ret = AMediaFormat_getString(mAMediaFormat, name, &outChar);
-    if (ret) {
-        *out = AString(outChar);
-    }
-    return ret;
-}
-
-void AMediaFormatWrapper::setInt32(const char* name, int32_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setInt32(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setInt64(const char* name, int64_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setInt64(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setFloat(const char* name, float value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setFloat(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setDouble(const char* name, double value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setDouble(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setSize(const char* name, size_t value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setSize(mAMediaFormat, name, value);
-    }
-}
-
-void AMediaFormatWrapper::setRect(
-        const char* name, int32_t left, int32_t top, int32_t right, int32_t bottom) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setRect(mAMediaFormat, name, left, top, right, bottom);
-    }
-}
-
-void AMediaFormatWrapper::setString(const char* name, const AString &value) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setString(mAMediaFormat, name, value.c_str());
-    }
-}
-
-void AMediaFormatWrapper::setBuffer(const char* name, void* data, size_t size) {
-    if (mAMediaFormat != NULL) {
-        AMediaFormat_setBuffer(mAMediaFormat, name, data, size);
-    }
-}
-
-
-//////////// ANativeWindowWrapper
-ANativeWindowWrapper::ANativeWindowWrapper(ANativeWindow *aNativeWindow)
-    : mANativeWindow(aNativeWindow) {
-    if (aNativeWindow != NULL) {
-        ANativeWindow_acquire(aNativeWindow);
-    }
-}
-
-ANativeWindowWrapper::~ANativeWindowWrapper() {
-    release();
-}
-
-status_t ANativeWindowWrapper::release() {
-    if (mANativeWindow != NULL) {
-        ANativeWindow_release(mANativeWindow);
-        mANativeWindow = NULL;
-    }
-    return OK;
-}
-
-ANativeWindow *ANativeWindowWrapper::getANativeWindow() const {
-    return mANativeWindow;
-}
-
-
-//////////// AMediaDrmWrapper
-AMediaDrmWrapper::AMediaDrmWrapper(const uint8_t uuid[16]) {
-    mAMediaDrm = AMediaDrm_createByUUID(uuid);
-}
-
-AMediaDrmWrapper::AMediaDrmWrapper(AMediaDrm *aMediaDrm)
-    : mAMediaDrm(aMediaDrm) {
-}
-
-AMediaDrmWrapper::~AMediaDrmWrapper() {
-    release();
-}
-
-status_t AMediaDrmWrapper::release() {
-    if (mAMediaDrm != NULL) {
-        AMediaDrm_release(mAMediaDrm);
-        mAMediaDrm = NULL;
-    }
-    return OK;
-}
-
-AMediaDrm *AMediaDrmWrapper::getAMediaDrm() const {
-    return mAMediaDrm;
-}
-
-// static
-bool AMediaDrmWrapper::isCryptoSchemeSupported(
-        const uint8_t uuid[16],
-        const char *mimeType) {
-    return AMediaDrm_isCryptoSchemeSupported(uuid, mimeType);
-}
-
-
-//////////// AMediaCryptoWrapper
-AMediaCryptoWrapper::AMediaCryptoWrapper(
-        const uint8_t uuid[16], const void *initData, size_t initDataSize) {
-    mAMediaCrypto = AMediaCrypto_new(uuid, initData, initDataSize);
-}
-
-AMediaCryptoWrapper::AMediaCryptoWrapper(AMediaCrypto *aMediaCrypto)
-    : mAMediaCrypto(aMediaCrypto) {
-}
-
-AMediaCryptoWrapper::~AMediaCryptoWrapper() {
-    release();
-}
-
-status_t AMediaCryptoWrapper::release() {
-    if (mAMediaCrypto != NULL) {
-        AMediaCrypto_delete(mAMediaCrypto);
-        mAMediaCrypto = NULL;
-    }
-    return OK;
-}
-
-AMediaCrypto *AMediaCryptoWrapper::getAMediaCrypto() const {
-    return mAMediaCrypto;
-}
-
-bool AMediaCryptoWrapper::isCryptoSchemeSupported(const uint8_t uuid[16]) {
-    if (mAMediaCrypto == NULL) {
-        return false;
-    }
-    return AMediaCrypto_isCryptoSchemeSupported(uuid);
-}
-
-bool AMediaCryptoWrapper::requiresSecureDecoderComponent(const char *mime) {
-    if (mAMediaCrypto == NULL) {
-        return false;
-    }
-    return AMediaCrypto_requiresSecureDecoderComponent(mime);
-}
-
-
-//////////// AMediaCodecCryptoInfoWrapper
-// static
-sp<AMediaCodecCryptoInfoWrapper> AMediaCodecCryptoInfoWrapper::Create(MetaDataBase &meta) {
-
-    uint32_t type;
-    const void *crypteddata;
-    size_t cryptedsize;
-
-    if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
-        return NULL;
-    }
-
-    int numSubSamples = cryptedsize / sizeof(size_t);
-
-    if (numSubSamples <= 0) {
-        ALOGE("Create: INVALID numSubSamples: %d", numSubSamples);
-        return NULL;
-    }
-
-    const void *cleardata;
-    size_t clearsize;
-    if (meta.findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
-        if (clearsize != cryptedsize) {
-            // The two must be of the same length.
-            ALOGE("Create: mismatch cryptedsize: %zu != clearsize: %zu", cryptedsize, clearsize);
-            return NULL;
-        }
-    }
-
-    const void *key;
-    size_t keysize;
-    if (meta.findData(kKeyCryptoKey, &type, &key, &keysize)) {
-        if (keysize != kAESBlockSize) {
-            // Keys must be 16 bytes in length.
-            ALOGE("Create: Keys must be %zu bytes in length: %zu", kAESBlockSize, keysize);
-            return NULL;
-        }
-    }
-
-    const void *iv;
-    size_t ivsize;
-    if (meta.findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
-        if (ivsize != kAESBlockSize) {
-            // IVs must be 16 bytes in length.
-            ALOGE("Create: IV must be %zu bytes in length: %zu", kAESBlockSize, ivsize);
-            return NULL;
-        }
-    }
-
-    int32_t mode;
-    if (!meta.findInt32(kKeyCryptoMode, &mode)) {
-        mode = CryptoPlugin::kMode_AES_CTR;
-    }
-
-    return new AMediaCodecCryptoInfoWrapper(
-            numSubSamples,
-            (uint8_t*) key,
-            (uint8_t*) iv,
-            (CryptoPlugin::Mode)mode,
-            (size_t*) cleardata,
-            (size_t*) crypteddata);
-}
-
-AMediaCodecCryptoInfoWrapper::AMediaCodecCryptoInfoWrapper(
-        int numsubsamples,
-        uint8_t key[16],
-        uint8_t iv[16],
-        CryptoPlugin::Mode mode,
-        size_t *clearbytes,
-        size_t *encryptedbytes) {
-    mAMediaCodecCryptoInfo =
-        AMediaCodecCryptoInfo_new(numsubsamples,
-                                  key,
-                                  iv,
-                                  translateToCryptoInfoMode(mode),
-                                  clearbytes,
-                                  encryptedbytes);
-}
-
-AMediaCodecCryptoInfoWrapper::AMediaCodecCryptoInfoWrapper(
-        AMediaCodecCryptoInfo *aMediaCodecCryptoInfo)
-    : mAMediaCodecCryptoInfo(aMediaCodecCryptoInfo) {
-}
-
-AMediaCodecCryptoInfoWrapper::~AMediaCodecCryptoInfoWrapper() {
-    release();
-}
-
-status_t AMediaCodecCryptoInfoWrapper::release() {
-    if (mAMediaCodecCryptoInfo != NULL) {
-        media_status_t err = AMediaCodecCryptoInfo_delete(mAMediaCodecCryptoInfo);
-        mAMediaCodecCryptoInfo = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaCodecCryptoInfo *AMediaCodecCryptoInfoWrapper::getAMediaCodecCryptoInfo() const {
-    return mAMediaCodecCryptoInfo;
-}
-
-void AMediaCodecCryptoInfoWrapper::setPattern(CryptoPlugin::Pattern *pattern) {
-    if (mAMediaCodecCryptoInfo == NULL || pattern == NULL) {
-        return;
-    }
-    cryptoinfo_pattern_t ndkPattern = {(int32_t)pattern->mEncryptBlocks,
-                                       (int32_t)pattern->mSkipBlocks };
-    return AMediaCodecCryptoInfo_setPattern(mAMediaCodecCryptoInfo, &ndkPattern);
-}
-
-size_t AMediaCodecCryptoInfoWrapper::getNumSubSamples() {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return 0;
-    }
-    return AMediaCodecCryptoInfo_getNumSubSamples(mAMediaCodecCryptoInfo);
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getKey(uint8_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getKey(mAMediaCodecCryptoInfo, dst));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getIV(uint8_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getIV(mAMediaCodecCryptoInfo, dst));
-}
-
-CryptoPlugin::Mode AMediaCodecCryptoInfoWrapper::getMode() {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return CryptoPlugin::kMode_Unencrypted;
-    }
-    return translateToCryptoPluginMode(
-        AMediaCodecCryptoInfo_getMode(mAMediaCodecCryptoInfo));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getClearBytes(size_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getClearBytes(mAMediaCodecCryptoInfo, dst));
-}
-
-status_t AMediaCodecCryptoInfoWrapper::getEncryptedBytes(size_t *dst) {
-    if (mAMediaCodecCryptoInfo == NULL) {
-        return DEAD_OBJECT;
-    }
-    if (dst == NULL) {
-        return BAD_VALUE;
-    }
-    return translateErrorCode(
-        AMediaCodecCryptoInfo_getEncryptedBytes(mAMediaCodecCryptoInfo, dst));
-}
-
-
-//////////// AMediaCodecWrapper
-// static
-sp<AMediaCodecWrapper> AMediaCodecWrapper::CreateCodecByName(const AString &name) {
-    AMediaCodec *aMediaCodec = AMediaCodec_createCodecByName(name.c_str());
-    return new AMediaCodecWrapper(aMediaCodec);
-}
-
-// static
-sp<AMediaCodecWrapper> AMediaCodecWrapper::CreateDecoderByType(const AString &mimeType) {
-    AMediaCodec *aMediaCodec = AMediaCodec_createDecoderByType(mimeType.c_str());
-    return new AMediaCodecWrapper(aMediaCodec);
-}
-
-// static
-void AMediaCodecWrapper::OnInputAvailableCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        int32_t index) {
-    ALOGV("OnInputAvailableCB: index(%d)", index);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
-    msg->setInt32("index", index);
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnOutputAvailableCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        int32_t index,
-        AMediaCodecBufferInfo *bufferInfo) {
-    ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)",
-          index, bufferInfo->offset, bufferInfo->size,
-          (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
-    msg->setInt32("index", index);
-    msg->setSize("offset", (size_t)(bufferInfo->offset));
-    msg->setSize("size", (size_t)(bufferInfo->size));
-    msg->setInt64("timeUs", bufferInfo->presentationTimeUs);
-    msg->setInt32("flags", (int32_t)(bufferInfo->flags));
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnFormatChangedCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        AMediaFormat *format) {
-    sp<AMediaFormatWrapper> formatWrapper = new AMediaFormatWrapper(format);
-    sp<AMessage> outputFormat = formatWrapper->toAMessage();
-    ALOGV("OnFormatChangedCB: format(%s)", outputFormat->debugString().c_str());
-
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
-    msg->setMessage("format", outputFormat);
-    msg->post();
-}
-
-// static
-void AMediaCodecWrapper::OnErrorCB(
-        AMediaCodec * /* aMediaCodec */,
-        void *userdata,
-        media_status_t err,
-        int32_t actionCode,
-        const char *detail) {
-    ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
-    sp<AMessage> msg = sp<AMessage>((AMessage *)userdata)->dup();
-    msg->setInt32("callbackID", CB_ERROR);
-    msg->setInt32("err", translateErrorCode(err));
-    msg->setInt32("actionCode", translateActionCode(actionCode));
-    msg->setString("detail", detail);
-    msg->post();
-}
-
-AMediaCodecWrapper::AMediaCodecWrapper(AMediaCodec *aMediaCodec)
-    : mAMediaCodec(aMediaCodec) {
-}
-
-AMediaCodecWrapper::~AMediaCodecWrapper() {
-    release();
-}
-
-status_t AMediaCodecWrapper::release() {
-    if (mAMediaCodec != NULL) {
-        AMediaCodecOnAsyncNotifyCallback aCB = {};
-        AMediaCodec_setAsyncNotifyCallback(mAMediaCodec, aCB, NULL);
-        mCallback = NULL;
-
-        media_status_t err = AMediaCodec_delete(mAMediaCodec);
-        mAMediaCodec = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaCodec *AMediaCodecWrapper::getAMediaCodec() const {
-    return mAMediaCodec;
-}
-
-status_t AMediaCodecWrapper::getName(AString *outComponentName) const {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    char *name = NULL;
-    media_status_t err = AMediaCodec_getName(mAMediaCodec, &name);
-    if (err != AMEDIA_OK) {
-        return translateErrorCode(err);
-    }
-
-    *outComponentName = AString(name);
-    AMediaCodec_releaseName(mAMediaCodec, name);
-    return OK;
-}
-
-status_t AMediaCodecWrapper::configure(
-    const sp<AMediaFormatWrapper> &format,
-    const sp<ANativeWindowWrapper> &nww,
-    const sp<AMediaCryptoWrapper> &crypto,
-    uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    media_status_t err = AMediaCodec_configure(
-            mAMediaCodec,
-            format->getAMediaFormat(),
-            (nww == NULL ? NULL : nww->getANativeWindow()),
-            crypto == NULL ? NULL : crypto->getAMediaCrypto(),
-            flags);
-
-    return translateErrorCode(err);
-}
-
-status_t AMediaCodecWrapper::setCallback(const sp<AMessage> &callback) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    mCallback = callback;
-
-    AMediaCodecOnAsyncNotifyCallback aCB = {
-        OnInputAvailableCB,
-        OnOutputAvailableCB,
-        OnFormatChangedCB,
-        OnErrorCB
-    };
-
-    return translateErrorCode(
-            AMediaCodec_setAsyncNotifyCallback(mAMediaCodec, aCB, callback.get()));
-}
-
-status_t AMediaCodecWrapper::releaseCrypto() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_releaseCrypto(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::start() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_start(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::stop() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_stop(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::flush() {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaCodec_flush(mAMediaCodec));
-}
-
-uint8_t* AMediaCodecWrapper::getInputBuffer(size_t idx, size_t *out_size) {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return AMediaCodec_getInputBuffer(mAMediaCodec, idx, out_size);
-}
-
-uint8_t* AMediaCodecWrapper::getOutputBuffer(size_t idx, size_t *out_size) {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return AMediaCodec_getOutputBuffer(mAMediaCodec, idx, out_size);
-}
-
-status_t AMediaCodecWrapper::queueInputBuffer(
-        size_t idx,
-        size_t offset,
-        size_t size,
-        uint64_t time,
-        uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_queueInputBuffer(mAMediaCodec, idx, offset, size, time, flags));
-}
-
-status_t AMediaCodecWrapper::queueSecureInputBuffer(
-        size_t idx,
-        size_t offset,
-        sp<AMediaCodecCryptoInfoWrapper> &codecCryptoInfo,
-        uint64_t time,
-        uint32_t flags) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_queueSecureInputBuffer(
-            mAMediaCodec,
-            idx,
-            offset,
-            codecCryptoInfo->getAMediaCodecCryptoInfo(),
-            time,
-            flags));
-}
-
-sp<AMediaFormatWrapper> AMediaCodecWrapper::getOutputFormat() {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaCodec_getOutputFormat(mAMediaCodec));
-}
-
-sp<AMediaFormatWrapper> AMediaCodecWrapper::getInputFormat() {
-    if (mAMediaCodec == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaCodec_getInputFormat(mAMediaCodec));
-}
-
-status_t AMediaCodecWrapper::releaseOutputBuffer(size_t idx, bool render) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_releaseOutputBuffer(mAMediaCodec, idx, render));
-}
-
-status_t AMediaCodecWrapper::setOutputSurface(const sp<ANativeWindowWrapper> &nww) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_setOutputSurface(mAMediaCodec,
-                                     (nww == NULL ? NULL : nww->getANativeWindow())));
-}
-
-status_t AMediaCodecWrapper::releaseOutputBufferAtTime(size_t idx, int64_t timestampNs) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_releaseOutputBufferAtTime(mAMediaCodec, idx, timestampNs));
-}
-
-status_t AMediaCodecWrapper::setParameters(const sp<AMediaFormatWrapper> &params) {
-    if (mAMediaCodec == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(
-        AMediaCodec_setParameters(mAMediaCodec, params->getAMediaFormat()));
-}
-
-//////////// AMediaExtractorWrapper
-
-AMediaExtractorWrapper::AMediaExtractorWrapper(AMediaExtractor *aMediaExtractor)
-    : mAMediaExtractor(aMediaExtractor) {
-}
-
-AMediaExtractorWrapper::~AMediaExtractorWrapper() {
-    release();
-}
-
-status_t AMediaExtractorWrapper::release() {
-    if (mAMediaExtractor != NULL) {
-        media_status_t err = AMediaExtractor_delete(mAMediaExtractor);
-        mAMediaExtractor = NULL;
-        return translateErrorCode(err);
-    }
-    return OK;
-}
-
-AMediaExtractor *AMediaExtractorWrapper::getAMediaExtractor() const {
-    return mAMediaExtractor;
-}
-
-status_t AMediaExtractorWrapper::setDataSource(int fd, off64_t offset, off64_t length) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSourceFd(
-            mAMediaExtractor, fd, offset, length));
-}
-
-status_t AMediaExtractorWrapper::setDataSource(const char *location) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSource(mAMediaExtractor, location));
-}
-
-status_t AMediaExtractorWrapper::setDataSource(AMediaDataSource *source) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_setDataSourceCustom(mAMediaExtractor, source));
-}
-
-size_t AMediaExtractorWrapper::getTrackCount() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getTrackCount(mAMediaExtractor);
-}
-
-sp<AMediaFormatWrapper> AMediaExtractorWrapper::getFormat() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaExtractor_getFileFormat(mAMediaExtractor));
-}
-
-sp<AMediaFormatWrapper> AMediaExtractorWrapper::getTrackFormat(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return new AMediaFormatWrapper(AMediaExtractor_getTrackFormat(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::selectTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_selectTrack(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::unselectTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    return translateErrorCode(AMediaExtractor_unselectTrack(mAMediaExtractor, idx));
-}
-
-status_t AMediaExtractorWrapper::selectSingleTrack(size_t idx) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    for (size_t i = 0; i < AMediaExtractor_getTrackCount(mAMediaExtractor); ++i) {
-        if (i == idx) {
-            media_status_t err = AMediaExtractor_selectTrack(mAMediaExtractor, i);
-            if (err != AMEDIA_OK) {
-                return translateErrorCode(err);
-            }
-        } else {
-            media_status_t err = AMediaExtractor_unselectTrack(mAMediaExtractor, i);
-            if (err != AMEDIA_OK) {
-                return translateErrorCode(err);
-            }
-        }
-    }
-    return OK;
-}
-
-ssize_t AMediaExtractorWrapper::readSampleData(const sp<ABuffer> &buffer) {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_readSampleData(mAMediaExtractor, buffer->data(), buffer->capacity());
-}
-
-ssize_t AMediaExtractorWrapper::getSampleSize() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getSampleSize(mAMediaExtractor);
-}
-
-uint32_t AMediaExtractorWrapper::getSampleFlags() {
-    if (mAMediaExtractor == NULL) {
-        return 0;
-    }
-    return AMediaExtractor_getSampleFlags(mAMediaExtractor);
-}
-
-int AMediaExtractorWrapper::getSampleTrackIndex() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getSampleTrackIndex(mAMediaExtractor);
-}
-
-int64_t AMediaExtractorWrapper::getSampleTime() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getSampleTime(mAMediaExtractor);
-}
-
-status_t AMediaExtractorWrapper::getSampleFormat(sp<AMediaFormatWrapper> &formatWrapper) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-    AMediaFormat *format = AMediaFormat_new();
-    formatWrapper = new AMediaFormatWrapper(format);
-    return translateErrorCode(AMediaExtractor_getSampleFormat(mAMediaExtractor, format));
-}
-
-int64_t AMediaExtractorWrapper::getCachedDuration() {
-    if (mAMediaExtractor == NULL) {
-        return -1;
-    }
-    return AMediaExtractor_getCachedDuration(mAMediaExtractor);
-}
-
-bool AMediaExtractorWrapper::advance() {
-    if (mAMediaExtractor == NULL) {
-        return false;
-    }
-    return AMediaExtractor_advance(mAMediaExtractor);
-}
-
-status_t AMediaExtractorWrapper::seekTo(int64_t seekPosUs, MediaSource::ReadOptions::SeekMode mode) {
-    if (mAMediaExtractor == NULL) {
-        return DEAD_OBJECT;
-    }
-
-    SeekMode aMode;
-    switch (mode) {
-        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: {
-            aMode = AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC;
-            break;
-        }
-        case MediaSource::ReadOptions::SEEK_NEXT_SYNC: {
-            aMode = AMEDIAEXTRACTOR_SEEK_NEXT_SYNC;
-            break;
-        }
-        default: {
-            aMode = AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC;
-            break;
-        }
-    }
-    return AMediaExtractor_seekTo(mAMediaExtractor, seekPosUs, aMode);
-}
-
-PsshInfo* AMediaExtractorWrapper::getPsshInfo() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    return AMediaExtractor_getPsshInfo(mAMediaExtractor);
-}
-
-sp<AMediaCodecCryptoInfoWrapper> AMediaExtractorWrapper::getSampleCryptoInfo() {
-    if (mAMediaExtractor == NULL) {
-        return NULL;
-    }
-    AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
-    if (cryptoInfo == NULL) {
-        return NULL;
-    }
-    return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
-}
-
-AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
-    : mDataSource(dataSource),
-      mAMediaDataSource(convertDataSourceToAMediaDataSource(dataSource)) {
-}
-
-AMediaDataSourceWrapper::AMediaDataSourceWrapper(AMediaDataSource *aDataSource)
-    : mDataSource(NULL),
-      mAMediaDataSource(aDataSource) {
-}
-
-AMediaDataSourceWrapper::~AMediaDataSourceWrapper() {
-    if (mAMediaDataSource == NULL) {
-        return;
-    }
-    AMediaDataSource_close(mAMediaDataSource);
-    AMediaDataSource_delete(mAMediaDataSource);
-    mAMediaDataSource = NULL;
-}
-
-AMediaDataSource* AMediaDataSourceWrapper::getAMediaDataSource() {
-    return mAMediaDataSource;
-}
-
-void AMediaDataSourceWrapper::close() {
-    AMediaDataSource_close(mAMediaDataSource);
-}
-
-}  // namespace android
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
deleted file mode 100644
index 5be78d1..0000000
--- a/media/libmedia/TypeConverter.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2016 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 <media/TypeConverter.h>
-
-namespace android {
-
-#define MAKE_STRING_FROM_ENUM(string) { #string, string }
-#define TERMINATOR { .literal = nullptr }
-
-template <>
-const OutputDeviceConverter::Table OutputDeviceConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_LINE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPDIF),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_PROXY),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HEARING_AID),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ECHO_CANCELLER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DEFAULT),
-    // STUB must be after DEFAULT, so the latter is picked up by toString first.
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_STUB),
-    TERMINATOR
-};
-
-template <>
-const InputDeviceConverter::Table InputDeviceConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI_ARC),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_USB),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ECHO_REFERENCE),
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
-    // STUB must be after DEFAULT, so the latter is picked up by toString first.
-    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
-    TERMINATOR
-};
-
-
-template <>
-const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_FAST),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_TTS),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_RAW),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
-    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
-    TERMINATOR
-};
-
-
-template <>
-const InputFlagConverter::Table InputFlagConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_NONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_FAST),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_RAW),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_SYNC),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_MMAP_NOIRQ),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_VOIP_TX),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_AV_SYNC),
-    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_DIRECT),
-    TERMINATOR
-};
-
-
-template <>
-const FormatConverter::Table FormatConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_16_BIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_BIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_32_BIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_FLOAT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP3),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_NB),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_MAIN),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SSR),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LTP),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V1),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ERLC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V2),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ELD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_XHE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_XHE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_VORBIS),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V1),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V2),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_OPUS),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC3),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCB),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCWB),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCNW),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADIF),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA_PRO),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP2),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_QCELP),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DSD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_FLAC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_ALAC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_SBC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_HD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC4),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LDAC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3_JOC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_1_0),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_0),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_1),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_LC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V1),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V2),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_CELT),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_ADAPTIVE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC_LL),
-    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_TWSP),
-    TERMINATOR
-};
-
-
-template <>
-const OutputChannelConverter::Table OutputChannelConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT0POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI_BACK),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT0POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_BACK),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_PENTA),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_BACK),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT4),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT4),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_A),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_A),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_AB),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB),
-    TERMINATOR
-};
-
-
-template <>
-const InputChannelConverter::Table InputChannelConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_MONO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_6),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT0POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT0POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT1POINT2),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_5POINT1),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
-    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
-    TERMINATOR
-};
-
-template <>
-const ChannelIndexConverter::Table ChannelIndexConverter::mTable[] = {
-    {"AUDIO_CHANNEL_INDEX_MASK_1", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_1)},
-    {"AUDIO_CHANNEL_INDEX_MASK_2", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_2)},
-    {"AUDIO_CHANNEL_INDEX_MASK_3", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_3)},
-    {"AUDIO_CHANNEL_INDEX_MASK_4", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_4)},
-    {"AUDIO_CHANNEL_INDEX_MASK_5", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_5)},
-    {"AUDIO_CHANNEL_INDEX_MASK_6", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_6)},
-    {"AUDIO_CHANNEL_INDEX_MASK_7", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_7)},
-    {"AUDIO_CHANNEL_INDEX_MASK_8", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_8)},
-    TERMINATOR
-};
-
-
-template <>
-const GainModeConverter::Table GainModeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_JOINT),
-    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_CHANNELS),
-    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_RAMP),
-    TERMINATOR
-};
-
-
-template <>
-const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DEFAULT),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_VOICE_CALL),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_SYSTEM),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_RING),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_MUSIC),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ALARM),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_NOTIFICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_BLUETOOTH_SCO ),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ENFORCED_AUDIBLE),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DTMF),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_TTS),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ACCESSIBILITY),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_REROUTING),
-    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH),
-    TERMINATOR
-};
-
-template<>
-const AudioModeConverter::Table AudioModeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_INVALID),
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_CURRENT),
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_NORMAL),
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_RINGTONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_CALL),
-    MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_COMMUNICATION),
-    TERMINATOR
-};
-
-template<>
-const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_UNKNOWN),
-    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SPEECH),
-    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MUSIC),
-    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MOVIE),
-    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SONIFICATION),
-    TERMINATOR
-};
-
-template <>
-const UsageTypeConverter::Table UsageTypeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_UNKNOWN),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_MEDIA),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ALARM),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_EVENT),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_SONIFICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_GAME),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VIRTUAL_SOURCE),
-    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANT),
-    TERMINATOR
-};
-
-template <>
-const SourceTypeConverter::Table SourceTypeConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_DEFAULT),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_MIC),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_UPLINK),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_DOWNLINK),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_CALL),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_CAMCORDER),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_RECOGNITION),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_COMMUNICATION),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_REMOTE_SUBMIX),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_UNPROCESSED),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_PERFORMANCE),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_ECHO_REFERENCE),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_FM_TUNER),
-    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_HOTWORD),
-    TERMINATOR
-};
-
-template <>
-const AudioFlagConverter::Table AudioFlagConverter::mTable[] = {
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NONE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_AUDIBILITY_ENFORCED),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SECURE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SCO),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BEACON),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_AV_SYNC),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_HOTWORD),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_MUTE),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_LOW_LATENCY),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_MEDIA_PROJECTION),
-    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_SYSTEM_CAPTURE),
-    TERMINATOR
-};
-
-template class TypeConverter<OutputDeviceTraits>;
-template class TypeConverter<InputDeviceTraits>;
-template class TypeConverter<OutputFlagTraits>;
-template class TypeConverter<InputFlagTraits>;
-template class TypeConverter<FormatTraits>;
-template class TypeConverter<OutputChannelTraits>;
-template class TypeConverter<InputChannelTraits>;
-template class TypeConverter<ChannelIndexTraits>;
-template class TypeConverter<GainModeTraits>;
-template class TypeConverter<StreamTraits>;
-template class TypeConverter<AudioModeTraits>;
-template class TypeConverter<UsageTraits>;
-template class TypeConverter<SourceTraits>;
-template class TypeConverter<AudioFlagTraits>;
-
-bool deviceFromString(const std::string& literalDevice, audio_devices_t& device) {
-    return InputDeviceConverter::fromString(literalDevice, device) ||
-            OutputDeviceConverter::fromString(literalDevice, device);
-}
-
-SampleRateTraits::Collection samplingRatesFromString(
-        const std::string &samplingRates, const char *del)
-{
-    SampleRateTraits::Collection samplingRateCollection;
-    collectionFromString<SampleRateTraits>(samplingRates, samplingRateCollection, del);
-    return samplingRateCollection;
-}
-
-FormatTraits::Collection formatsFromString(
-        const std::string &formats, const char *del)
-{
-    FormatTraits::Collection formatCollection;
-    FormatConverter::collectionFromString(formats, formatCollection, del);
-    return formatCollection;
-}
-
-audio_format_t formatFromString(const std::string &literalFormat, audio_format_t defaultFormat)
-{
-    audio_format_t format;
-    if (literalFormat.empty()) {
-        return defaultFormat;
-    }
-    FormatConverter::fromString(literalFormat, format);
-    return format;
-}
-
-audio_channel_mask_t channelMaskFromString(const std::string &literalChannels)
-{
-    audio_channel_mask_t channels;
-    if (!OutputChannelConverter::fromString(literalChannels, channels) &&
-            !InputChannelConverter::fromString(literalChannels, channels)) {
-        return AUDIO_CHANNEL_INVALID;
-    }
-    return channels;
-}
-
-ChannelTraits::Collection channelMasksFromString(
-        const std::string &channels, const char *del)
-{
-    ChannelTraits::Collection channelMaskCollection;
-    OutputChannelConverter::collectionFromString(channels, channelMaskCollection, del);
-    InputChannelConverter::collectionFromString(channels, channelMaskCollection, del);
-    ChannelIndexConverter::collectionFromString(channels, channelMaskCollection, del);
-    return channelMaskCollection;
-}
-
-InputChannelTraits::Collection inputChannelMasksFromString(
-        const std::string &inChannels, const char *del)
-{
-    InputChannelTraits::Collection inputChannelMaskCollection;
-    InputChannelConverter::collectionFromString(inChannels, inputChannelMaskCollection, del);
-    ChannelIndexConverter::collectionFromString(inChannels, inputChannelMaskCollection, del);
-    return inputChannelMaskCollection;
-}
-
-OutputChannelTraits::Collection outputChannelMasksFromString(
-        const std::string &outChannels, const char *del)
-{
-    OutputChannelTraits::Collection outputChannelMaskCollection;
-    OutputChannelConverter::collectionFromString(outChannels, outputChannelMaskCollection, del);
-    ChannelIndexConverter::collectionFromString(outChannels, outputChannelMaskCollection, del);
-    return outputChannelMaskCollection;
-}
-
-}; // namespace android
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
deleted file mode 100644
index 2bf0802..0000000
--- a/media/libmedia/Visualizer.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
-**
-** Copyright 2010, 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 "Visualizer"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include <media/Visualizer.h>
-#include <audio_utils/fixedfft.h>
-#include <utils/Thread.h>
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-Visualizer::Visualizer (const String16& opPackageName,
-         int32_t priority,
-         effect_callback_t cbf,
-         void* user,
-         audio_session_t sessionId)
-    :   AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
-        mCaptureRate(CAPTURE_RATE_DEF),
-        mCaptureSize(CAPTURE_SIZE_DEF),
-        mSampleRate(44100000),
-        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
-        mMeasurementMode(MEASUREMENT_MODE_NONE),
-        mCaptureCallBack(NULL),
-        mCaptureCbkUser(NULL)
-{
-    initCaptureSize();
-}
-
-Visualizer::~Visualizer()
-{
-    ALOGV("Visualizer::~Visualizer()");
-    setEnabled(false);
-    setCaptureCallBack(NULL, NULL, 0, 0);
-}
-
-void Visualizer::release()
-{
-    ALOGV("Visualizer::release()");
-    setEnabled(false);
-    Mutex::Autolock _l(mCaptureLock);
-
-    mCaptureThread.clear();
-    mCaptureCallBack = NULL;
-    mCaptureCbkUser = NULL;
-    mCaptureFlags = 0;
-    mCaptureRate = 0;
-}
-
-status_t Visualizer::setEnabled(bool enabled)
-{
-    Mutex::Autolock _l(mCaptureLock);
-
-    sp<CaptureThread> t = mCaptureThread;
-    if (t != 0) {
-        if (enabled) {
-            if (t->exitPending()) {
-                mCaptureLock.unlock();
-                if (t->requestExitAndWait() == WOULD_BLOCK) {
-                    mCaptureLock.lock();
-                    ALOGE("Visualizer::enable() called from thread");
-                    return INVALID_OPERATION;
-                }
-                mCaptureLock.lock();
-            }
-        }
-        t->mLock.lock();
-    }
-
-    status_t status = AudioEffect::setEnabled(enabled);
-
-    if (t != 0) {
-        if (enabled && status == NO_ERROR) {
-            t->run("Visualizer");
-        } else {
-            t->requestExit();
-        }
-    }
-
-    if (t != 0) {
-        t->mLock.unlock();
-    }
-
-    return status;
-}
-
-status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags,
-        uint32_t rate)
-{
-    if (rate > CAPTURE_RATE_MAX) {
-        return BAD_VALUE;
-    }
-    Mutex::Autolock _l(mCaptureLock);
-
-    if (mEnabled) {
-        return INVALID_OPERATION;
-    }
-
-    if (mCaptureThread != 0) {
-        mCaptureLock.unlock();
-        mCaptureThread->requestExitAndWait();
-        mCaptureLock.lock();
-    }
-
-    mCaptureThread.clear();
-    mCaptureCallBack = cbk;
-    mCaptureCbkUser = user;
-    mCaptureFlags = flags;
-    mCaptureRate = rate;
-
-    if (cbk != NULL) {
-        mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
-    }
-    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
-            rate, mCaptureThread.get(), mCaptureFlags);
-    return NO_ERROR;
-}
-
-status_t Visualizer::setCaptureSize(uint32_t size)
-{
-    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
-        size < VISUALIZER_CAPTURE_SIZE_MIN ||
-        popcount(size) != 1) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-    if (mEnabled) {
-        return INVALID_OPERATION;
-    }
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
-    *((int32_t *)p->data + 1)= size;
-    status_t status = setParameter(p);
-
-    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mCaptureSize = size;
-        }
-    }
-
-    return status;
-}
-
-status_t Visualizer::setScalingMode(uint32_t mode) {
-    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
-            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
-    *((int32_t *)p->data + 1)= mode;
-    status_t status = setParameter(p);
-
-    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mScalingMode = mode;
-        }
-    }
-
-    return status;
-}
-
-status_t Visualizer::setMeasurementMode(uint32_t mode) {
-    if ((mode != MEASUREMENT_MODE_NONE)
-            //Note: needs to be handled as a mask when more measurement modes are added
-            && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mCaptureLock);
-
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
-    *((int32_t *)p->data + 1)= mode;
-    status_t status = setParameter(p);
-
-    ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-        if (status == NO_ERROR) {
-            mMeasurementMode = mode;
-        }
-    }
-    return status;
-}
-
-status_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) {
-    if (mMeasurementMode == MEASUREMENT_MODE_NONE) {
-        ALOGE("Cannot retrieve int measurements, no measurement mode set");
-        return INVALID_OPERATION;
-    }
-    if (!(mMeasurementMode & type)) {
-        // measurement type has not been set on this Visualizer
-        ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)",
-                type, mMeasurementMode);
-        return INVALID_OPERATION;
-    }
-    // only peak+RMS measurement supported
-    if ((type != MEASUREMENT_MODE_PEAK_RMS)
-            // for peak+RMS measurement, the results are 2 int32_t values
-            || (number != 2)) {
-        ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
-                        number);
-        return BAD_VALUE;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint32_t replySize = number * sizeof(int32_t);
-        status = command(VISUALIZER_CMD_MEASURE,
-                sizeof(uint32_t)  /*cmdSize*/,
-                &type /*cmdData*/,
-                &replySize, measurements);
-        ALOGV("getMeasurements() command returned %d", status);
-        if ((status == NO_ERROR) && (replySize == 0)) {
-            status = NOT_ENOUGH_DATA;
-        }
-    } else {
-        ALOGV("getMeasurements() disabled");
-        return INVALID_OPERATION;
-    }
-    return status;
-}
-
-status_t Visualizer::getWaveForm(uint8_t *waveform)
-{
-    if (waveform == NULL) {
-        return BAD_VALUE;
-    }
-    if (mCaptureSize == 0) {
-        return NO_INIT;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint32_t replySize = mCaptureSize;
-        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
-        ALOGV("getWaveForm() command returned %d", status);
-        if ((status == NO_ERROR) && (replySize == 0)) {
-            status = NOT_ENOUGH_DATA;
-        }
-    } else {
-        ALOGV("getWaveForm() disabled");
-        memset(waveform, 0x80, mCaptureSize);
-    }
-    return status;
-}
-
-status_t Visualizer::getFft(uint8_t *fft)
-{
-    if (fft == NULL) {
-        return BAD_VALUE;
-    }
-    if (mCaptureSize == 0) {
-        return NO_INIT;
-    }
-
-    status_t status = NO_ERROR;
-    if (mEnabled) {
-        uint8_t buf[mCaptureSize];
-        status = getWaveForm(buf);
-        if (status == NO_ERROR) {
-            status = doFft(fft, buf);
-        }
-    } else {
-        memset(fft, 0, mCaptureSize);
-    }
-    return status;
-}
-
-status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
-{
-    int32_t workspace[mCaptureSize >> 1];
-    int32_t nonzero = 0;
-
-    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
-        workspace[i >> 1] =
-                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
-        nonzero |= workspace[i >> 1];
-    }
-
-    if (nonzero) {
-        fixed_fft_real(mCaptureSize >> 1, workspace);
-    }
-
-    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
-        short tmp = workspace[i >> 1] >> 21;
-        while (tmp > 127 || tmp < -128) tmp >>= 1;
-        fft[i] = tmp;
-        tmp = workspace[i >> 1];
-        tmp >>= 5;
-        while (tmp > 127 || tmp < -128) tmp >>= 1;
-        fft[i + 1] = tmp;
-    }
-
-    return NO_ERROR;
-}
-
-void Visualizer::periodicCapture()
-{
-    Mutex::Autolock _l(mCaptureLock);
-    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
-            this, mCaptureCallBack, mCaptureFlags);
-    if (mCaptureCallBack != NULL &&
-        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
-        mCaptureSize != 0) {
-        uint8_t waveform[mCaptureSize];
-        status_t status = getWaveForm(waveform);
-        if (status != NO_ERROR) {
-            return;
-        }
-        uint8_t fft[mCaptureSize];
-        if (mCaptureFlags & CAPTURE_FFT) {
-            status = doFft(fft, waveform);
-        }
-        if (status != NO_ERROR) {
-            return;
-        }
-        uint8_t *wavePtr = NULL;
-        uint8_t *fftPtr = NULL;
-        uint32_t waveSize = 0;
-        uint32_t fftSize = 0;
-        if (mCaptureFlags & CAPTURE_WAVEFORM) {
-            wavePtr = waveform;
-            waveSize = mCaptureSize;
-        }
-        if (mCaptureFlags & CAPTURE_FFT) {
-            fftPtr = fft;
-            fftSize = mCaptureSize;
-        }
-        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
-    }
-}
-
-uint32_t Visualizer::initCaptureSize()
-{
-    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
-    effect_param_t *p = (effect_param_t *)buf32;
-
-    p->psize = sizeof(uint32_t);
-    p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
-    status_t status = getParameter(p);
-
-    if (status == NO_ERROR) {
-        status = p->status;
-    }
-
-    uint32_t size = 0;
-    if (status == NO_ERROR) {
-        size = *((int32_t *)p->data + 1);
-    }
-    mCaptureSize = size;
-
-    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
-
-    return size;
-}
-
-void Visualizer::controlStatusChanged(bool controlGranted) {
-    if (controlGranted) {
-        // this Visualizer instance regained control of the effect, reset the scaling mode
-        //   and capture size as has been cached through it.
-        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
-        ALOGV("    scaling mode reset to %d", mScalingMode);
-        setScalingMode(mScalingMode);
-        ALOGV("    capture size reset to %d", mCaptureSize);
-        setCaptureSize(mCaptureSize);
-    }
-    AudioEffect::controlStatusChanged(controlGranted);
-}
-
-//-------------------------------------------------------------------------
-
-Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate,
-        bool bCanCallJava)
-    : Thread(bCanCallJava), mReceiver(receiver)
-{
-    mSleepTimeUs = 1000000000 / captureRate;
-    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
-}
-
-bool Visualizer::CaptureThread::threadLoop()
-{
-    ALOGV("CaptureThread %p enter", this);
-    sp<Visualizer> receiver = mReceiver.promote();
-    if (receiver == NULL) {
-        return false;
-    }
-    while (!exitPending())
-    {
-        usleep(mSleepTimeUs);
-        receiver->periodicCapture();
-    }
-    ALOGV("CaptureThread %p exiting", this);
-    return false;
-}
-
-} // namespace android
diff --git a/media/libmedia/aidl/android/IDataSource.aidl b/media/libmedia/aidl/android/IDataSource.aidl
new file mode 100644
index 0000000..fb954bf
--- /dev/null
+++ b/media/libmedia/aidl/android/IDataSource.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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;
+
+/** @hide */
+interface IDataSource {
+    // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IMediaExtractor.aidl b/media/libmedia/aidl/android/IMediaExtractor.aidl
new file mode 100644
index 0000000..5ba68e6
--- /dev/null
+++ b/media/libmedia/aidl/android/IMediaExtractor.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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;
+
+/** @hide */
+interface IMediaExtractor {
+    // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IMediaExtractorService.aidl b/media/libmedia/aidl/android/IMediaExtractorService.aidl
new file mode 100644
index 0000000..c57fa16
--- /dev/null
+++ b/media/libmedia/aidl/android/IMediaExtractorService.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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;
+
+import android.IDataSource;
+import android.IMediaExtractor;
+
+/**
+ * Binder interface for the media extractor service
+ *
+ * @hide
+ */
+interface IMediaExtractorService {
+
+    IMediaExtractor makeExtractor(IDataSource source, @nullable @utf8InCpp String mime);
+    IDataSource makeIDataSource(in FileDescriptor fd, long offset, long length);
+    @utf8InCpp String[] getSupportedTypes();
+}
diff --git a/media/libmedia/aidl/android/media/IResourceManagerClient.aidl b/media/libmedia/aidl/android/media/IResourceManagerClient.aidl
new file mode 100644
index 0000000..4c3ef47
--- /dev/null
+++ b/media/libmedia/aidl/android/media/IResourceManagerClient.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * IResourceManagerClient interface for the ResourceManagerService to
+ * call the client.
+ *
+ * {@hide}
+ */
+interface IResourceManagerClient {
+    /**
+     * Instruct the client to reclaim its resources.
+     *
+     * @return true if the reclaim was successful and false otherwise.
+     */
+    boolean reclaimResource();
+
+    /**
+     * Retrieve the name of the client.
+     *
+     * @return name of the client.
+     */
+    @utf8InCpp String getName();
+}
diff --git a/media/libmedia/aidl/android/media/IResourceManagerService.aidl b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
new file mode 100644
index 0000000..1b2d522
--- /dev/null
+++ b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2019, 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.IResourceManagerClient;
+import android.media.MediaResourceParcel;
+import android.media.MediaResourcePolicyParcel;
+
+/**
+ * ResourceManagerService interface that keeps track of media resource
+ * owned by clients, and reclaims resources based on configured policies
+ * when necessary.
+ *
+ * {@hide}
+ */
+interface IResourceManagerService {
+    const @utf8InCpp String kPolicySupportsMultipleSecureCodecs
+            = "supports-multiple-secure-codecs";
+    const @utf8InCpp String kPolicySupportsSecureWithNonSecureCodec
+            = "supports-secure-with-non-secure-codec";
+
+    /**
+     * Configure the ResourceManagerService to adopted particular policies when
+     * managing the resources.
+     *
+     * @param policies an array of policies to be adopted.
+     */
+    void config(in MediaResourcePolicyParcel[] policies);
+
+    /**
+     * Add a client to a process with a list of resources.
+     *
+     * @param pid pid of the client.
+     * @param uid uid of the client.
+     * @param clientId an identifier that uniquely identifies the client within the pid.
+     * @param client interface for the ResourceManagerService to call the client.
+     * @param resources an array of resources to be added.
+     */
+    void addResource(
+            int pid,
+            int uid,
+            long clientId,
+            IResourceManagerClient client,
+            in MediaResourceParcel[] resources);
+
+    /**
+     * Remove the listed resources from a client.
+     *
+     * @param pid pid from which the list of resources will be removed.
+     * @param clientId clientId within the pid from which the list of resources will be removed.
+     * @param resources an array of resources to be removed from the client.
+     */
+    void removeResource(int pid, long clientId, in MediaResourceParcel[] resources);
+
+    /**
+     * Remove all resources from a client.
+     *
+     * @param pid pid from which the client's resources will be removed.
+     * @param clientId clientId within the pid that will be removed.
+     */
+    void removeClient(int pid, long clientId);
+
+    /**
+     * Tries to reclaim resource from processes with lower priority than the
+     * calling process according to the requested resources.
+     *
+     * @param callingPid pid of the calling process.
+     * @param resources an array of resources to be reclaimed.
+     *
+     * @return true if the reclaim was successful and false otherwise.
+     */
+    boolean reclaimResource(int callingPid, in MediaResourceParcel[] resources);
+
+    /**
+     * Override the pid of original calling process with the pid of the process
+     * who actually use the requested resources.
+     *
+     * @param originalPid pid of the original calling process.
+     * @param newPid pid of the actual process who use the resources.
+     *        remove existing override on originalPid if newPid is -1.
+     */
+    void overridePid(int originalPid, int newPid);
+
+    /**
+     * Mark a client for pending removal
+     *
+     * @param pid pid from which the client's resources will be removed.
+     * @param clientId clientId within the pid that will be removed.
+     */
+    void markClientForPendingRemoval(int pid, long clientId);
+}
diff --git a/media/libmedia/aidl/android/media/MediaResourceParcel.aidl b/media/libmedia/aidl/android/media/MediaResourceParcel.aidl
new file mode 100644
index 0000000..b0f2b71
--- /dev/null
+++ b/media/libmedia/aidl/android/media/MediaResourceParcel.aidl
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2019, 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.MediaResourceType;
+import android.media.MediaResourceSubType;
+
+/**
+ * Description of a media resource to be tracked by MediaResourceManager.
+ *
+ * {@hide}
+ */
+parcelable MediaResourceParcel {
+    // TODO: default enum value is not supported yet.
+    // Set default enum value when b/142739329 is fixed.
+
+    /**
+     * Type of the media resource.
+     */
+    MediaResourceType type;// = MediaResourceTypeEnum::kUnspecified;
+
+    /**
+     * Sub-type of the media resource.
+     */
+    MediaResourceSubType subType;// = MediaResourceSubTypeEnum::kUnspecifiedSubType;
+
+    /**
+     * Identifier of the media resource (eg. Drm session id).
+     */
+    byte[] id;
+
+    /**
+     * Number of units of the media resource (bytes of graphic memory, number of codecs, etc.).
+     */
+    long value = 0;
+}
diff --git a/media/libmedia/aidl/android/media/MediaResourcePolicyParcel.aidl b/media/libmedia/aidl/android/media/MediaResourcePolicyParcel.aidl
new file mode 100644
index 0000000..4ea859a
--- /dev/null
+++ b/media/libmedia/aidl/android/media/MediaResourcePolicyParcel.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Description of a policy to be adopted by ResourceManagerService.
+ * {@hide}
+ */
+parcelable MediaResourcePolicyParcel {
+    /**
+     * Name of the policy to be adopted.
+     */
+    @utf8InCpp String type;
+
+    /**
+     * Value of the policy to be adopted.
+     */
+    @utf8InCpp String value;
+}
diff --git a/media/libmedia/aidl/android/media/MediaResourceSubType.aidl b/media/libmedia/aidl/android/media/MediaResourceSubType.aidl
new file mode 100644
index 0000000..af2ba68
--- /dev/null
+++ b/media/libmedia/aidl/android/media/MediaResourceSubType.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Sub-type enums of media resources.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+enum MediaResourceSubType {
+    kUnspecifiedSubType = 0,
+    kAudioCodec = 1,
+    kVideoCodec = 2,
+}
diff --git a/media/libmedia/aidl/android/media/MediaResourceType.aidl b/media/libmedia/aidl/android/media/MediaResourceType.aidl
new file mode 100644
index 0000000..b2bb71b
--- /dev/null
+++ b/media/libmedia/aidl/android/media/MediaResourceType.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Type enums of media resources.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+enum MediaResourceType {
+    kUnspecified = 0,
+    kSecureCodec = 1,
+    kNonSecureCodec = 2,
+    kGraphicMemory = 3,
+    kCpuBoost = 4,
+    kBattery = 5,
+    kDrmSession = 6,
+}
diff --git a/media/libmedia/include/android/IDataSource.h b/media/libmedia/include/android/IDataSource.h
new file mode 100644
index 0000000..43e2b50
--- /dev/null
+++ b/media/libmedia/include/android/IDataSource.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 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 ANDROID_IDATASOURCE_H
+#define ANDROID_IDATASOURCE_H
+
+#include <binder/IInterface.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class IMemory;
+class DecryptHandle;
+
+// A binder interface for implementing a stagefright DataSource remotely.
+class IDataSource : public IInterface {
+public:
+    DECLARE_META_INTERFACE(DataSource);
+
+    // Get the memory that readAt writes into.
+    virtual sp<IMemory> getIMemory() = 0;
+    // Read up to |size| bytes into the memory returned by getIMemory(). Returns
+    // the number of bytes read, or negative value on error (eg.
+    // ERROR_END_OF_STREAM indicating EOS. This is needed by CallbackDataSource
+    // to properly handle reading of last chunk). |size| must not be larger than
+    // the buffer.
+    virtual ssize_t readAt(off64_t offset, size_t size) = 0;
+    // Get the size, or -1 if the size is unknown.
+    virtual status_t getSize(off64_t* size) = 0;
+    // This should be called before deleting |this|. The other methods may
+    // return errors if they're called after calling close().
+    virtual void close() = 0;
+    // Get the flags of the source.
+    // Refer to DataSource:Flags for the definition of the flags.
+    virtual uint32_t getFlags() = 0;
+    // get a description of the source, e.g. the url or filename it is based on
+    virtual String8 toString() = 0;
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(IDataSource);
+};
+
+// ----------------------------------------------------------------------------
+
+class BnDataSource : public BnInterface<IDataSource> {
+public:
+    virtual status_t onTransact(uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IDATASOURCE_H
diff --git a/media/libmedia/include/android/IMediaExtractor.h b/media/libmedia/include/android/IMediaExtractor.h
new file mode 100644
index 0000000..3e035ad
--- /dev/null
+++ b/media/libmedia/include/android/IMediaExtractor.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 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 IMEDIA_EXTRACTOR_BASE_H_
+
+#define IMEDIA_EXTRACTOR_BASE_H_
+
+#include <media/DataSource.h>
+#include <media/IMediaSource.h>
+#include <vector>
+
+namespace android {
+
+class MetaData;
+typedef std::vector<uint8_t> HInterfaceToken;
+
+class IMediaExtractor : public IInterface {
+public:
+    DECLARE_META_INTERFACE(MediaExtractor);
+
+    virtual size_t countTracks() = 0;
+    // This function could return NULL IMediaSource even when index is within the
+    // track count returned by countTracks, since it's possible the track is malformed
+    // and it's not detected during countTracks call.
+    virtual sp<IMediaSource> getTrack(size_t index) = 0;
+
+    enum GetTrackMetaDataFlags {
+        kIncludeExtensiveMetaData = 1
+    };
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags = 0) = 0;
+
+    // Return container specific meta-data. The default implementation
+    // returns an empty metadata object.
+    virtual sp<MetaData> getMetaData() = 0;
+
+    virtual status_t getMetrics(Parcel *reply) = 0;
+
+    enum Flags {
+        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
+        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
+        CAN_PAUSE          = 4,
+        CAN_SEEK           = 8,  // the "seek bar"
+    };
+
+    // If subclasses do _not_ override this, the default is
+    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
+    virtual uint32_t flags() const = 0;
+
+    virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
+
+    virtual String8 name() = 0;
+};
+
+
+class BnMediaExtractor: public BnInterface<IMediaExtractor>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+void registerMediaExtractor(
+        const sp<IMediaExtractor> &extractor,
+        const sp<DataSource> &source,
+        const char *mime);
+
+void registerMediaSource(
+        const sp<IMediaExtractor> &extractor,
+        const sp<IMediaSource> &source);
+
+status_t dumpExtractors(int fd, const Vector<String16>& args);
+
+
+}  // namespace android
+
+#endif  // IMEDIA_EXTRACTOR_BASE_H_
diff --git a/media/libmedia/include/media/CounterMetric.h b/media/libmedia/include/media/CounterMetric.h
index b53470d..8bd4049 100644
--- a/media/libmedia/include/media/CounterMetric.h
+++ b/media/libmedia/include/media/CounterMetric.h
@@ -20,7 +20,7 @@
 #include <map>
 #include <string>
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <utils/Log.h>
 
 namespace android {
diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h
deleted file mode 100644
index 73c029f..0000000
--- a/media/libmedia/include/media/CryptoHal.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017 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 CRYPTO_HAL_H_
-
-#define CRYPTO_HAL_H_
-
-#include <android/hardware/drm/1.0/ICryptoFactory.h>
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.1/ICryptoFactory.h>
-#include <android/hardware/drm/1.2/ICryptoPlugin.h>
-
-#include <mediadrm/ICrypto.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::ICryptoFactory;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::SharedBuffer;
-
-class IMemoryHeap;
-
-namespace android {
-
-struct CryptoHal : public BnCrypto {
-    CryptoHal();
-    virtual ~CryptoHal();
-
-    virtual status_t initCheck() const;
-
-    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
-
-    virtual status_t createPlugin(
-            const uint8_t uuid[16], const void *data, size_t size);
-
-    virtual status_t destroyPlugin();
-
-    virtual bool requiresSecureDecoderComponent(
-            const char *mime) const;
-
-    virtual void notifyResolution(uint32_t width, uint32_t height);
-
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
-
-    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
-            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const ICrypto::SourceBuffer &source, size_t offset,
-            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const ICrypto::DestinationBuffer &destination,
-            AString *errorDetailMsg);
-
-    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) {
-        return setHeapBase(heap);
-    }
-    virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
-
-private:
-    mutable Mutex mLock;
-
-    const Vector<sp<ICryptoFactory>> mFactories;
-    sp<ICryptoPlugin> mPlugin;
-    sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
-
-    /**
-     * mInitCheck is:
-     *   NO_INIT if a plugin hasn't been created yet
-     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
-     *   OK after a plugin has been created and mPlugin is valid
-     */
-    status_t mInitCheck;
-
-    struct HeapBase {
-        HeapBase() : mBufferId(0), mSize(0) {}
-        HeapBase(uint32_t bufferId, size_t size) :
-            mBufferId(bufferId), mSize(size) {}
-
-        uint32_t getBufferId() const {return mBufferId;}
-        size_t getSize() const {return mSize;}
-
-    private:
-        uint32_t mBufferId;
-        size_t mSize;
-    };
-
-    KeyedVector<int32_t, HeapBase> mHeapBases;
-    uint32_t mNextBufferId;
-    int32_t mHeapSeqNum;
-
-    Vector<sp<ICryptoFactory>> makeCryptoFactories();
-    sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
-            const uint8_t uuid[16], const void *initData, size_t size);
-
-    int32_t setHeapBase(const sp<IMemoryHeap>& heap);
-    void clearHeapBase(int32_t seqNum);
-
-    status_t toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer);
-
-    DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
-};
-
-}  // namespace android
-
-#endif  // CRYPTO_HAL_H_
diff --git a/media/libmedia/include/media/DataSourceDesc.h b/media/libmedia/include/media/DataSourceDesc.h
deleted file mode 100644
index 4336767..0000000
--- a/media/libmedia/include/media/DataSourceDesc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 ANDROID_DATASOURCEDESC_H
-#define ANDROID_DATASOURCEDESC_H
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class DataSource;
-struct MediaHTTPService;
-
-// A binder interface for implementing a stagefright DataSource remotely.
-struct DataSourceDesc : public RefBase {
-public:
-    // intentionally less than INT64_MAX
-    // keep consistent with JAVA code
-    static const int64_t kMaxTimeMs = 0x7ffffffffffffffll / 1000;
-    static const int64_t kMaxTimeUs = kMaxTimeMs * 1000;
-
-    enum {
-        /* No data source has been set yet */
-        TYPE_NONE     = 0,
-        /* data source is type of MediaDataSource */
-        TYPE_CALLBACK = 1,
-        /* data source is type of FileDescriptor */
-        TYPE_FD       = 2,
-        /* data source is type of Url */
-        TYPE_URL      = 3,
-    };
-
-    DataSourceDesc();
-
-    int mType;
-
-    sp<MediaHTTPService> mHttpService;
-    String8 mUrl;
-    KeyedVector<String8, String8> mHeaders;
-
-    int mFD;
-    int64_t mFDOffset;
-    int64_t mFDLength;
-
-    sp<DataSource> mCallbackSource;
-
-    int64_t mId;
-    int64_t mStartPositionMs;
-    int64_t mEndPositionMs;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(DataSourceDesc);
-};
-
-}; // namespace android
-
-#endif // ANDROID_DATASOURCEDESC_H
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
deleted file mode 100644
index bdf1b30..0000000
--- a/media/libmedia/include/media/DrmHal.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2017 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 DRM_HAL_H_
-
-#define DRM_HAL_H_
-
-#include <android/hardware/drm/1.0/IDrmFactory.h>
-#include <android/hardware/drm/1.0/IDrmPlugin.h>
-#include <android/hardware/drm/1.1/IDrmFactory.h>
-#include <android/hardware/drm/1.1/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmFactory.h>
-#include <android/hardware/drm/1.2/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-
-#include <media/MediaAnalyticsItem.h>
-#include <mediadrm/DrmMetrics.h>
-#include <mediadrm/IDrm.h>
-#include <mediadrm/IDrmClient.h>
-#include <utils/threads.h>
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::EventType;
-using drm::V1_0::IDrmFactory;
-using drm::V1_0::IDrmPlugin;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeyStatus;
-using drm::V1_2::OfflineLicenseState;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
-typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
-
-namespace android {
-
-struct DrmSessionClientInterface;
-
-inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
-    if (l.size() != r.size()) return false;
-    return memcmp(l.array(), r.array(), l.size()) == 0;
-}
-
-struct DrmHal : public BnDrm,
-                public IBinder::DeathRecipient,
-                public IDrmPluginListener_V1_2 {
-    DrmHal();
-    virtual ~DrmHal();
-
-    virtual status_t initCheck() const;
-
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
-                                             const String8& mimeType,
-                                             DrmPlugin::SecurityLevel level,
-                                             bool *isSupported);
-
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName);
-
-    virtual status_t destroyPlugin();
-
-    virtual status_t openSession(DrmPlugin::SecurityLevel level,
-            Vector<uint8_t> &sessionId);
-
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId);
-
-    virtual status_t
-        getKeyRequest(Vector<uint8_t> const &sessionId,
-                      Vector<uint8_t> const &initData,
-                      String8 const &mimeType, DrmPlugin::KeyType keyType,
-                      KeyedVector<String8, String8> const &optionalParameters,
-                      Vector<uint8_t> &request, String8 &defaultUrl,
-                      DrmPlugin::KeyRequestType *keyRequestType);
-
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId);
-
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
-
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId);
-
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                    KeyedVector<String8, String8> &infoMap) const;
-
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaulUrl);
-
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey);
-
-    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
-
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
-    virtual status_t removeAllSecureStops();
-
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
-            DrmPlugin::HdcpLevel *maxLevel) const;
-    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
-            uint32_t *maxSessions) const;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
-            DrmPlugin::SecurityLevel *level) const;
-
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
-            DrmPlugin::OfflineLicenseState *licenseState) const;
-
-    virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
-    virtual status_t getPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> &value ) const;
-    virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value ) const;
-    virtual status_t getMetrics(os::PersistableBundle *metrics);
-
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm);
-
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm);
-
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature);
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match);
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
-                             Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature);
-
-    virtual status_t setListener(const sp<IDrmClient>& listener);
-
-    // Methods of IDrmPluginListener
-    Return<void> sendEvent(EventType eventType,
-            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
-
-    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
-            int64_t expiryTimeInMS);
-
-    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
-
-    Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
-            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
-
-    Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
-
-    virtual void binderDied(const wp<IBinder> &the_late_who);
-
-private:
-    static Mutex mLock;
-
-    sp<DrmSessionClientInterface> mDrmSessionClient;
-
-    sp<IDrmClient> mListener;
-    mutable Mutex mEventLock;
-    mutable Mutex mNotifyLock;
-
-    const Vector<sp<IDrmFactory>> mFactories;
-    sp<IDrmPlugin> mPlugin;
-    sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
-    sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
-    String8 mAppPackageName;
-
-    // Mutable to allow modification within GetPropertyByteArray.
-    mutable MediaDrmMetrics mMetrics;
-
-    Vector<Vector<uint8_t>> mOpenSessions;
-    void closeOpenSessions();
-    void cleanup();
-
-    /**
-     * mInitCheck is:
-     *   NO_INIT if a plugin hasn't been created yet
-     *   ERROR_UNSUPPORTED if a plugin can't be created for the uuid
-     *   OK after a plugin has been created and mPlugin is valid
-     */
-    status_t mInitCheck;
-
-    Vector<sp<IDrmFactory>> makeDrmFactories();
-    sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
-            const uint8_t uuid[16], const String8& appPackageName);
-
-    void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
-
-    void reportPluginMetrics() const;
-    void reportFrameworkMetrics() const;
-    status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
-    status_t getPropertyByteArrayInternal(String8 const &name,
-                                          Vector<uint8_t> &value) const;
-    status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
-                                           const uint8_t uuid[16],
-                                           const String8 &mimeType,
-                                           DrmPlugin::SecurityLevel level,
-                                           bool *isSupported);
-
-    DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
-};
-
-}  // namespace android
-
-#endif  // DRM_HAL_H_
diff --git a/media/libmedia/include/media/DrmMetrics.h b/media/libmedia/include/media/DrmMetrics.h
deleted file mode 100644
index 6f132bf..0000000
--- a/media/libmedia/include/media/DrmMetrics.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 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 DRM_METRICS_H_
-#define DRM_METRICS_H_
-
-#include <map>
-
-#include <android/hardware/drm/1.0/types.h>
-#include <android/hardware/drm/1.1/types.h>
-#include <android/hardware/drm/1.2/types.h>
-#include <binder/PersistableBundle.h>
-#include <media/CounterMetric.h>
-#include <media/EventMetric.h>
-
-namespace android {
-
-/**
- * This class contains the definition of metrics captured within MediaDrm.
- * It also contains a method for exporting all of the metrics to a
- * PersistableBundle.
- */
-class MediaDrmMetrics {
- public:
-  explicit MediaDrmMetrics();
-  virtual ~MediaDrmMetrics() {};
-  // Count of openSession calls.
-  CounterMetric<status_t> mOpenSessionCounter;
-  // Count of closeSession calls.
-  CounterMetric<status_t> mCloseSessionCounter;
-  // Count and timing of getKeyRequest calls.
-  EventMetric<status_t> mGetKeyRequestTimeUs;
-  // Count and timing of provideKeyResponse calls.
-  EventMetric<status_t> mProvideKeyResponseTimeUs;
-  // Count of getProvisionRequest calls.
-  CounterMetric<status_t> mGetProvisionRequestCounter;
-  // Count of provideProvisionResponse calls.
-  CounterMetric<status_t> mProvideProvisionResponseCounter;
-
-  // Count of key status events broken out by status type.
-  CounterMetric<::android::hardware::drm::V1_2::KeyStatusType>
-      mKeyStatusChangeCounter;
-  // Count of events broken out by event type
-  CounterMetric<::android::hardware::drm::V1_0::EventType> mEventCounter;
-
-  // Count getPropertyByteArray calls to retrieve the device unique id.
-  CounterMetric<status_t> mGetDeviceUniqueIdCounter;
-
-  // Adds a session start time record.
-  void SetSessionStart(const Vector<uint8_t>& sessionId);
-
-  // Adds a session end time record.
-  void SetSessionEnd(const Vector<uint8_t>& sessionId);
-
-  // The app package name is the application package name that is using the
-  // instance. The app package name is held here for convenience. It is not
-  // serialized or exported with the metrics.
-  void SetAppPackageName(const String8& appPackageName) { mAppPackageName = appPackageName; }
-  const String8& GetAppPackageName() { return mAppPackageName; }
-
-  // Export the metrics to a PersistableBundle.
-  void Export(os::PersistableBundle* metricsBundle);
-
-  // Get the serialized metrics. Metrics are formatted as a serialized
-  // DrmFrameworkMetrics proto. If there is a failure serializing the metrics,
-  // this returns an error. The parameter |serlializedMetrics| is owned by the
-  // caller and must not be null.
-  status_t GetSerializedMetrics(std::string* serializedMetrics);
-
-  // Converts the DRM plugin metrics to a PersistableBundle. All of the metrics
-  // found in |pluginMetrics| are added to the |metricsBundle| parameter.
-  // |pluginBundle| is owned by the caller and must not be null.
-  //
-  // Each item in the pluginMetrics vector is added as a new PersistableBundle. E.g.
-  // DrmMetricGroup {
-  //   metrics[0] {
-  //     name: "buf_copy"
-  //     attributes[0] {
-  //       name: "size"
-  //       type: INT64_TYPE
-  //       int64Value: 1024
-  //     }
-  //     values[0] {
-  //       componentName: "operation_count"
-  //       type: INT64_TYPE
-  //       int64Value: 75
-  //     }
-  //     values[1] {
-  //       component_name: "average_time_seconds"
-  //       type: DOUBLE_TYPE
-  //       doubleValue: 0.00000042
-  //     }
-  //   }
-  // }
-  //
-  // becomes
-  //
-  // metricsBundle {
-  //   "0": (PersistableBundle) {
-  //     "attributes" : (PersistableBundle) {
-  //       "size" : (int64) 1024
-  //     }
-  //     "operation_count" : (int64) 75
-  //     "average_time_seconds" : (double) 0.00000042
-  //   }
-  //
-  static status_t HidlMetricsToBundle(
-          const hardware::hidl_vec<hardware::drm::V1_1::DrmMetricGroup>& pluginMetrics,
-          os::PersistableBundle* metricsBundle);
-
- protected:
-  // This is visible for testing only.
-  virtual int64_t GetCurrentTimeMs();
-
- private:
-  // Session lifetimes. A pair of values representing the milliseconds since
-  // epoch, UTC. The first value is the start time, the second is the end time.
-  std::map<std::string, std::pair<int64_t, int64_t>> mSessionLifespans;
-
-  String8 mAppPackageName;
-};
-
-}  // namespace android
-
-#endif  // DRM_METRICS_H_
diff --git a/media/libmedia/include/media/DrmSessionManager.h b/media/libmedia/include/media/DrmSessionManager.h
deleted file mode 100644
index ba27199..0000000
--- a/media/libmedia/include/media/DrmSessionManager.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2015 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 DRM_SESSION_MANAGER_H_
-
-#define DRM_SESSION_MANAGER_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-class DrmSessionManagerTest;
-struct DrmSessionClientInterface;
-struct ProcessInfoInterface;
-
-bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
-
-struct SessionInfo {
-    sp<DrmSessionClientInterface> drm;
-    Vector<uint8_t> sessionId;
-    int64_t timeStamp;
-};
-
-typedef Vector<SessionInfo > SessionInfos;
-typedef KeyedVector<int, SessionInfos > PidSessionInfosMap;
-
-struct DrmSessionManager : public RefBase {
-    static sp<DrmSessionManager> Instance();
-
-    DrmSessionManager();
-    explicit DrmSessionManager(sp<ProcessInfoInterface> processInfo);
-
-    void addSession(int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t>& sessionId);
-    void useSession(const Vector<uint8_t>& sessionId);
-    void removeSession(const Vector<uint8_t>& sessionId);
-    void removeDrm(const sp<DrmSessionClientInterface>& drm);
-    bool reclaimSession(int callingPid);
-
-protected:
-    virtual ~DrmSessionManager();
-
-private:
-    friend class DrmSessionManagerTest;
-
-    int64_t getTime_l();
-    bool getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority);
-    bool getLeastUsedSession_l(
-            int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId);
-
-    sp<ProcessInfoInterface> mProcessInfo;
-    mutable Mutex mLock;
-    PidSessionInfosMap mSessionMap;
-    int64_t mTime;
-
-    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
-};
-
-}  // namespace android
-
-#endif  // DRM_SESSION_MANAGER_H_
diff --git a/media/libmedia/include/media/EventMetric.h b/media/libmedia/include/media/EventMetric.h
index dbb736a..d6f3402 100644
--- a/media/libmedia/include/media/EventMetric.h
+++ b/media/libmedia/include/media/EventMetric.h
@@ -16,7 +16,7 @@
 #ifndef ANDROID_EVENT_METRIC_H_
 #define ANDROID_EVENT_METRIC_H_
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <utils/Timers.h>
 
 namespace android {
diff --git a/media/libmedia/include/media/ICrypto.h b/media/libmedia/include/media/ICrypto.h
deleted file mode 100644
index 6d896b8..0000000
--- a/media/libmedia/include/media/ICrypto.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012 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 <binder/IInterface.h>
-#include <cutils/native_handle.h>
-#include <media/hardware/CryptoAPI.h>
-#include <media/stagefright/foundation/ABase.h>
-
-#ifndef ANDROID_ICRYPTO_H_
-
-#define ANDROID_ICRYPTO_H_
-
-namespace android {
-
-struct AString;
-class IMemory;
-class IMemoryHeap;
-
-struct ICrypto : public IInterface {
-    DECLARE_META_INTERFACE(Crypto);
-
-    virtual status_t initCheck() const = 0;
-
-    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) = 0;
-
-    virtual status_t createPlugin(
-            const uint8_t uuid[16], const void *data, size_t size) = 0;
-
-    virtual status_t destroyPlugin() = 0;
-
-    virtual bool requiresSecureDecoderComponent(
-            const char *mime) const = 0;
-
-    virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
-
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
-
-    struct SourceBuffer {
-        sp<IMemory> mSharedMemory;
-        int32_t mHeapSeqNum;
-    };
-
-    enum DestinationType {
-        kDestinationTypeSharedMemory, // non-secure
-        kDestinationTypeNativeHandle  // secure
-    };
-
-    struct DestinationBuffer {
-        DestinationType mType;
-        native_handle_t *mHandle;
-        sp<IMemory> mSharedMemory;
-    };
-
-    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
-            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
-            const SourceBuffer &source, size_t offset,
-            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
-            const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
-
-    /**
-     * Declare the heap that the shared memory source buffers passed
-     * to decrypt will be allocated from. Returns a sequence number
-     * that subsequent decrypt calls can use to refer to the heap,
-     * with -1 indicating failure.
-     */
-    virtual int32_t setHeap(const sp<IMemoryHeap>& heap) = 0;
-    virtual void unsetHeap(int32_t seqNum) = 0;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
-};
-
-struct BnCrypto : public BnInterface<ICrypto> {
-    virtual status_t onTransact(
-            uint32_t code, const Parcel &data, Parcel *reply,
-            uint32_t flags = 0);
-private:
-    void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
-    void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
-}  // namespace android
-
-#endif // ANDROID_ICRYPTO_H_
diff --git a/media/libmedia/include/media/IDataSource.h b/media/libmedia/include/media/IDataSource.h
deleted file mode 100644
index 3858f78..0000000
--- a/media/libmedia/include/media/IDataSource.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2015 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 ANDROID_IDATASOURCE_H
-#define ANDROID_IDATASOURCE_H
-
-#include <binder/IInterface.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/Errors.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class IMemory;
-class DecryptHandle;
-
-// A binder interface for implementing a stagefright DataSource remotely.
-class IDataSource : public IInterface {
-public:
-    DECLARE_META_INTERFACE(DataSource);
-
-    // Get the memory that readAt writes into.
-    virtual sp<IMemory> getIMemory() = 0;
-    // Read up to |size| bytes into the memory returned by getIMemory(). Returns
-    // the number of bytes read, or negative value on error (eg.
-    // ERROR_END_OF_STREAM indicating EOS. This is needed by CallbackDataSource
-    // to properly handle reading of last chunk). |size| must not be larger than
-    // the buffer.
-    virtual ssize_t readAt(off64_t offset, size_t size) = 0;
-    // Get the size, or -1 if the size is unknown.
-    virtual status_t getSize(off64_t* size) = 0;
-    // This should be called before deleting |this|. The other methods may
-    // return errors if they're called after calling close().
-    virtual void close() = 0;
-    // Get the flags of the source.
-    // Refer to DataSource:Flags for the definition of the flags.
-    virtual uint32_t getFlags() = 0;
-    // get a description of the source, e.g. the url or filename it is based on
-    virtual String8 toString() = 0;
-    // Initialize DRM and return a DecryptHandle.
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) = 0;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(IDataSource);
-};
-
-// ----------------------------------------------------------------------------
-
-class BnDataSource : public BnInterface<IDataSource> {
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel& data,
-                                Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IDATASOURCE_H
diff --git a/media/libmedia/include/media/IDrm.h b/media/libmedia/include/media/IDrm.h
deleted file mode 100644
index fbe80c6..0000000
--- a/media/libmedia/include/media/IDrm.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2013 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 <binder/IInterface.h>
-#include <binder/PersistableBundle.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <media/drm/DrmAPI.h>
-#include <media/MediaAnalyticsItem.h>
-#include <mediadrm/IDrmClient.h>
-
-#ifndef ANDROID_IDRM_H_
-
-#define ANDROID_IDRM_H_
-
-namespace android {
-
-struct AString;
-
-struct IDrm : public IInterface {
-    DECLARE_META_INTERFACE(Drm);
-
-    virtual status_t initCheck() const = 0;
-
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
-                                             const String8 &mimeType,
-                                             DrmPlugin::SecurityLevel securityLevel,
-                                             bool *result) = 0;
-
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName) = 0;
-
-    virtual status_t destroyPlugin() = 0;
-
-    virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
-            Vector<uint8_t> &sessionId) = 0;
-
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
-
-    virtual status_t
-        getKeyRequest(Vector<uint8_t> const &sessionId,
-                      Vector<uint8_t> const &initData,
-                      String8 const &mimeType, DrmPlugin::KeyType keyType,
-                      KeyedVector<String8, String8> const &optionalParameters,
-                      Vector<uint8_t> &request, String8 &defaultUrl,
-                      DrmPlugin::KeyRequestType *keyRequestType) = 0;
-
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId) = 0;
-
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
-
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId) = 0;
-
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                    KeyedVector<String8, String8> &infoMap) const = 0;
-
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaulUrl) = 0;
-
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey) = 0;
-
-    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
-
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
-    virtual status_t removeAllSecureStops() = 0;
-
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
-            DrmPlugin::HdcpLevel *maxLevel)
-            const = 0;
-    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
-            uint32_t *maxSessions) const = 0;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
-            DrmPlugin::SecurityLevel *level) const = 0;
-
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
-            DrmPlugin::OfflineLicenseState *licenseState) const = 0;
-
-    virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
-    virtual status_t getPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> &value) const = 0;
-    virtual status_t setPropertyString(String8 const &name,
-                                       String8 const &value ) const = 0;
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value) const = 0;
-
-    virtual status_t getMetrics(os::PersistableBundle *metrics) = 0;
-
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm) = 0;
-
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm) = 0;
-
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) = 0;
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) = 0;
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature) = 0;
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match) = 0;
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
-                             Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature) = 0;
-
-    virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(IDrm);
-};
-
-struct BnDrm : public BnInterface<IDrm> {
-    virtual status_t onTransact(
-            uint32_t code, const Parcel &data, Parcel *reply,
-            uint32_t flags = 0);
-private:
-    void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
-    void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
-}  // namespace android
-
-#endif // ANDROID_IDRM_H_
diff --git a/media/libmedia/include/media/IDrmClient.h b/media/libmedia/include/media/IDrmClient.h
deleted file mode 100644
index 3b2fc7c..0000000
--- a/media/libmedia/include/media/IDrmClient.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 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 ANDROID_IDRMCLIENT_H
-#define ANDROID_IDRMCLIENT_H
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <media/drm/DrmAPI.h>
-
-namespace android {
-
-class IDrmClient: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(DrmClient);
-
-    virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnDrmClient: public BnInterface<IDrmClient>
-{
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel& data,
-                                Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IDRMCLIENT_H
diff --git a/media/libmedia/include/media/IMediaDrmService.h b/media/libmedia/include/media/IMediaDrmService.h
deleted file mode 100644
index 323fae5..0000000
--- a/media/libmedia/include/media/IMediaDrmService.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 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 ANDROID_IMEDIADRMSERVICE_H
-#define ANDROID_IMEDIADRMSERVICE_H
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-struct ICrypto;
-struct IDrm;
-
-class IMediaDrmService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaDrmService);
-
-    virtual sp<ICrypto>         makeCrypto() = 0;
-    virtual sp<IDrm>            makeDrm() = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaDrmService: public BnInterface<IMediaDrmService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIADRMSERVICE_H
diff --git a/media/libmedia/include/media/IMediaExtractor.h b/media/libmedia/include/media/IMediaExtractor.h
deleted file mode 100644
index 75e4ee2..0000000
--- a/media/libmedia/include/media/IMediaExtractor.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2009 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 IMEDIA_EXTRACTOR_BASE_H_
-
-#define IMEDIA_EXTRACTOR_BASE_H_
-
-#include <media/DataSource.h>
-#include <media/IMediaSource.h>
-#include <vector>
-
-namespace android {
-
-class MetaData;
-typedef std::vector<uint8_t> HInterfaceToken;
-
-class IMediaExtractor : public IInterface {
-public:
-    DECLARE_META_INTERFACE(MediaExtractor);
-
-    virtual size_t countTracks() = 0;
-    // This function could return NULL IMediaSource even when index is within the
-    // track count returned by countTracks, since it's possible the track is malformed
-    // and it's not detected during countTracks call.
-    virtual sp<IMediaSource> getTrack(size_t index) = 0;
-
-    enum GetTrackMetaDataFlags {
-        kIncludeExtensiveMetaData = 1
-    };
-    virtual sp<MetaData> getTrackMetaData(
-            size_t index, uint32_t flags = 0) = 0;
-
-    // Return container specific meta-data. The default implementation
-    // returns an empty metadata object.
-    virtual sp<MetaData> getMetaData() = 0;
-
-    virtual status_t getMetrics(Parcel *reply) = 0;
-
-    enum Flags {
-        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
-        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
-        CAN_PAUSE          = 4,
-        CAN_SEEK           = 8,  // the "seek bar"
-    };
-
-    // If subclasses do _not_ override this, the default is
-    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
-    virtual uint32_t flags() const = 0;
-
-    virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
-
-    virtual const char * name() = 0;
-};
-
-
-class BnMediaExtractor: public BnInterface<IMediaExtractor>
-{
-public:
-    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-void registerMediaExtractor(
-        const sp<IMediaExtractor> &extractor,
-        const sp<DataSource> &source,
-        const char *mime);
-
-void registerMediaSource(
-        const sp<IMediaExtractor> &extractor,
-        const sp<IMediaSource> &source);
-
-status_t dumpExtractors(int fd, const Vector<String16>& args);
-
-
-}  // namespace android
-
-#endif  // IMEDIA_EXTRACTOR_BASE_H_
diff --git a/media/libmedia/include/media/IMediaExtractorService.h b/media/libmedia/include/media/IMediaExtractorService.h
deleted file mode 100644
index 5ce2cdb..0000000
--- a/media/libmedia/include/media/IMediaExtractorService.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 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 ANDROID_IMEDIAEXTRACTORSERVICE_H
-#define ANDROID_IMEDIAEXTRACTORSERVICE_H
-
-#include <unordered_set>
-
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <media/IDataSource.h>
-#include <media/IMediaExtractor.h>
-
-namespace android {
-
-class IMediaExtractorService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaExtractorService);
-
-    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
-
-    virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length) = 0;
-
-    virtual std::unordered_set<std::string> getSupportedTypes() = 0;
-};
-
-class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
-{
-public:
-    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-}   // namespace android
-
-#endif  // ANDROID_IMEDIAEXTRACTORSERVICE_H
diff --git a/media/libmedia/include/media/IMediaMetadataRetriever.h b/media/libmedia/include/media/IMediaMetadataRetriever.h
index c6f422d..28d2192 100644
--- a/media/libmedia/include/media/IMediaMetadataRetriever.h
+++ b/media/libmedia/include/media/IMediaMetadataRetriever.h
@@ -48,9 +48,8 @@
             int index, int colorFormat, bool metaOnly, bool thumbnail) = 0;
     virtual sp<IMemory>     getImageRectAtIndex(
             int index, int colorFormat, int left, int top, int right, int bottom) = 0;
-    virtual status_t        getFrameAtIndex(
-            std::vector<sp<IMemory> > *frames,
-            int frameIndex, int numFrames, int colorFormat, bool metaOnly) = 0;
+    virtual sp<IMemory>     getFrameAtIndex(
+            int index, int colorFormat, bool metaOnly) = 0;
     virtual sp<IMemory>     extractAlbumArt() = 0;
     virtual const char*     extractMetadata(int keyCode) = 0;
 };
diff --git a/media/libmedia/include/media/IMediaPlayer.h b/media/libmedia/include/media/IMediaPlayer.h
index 97a998e..a4c0ec6 100644
--- a/media/libmedia/include/media/IMediaPlayer.h
+++ b/media/libmedia/include/media/IMediaPlayer.h
@@ -23,7 +23,8 @@
 #include <utils/KeyedVector.h>
 #include <system/audio.h>
 
-#include <media/MediaSource.h>
+#include <media/AudioResamplerPublic.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/VolumeShaper.h>
 
 // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
@@ -38,7 +39,6 @@
 struct IStreamSource;
 class IGraphicBufferProducer;
 struct IMediaHTTPService;
-struct AudioPlaybackRate;
 struct AVSyncSettings;
 struct BufferingSettings;
 
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index f9c557c..651bd5e 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -44,6 +44,8 @@
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface) = 0;
     virtual status_t setVideoSource(int vs) = 0;
     virtual status_t setAudioSource(int as) = 0;
+    virtual status_t setPrivacySensitive(bool privacySensitive) = 0;
+    virtual status_t isPrivacySensitive(bool *privacySensitive) const = 0;
     virtual status_t setOutputFormat(int of) = 0;
     virtual status_t setVideoEncoder(int ve) = 0;
     virtual status_t setAudioEncoder(int ae) = 0;
diff --git a/media/libmedia/include/media/IMediaSource.h b/media/libmedia/include/media/IMediaSource.h
index 381df24..84310f0 100644
--- a/media/libmedia/include/media/IMediaSource.h
+++ b/media/libmedia/include/media/IMediaSource.h
@@ -22,7 +22,7 @@
 
 #include <binder/IInterface.h>
 #include <binder/IMemory.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaErrors.h>
 
@@ -135,6 +135,7 @@
 
 private:
     uint32_t mBuffersSinceStop; // Buffer tracking variable
+    Mutex mBnLock; // to guard readMultiple against concurrent access to the buffer cache
 
     std::unique_ptr<MediaBufferGroup> mGroup;
 
diff --git a/media/libmedia/include/media/IOMX.h b/media/libmedia/include/media/IOMX.h
index 7e7c2d2..70c8a74 100644
--- a/media/libmedia/include/media/IOMX.h
+++ b/media/libmedia/include/media/IOMX.h
@@ -34,9 +34,17 @@
 #include <media/openmax/OMX_VideoExt.h>
 
 namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+struct IGraphicBufferSource;
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
 
 class IGraphicBufferProducer;
-class IGraphicBufferSource;
 class IMemory;
 class IOMXBufferSource;
 class IOMXNode;
@@ -82,7 +90,7 @@
 
     virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource) = 0;
+            sp<hardware::media::omx::V1_0::IGraphicBufferSource> *bufferSource) = 0;
 };
 
 class IOMXNode : public IInterface {
diff --git a/media/libmedia/include/media/IResourceManagerClient.h b/media/libmedia/include/media/IResourceManagerClient.h
deleted file mode 100644
index aa0cd88..0000000
--- a/media/libmedia/include/media/IResourceManagerClient.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015 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 ANDROID_IRESOURCEMANAGERCLIENT_H
-#define ANDROID_IRESOURCEMANAGERCLIENT_H
-
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class IResourceManagerClient: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(ResourceManagerClient);
-
-    virtual bool reclaimResource() = 0;
-    virtual String8 getName() = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnResourceManagerClient: public BnInterface<IResourceManagerClient>
-{
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel &data,
-                                Parcel *reply,
-                                uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IRESOURCEMANAGERCLIENT_H
diff --git a/media/libmedia/include/media/IResourceManagerService.h b/media/libmedia/include/media/IResourceManagerService.h
deleted file mode 100644
index 8992f8b..0000000
--- a/media/libmedia/include/media/IResourceManagerService.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2015 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 ANDROID_IRESOURCEMANAGERSERVICE_H
-#define ANDROID_IRESOURCEMANAGERSERVICE_H
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <media/IResourceManagerClient.h>
-#include <media/MediaResource.h>
-#include <media/MediaResourcePolicy.h>
-
-namespace android {
-
-class IResourceManagerService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(ResourceManagerService);
-
-    virtual void config(const Vector<MediaResourcePolicy> &policies) = 0;
-
-    virtual void addResource(
-            int pid,
-            int uid,
-            int64_t clientId,
-            const sp<IResourceManagerClient> client,
-            const Vector<MediaResource> &resources) = 0;
-
-    virtual void removeResource(int pid, int64_t clientId,
-            const Vector<MediaResource> &resources) = 0;
-
-    virtual void removeClient(int pid, int64_t clientId) = 0;
-
-    virtual bool reclaimResource(
-            int callingPid,
-            const Vector<MediaResource> &resources) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnResourceManagerService: public BnInterface<IResourceManagerService>
-{
-public:
-    virtual status_t onTransact(uint32_t code,
-                                const Parcel &data,
-                                Parcel *reply,
-                                uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IRESOURCEMANAGERSERVICE_H
diff --git a/media/libmedia/include/media/JetPlayer.h b/media/libmedia/include/media/JetPlayer.h
deleted file mode 100644
index bb569bc..0000000
--- a/media/libmedia/include/media/JetPlayer.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2008 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 JETPLAYER_H_
-#define JETPLAYER_H_
-
-#include <utils/threads.h>
-
-#include <libsonivox/jet.h>
-#include <libsonivox/eas_types.h>
-#include <media/AudioTrack.h>
-#include <media/MidiIoWrapper.h>
-
-
-namespace android {
-
-typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
-
-class JetPlayer {
-
-public:
-
-    // to keep in sync with the JetPlayer class constants
-    // defined in frameworks/base/media/java/android/media/JetPlayer.java
-    static const int JET_EVENT                   = 1;
-    static const int JET_USERID_UPDATE           = 2;
-    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
-    static const int JET_PAUSE_UPDATE            = 4;
-
-    JetPlayer(void *javaJetPlayer,
-            int maxTracks = 32,
-            int trackBufferSize = 1200);
-    ~JetPlayer();
-    int init();
-    int release();
-
-    int loadFromFile(const char* url);
-    int loadFromFD(const int fd, const long long offset, const long long length);
-    int closeFile();
-    int play();
-    int pause();
-    int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
-            EAS_U32 muteFlags, EAS_U8 userID);
-    int setMuteFlags(EAS_U32 muteFlags, bool sync);
-    int setMuteFlag(int trackNum, bool muteFlag, bool sync);
-    int triggerClip(int clipId);
-    int clearQueue();
-
-    void setEventCallback(jetevent_callback callback);
-
-    int getMaxTracks() { return mMaxTracks; };
-
-
-private:
-    int                 render();
-    void                fireUpdateOnStatusChange();
-    void                fireEventsFromJetQueue();
-
-    JetPlayer() {} // no default constructor
-    void dump();
-    void dumpJetStatus(S_JET_STATUS* pJetStatus);
-
-    jetevent_callback   mEventCallback;
-
-    void*               mJavaJetPlayerRef;
-    Mutex               mMutex; // mutex to sync the render and playback thread with the JET calls
-    pid_t               mTid;
-    Condition           mCondition;
-    volatile bool       mRender;
-    bool                mPaused;
-
-    EAS_STATE           mState;
-    int*                mMemFailedVar;
-
-    int                 mMaxTracks; // max number of MIDI tracks, usually 32
-    EAS_DATA_HANDLE     mEasData;
-    MidiIoWrapper*      mIoWrapper;
-    EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
-    sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
-    int                 mTrackBufferSize;
-    S_JET_STATUS        mJetStatus;
-    S_JET_STATUS        mPreviousJetStatus;
-
-    class JetPlayerThread : public Thread {
-    public:
-        JetPlayerThread(JetPlayer *player) : mPlayer(player) {
-        }
-
-    protected:
-        virtual ~JetPlayerThread() {}
-
-    private:
-        JetPlayer *mPlayer;
-
-        bool threadLoop() {
-            int result;
-            result = mPlayer->render();
-            return false;
-        }
-
-        JetPlayerThread(const JetPlayerThread &);
-        JetPlayerThread &operator=(const JetPlayerThread &);
-    };
-
-    sp<JetPlayerThread> mThread;
-
-}; // end class JetPlayer
-
-} // end namespace android
-
-
-
-#endif /*JETPLAYER_H_*/
diff --git a/media/libmedia/include/media/LinearMap.h b/media/libmedia/include/media/LinearMap.h
deleted file mode 100644
index 2220a0c..0000000
--- a/media/libmedia/include/media/LinearMap.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright 2015 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 ANDROID_LINEAR_MAP_H
-#define ANDROID_LINEAR_MAP_H
-
-#include <stdint.h>
-
-namespace android {
-
-/*
-A general purpose lookup utility that defines a mapping between X and Y as a
-continuous set of line segments with shared (x, y) end-points.
-The (x, y) points must be added in order, monotonically increasing in both x and y;
-a log warning is emitted if this does not happen (See general usage notes below).
-
-A limited history of (x, y) points is kept for space reasons (See general usage notes).
-
-In AudioFlinger, we use the LinearMap to associate track frames to
-sink frames.  When we want to obtain a client track timestamp, we first
-get a timestamp from the sink.  The sink timestamp's position (mPosition)
-corresponds to the sink frames written. We use LinearMap to figure out which track frame
-the sink frame corresponds to. This allows us to substitute a track frame for the
-the sink frame (keeping the mTime identical) and return that timestamp back to the client.
-
-The method findX() can be used to retrieve an x value from a given y value and is
-used for timestamps, similarly for findY() which is provided for completeness.
-
-We update the (track frame, sink frame) points in the LinearMap each time we write data
-to the sink by the AudioFlinger PlaybackThread (MixerThread).
-
-
-AudioFlinger Timestamp Notes:
-
-1) Example: Obtaining a track timestamp during playback.  In this case, the LinearMap
-looks something like this:
-
-Track Frame    Sink Frame
-(track start)
-0              50000  (track starts here, the sink may already be running)
-1000           51000
-2000           52000
-
-When we request a track timestamp, we call the sink getTimestamp() and get for example
-mPosition = 51020.  Using the LinearMap, we find we have played to track frame 1020.
-We substitute the sink mPosition of 51020 with the track position 1020,
-and return that timestamp to the app.
-
-2) Example: Obtaining a track timestamp duing pause. In this case, the LinearMap
-looks something like this:
-
-Track Frame    Sink Frame
-... (some time has gone by)
-15000          30000
-16000          31000
-17000          32000
-(pause here)
-(suppose we call sink getTimestamp() here and get sink mPosition = 31100; that means
-        we have played to track frame 16100.  The track timestamp mPosition will
-        continue to advance until the sink timestamp returns a value of mPosition
-        greater than 32000, corresponding to track frame 17000 when the pause was called).
-17000          33000
-17000          34000
-...
-
-3) If the track underruns, it appears as if a pause was called on that track.
-
-4) If there is an underrun in the HAL layer, then it may be possible that
-the sink getTimestamp() will return a value greater than the number of frames written
-(it should always be less). This should be rare, if not impossible by some
-HAL implementations of the sink getTimestamp. In that case, timing is lost
-and we will return the most recent track frame written.
-
-5) When called with no points in the map, findX() returns the start value (default 0).
-This is consistent with starting after a stop() or flush().
-
-6) Resuming after Track standby will be similar to coming out of pause, as the HAL ensures
-framesWritten() and getTimestamp() are contiguous for non-offloaded/direct tracks.
-
-7) LinearMap works for different speeds and sample rates as it uses
-linear interpolation. Since AudioFlinger only updates speed and sample rate
-exactly at the sample points pushed into the LinearMap, the returned values
-from findX() and findY() are accurate regardless of how many speed or sample
-rate changes are made, so long as the coordinate looked up is within the
-sample history.
-
-General usage notes:
-
-1) In order for the LinearMap to work reliably, you cannot look backwards more
-than the size of its circular buffer history, set upon creation (typically 16).
-If you look back further, the position is extrapolated either from a passed in
-extrapolation parameter or from the oldest line segment.
-
-2) Points must monotonically increase in x and y. The increment between adjacent
-points cannot be greater than signed 32 bits. Wrap in the x, y coordinates are supported,
-since we use differences in our computation.
-
-3) If the frame data is discontinuous (due to stop or flush) call reset() to clear
-the sample counter.
-
-4) If (x, y) are not strictly monotonic increasing, i.e. (x2 > x1) and (y2 > y1),
-then one or both of the inverses y = f(x) or x = g(y) may have multiple solutions.
-In that case, the most recent solution is returned by findX() or findY().  We
-do not warn if (x2 == x1) or (y2 == y1), but we do logcat warn if (x2 < x1) or
-(y2 < y1).
-
-5) Due to rounding it is possible x != findX(findY(x)) or y != findY(findX(y))
-even when the inverse exists. Nevertheless, the values should be close.
-
-*/
-
-template <typename T>
-class LinearMap {
-public:
-    // This enumeration describes the reliability of the findX() or findY() estimation
-    // in descending order.
-    enum FindMethod {
-        FIND_METHOD_INTERPOLATION,           // High reliability (errors due to rounding)
-        FIND_METHOD_FORWARD_EXTRAPOLATION,   // Reliability based on no future speed changes
-        FIND_METHOD_BACKWARD_EXTRAPOLATION,  // Reliability based on prior estimated speed
-        FIND_METHOD_START_VALUE,             // No samples in history, using start value
-    };
-
-    explicit LinearMap(size_t size)
-            : mSize(size),
-              mPos(0), // a circular buffer, so could start anywhere. the first sample is at 1.
-              mSamples(0),
-              // mStepValid(false),      // only valid if mSamples > 1
-              // mExtrapolateTail(false), // only valid if mSamples > 0
-              mX(new T[size]),
-              mY(new T[size]) { }
-
-    ~LinearMap() {
-        delete[] mX;
-        delete[] mY;
-    }
-
-    // Add a new sample point to the linear map.
-    //
-    // The difference between the new sample and the previous sample
-    // in the x or y coordinate must be less than INT32_MAX for purposes
-    // of the linear interpolation or extrapolation.
-    //
-    // The value should be monotonic increasing (e.g. diff >= 0);
-    // logcat warnings are issued if they are not.
-    __attribute__((no_sanitize("integer")))
-    void push(T x, T y) {
-        // Assumption: we assume x, y are monotonic increasing values,
-        // which (can) wrap in precision no less than 32 bits and have
-        // "step" or differences between adjacent points less than 32 bits.
-
-        if (mSamples > 0) {
-            const bool lastStepValid = mStepValid;
-            int32_t xdiff;
-            int32_t ydiff;
-            // check difference assumption here
-            mStepValid = checkedDiff(&xdiff, x, mX[mPos], "x")
-                    & /* bitwise AND to always warn for ydiff, though logical AND is also OK */
-                    checkedDiff(&ydiff, y, mY[mPos], "y");
-
-            // Optimization: do not add a new sample if the line segment would
-            // simply extend the previous line segment.  This extends the useful
-            // history by removing redundant points.
-            if (mSamples > 1 && mStepValid && lastStepValid) {
-                const size_t prev = previousPosition();
-                const int32_t xdiff2 = x - mX[prev];
-                const int32_t ydiff2 = y - mY[prev];
-
-                // if both current step and previous step are valid (non-negative and
-                // less than INT32_MAX for precision greater than 4 bytes)
-                // then the sum of the two steps is valid when the
-                // int32_t difference is non-negative.
-                if (xdiff2 >= 0 && ydiff2 >= 0
-                        && (int64_t)xdiff2 * ydiff == (int64_t)ydiff2 * xdiff) {
-                    // ALOGD("reusing sample! (%u, %u) sample depth %zd", x, y, mSamples);
-                    mX[mPos] = x;
-                    mY[mPos] = y;
-                    return;
-                }
-            }
-        }
-        if (++mPos >= mSize) {
-            mPos = 0;
-        }
-        if (mSamples < mSize) {
-            mExtrapolateTail = false;
-            ++mSamples;
-        } else {
-            // we enable extrapolation beyond the oldest sample
-            // if the sample buffers are completely full and we
-            // no longer know the full history.
-            mExtrapolateTail = true;
-        }
-        mX[mPos] = x;
-        mY[mPos] = y;
-    }
-
-    // clear all samples from the circular array
-    void reset() {
-        // no need to reset mPos, we use a circular buffer.
-        // computed values such as mStepValid are set after a subsequent push().
-        mSamples = 0;
-    }
-
-    // returns true if LinearMap contains at least one sample.
-    bool hasData() const {
-        return mSamples != 0;
-    }
-
-    // find the corresponding X point from a Y point.
-    // See findU for details.
-    __attribute__((no_sanitize("integer")))
-    T findX(T y, FindMethod *method = NULL, double extrapolation = 0.0, T startValue = 0) const {
-        return findU(y, mX, mY, method, extrapolation, startValue);
-    }
-
-    // find the corresponding Y point from a X point.
-    // See findU for details.
-    __attribute__((no_sanitize("integer")))
-    T findY(T x, FindMethod *method = NULL, double extrapolation = 0.0, T startValue = 0) const {
-        return findU(x, mY, mX, method, extrapolation, startValue);
-    }
-
-protected:
-
-    // returns false if the diff is out of int32_t bounds or negative.
-    __attribute__((no_sanitize("integer")))
-    static inline bool checkedDiff(int32_t *diff, T x2, T x1, const char *coord) {
-        if (sizeof(T) >= 8) {
-            const int64_t diff64 = x2 - x1;
-            *diff = (int32_t)diff64;  // intentionally lose precision
-            if (diff64 > INT32_MAX) {
-                ALOGW("LinearMap: %s overflow diff(%lld) from %llu - %llu exceeds INT32_MAX",
-                        coord, (long long)diff64,
-                        (unsigned long long)x2, (unsigned long long)x1);
-                return false;
-            } else if (diff64 < 0) {
-                ALOGW("LinearMap: %s negative diff(%lld) from %llu - %llu",
-                        coord, (long long)diff64,
-                        (unsigned long long)x2, (unsigned long long)x1);
-                return false;
-            }
-            return true;
-        }
-        // for 32 bit integers we cannot detect overflow (it
-        // shows up as a negative difference).
-        *diff = x2 - x1;
-        if (*diff < 0) {
-            ALOGW("LinearMap: %s negative diff(%d) from %u - %u",
-                    coord, *diff, (unsigned)x2, (unsigned)x1);
-            return false;
-        }
-        return true;
-    }
-
-    // Returns the previous position in the mSamples array
-    // going backwards back steps.
-    //
-    // Parameters:
-    //   back: number of backward steps, cannot be less than zero or greater than mSamples.
-    //
-    __attribute__((no_sanitize("integer")))
-    size_t previousPosition(ssize_t back = 1) const {
-        LOG_ALWAYS_FATAL_IF(back < 0 || (size_t)back > mSamples, "Invalid back(%zd)", back);
-        ssize_t position = mPos - back;
-        if (position < 0) position += mSize;
-        return (size_t)position;
-    }
-
-    // A generic implementation of finding the "other coordinate" with coordinates
-    // (u, v) = (x, y) or (u, v) = (y, x).
-    //
-    // Parameters:
-    //   uArray: the u axis samples.
-    //   vArray: the v axis samples.
-    //   method: [out] how the returned value was computed.
-    //   extrapolation: the slope used when extrapolating from the
-    //     first sample value or the last sample value in the history.
-    //     If mExtrapolateTail is set, the slope of the last line segment
-    //     is used if the extrapolation parameter is zero to continue the tail of history.
-    //     At this time, we do not use a different value for forward extrapolation from the
-    //     head of history from backward extrapolation from the tail of history.
-    //     TODO: back extrapolation value could be stored along with mX, mY in history.
-    //   startValue: used only when there are no samples in history. One can detect
-    //     whether there are samples in history by the method hasData().
-    //
-    __attribute__((no_sanitize("integer")))
-    T findU(T v, T *uArray, T *vArray, FindMethod *method,
-            double extrapolation, T startValue) const {
-        if (mSamples == 0) {
-            if (method != NULL) {
-                *method = FIND_METHOD_START_VALUE;
-            }
-            return startValue;  // nothing yet
-        }
-        ssize_t previous = 0;
-        int32_t diff = 0;
-        for (ssize_t i = 0; i < (ssize_t)mSamples; ++i) {
-            size_t current = previousPosition(i);
-
-            // Assumption: even though the type "T" may have precision greater
-            // than 32 bits, the difference between adjacent points is limited to 32 bits.
-            diff = v - vArray[current];
-            if (diff >= 0 ||
-                    (i == (ssize_t)mSamples - 1 && mExtrapolateTail && extrapolation == 0.0)) {
-                // ALOGD("depth = %zd out of %zd", i, limit);
-                if (i == 0) {
-                    if (method != NULL) {
-                        *method = FIND_METHOD_FORWARD_EXTRAPOLATION;
-                    }
-                    return uArray[current] + diff * extrapolation;
-                }
-                // interpolate / extrapolate: For this computation, we
-                // must use differentials here otherwise we have inconsistent
-                // values on modulo wrap. previous is always valid here since
-                // i > 0.  we also perform rounding with the assumption
-                // that uStep, vStep, and diff are non-negative.
-                int32_t uStep = uArray[previous] - uArray[current]; // non-negative
-                int32_t vStep = vArray[previous] - vArray[current]; // positive
-                T u = uStep <= 0 || vStep <= 0 ?  // we do not permit negative ustep or vstep
-                        uArray[current]
-                      : ((int64_t)diff * uStep + (vStep >> 1)) / vStep + uArray[current];
-                // ALOGD("u:%u  diff:%d  uStep:%d  vStep:%d  u_current:%d",
-                //         u, diff, uStep, vStep, uArray[current]);
-                if (method != NULL) {
-                    *method = (diff >= 0) ?
-                            FIND_METHOD_INTERPOLATION : FIND_METHOD_BACKWARD_EXTRAPOLATION;
-                }
-                return u;
-            }
-            previous = current;
-        }
-        // previous is always valid here.
-        if (method != NULL) {
-            *method = FIND_METHOD_BACKWARD_EXTRAPOLATION;
-        }
-        return uArray[previous] + diff * extrapolation;
-    }
-
-private:
-    const size_t    mSize;      // Size of mX and mY arrays (history).
-    size_t          mPos;       // Index in mX and mY of last pushed data;
-                                // (incremented after push) [0, mSize - 1].
-    size_t          mSamples;   // Number of valid samples in the array [0, mSize].
-    bool            mStepValid; // Last sample step was valid (non-negative)
-    bool            mExtrapolateTail; // extrapolate tail using oldest line segment
-    T * const       mX;         // History of X values as a circular array.
-    T * const       mY;         // History of Y values as a circular array.
-};
-
-} // namespace android
-
-#endif // ANDROID_LINEAR_MAP_H
diff --git a/media/libmedia/include/media/MediaCodecBuffer.h b/media/libmedia/include/media/MediaCodecBuffer.h
index 2c16fba..101377c 100644
--- a/media/libmedia/include/media/MediaCodecBuffer.h
+++ b/media/libmedia/include/media/MediaCodecBuffer.h
@@ -22,6 +22,8 @@
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
 
+class C2Buffer;
+
 namespace android {
 
 struct ABuffer;
@@ -57,6 +59,36 @@
 
     void setFormat(const sp<AMessage> &format);
 
+    /**
+     * \return  C2Buffer object represents this buffer.
+     */
+    virtual std::shared_ptr<C2Buffer> asC2Buffer() { return nullptr; }
+
+    /**
+     * Test if we can copy the content of |buffer| into this object.
+     *
+     * \param   buffer  C2Buffer object to copy.
+     * \return  true    if the content of buffer can be copied over to this buffer
+     *          false   otherwise.
+     */
+    virtual bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
+        (void)buffer;
+        return false;
+    }
+
+    /**
+     * Copy the content of |buffer| into this object. This method assumes that
+     * canCopy() check already passed.
+     *
+     * \param   buffer  C2Buffer object to copy.
+     * \return  true    if successful
+     *          false   otherwise.
+     */
+    virtual bool copy(const std::shared_ptr<C2Buffer> &buffer) {
+        (void)buffer;
+        return false;
+    }
+
 private:
     MediaCodecBuffer() = delete;
 
diff --git a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
index 98d300f..37dc401 100644
--- a/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
+++ b/media/libmedia/include/media/MediaMetadataRetrieverInterface.h
@@ -49,9 +49,8 @@
             int index, int colorFormat, bool metaOnly, bool thumbnail) = 0;
     virtual sp<IMemory> getImageRectAtIndex(
             int index, int colorFormat, int left, int top, int right, int bottom) = 0;
-    virtual status_t getFrameAtIndex(
-            std::vector<sp<IMemory> >* frames,
-            int frameIndex, int numFrames, int colorFormat, bool metaOnly) = 0;
+    virtual sp<IMemory> getFrameAtIndex(
+            int frameIndex, int colorFormat, bool metaOnly) = 0;
     virtual MediaAlbumArt* extractAlbumArt() = 0;
     virtual const char* extractMetadata(int keyCode) = 0;
 };
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 3e8e7c8..4cc5b95 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -1,18 +1,18 @@
 /*
- **
- ** Copyright 2010, 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.
+ *
+ * Copyright 2010, 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 ANDROID_MEDIAPROFILES_H
@@ -82,29 +82,12 @@
 {
 public:
 
-    /*
-     * If property media.settings.xml is not set:
-     *
-     * getInstance() will search through paths listed in xmlFiles.
-     * The search goes through members of xmlFiles in the order that they are
-     * defined, so files at lower indices have higher priority than those at
-     * higher indices.
-     *
-     * TODO: Add runtime validation of xml files. A search should be considered
-     * successful only when validation is successful.
-     */
-    static constexpr char const * const xmlFiles[] = {
-            "odm/etc/media_profiles_V1_0.xml",
-            "vendor/etc/media_profiles_V1_0.xml",
-            "system/etc/media_profiles.xml"
-            };
-
     /**
      * Returns the singleton instance for subsequence queries or NULL if error.
      *
      * If property media.settings.xml is set, getInstance() will attempt to read
      * from file path in media.settings.xml. Otherwise, getInstance() will
-     * search through the list xmlFiles as described above.
+     * search through the list of preset XML file paths.
      *
      * If the search is unsuccessful, the default instance will be created
      * instead.
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index a2dff31..8493f64 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -39,6 +39,8 @@
 
     virtual status_t init() = 0;
     virtual status_t setAudioSource(audio_source_t as) = 0;
+    virtual status_t setPrivacySensitive(bool privacySensitive) = 0 ;
+    virtual status_t isPrivacySensitive(bool *privacySensitive) const = 0;
     virtual status_t setVideoSource(video_source vs) = 0;
     virtual status_t setOutputFormat(output_format of) = 0;
     virtual status_t setAudioEncoder(audio_encoder ae) = 0;
@@ -79,6 +81,7 @@
 
 
 protected:
+
     String16 mOpPackageName;
 
 private:
diff --git a/media/libmedia/include/media/MediaResource.h b/media/libmedia/include/media/MediaResource.h
index 10a07bb..e7362c1 100644
--- a/media/libmedia/include/media/MediaResource.h
+++ b/media/libmedia/include/media/MediaResource.h
@@ -18,66 +18,56 @@
 #ifndef ANDROID_MEDIA_RESOURCE_H
 #define ANDROID_MEDIA_RESOURCE_H
 
-#include <binder/Parcel.h>
+#include <aidl/android/media/MediaResourceParcel.h>
 #include <utils/String8.h>
 
 namespace android {
 
-class MediaResource {
+using aidl::android::media::MediaResourceParcel;
+using aidl::android::media::MediaResourceSubType;
+using aidl::android::media::MediaResourceType;
+
+class MediaResource : public MediaResourceParcel {
 public:
-    enum Type {
-        kUnspecified = 0,
-        kSecureCodec,
-        kNonSecureCodec,
-        kGraphicMemory,
-        kCpuBoost,
-        kBattery,
-    };
+    using Type = MediaResourceType;
+    using SubType = MediaResourceSubType;
 
-    enum SubType {
-        kUnspecifiedSubType = 0,
-        kAudioCodec,
-        kVideoCodec,
-    };
+    MediaResource() = delete;
+    MediaResource(Type type, int64_t value);
+    MediaResource(Type type, SubType subType, int64_t value);
+    MediaResource(Type type, const std::vector<int8_t> &id, int64_t value);
 
-    MediaResource();
-    MediaResource(Type type, uint64_t value);
-    MediaResource(Type type, SubType subType, uint64_t value);
-
-    void readFromParcel(const Parcel &parcel);
-    void writeToParcel(Parcel *parcel) const;
-
-    String8 toString() const;
-
-    bool operator==(const MediaResource &other) const;
-    bool operator!=(const MediaResource &other) const;
-
-    Type mType;
-    SubType mSubType;
-    uint64_t mValue;
+    static MediaResource CodecResource(bool secure, bool video);
+    static MediaResource GraphicMemoryResource(int64_t value);
+    static MediaResource CpuBoostResource();
+    static MediaResource VideoBatteryResource();
+    static MediaResource DrmSessionResource(const std::vector<int8_t> &id, int64_t value);
 };
 
 inline static const char *asString(MediaResource::Type i, const char *def = "??") {
     switch (i) {
-        case MediaResource::kUnspecified:    return "unspecified";
-        case MediaResource::kSecureCodec:    return "secure-codec";
-        case MediaResource::kNonSecureCodec: return "non-secure-codec";
-        case MediaResource::kGraphicMemory:  return "graphic-memory";
-        case MediaResource::kCpuBoost:       return "cpu-boost";
-        case MediaResource::kBattery:        return "battery";
-        default:                             return def;
+        case MediaResource::Type::kUnspecified:    return "unspecified";
+        case MediaResource::Type::kSecureCodec:    return "secure-codec";
+        case MediaResource::Type::kNonSecureCodec: return "non-secure-codec";
+        case MediaResource::Type::kGraphicMemory:  return "graphic-memory";
+        case MediaResource::Type::kCpuBoost:       return "cpu-boost";
+        case MediaResource::Type::kBattery:        return "battery";
+        case MediaResource::Type::kDrmSession:     return "drm-session";
+        default:                                   return def;
     }
 }
 
 inline static const char *asString(MediaResource::SubType i, const char *def = "??") {
     switch (i) {
-        case MediaResource::kUnspecifiedSubType: return "unspecified";
-        case MediaResource::kAudioCodec:         return "audio-codec";
-        case MediaResource::kVideoCodec:         return "video-codec";
+        case MediaResource::SubType::kUnspecifiedSubType: return "unspecified";
+        case MediaResource::SubType::kAudioCodec:         return "audio-codec";
+        case MediaResource::SubType::kVideoCodec:         return "video-codec";
         default:                                 return def;
     }
 }
 
+String8 toString(const MediaResourceParcel& resource);
+
 }; // namespace android
 
 #endif  // ANDROID_MEDIA_RESOURCE_H
diff --git a/media/libmedia/include/media/MediaResourcePolicy.h b/media/libmedia/include/media/MediaResourcePolicy.h
index 9bc2eec..052395b 100644
--- a/media/libmedia/include/media/MediaResourcePolicy.h
+++ b/media/libmedia/include/media/MediaResourcePolicy.h
@@ -18,28 +18,24 @@
 #ifndef ANDROID_MEDIA_RESOURCE_POLICY_H
 #define ANDROID_MEDIA_RESOURCE_POLICY_H
 
-#include <binder/Parcel.h>
+#include <aidl/android/media/MediaResourcePolicyParcel.h>
 #include <utils/String8.h>
 
 namespace android {
 
-extern const char kPolicySupportsMultipleSecureCodecs[];
-extern const char kPolicySupportsSecureWithNonSecureCodec[];
+using aidl::android::media::MediaResourcePolicyParcel;
 
-class MediaResourcePolicy {
+class MediaResourcePolicy : public MediaResourcePolicyParcel {
 public:
-    MediaResourcePolicy();
-    MediaResourcePolicy(String8 type, String8 value);
+    MediaResourcePolicy() = delete;
+    MediaResourcePolicy(const std::string& type, const std::string& value);
 
-    void readFromParcel(const Parcel &parcel);
-    void writeToParcel(Parcel *parcel) const;
-
-    String8 toString() const;
-
-    String8 mType;
-    String8 mValue;
+    static const char* kPolicySupportsMultipleSecureCodecs();
+    static const char* kPolicySupportsSecureWithNonSecureCodec();
 };
 
+String8 toString(const MediaResourcePolicyParcel &policy);
+
 }; // namespace android
 
 #endif  // ANDROID_MEDIA_RESOURCE_POLICY_H
diff --git a/media/libmedia/include/media/MidiDeviceInfo.h b/media/libmedia/include/media/MidiDeviceInfo.h
deleted file mode 100644
index 5b4a241..0000000
--- a/media/libmedia/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-
-#include <binder/Parcelable.h>
-#include <binder/PersistableBundle.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-class MidiDeviceInfo : public Parcelable {
-public:
-    MidiDeviceInfo() = default;
-    virtual ~MidiDeviceInfo() = default;
-    MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
-
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
-    int getType() const { return mType; }
-    int getUid() const { return mId; }
-    bool isPrivate() const { return mIsPrivate; }
-    const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
-    const Vector<String16>&  getOutputPortNames() const { return mOutputPortNames; }
-    String16 getProperty(const char* propertyName);
-
-    // The constants need to be kept in sync with MidiDeviceInfo.java
-    enum {
-        TYPE_USB = 1,
-        TYPE_VIRTUAL = 2,
-        TYPE_BLUETOOTH = 3,
-    };
-    static const char* const PROPERTY_NAME;
-    static const char* const PROPERTY_MANUFACTURER;
-    static const char* const PROPERTY_PRODUCT;
-    static const char* const PROPERTY_VERSION;
-    static const char* const PROPERTY_SERIAL_NUMBER;
-    static const char* const PROPERTY_ALSA_CARD;
-    static const char* const PROPERTY_ALSA_DEVICE;
-
-    friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
-    friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-        return !(lhs == rhs);
-    }
-
-private:
-    status_t readStringVector(
-            const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
-    status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
-
-    int32_t mType;
-    int32_t mId;
-    Vector<String16> mInputPortNames;
-    Vector<String16> mOutputPortNames;
-    os::PersistableBundle mProperties;
-    bool mIsPrivate;
-};
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
-
-#endif  // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index b19d49e..0cdd4ad 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -19,12 +19,9 @@
 
 #include <libsonivox/eas_types.h>
 
-#include <media/DataSourceBase.h>
-
 namespace android {
 
 struct CDataSource;
-class DataSourceUnwrapper;
 
 class MidiIoWrapper {
 public:
@@ -43,6 +40,7 @@
     int mFd;
     off64_t mBase;
     int64_t  mLength;
+    class DataSourceUnwrapper;
     DataSourceUnwrapper *mDataSource;
     EAS_FILE mEasFile;
 };
diff --git a/media/libmedia/include/media/Modulo.h b/media/libmedia/include/media/Modulo.h
index 23280ac..c66928d 100644
--- a/media/libmedia/include/media/Modulo.h
+++ b/media/libmedia/include/media/Modulo.h
@@ -90,7 +90,7 @@
     typedef typename std::make_unsigned<T>::type unsignedT;
 
     Modulo() { } // intentionally uninitialized data
-    Modulo(const T &value) { mValue = value; }
+    Modulo(const T &value) { mValue = value; } // NOLINT
     const T & value() const { return mValue; } // not assignable
     signedT signedValue() const { return mValue; }
     unsignedT unsignedValue() const { return mValue; }
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index 8a417f6..39c0574 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -19,7 +19,7 @@
 #define NDK_WRAPPER_H_
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/NdkMediaDataSource.h>
 #include <media/NdkMediaError.h>
 #include <media/NdkMediaExtractor.h>
diff --git a/media/libmedia/include/media/PluginMetricsReporting.h b/media/libmedia/include/media/PluginMetricsReporting.h
index e00bd43..f71c52d 100644
--- a/media/libmedia/include/media/PluginMetricsReporting.h
+++ b/media/libmedia/include/media/PluginMetricsReporting.h
@@ -18,6 +18,7 @@
 
 #define PLUGIN_METRICS_REPORTING_H_
 
+#include <sys/types.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 
@@ -26,7 +27,7 @@
 status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
                                 const String8& vendorName,
                                 const String8& description,
-                                const String8& appPackageName);
+                                uid_t appUid);
 
 }  // namespace android
 
diff --git a/media/libmedia/include/media/TypeConverter.h b/media/libmedia/include/media/TypeConverter.h
deleted file mode 100644
index 2f8c209..0000000
--- a/media/libmedia/include/media/TypeConverter.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_TYPE_CONVERTER_H_
-#define ANDROID_TYPE_CONVERTER_H_
-
-#include <string>
-#include <string.h>
-
-#include <vector>
-#include <system/audio.h>
-#include <utils/Log.h>
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-
-#include <media/AudioParameter.h>
-#include "convert.h"
-
-namespace android {
-
-template <typename T>
-struct DefaultTraits
-{
-    typedef T Type;
-    typedef std::vector<Type> Collection;
-    static void add(Collection &collection, Type value)
-    {
-        collection.push_back(value);
-    }
-};
-template <typename T>
-struct VectorTraits
-{
-    typedef T Type;
-    typedef Vector<Type> Collection;
-    static void add(Collection &collection, Type value)
-    {
-        collection.add(value);
-    }
-};
-template <typename T>
-struct SortedVectorTraits
-{
-    typedef T Type;
-    typedef SortedVector<Type> Collection;
-    static void add(Collection &collection, Type value)
-    {
-        collection.add(value);
-    }
-};
-
-using SampleRateTraits = SortedVectorTraits<uint32_t>;
-using DeviceTraits = DefaultTraits<audio_devices_t>;
-struct OutputDeviceTraits : public DeviceTraits {};
-struct InputDeviceTraits : public DeviceTraits {};
-using ChannelTraits = SortedVectorTraits<audio_channel_mask_t>;
-struct OutputChannelTraits : public ChannelTraits {};
-struct InputChannelTraits : public ChannelTraits {};
-struct ChannelIndexTraits : public ChannelTraits {};
-using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
-using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
-using FormatTraits = VectorTraits<audio_format_t>;
-using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
-using StreamTraits = DefaultTraits<audio_stream_type_t>;
-using AudioModeTraits = DefaultTraits<audio_mode_t>;
-using AudioContentTraits = DefaultTraits<audio_content_type_t>;
-using UsageTraits = DefaultTraits<audio_usage_t>;
-using SourceTraits = DefaultTraits<audio_source_t>;
-struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
-
-template <class Traits>
-static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
-                                 const char *del = AudioParameter::valueListSeparator)
-{
-    char *literal = strdup(str.c_str());
-    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
-        typename Traits::Type value;
-        if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
-            Traits::add(collection, value);
-        }
-    }
-    free(literal);
-}
-
-template <class Traits>
-class TypeConverter
-{
-public:
-    static bool toString(const typename Traits::Type &value, std::string &str);
-
-    static bool fromString(const std::string &str, typename Traits::Type &result);
-
-    static void collectionFromString(const std::string &str,
-                                     typename Traits::Collection &collection,
-                                     const char *del = AudioParameter::valueListSeparator);
-
-    static uint32_t maskFromString(
-            const std::string &str, const char *del = AudioParameter::valueListSeparator);
-
-    static void maskToString(
-            uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);
-
-protected:
-    struct Table {
-        const char *literal;
-        typename Traits::Type value;
-    };
-
-    static const Table mTable[];
-};
-
-template <class Traits>
-inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
-{
-    for (size_t i = 0; mTable[i].literal; i++) {
-        if (mTable[i].value == value) {
-            str = mTable[i].literal;
-            return true;
-        }
-    }
-    char result[64];
-    snprintf(result, sizeof(result), "Unknown enum value %d", value);
-    str = result;
-    return false;
-}
-
-template <class Traits>
-inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
-{
-    for (size_t i = 0; mTable[i].literal; i++) {
-        if (strcmp(mTable[i].literal, str.c_str()) == 0) {
-            ALOGV("stringToEnum() found %s", mTable[i].literal);
-            result = mTable[i].value;
-            return true;
-        }
-    }
-    return false;
-}
-
-template <class Traits>
-inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
-        typename Traits::Collection &collection,
-        const char *del)
-{
-    char *literal = strdup(str.c_str());
-
-    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
-        typename Traits::Type value;
-        if (fromString(cstr, value)) {
-            Traits::add(collection, value);
-        }
-    }
-    free(literal);
-}
-
-template <class Traits>
-inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
-{
-    char *literal = strdup(str.c_str());
-    uint32_t value = 0;
-    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
-        typename Traits::Type type;
-        if (fromString(cstr, type)) {
-            value |= static_cast<uint32_t>(type);
-        }
-    }
-    free(literal);
-    return value;
-}
-
-template <class Traits>
-inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
-{
-    if (mask != 0) {
-        bool first_flag = true;
-        for (size_t i = 0; mTable[i].literal; i++) {
-            uint32_t value = static_cast<uint32_t>(mTable[i].value);
-            if (mTable[i].value != 0 && ((mask & value) == value)) {
-                if (!first_flag) str += del;
-                first_flag = false;
-                str += mTable[i].literal;
-            }
-        }
-    } else {
-        toString(static_cast<typename Traits::Type>(0), str);
-    }
-}
-
-typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
-typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
-typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
-typedef TypeConverter<InputFlagTraits> InputFlagConverter;
-typedef TypeConverter<FormatTraits> FormatConverter;
-typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
-typedef TypeConverter<InputChannelTraits> InputChannelConverter;
-typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
-typedef TypeConverter<GainModeTraits> GainModeConverter;
-typedef TypeConverter<StreamTraits> StreamTypeConverter;
-typedef TypeConverter<AudioModeTraits> AudioModeConverter;
-typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
-typedef TypeConverter<UsageTraits> UsageTypeConverter;
-typedef TypeConverter<SourceTraits> SourceTypeConverter;
-typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
-
-template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
-template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
-template<> const OutputFlagConverter::Table OutputFlagConverter::mTable[];
-template<> const InputFlagConverter::Table InputFlagConverter::mTable[];
-template<> const FormatConverter::Table FormatConverter::mTable[];
-template<> const OutputChannelConverter::Table OutputChannelConverter::mTable[];
-template<> const InputChannelConverter::Table InputChannelConverter::mTable[];
-template<> const ChannelIndexConverter::Table ChannelIndexConverter::mTable[];
-template<> const GainModeConverter::Table GainModeConverter::mTable[];
-template<> const StreamTypeConverter::Table StreamTypeConverter::mTable[];
-template<> const AudioModeConverter::Table AudioModeConverter::mTable[];
-template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
-template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
-template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
-template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
-
-bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
-
-SampleRateTraits::Collection samplingRatesFromString(
-        const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
-
-FormatTraits::Collection formatsFromString(
-        const std::string &formats, const char *del = AudioParameter::valueListSeparator);
-
-audio_format_t formatFromString(
-        const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);
-
-audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);
-
-ChannelTraits::Collection channelMasksFromString(
-        const std::string &channels, const char *del = AudioParameter::valueListSeparator);
-
-InputChannelTraits::Collection inputChannelMasksFromString(
-        const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);
-
-OutputChannelTraits::Collection outputChannelMasksFromString(
-        const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
-
-// counting enumerations
-template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
-                                    || std::is_same<T, audio_mode_t>::value
-                                    || std::is_same<T, audio_source_t>::value
-                                    || std::is_same<T, audio_stream_type_t>::value
-                                    || std::is_same<T, audio_usage_t>::value
-                                    , int> = 0>
-static inline std::string toString(const T& value)
-{
-    std::string result;
-    return TypeConverter<DefaultTraits<T>>::toString(value, result)
-            ? result : std::to_string(static_cast<int>(value));
-
-}
-
-// flag enumerations
-template <typename T, std::enable_if_t<std::is_same<T, audio_gain_mode_t>::value
-                                    || std::is_same<T, audio_input_flags_t>::value
-                                    || std::is_same<T, audio_output_flags_t>::value
-                                    , int> = 0>
-static inline std::string toString(const T& value)
-{
-    std::string result;
-    TypeConverter<DefaultTraits<T>>::maskToString(value, result);
-    return result;
-}
-
-static inline std::string toString(const audio_devices_t& devices)
-{
-    std::string result;
-    if ((devices & AUDIO_DEVICE_BIT_IN) != 0) {
-        InputDeviceConverter::maskToString(devices, result);
-    } else {
-        OutputDeviceConverter::maskToString(devices, result);
-    }
-    return result;
-}
-
-// TODO: Remove when FormatTraits uses DefaultTraits.
-static inline std::string toString(const audio_format_t& format)
-{
-    std::string result;
-    return TypeConverter<VectorTraits<audio_format_t>>::toString(format, result)
-            ? result : std::to_string(static_cast<int>(format));
-}
-
-static inline std::string toString(const audio_attributes_t& attributes)
-{
-    std::ostringstream result;
-    result << "{ Content type: " << toString(attributes.content_type)
-           << " Usage: " << toString(attributes.usage)
-           << " Source: " << toString(attributes.source)
-           << std::hex << " Flags: 0x" << attributes.flags
-           << std::dec << " Tags: " << attributes.tags
-           << " }";
-
-    return result.str();
-}
-
-}; // namespace android
-
-#endif  /*ANDROID_TYPE_CONVERTER_H_*/
diff --git a/media/libmedia/include/media/Visualizer.h b/media/libmedia/include/media/Visualizer.h
deleted file mode 100644
index 8078e36..0000000
--- a/media/libmedia/include/media/Visualizer.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010 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 ANDROID_MEDIA_VISUALIZER_H
-#define ANDROID_MEDIA_VISUALIZER_H
-
-#include <media/AudioEffect.h>
-#include <system/audio_effects/effect_visualizer.h>
-#include <utils/Thread.h>
-
-/**
- * The Visualizer class enables application to retrieve part of the currently playing audio for
- * visualization purpose. It is not an audio recording interface and only returns partial and low
- * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
- * of the visualizer requires the permission android.permission.RECORD_AUDIO.
- * The audio session ID passed to the constructor indicates which audio content should be
- * visualized:
- * - If the session is 0, the audio output mix is visualized
- * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
- *   using this audio session is visualized
- * Two types of representation of audio content can be captured:
- * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
- * - Frequency data: 8-bit magnitude FFT by using the getFft() method
- *
- * The length of the capture can be retrieved or specified by calling respectively
- * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
- * is half of the specified capture size but both sides of the spectrum are returned yielding in a
- * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
- * returned by getMinCaptureSize() and getMaxCaptureSize().
- * In addition to the polling capture mode, a callback mode is also available by installing a
- * callback function by use of the setCaptureCallBack() method. The rate at which the callback
- * is called as well as the type of data returned is specified.
- * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
- * When data capture is not needed any more, the Visualizer should be disabled.
- */
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class Visualizer: public AudioEffect {
-public:
-
-    enum callback_flags {
-        CAPTURE_WAVEFORM = 0x00000001,  // capture callback returns a PCM wave form
-        CAPTURE_FFT = 0x00000002,       // apture callback returns a frequency representation
-        CAPTURE_CALL_JAVA = 0x00000004  // the callback thread can call java
-    };
-
-
-    /* Constructor.
-     * See AudioEffect constructor for details on parameters.
-     */
-                        Visualizer(const String16& opPackageName,
-                                   int32_t priority = 0,
-                                   effect_callback_t cbf = NULL,
-                                   void* user = NULL,
-                                   audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
-
-                        ~Visualizer();
-
-    virtual status_t    setEnabled(bool enabled);
-
-    // maximum capture size in samples
-    static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
-    // minimum capture size in samples
-    static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
-    // maximum capture rate in millihertz
-    static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
-
-    // callback used to return periodic PCM or FFT captures to the application. Either one or both
-    // types of data are returned (PCM and FFT) according to flags indicated when installing the
-    // callback. When a type of data is not present, the corresponding size (waveformSize or
-    // fftSize) is 0.
-    typedef void (*capture_cbk_t)(void* user,
-                                    uint32_t waveformSize,
-                                    uint8_t *waveform,
-                                    uint32_t fftSize,
-                                    uint8_t *fft,
-                                    uint32_t samplingrate);
-
-    // install a callback to receive periodic captures. The capture rate is specified in milliHertz
-    // and the capture format is according to flags  (see callback_flags).
-    status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
-
-    // set the capture size capture size must be a power of two in the range
-    // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
-    // must be called when the visualizer is not enabled
-    status_t setCaptureSize(uint32_t size);
-    uint32_t getCaptureSize() { return mCaptureSize; }
-
-    // returns the capture rate indicated when installing the callback
-    uint32_t getCaptureRate() { return mCaptureRate; }
-
-    // returns the sampling rate of the audio being captured
-    uint32_t getSamplingRate() { return mSampleRate; }
-
-    // set the way volume affects the captured data
-    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
-    //  VISUALIZER_SCALING_MODE_AS_PLAYED
-    status_t setScalingMode(uint32_t mode);
-    uint32_t getScalingMode() { return mScalingMode; }
-
-    // set which measurements are done on the audio buffers processed by the effect.
-    // valid measurements (mask): MEASUREMENT_MODE_PEAK_RMS
-    status_t setMeasurementMode(uint32_t mode);
-    uint32_t getMeasurementMode() { return mMeasurementMode; }
-
-    // return a set of int32_t measurements
-    status_t getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements);
-
-    // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
-    // getCaptureSize()
-    status_t getWaveForm(uint8_t *waveform);
-
-    // return a capture in FFT 8 bit signed format. The size of the capture is equal to
-    // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
-    // are returned
-    status_t getFft(uint8_t *fft);
-    void release();
-
-protected:
-    // from IEffectClient
-    virtual void controlStatusChanged(bool controlGranted);
-
-private:
-
-    static const uint32_t CAPTURE_RATE_MAX = 20000;
-    static const uint32_t CAPTURE_RATE_DEF = 10000;
-    static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
-
-    /* internal class to handle the callback */
-    class CaptureThread : public Thread
-    {
-    public:
-        CaptureThread(Visualizer* visualizer, uint32_t captureRate, bool bCanCallJava = false);
-
-    private:
-        friend class Visualizer;
-        virtual bool        threadLoop();
-        wp<Visualizer> mReceiver;
-        Mutex       mLock;
-        uint32_t mSleepTimeUs;
-    };
-
-    status_t doFft(uint8_t *fft, uint8_t *waveform);
-    void periodicCapture();
-    uint32_t initCaptureSize();
-
-    Mutex mCaptureLock;
-    uint32_t mCaptureRate;
-    uint32_t mCaptureSize;
-    uint32_t mSampleRate;
-    uint32_t mScalingMode;
-    uint32_t mMeasurementMode;
-    capture_cbk_t mCaptureCallBack;
-    void *mCaptureCbkUser;
-    sp<CaptureThread> mCaptureThread;
-    uint32_t mCaptureFlags;
-};
-
-
-}; // namespace android
-
-#endif // ANDROID_MEDIA_VISUALIZER_H
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index d29e97d..138a014 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -98,9 +98,8 @@
             int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false, bool thumbnail = false);
     sp<IMemory> getImageRectAtIndex(
             int index, int colorFormat, int left, int top, int right, int bottom);
-    status_t getFrameAtIndex(
-            std::vector<sp<IMemory> > *frames, int frameIndex, int numFrames = 1,
-            int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
+    sp<IMemory>  getFrameAtIndex(
+            int index, int colorFormat = HAL_PIXEL_FORMAT_RGB_565, bool metaOnly = false);
     sp<IMemory> extractAlbumArt();
     const char* extractMetadata(int keyCode);
 
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 2dd4b7f..6e2d94d 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -236,6 +236,8 @@
     status_t    setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
     status_t    setVideoSource(int vs);
     status_t    setAudioSource(int as);
+    status_t    setPrivacySensitive(bool privacySensitive);
+    status_t    isPrivacySensitive(bool *privacySensitive) const;
     status_t    setOutputFormat(int of);
     status_t    setVideoEncoder(int ve);
     status_t    setAudioEncoder(int ae);
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index 6dc46b7..811936b 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -45,7 +45,6 @@
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
 namespace android {
diff --git a/media/libmedia/include/media/omx/1.0/WOmx.h b/media/libmedia/include/media/omx/1.0/WOmx.h
index 0680eec..46ada9b 100644
--- a/media/libmedia/include/media/omx/1.0/WOmx.h
+++ b/media/libmedia/include/media/omx/1.0/WOmx.h
@@ -67,7 +67,7 @@
             sp<IOMXNode>* omxNode) override;
     status_t createInputSurface(
             sp<::android::IGraphicBufferProducer>* bufferProducer,
-            sp<::android::IGraphicBufferSource>* bufferSource) override;
+            sp<::android::hardware::media::omx::V1_0::IGraphicBufferSource>* bufferSource) override;
 };
 
 }  // namespace utils
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index e61b04d..2ae76b3 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -179,18 +179,16 @@
             index, colorFormat, left, top, right, bottom);
 }
 
-status_t MediaMetadataRetriever::getFrameAtIndex(
-        std::vector<sp<IMemory> > *frames,
-        int frameIndex, int numFrames, int colorFormat, bool metaOnly) {
-    ALOGV("getFrameAtIndex: frameIndex(%d), numFrames(%d), colorFormat(%d) metaOnly(%d)",
-            frameIndex, numFrames, colorFormat, metaOnly);
+sp<IMemory>  MediaMetadataRetriever::getFrameAtIndex(
+        int index, int colorFormat, bool metaOnly) {
+    ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
+            index, colorFormat, metaOnly);
     Mutex::Autolock _l(mLock);
     if (mRetriever == 0) {
         ALOGE("retriever is not initialized");
-        return INVALID_OPERATION;
+        return NULL;
     }
-    return mRetriever->getFrameAtIndex(
-            frames, frameIndex, numFrames, colorFormat, metaOnly);
+    return mRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
 }
 
 const char* MediaMetadataRetriever::extractMetadata(int keyCode)
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 26908e5..1fadc94 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -17,6 +17,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaPlayerNative"
+#include <utils/Log.h>
 
 #include <fcntl.h>
 #include <inttypes.h>
@@ -24,25 +25,15 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <utils/Log.h>
 
-#include <binder/IServiceManager.h>
+#include <android/IDataSource.h>
 #include <binder/IPCThreadState.h>
-
-#include <gui/Surface.h>
-
 #include <media/mediaplayer.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
 #include <media/AVSyncSettings.h>
-#include <media/IDataSource.h>
-#include <media/MediaAnalyticsItem.h>
-
-#include <binder/MemoryBase.h>
-
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
-
 #include <system/audio.h>
 #include <system/window.h>
 
@@ -69,7 +60,7 @@
     mVideoWidth = mVideoHeight = 0;
     mLockThreadId = 0;
     mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
-    AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
+    AudioSystem::acquireAudioSessionId(mAudioSessionId, (pid_t)-1, (uid_t)-1); // always in client.
     mSendLevel = 0;
     mRetransmitEndpointValid = false;
 }
@@ -81,7 +72,7 @@
         delete mAudioAttributesParcel;
         mAudioAttributesParcel = NULL;
     }
-    AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
+    AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
     disconnect();
     IPCThreadState::self()->flushCommands();
 }
@@ -718,8 +709,8 @@
         return BAD_VALUE;
     }
     if (sessionId != mAudioSessionId) {
-        AudioSystem::acquireAudioSessionId(sessionId, -1);
-        AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
+        AudioSystem::acquireAudioSessionId(sessionId, (pid_t)-1, (uid_t)-1);
+        AudioSystem::releaseAudioSessionId(mAudioSessionId, (pid_t)-1);
         mAudioSessionId = sessionId;
     }
     return NO_ERROR;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 4570af9..70655d5 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -178,6 +178,47 @@
     return ret;
 }
 
+status_t MediaRecorder::setPrivacySensitive(bool privacySensitive)
+{
+    ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+    if (mMediaRecorder == NULL) {
+        ALOGE("%s: media recorder is not initialized yet", __func__);
+        return INVALID_OPERATION;
+    }
+
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED) || !mIsAudioSourceSet) {
+        ALOGE("%s called in an invalid state(%d) or audio source not (%d)",
+            __func__, mCurrentState, mIsAudioSourceSet);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setPrivacySensitive(privacySensitive);
+    if (OK != ret) {
+        ALOGV("%s failed: %d", __func__, ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::isPrivacySensitive(bool *privacySensitive) const
+{
+    if (mMediaRecorder == NULL) {
+        ALOGE("%s: media recorder is not initialized yet", __func__);
+        return INVALID_OPERATION;
+    }
+
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED) || !mIsAudioSourceSet) {
+        ALOGE("%s called in an invalid state(%d) or audio source not (%d)",
+            __func__, mCurrentState, mIsAudioSourceSet);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->isPrivacySensitive(privacySensitive);
+    ALOGV("%s status: %d eanbled %s", __func__, ret, *privacySensitive ? "enabled" : "disabled");
+    return ret;
+}
+
 status_t MediaRecorder::setOutputFormat(int of)
 {
     ALOGV("setOutputFormat(%d)", of);
diff --git a/media/libmedia/omx/1.0/WOmx.cpp b/media/libmedia/omx/1.0/WOmx.cpp
index ce624fa..4bacdda 100644
--- a/media/libmedia/omx/1.0/WOmx.cpp
+++ b/media/libmedia/omx/1.0/WOmx.cpp
@@ -18,7 +18,6 @@
 #include <media/omx/1.0/WOmx.h>
 #include <media/omx/1.0/WOmxNode.h>
 #include <media/omx/1.0/WOmxObserver.h>
-#include <media/omx/1.0/WGraphicBufferSource.h>
 #include <media/omx/1.0/Conversion.h>
 
 namespace android {
@@ -70,7 +69,7 @@
 
 status_t LWOmx::createInputSurface(
         sp<::android::IGraphicBufferProducer>* bufferProducer,
-        sp<::android::IGraphicBufferSource>* bufferSource) {
+        sp<::android::hardware::media::omx::V1_0::IGraphicBufferSource>* bufferSource) {
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->createInputSurface(
             [&fnStatus, bufferProducer, bufferSource] (
@@ -79,7 +78,7 @@
                     sp<IGraphicBufferSource> const& tSource) {
                 fnStatus = toStatusT(status);
                 *bufferProducer = new H2BGraphicBufferProducer(tProducer);
-                *bufferSource = new LWGraphicBufferSource(tSource);
+                *bufferSource = tSource;
             }));
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
diff --git a/media/libmedia/xsd/vts/Android.bp b/media/libmedia/xsd/vts/Android.bp
index 4739504..598e41b 100644
--- a/media/libmedia/xsd/vts/Android.bp
+++ b/media/libmedia/xsd/vts/Android.bp
@@ -31,4 +31,12 @@
         "-Wall",
         "-Werror",
     ],
+    data: [
+        ":media_profiles",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts"
+    ],
+    test_config: "vts_mediaProfiles_validate_test.xml",
 }
diff --git a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
index 7729d52..4f3951a 100644
--- a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
+++ b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
@@ -14,23 +14,68 @@
  * limitations under the License.
  */
 
+#include <fstream>
 #include <string>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include "utility/ValidateXml.h"
 
+bool isFileReadable(std::string const& path) {
+  std::ifstream f(path);
+  return f.good();
+}
+
 TEST(CheckConfig, mediaProfilesValidation) {
     RecordProperty("description",
                    "Verify that the media profiles file "
                    "is valid according to the schema");
 
+    // Schema path.
+    constexpr char const* xsdPath = "/data/local/tmp/media_profiles.xsd";
+
+    // If "media.settings.xml" is set, it will be used as an absolute path.
     std::string mediaSettingsPath = android::base::GetProperty("media.settings.xml", "");
     if (mediaSettingsPath.empty()) {
-        mediaSettingsPath.assign("/vendor/etc/media_profiles_V1_0.xml");
-    }
+        // If "media.settings.xml" is not set, we will search through a list of
+        // file paths.
 
-    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(android::base::Basename(mediaSettingsPath).c_str(),
-                                            {android::base::Dirname(mediaSettingsPath).c_str()},
-                                            "/data/local/tmp/media_profiles.xsd");
+        constexpr char const* xmlSearchDirs[] = {
+                "/product/etc/",
+                "/odm/etc/",
+                "/vendor/etc/",
+            };
+
+        // The vendor may provide a vendor variant for the file name.
+        std::string variant = android::base::GetProperty(
+                "ro.media.xml_variant.profiles", "_V1_0");
+        std::string fileName = "media_profiles" + variant + ".xml";
+
+        // Fallback path does not depend on the property defined from the vendor
+        // partition.
+        constexpr char const* fallbackXmlPath =
+                "/system/etc/media_profiles_V1_0.xml";
+
+        std::vector<std::string> xmlPaths = {
+                xmlSearchDirs[0] + fileName,
+                xmlSearchDirs[1] + fileName,
+                xmlSearchDirs[2] + fileName,
+                fallbackXmlPath
+            };
+
+        auto findXmlPath =
+            std::find_if(xmlPaths.begin(), xmlPaths.end(), isFileReadable);
+        ASSERT_TRUE(findXmlPath != xmlPaths.end())
+                << "Cannot read from " << fileName
+                << " in any search directories ("
+                << xmlSearchDirs[0] << ", "
+                << xmlSearchDirs[1] << ", "
+                << xmlSearchDirs[2] << ") and from "
+                << fallbackXmlPath << ".";
+
+        char const* xmlPath = findXmlPath->c_str();
+        EXPECT_VALID_XML(xmlPath, xsdPath);
+    } else {
+        EXPECT_VALID_XML(mediaSettingsPath.c_str(), xsdPath);
+    }
 }
diff --git a/media/libmedia/xsd/vts/vts_mediaProfiles_validate_test.xml b/media/libmedia/xsd/vts/vts_mediaProfiles_validate_test.xml
new file mode 100644
index 0000000..08ab8f4
--- /dev/null
+++ b/media/libmedia/xsd/vts/vts_mediaProfiles_validate_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs vts_mediaProfiles_validate_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="media_profiles.xsd->/data/local/tmp/media_profiles.xsd" />
+        <option name="push" value="vts_mediaProfiles_validate_test->/data/local/tmp/vts_mediaProfiles_validate_test" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_mediaProfiles_validate_test" />
+    </test>
+</configuration>
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
new file mode 100644
index 0000000..6fcbc7b
--- /dev/null
+++ b/media/libmediahelper/Android.bp
@@ -0,0 +1,30 @@
+cc_library_headers {
+    name: "libmedia_helper_headers",
+    vendor_available: true,
+    min_sdk_version: "29",
+    export_include_dirs: ["include"],
+}
+
+cc_library {
+    name: "libmedia_helper",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    double_loadable: true,
+    srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
+    cflags: [
+        "-Werror",
+        "-Wextra",
+        "-Wall",
+    ],
+    shared_libs: ["libutils", "liblog"],
+    header_libs: [
+        "libmedia_helper_headers",
+        "libaudio_system_headers",
+    ],
+    export_header_lib_headers: [
+        "libmedia_helper_headers",
+    ],
+    clang: true,
+}
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
new file mode 100644
index 0000000..fc8306c
--- /dev/null
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2006-2011 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_TAG "AudioParameter"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include <media/AudioParameter.h>
+#include <system/audio.h>
+
+namespace android {
+
+// static
+const char * const AudioParameter::keyRouting = AUDIO_PARAMETER_STREAM_ROUTING;
+const char * const AudioParameter::keySamplingRate = AUDIO_PARAMETER_STREAM_SAMPLING_RATE;
+const char * const AudioParameter::keyFormat = AUDIO_PARAMETER_STREAM_FORMAT;
+const char * const AudioParameter::keyChannels = AUDIO_PARAMETER_STREAM_CHANNELS;
+const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
+const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
+const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyBtNrec = AUDIO_PARAMETER_KEY_BT_NREC;
+const char * const AudioParameter::keyHwAvSync = AUDIO_PARAMETER_HW_AV_SYNC;
+const char * const AudioParameter::keyPresentationId = AUDIO_PARAMETER_STREAM_PRESENTATION_ID;
+const char * const AudioParameter::keyProgramId = AUDIO_PARAMETER_STREAM_PROGRAM_ID;
+const char * const AudioParameter::keyAudioLanguagePreferred =
+        AUDIO_PARAMETER_KEY_AUDIO_LANGUAGE_PREFERRED;
+const char * const AudioParameter::keyMonoOutput = AUDIO_PARAMETER_MONO_OUTPUT;
+const char * const AudioParameter::keyStreamHwAvSync = AUDIO_PARAMETER_STREAM_HW_AV_SYNC;
+const char * const AudioParameter::keyDeviceConnect = AUDIO_PARAMETER_DEVICE_CONNECT;
+const char * const AudioParameter::keyDeviceDisconnect = AUDIO_PARAMETER_DEVICE_DISCONNECT;
+const char * const AudioParameter::keyStreamConnect = AUDIO_PARAMETER_DEVICE_CONNECT;
+const char * const AudioParameter::keyStreamDisconnect = AUDIO_PARAMETER_DEVICE_DISCONNECT;
+const char * const AudioParameter::keyStreamSupportedFormats = AUDIO_PARAMETER_STREAM_SUP_FORMATS;
+const char * const AudioParameter::keyStreamSupportedChannels = AUDIO_PARAMETER_STREAM_SUP_CHANNELS;
+const char * const AudioParameter::keyStreamSupportedSamplingRates =
+        AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES;
+const char * const AudioParameter::valueOn = AUDIO_PARAMETER_VALUE_ON;
+const char * const AudioParameter::valueOff = AUDIO_PARAMETER_VALUE_OFF;
+const char * const AudioParameter::valueListSeparator = AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
+const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
+const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
+// const char * const AudioParameter::keyDeviceSupportedEncapsulationModes =
+//        AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
+// const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
+//        AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES;
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+    char *str = new char[keyValuePairs.length()+1];
+    mKeyValuePairs = keyValuePairs;
+    char *last;
+
+    strcpy(str, keyValuePairs.string());
+    char *pair = strtok_r(str, ";", &last);
+    while (pair != NULL) {
+        if (strlen(pair) != 0) {
+            size_t eqIdx = strcspn(pair, "=");
+            String8 key = String8(pair, eqIdx);
+            String8 value;
+            if (eqIdx == strlen(pair)) {
+                value = String8("");
+            } else {
+                value = String8(pair + eqIdx + 1);
+            }
+            if (mParameters.indexOfKey(key) < 0) {
+                mParameters.add(key, value);
+            } else {
+                mParameters.replaceValueFor(key, value);
+            }
+        } else {
+            ALOGV("AudioParameter() cstor empty key value pair");
+        }
+        pair = strtok_r(NULL, ";", &last);
+    }
+
+    delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+    mParameters.clear();
+}
+
+String8 AudioParameter::toStringImpl(bool useValues) const
+{
+    String8 str = String8("");
+
+    size_t size = mParameters.size();
+    for (size_t i = 0; i < size; i++) {
+        str += mParameters.keyAt(i);
+        if (useValues) {
+            str += "=";
+            str += mParameters.valueAt(i);
+        }
+        if (i < (size - 1)) str += ";";
+    }
+    return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+    if (mParameters.indexOfKey(key) < 0) {
+        mParameters.add(key, value);
+        return NO_ERROR;
+    } else {
+        mParameters.replaceValueFor(key, value);
+        return ALREADY_EXISTS;
+    }
+}
+
+status_t AudioParameter::addKey(const String8& key)
+{
+    return add(key, String8());
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+    char str[12];
+    if (snprintf(str, 12, "%d", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+    char str[23];
+    if (snprintf(str, 23, "%.10f", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        mParameters.removeItem(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value) const
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        value = mParameters.valueFor(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value) const
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        int val;
+        if (sscanf(str8.string(), "%d", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value) const
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        float val;
+        if (sscanf(str8.string(), "%f", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
+
+status_t AudioParameter::getAt(size_t index, String8& key) const
+{
+    if (mParameters.size() > index) {
+        key = mParameters.keyAt(index);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::getAt(size_t index, String8& key, String8& value) const
+{
+    if (mParameters.size() > index) {
+        key = mParameters.keyAt(index);
+        value = mParameters.valueAt(index);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+} // namespace android
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
new file mode 100644
index 0000000..6382ce4
--- /dev/null
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2016 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 <media/TypeConverter.h>
+
+namespace android {
+
+#define MAKE_STRING_FROM_ENUM(string) { #string, string }
+#define TERMINATOR { .literal = nullptr }
+
+template <>
+const OutputDeviceConverter::Table OutputDeviceConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_LINE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_SPDIF),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_PROXY),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_USB_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_HEARING_AID),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_ECHO_CANCELLER),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_DEFAULT),
+    // STUB must be after DEFAULT, so the latter is picked up by toString first.
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_STUB),
+    TERMINATOR
+};
+
+template <>
+const InputDeviceConverter::Table InputDeviceConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI_ARC),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ALL_USB),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ECHO_REFERENCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
+    // STUB must be after DEFAULT, so the latter is picked up by toString first.
+    MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
+    TERMINATOR
+};
+
+
+template <>
+const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_TTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_RAW),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+    MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
+    TERMINATOR
+};
+
+
+template <>
+const InputFlagConverter::Table InputFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_FAST),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_RAW),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_MMAP_NOIRQ),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_VOIP_TX),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_DIRECT),
+    TERMINATOR
+};
+
+
+template <>
+const FormatConverter::Table FormatConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_32_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_FLOAT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_NB),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_MAIN),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SSR),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LTP),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ERLC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_HE_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ELD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_XHE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_LD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS_XHE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_VORBIS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_HE_AAC_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_OPUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCB),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCWB),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_EVRCNW),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADIF),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_WMA_PRO),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MP2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_QCELP),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DSD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_FLAC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_ALAC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_ADTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_SBC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_HD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC4),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LDAC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_1_0),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_0),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_MAT_2_1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_LC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V1),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AAC_LATM_HE_V2),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_CELT),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_ADAPTIVE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LHDC_LL),
+    MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_TWSP),
+    TERMINATOR
+};
+
+
+template <>
+const OutputChannelConverter::Table OutputChannelConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT0POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_2POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_TRI_BACK),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT0POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_3POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_BACK),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_PENTA),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_BACK),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1POINT4),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT4),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_A),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_A),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_AB),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB),
+    TERMINATOR
+};
+
+
+template <>
+const InputChannelConverter::Table InputChannelConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_6),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT0POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_2POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT0POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_3POINT1POINT2),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_5POINT1),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
+    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
+    TERMINATOR
+};
+
+template <>
+const ChannelIndexConverter::Table ChannelIndexConverter::mTable[] = {
+    {"AUDIO_CHANNEL_INDEX_MASK_1", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_1)},
+    {"AUDIO_CHANNEL_INDEX_MASK_2", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_2)},
+    {"AUDIO_CHANNEL_INDEX_MASK_3", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_3)},
+    {"AUDIO_CHANNEL_INDEX_MASK_4", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_4)},
+    {"AUDIO_CHANNEL_INDEX_MASK_5", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_5)},
+    {"AUDIO_CHANNEL_INDEX_MASK_6", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_6)},
+    {"AUDIO_CHANNEL_INDEX_MASK_7", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_7)},
+    {"AUDIO_CHANNEL_INDEX_MASK_8", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_8)},
+    TERMINATOR
+};
+
+
+template <>
+const GainModeConverter::Table GainModeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_JOINT),
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_CHANNELS),
+    MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_RAMP),
+    TERMINATOR
+};
+
+
+template <>
+const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DEFAULT),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_VOICE_CALL),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_SYSTEM),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_RING),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_MUSIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ALARM),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_NOTIFICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_BLUETOOTH_SCO ),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ENFORCED_AUDIBLE),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DTMF),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_TTS),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ACCESSIBILITY),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_ASSISTANT),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_REROUTING),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH),
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_CALL_ASSISTANT),
+    TERMINATOR
+};
+
+template<>
+const AudioModeConverter::Table AudioModeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_INVALID),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_CURRENT),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_NORMAL),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_RINGTONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_CALL),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_COMMUNICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_MODE_CALL_SCREEN),
+    TERMINATOR
+};
+
+template<>
+const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_UNKNOWN),
+    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SPEECH),
+    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MUSIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_MOVIE),
+    MAKE_STRING_FROM_ENUM(AUDIO_CONTENT_TYPE_SONIFICATION),
+    TERMINATOR
+};
+
+template <>
+const UsageTypeConverter::Table UsageTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_UNKNOWN),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_MEDIA),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ALARM),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_NOTIFICATION_EVENT),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANCE_SONIFICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_GAME),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VIRTUAL_SOURCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANT),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_CALL_ASSISTANT),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_EMERGENCY),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_SAFETY),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VEHICLE_STATUS),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ANNOUNCEMENT),
+    TERMINATOR
+};
+
+template <>
+const SourceTypeConverter::Table SourceTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_DEFAULT),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_MIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_UPLINK),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_DOWNLINK),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_CALL),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_CAMCORDER),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_RECOGNITION),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_COMMUNICATION),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_REMOTE_SUBMIX),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_UNPROCESSED),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_PERFORMANCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_ECHO_REFERENCE),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_FM_TUNER),
+    MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_HOTWORD),
+    TERMINATOR
+};
+
+template <>
+const AudioFlagConverter::Table AudioFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_AUDIBILITY_ENFORCED),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SECURE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BEACON),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_HOTWORD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_MUTE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_LOW_LATENCY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_MEDIA_PROJECTION),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_MUTE_HAPTIC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NO_SYSTEM_CAPTURE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_CAPTURE_PRIVATE),
+    TERMINATOR
+};
+
+template class TypeConverter<OutputDeviceTraits>;
+template class TypeConverter<InputDeviceTraits>;
+template class TypeConverter<OutputFlagTraits>;
+template class TypeConverter<InputFlagTraits>;
+template class TypeConverter<FormatTraits>;
+template class TypeConverter<OutputChannelTraits>;
+template class TypeConverter<InputChannelTraits>;
+template class TypeConverter<ChannelIndexTraits>;
+template class TypeConverter<GainModeTraits>;
+template class TypeConverter<StreamTraits>;
+template class TypeConverter<AudioModeTraits>;
+template class TypeConverter<UsageTraits>;
+template class TypeConverter<SourceTraits>;
+template class TypeConverter<AudioFlagTraits>;
+
+bool deviceFromString(const std::string& literalDevice, audio_devices_t& device) {
+    return InputDeviceConverter::fromString(literalDevice, device) ||
+            OutputDeviceConverter::fromString(literalDevice, device);
+}
+
+SampleRateTraits::Collection samplingRatesFromString(
+        const std::string &samplingRates, const char *del)
+{
+    SampleRateTraits::Collection samplingRateCollection;
+    collectionFromString<SampleRateTraits>(samplingRates, samplingRateCollection, del);
+    return samplingRateCollection;
+}
+
+FormatTraits::Collection formatsFromString(
+        const std::string &formats, const char *del)
+{
+    FormatTraits::Collection formatCollection;
+    FormatConverter::collectionFromString(formats, formatCollection, del);
+    return formatCollection;
+}
+
+audio_format_t formatFromString(const std::string &literalFormat, audio_format_t defaultFormat)
+{
+    audio_format_t format;
+    if (literalFormat.empty()) {
+        return defaultFormat;
+    }
+    FormatConverter::fromString(literalFormat, format);
+    return format;
+}
+
+audio_channel_mask_t channelMaskFromString(const std::string &literalChannels)
+{
+    audio_channel_mask_t channels;
+    if (!OutputChannelConverter::fromString(literalChannels, channels) &&
+            !InputChannelConverter::fromString(literalChannels, channels)) {
+        return AUDIO_CHANNEL_INVALID;
+    }
+    return channels;
+}
+
+ChannelTraits::Collection channelMasksFromString(
+        const std::string &channels, const char *del)
+{
+    ChannelTraits::Collection channelMaskCollection;
+    OutputChannelConverter::collectionFromString(channels, channelMaskCollection, del);
+    InputChannelConverter::collectionFromString(channels, channelMaskCollection, del);
+    ChannelIndexConverter::collectionFromString(channels, channelMaskCollection, del);
+    return channelMaskCollection;
+}
+
+InputChannelTraits::Collection inputChannelMasksFromString(
+        const std::string &inChannels, const char *del)
+{
+    InputChannelTraits::Collection inputChannelMaskCollection;
+    InputChannelConverter::collectionFromString(inChannels, inputChannelMaskCollection, del);
+    ChannelIndexConverter::collectionFromString(inChannels, inputChannelMaskCollection, del);
+    return inputChannelMaskCollection;
+}
+
+OutputChannelTraits::Collection outputChannelMasksFromString(
+        const std::string &outChannels, const char *del)
+{
+    OutputChannelTraits::Collection outputChannelMaskCollection;
+    OutputChannelConverter::collectionFromString(outChannels, outputChannelMaskCollection, del);
+    ChannelIndexConverter::collectionFromString(outChannels, outputChannelMaskCollection, del);
+    return outputChannelMaskCollection;
+}
+
+}; // namespace android
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
new file mode 100644
index 0000000..66d8dfb
--- /dev/null
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2008-2011 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 ANDROID_AUDIOPARAMETER_H_
+#define ANDROID_AUDIOPARAMETER_H_
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class AudioParameter {
+
+public:
+    AudioParameter() {}
+    AudioParameter(const String8& keyValuePairs);
+    virtual ~AudioParameter();
+
+    // reserved parameter keys for changing standard parameters with setParameters() function.
+    // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
+    // configuration changes and act accordingly.
+    //  keyRouting: to change audio routing, value is an int in audio_devices_t
+    //  keySamplingRate: to change sampling rate routing, value is an int
+    //  keyFormat: to change audio format, value is an int in audio_format_t
+    //  keyChannels: to change audio channel configuration, value is an int in audio_channels_t
+    //  keyFrameCount: to change audio output frame count, value is an int
+    //  keyInputSource: to change audio input source, value is an int in audio_source_t
+    //     (defined in media/mediarecorder.h)
+    //  keyScreenState: either "on" or "off"
+    static const char * const keyRouting;
+    static const char * const keySamplingRate;
+    static const char * const keyFormat;
+    static const char * const keyChannels;
+    static const char * const keyFrameCount;
+    static const char * const keyInputSource;
+    static const char * const keyScreenState;
+
+    //  keyBtNrec: BT SCO Noise Reduction + Echo Cancellation parameters
+    //  keyHwAvSync: get HW synchronization source identifier from a device
+    //  keyMonoOutput: Enable mono audio playback
+    //  keyStreamHwAvSync: set HW synchronization source identifier on a stream
+    static const char * const keyBtNrec;
+    static const char * const keyHwAvSync;
+    static const char * const keyMonoOutput;
+    static const char * const keyStreamHwAvSync;
+
+    //  keys for presentation selection
+    //  keyPresentationId: Audio presentation identifier
+    //  keyProgramId: Audio presentation program identifier
+    static const char * const keyPresentationId;
+    static const char * const keyProgramId;
+
+    //  keyAudioLanguagePreferred: Preferred audio language
+    static const char * const keyAudioLanguagePreferred;
+
+    //  keyDeviceConnect / Disconnect: value is an int in audio_devices_t
+    static const char * const keyDeviceConnect;
+    static const char * const keyDeviceDisconnect;
+    //  Need to be here because vendors still use them.
+    static const char * const keyStreamConnect;  // Deprecated: DO NOT USE.
+    static const char * const keyStreamDisconnect;  // Deprecated: DO NOT USE.
+
+    // For querying stream capabilities. All the returned values are lists.
+    //   keyStreamSupportedFormats: audio_format_t
+    //   keyStreamSupportedChannels: audio_channel_mask_t
+    //   keyStreamSupportedSamplingRates: sampling rate values
+    static const char * const keyStreamSupportedFormats;
+    static const char * const keyStreamSupportedChannels;
+    static const char * const keyStreamSupportedSamplingRates;
+
+    static const char * const valueOn;
+    static const char * const valueOff;
+
+    static const char * const valueListSeparator;
+
+    // keyReconfigA2dp: Ask HwModule to reconfigure A2DP offloaded codec
+    // keyReconfigA2dpSupported: Query if HwModule supports A2DP offload codec config
+    static const char * const keyReconfigA2dp;
+    static const char * const keyReconfigA2dpSupported;
+
+    // For querying device supported encapsulation capabilities. All returned values are integer,
+    // which are bit fields composed from using encapsulation capability values as position bits.
+    // Encapsulation capability values are defined in audio_encapsulation_mode_t and
+    // audio_encapsulation_metadata_type_t. For instance, if the supported encapsulation mode is
+    // AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM, the returned value is
+    // "supEncapsulationModes=1 << AUDIO_ENCAPSULATION_MODE_HANDLE".
+    // When querying device supported encapsulation capabilities, the key should use with device
+    // type and address so that it is able to identify the device. The device will be a key. The
+    // device type will be the value of key AUDIO_PARAMETER_STREAM_ROUTING.
+    // static const char * const keyDeviceSupportedEncapsulationModes;
+    // static const char * const keyDeviceSupportedEncapsulationMetadataTypes;
+
+    String8 toString() const { return toStringImpl(true); }
+    String8 keysToString() const { return toStringImpl(false); }
+
+    status_t add(const String8& key, const String8& value);
+    status_t addInt(const String8& key, const int value);
+    status_t addKey(const String8& key);
+    status_t addFloat(const String8& key, const float value);
+
+    status_t remove(const String8& key);
+
+    status_t get(const String8& key, String8& value) const;
+    status_t getInt(const String8& key, int& value) const;
+    status_t getFloat(const String8& key, float& value) const;
+    status_t getAt(size_t index, String8& key) const;
+    status_t getAt(size_t index, String8& key, String8& value) const;
+
+    size_t size() const { return mParameters.size(); }
+
+private:
+    String8 mKeyValuePairs;
+    KeyedVector <String8, String8> mParameters;
+
+    String8 toStringImpl(bool useValues) const;
+};
+
+};  // namespace android
+
+#endif  /*ANDROID_AUDIOPARAMETER_H_*/
diff --git a/media/libmediahelper/include/media/TypeConverter.h b/media/libmediahelper/include/media/TypeConverter.h
new file mode 100644
index 0000000..011498a
--- /dev/null
+++ b/media/libmediahelper/include/media/TypeConverter.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2016 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 ANDROID_TYPE_CONVERTER_H_
+#define ANDROID_TYPE_CONVERTER_H_
+
+#include <set>
+#include <string>
+#include <string.h>
+#include <vector>
+
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+
+#include <media/AudioParameter.h>
+#include "convert.h"
+
+namespace android {
+
+template <typename T>
+struct DefaultTraits
+{
+    typedef T Type;
+    typedef std::vector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.push_back(value);
+    }
+};
+template <typename T>
+struct SortedVectorTraits
+{
+    typedef T Type;
+    typedef SortedVector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.add(value);
+    }
+};
+template <typename T>
+struct SetTraits
+{
+    typedef T Type;
+    typedef std::set<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.insert(value);
+    }
+};
+
+using SampleRateTraits = SetTraits<uint32_t>;
+using DeviceTraits = DefaultTraits<audio_devices_t>;
+struct OutputDeviceTraits : public DeviceTraits {};
+struct InputDeviceTraits : public DeviceTraits {};
+using ChannelTraits = SetTraits<audio_channel_mask_t>;
+struct OutputChannelTraits : public ChannelTraits {};
+struct InputChannelTraits : public ChannelTraits {};
+struct ChannelIndexTraits : public ChannelTraits {};
+using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
+using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
+using FormatTraits = DefaultTraits<audio_format_t>;
+using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
+using StreamTraits = DefaultTraits<audio_stream_type_t>;
+using AudioModeTraits = DefaultTraits<audio_mode_t>;
+using AudioContentTraits = DefaultTraits<audio_content_type_t>;
+using UsageTraits = DefaultTraits<audio_usage_t>;
+using SourceTraits = DefaultTraits<audio_source_t>;
+struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
+
+template <class Traits>
+static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
+                                 const char *del = AudioParameter::valueListSeparator)
+{
+    char *literal = strdup(str.c_str());
+    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
+        typename Traits::Type value;
+        if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
+            Traits::add(collection, value);
+        }
+    }
+    free(literal);
+}
+
+template <class Traits>
+class TypeConverter
+{
+public:
+    static bool toString(const typename Traits::Type &value, std::string &str);
+
+    static bool fromString(const std::string &str, typename Traits::Type &result);
+
+    static void collectionFromString(const std::string &str,
+                                     typename Traits::Collection &collection,
+                                     const char *del = AudioParameter::valueListSeparator);
+
+    static uint32_t maskFromString(
+            const std::string &str, const char *del = AudioParameter::valueListSeparator);
+
+    static void maskToString(
+            uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);
+
+protected:
+    struct Table {
+        const char *literal;
+        typename Traits::Type value;
+    };
+
+    static const Table mTable[];
+};
+
+template <class Traits>
+inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
+{
+    for (size_t i = 0; mTable[i].literal; i++) {
+        if (mTable[i].value == value) {
+            str = mTable[i].literal;
+            return true;
+        }
+    }
+    char result[64];
+    snprintf(result, sizeof(result), "Unknown enum value %d", value);
+    str = result;
+    return false;
+}
+
+template <class Traits>
+inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
+{
+    for (size_t i = 0; mTable[i].literal; i++) {
+        if (strcmp(mTable[i].literal, str.c_str()) == 0) {
+            ALOGV("stringToEnum() found %s", mTable[i].literal);
+            result = mTable[i].value;
+            return true;
+        }
+    }
+    return false;
+}
+
+template <class Traits>
+inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
+        typename Traits::Collection &collection,
+        const char *del)
+{
+    char *literal = strdup(str.c_str());
+
+    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
+        typename Traits::Type value;
+        if (fromString(cstr, value)) {
+            Traits::add(collection, value);
+        }
+    }
+    free(literal);
+}
+
+template <class Traits>
+inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
+{
+    char *literal = strdup(str.c_str());
+    uint32_t value = 0;
+    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
+        typename Traits::Type type;
+        if (fromString(cstr, type)) {
+            value |= static_cast<uint32_t>(type);
+        }
+    }
+    free(literal);
+    return value;
+}
+
+template <class Traits>
+inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
+{
+    if (mask != 0) {
+        bool first_flag = true;
+        for (size_t i = 0; mTable[i].literal; i++) {
+            uint32_t value = static_cast<uint32_t>(mTable[i].value);
+            if (mTable[i].value != 0 && ((mask & value) == value)) {
+                if (!first_flag) str += del;
+                first_flag = false;
+                str += mTable[i].literal;
+            }
+        }
+    } else {
+        toString(static_cast<typename Traits::Type>(0), str);
+    }
+}
+
+typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
+typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
+typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
+typedef TypeConverter<InputFlagTraits> InputFlagConverter;
+typedef TypeConverter<FormatTraits> FormatConverter;
+typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
+typedef TypeConverter<InputChannelTraits> InputChannelConverter;
+typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
+typedef TypeConverter<GainModeTraits> GainModeConverter;
+typedef TypeConverter<StreamTraits> StreamTypeConverter;
+typedef TypeConverter<AudioModeTraits> AudioModeConverter;
+typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
+typedef TypeConverter<UsageTraits> UsageTypeConverter;
+typedef TypeConverter<SourceTraits> SourceTypeConverter;
+typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
+
+template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
+template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
+template<> const OutputFlagConverter::Table OutputFlagConverter::mTable[];
+template<> const InputFlagConverter::Table InputFlagConverter::mTable[];
+template<> const FormatConverter::Table FormatConverter::mTable[];
+template<> const OutputChannelConverter::Table OutputChannelConverter::mTable[];
+template<> const InputChannelConverter::Table InputChannelConverter::mTable[];
+template<> const ChannelIndexConverter::Table ChannelIndexConverter::mTable[];
+template<> const GainModeConverter::Table GainModeConverter::mTable[];
+template<> const StreamTypeConverter::Table StreamTypeConverter::mTable[];
+template<> const AudioModeConverter::Table AudioModeConverter::mTable[];
+template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
+template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
+template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
+template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
+
+bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
+
+SampleRateTraits::Collection samplingRatesFromString(
+        const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
+
+FormatTraits::Collection formatsFromString(
+        const std::string &formats, const char *del = AudioParameter::valueListSeparator);
+
+audio_format_t formatFromString(
+        const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);
+
+audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);
+
+ChannelTraits::Collection channelMasksFromString(
+        const std::string &channels, const char *del = AudioParameter::valueListSeparator);
+
+InputChannelTraits::Collection inputChannelMasksFromString(
+        const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);
+
+OutputChannelTraits::Collection outputChannelMasksFromString(
+        const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
+
+// counting enumerations
+template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
+                                    || std::is_same<T, audio_mode_t>::value
+                                    || std::is_same<T, audio_source_t>::value
+                                    || std::is_same<T, audio_stream_type_t>::value
+                                    || std::is_same<T, audio_usage_t>::value
+                                    || std::is_same<T, audio_format_t>::value
+                                    , int> = 0>
+static inline std::string toString(const T& value)
+{
+    std::string result;
+    return TypeConverter<DefaultTraits<T>>::toString(value, result)
+            ? result : std::to_string(static_cast<int>(value));
+
+}
+
+// flag enumerations
+template <typename T, std::enable_if_t<std::is_same<T, audio_gain_mode_t>::value
+                                    || std::is_same<T, audio_input_flags_t>::value
+                                    || std::is_same<T, audio_output_flags_t>::value
+                                    , int> = 0>
+static inline std::string toString(const T& value)
+{
+    std::string result;
+    TypeConverter<DefaultTraits<T>>::maskToString(value, result);
+    return result;
+}
+
+static inline std::string toString(const audio_devices_t& devices)
+{
+    std::string result;
+    if ((devices & AUDIO_DEVICE_BIT_IN) != 0) {
+        InputDeviceConverter::maskToString(devices, result);
+    } else {
+        OutputDeviceConverter::maskToString(devices, result);
+    }
+    return result;
+}
+
+static inline std::string toString(const audio_attributes_t& attributes)
+{
+    std::ostringstream result;
+    result << "{ Content type: " << toString(attributes.content_type)
+           << " Usage: " << toString(attributes.usage)
+           << " Source: " << toString(attributes.source)
+           << std::hex << " Flags: 0x" << attributes.flags
+           << std::dec << " Tags: " << attributes.tags
+           << " }";
+
+    return result.str();
+}
+
+}; // namespace android
+
+#endif  /*ANDROID_TYPE_CONVERTER_H_*/
diff --git a/media/libmedia/include/media/convert.h b/media/libmediahelper/include/media/convert.h
similarity index 100%
rename from media/libmedia/include/media/convert.h
rename to media/libmediahelper/include/media/convert.h
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 15ea578..03068c7 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -1,9 +1,14 @@
+cc_library_headers {
+    name: "libmediametrics_headers",
+    export_include_dirs: ["include"],
+}
+
 cc_library_shared {
     name: "libmediametrics",
 
     srcs: [
-        "IMediaAnalyticsService.cpp",
-        "MediaAnalyticsItem.cpp",
+        "IMediaMetricsService.cpp",
+        "MediaMetricsItem.cpp",
         "MediaMetrics.cpp",
     ],
 
@@ -17,9 +22,11 @@
     export_include_dirs: ["include"],
 
     cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
         "-Wall",
+        "-Werror",
+        "-Wextra",
+        "-Wthread-safety",
+        "-Wunreachable-code",
     ],
 
     sanitize: {
@@ -37,6 +44,16 @@
             "1" ,
         ]
     },
+
+    header_abi_checker: {
+        enabled: true,
+        symbol_file: "libmediametrics.map.txt",
+    },
+
+    visibility: [
+        "//cts/tests/tests/nativemedia/mediametrics",
+        "//frameworks/av:__subpackages__",
+        "//frameworks/base/core/jni",
+        "//frameworks/base/media/jni",
+    ],
 }
-
-
diff --git a/media/libmediametrics/IMediaAnalyticsService.cpp b/media/libmediametrics/IMediaAnalyticsService.cpp
deleted file mode 100644
index 9114927..0000000
--- a/media/libmediametrics/IMediaAnalyticsService.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2016 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_TAG "MediaAnalytics"
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <binder/IPCThreadState.h>
-
-#include <utils/Errors.h>  // for status_t
-#include <utils/List.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include <media/MediaAnalyticsItem.h>
-#include <media/IMediaAnalyticsService.h>
-
-#define DEBUGGING               0
-#define DEBUGGING_FLOW          0
-#define DEBUGGING_RETURNS       0
-
-namespace android {
-
-enum {
-    GENERATE_UNIQUE_SESSIONID = IBinder::FIRST_CALL_TRANSACTION,
-    SUBMIT_ITEM,
-};
-
-class BpMediaAnalyticsService: public BpInterface<IMediaAnalyticsService>
-{
-public:
-    explicit BpMediaAnalyticsService(const sp<IBinder>& impl)
-        : BpInterface<IMediaAnalyticsService>(impl)
-    {
-    }
-
-    virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() {
-        Parcel data, reply;
-        status_t err;
-        MediaAnalyticsItem::SessionID_t sessionid =
-                        MediaAnalyticsItem::SessionIDInvalid;
-
-        data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
-        err = remote()->transact(GENERATE_UNIQUE_SESSIONID, data, &reply);
-        if (err != NO_ERROR) {
-            ALOGW("bad response from service for generateSessionId, err=%d", err);
-            return MediaAnalyticsItem::SessionIDInvalid;
-        }
-        sessionid = reply.readInt64();
-        if (DEBUGGING_RETURNS) {
-            ALOGD("the caller gets a sessionid of %" PRId64 " back", sessionid);
-        }
-        return sessionid;
-    }
-
-    virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew)
-    {
-        // have this record submit itself
-        // this will be a binder call with appropriate timing
-        // return value is the uuid that the system generated for it.
-        // the return value 0 and -1 are reserved.
-        // -1 to indicate that there was a problem recording...
-
-        Parcel data, reply;
-        status_t err;
-
-        if (item == NULL) {
-                return MediaAnalyticsItem::SessionIDInvalid;
-        }
-
-        data.writeInterfaceToken(IMediaAnalyticsService::getInterfaceDescriptor());
-        if(DEBUGGING_FLOW) {
-            ALOGD("client offers record: %s", item->toString().c_str());
-        }
-        data.writeBool(forcenew);
-        item->writeToParcel(&data);
-
-        err = remote()->transact(SUBMIT_ITEM, data, &reply);
-        if (err != NO_ERROR) {
-            ALOGW("bad response from service for submit, err=%d", err);
-            return MediaAnalyticsItem::SessionIDInvalid;
-        }
-
-        // get an answer out of 'reply'
-        int64_t sessionid = reply.readInt64();
-        if (DEBUGGING_RETURNS) {
-            ALOGD("the caller gets sessionid=%" PRId64 "", sessionid);
-        }
-        return sessionid;
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaAnalyticsService, "android.media.IMediaAnalyticsService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaAnalyticsService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-
-
-    // get calling pid/tid
-    IPCThreadState *ipc = IPCThreadState::self();
-    int clientPid = ipc->getCallingPid();
-    // permission checking
-
-    if(DEBUGGING_FLOW) {
-        ALOGD("running in service, code %d, pid %d; called from pid %d",
-            code, getpid(), clientPid);
-    }
-
-    switch (code) {
-
-        case GENERATE_UNIQUE_SESSIONID: {
-            CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
-
-            MediaAnalyticsItem::SessionID_t sessionid = generateUniqueSessionID();
-            reply->writeInt64(sessionid);
-
-            return NO_ERROR;
-        } break;
-
-        case SUBMIT_ITEM: {
-            CHECK_INTERFACE(IMediaAnalyticsService, data, reply);
-
-            bool forcenew;
-            MediaAnalyticsItem *item = MediaAnalyticsItem::create();
-
-            data.readBool(&forcenew);
-            item->readFromParcel(data);
-
-            item->setPid(clientPid);
-
-            // submit() takes over ownership of 'item'
-            MediaAnalyticsItem::SessionID_t sessionid = submit(item, forcenew);
-            reply->writeInt64(sessionid);
-
-            return NO_ERROR;
-        } break;
-
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libmediametrics/IMediaMetricsService.cpp b/media/libmediametrics/IMediaMetricsService.cpp
new file mode 100644
index 0000000..b5675e6
--- /dev/null
+++ b/media/libmediametrics/IMediaMetricsService.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 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_TAG "MediaMetrics"
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+
+#include <utils/Errors.h>  // for status_t
+#include <utils/List.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <media/MediaMetricsItem.h>
+#include <media/IMediaMetricsService.h>
+
+namespace android {
+
+// TODO: Currently ONE_WAY transactions, make both ONE_WAY and synchronous options.
+
+enum {
+    SUBMIT_ITEM = IBinder::FIRST_CALL_TRANSACTION,
+    SUBMIT_BUFFER,
+};
+
+class BpMediaMetricsService: public BpInterface<IMediaMetricsService>
+{
+public:
+    explicit BpMediaMetricsService(const sp<IBinder>& impl)
+        : BpInterface<IMediaMetricsService>(impl)
+    {
+    }
+
+    status_t submit(mediametrics::Item *item) override
+    {
+        if (item == nullptr) {
+            return BAD_VALUE;
+        }
+        ALOGV("%s: (ONEWAY) item=%s", __func__, item->toString().c_str());
+
+        Parcel data;
+        data.writeInterfaceToken(IMediaMetricsService::getInterfaceDescriptor());
+
+        status_t status = item->writeToParcel(&data);
+        if (status != NO_ERROR) { // assume failure logged in item
+            return status;
+        }
+
+        status = remote()->transact(
+                SUBMIT_ITEM, data, nullptr /* reply */, IBinder::FLAG_ONEWAY);
+        ALOGW_IF(status != NO_ERROR, "%s: bad response from service for submit, status=%d",
+                __func__, status);
+        return status;
+    }
+
+    status_t submitBuffer(const char *buffer, size_t length) override
+    {
+        if (buffer == nullptr || length > INT32_MAX) {
+            return BAD_VALUE;
+        }
+        ALOGV("%s: (ONEWAY) length:%zu", __func__, length);
+
+        Parcel data;
+        data.writeInterfaceToken(IMediaMetricsService::getInterfaceDescriptor());
+
+        status_t status = data.writeInt32(length)
+                ?: data.write((uint8_t*)buffer, length);
+        if (status != NO_ERROR) {
+            return status;
+        }
+
+        status = remote()->transact(
+                SUBMIT_BUFFER, data, nullptr /* reply */, IBinder::FLAG_ONEWAY);
+        ALOGW_IF(status != NO_ERROR, "%s: bad response from service for submit, status=%d",
+                __func__, status);
+        return status;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaMetricsService, "android.media.IMediaMetricsService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaMetricsService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+    case SUBMIT_ITEM: {
+        CHECK_INTERFACE(IMediaMetricsService, data, reply);
+
+        mediametrics::Item * const item = mediametrics::Item::create();
+        status_t status = item->readFromParcel(data);
+        if (status != NO_ERROR) { // assume failure logged in item
+            return status;
+        }
+        status = submitInternal(item, true /* release */);
+        // assume failure logged by submitInternal
+        return NO_ERROR;
+    }
+    case SUBMIT_BUFFER: {
+        CHECK_INTERFACE(IMediaMetricsService, data, reply);
+        int32_t length;
+        status_t status = data.readInt32(&length);
+        if (status != NO_ERROR || length <= 0) {
+            return BAD_VALUE;
+        }
+        const void *ptr = data.readInplace(length);
+        if (ptr == nullptr) {
+            return BAD_VALUE;
+        }
+        status = submitBuffer(static_cast<const char *>(ptr), length);
+        // assume failure logged by submitBuffer
+        return NO_ERROR;
+    }
+
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
deleted file mode 100644
index 02c23b1..0000000
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "MediaAnalyticsItem"
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/Mutex.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-
-#include <binder/IServiceManager.h>
-#include <media/IMediaAnalyticsService.h>
-#include <media/MediaAnalyticsItem.h>
-#include <private/android_filesystem_config.h>
-
-namespace android {
-
-#define DEBUG_SERVICEACCESS     0
-#define DEBUG_API               0
-#define DEBUG_ALLOCATIONS       0
-
-// after this many failed attempts, we stop trying [from this process] and just say that
-// the service is off.
-#define SVC_TRIES               2
-
-// the few universal keys we have
-const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyAny  = "any";
-const MediaAnalyticsItem::Key MediaAnalyticsItem::kKeyNone  = "none";
-
-const char * const MediaAnalyticsItem::EnabledProperty  = "media.metrics.enabled";
-const char * const MediaAnalyticsItem::EnabledPropertyPersist  = "persist.media.metrics.enabled";
-const int MediaAnalyticsItem::EnabledProperty_default  = 1;
-
-// So caller doesn't need to know size of allocated space
-MediaAnalyticsItem *MediaAnalyticsItem::create()
-{
-    return MediaAnalyticsItem::create(kKeyNone);
-}
-
-MediaAnalyticsItem *MediaAnalyticsItem::create(MediaAnalyticsItem::Key key)
-{
-    MediaAnalyticsItem *item = new MediaAnalyticsItem(key);
-    return item;
-}
-
-// access functions for the class
-MediaAnalyticsItem::MediaAnalyticsItem()
-    : mPid(-1),
-      mUid(-1),
-      mPkgVersionCode(0),
-      mSessionID(MediaAnalyticsItem::SessionIDNone),
-      mTimestamp(0),
-      mFinalized(1),
-      mPropCount(0), mPropSize(0), mProps(NULL)
-{
-    mKey = MediaAnalyticsItem::kKeyNone;
-}
-
-MediaAnalyticsItem::MediaAnalyticsItem(MediaAnalyticsItem::Key key)
-    : mPid(-1),
-      mUid(-1),
-      mPkgVersionCode(0),
-      mSessionID(MediaAnalyticsItem::SessionIDNone),
-      mTimestamp(0),
-      mFinalized(1),
-      mPropCount(0), mPropSize(0), mProps(NULL)
-{
-    if (DEBUG_ALLOCATIONS) {
-        ALOGD("Allocate MediaAnalyticsItem @ %p", this);
-    }
-    mKey = key;
-}
-
-MediaAnalyticsItem::~MediaAnalyticsItem() {
-    if (DEBUG_ALLOCATIONS) {
-        ALOGD("Destroy  MediaAnalyticsItem @ %p", this);
-    }
-    clear();
-}
-
-void MediaAnalyticsItem::clear() {
-
-    // clean allocated storage from key
-    mKey.clear();
-
-    // clean various major parameters
-    mSessionID = MediaAnalyticsItem::SessionIDNone;
-
-    // clean attributes
-    // contents of the attributes
-    for (size_t i = 0 ; i < mPropCount; i++ ) {
-        clearProp(&mProps[i]);
-    }
-    // the attribute records themselves
-    if (mProps != NULL) {
-        free(mProps);
-        mProps = NULL;
-    }
-    mPropSize = 0;
-    mPropCount = 0;
-
-    return;
-}
-
-// make a deep copy of myself
-MediaAnalyticsItem *MediaAnalyticsItem::dup() {
-    MediaAnalyticsItem *dst = new MediaAnalyticsItem(this->mKey);
-
-    if (dst != NULL) {
-        // key as part of constructor
-        dst->mPid = this->mPid;
-        dst->mUid = this->mUid;
-        dst->mPkgName = this->mPkgName;
-        dst->mPkgVersionCode = this->mPkgVersionCode;
-        dst->mSessionID = this->mSessionID;
-        dst->mTimestamp = this->mTimestamp;
-        dst->mFinalized = this->mFinalized;
-
-        // properties aka attributes
-        dst->growProps(this->mPropCount);
-        for(size_t i=0;i<mPropCount;i++) {
-            copyProp(&dst->mProps[i], &this->mProps[i]);
-        }
-        dst->mPropCount = this->mPropCount;
-    }
-
-    return dst;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setSessionID(MediaAnalyticsItem::SessionID_t id) {
-    mSessionID = id;
-    return *this;
-}
-
-MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::getSessionID() const {
-    return mSessionID;
-}
-
-MediaAnalyticsItem::SessionID_t MediaAnalyticsItem::generateSessionID() {
-
-    if (mSessionID == SessionIDNone) {
-        // get one from the server
-        MediaAnalyticsItem::SessionID_t newid = SessionIDNone;
-        sp<IMediaAnalyticsService> svc = getInstance();
-        if (svc != NULL) {
-            newid = svc->generateUniqueSessionID();
-        }
-        mSessionID = newid;
-    }
-
-    return mSessionID;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::clearSessionID() {
-    mSessionID = MediaAnalyticsItem::SessionIDNone;
-    return *this;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setTimestamp(nsecs_t ts) {
-    mTimestamp = ts;
-    return *this;
-}
-
-nsecs_t MediaAnalyticsItem::getTimestamp() const {
-    return mTimestamp;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setPid(pid_t pid) {
-    mPid = pid;
-    return *this;
-}
-
-pid_t MediaAnalyticsItem::getPid() const {
-    return mPid;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setUid(uid_t uid) {
-    mUid = uid;
-    return *this;
-}
-
-uid_t MediaAnalyticsItem::getUid() const {
-    return mUid;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setPkgName(const std::string &pkgName) {
-    mPkgName = pkgName;
-    return *this;
-}
-
-MediaAnalyticsItem &MediaAnalyticsItem::setPkgVersionCode(int64_t pkgVersionCode) {
-    mPkgVersionCode = pkgVersionCode;
-    return *this;
-}
-
-int64_t MediaAnalyticsItem::getPkgVersionCode() const {
-    return mPkgVersionCode;
-}
-
-// this key is for the overall record -- "codec", "player", "drm", etc
-MediaAnalyticsItem &MediaAnalyticsItem::setKey(MediaAnalyticsItem::Key key) {
-    mKey = key;
-    return *this;
-}
-
-MediaAnalyticsItem::Key MediaAnalyticsItem::getKey() {
-    return mKey;
-}
-
-// number of attributes we have in this record
-int32_t MediaAnalyticsItem::count() const {
-    return mPropCount;
-}
-
-// find the proper entry in the list
-size_t MediaAnalyticsItem::findPropIndex(const char *name, size_t len)
-{
-    size_t i = 0;
-    for (; i < mPropCount; i++) {
-        Prop *prop = &mProps[i];
-        if (prop->mNameLen != len) {
-            continue;
-        }
-        if (memcmp(name, prop->mName, len) == 0) {
-            break;
-        }
-    }
-    return i;
-}
-
-MediaAnalyticsItem::Prop *MediaAnalyticsItem::findProp(const char *name) {
-    size_t len = strlen(name);
-    size_t i = findPropIndex(name, len);
-    if (i < mPropCount) {
-        return &mProps[i];
-    }
-    return NULL;
-}
-
-void MediaAnalyticsItem::Prop::setName(const char *name, size_t len) {
-    free((void *)mName);
-    mName = (const char *) malloc(len+1);
-    LOG_ALWAYS_FATAL_IF(mName == NULL,
-                        "failed malloc() for property '%s' (len %zu)",
-                        name, len);
-    memcpy ((void *)mName, name, len+1);
-    mNameLen = len;
-}
-
-// consider this "find-or-allocate".
-// caller validates type and uses clearPropValue() accordingly
-MediaAnalyticsItem::Prop *MediaAnalyticsItem::allocateProp(const char *name) {
-    size_t len = strlen(name);
-    size_t i = findPropIndex(name, len);
-    Prop *prop;
-
-    if (i < mPropCount) {
-        prop = &mProps[i];
-    } else {
-        if (i == mPropSize) {
-            if (growProps() == false) {
-                ALOGE("failed allocation for new props");
-                return NULL;
-            }
-        }
-        i = mPropCount++;
-        prop = &mProps[i];
-        prop->setName(name, len);
-    }
-
-    return prop;
-}
-
-// used within the summarizers; return whether property existed
-bool MediaAnalyticsItem::removeProp(const char *name) {
-    size_t len = strlen(name);
-    size_t i = findPropIndex(name, len);
-    if (i < mPropCount) {
-        Prop *prop = &mProps[i];
-        clearProp(prop);
-        if (i != mPropCount-1) {
-            // in the middle, bring last one down to fill gap
-            copyProp(prop, &mProps[mPropCount-1]);
-            clearProp(&mProps[mPropCount-1]);
-        }
-        mPropCount--;
-        return true;
-    }
-    return false;
-}
-
-// set the values
-void MediaAnalyticsItem::setInt32(MediaAnalyticsItem::Attr name, int32_t value) {
-    Prop *prop = allocateProp(name);
-    if (prop != NULL) {
-        clearPropValue(prop);
-        prop->mType = kTypeInt32;
-        prop->u.int32Value = value;
-    }
-}
-
-void MediaAnalyticsItem::setInt64(MediaAnalyticsItem::Attr name, int64_t value) {
-    Prop *prop = allocateProp(name);
-    if (prop != NULL) {
-        clearPropValue(prop);
-        prop->mType = kTypeInt64;
-        prop->u.int64Value = value;
-    }
-}
-
-void MediaAnalyticsItem::setDouble(MediaAnalyticsItem::Attr name, double value) {
-    Prop *prop = allocateProp(name);
-    if (prop != NULL) {
-        clearPropValue(prop);
-        prop->mType = kTypeDouble;
-        prop->u.doubleValue = value;
-    }
-}
-
-void MediaAnalyticsItem::setCString(MediaAnalyticsItem::Attr name, const char *value) {
-
-    Prop *prop = allocateProp(name);
-    // any old value will be gone
-    if (prop != NULL) {
-        clearPropValue(prop);
-        prop->mType = kTypeCString;
-        prop->u.CStringValue = strdup(value);
-    }
-}
-
-void MediaAnalyticsItem::setRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
-    Prop *prop = allocateProp(name);
-    if (prop != NULL) {
-        clearPropValue(prop);
-        prop->mType = kTypeRate;
-        prop->u.rate.count = count;
-        prop->u.rate.duration = duration;
-    }
-}
-
-
-// find/add/set fused into a single operation
-void MediaAnalyticsItem::addInt32(MediaAnalyticsItem::Attr name, int32_t value) {
-    Prop *prop = allocateProp(name);
-    if (prop == NULL) {
-        return;
-    }
-    switch (prop->mType) {
-        case kTypeInt32:
-            prop->u.int32Value += value;
-            break;
-        default:
-            clearPropValue(prop);
-            prop->mType = kTypeInt32;
-            prop->u.int32Value = value;
-            break;
-    }
-}
-
-void MediaAnalyticsItem::addInt64(MediaAnalyticsItem::Attr name, int64_t value) {
-    Prop *prop = allocateProp(name);
-    if (prop == NULL) {
-        return;
-    }
-    switch (prop->mType) {
-        case kTypeInt64:
-            prop->u.int64Value += value;
-            break;
-        default:
-            clearPropValue(prop);
-            prop->mType = kTypeInt64;
-            prop->u.int64Value = value;
-            break;
-    }
-}
-
-void MediaAnalyticsItem::addRate(MediaAnalyticsItem::Attr name, int64_t count, int64_t duration) {
-    Prop *prop = allocateProp(name);
-    if (prop == NULL) {
-        return;
-    }
-    switch (prop->mType) {
-        case kTypeRate:
-            prop->u.rate.count += count;
-            prop->u.rate.duration += duration;
-            break;
-        default:
-            clearPropValue(prop);
-            prop->mType = kTypeRate;
-            prop->u.rate.count = count;
-            prop->u.rate.duration = duration;
-            break;
-    }
-}
-
-void MediaAnalyticsItem::addDouble(MediaAnalyticsItem::Attr name, double value) {
-    Prop *prop = allocateProp(name);
-    if (prop == NULL) {
-        return;
-    }
-    switch (prop->mType) {
-        case kTypeDouble:
-            prop->u.doubleValue += value;
-            break;
-        default:
-            clearPropValue(prop);
-            prop->mType = kTypeDouble;
-            prop->u.doubleValue = value;
-            break;
-    }
-}
-
-// find & extract values
-bool MediaAnalyticsItem::getInt32(MediaAnalyticsItem::Attr name, int32_t *value) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeInt32) {
-        return false;
-    }
-    if (value != NULL) {
-        *value = prop->u.int32Value;
-    }
-    return true;
-}
-
-bool MediaAnalyticsItem::getInt64(MediaAnalyticsItem::Attr name, int64_t *value) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeInt64) {
-        return false;
-    }
-    if (value != NULL) {
-        *value = prop->u.int64Value;
-    }
-    return true;
-}
-
-bool MediaAnalyticsItem::getRate(MediaAnalyticsItem::Attr name, int64_t *count, int64_t *duration, double *rate) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeRate) {
-        return false;
-    }
-    if (count != NULL) {
-        *count = prop->u.rate.count;
-    }
-    if (duration != NULL) {
-        *duration = prop->u.rate.duration;
-    }
-    if (rate != NULL) {
-        double r = 0.0;
-        if (prop->u.rate.duration != 0) {
-            r = prop->u.rate.count / (double) prop->u.rate.duration;
-        }
-        *rate = r;
-    }
-    return true;
-}
-
-bool MediaAnalyticsItem::getDouble(MediaAnalyticsItem::Attr name, double *value) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeDouble) {
-        return false;
-    }
-    if (value != NULL) {
-        *value = prop->u.doubleValue;
-    }
-    return true;
-}
-
-// caller responsible for the returned string
-bool MediaAnalyticsItem::getCString(MediaAnalyticsItem::Attr name, char **value) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeCString) {
-        return false;
-    }
-    if (value != NULL) {
-        *value = strdup(prop->u.CStringValue);
-    }
-    return true;
-}
-
-bool MediaAnalyticsItem::getString(MediaAnalyticsItem::Attr name, std::string *value) {
-    Prop *prop = findProp(name);
-    if (prop == NULL || prop->mType != kTypeCString) {
-        return false;
-    }
-    if (value != NULL) {
-        // std::string makes a copy for us
-        *value = prop->u.CStringValue;
-    }
-    return true;
-}
-
-// remove indicated keys and their values
-// return value is # keys removed
-int32_t MediaAnalyticsItem::filter(int n, MediaAnalyticsItem::Attr attrs[]) {
-    int zapped = 0;
-    if (attrs == NULL || n <= 0) {
-        return -1;
-    }
-    for (ssize_t i = 0 ; i < n ;  i++) {
-        const char *name = attrs[i];
-        size_t len = strlen(name);
-        size_t j = findPropIndex(name, len);
-        if (j >= mPropCount) {
-            // not there
-            continue;
-        } else if (j+1 == mPropCount) {
-            // last one, shorten
-            zapped++;
-            clearProp(&mProps[j]);
-            mPropCount--;
-        } else {
-            // in the middle, bring last one down and shorten
-            zapped++;
-            clearProp(&mProps[j]);
-            mProps[j] = mProps[mPropCount-1];
-            mPropCount--;
-        }
-    }
-    return zapped;
-}
-
-// remove any keys NOT in the provided list
-// return value is # keys removed
-int32_t MediaAnalyticsItem::filterNot(int n, MediaAnalyticsItem::Attr attrs[]) {
-    int zapped = 0;
-    if (attrs == NULL || n <= 0) {
-        return -1;
-    }
-    for (ssize_t i = mPropCount-1 ; i >=0 ;  i--) {
-        Prop *prop = &mProps[i];
-        for (ssize_t j = 0; j < n ; j++) {
-            if (strcmp(prop->mName, attrs[j]) == 0) {
-                clearProp(prop);
-                zapped++;
-                if (i != (ssize_t)(mPropCount-1)) {
-                    *prop = mProps[mPropCount-1];
-                }
-                initProp(&mProps[mPropCount-1]);
-                mPropCount--;
-                break;
-            }
-        }
-    }
-    return zapped;
-}
-
-// remove a single key
-// return value is 0 (not found) or 1 (found and removed)
-int32_t MediaAnalyticsItem::filter(MediaAnalyticsItem::Attr name) {
-    return filter(1, &name);
-}
-
-// handle individual items/properties stored within the class
-//
-
-void MediaAnalyticsItem::initProp(Prop *prop) {
-    if (prop != NULL) {
-        prop->mName = NULL;
-        prop->mNameLen = 0;
-
-        prop->mType = kTypeNone;
-    }
-}
-
-void MediaAnalyticsItem::clearProp(Prop *prop)
-{
-    if (prop != NULL) {
-        if (prop->mName != NULL) {
-            free((void *)prop->mName);
-            prop->mName = NULL;
-            prop->mNameLen = 0;
-        }
-
-        clearPropValue(prop);
-    }
-}
-
-void MediaAnalyticsItem::clearPropValue(Prop *prop)
-{
-    if (prop != NULL) {
-        if (prop->mType == kTypeCString && prop->u.CStringValue != NULL) {
-            free(prop->u.CStringValue);
-            prop->u.CStringValue = NULL;
-        }
-        prop->mType = kTypeNone;
-    }
-}
-
-void MediaAnalyticsItem::copyProp(Prop *dst, const Prop *src)
-{
-    // get rid of any pointers in the dst
-    clearProp(dst);
-
-    *dst = *src;
-
-    // fix any pointers that we blindly copied, so we have our own copies
-    if (dst->mName) {
-        void *p =  malloc(dst->mNameLen + 1);
-        LOG_ALWAYS_FATAL_IF(p == NULL,
-                            "failed malloc() duping property '%s' (len %zu)",
-                            dst->mName, dst->mNameLen);
-        memcpy (p, src->mName, dst->mNameLen + 1);
-        dst->mName = (const char *) p;
-    }
-    if (dst->mType == kTypeCString) {
-        dst->u.CStringValue = strdup(src->u.CStringValue);
-    }
-}
-
-bool MediaAnalyticsItem::growProps(int increment)
-{
-    if (increment <= 0) {
-        increment = kGrowProps;
-    }
-    int nsize = mPropSize + increment;
-    Prop *ni = (Prop *)realloc(mProps, sizeof(Prop) * nsize);
-
-    if (ni != NULL) {
-        for (int i = mPropSize; i < nsize; i++) {
-            initProp(&ni[i]);
-        }
-        mProps = ni;
-        mPropSize = nsize;
-        return true;
-    } else {
-        ALOGW("MediaAnalyticsItem::growProps fails");
-        return false;
-    }
-}
-
-// Parcel / serialize things for binder calls
-//
-
-int32_t MediaAnalyticsItem::readFromParcel(const Parcel& data) {
-    int32_t version = data.readInt32();
-
-    switch(version) {
-        case 0:
-          return readFromParcel0(data);
-          break;
-        default:
-          ALOGE("Unsupported MediaAnalyticsItem Parcel version: %d", version);
-          return -1;
-    }
-}
-
-int32_t MediaAnalyticsItem::readFromParcel0(const Parcel& data) {
-    // into 'this' object
-    // .. we make a copy of the string to put away.
-    mKey = data.readCString();
-    mPid = data.readInt32();
-    mUid = data.readInt32();
-    mPkgName = data.readCString();
-    mPkgVersionCode = data.readInt64();
-    mSessionID = data.readInt64();
-    // We no longer pay attention to user setting of finalized, BUT it's
-    // still part of the wire packet -- so read & discard.
-    mFinalized = data.readInt32();
-    mFinalized = 1;
-    mTimestamp = data.readInt64();
-
-    int count = data.readInt32();
-    for (int i = 0; i < count ; i++) {
-            MediaAnalyticsItem::Attr attr = data.readCString();
-            int32_t ztype = data.readInt32();
-                switch (ztype) {
-                    case MediaAnalyticsItem::kTypeInt32:
-                            setInt32(attr, data.readInt32());
-                            break;
-                    case MediaAnalyticsItem::kTypeInt64:
-                            setInt64(attr, data.readInt64());
-                            break;
-                    case MediaAnalyticsItem::kTypeDouble:
-                            setDouble(attr, data.readDouble());
-                            break;
-                    case MediaAnalyticsItem::kTypeCString:
-                            setCString(attr, data.readCString());
-                            break;
-                    case MediaAnalyticsItem::kTypeRate:
-                            {
-                                int64_t count = data.readInt64();
-                                int64_t duration = data.readInt64();
-                                setRate(attr, count, duration);
-                            }
-                            break;
-                    default:
-                            ALOGE("reading bad item type: %d, idx %d",
-                                  ztype, i);
-                            return -1;
-                }
-    }
-
-    return 0;
-}
-
-int32_t MediaAnalyticsItem::writeToParcel(Parcel *data) {
-
-    if (data == NULL) return -1;
-
-    int32_t version = 0;
-    data->writeInt32(version);
-
-    switch(version) {
-        case 0:
-          return writeToParcel0(data);
-          break;
-        default:
-          ALOGE("Unsupported MediaAnalyticsItem Parcel version: %d", version);
-          return -1;
-    }
-}
-
-int32_t MediaAnalyticsItem::writeToParcel0(Parcel *data) {
-
-    data->writeCString(mKey.c_str());
-    data->writeInt32(mPid);
-    data->writeInt32(mUid);
-    data->writeCString(mPkgName.c_str());
-    data->writeInt64(mPkgVersionCode);
-    data->writeInt64(mSessionID);
-    data->writeInt32(mFinalized);
-    data->writeInt64(mTimestamp);
-
-    // set of items
-    int count = mPropCount;
-    data->writeInt32(count);
-    for (int i = 0 ; i < count; i++ ) {
-            Prop *prop = &mProps[i];
-            data->writeCString(prop->mName);
-            data->writeInt32(prop->mType);
-            switch (prop->mType) {
-                case MediaAnalyticsItem::kTypeInt32:
-                        data->writeInt32(prop->u.int32Value);
-                        break;
-                case MediaAnalyticsItem::kTypeInt64:
-                        data->writeInt64(prop->u.int64Value);
-                        break;
-                case MediaAnalyticsItem::kTypeDouble:
-                        data->writeDouble(prop->u.doubleValue);
-                        break;
-                case MediaAnalyticsItem::kTypeRate:
-                        data->writeInt64(prop->u.rate.count);
-                        data->writeInt64(prop->u.rate.duration);
-                        break;
-                case MediaAnalyticsItem::kTypeCString:
-                        data->writeCString(prop->u.CStringValue);
-                        break;
-                default:
-                        ALOGE("found bad Prop type: %d, idx %d, name %s",
-                              prop->mType, i, prop->mName);
-                        break;
-            }
-    }
-
-    return 0;
-}
-
-const char *MediaAnalyticsItem::toCString() {
-   return toCString(PROTO_LAST);
-}
-
-const char * MediaAnalyticsItem::toCString(int version) {
-    std::string val = toString(version);
-    return strdup(val.c_str());
-}
-
-std::string MediaAnalyticsItem::toString() {
-   return toString(PROTO_LAST);
-}
-
-std::string MediaAnalyticsItem::toString(int version) {
-
-    // v0 : released with 'o'
-    // v1 : bug fix (missing pid/finalized separator),
-    //      adds apk name, apk version code
-
-    if (version <= PROTO_FIRST) {
-        // default to original v0 format, until proper parsers are in place
-        version = PROTO_V0;
-    } else if (version > PROTO_LAST) {
-        version = PROTO_LAST;
-    }
-
-    std::string result;
-    char buffer[512];
-
-    if (version == PROTO_V0) {
-        result = "(";
-    } else {
-        snprintf(buffer, sizeof(buffer), "[%d:", version);
-        result.append(buffer);
-    }
-
-    // same order as we spill into the parcel, although not required
-    // key+session are our primary matching criteria
-    result.append(mKey.c_str());
-    result.append(":");
-    snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mSessionID);
-    result.append(buffer);
-
-    snprintf(buffer, sizeof(buffer), "%d:", mUid);
-    result.append(buffer);
-
-    if (version >= PROTO_V1) {
-        result.append(mPkgName);
-        snprintf(buffer, sizeof(buffer), ":%"  PRId64 ":", mPkgVersionCode);
-        result.append(buffer);
-    }
-
-    // in 'o' (v1) , the separator between pid and finalized was omitted
-    if (version <= PROTO_V0) {
-        snprintf(buffer, sizeof(buffer), "%d", mPid);
-    } else {
-        snprintf(buffer, sizeof(buffer), "%d:", mPid);
-    }
-    result.append(buffer);
-
-    snprintf(buffer, sizeof(buffer), "%d:", mFinalized);
-    result.append(buffer);
-    snprintf(buffer, sizeof(buffer), "%" PRId64 ":", mTimestamp);
-    result.append(buffer);
-
-    // set of items
-    int count = mPropCount;
-    snprintf(buffer, sizeof(buffer), "%d:", count);
-    result.append(buffer);
-    for (int i = 0 ; i < count; i++ ) {
-            Prop *prop = &mProps[i];
-            switch (prop->mType) {
-                case MediaAnalyticsItem::kTypeInt32:
-                        snprintf(buffer,sizeof(buffer),
-                        "%s=%d:", prop->mName, prop->u.int32Value);
-                        break;
-                case MediaAnalyticsItem::kTypeInt64:
-                        snprintf(buffer,sizeof(buffer),
-                        "%s=%" PRId64 ":", prop->mName, prop->u.int64Value);
-                        break;
-                case MediaAnalyticsItem::kTypeDouble:
-                        snprintf(buffer,sizeof(buffer),
-                        "%s=%e:", prop->mName, prop->u.doubleValue);
-                        break;
-                case MediaAnalyticsItem::kTypeRate:
-                        snprintf(buffer,sizeof(buffer),
-                        "%s=%" PRId64 "/%" PRId64 ":", prop->mName,
-                        prop->u.rate.count, prop->u.rate.duration);
-                        break;
-                case MediaAnalyticsItem::kTypeCString:
-                        snprintf(buffer,sizeof(buffer), "%s=", prop->mName);
-                        result.append(buffer);
-                        // XXX: sanitize string for ':' '='
-                        result.append(prop->u.CStringValue);
-                        buffer[0] = ':';
-                        buffer[1] = '\0';
-                        break;
-                default:
-                        ALOGE("to_String bad item type: %d for %s",
-                              prop->mType, prop->mName);
-                        break;
-            }
-            result.append(buffer);
-    }
-
-    if (version == PROTO_V0) {
-        result.append(")");
-    } else {
-        result.append("]");
-    }
-
-    return result;
-}
-
-// for the lazy, we offer methods that finds the service and
-// calls the appropriate daemon
-bool MediaAnalyticsItem::selfrecord() {
-    return selfrecord(false);
-}
-
-bool MediaAnalyticsItem::selfrecord(bool forcenew) {
-
-    if (DEBUG_API) {
-        std::string p = this->toString();
-        ALOGD("selfrecord of: %s [forcenew=%d]", p.c_str(), forcenew);
-    }
-
-    sp<IMediaAnalyticsService> svc = getInstance();
-
-    if (svc != NULL) {
-        MediaAnalyticsItem::SessionID_t newid = svc->submit(this, forcenew);
-        if (newid == SessionIDInvalid) {
-            std::string p = this->toString();
-            ALOGW("Failed to record: %s [forcenew=%d]", p.c_str(), forcenew);
-            return false;
-        }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-// get a connection we can reuse for most of our lifetime
-// static
-sp<IMediaAnalyticsService> MediaAnalyticsItem::sAnalyticsService;
-static Mutex sInitMutex;
-static int remainingBindAttempts = SVC_TRIES;
-
-//static
-bool MediaAnalyticsItem::isEnabled() {
-    int enabled = property_get_int32(MediaAnalyticsItem::EnabledProperty, -1);
-
-    if (enabled == -1) {
-        enabled = property_get_int32(MediaAnalyticsItem::EnabledPropertyPersist, -1);
-    }
-    if (enabled == -1) {
-        enabled = MediaAnalyticsItem::EnabledProperty_default;
-    }
-    if (enabled <= 0) {
-        return false;
-    }
-    return true;
-}
-
-
-// monitor health of our connection to the metrics service
-class MediaMetricsDeathNotifier : public IBinder::DeathRecipient {
-        virtual void binderDied(const wp<IBinder> &) {
-            ALOGW("Reacquire service connection on next request");
-            MediaAnalyticsItem::dropInstance();
-        }
-};
-
-static sp<MediaMetricsDeathNotifier> sNotifier = NULL;
-
-// static
-void MediaAnalyticsItem::dropInstance() {
-    Mutex::Autolock _l(sInitMutex);
-    remainingBindAttempts = SVC_TRIES;
-    sAnalyticsService = NULL;
-}
-
-//static
-sp<IMediaAnalyticsService> MediaAnalyticsItem::getInstance() {
-
-    static const char *servicename = "media.metrics";
-    int enabled = isEnabled();
-
-    if (enabled == false) {
-        if (DEBUG_SERVICEACCESS) {
-                ALOGD("disabled");
-        }
-        return NULL;
-    }
-
-    // completely skip logging from certain UIDs. We do this here
-    // to avoid the multi-second timeouts while we learn that
-    // sepolicy will not let us find the service.
-    // We do this only for a select set of UIDs
-    // The sepolicy protection is still in place, we just want a faster
-    // response from this specific, small set of uids.
-    {
-        uid_t uid = getuid();
-        switch (uid) {
-            case AID_RADIO:     // telephony subsystem, RIL
-                return NULL;
-                break;
-            default:
-                // let sepolicy deny access if appropriate
-                break;
-        }
-    }
-
-    {
-        Mutex::Autolock _l(sInitMutex);
-        const char *badness = "";
-
-        // think of remainingBindAttempts as telling us whether service==NULL because
-        // (1) we haven't tried to initialize it yet
-        // (2) we've tried to initialize it, but failed.
-        if (sAnalyticsService == NULL && remainingBindAttempts > 0) {
-            sp<IServiceManager> sm = defaultServiceManager();
-            if (sm != NULL) {
-                sp<IBinder> binder = sm->getService(String16(servicename));
-                if (binder != NULL) {
-                    sAnalyticsService = interface_cast<IMediaAnalyticsService>(binder);
-                    if (sNotifier != NULL) {
-                        sNotifier = NULL;
-                    }
-                    sNotifier = new MediaMetricsDeathNotifier();
-                    binder->linkToDeath(sNotifier);
-                } else {
-                    badness = "did not find service";
-                }
-            } else {
-                badness = "No Service Manager access";
-            }
-
-            if (sAnalyticsService == NULL) {
-                if (remainingBindAttempts > 0) {
-                    remainingBindAttempts--;
-                }
-                if (DEBUG_SERVICEACCESS) {
-                    ALOGD("Unable to bind to service %s: %s", servicename, badness);
-                }
-            }
-        }
-
-        return sAnalyticsService;
-    }
-}
-
-// merge the info from 'incoming' into this record.
-// we finish with a union of this+incoming and special handling for collisions
-bool MediaAnalyticsItem::merge(MediaAnalyticsItem *incoming) {
-
-    // if I don't have key or session id, take them from incoming
-    // 'this' should never be missing both of them...
-    if (mKey.empty()) {
-        mKey = incoming->mKey;
-    } else if (mSessionID == 0) {
-        mSessionID = incoming->mSessionID;
-    }
-
-    // for each attribute from 'incoming', resolve appropriately
-    int nattr = incoming->mPropCount;
-    for (int i = 0 ; i < nattr; i++ ) {
-        Prop *iprop = &incoming->mProps[i];
-        const char *p = iprop->mName;
-        size_t len = strlen(p);
-
-        // should ignore a zero length name...
-        if (len == 0) {
-            continue;
-        }
-
-        Prop *oprop = findProp(iprop->mName);
-
-        if (oprop == NULL) {
-            // no oprop, so we insert the new one
-            oprop = allocateProp(p);
-            if (oprop != NULL) {
-                copyProp(oprop, iprop);
-            } else {
-                ALOGW("dropped property '%s'", iprop->mName);
-            }
-        } else {
-            copyProp(oprop, iprop);
-        }
-    }
-
-    // not sure when we'd return false...
-    return true;
-}
-
-// a byte array; contents are
-// overall length (uint32) including the length field itself
-// encoding version (uint32)
-// count of properties (uint32)
-// N copies of:
-//     property name as length(int16), bytes
-//         the bytes WILL include the null terminator of the name
-//     type (uint8 -- 1 byte)
-//     size of value field (int16 -- 2 bytes)
-//     value (size based on type)
-//       int32, int64, double -- little endian 4/8/8 bytes respectively
-//       cstring -- N bytes of value [WITH terminator]
-
-enum { kInt32 = 0, kInt64, kDouble, kRate, kCString};
-
-bool MediaAnalyticsItem::dumpAttributes(char **pbuffer, size_t *plength) {
-
-    char *build = NULL;
-
-    if (pbuffer == NULL || plength == NULL)
-        return false;
-
-    // consistency for the caller, who owns whatever comes back in this pointer.
-    *pbuffer = NULL;
-
-    // first, let's calculate sizes
-    int32_t goal = 0;
-    int32_t version = 0;
-
-    goal += sizeof(uint32_t);   // overall length, including the length field
-    goal += sizeof(uint32_t);   // encoding version
-    goal += sizeof(uint32_t);   // # properties
-
-    int32_t count = mPropCount;
-    for (int i = 0 ; i < count; i++ ) {
-        Prop *prop = &mProps[i];
-        goal += sizeof(uint16_t);           // name length
-        goal += strlen(prop->mName) + 1;    // string + null
-        goal += sizeof(uint8_t);            // type
-        goal += sizeof(uint16_t);           // size of value
-        switch (prop->mType) {
-            case MediaAnalyticsItem::kTypeInt32:
-                    goal += sizeof(uint32_t);
-                    break;
-            case MediaAnalyticsItem::kTypeInt64:
-                    goal += sizeof(uint64_t);
-                    break;
-            case MediaAnalyticsItem::kTypeDouble:
-                    goal += sizeof(double);
-                    break;
-            case MediaAnalyticsItem::kTypeRate:
-                    goal += 2 * sizeof(uint64_t);
-                    break;
-            case MediaAnalyticsItem::kTypeCString:
-                    // length + actual string + null
-                    goal += strlen(prop->u.CStringValue) + 1;
-                    break;
-            default:
-                    ALOGE("found bad Prop type: %d, idx %d, name %s",
-                          prop->mType, i, prop->mName);
-                    return false;
-        }
-    }
-
-    // now that we have a size... let's allocate and fill
-    build = (char *)malloc(goal);
-    if (build == NULL)
-        return false;
-
-    memset(build, 0, goal);
-
-    char *filling = build;
-
-#define _INSERT(val, size) \
-    { memcpy(filling, &(val), (size)); filling += (size);}
-#define _INSERTSTRING(val, size) \
-    { memcpy(filling, (val), (size)); filling += (size);}
-
-    _INSERT(goal, sizeof(int32_t));
-    _INSERT(version, sizeof(int32_t));
-    _INSERT(count, sizeof(int32_t));
-
-    for (int i = 0 ; i < count; i++ ) {
-        Prop *prop = &mProps[i];
-        int16_t attrNameLen = strlen(prop->mName) + 1;
-        _INSERT(attrNameLen, sizeof(int16_t));
-        _INSERTSTRING(prop->mName, attrNameLen);    // termination included
-        int8_t elemtype;
-        int16_t elemsize;
-        switch (prop->mType) {
-            case MediaAnalyticsItem::kTypeInt32:
-                {
-                    elemtype = kInt32;
-                    _INSERT(elemtype, sizeof(int8_t));
-                    elemsize = sizeof(int32_t);
-                    _INSERT(elemsize, sizeof(int16_t));
-
-                    _INSERT(prop->u.int32Value, sizeof(int32_t));
-                    break;
-                }
-            case MediaAnalyticsItem::kTypeInt64:
-                {
-                    elemtype = kInt64;
-                    _INSERT(elemtype, sizeof(int8_t));
-                    elemsize = sizeof(int64_t);
-                    _INSERT(elemsize, sizeof(int16_t));
-
-                    _INSERT(prop->u.int64Value, sizeof(int64_t));
-                    break;
-                }
-            case MediaAnalyticsItem::kTypeDouble:
-                {
-                    elemtype = kDouble;
-                    _INSERT(elemtype, sizeof(int8_t));
-                    elemsize = sizeof(double);
-                    _INSERT(elemsize, sizeof(int16_t));
-
-                    _INSERT(prop->u.doubleValue, sizeof(double));
-                    break;
-                }
-            case MediaAnalyticsItem::kTypeRate:
-                {
-                    elemtype = kRate;
-                    _INSERT(elemtype, sizeof(int8_t));
-                    elemsize = 2 * sizeof(uint64_t);
-                    _INSERT(elemsize, sizeof(int16_t));
-
-                    _INSERT(prop->u.rate.count, sizeof(uint64_t));
-                    _INSERT(prop->u.rate.duration, sizeof(uint64_t));
-                    break;
-                }
-            case MediaAnalyticsItem::kTypeCString:
-                {
-                    elemtype = kCString;
-                    _INSERT(elemtype, sizeof(int8_t));
-                    elemsize = strlen(prop->u.CStringValue) + 1;
-                    _INSERT(elemsize, sizeof(int16_t));
-
-                    _INSERTSTRING(prop->u.CStringValue, elemsize);
-                    break;
-                }
-            default:
-                    // error if can't encode; warning if can't decode
-                    ALOGE("found bad Prop type: %d, idx %d, name %s",
-                          prop->mType, i, prop->mName);
-                    goto badness;
-        }
-    }
-
-    if (build + goal != filling) {
-        ALOGE("problems populating; wrote=%d planned=%d",
-              (int)(filling-build), goal);
-        goto badness;
-    }
-
-    *pbuffer = build;
-    *plength = goal;
-
-    return true;
-
-  badness:
-    free(build);
-    return false;
-}
-
-} // namespace android
-
diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp
index 6109190..a3c2f1a 100644
--- a/media/libmediametrics/MediaMetrics.cpp
+++ b/media/libmediametrics/MediaMetrics.cpp
@@ -21,7 +21,7 @@
 #include <string.h>
 #include <sys/types.h>
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/MediaMetrics.h>
 
 //
@@ -31,28 +31,31 @@
 // ALL functions returning a char * give responsibility for the allocated buffer
 // to the caller. The caller is responsible to call free() on that pointer.
 //
+//
+
+using namespace android::mediametrics;
 
 // manage the overall record
 mediametrics_handle_t mediametrics_create(mediametricskey_t key) {
-    android::MediaAnalyticsItem *item = android::MediaAnalyticsItem::create(key);
+    Item *item = Item::create(key);
     return (mediametrics_handle_t) item;
 }
 
 void mediametrics_delete(mediametrics_handle_t handle) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return;
     delete item;
 }
 
 mediametricskey_t mediametrics_getKey(mediametrics_handle_t handle) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return NULL;
     return strdup(item->getKey().c_str());
 }
 
 // nuplayer, et al use it when acting as proxies
 void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setUid(uid);
 }
 
@@ -61,31 +64,31 @@
 
 void mediametrics_setInt32(mediametrics_handle_t handle, attr_t attr,
                                 int32_t value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setInt32(attr, value);
 }
 
 void mediametrics_setInt64(mediametrics_handle_t handle, attr_t attr,
                                 int64_t value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setInt64(attr, value);
 }
 
 void mediametrics_setDouble(mediametrics_handle_t handle, attr_t attr,
                                  double value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setDouble(attr, value);
 }
 
 void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
                                int64_t count, int64_t duration) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setRate(attr, count, duration);
 }
 
 void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
                                  const char *value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->setCString(attr, value);
 }
 
@@ -94,25 +97,25 @@
 
 void mediametrics_addInt32(mediametrics_handle_t handle, attr_t attr,
                                 int32_t value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->addInt32(attr, value);
 }
 
 void mediametrics_addInt64(mediametrics_handle_t handle, attr_t attr,
                                 int64_t value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->addInt64(attr, value);
 }
 
 void mediametrics_addDouble(mediametrics_handle_t handle, attr_t attr,
                                  double value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->addDouble(attr, value);
 }
 
 void mediametrics_addRate(mediametrics_handle_t handle, attr_t attr,
                                int64_t count, int64_t duration) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item != NULL) item->addRate(attr, count, duration);
 }
 
@@ -123,28 +126,28 @@
 
 bool mediametrics_getInt32(mediametrics_handle_t handle, attr_t attr,
                                 int32_t * value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
     return item->getInt32(attr, value);
 }
 
 bool mediametrics_getInt64(mediametrics_handle_t handle, attr_t attr,
                                 int64_t * value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
     return item->getInt64(attr, value);
 }
 
 bool mediametrics_getDouble(mediametrics_handle_t handle, attr_t attr,
                                  double *value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
     return item->getDouble(attr, value);
 }
 
 bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
                                int64_t * count, int64_t * duration, double *rate) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
     return item->getRate(attr, count, duration, rate);
 }
@@ -152,7 +155,7 @@
 // NB: caller owns the string that comes back, is responsible for freeing it
 bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
                                  char **value) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
 
     return item->getCString(attr, value);
@@ -164,32 +167,37 @@
 }
 
 bool mediametrics_selfRecord(mediametrics_handle_t handle) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
     return item->selfrecord();
 }
 
+mediametrics_handle_t mediametrics_dup(mediametrics_handle_t handle) {
+    Item *item = (Item *) handle;
+    if (item == NULL) return Item::convert(item);
+    return Item::convert(item->dup());
+}
 
 const char *mediametrics_readable(mediametrics_handle_t handle) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return "";
     return item->toCString();
 }
 
 int32_t mediametrics_count(mediametrics_handle_t handle) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return 0;
     return item->count();
 }
 
 bool mediametrics_isEnabled() {
     // static, so doesn't need an instance
-    return android::MediaAnalyticsItem::isEnabled();
+    return Item::isEnabled();
 }
 
 bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, size_t *length) {
-    android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+    Item *item = (Item *) handle;
     if (item == NULL) return false;
-    return item->dumpAttributes(buffer, length);
+    return item->writeToByteString(buffer, length) == android::NO_ERROR;
 
 }
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
new file mode 100644
index 0000000..7cdbe5f
--- /dev/null
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2016 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_TAG "mediametrics::Item"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <mutex>
+#include <set>
+
+#include <binder/Parcel.h>
+#include <cutils/properties.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaMetricsService.h>
+#include <media/MediaMetricsItem.h>
+#include <private/android_filesystem_config.h>
+
+// Max per-property string size before truncation in toString().
+// Do not make too large, as this is used for dumpsys purposes.
+static constexpr size_t kMaxPropertyStringSize = 4096;
+
+namespace android::mediametrics {
+
+#define DEBUG_SERVICEACCESS     0
+#define DEBUG_API               0
+#define DEBUG_ALLOCATIONS       0
+
+// after this many failed attempts, we stop trying [from this process] and just say that
+// the service is off.
+#define SVC_TRIES               2
+
+mediametrics::Item* mediametrics::Item::convert(mediametrics_handle_t handle) {
+    mediametrics::Item *item = (android::mediametrics::Item *) handle;
+    return item;
+}
+
+mediametrics_handle_t mediametrics::Item::convert(mediametrics::Item *item ) {
+    mediametrics_handle_t handle = (mediametrics_handle_t) item;
+    return handle;
+}
+
+mediametrics::Item::~Item() {
+    if (DEBUG_ALLOCATIONS) {
+        ALOGD("Destroy  mediametrics::Item @ %p", this);
+    }
+}
+
+mediametrics::Item &mediametrics::Item::setTimestamp(nsecs_t ts) {
+    mTimestamp = ts;
+    return *this;
+}
+
+nsecs_t mediametrics::Item::getTimestamp() const {
+    return mTimestamp;
+}
+
+mediametrics::Item &mediametrics::Item::setPid(pid_t pid) {
+    mPid = pid;
+    return *this;
+}
+
+pid_t mediametrics::Item::getPid() const {
+    return mPid;
+}
+
+mediametrics::Item &mediametrics::Item::setUid(uid_t uid) {
+    mUid = uid;
+    return *this;
+}
+
+uid_t mediametrics::Item::getUid() const {
+    return mUid;
+}
+
+mediametrics::Item &mediametrics::Item::setPkgName(const std::string &pkgName) {
+    mPkgName = pkgName;
+    return *this;
+}
+
+mediametrics::Item &mediametrics::Item::setPkgVersionCode(int64_t pkgVersionCode) {
+    mPkgVersionCode = pkgVersionCode;
+    return *this;
+}
+
+int64_t mediametrics::Item::getPkgVersionCode() const {
+    return mPkgVersionCode;
+}
+
+// remove indicated keys and their values
+// return value is # keys removed
+size_t mediametrics::Item::filter(size_t n, const char *attrs[]) {
+    size_t zapped = 0;
+    for (size_t i = 0; i < n; ++i) {
+        zapped += mProps.erase(attrs[i]);
+    }
+    return zapped;
+}
+
+// remove any keys NOT in the provided list
+// return value is # keys removed
+size_t mediametrics::Item::filterNot(size_t n, const char *attrs[]) {
+    std::set<std::string> check(attrs, attrs + n);
+    size_t zapped = 0;
+    for (auto it = mProps.begin(); it != mProps.end();) {
+        if (check.find(it->first) != check.end()) {
+            ++it;
+        } else {
+           it = mProps.erase(it);
+           ++zapped;
+        }
+    }
+    return zapped;
+}
+
+// Parcel / serialize things for binder calls
+//
+
+status_t mediametrics::Item::readFromParcel(const Parcel& data) {
+    int32_t version;
+    status_t status = data.readInt32(&version);
+    if (status != NO_ERROR) return status;
+
+    switch (version) {
+    case 0:
+      return readFromParcel0(data);
+    default:
+      ALOGE("%s: unsupported parcel version: %d", __func__, version);
+      return INVALID_OPERATION;
+    }
+}
+
+status_t mediametrics::Item::readFromParcel0(const Parcel& data) {
+    const char *s = data.readCString();
+    mKey = s == nullptr ? "" : s;
+    int32_t pid, uid;
+    status_t status = data.readInt32(&pid) ?: data.readInt32(&uid);
+    if (status != NO_ERROR) return status;
+    mPid = (pid_t)pid;
+    mUid = (uid_t)uid;
+    s = data.readCString();
+    mPkgName = s == nullptr ? "" : s;
+    int32_t count;
+    int64_t version, timestamp;
+    status = data.readInt64(&version) ?: data.readInt64(&timestamp) ?: data.readInt32(&count);
+    if (status != NO_ERROR) return status;
+    if (count < 0) return BAD_VALUE;
+    mPkgVersionCode = version;
+    mTimestamp = timestamp;
+    for (int i = 0; i < count; i++) {
+        Prop prop;
+        status_t status = prop.readFromParcel(data);
+        if (status != NO_ERROR) return status;
+        mProps[prop.getName()] = std::move(prop);
+    }
+    return NO_ERROR;
+}
+
+status_t mediametrics::Item::writeToParcel(Parcel *data) const {
+    if (data == nullptr) return BAD_VALUE;
+
+    const int32_t version = 0;
+    status_t status = data->writeInt32(version);
+    if (status != NO_ERROR) return status;
+
+    switch (version) {
+    case 0:
+      return writeToParcel0(data);
+    default:
+      ALOGE("%s: unsupported parcel version: %d", __func__, version);
+      return INVALID_OPERATION;
+    }
+}
+
+status_t mediametrics::Item::writeToParcel0(Parcel *data) const {
+    status_t status =
+        data->writeCString(mKey.c_str())
+        ?: data->writeInt32(mPid)
+        ?: data->writeInt32(mUid)
+        ?: data->writeCString(mPkgName.c_str())
+        ?: data->writeInt64(mPkgVersionCode)
+        ?: data->writeInt64(mTimestamp);
+    if (status != NO_ERROR) return status;
+
+    data->writeInt32((int32_t)mProps.size());
+    for (auto &prop : *this) {
+        status = prop.writeToParcel(data);
+        if (status != NO_ERROR) return status;
+    }
+    return NO_ERROR;
+}
+
+const char *mediametrics::Item::toCString() {
+    std::string val = toString();
+    return strdup(val.c_str());
+}
+
+/*
+ * Similar to audio_utils/clock.h but customized for displaying mediametrics time.
+ */
+
+void nsToString(int64_t ns, char *buffer, size_t bufferSize, PrintFormat format)
+{
+    if (bufferSize == 0) return;
+
+    const int one_second = 1000000000;
+    const time_t sec = ns / one_second;
+    struct tm tm;
+
+    // Supported on bionic, glibc, and macOS, but not mingw.
+    if (localtime_r(&sec, &tm) == NULL) {
+        buffer[0] = '\0';
+        return;
+    }
+
+    switch (format) {
+    default:
+    case kPrintFormatLong:
+        if (snprintf(buffer, bufferSize, "%02d-%02d %02d:%02d:%02d.%03d",
+            tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
+            tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
+            (int)(ns % one_second / 1000000)) < 0) {
+            buffer[0] = '\0'; // null terminate on format error, which should not happen
+        }
+        break;
+    case kPrintFormatShort:
+        if (snprintf(buffer, bufferSize, "%02d:%02d:%02d.%03d",
+            tm.tm_hour, tm.tm_min, tm.tm_sec,
+            (int)(ns % one_second / 1000000)) < 0) {
+            buffer[0] = '\0'; // null terminate on format error, which should not happen
+        }
+        break;
+    }
+}
+
+std::string mediametrics::Item::toString() const {
+    std::string result;
+    char buffer[kMaxPropertyStringSize];
+
+    snprintf(buffer, sizeof(buffer), "{%s, (%s), (%s, %d, %d)",
+            mKey.c_str(),
+            timeStringFromNs(mTimestamp, kPrintFormatLong).time,
+            mPkgName.c_str(), mPid, mUid
+           );
+    result.append(buffer);
+    bool first = true;
+    for (auto &prop : *this) {
+        prop.toStringBuffer(buffer, sizeof(buffer));
+        result += first ? ", (" : ", ";
+        result += buffer;
+        first = false;
+    }
+    result.append(")}");
+    return result;
+}
+
+// for the lazy, we offer methods that finds the service and
+// calls the appropriate daemon
+bool mediametrics::Item::selfrecord() {
+    ALOGD_IF(DEBUG_API, "%s: delivering %s", __func__, this->toString().c_str());
+    sp<IMediaMetricsService> svc = getService();
+    if (svc != NULL) {
+        status_t status = svc->submit(this);
+        if (status != NO_ERROR) {
+            ALOGW("%s: failed to record: %s", __func__, this->toString().c_str());
+            return false;
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+//static
+bool BaseItem::isEnabled() {
+    // completely skip logging from certain UIDs. We do this here
+    // to avoid the multi-second timeouts while we learn that
+    // sepolicy will not let us find the service.
+    // We do this only for a select set of UIDs
+    // The sepolicy protection is still in place, we just want a faster
+    // response from this specific, small set of uids.
+
+    // This is checked only once in the lifetime of the process.
+    const uid_t uid = getuid();
+    switch (uid) {
+    case AID_RADIO:     // telephony subsystem, RIL
+        return false;
+    }
+
+    int enabled = property_get_int32(Item::EnabledProperty, -1);
+    if (enabled == -1) {
+        enabled = property_get_int32(Item::EnabledPropertyPersist, -1);
+    }
+    if (enabled == -1) {
+        enabled = Item::EnabledProperty_default;
+    }
+    return enabled > 0;
+}
+
+// monitor health of our connection to the metrics service
+class MediaMetricsDeathNotifier : public IBinder::DeathRecipient {
+        virtual void binderDied(const wp<IBinder> &) {
+            ALOGW("Reacquire service connection on next request");
+            BaseItem::dropInstance();
+        }
+};
+
+static sp<MediaMetricsDeathNotifier> sNotifier;
+// static
+sp<IMediaMetricsService> BaseItem::sMediaMetricsService;
+static std::mutex sServiceMutex;
+static int sRemainingBindAttempts = SVC_TRIES;
+
+// static
+void BaseItem::dropInstance() {
+    std::lock_guard  _l(sServiceMutex);
+    sRemainingBindAttempts = SVC_TRIES;
+    sMediaMetricsService = nullptr;
+}
+
+// static
+bool BaseItem::submitBuffer(const char *buffer, size_t size) {
+/*
+    mediametrics::Item item;
+    status_t status = item.readFromByteString(buffer, size);
+    ALOGD("%s: status:%d, size:%zu, item:%s", __func__, status, size, item.toString().c_str());
+    return item.selfrecord();
+    */
+
+    ALOGD_IF(DEBUG_API, "%s: delivering %zu bytes", __func__, size);
+    sp<IMediaMetricsService> svc = getService();
+    if (svc != nullptr) {
+        const status_t status = svc->submitBuffer(buffer, size);
+        if (status != NO_ERROR) {
+            ALOGW("%s: failed(%d) to record: %zu bytes", __func__, status, size);
+            return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+//static
+sp<IMediaMetricsService> BaseItem::getService() {
+    static const char *servicename = "media.metrics";
+    static const bool enabled = isEnabled(); // singleton initialized
+
+    if (enabled == false) {
+        ALOGD_IF(DEBUG_SERVICEACCESS, "disabled");
+        return nullptr;
+    }
+    std::lock_guard _l(sServiceMutex);
+    // think of remainingBindAttempts as telling us whether service == nullptr because
+    // (1) we haven't tried to initialize it yet
+    // (2) we've tried to initialize it, but failed.
+    if (sMediaMetricsService == nullptr && sRemainingBindAttempts > 0) {
+        const char *badness = "";
+        sp<IServiceManager> sm = defaultServiceManager();
+        if (sm != nullptr) {
+            sp<IBinder> binder = sm->getService(String16(servicename));
+            if (binder != nullptr) {
+                sMediaMetricsService = interface_cast<IMediaMetricsService>(binder);
+                sNotifier = new MediaMetricsDeathNotifier();
+                binder->linkToDeath(sNotifier);
+            } else {
+                badness = "did not find service";
+            }
+        } else {
+            badness = "No Service Manager access";
+        }
+        if (sMediaMetricsService == nullptr) {
+            if (sRemainingBindAttempts > 0) {
+                sRemainingBindAttempts--;
+            }
+            ALOGD_IF(DEBUG_SERVICEACCESS, "%s: unable to bind to service %s: %s",
+                    __func__, servicename, badness);
+        }
+    }
+    return sMediaMetricsService;
+}
+
+
+status_t mediametrics::Item::writeToByteString(char **pbuffer, size_t *plength) const
+{
+    if (pbuffer == nullptr || plength == nullptr)
+        return BAD_VALUE;
+
+    // get size
+    const size_t keySizeZeroTerminated = strlen(mKey.c_str()) + 1;
+    if (keySizeZeroTerminated > UINT16_MAX) {
+        ALOGW("%s: key size %zu too large", __func__, keySizeZeroTerminated);
+        return INVALID_OPERATION;
+    }
+    const uint16_t version = 0;
+    const uint32_t header_size =
+        sizeof(uint32_t)      // total size
+        + sizeof(header_size) // header size
+        + sizeof(version)     // encoding version
+        + sizeof(uint16_t)    // key size
+        + keySizeZeroTerminated // key, zero terminated
+        + sizeof(int32_t)     // pid
+        + sizeof(int32_t)     // uid
+        + sizeof(int64_t)     // timestamp
+        ;
+
+    uint32_t size = header_size
+        + sizeof(uint32_t) // # properties
+        ;
+    for (auto &prop : *this) {
+        const size_t propSize = prop.getByteStringSize();
+        if (propSize > UINT16_MAX) {
+            ALOGW("%s: prop %s size %zu too large", __func__, prop.getName(), propSize);
+            return INVALID_OPERATION;
+        }
+        if (__builtin_add_overflow(size, propSize, &size)) {
+            ALOGW("%s: item size overflow at property %s", __func__, prop.getName());
+            return INVALID_OPERATION;
+        }
+    }
+
+    // since we fill every byte in the buffer (there is no padding),
+    // malloc is used here instead of calloc.
+    char * const build = (char *)malloc(size);
+    if (build == nullptr) return NO_MEMORY;
+
+    char *filling = build;
+    char *buildmax = build + size;
+    if (insert((uint32_t)size, &filling, buildmax) != NO_ERROR
+            || insert(header_size, &filling, buildmax) != NO_ERROR
+            || insert(version, &filling, buildmax) != NO_ERROR
+            || insert((uint16_t)keySizeZeroTerminated, &filling, buildmax) != NO_ERROR
+            || insert(mKey.c_str(), &filling, buildmax) != NO_ERROR
+            || insert((int32_t)mPid, &filling, buildmax) != NO_ERROR
+            || insert((int32_t)mUid, &filling, buildmax) != NO_ERROR
+            || insert((int64_t)mTimestamp, &filling, buildmax) != NO_ERROR
+            || insert((uint32_t)mProps.size(), &filling, buildmax) != NO_ERROR) {
+        ALOGE("%s:could not write header", __func__);  // shouldn't happen
+        free(build);
+        return INVALID_OPERATION;
+    }
+    for (auto &prop : *this) {
+        if (prop.writeToByteString(&filling, buildmax) != NO_ERROR) {
+            free(build);
+            // shouldn't happen
+            ALOGE("%s:could not write prop %s", __func__, prop.getName());
+            return INVALID_OPERATION;
+        }
+    }
+
+    if (filling != buildmax) {
+        ALOGE("%s: problems populating; wrote=%d planned=%d",
+                __func__, (int)(filling - build), (int)size);
+        free(build);
+        return INVALID_OPERATION;
+    }
+    *pbuffer = build;
+    *plength = size;
+    return NO_ERROR;
+}
+
+status_t mediametrics::Item::readFromByteString(const char *bufferptr, size_t length)
+{
+    if (bufferptr == nullptr) return BAD_VALUE;
+
+    const char *read = bufferptr;
+    const char *readend = bufferptr + length;
+
+    uint32_t size;
+    uint32_t header_size;
+    uint16_t version;
+    uint16_t key_size;
+    std::string key;
+    int32_t pid;
+    int32_t uid;
+    int64_t timestamp;
+    uint32_t propCount;
+    if (extract(&size, &read, readend) != NO_ERROR
+            || extract(&header_size, &read, readend) != NO_ERROR
+            || extract(&version, &read, readend) != NO_ERROR
+            || extract(&key_size, &read, readend) != NO_ERROR
+            || extract(&key, &read, readend) != NO_ERROR
+            || extract(&pid, &read, readend) != NO_ERROR
+            || extract(&uid, &read, readend) != NO_ERROR
+            || extract(&timestamp, &read, readend) != NO_ERROR
+            || size > length
+            || key.size() + 1 != key_size
+            || header_size > size) {
+        ALOGW("%s: invalid header", __func__);
+        return INVALID_OPERATION;
+    }
+    mKey = std::move(key);
+    const size_t pos = read - bufferptr;
+    if (pos > header_size) {
+        ALOGW("%s: invalid header pos:%zu > header_size:%u",
+                __func__, pos, header_size);
+        return INVALID_OPERATION;
+    } else if (pos < header_size) {
+        ALOGW("%s: mismatched header pos:%zu < header_size:%u, advancing",
+                __func__, pos, header_size);
+        read += (header_size - pos);
+    }
+    if (extract(&propCount, &read, readend) != NO_ERROR) {
+        ALOGD("%s: cannot read prop count", __func__);
+        return INVALID_OPERATION;
+    }
+    mPid = pid;
+    mUid = uid;
+    mTimestamp = timestamp;
+    for (size_t i = 0; i < propCount; ++i) {
+        Prop prop;
+        if (prop.readFromByteString(&read, readend) != NO_ERROR) {
+            ALOGW("%s: cannot read prop %zu", __func__, i);
+            return INVALID_OPERATION;
+        }
+        mProps[prop.getName()] = std::move(prop);
+    }
+    return NO_ERROR;
+}
+
+status_t mediametrics::Item::Prop::readFromParcel(const Parcel& data)
+{
+    const char *key = data.readCString();
+    if (key == nullptr) return BAD_VALUE;
+    int32_t type;
+    status_t status = data.readInt32(&type);
+    if (status != NO_ERROR) return status;
+    switch (type) {
+    case mediametrics::kTypeInt32: {
+        int32_t value;
+        status = data.readInt32(&value);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeInt64: {
+        int64_t value;
+        status = data.readInt64(&value);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeDouble: {
+        double value;
+        status = data.readDouble(&value);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeCString: {
+        const char *s = data.readCString();
+        if (s == nullptr) return BAD_VALUE;
+        mElem = s;
+    } break;
+    case mediametrics::kTypeRate: {
+        std::pair<int64_t, int64_t> rate;
+        status = data.readInt64(&rate.first)
+                ?: data.readInt64(&rate.second);
+        if (status != NO_ERROR) return status;
+        mElem = rate;
+    } break;
+    case mediametrics::kTypeNone: {
+        mElem = std::monostate{};
+    } break;
+    default:
+        ALOGE("%s: reading bad item type: %d", __func__, type);
+        return BAD_VALUE;
+    }
+    setName(key);
+    return NO_ERROR;
+}
+
+status_t mediametrics::Item::Prop::readFromByteString(
+        const char **bufferpptr, const char *bufferptrmax)
+{
+    uint16_t len;
+    std::string name;
+    uint8_t type;
+    status_t status = extract(&len, bufferpptr, bufferptrmax)
+            ?: extract(&type, bufferpptr, bufferptrmax)
+            ?: extract(&name, bufferpptr, bufferptrmax);
+    if (status != NO_ERROR) return status;
+    switch (type) {
+    case mediametrics::kTypeInt32: {
+        int32_t value;
+        status = extract(&value, bufferpptr, bufferptrmax);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeInt64: {
+        int64_t value;
+        status = extract(&value, bufferpptr, bufferptrmax);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeDouble: {
+        double value;
+        status = extract(&value, bufferpptr, bufferptrmax);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeRate: {
+        std::pair<int64_t, int64_t> value;
+        status = extract(&value.first, bufferpptr, bufferptrmax)
+                ?: extract(&value.second, bufferpptr, bufferptrmax);
+        if (status != NO_ERROR) return status;
+        mElem = value;
+    } break;
+    case mediametrics::kTypeCString: {
+        std::string value;
+        status = extract(&value, bufferpptr, bufferptrmax);
+        if (status != NO_ERROR) return status;
+        mElem = std::move(value);
+    } break;
+    case mediametrics::kTypeNone: {
+        mElem = std::monostate{};
+    } break;
+    default:
+        ALOGE("%s: found bad prop type: %d, name %s",
+                __func__, (int)type, mName.c_str());  // no payload sent
+        return BAD_VALUE;
+    }
+    mName = name;
+    return NO_ERROR;
+}
+
+} // namespace android::mediametrics
diff --git a/media/libmediametrics/TEST_MAPPING b/media/libmediametrics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/media/libmediametrics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+       "name": "mediametrics_tests"
+    },
+    {
+       "name": "CtsNativeMediaMetricsTestCases"
+    }
+  ]
+}
diff --git a/media/libmediametrics/include/IMediaAnalyticsService.h b/media/libmediametrics/include/IMediaAnalyticsService.h
deleted file mode 100644
index f635e94..0000000
--- a/media/libmediametrics/include/IMediaAnalyticsService.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_IMEDIAANALYTICSSERVICE_H
-#define ANDROID_IMEDIAANALYTICSSERVICE_H
-
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/RefBase.h>
-#include <utils/List.h>
-
-#include <binder/IServiceManager.h>
-
-#include <media/MediaAnalyticsItem.h>
-// nope...#include <media/MediaAnalytics.h>
-
-namespace android {
-
-class IMediaAnalyticsService: public IInterface
-{
-public:
-    DECLARE_META_INTERFACE(MediaAnalyticsService);
-
-    // generate a unique sessionID to use across multiple requests
-    // 'unique' is within this device, since last reboot
-    virtual MediaAnalyticsItem::SessionID_t generateUniqueSessionID() = 0;
-
-    // submit the indicated record to the mediaanalytics service, where
-    // it will be merged (if appropriate) with incomplete records that
-    // share the same key and sessionid.
-    // 'forcenew' marks any matching incomplete record as complete before
-    // inserting this new record.
-    // returns the sessionID associated with that item.
-    // caller continues to own the passed item
-    virtual MediaAnalyticsItem::SessionID_t submit(MediaAnalyticsItem *item, bool forcenew) = 0;
-
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaAnalyticsService: public BnInterface<IMediaAnalyticsService>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIASTATISTICSSERVICE_H
diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
deleted file mode 100644
index 4a36f6a..0000000
--- a/media/libmediametrics/include/MediaAnalyticsItem.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_MEDIA_MEDIAANALYTICSITEM_H
-#define ANDROID_MEDIA_MEDIAANALYTICSITEM_H
-
-#include <string>
-#include <sys/types.h>
-
-#include <cutils/properties.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/StrongPointer.h>
-#include <utils/Timers.h>
-
-namespace android {
-
-class IMediaAnalyticsService;
-class Parcel;
-
-// the class interface
-//
-
-class MediaAnalyticsItem {
-
-    friend class MediaAnalyticsService;
-    friend class IMediaAnalyticsService;
-    friend class MediaMetricsJNI;
-    friend class MetricsSummarizer;
-    friend class MediaMetricsDeathNotifier;
-
-    public:
-
-            enum Type {
-                kTypeNone = 0,
-                kTypeInt32 = 1,
-                kTypeInt64 = 2,
-                kTypeDouble = 3,
-                kTypeCString = 4,
-                kTypeRate = 5,
-            };
-
-        // sessionid
-        // unique within device, within boot,
-        typedef int64_t SessionID_t;
-        static constexpr SessionID_t SessionIDInvalid = -1;
-        static constexpr SessionID_t SessionIDNone = 0;
-
-        // Key: the record descriminator
-        // values for the record discriminator
-        // values can be "component/component"
-        // basic values: "video", "audio", "drm"
-        // XXX: need to better define the format
-        typedef std::string Key;
-        static const Key kKeyNone;              // ""
-        static const Key kKeyAny;               // "*"
-
-        // Attr: names for attributes within a record
-        // format "prop1" or "prop/subprop"
-        // XXX: need to better define the format
-        typedef const char *Attr;
-
-
-        enum {
-            PROTO_V0 = 0,
-            PROTO_FIRST = PROTO_V0,
-            PROTO_V1 = 1,
-            PROTO_LAST = PROTO_V1,
-        };
-
-    private:
-        // use the ::create() method instead
-        MediaAnalyticsItem();
-        MediaAnalyticsItem(Key);
-        MediaAnalyticsItem(const MediaAnalyticsItem&);
-        MediaAnalyticsItem &operator=(const MediaAnalyticsItem&);
-
-    public:
-
-        static MediaAnalyticsItem* create(Key key);
-        static MediaAnalyticsItem* create();
-
-        // access functions for the class
-        ~MediaAnalyticsItem();
-
-        // SessionID ties multiple submissions for same key together
-        // so that if video "height" and "width" are known at one point
-        // and "framerate" is only known later, they can be be brought
-        // together.
-        MediaAnalyticsItem &setSessionID(SessionID_t);
-        MediaAnalyticsItem &clearSessionID();
-        SessionID_t getSessionID() const;
-        // generates and stores a new ID iff mSessionID == SessionIDNone
-        SessionID_t generateSessionID();
-
-        // reset all contents, discarding any extra data
-        void clear();
-        MediaAnalyticsItem *dup();
-
-        // set the key discriminator for the record.
-        // most often initialized as part of the constructor
-        MediaAnalyticsItem &setKey(MediaAnalyticsItem::Key);
-        MediaAnalyticsItem::Key getKey();
-
-        // # of attributes in the record
-        int32_t count() const;
-
-        // set values appropriately
-        void setInt32(Attr, int32_t value);
-        void setInt64(Attr, int64_t value);
-        void setDouble(Attr, double value);
-        void setRate(Attr, int64_t count, int64_t duration);
-        void setCString(Attr, const char *value);
-
-        // fused get/add/set; if attr wasn't there, it's a simple set.
-        // type-mismatch counts as "wasn't there".
-        void addInt32(Attr, int32_t value);
-        void addInt64(Attr, int64_t value);
-        void addDouble(Attr, double value);
-        void addRate(Attr, int64_t count, int64_t duration);
-
-        // find & extract values
-        // return indicates whether attr exists (and thus value filled in)
-        // NULL parameter value suppresses storage of value.
-        bool getInt32(Attr, int32_t *value);
-        bool getInt64(Attr, int64_t *value);
-        bool getDouble(Attr, double *value);
-        bool getRate(Attr, int64_t *count, int64_t *duration, double *rate);
-        // Caller owns the returned string
-        bool getCString(Attr, char **value);
-        bool getString(Attr, std::string *value);
-
-        // parameter indicates whether to close any existing open
-        // record with same key before establishing a new record
-        // caller retains ownership of 'this'.
-        bool selfrecord(bool);
-        bool selfrecord();
-
-        // remove indicated attributes and their values
-        // filterNot() could also be called keepOnly()
-        // return value is # attributes removed
-        // XXX: perhaps 'remove' instead of 'filter'
-        // XXX: filterNot would become 'keep'
-        int32_t filter(int count, Attr attrs[]);
-        int32_t filterNot(int count, Attr attrs[]);
-        int32_t filter(Attr attr);
-
-        // below here are used on server side or to talk to server
-        // clients need not worry about these.
-
-        // timestamp, pid, and uid only used on server side
-        // timestamp is in 'nanoseconds, unix time'
-        MediaAnalyticsItem &setTimestamp(nsecs_t);
-        nsecs_t getTimestamp() const;
-
-        MediaAnalyticsItem &setPid(pid_t);
-        pid_t getPid() const;
-
-        MediaAnalyticsItem &setUid(uid_t);
-        uid_t getUid() const;
-
-        MediaAnalyticsItem &setPkgName(const std::string &pkgName);
-        std::string getPkgName() const { return mPkgName; }
-
-        MediaAnalyticsItem &setPkgVersionCode(int64_t);
-        int64_t getPkgVersionCode() const;
-
-        // our serialization code for binder calls
-        int32_t writeToParcel(Parcel *);
-        int32_t readFromParcel(const Parcel&);
-
-        // supports the stable interface
-        bool dumpAttributes(char **pbuffer, size_t *plength);
-
-        std::string toString();
-        std::string toString(int version);
-        const char *toCString();
-        const char *toCString(int version);
-
-        // are we collecting analytics data
-        static bool isEnabled();
-
-    private:
-        // handle Parcel version 0
-        int32_t writeToParcel0(Parcel *);
-        int32_t readFromParcel0(const Parcel&);
-
-    protected:
-
-        // merge fields from arg into this
-        // with rules for first/last/add, etc
-        // XXX: document semantics and how they are indicated
-        // caller continues to own 'incoming'
-        bool merge(MediaAnalyticsItem *incoming);
-
-        // enabled 1, disabled 0
-        static const char * const EnabledProperty;
-        static const char * const EnabledPropertyPersist;
-        static const int   EnabledProperty_default;
-
-    private:
-
-        // to help validate that A doesn't mess with B's records
-        pid_t     mPid;
-        uid_t     mUid;
-        std::string   mPkgName;
-        int64_t   mPkgVersionCode;
-
-        // let's reuse a binder connection
-        static sp<IMediaAnalyticsService> sAnalyticsService;
-        static sp<IMediaAnalyticsService> getInstance();
-        static void dropInstance();
-
-        // tracking information
-        SessionID_t mSessionID;         // grouping similar records
-        nsecs_t mTimestamp;             // ns, system_time_monotonic
-
-        // will this record accept further updates
-        bool mFinalized;
-
-        Key mKey;
-
-        struct Prop {
-
-            Type mType;
-            const char *mName;
-            size_t mNameLen;    // the strlen(), doesn't include the null
-            union {
-                    int32_t int32Value;
-                    int64_t int64Value;
-                    double doubleValue;
-                    char *CStringValue;
-                    struct { int64_t count, duration; } rate;
-            } u;
-            void setName(const char *name, size_t len);
-        };
-
-        void initProp(Prop *item);
-        void clearProp(Prop *item);
-        void clearPropValue(Prop *item);
-        void copyProp(Prop *dst, const Prop *src);
-        enum {
-            kGrowProps = 10
-        };
-        bool growProps(int increment = kGrowProps);
-        size_t findPropIndex(const char *name, size_t len);
-        Prop *findProp(const char *name);
-        Prop *allocateProp(const char *name);
-        bool removeProp(const char *name);
-
-        size_t mPropCount;
-        size_t mPropSize;
-        Prop *mProps;
-};
-
-} // namespace android
-
-#endif
diff --git a/media/libmediametrics/include/MediaMetrics.h b/media/libmediametrics/include/MediaMetrics.h
deleted file mode 100644
index a4e1ed2..0000000
--- a/media/libmediametrics/include/MediaMetrics.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 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 ANDROID_MEDIA_MEDIAMETRICS_H
-#define ANDROID_MEDIA_MEDIAMETRICS_H
-
-//
-// define a C interface to the media metrics functionality
-//
-// All functions that return a char * or const char * also give responsibility
-// for that string to the caller. The caller is responsible for calling free()
-// on that pointer when done using the value.
-
-__BEGIN_DECLS
-
-// internally re-cast to the behind-the-scenes C++ class instance
-typedef int64_t mediametrics_handle_t;
-typedef const char *mediametricskey_t;
-typedef const char *attr_t;
-
-mediametrics_handle_t mediametrics_create(mediametricskey_t key);
-void mediametrics_delete(mediametrics_handle_t handle);
-
-mediametricskey_t mediametrics_getKey(mediametrics_handle_t handle);
-
-
-// set
-void mediametrics_setInt32(mediametrics_handle_t handle, attr_t attr,
-                           int32_t value);
-void mediametrics_setInt64(mediametrics_handle_t handle, attr_t attr,
-                           int64_t value);
-void mediametrics_setDouble(mediametrics_handle_t handle, attr_t attr,
-                            double value);
-void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
-                          int64_t count, int64_t duration);
-void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
-                            const char * value);
-
-// fused get/add/set; if attr wasn't there, it's a simple set.
-// these do not provide atomicity or mutual exclusion, only simpler code sequences.
-void mediametrics_addInt32(mediametrics_handle_t handle, attr_t attr,
-                           int32_t value);
-void mediametrics_addInt64(mediametrics_handle_t handle, attr_t attr,
-                           int64_t value);
-void mediametrics_addDouble(mediametrics_handle_t handle, attr_t attr,
-                            double value);
-void mediametrics_addRate(mediametrics_handle_t handle, attr_t attr,
-                          int64_t count, int64_t duration);
-
-// find & extract values
-// return indicates whether attr exists (and thus whether value filled in)
-// NULL parameter value suppresses storage of value.
-bool mediametrics_getInt32(mediametrics_handle_t handle, attr_t attr,
-                           int32_t * value);
-bool mediametrics_getInt64(mediametrics_handle_t handle, attr_t attr,
-                           int64_t * value);
-bool mediametrics_getDouble(mediametrics_handle_t handle, attr_t attr,
-                            double *value);
-bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
-                          int64_t * count, int64_t * duration, double *rate);
-bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
-                            char **value);
-// to release strings returned via getCString()
-void mediametrics_freeCString(char *value);
-
-// # of attributes set within this record.
-int32_t mediametrics_count(mediametrics_handle_t handle);
-
-bool mediametrics_selfRecord(mediametrics_handle_t handle);
-
-const char *mediametrics_readable(mediametrics_handle_t handle);
-void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid);
-bool mediametrics_isEnabled();
-
-// serialized copy of the attributes/values, mostly for upstream getMetrics() calls
-// caller owns the buffer allocated as part of this call.
-bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, size_t *length);
-
-__END_DECLS
-
-#endif
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
new file mode 100644
index 0000000..84388c9
--- /dev/null
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_MEDIAMETRICSCONSTANTS_H
+#define ANDROID_MEDIA_MEDIAMETRICSCONSTANTS_H
+
+/*
+ * MediaMetrics Keys and Properties.
+ *
+ * C/C++ friendly constants that ensure
+ * 1) Compilation error on misspelling
+ * 2) Consistent behavior and documentation.
+ */
+
+/*
+ * Taxonomy of audio keys
+ *
+ * To build longer keys, we use compiler string concatenation of
+ * adjacent string literals.  This is done in the translation phase
+ * of compilation to make a single string token.
+ */
+
+// Key Prefixes are used for MediaMetrics Item Keys and ends with a ".".
+// They must be appended with another value to make a key.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO "audio."
+
+// Device related key prefix.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE  AMEDIAMETRICS_KEY_PREFIX_AUDIO "device."
+
+// The AudioMmap key appends the "trackId" to the prefix.
+// This is the AudioFlinger equivalent of the AAudio Stream.
+// TODO: unify with AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP  AMEDIAMETRICS_KEY_PREFIX_AUDIO "mmap."
+
+// The AudioRecord key appends the "trackId" to the prefix.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD AMEDIAMETRICS_KEY_PREFIX_AUDIO "record."
+
+// The AudioStream key appends the "streamId" to the prefix.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM  AMEDIAMETRICS_KEY_PREFIX_AUDIO "stream."
+
+// The AudioThread key appends the "threadId" to the prefix.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD AMEDIAMETRICS_KEY_PREFIX_AUDIO "thread."
+
+// The AudioTrack key appends the "trackId" to the prefix.
+#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK  AMEDIAMETRICS_KEY_PREFIX_AUDIO "track."
+
+// Keys are strings used for MediaMetrics Item Keys
+#define AMEDIAMETRICS_KEY_AUDIO_FLINGER       AMEDIAMETRICS_KEY_PREFIX_AUDIO "flinger"
+#define AMEDIAMETRICS_KEY_AUDIO_POLICY        AMEDIAMETRICS_KEY_PREFIX_AUDIO "policy"
+
+/*
+ * MediaMetrics Properties are unified space for consistency and readability.
+ */
+
+// Property prefixes may be applied before a property name to indicate a specific
+// category to which it is associated.
+#define AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE "effective."
+#define AMEDIAMETRICS_PROP_PREFIX_HAL       "hal."
+#define AMEDIAMETRICS_PROP_PREFIX_HAPTIC    "haptic."
+#define AMEDIAMETRICS_PROP_PREFIX_SERVER    "server."
+
+// Properties within mediametrics are string constants denoted by
+// a macro name beginning with AMEDIAMETRICS_PROP_*
+//
+// For a property name like "auxEffectId" we write this as a single upper case word
+// at the end of the macro name, such as AMEDIAMETRICS_PROP_AUXEFFECTID.
+//
+// Underscores after the AMEDIAMETRICS_PROP_* prefix indicate
+// a "dot" in the property name. For example AMEDIAMETRICS_PROP_VOLUME_LEFT
+// corresponds to "volume.left".
+//
+// The property names are camel case, typically a lowercase letter [a-z]
+// followed by one or more characters in the range [a-zA-Z0-9_.].
+// Special symbols such as !@#$%^&*()[]{}<>,:;'"\/?|+-=~ are reserved.
+//
+// Properties within this header should include special suffixes like '#'
+// directly in the string for brevity.  Code outside of this header should
+// use the macro constant for the special symbols for searchability.
+
+// Any property that ends with a # will have duplicate values listed instead
+// of suppressed in the Time Machine.
+#define AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED '#'
+
+#define AMEDIAMETRICS_PROP_ALLOWUID       "_allowUid"      // int32_t, allow client uid to post
+#define AMEDIAMETRICS_PROP_AUDIOMODE      "audioMode"      // string (audio.flinger)
+#define AMEDIAMETRICS_PROP_AUXEFFECTID    "auxEffectId"    // int32 (AudioTrack)
+#define AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES "bufferSizeFrames" // int32
+#define AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES "bufferCapacityFrames" // int32
+#define AMEDIAMETRICS_PROP_BURSTFRAMES    "burstFrames"    // int32
+#define AMEDIAMETRICS_PROP_CALLERNAME     "callerName"     // string, eg. "aaudio"
+#define AMEDIAMETRICS_PROP_CHANNELCOUNT   "channelCount"   // int32
+#define AMEDIAMETRICS_PROP_CHANNELMASK    "channelMask"    // int32
+#define AMEDIAMETRICS_PROP_CONTENTTYPE    "contentType"    // string attributes (AudioTrack)
+#define AMEDIAMETRICS_PROP_CUMULATIVETIMENS "cumulativeTimeNs" // int64_t playback/record time
+                                                           // since start
+// DEVICE values are averaged since starting on device
+#define AMEDIAMETRICS_PROP_DEVICELATENCYMS "deviceLatencyMs" // double - avg latency time
+#define AMEDIAMETRICS_PROP_DEVICESTARTUPMS "deviceStartupMs" // double - avg startup time
+#define AMEDIAMETRICS_PROP_DEVICETIMENS   "deviceTimeNs"   // int64_t playback/record time
+#define AMEDIAMETRICS_PROP_DEVICEVOLUME   "deviceVolume"   // double - average device volume
+
+#define AMEDIAMETRICS_PROP_DIRECTION      "direction"      // string AAudio input or output
+#define AMEDIAMETRICS_PROP_DURATIONNS     "durationNs"     // int64 duration time span
+#define AMEDIAMETRICS_PROP_ENCODING       "encoding"       // string value of format
+#define AMEDIAMETRICS_PROP_EVENT          "event#"         // string value (often func name)
+#define AMEDIAMETRICS_PROP_EXECUTIONTIMENS "executionTimeNs"  // time to execute the event
+
+// TODO: fix inconsistency in flags: AudioRecord / AudioTrack int32,  AudioThread string
+#define AMEDIAMETRICS_PROP_FLAGS          "flags"
+
+#define AMEDIAMETRICS_PROP_FRAMECOUNT     "frameCount"     // int32
+#define AMEDIAMETRICS_PROP_INPUTDEVICES   "inputDevices"   // string value
+#define AMEDIAMETRICS_PROP_INTERVALCOUNT  "intervalCount"  // int32
+#define AMEDIAMETRICS_PROP_LATENCYMS      "latencyMs"      // double value
+#define AMEDIAMETRICS_PROP_NAME           "name"           // string value
+#define AMEDIAMETRICS_PROP_ORIGINALFLAGS  "originalFlags"  // int32
+#define AMEDIAMETRICS_PROP_OUTPUTDEVICES  "outputDevices"  // string value
+#define AMEDIAMETRICS_PROP_PERFORMANCEMODE "performanceMode"    // string value, "none", lowLatency"
+#define AMEDIAMETRICS_PROP_PLAYBACK_PITCH "playback.pitch" // double value (AudioTrack)
+#define AMEDIAMETRICS_PROP_PLAYBACK_SPEED "playback.speed" // double value (AudioTrack)
+#define AMEDIAMETRICS_PROP_ROUTEDDEVICEID "routedDeviceId" // int32
+#define AMEDIAMETRICS_PROP_SAMPLERATE     "sampleRate"     // int32
+#define AMEDIAMETRICS_PROP_SELECTEDDEVICEID "selectedDeviceId" // int32
+#define AMEDIAMETRICS_PROP_SELECTEDMICDIRECTION "selectedMicDirection" // int32
+#define AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION "selectedMicFieldDimension" // double
+#define AMEDIAMETRICS_PROP_SESSIONID      "sessionId"      // int32
+#define AMEDIAMETRICS_PROP_SHARINGMODE    "sharingMode"    // string value, "exclusive", shared"
+#define AMEDIAMETRICS_PROP_SOURCE         "source"         // string (AudioAttributes)
+#define AMEDIAMETRICS_PROP_STARTUPMS      "startupMs"      // double value
+// State is "ACTIVE" or "STOPPED" for AudioRecord
+#define AMEDIAMETRICS_PROP_STATE          "state"          // string
+#define AMEDIAMETRICS_PROP_STATUS         "status"         // int32 status_t
+#define AMEDIAMETRICS_PROP_STREAMTYPE     "streamType"     // string (AudioTrack)
+#define AMEDIAMETRICS_PROP_THREADID       "threadId"       // int32 value io handle
+#define AMEDIAMETRICS_PROP_THROTTLEMS     "throttleMs"     // double
+#define AMEDIAMETRICS_PROP_TRACKID        "trackId"        // int32 port id of track/record
+#define AMEDIAMETRICS_PROP_TRAITS         "traits"         // string
+#define AMEDIAMETRICS_PROP_TYPE           "type"           // string (thread type)
+#define AMEDIAMETRICS_PROP_UNDERRUN       "underrun"       // int32
+#define AMEDIAMETRICS_PROP_UNDERRUNFRAMES "underrunFrames" // int64_t from Thread
+#define AMEDIAMETRICS_PROP_USAGE          "usage"          // string attributes (ATrack)
+#define AMEDIAMETRICS_PROP_VOICEVOLUME    "voiceVolume"    // double (audio.flinger)
+#define AMEDIAMETRICS_PROP_VOLUME_LEFT    "volume.left"    // double (AudioTrack)
+#define AMEDIAMETRICS_PROP_VOLUME_RIGHT   "volume.right"   // double (AudioTrack)
+#define AMEDIAMETRICS_PROP_WHERE          "where"          // string value
+
+// Timing values: millisecond values are suffixed with MS and the type is double
+// nanosecond values are suffixed with NS and the type is int64.
+
+// Values are strings accepted for a given property.
+
+// An event is a general description, which often is a function name.
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP "beginAudioIntervalGroup"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE      "close"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE     "create"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATEAUDIOPATCH "createAudioPatch"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR       "ctor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT "disconnect"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR       "dtor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP "endAudioIntervalGroup"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH      "flush"  // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE "invalidate" // server track, record
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN       "open"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE      "pause"  // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS "readParameters" // Thread
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_RELEASE    "release"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE    "restore"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE    "setMode" // AudioFlinger
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETBUFFERSIZE    "setBufferSize" // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYBACKPARAM "setPlaybackParam" // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME   "setVoiceVolume" // AudioFlinger
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOLUME  "setVolume"  // AudioTrack
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_START      "start"  // AudioTrack, AudioRecord
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_STOP       "stop"   // AudioTrack, AudioRecord
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_UNDERRUN   "underrun" // from Thread
+
+// Possible values for AMEDIAMETRICS_PROP_CALLERNAME
+// Check within the framework for these strings as this header file may not be explicitly
+// included to avoid unnecessary cross-project dependencies.
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_AAUDIO        "aaudio"         // Native AAudio
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_JAVA          "java"           // Java API layer
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA         "media"          // libmedia
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_OPENSLES      "opensles"       // Open SLES
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_RTP           "rtp"            // RTP communication
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL     "soundpool"      // SoundPool
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_TONEGENERATOR "tonegenerator"  // dial tones
+#define AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN       "unknown"        // callerName not set
+
+#endif // ANDROID_MEDIA_MEDIAMETRICSCONSTANTS_H
diff --git a/media/libmediametrics/include/media/IMediaMetricsService.h b/media/libmediametrics/include/media/IMediaMetricsService.h
new file mode 100644
index 0000000..d6871ec
--- /dev/null
+++ b/media/libmediametrics/include/media/IMediaMetricsService.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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 ANDROID_IMEDIAANALYTICSSERVICE_H
+#define ANDROID_IMEDIAANALYTICSSERVICE_H
+
+#include <utils/String8.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <utils/List.h>
+
+#include <binder/IServiceManager.h>
+
+#include <media/MediaMetricsItem.h>
+
+namespace android {
+
+class IMediaMetricsService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaMetricsService);
+
+    /**
+     * Submits the indicated record to the mediaanalytics service, where
+     * it will be merged (if appropriate) with incomplete records that
+     * share the same key and sessionID.
+     *
+     * \param item the item to submit.
+     * \return status which is negative if an error is detected (some errors
+               may be silent and return 0 - success).
+     */
+    virtual status_t submit(mediametrics::Item *item) = 0;
+
+    virtual status_t submitBuffer(const char *buffer, size_t length) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaMetricsService: public BnInterface<IMediaMetricsService>
+{
+public:
+    status_t onTransact(uint32_t code,
+                        const Parcel& data,
+                        Parcel* reply,
+                        uint32_t flags = 0) override;
+
+protected:
+    // Internal call where release is true if the service is to delete the item.
+    virtual status_t submitInternal(
+            mediametrics::Item *item, bool release) = 0;
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIASTATISTICSSERVICE_H
diff --git a/media/libmediametrics/include/media/MediaMetrics.h b/media/libmediametrics/include/media/MediaMetrics.h
new file mode 100644
index 0000000..76abe86
--- /dev/null
+++ b/media/libmediametrics/include/media/MediaMetrics.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 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 ANDROID_MEDIA_MEDIAMETRICS_H
+#define ANDROID_MEDIA_MEDIAMETRICS_H
+
+//
+// define a C interface to the media metrics functionality
+//
+// All functions that return a char * or const char * also give responsibility
+// for that string to the caller. The caller is responsible for calling free()
+// on that pointer when done using the value.
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+// internally re-cast to the behind-the-scenes C++ class instance
+typedef int64_t mediametrics_handle_t;
+typedef const char *mediametricskey_t;
+typedef const char *attr_t;
+
+mediametrics_handle_t mediametrics_create(mediametricskey_t key);
+void mediametrics_delete(mediametrics_handle_t handle);
+
+mediametricskey_t mediametrics_getKey(mediametrics_handle_t handle);
+
+
+// set
+void mediametrics_setInt32(mediametrics_handle_t handle, attr_t attr,
+                           int32_t value);
+void mediametrics_setInt64(mediametrics_handle_t handle, attr_t attr,
+                           int64_t value);
+void mediametrics_setDouble(mediametrics_handle_t handle, attr_t attr,
+                            double value);
+void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
+                          int64_t count, int64_t duration);
+void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
+                            const char * value);
+
+// fused get/add/set; if attr wasn't there, it's a simple set.
+// these do not provide atomicity or mutual exclusion, only simpler code sequences.
+void mediametrics_addInt32(mediametrics_handle_t handle, attr_t attr,
+                           int32_t value);
+void mediametrics_addInt64(mediametrics_handle_t handle, attr_t attr,
+                           int64_t value);
+void mediametrics_addDouble(mediametrics_handle_t handle, attr_t attr,
+                            double value);
+void mediametrics_addRate(mediametrics_handle_t handle, attr_t attr,
+                          int64_t count, int64_t duration);
+
+// find & extract values
+// return indicates whether attr exists (and thus whether value filled in)
+// NULL parameter value suppresses storage of value.
+bool mediametrics_getInt32(mediametrics_handle_t handle, attr_t attr,
+                           int32_t * value);
+bool mediametrics_getInt64(mediametrics_handle_t handle, attr_t attr,
+                           int64_t * value);
+bool mediametrics_getDouble(mediametrics_handle_t handle, attr_t attr,
+                            double *value);
+bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
+                          int64_t * count, int64_t * duration, double *rate);
+bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
+                            char **value);
+// to release strings returned via getCString()
+void mediametrics_freeCString(char *value);
+
+// # of attributes set within this record.
+int32_t mediametrics_count(mediametrics_handle_t handle);
+
+mediametrics_handle_t mediametrics_dup(mediametrics_handle_t handle);
+bool mediametrics_selfRecord(mediametrics_handle_t handle);
+
+const char *mediametrics_readable(mediametrics_handle_t handle);
+void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid);
+bool mediametrics_isEnabled();
+
+// serialized copy of the attributes/values, mostly for upstream getMetrics() calls
+// caller owns the buffer allocated as part of this call.
+bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, size_t *length);
+
+__END_DECLS
+
+#endif
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
new file mode 100644
index 0000000..303343f
--- /dev/null
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -0,0 +1,1183 @@
+/*
+ * Copyright (C) 2016 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 ANDROID_MEDIA_MEDIAMETRICSITEM_H
+#define ANDROID_MEDIA_MEDIAMETRICSITEM_H
+
+#include "MediaMetrics.h"
+#include "MediaMetricsConstants.h"
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <sys/types.h>
+#include <variant>
+
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/Timers.h> // nsecs_t
+
+namespace android {
+
+class IMediaMetricsService;
+class Parcel;
+
+/*
+ * MediaMetrics Item
+ *
+ * The MediaMetrics Item allows get/set operations and recording to the service.
+ *
+ * The MediaMetrics LogItem is a faster logging variant. It allows set operations only,
+ * and then recording to the service.
+ *
+ * The Byte String format is as follows:
+ *
+ * For Java
+ *  int64 corresponds to long
+ *  int32, uint32 corresponds to int
+ *  uint16 corresponds to char
+ *  uint8, int8 corresponds to byte
+ *
+ * For items transmitted from Java, uint8 and uint32 values are limited
+ * to INT8_MAX and INT32_MAX.  This constrains the size of large items
+ * to 2GB, which is consistent with ByteBuffer max size. A native item
+ * can conceivably have size of 4GB.
+ *
+ * Physical layout of integers and doubles within the MediaMetrics byte string
+ * is in Native / host order, which is usually little endian.
+ *
+ * Note that primitive data (ints, doubles) within a Byte String has
+ * no extra padding or alignment requirements, like ByteBuffer.
+ *
+ * -- begin of item
+ * -- begin of header
+ * (uint32) item size: including the item size field
+ * (uint32) header size, including the item size and header size fields.
+ * (uint16) version: exactly 0
+ * (uint16) key size, that is key strlen + 1 for zero termination.
+ * (int8)+ key, a string which is 0 terminated (UTF-8).
+ * (int32) pid
+ * (int32) uid
+ * (int64) timestamp
+ * -- end of header
+ * -- begin body
+ * (uint32) number of properties
+ * -- repeat for number of properties
+ *     (uint16) property size, including property size field itself
+ *     (uint8) type of property
+ *     (int8)+ key string, including 0 termination
+ *      based on type of property (given above), one of:
+ *       (int32)
+ *       (int64)
+ *       (double)
+ *       (int8)+ for TYPE_CSTRING, including 0 termination
+ *       (int64, int64) for rate
+ * -- end body
+ * -- end of item
+ *
+ * The Byte String format must match MediaMetrics.java.
+ */
+
+namespace mediametrics {
+
+// Type must match MediaMetrics.java
+enum Type {
+    kTypeNone = 0,
+    kTypeInt32 = 1,
+    kTypeInt64 = 2,
+    kTypeDouble = 3,
+    kTypeCString = 4,
+    kTypeRate = 5,
+};
+
+/*
+ * Time printing
+ *
+ * kPrintFormatLong time string is 19 characters (including null termination).
+ * Example Long Form: "03-27 16:47:06.187"
+ *                     MM DD HH MM SS MS
+ *
+ * kPrintFormatShort time string is 13 characters (including null termination).
+ * Example Short Form: "16:47:06.187"
+ *                      HH MM SS MS
+ */
+
+enum PrintFormat {
+    kPrintFormatLong = 0,
+    kPrintFormatShort = 1,
+};
+
+/**
+ * Converts real time in ns to a time string object, with format similar to logcat.
+ *
+ * \param ns         input real time in nanoseconds to convert.
+ * \param buffer     the buffer location to put the converted string.
+ * \param bufferSize the size of buffer in bytes.
+ * \param format     format, from enum PrintFormat.
+ */
+void nsToString(
+        int64_t ns, char *buffer, size_t bufferSize, PrintFormat format = kPrintFormatLong);
+
+// Contains the time string
+struct time_string_t {
+    char time[19]; /* minimum size buffer */
+};
+
+/**
+ * Converts real time in ns to a time string object, with format similar to logcat.
+ *
+ * \param ns     input real time in nanoseconds to convert.
+ * \param format format, from enum PrintFormat.
+ * \return       a time_string_t object with the time string encoded.
+ */
+static inline time_string_t timeStringFromNs(int64_t ns, PrintFormat format = kPrintFormatLong) {
+    time_string_t ts;
+    nsToString(ns, ts.time, sizeof(ts.time), format);
+    return ts;
+}
+
+/**
+ * Finds the end of the common time prefix.
+ *
+ * This is as an option to remove the common time prefix to avoid
+ * unnecessary duplicated strings.
+ *
+ * \param time1 a time string from timeStringFromNs
+ * \param time2 a time string from timeStringFromNs
+ * \return      the position where the common time prefix ends. For abbreviated
+ *              printing of time2, offset the character pointer by this position.
+ */
+static inline size_t commonTimePrefixPosition(const char *time1, const char *time2) {
+    size_t i;
+
+    // Find location of the first mismatch between strings
+    for (i = 0; ; ++i) {
+        if (time1[i] != time2[i]) {
+            break;
+        }
+        if (time1[i] == 0) {
+            return i; // strings match completely
+        }
+    }
+
+    // Go backwards until we find a delimeter or space.
+    for (; i > 0
+           && isdigit(time1[i]) // still a number
+           && time1[i - 1] != ' '
+         ; --i) {
+    }
+    return i;
+}
+
+/**
+ * The MediaMetrics Item has special Item properties,
+ * derived internally or through dedicated setters.
+ *
+ * For consistency we use the following keys to represent
+ * these special Item properties when in a generic Bundle
+ * or in a std::map.
+ *
+ * These values must match MediaMetrics.java
+ */
+static inline constexpr const char *BUNDLE_TOTAL_SIZE = "_totalSize";
+static inline constexpr const char *BUNDLE_HEADER_SIZE = "_headerSize";
+static inline constexpr const char *BUNDLE_VERSION = "_version";
+static inline constexpr const char *BUNDLE_KEY_SIZE = "_keySize";
+static inline constexpr const char *BUNDLE_KEY = "_key";
+static inline constexpr const char *BUNDLE_PID = "_pid";
+static inline constexpr const char *BUNDLE_UID = "_uid";
+static inline constexpr const char *BUNDLE_TIMESTAMP = "_timestamp";
+static inline constexpr const char *BUNDLE_PROPERTY_COUNT = "_propertyCount";
+
+template<size_t N>
+static inline bool startsWith(const std::string &s, const char (&comp)[N]) {
+    return !strncmp(s.c_str(), comp, N - 1); // last char is null termination
+}
+
+static inline bool startsWith(const std::string& s, const std::string& comp) {
+    return !strncmp(s.c_str(), comp.c_str(), comp.size());
+}
+
+/**
+ * Defers a function to run in the destructor.
+ *
+ * This helper class is used to log results on exit of a method.
+ */
+class Defer {
+public:
+    template <typename U>
+    explicit Defer(U &&f) : mThunk(std::forward<U>(f)) {}
+    ~Defer() { mThunk(); }
+
+private:
+    const std::function<void()> mThunk;
+};
+
+/**
+ * Media Metrics BaseItem
+ *
+ * A base class which contains utility static functions to write to a byte stream
+ * and access the Media Metrics service.
+ */
+
+class BaseItem {
+    friend class MediaMetricsDeathNotifier; // for dropInstance
+    // enabled 1, disabled 0
+public:
+    // are we collecting metrics data
+    static bool isEnabled();
+    static sp<IMediaMetricsService> getService();
+
+protected:
+    static constexpr const char * const EnabledProperty = "media.metrics.enabled";
+    static constexpr const char * const EnabledPropertyPersist = "persist.media.metrics.enabled";
+    static const int EnabledProperty_default = 1;
+
+    // let's reuse a binder connection
+    static sp<IMediaMetricsService> sMediaMetricsService;
+
+    static void dropInstance();
+    static bool submitBuffer(const char *buffer, size_t len);
+
+    template <typename T>
+    struct is_item_type {
+        static constexpr inline bool value =
+             std::is_same<T, int32_t>::value
+             || std::is_same<T, int64_t>::value
+             || std::is_same<T, double>::value
+             || std::is_same<T, std::pair<int64_t, int64_t>>:: value
+             || std::is_same<T, std::string>::value
+             || std::is_same<T, std::monostate>::value;
+    };
+
+    template <typename T>
+    struct get_type_of {
+        static_assert(is_item_type<T>::value);
+        static constexpr inline Type value =
+             std::is_same<T, int32_t>::value ? kTypeInt32
+             : std::is_same<T, int64_t>::value ? kTypeInt64
+             : std::is_same<T, double>::value ? kTypeDouble
+             : std::is_same<T, std::pair<int64_t, int64_t>>:: value ? kTypeRate
+             : std::is_same<T, std::string>::value ? kTypeCString
+             : std::is_same<T, std::monostate>::value ? kTypeNone
+         : kTypeNone;
+    };
+
+    template <typename T>
+    static size_t sizeOfByteString(const char *name, const T& value) {
+        static_assert(is_item_type<T>::value);
+        return 2 + 1 + strlen(name) + 1 + sizeof(value);
+    }
+    template <> // static
+    size_t sizeOfByteString(const char *name, const std::string& value) {
+        return 2 + 1 + strlen(name) + 1 + value.size() + 1;
+    }
+    template <> // static
+    size_t sizeOfByteString(const char *name, const std::monostate&) {
+         return 2 + 1 + strlen(name) + 1;
+    }
+    // for speed
+    static size_t sizeOfByteString(const char *name, const char *value) {
+        return 2 + 1 + strlen(name) + 1 + strlen(value) + 1;
+    }
+
+    template <typename T>
+    static status_t insert(const T& val, char **bufferpptr, char *bufferptrmax) {
+        static_assert(std::is_trivially_constructible<T>::value);
+        const size_t size = sizeof(val);
+        if (*bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(*bufferpptr, &val, size);
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t insert(const std::string& val, char **bufferpptr, char *bufferptrmax) {
+        const size_t size = val.size() + 1;
+        if (size > UINT16_MAX || *bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(*bufferpptr, val.c_str(), size);
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t insert(const std::pair<int64_t, int64_t>& val,
+            char **bufferpptr, char *bufferptrmax) {
+        const size_t size = sizeof(val.first) + sizeof(val.second);
+        if (*bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(*bufferpptr, &val.first, sizeof(val.first));
+        memcpy(*bufferpptr + sizeof(val.first), &val.second, sizeof(val.second));
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t insert(const std::monostate&, char **, char *) {
+        return NO_ERROR;
+    }
+    // for speed
+    static status_t insert(const char *val, char **bufferpptr, char *bufferptrmax) {
+        const size_t size = strlen(val) + 1;
+        if (size > UINT16_MAX || *bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(*bufferpptr, val, size);
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+
+    template <typename T>
+    static status_t writeToByteString(
+            const char *name, const T& value, char **bufferpptr, char *bufferptrmax) {
+        static_assert(is_item_type<T>::value);
+        const size_t len = sizeOfByteString(name, value);
+        if (len > UINT16_MAX) return BAD_VALUE;
+        return insert((uint16_t)len, bufferpptr, bufferptrmax)
+                ?: insert((uint8_t)get_type_of<T>::value, bufferpptr, bufferptrmax)
+                ?: insert(name, bufferpptr, bufferptrmax)
+                ?: insert(value, bufferpptr, bufferptrmax);
+    }
+    // for speed
+    static status_t writeToByteString(
+            const char *name, const char *value, char **bufferpptr, char *bufferptrmax) {
+        const size_t len = sizeOfByteString(name, value);
+        if (len > UINT16_MAX) return BAD_VALUE;
+        return insert((uint16_t)len, bufferpptr, bufferptrmax)
+                ?: insert((uint8_t)kTypeCString, bufferpptr, bufferptrmax)
+                ?: insert(name, bufferpptr, bufferptrmax)
+                ?: insert(value, bufferpptr, bufferptrmax);
+    }
+
+    template <typename T>
+    static void toStringBuffer(
+            const char *name, const T& value, char *buffer, size_t length) = delete;
+    template <> // static
+    void toStringBuffer(
+            const char *name, const int32_t& value, char *buffer, size_t length) {
+        snprintf(buffer, length, "%s=%d", name, value);
+    }
+    template <> // static
+    void toStringBuffer(
+            const char *name, const int64_t& value, char *buffer, size_t length) {
+        snprintf(buffer, length, "%s=%lld", name, (long long)value);
+    }
+    template <> // static
+    void toStringBuffer(
+            const char *name, const double& value, char *buffer, size_t length) {
+        snprintf(buffer, length, "%s=%e", name, value);
+    }
+    template <> // static
+    void toStringBuffer(
+            const char *name, const std::pair<int64_t, int64_t>& value,
+            char *buffer, size_t length) {
+        snprintf(buffer, length, "%s=%lld/%lld",
+                name, (long long)value.first, (long long)value.second);
+    }
+    template <> // static
+    void toStringBuffer(
+            const char *name, const std::string& value, char *buffer, size_t length) {
+        // TODO sanitize string for ':' '='
+        snprintf(buffer, length, "%s=%s", name, value.c_str());
+    }
+    template <> // static
+    void toStringBuffer(
+            const char *name, const std::monostate&, char *buffer, size_t length) {
+        snprintf(buffer, length, "%s=()", name);
+    }
+
+    template <typename T>
+    static status_t writeToParcel(
+            const char *name, const T& value, Parcel *parcel) = delete;
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const int32_t& value, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of<int32_t>::value)
+               ?: parcel->writeInt32(value);
+    }
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const int64_t& value, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of<int64_t>::value)
+               ?: parcel->writeInt64(value);
+    }
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const double& value, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of<double>::value)
+               ?: parcel->writeDouble(value);
+    }
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const std::pair<int64_t, int64_t>& value, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of< std::pair<int64_t, int64_t>>::value)
+               ?: parcel->writeInt64(value.first)
+               ?: parcel->writeInt64(value.second);
+    }
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const std::string& value, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of<std::string>::value)
+               ?: parcel->writeCString(value.c_str());
+    }
+    template <> // static
+    status_t writeToParcel(
+            const char *name, const std::monostate&, Parcel *parcel) {
+        return parcel->writeCString(name)
+               ?: parcel->writeInt32(get_type_of<std::monostate>::value);
+    }
+
+    template <typename T>
+    static status_t extract(T *val, const char **bufferpptr, const char *bufferptrmax) {
+        static_assert(std::is_trivially_constructible<T>::value);
+        const size_t size = sizeof(*val);
+        if (*bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(val, *bufferpptr, size);
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t extract(std::string *val, const char **bufferpptr, const char *bufferptrmax) {
+        const char *ptr = *bufferpptr;
+        while (*ptr != 0) {
+            if (ptr >= bufferptrmax) {
+                ALOGE("%s: buffer exceeded", __func__);
+                return BAD_VALUE;
+            }
+            ++ptr;
+        }
+        const size_t size = (ptr - *bufferpptr) + 1;
+        *val = *bufferpptr;
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t extract(std::pair<int64_t, int64_t> *val,
+            const char **bufferpptr, const char *bufferptrmax) {
+        const size_t size = sizeof(val->first) + sizeof(val->second);
+        if (*bufferpptr + size > bufferptrmax) {
+            ALOGE("%s: buffer exceeded with size %zu", __func__, size);
+            return BAD_VALUE;
+        }
+        memcpy(&val->first, *bufferpptr, sizeof(val->first));
+        memcpy(&val->second, *bufferpptr + sizeof(val->first), sizeof(val->second));
+        *bufferpptr += size;
+        return NO_ERROR;
+    }
+    template <> // static
+    status_t extract(std::monostate *, const char **, const char *) {
+        return NO_ERROR;
+    }
+};
+
+/**
+ * Media Metrics BufferedItem
+ *
+ * A base class which represents a put-only Media Metrics item, storing
+ * the Media Metrics data in a buffer with begin and end pointers.
+ *
+ * If a property key is entered twice, it will be stored in the buffer twice,
+ * and (implementation defined) the last value for that key will be used
+ * by the Media Metrics service.
+ *
+ * For realloc, a baseRealloc pointer must be passed in either explicitly
+ * or implicitly in the constructor. This will be updated with the value used on realloc.
+ */
+class BufferedItem : public BaseItem {
+public:
+    static inline constexpr uint16_t kVersion = 0;
+
+    virtual ~BufferedItem() = default;
+    BufferedItem(const BufferedItem&) = delete;
+    BufferedItem& operator=(const BufferedItem&) = delete;
+
+    BufferedItem(const std::string& key, char *begin, char *end)
+        : BufferedItem(key.c_str(), begin, end) { }
+
+    BufferedItem(const char *key, char *begin, char *end)
+        : BufferedItem(key, begin, end, nullptr) { }
+
+    BufferedItem(const char *key, char **begin, char *end)
+        : BufferedItem(key, *begin, end, begin) { }
+
+    BufferedItem(const char *key, char *begin, char *end, char **baseRealloc)
+        : mBegin(begin)
+        , mEnd(end)
+        , mBaseRealloc(baseRealloc)
+    {
+        init(key);
+    }
+
+    template<typename T>
+    BufferedItem &set(const char *key, const T& value) {
+        reallocFor(sizeOfByteString(key, value));
+        if (mStatus == NO_ERROR) {
+            mStatus = BaseItem::writeToByteString(key, value, &mBptr, mEnd);
+            ++mPropCount;
+        }
+        return *this;
+    }
+
+    template<typename T>
+    BufferedItem &set(const std::string& key, const T& value) {
+        return set(key.c_str(), value);
+    }
+
+    BufferedItem &setPid(pid_t pid) {
+        if (mStatus == NO_ERROR) {
+            copyTo(mBegin + mHeaderLen - 16, (int32_t)pid);
+        }
+        return *this;
+    }
+
+    BufferedItem &setUid(uid_t uid) {
+        if (mStatus == NO_ERROR) {
+            copyTo(mBegin + mHeaderLen - 12, (int32_t)uid);
+        }
+        return *this;
+    }
+
+    BufferedItem &setTimestamp(nsecs_t timestamp) {
+        if (mStatus == NO_ERROR) {
+            copyTo(mBegin + mHeaderLen - 8, (int64_t)timestamp);
+        }
+        return *this;
+    }
+
+    bool record() {
+        return updateHeader()
+                && BaseItem::submitBuffer(getBuffer(), getLength());
+    }
+
+    bool isValid () const {
+        return mStatus == NO_ERROR;
+    }
+
+    char *getBuffer() const { return mBegin; }
+    size_t getLength() const { return mBptr - mBegin; }
+    size_t getRemaining() const { return mEnd - mBptr; }
+    size_t getCapacity() const { return mEnd - mBegin; }
+
+    bool updateHeader() {
+        if (mStatus != NO_ERROR) return false;
+        copyTo(mBegin + 0, (uint32_t)getLength());
+        copyTo(mBegin + 4, (uint32_t)mHeaderLen);
+        copyTo(mBegin + mHeaderLen, (uint32_t)mPropCount);
+        return true;
+    }
+
+protected:
+    BufferedItem() = default;
+
+    void reallocFor(size_t required) {
+        if (mStatus != NO_ERROR) return;
+        const size_t remaining = getRemaining();
+        if (required <= remaining) return;
+        if (mBaseRealloc == nullptr) {
+            mStatus = NO_MEMORY;
+            return;
+        }
+
+        const size_t current = getLength();
+        size_t minimum = current + required;
+        if (minimum > SSIZE_MAX >> 1) {
+            mStatus = NO_MEMORY;
+            return;
+        }
+        minimum <<= 1;
+        void *newptr = realloc(*mBaseRealloc, minimum);
+        if (newptr == nullptr) {
+            mStatus = NO_MEMORY;
+            return;
+        }
+        if (newptr != *mBaseRealloc) {
+            // ALOGD("base changed! current:%zu new size %zu", current, minimum);
+            if (*mBaseRealloc == nullptr) {
+                memcpy(newptr, mBegin, current);
+            }
+            mBegin = (char *)newptr;
+            *mBaseRealloc = mBegin;
+            mEnd = mBegin + minimum;
+            mBptr = mBegin + current;
+        } else {
+            // ALOGD("base kept! current:%zu new size %zu", current, minimum);
+            mEnd = mBegin + minimum;
+        }
+    }
+    template<typename T>
+    void copyTo(char *ptr, const T& value) {
+        memcpy(ptr, &value, sizeof(value));
+    }
+
+    void init(const char *key) {
+        mBptr = mBegin;
+        const size_t keylen = key == nullptr ? 0 : strlen(key) + 1;
+        if (keylen <= 1) {
+            mStatus = BAD_VALUE; // prevent null pointer or empty keys.
+            return;
+        }
+        mHeaderLen = 4 + 4 + 2 + 2 + keylen + 4 + 4 + 8;
+        reallocFor(mHeaderLen);
+        if (mStatus != NO_ERROR) return;
+        mBptr = mBegin + mHeaderLen + 4; // this includes propcount.
+
+        if (mEnd < mBptr || keylen > UINT16_MAX) {
+           mStatus = NO_MEMORY;
+           mBptr = mEnd;
+           return;
+        }
+        copyTo(mBegin + 8, kVersion);
+        copyTo(mBegin + 10, (uint16_t)keylen);
+        strcpy(mBegin + 12, key);
+
+        // initialize some parameters (that could be overridden)
+        setPid(-1);
+        setUid(-1);
+        setTimestamp(0);
+    }
+
+    char *mBegin = nullptr;
+    char *mEnd = nullptr;
+    char **mBaseRealloc = nullptr;  // set to an address if realloc should be done.
+                                    // upon return, that pointer is updated with
+                                    // whatever needs to be freed.
+    char *mBptr = nullptr;
+    status_t mStatus = NO_ERROR;
+    uint32_t mPropCount = 0;
+    uint32_t mHeaderLen = 0;
+};
+
+/**
+ * MediaMetrics LogItem is a stack allocated mediametrics item used for
+ * fast logging.  It falls over to a malloc if needed.
+ *
+ * This is templated with a buffer size to allocate on the stack.
+ */
+template <size_t N = 4096>
+class LogItem : public BufferedItem {
+public:
+    explicit LogItem(const std::string& key) : LogItem(key.c_str()) { }
+
+    // Since this class will not be defined before the base class, we initialize variables
+    // in our own order.
+    explicit LogItem(const char *key) {
+         mBegin = mBuffer;
+         mEnd = mBuffer + N;
+         mBaseRealloc = &mReallocPtr;
+         init(key);
+    }
+
+    ~LogItem() override {
+        if (mReallocPtr != nullptr) { // do the check before calling free to avoid overhead.
+            free(mReallocPtr);
+        }
+    }
+
+private:
+    char *mReallocPtr = nullptr;  // set non-null by base class if realloc happened.
+    char mBuffer[N];
+};
+
+
+/**
+ * Media Metrics Item
+ *
+ * A mutable item representing an event or record that will be
+ * logged with the Media Metrics service.  For client logging, one should
+ * use the mediametrics::Item.
+ *
+ * The Item is designed for the service as it has getters.
+ */
+class Item final : public mediametrics::BaseItem {
+public:
+
+    class Prop {
+    public:
+        using Elem = std::variant<
+                std::monostate,               // kTypeNone
+                int32_t,                      // kTypeInt32
+                int64_t,                      // kTypeInt64
+                double,                       // kTypeDouble
+                std::string,                  // kTypeCString
+                std::pair<int64_t, int64_t>   // kTypeRate
+                >;
+
+        Prop() = default;
+        Prop(const Prop& other) {
+           *this = other;
+        }
+        Prop& operator=(const Prop& other) {
+            mName = other.mName;
+            mElem = other.mElem;
+            return *this;
+        }
+        Prop(Prop&& other) noexcept {
+            *this = std::move(other);
+        }
+        Prop& operator=(Prop&& other) noexcept {
+            mName = std::move(other.mName);
+            mElem = std::move(other.mElem);
+            return *this;
+        }
+
+        bool operator==(const Prop& other) const {
+            return mName == other.mName && mElem == other.mElem;
+        }
+        bool operator!=(const Prop& other) const {
+            return !(*this == other);
+        }
+
+        void clear() {
+            mName.clear();
+            mElem = std::monostate{};
+        }
+        void clearValue() {
+            mElem = std::monostate{};
+        }
+
+        const char *getName() const {
+            return mName.c_str();
+        }
+
+        void swap(Prop& other) {
+            std::swap(mName, other.mName);
+            std::swap(mElem, other.mElem);
+        }
+
+        void setName(const char *name) {
+            mName = name;
+        }
+
+        bool isNamed(const char *name) const {
+            return mName == name;
+        }
+
+        template <typename T> void visit(T f) const {
+            std::visit(f, mElem);
+        }
+
+        template <typename T> bool get(T *value) const {
+            auto pval = std::get_if<T>(&mElem);
+            if (pval != nullptr) {
+                *value = *pval;
+                return true;
+            }
+            return false;
+        }
+
+        const Elem& get() const {
+            return mElem;
+        }
+
+        template <typename T> void set(const T& value) {
+            mElem = value;
+        }
+
+        template <typename T> void add(const T& value) {
+            auto pval = std::get_if<T>(&mElem);
+            if (pval != nullptr) {
+                *pval += value;
+            } else {
+                mElem = value;
+            }
+        }
+
+        template <> void add(const std::pair<int64_t, int64_t>& value) {
+            auto pval = std::get_if<std::pair<int64_t, int64_t>>(&mElem);
+            if (pval != nullptr) {
+                pval->first += value.first;
+                pval->second += value.second;
+            } else {
+                mElem = value;
+            }
+        }
+
+        status_t writeToParcel(Parcel *parcel) const {
+            return std::visit([this, parcel](auto &value) {
+                    return BaseItem::writeToParcel(mName.c_str(), value, parcel);}, mElem);
+        }
+
+        void toStringBuffer(char *buffer, size_t length) const {
+            return std::visit([this, buffer, length](auto &value) {
+                BaseItem::toStringBuffer(mName.c_str(), value, buffer, length);}, mElem);
+        }
+
+        size_t getByteStringSize() const {
+            return std::visit([this](auto &value) {
+                return BaseItem::sizeOfByteString(mName.c_str(), value);}, mElem);
+        }
+
+        status_t writeToByteString(char **bufferpptr, char *bufferptrmax) const {
+            return std::visit([this, bufferpptr, bufferptrmax](auto &value) {
+                return BaseItem::writeToByteString(mName.c_str(), value, bufferpptr, bufferptrmax);
+            }, mElem);
+        }
+
+        status_t readFromParcel(const Parcel& data);
+
+        status_t readFromByteString(const char **bufferpptr, const char *bufferptrmax);
+
+    private:
+        std::string mName;
+        Elem mElem;
+    };
+
+    // Iteration of props within item
+    class iterator {
+    public:
+        explicit iterator(const std::map<std::string, Prop>::const_iterator &_it) : it(_it) { }
+        iterator &operator++() {
+            ++it;
+            return *this;
+        }
+        bool operator!=(iterator &other) const {
+            return it != other.it;
+        }
+        const Prop &operator*() const {
+            return it->second;
+        }
+
+    private:
+        std::map<std::string, Prop>::const_iterator it;
+    };
+
+    iterator begin() const {
+        return iterator(mProps.cbegin());
+    }
+
+    iterator end() const {
+        return iterator(mProps.cend());
+    }
+
+    // T must be convertible to mKey
+    template <typename T>
+    explicit Item(T key)
+        : mKey(key) { }
+    Item() = default;
+
+    // We enable default copy and move constructors and make this class final
+    // to prevent a derived class; this avoids possible data slicing.
+    Item(const Item& other) = default;
+    Item(Item&& other) = default;
+    Item& operator=(const Item& other) = default;
+    Item& operator=(Item&& other) = default;
+
+    bool operator==(const Item& other) const {
+        return mPid == other.mPid
+            && mUid == other.mUid
+            && mPkgName == other.mPkgName
+            && mPkgVersionCode == other.mPkgVersionCode
+            && mKey == other.mKey
+            && mTimestamp == other.mTimestamp
+            && mProps == other.mProps
+            ;
+    }
+    bool operator!=(const Item& other) const {
+        return !(*this == other);
+    }
+
+    template <typename T>
+    static Item* create(T key) {
+        return new Item(key);
+    }
+    static Item* create() {
+        return new Item();
+    }
+
+        static Item* convert(mediametrics_handle_t);
+        static mediametrics_handle_t convert(Item *);
+
+        // access functions for the class
+        ~Item();
+
+    void clear() {
+        mPid = -1;
+        mUid = -1;
+        mPkgName.clear();
+        mPkgVersionCode = 0;
+        mTimestamp = 0;
+        mKey.clear();
+        mProps.clear();
+    }
+
+    Item *dup() const { return new Item(*this); }
+
+    Item &setKey(const char *key) {
+        mKey = key;
+        return *this;
+    }
+    const std::string& getKey() const { return mKey; }
+
+    // # of properties in the record
+    size_t count() const { return mProps.size(); }
+
+    template<typename S, typename T>
+    Item &set(S key, T value) {
+        findOrAllocateProp(key).set(value);
+        return *this;
+    }
+
+    // set values appropriately
+    Item &setInt32(const char *key, int32_t value) {
+        return set(key, value);
+    }
+    Item &setInt64(const char *key, int64_t value) {
+        return set(key, value);
+    }
+    Item &setDouble(const char *key, double value) {
+        return set(key, value);
+    }
+    Item &setRate(const char *key, int64_t count, int64_t duration) {
+        return set(key, std::make_pair(count, duration));
+    }
+    Item &setCString(const char *key, const char *value) {
+        return set(key, value);
+    }
+
+    // fused get/add/set; if attr wasn't there, it's a simple set.
+    // type-mismatch counts as "wasn't there".
+    template<typename S, typename T>
+    Item &add(S key, T value) {
+        findOrAllocateProp(key).add(value);
+        return *this;
+    }
+
+    Item &addInt32(const char *key, int32_t value) {
+        return add(key, value);
+    }
+    Item &addInt64(const char *key, int64_t value) {
+        return add(key, value);
+    }
+    Item &addDouble(const char *key, double value) {
+        return add(key, value);
+    }
+    Item &addRate(const char *key, int64_t count, int64_t duration) {
+        return add(key, std::make_pair(count, duration));
+    }
+
+    // find & extract values
+    // return indicates whether attr exists (and thus value filled in)
+    // NULL parameter value suppresses storage of value.
+    template<typename S, typename T>
+    bool get(S key, T *value) const {
+        const Prop *prop = findProp(key);
+        return prop != nullptr && prop->get(value);
+    }
+
+    bool getInt32(const char *key, int32_t *value) const {
+        return get(key, value);
+    }
+    bool getInt64(const char *key, int64_t *value) const {
+        return get(key, value);
+    }
+    bool getDouble(const char *key, double *value) const {
+        return get(key, value);
+    }
+    bool getRate(const char *key, int64_t *count, int64_t *duration, double *rate) const {
+        std::pair<int64_t, int64_t> value;
+        if (!get(key, &value)) return false;
+        if (count != nullptr) *count = value.first;
+        if (duration != nullptr) *duration = value.second;
+        if (rate != nullptr) {
+            if (value.second != 0) {
+                *rate = (double)value.first / value.second;  // TODO: isn't INF OK?
+            } else {
+                *rate = 0.;
+            }
+        }
+        return true;
+    }
+    // Caller owns the returned string
+    bool getCString(const char *key, char **value) const {
+        std::string s;
+        if (get(key, &s)) {
+            *value = strdup(s.c_str());
+            return true;
+        }
+        return false;
+    }
+    bool getString(const char *key, std::string *value) const {
+        return get(key, value);
+    }
+
+    const Prop::Elem* get(const char *key) const {
+        const Prop *prop = findProp(key);
+        return prop == nullptr ? nullptr : &prop->get();
+    }
+
+        // Deliver the item to MediaMetrics
+        bool selfrecord();
+
+    // remove indicated attributes and their values
+    // filterNot() could also be called keepOnly()
+    // return value is # attributes removed
+    // XXX: perhaps 'remove' instead of 'filter'
+    // XXX: filterNot would become 'keep'
+    size_t filter(size_t count, const char *attrs[]);
+    size_t filterNot(size_t count, const char *attrs[]);
+    size_t filter(const char *attr) { return filter(1, &attr); }
+
+        // below here are used on server side or to talk to server
+        // clients need not worry about these.
+
+        // timestamp, pid, and uid only used on server side
+        // timestamp is in 'nanoseconds, unix time'
+        Item &setTimestamp(nsecs_t);
+        nsecs_t getTimestamp() const;
+
+        Item &setPid(pid_t);
+        pid_t getPid() const;
+
+        Item &setUid(uid_t);
+        uid_t getUid() const;
+
+        Item &setPkgName(const std::string &pkgName);
+        std::string getPkgName() const { return mPkgName; }
+
+        Item &setPkgVersionCode(int64_t);
+        int64_t getPkgVersionCode() const;
+
+    // our serialization code for binder calls
+    status_t writeToParcel(Parcel *) const;
+    status_t readFromParcel(const Parcel&);
+
+    status_t writeToByteString(char **bufferptr, size_t *length) const;
+    status_t readFromByteString(const char *bufferptr, size_t length);
+
+
+        std::string toString() const;
+        const char *toCString();
+
+    /**
+     * Returns true if the item has a property with a target value.
+     *
+     * If propName is nullptr, hasPropElem() returns false.
+     *
+     * \param propName is the property name.
+     * \param elem is the value to match.  std::monostate matches any.
+     */
+    bool hasPropElem(const char *propName, const Prop::Elem& elem) const {
+        if (propName == nullptr) return false;
+        const Prop::Elem *e = get(propName);
+        return e != nullptr && (std::holds_alternative<std::monostate>(elem) || elem == *e);
+    }
+
+    /**
+     * Returns -2, -1, 0 (success) if the item has a property (wildcard matched) with a
+     * target value.
+     *
+     * The enum RecursiveWildcardCheck designates the meaning of the returned value.
+     *
+     * RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD = -2,
+     * RECURSIVE_WILDCARD_CHECK_NO_MATCH_WILDCARD_FOUND = -1,
+     * RECURSIVE_WILDCARD_CHECK_MATCH_FOUND = 0.
+     *
+     * If url is nullptr, RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD is returned.
+     *
+     * \param url is the full item + property name, which may have wildcards '*'
+     *            denoting an arbitrary sequence of 0 or more characters.
+     * \param elem is the target property value to match. std::monostate matches any.
+     * \return 0 if the property was matched,
+     *         -1 if the property was not matched and a wildcard char was encountered,
+     *         -2 if the property was not matched with no wildcard char encountered.
+     */
+    enum RecursiveWildcardCheck {
+        RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD = -2,
+        RECURSIVE_WILDCARD_CHECK_NO_MATCH_WILDCARD_FOUND = -1,
+        RECURSIVE_WILDCARD_CHECK_MATCH_FOUND = 0,
+    };
+
+    enum RecursiveWildcardCheck recursiveWildcardCheckElem(
+        const char *url, const Prop::Elem& elem) const {
+        if (url == nullptr) return RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD;
+        return recursiveWildcardCheckElem(getKey().c_str(), url, elem);
+    }
+
+private:
+
+    enum RecursiveWildcardCheck recursiveWildcardCheckElem(
+            const char *itemKeyPtr, const char *url, const Prop::Elem& elem) const {
+        for (; *url && *itemKeyPtr; ++url, ++itemKeyPtr) {
+            if (*url != *itemKeyPtr) {
+                if (*url == '*') { // wildcard
+                    ++url;
+                    while (true) {
+                        if (recursiveWildcardCheckElem(itemKeyPtr, url, elem)
+                                == RECURSIVE_WILDCARD_CHECK_MATCH_FOUND) {
+                            return RECURSIVE_WILDCARD_CHECK_MATCH_FOUND;
+                        }
+                        if (*itemKeyPtr == 0) break;
+                        ++itemKeyPtr;
+                    }
+                    return RECURSIVE_WILDCARD_CHECK_NO_MATCH_WILDCARD_FOUND;
+                }
+                return RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD;
+            }
+        }
+        if (itemKeyPtr[0] != 0 || url[0] != '.') {
+            return RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD;
+        }
+        const char *propName = url + 1; // skip the '.'
+        return hasPropElem(propName, elem)
+                ? RECURSIVE_WILDCARD_CHECK_MATCH_FOUND
+                : RECURSIVE_WILDCARD_CHECK_NO_MATCH_NO_WILDCARD;
+    }
+
+    // handle Parcel version 0
+    int32_t writeToParcel0(Parcel *) const;
+    int32_t readFromParcel0(const Parcel&);
+
+    const Prop *findProp(const char *key) const {
+        auto it = mProps.find(key);
+        return it != mProps.end() ? &it->second : nullptr;
+    }
+
+    Prop &findOrAllocateProp(const char *key) {
+        auto it = mProps.find(key);
+        if (it != mProps.end()) return it->second;
+        Prop &prop = mProps[key];
+        prop.setName(key);
+        return prop;
+    }
+
+    // Changes to member variables below require changes to clear().
+    pid_t         mPid = -1;
+    uid_t         mUid = -1;
+    std::string   mPkgName;
+    int64_t       mPkgVersionCode = 0;
+    std::string   mKey;
+    nsecs_t       mTimestamp = 0;
+    std::map<std::string, Prop> mProps;
+};
+
+} // namespace mediametrics
+} // namespace android
+
+#endif // ANDROID_MEDIA_MEDIAMETRICSITEM_H
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
deleted file mode 100644
index dca6bb6..0000000
--- a/media/libmediaplayer2/Android.bp
+++ /dev/null
@@ -1,129 +0,0 @@
-cc_library_headers {
-    name: "libmediaplayer2_headers",
-    vendor_available: true,
-    export_include_dirs: ["include"],
-}
-
-cc_library_static {
-    name: "libmediaplayer2",
-
-    srcs: [
-        "MediaPlayer2AudioOutput.cpp",
-        "mediaplayer2.cpp",
-    ],
-
-    shared_libs: [
-        "libandroid_runtime",
-        "libaudioclient",
-        "libbinder",
-        "libbinder_ndk",
-        "libcutils",
-        "libgui",
-        "liblog",
-        "libmedia_omx",
-        "libui",
-        "libutils",
-
-        "libcrypto",
-        "libmediametrics",
-        "libmediandk",
-        "libmediandk_utils",
-        "libmediautils",
-        "libmemunreachable",
-        "libnativewindow",
-        "libpowermanager",
-        "libstagefright_httplive",
-    ],
-
-    export_shared_lib_headers: [
-        "libaudioclient",
-        "libbinder",
-        "libgui",
-        "libmedia_omx",
-    ],
-
-    header_libs: [
-        "media_plugin_headers",
-    ],
-
-    include_dirs: [
-        "frameworks/base/core/jni",
-    ],
-
-    static_libs: [
-        "libmedia_helper",
-        "libmediaplayer2-protos",
-        "libmedia_player2_util",
-        "libprotobuf-cpp-lite",
-        "libstagefright_foundation_without_imemory",
-        "libstagefright_nuplayer2",
-        "libstagefright_player2",
-        "libstagefright_rtsp",
-        "libstagefright_timedtext2",
-        "libmedia2_jni_core",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
-    ],
-
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-}
-
-cc_library {
-    name: "libmedia2_jni_core",
-
-    srcs: [
-        "JavaVMHelper.cpp",
-        "JAudioTrack.cpp",
-        "JMedia2HTTPService.cpp",
-        "JMedia2HTTPConnection.cpp",
-    ],
-
-    header_libs: [
-        "libbinder_headers",
-        "libnativehelper_header_only",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libutils",
-        "libdl",
-    ],
-
-    include_dirs: [
-        "frameworks/av/media/libmedia/include",
-        "frameworks/base/core/jni",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
-    ],
-
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-
-}
diff --git a/media/libmediaplayer2/JAudioTrack.cpp b/media/libmediaplayer2/JAudioTrack.cpp
deleted file mode 100644
index fab6c64..0000000
--- a/media/libmediaplayer2/JAudioTrack.cpp
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- * 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_TAG "JAudioTrack"
-
-#include "media/JAudioAttributes.h"
-#include "media/JAudioFormat.h"
-#include "mediaplayer2/JAudioTrack.h"
-
-#include <android_media_AudioErrors.h>
-#include <mediaplayer2/JavaVMHelper.h>
-
-namespace android {
-
-// TODO: Store Java class/methodID as a member variable in the class.
-// TODO: Add NULL && Exception checks after every JNI call.
-JAudioTrack::JAudioTrack(                             // < Usages of the arguments are below >
-        uint32_t sampleRate,                          // AudioFormat && bufferSizeInBytes
-        audio_format_t format,                        // AudioFormat && bufferSizeInBytes
-        audio_channel_mask_t channelMask,             // AudioFormat && bufferSizeInBytes
-        callback_t cbf,                               // Offload
-        void* user,                                   // Offload
-        size_t frameCount,                            // bufferSizeInBytes
-        int32_t sessionId,                            // AudioTrack
-        const jobject attributes,                     // AudioAttributes
-        float maxRequiredSpeed) {                     // bufferSizeInBytes
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jclass jAudioTrackCls = env->FindClass("android/media/AudioTrack");
-    mAudioTrackCls = reinterpret_cast<jclass>(env->NewGlobalRef(jAudioTrackCls));
-    env->DeleteLocalRef(jAudioTrackCls);
-
-    maxRequiredSpeed = std::min(std::max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
-
-    int bufferSizeInBytes = 0;
-    if (sampleRate == 0 || frameCount > 0) {
-        // Manually calculate buffer size.
-        bufferSizeInBytes = audio_channel_count_from_out_mask(channelMask)
-                * audio_bytes_per_sample(format) * (frameCount > 0 ? frameCount : 1);
-    } else if (sampleRate > 0) {
-        // Call Java AudioTrack::getMinBufferSize().
-        jmethodID jGetMinBufferSize =
-                env->GetStaticMethodID(mAudioTrackCls, "getMinBufferSize", "(III)I");
-        bufferSizeInBytes = env->CallStaticIntMethod(mAudioTrackCls, jGetMinBufferSize,
-                sampleRate, outChannelMaskFromNative(channelMask), audioFormatFromNative(format));
-    }
-    bufferSizeInBytes = (int) (bufferSizeInBytes * maxRequiredSpeed);
-
-    // Create a Java AudioTrack object through its Builder.
-    jclass jBuilderCls = env->FindClass("android/media/AudioTrack$Builder");
-    jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
-    jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
-
-    {
-        sp<JObjectHolder> audioAttributesObj;
-        if (attributes != NULL) {
-            audioAttributesObj = new JObjectHolder(attributes);
-        } else {
-            audioAttributesObj = new JObjectHolder(
-                    JAudioAttributes::createAudioAttributesObj(env, NULL));
-        }
-        jmethodID jSetAudioAttributes = env->GetMethodID(jBuilderCls, "setAudioAttributes",
-                "(Landroid/media/AudioAttributes;)Landroid/media/AudioTrack$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderObj,
-                jSetAudioAttributes, audioAttributesObj->getJObject());
-    }
-
-    jmethodID jSetAudioFormat = env->GetMethodID(jBuilderCls, "setAudioFormat",
-            "(Landroid/media/AudioFormat;)Landroid/media/AudioTrack$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetAudioFormat,
-            JAudioFormat::createAudioFormatObj(env, sampleRate, format, channelMask));
-
-    jmethodID jSetBufferSizeInBytes = env->GetMethodID(jBuilderCls, "setBufferSizeInBytes",
-            "(I)Landroid/media/AudioTrack$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetBufferSizeInBytes, bufferSizeInBytes);
-
-    // We only use streaming mode of Java AudioTrack.
-    jfieldID jModeStream = env->GetStaticFieldID(mAudioTrackCls, "MODE_STREAM", "I");
-    jint transferMode = env->GetStaticIntField(mAudioTrackCls, jModeStream);
-    jmethodID jSetTransferMode = env->GetMethodID(jBuilderCls, "setTransferMode",
-            "(I)Landroid/media/AudioTrack$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetTransferMode,
-            transferMode /* Java AudioTrack::MODE_STREAM */);
-
-    if (sessionId != 0) {
-        jmethodID jSetSessionId = env->GetMethodID(jBuilderCls, "setSessionId",
-                "(I)Landroid/media/AudioTrack$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetSessionId, sessionId);
-    }
-
-    mFlags = AUDIO_OUTPUT_FLAG_NONE;
-    if (cbf != NULL) {
-        jmethodID jSetOffloadedPlayback = env->GetMethodID(jBuilderCls, "setOffloadedPlayback",
-                "(Z)Landroid/media/AudioTrack$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderObj, jSetOffloadedPlayback, true);
-        mFlags = AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-    }
-
-    jmethodID jBuild = env->GetMethodID(jBuilderCls, "build", "()Landroid/media/AudioTrack;");
-    jobject jAudioTrackObj = env->CallObjectMethod(jBuilderObj, jBuild);
-    mAudioTrackObj = reinterpret_cast<jobject>(env->NewGlobalRef(jAudioTrackObj));
-    env->DeleteLocalRef(jBuilderObj);
-
-    if (cbf != NULL) {
-        // Set offload mode callback
-        jobject jStreamEventCallbackObj = createStreamEventCallback(cbf, user);
-        jobject jExecutorObj = createCallbackExecutor();
-        jmethodID jSetStreamEventCallback = env->GetMethodID(
-                jAudioTrackCls,
-                "setStreamEventCallback",
-                "(Ljava/util/concurrent/Executor;Landroid/media/AudioTrack$StreamEventCallback;)V");
-        env->CallVoidMethod(
-                mAudioTrackObj, jSetStreamEventCallback, jExecutorObj, jStreamEventCallbackObj);
-    }
-}
-
-JAudioTrack::~JAudioTrack() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    env->DeleteGlobalRef(mAudioTrackCls);
-    env->DeleteGlobalRef(mAudioTrackObj);
-}
-
-size_t JAudioTrack::frameCount() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetBufferSizeInFrames = env->GetMethodID(
-            mAudioTrackCls, "getBufferSizeInFrames", "()I");
-    return env->CallIntMethod(mAudioTrackObj, jGetBufferSizeInFrames);
-}
-
-size_t JAudioTrack::channelCount() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetChannelCount = env->GetMethodID(mAudioTrackCls, "getChannelCount", "()I");
-    return env->CallIntMethod(mAudioTrackObj, jGetChannelCount);
-}
-
-uint32_t JAudioTrack::latency() {
-    // TODO: Currently hard-coded as returning zero.
-    return 0;
-}
-
-status_t JAudioTrack::getPosition(uint32_t *position) {
-    if (position == NULL) {
-        return BAD_VALUE;
-    }
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetPlaybackHeadPosition = env->GetMethodID(
-            mAudioTrackCls, "getPlaybackHeadPosition", "()I");
-    *position = env->CallIntMethod(mAudioTrackObj, jGetPlaybackHeadPosition);
-
-    return NO_ERROR;
-}
-
-status_t JAudioTrack::getTimestamp(AudioTimestamp& timestamp) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jclass jAudioTimeStampCls = env->FindClass("android/media/AudioTimestamp");
-    jobject jAudioTimeStampObj = env->AllocObject(jAudioTimeStampCls);
-
-    jfieldID jFramePosition = env->GetFieldID(jAudioTimeStampCls, "framePosition", "J");
-    jfieldID jNanoTime = env->GetFieldID(jAudioTimeStampCls, "nanoTime", "J");
-
-    jmethodID jGetTimestamp = env->GetMethodID(mAudioTrackCls,
-            "getTimestamp", "(Landroid/media/AudioTimestamp;)Z");
-    bool success = env->CallBooleanMethod(mAudioTrackObj, jGetTimestamp, jAudioTimeStampObj);
-
-    if (!success) {
-        return NO_INIT;
-    }
-
-    long long framePosition = env->GetLongField(jAudioTimeStampObj, jFramePosition);
-    long long nanoTime = env->GetLongField(jAudioTimeStampObj, jNanoTime);
-
-    struct timespec ts;
-    const long long secondToNano = 1000000000LL; // 1E9
-    ts.tv_sec = nanoTime / secondToNano;
-    ts.tv_nsec = nanoTime % secondToNano;
-    timestamp.mTime = ts;
-    timestamp.mPosition = (uint32_t) framePosition;
-
-    return NO_ERROR;
-}
-
-status_t JAudioTrack::getTimestamp(ExtendedTimestamp *timestamp __unused) {
-    // TODO: Implement this after appropriate Java AudioTrack method is available.
-    return NO_ERROR;
-}
-
-status_t JAudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate) {
-    // TODO: existing native AudioTrack returns INVALID_OPERATION on offload/direct/fast tracks.
-    // Should we do the same thing?
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jclass jPlaybackParamsCls = env->FindClass("android/media/PlaybackParams");
-    jmethodID jPlaybackParamsCtor = env->GetMethodID(jPlaybackParamsCls, "<init>", "()V");
-    jobject jPlaybackParamsObj = env->NewObject(jPlaybackParamsCls, jPlaybackParamsCtor);
-
-    jmethodID jSetAudioFallbackMode = env->GetMethodID(
-            jPlaybackParamsCls, "setAudioFallbackMode", "(I)Landroid/media/PlaybackParams;");
-    jPlaybackParamsObj = env->CallObjectMethod(
-            jPlaybackParamsObj, jSetAudioFallbackMode, playbackRate.mFallbackMode);
-
-    jmethodID jSetAudioStretchMode = env->GetMethodID(
-                jPlaybackParamsCls, "setAudioStretchMode", "(I)Landroid/media/PlaybackParams;");
-    jPlaybackParamsObj = env->CallObjectMethod(
-            jPlaybackParamsObj, jSetAudioStretchMode, playbackRate.mStretchMode);
-
-    jmethodID jSetPitch = env->GetMethodID(
-            jPlaybackParamsCls, "setPitch", "(F)Landroid/media/PlaybackParams;");
-    jPlaybackParamsObj = env->CallObjectMethod(jPlaybackParamsObj, jSetPitch, playbackRate.mPitch);
-
-    jmethodID jSetSpeed = env->GetMethodID(
-            jPlaybackParamsCls, "setSpeed", "(F)Landroid/media/PlaybackParams;");
-    jPlaybackParamsObj = env->CallObjectMethod(jPlaybackParamsObj, jSetSpeed, playbackRate.mSpeed);
-
-
-    // Set this Java PlaybackParams object into Java AudioTrack.
-    jmethodID jSetPlaybackParams = env->GetMethodID(
-            mAudioTrackCls, "setPlaybackParams", "(Landroid/media/PlaybackParams;)V");
-    env->CallVoidMethod(mAudioTrackObj, jSetPlaybackParams, jPlaybackParamsObj);
-    // TODO: Should we catch the Java IllegalArgumentException?
-
-    return NO_ERROR;
-}
-
-const AudioPlaybackRate JAudioTrack::getPlaybackRate() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jmethodID jGetPlaybackParams = env->GetMethodID(
-            mAudioTrackCls, "getPlaybackParams", "()Landroid/media/PlaybackParams;");
-    jobject jPlaybackParamsObj = env->CallObjectMethod(mAudioTrackObj, jGetPlaybackParams);
-
-    AudioPlaybackRate playbackRate;
-    jclass jPlaybackParamsCls = env->FindClass("android/media/PlaybackParams");
-
-    jmethodID jGetAudioFallbackMode = env->GetMethodID(
-            jPlaybackParamsCls, "getAudioFallbackMode", "()I");
-    // TODO: Should we enable passing AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT?
-    //       The enum is internal only, so it is not defined in PlaybackParmas.java.
-    // TODO: Is this right way to convert an int to an enum?
-    playbackRate.mFallbackMode = static_cast<AudioTimestretchFallbackMode>(
-            env->CallIntMethod(jPlaybackParamsObj, jGetAudioFallbackMode));
-
-    jmethodID jGetAudioStretchMode = env->GetMethodID(
-            jPlaybackParamsCls, "getAudioStretchMode", "()I");
-    playbackRate.mStretchMode = static_cast<AudioTimestretchStretchMode>(
-            env->CallIntMethod(jPlaybackParamsObj, jGetAudioStretchMode));
-
-    jmethodID jGetPitch = env->GetMethodID(jPlaybackParamsCls, "getPitch", "()F");
-    playbackRate.mPitch = env->CallFloatMethod(jPlaybackParamsObj, jGetPitch);
-
-    jmethodID jGetSpeed = env->GetMethodID(jPlaybackParamsCls, "getSpeed", "()F");
-    playbackRate.mSpeed = env->CallFloatMethod(jPlaybackParamsObj, jGetSpeed);
-
-    return playbackRate;
-}
-
-media::VolumeShaper::Status JAudioTrack::applyVolumeShaper(
-        const sp<media::VolumeShaper::Configuration>& configuration,
-        const sp<media::VolumeShaper::Operation>& operation) {
-
-    jobject jConfigurationObj = createVolumeShaperConfigurationObj(configuration);
-    jobject jOperationObj = createVolumeShaperOperationObj(operation);
-
-    if (jConfigurationObj == NULL || jOperationObj == NULL) {
-        return media::VolumeShaper::Status(BAD_VALUE);
-    }
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jmethodID jCreateVolumeShaper = env->GetMethodID(mAudioTrackCls, "createVolumeShaper",
-            "(Landroid/media/VolumeShaper$Configuration;)Landroid/media/VolumeShaper;");
-    jobject jVolumeShaperObj = env->CallObjectMethod(
-            mAudioTrackObj, jCreateVolumeShaper, jConfigurationObj);
-
-    jclass jVolumeShaperCls = env->FindClass("android/media/VolumeShaper");
-    jmethodID jApply = env->GetMethodID(jVolumeShaperCls, "apply",
-            "(Landroid/media/VolumeShaper$Operation;)V");
-    env->CallVoidMethod(jVolumeShaperObj, jApply, jOperationObj);
-
-    return media::VolumeShaper::Status(NO_ERROR);
-}
-
-status_t JAudioTrack::setAuxEffectSendLevel(float level) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jSetAuxEffectSendLevel = env->GetMethodID(
-            mAudioTrackCls, "setAuxEffectSendLevel", "(F)I");
-    int result = env->CallIntMethod(mAudioTrackObj, jSetAuxEffectSendLevel, level);
-    return javaToNativeStatus(result);
-}
-
-status_t JAudioTrack::attachAuxEffect(int effectId) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jAttachAuxEffect = env->GetMethodID(mAudioTrackCls, "attachAuxEffect", "(I)I");
-    int result = env->CallIntMethod(mAudioTrackObj, jAttachAuxEffect, effectId);
-    return javaToNativeStatus(result);
-}
-
-status_t JAudioTrack::setVolume(float left, float right) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    // TODO: Java setStereoVolume is deprecated. Do we really need this method?
-    jmethodID jSetStereoVolume = env->GetMethodID(mAudioTrackCls, "setStereoVolume", "(FF)I");
-    int result = env->CallIntMethod(mAudioTrackObj, jSetStereoVolume, left, right);
-    return javaToNativeStatus(result);
-}
-
-status_t JAudioTrack::setVolume(float volume) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jSetVolume = env->GetMethodID(mAudioTrackCls, "setVolume", "(F)I");
-    int result = env->CallIntMethod(mAudioTrackObj, jSetVolume, volume);
-    return javaToNativeStatus(result);
-}
-
-status_t JAudioTrack::start() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jPlay = env->GetMethodID(mAudioTrackCls, "play", "()V");
-    // TODO: Should we catch the Java IllegalStateException from play()?
-    env->CallVoidMethod(mAudioTrackObj, jPlay);
-    return NO_ERROR;
-}
-
-ssize_t JAudioTrack::write(const void* buffer, size_t size, bool blocking) {
-    if (buffer == NULL) {
-        return BAD_VALUE;
-    }
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jbyteArray jAudioData = env->NewByteArray(size);
-    env->SetByteArrayRegion(jAudioData, 0, size, (jbyte *) buffer);
-
-    jclass jByteBufferCls = env->FindClass("java/nio/ByteBuffer");
-    jmethodID jWrap = env->GetStaticMethodID(jByteBufferCls, "wrap", "([B)Ljava/nio/ByteBuffer;");
-    jobject jByteBufferObj = env->CallStaticObjectMethod(jByteBufferCls, jWrap, jAudioData);
-
-    int writeMode = 0;
-    if (blocking) {
-        jfieldID jWriteBlocking = env->GetStaticFieldID(mAudioTrackCls, "WRITE_BLOCKING", "I");
-        writeMode = env->GetStaticIntField(mAudioTrackCls, jWriteBlocking);
-    } else {
-        jfieldID jWriteNonBlocking = env->GetStaticFieldID(
-                mAudioTrackCls, "WRITE_NON_BLOCKING", "I");
-        writeMode = env->GetStaticIntField(mAudioTrackCls, jWriteNonBlocking);
-    }
-
-    jmethodID jWrite = env->GetMethodID(mAudioTrackCls, "write", "(Ljava/nio/ByteBuffer;II)I");
-    int result = env->CallIntMethod(mAudioTrackObj, jWrite, jByteBufferObj, size, writeMode);
-
-    if (result >= 0) {
-        return result;
-    } else {
-        return javaToNativeStatus(result);
-    }
-}
-
-void JAudioTrack::stop() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jStop = env->GetMethodID(mAudioTrackCls, "stop", "()V");
-    env->CallVoidMethod(mAudioTrackObj, jStop);
-    // TODO: Should we catch IllegalStateException?
-}
-
-// TODO: Is the right implementation?
-bool JAudioTrack::stopped() const {
-    return !isPlaying();
-}
-
-void JAudioTrack::flush() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jFlush = env->GetMethodID(mAudioTrackCls, "flush", "()V");
-    env->CallVoidMethod(mAudioTrackObj, jFlush);
-}
-
-void JAudioTrack::pause() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jPause = env->GetMethodID(mAudioTrackCls, "pause", "()V");
-    env->CallVoidMethod(mAudioTrackObj, jPause);
-    // TODO: Should we catch IllegalStateException?
-}
-
-bool JAudioTrack::isPlaying() const {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetPlayState = env->GetMethodID(mAudioTrackCls, "getPlayState", "()I");
-    int currentPlayState = env->CallIntMethod(mAudioTrackObj, jGetPlayState);
-
-    // TODO: In Java AudioTrack, there is no STOPPING state.
-    // This means while stopping, isPlaying() will return different value in two class.
-    //  - in existing native AudioTrack: true
-    //  - in JAudioTrack: false
-    // If not okay, also modify the implementation of stopped().
-    jfieldID jPlayStatePlaying = env->GetStaticFieldID(mAudioTrackCls, "PLAYSTATE_PLAYING", "I");
-    int statePlaying = env->GetStaticIntField(mAudioTrackCls, jPlayStatePlaying);
-    return currentPlayState == statePlaying;
-}
-
-uint32_t JAudioTrack::getSampleRate() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetSampleRate = env->GetMethodID(mAudioTrackCls, "getSampleRate", "()I");
-    return env->CallIntMethod(mAudioTrackObj, jGetSampleRate);
-}
-
-status_t JAudioTrack::getBufferDurationInUs(int64_t *duration) {
-    if (duration == nullptr) {
-        return BAD_VALUE;
-    }
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetBufferSizeInFrames = env->GetMethodID(
-            mAudioTrackCls, "getBufferSizeInFrames", "()I");
-    int bufferSizeInFrames = env->CallIntMethod(mAudioTrackObj, jGetBufferSizeInFrames);
-
-    const double secondToMicro = 1000000LL; // 1E6
-    int sampleRate = JAudioTrack::getSampleRate();
-    float speed = JAudioTrack::getPlaybackRate().mSpeed;
-
-    *duration = (int64_t) (bufferSizeInFrames * secondToMicro / (sampleRate * speed));
-    return NO_ERROR;
-}
-
-audio_format_t JAudioTrack::format() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetAudioFormat = env->GetMethodID(mAudioTrackCls, "getAudioFormat", "()I");
-    int javaFormat = env->CallIntMethod(mAudioTrackObj, jGetAudioFormat);
-    return audioFormatToNative(javaFormat);
-}
-
-size_t JAudioTrack::frameSize() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetFormat = env->GetMethodID(mAudioTrackCls,
-            "getFormat", "()Landroid/media/AudioFormat;");
-    jobject jAudioFormatObj = env->CallObjectMethod(mAudioTrackObj, jGetFormat);
-
-    jclass jAudioFormatCls = env->FindClass("android/media/AudioFormat");
-    jmethodID jGetFrameSizeInBytes = env->GetMethodID(
-            jAudioFormatCls, "getFrameSizeInBytes", "()I");
-    jint javaFrameSizeInBytes = env->CallIntMethod(jAudioFormatObj, jGetFrameSizeInBytes);
-
-    return (size_t)javaFrameSizeInBytes;
-}
-
-status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const
-{
-    String8 result;
-
-    result.append(" JAudioTrack::dump\n");
-
-    // TODO: Remove logs that includes unavailable information from below.
-//    result.appendFormat("  status(%d), state(%d), session Id(%d), flags(%#x)\n",
-//                        mStatus, mState, mSessionId, mFlags);
-//    result.appendFormat("  format(%#x), channel mask(%#x), channel count(%u)\n",
-//                  format(), mChannelMask, channelCount());
-//    result.appendFormat("  sample rate(%u), original sample rate(%u), speed(%f)\n",
-//            getSampleRate(), mOriginalSampleRate, mPlaybackRate.mSpeed);
-//    result.appendFormat("  frame count(%zu), req. frame count(%zu)\n",
-//                  frameCount(), mReqFrameCount);
-//    result.appendFormat("  notif. frame count(%u), req. notif. frame count(%u),"
-//            " req. notif. per buff(%u)\n",
-//             mNotificationFramesAct, mNotificationFramesReq, mNotificationsPerBufferReq);
-//    result.appendFormat("  latency (%d), selected device Id(%d), routed device Id(%d)\n",
-//                        latency(), mSelectedDeviceId, getRoutedDeviceId());
-//    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());
-    return NO_ERROR;
-}
-
-jobject JAudioTrack::getRoutedDevice() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetRoutedDevice = env->GetMethodID(mAudioTrackCls, "getRoutedDevice",
-            "()Landroid/media/AudioDeviceInfo;");
-    return env->CallObjectMethod(mAudioTrackObj, jGetRoutedDevice);
-}
-
-int32_t JAudioTrack::getAudioSessionId() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetAudioSessionId = env->GetMethodID(mAudioTrackCls, "getAudioSessionId", "()I");
-    jint sessionId = env->CallIntMethod(mAudioTrackObj, jGetAudioSessionId);
-    return sessionId;
-}
-
-status_t JAudioTrack::setPreferredDevice(jobject device) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jSetPreferredDeviceId = env->GetMethodID(mAudioTrackCls, "setPreferredDevice",
-            "(Landroid/media/AudioDeviceInfo;)Z");
-    jboolean result = env->CallBooleanMethod(mAudioTrackObj, jSetPreferredDeviceId, device);
-    return result == true ? NO_ERROR : BAD_VALUE;
-}
-
-audio_stream_type_t JAudioTrack::getAudioStreamType() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jGetAudioAttributes = env->GetMethodID(mAudioTrackCls, "getAudioAttributes",
-            "()Landroid/media/AudioAttributes;");
-    jobject jAudioAttributes = env->CallObjectMethod(mAudioTrackObj, jGetAudioAttributes);
-    jclass jAudioAttributesCls = env->FindClass("android/media/AudioAttributes");
-    jmethodID jGetVolumeControlStream = env->GetMethodID(jAudioAttributesCls,
-            "getVolumeControlStream", "()I");
-    int javaAudioStreamType = env->CallIntMethod(jAudioAttributes, jGetVolumeControlStream);
-    return (audio_stream_type_t)javaAudioStreamType;
-}
-
-status_t JAudioTrack::pendingDuration(int32_t *msec) {
-    if (msec == nullptr) {
-        return BAD_VALUE;
-    }
-
-    bool isPurePcmData = audio_is_linear_pcm(format()) && (getFlags() & AUDIO_FLAG_HW_AV_SYNC) == 0;
-    if (!isPurePcmData) {
-        return INVALID_OPERATION;
-    }
-
-    // TODO: Need to know the difference btw. client and server time.
-    // If getTimestamp(ExtendedTimestamp) is ready, and un-comment below and modify appropriately.
-    // (copied from AudioTrack.cpp)
-
-//    ExtendedTimestamp ets;
-//    ExtendedTimestamp::LOCATION location = ExtendedTimestamp::LOCATION_SERVER;
-//    if (getTimestamp_l(&ets) == OK && ets.mTimeNs[location] > 0) {
-//        int64_t diff = ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT]
-//                - ets.mPosition[location];
-//        if (diff < 0) {
-//            *msec = 0;
-//        } else {
-//            // ms is the playback time by frames
-//            int64_t ms = (int64_t)((double)diff * 1000 /
-//                    ((double)mSampleRate * mPlaybackRate.mSpeed));
-//            // clockdiff is the timestamp age (negative)
-//            int64_t clockdiff = (mState != STATE_ACTIVE) ? 0 :
-//                    ets.mTimeNs[location]
-//                    + ets.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_MONOTONIC]
-//                    - systemTime(SYSTEM_TIME_MONOTONIC);
-//
-//            //ALOGV("ms: %lld  clockdiff: %lld", (long long)ms, (long long)clockdiff);
-//            static const int NANOS_PER_MILLIS = 1000000;
-//            *msec = (int32_t)(ms + clockdiff / NANOS_PER_MILLIS);
-//        }
-//        return NO_ERROR;
-//    }
-
-    return NO_ERROR;
-}
-
-status_t JAudioTrack::addAudioDeviceCallback(jobject listener, jobject handler) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jAddOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls,
-            "addOnRoutingChangedListener",
-            "(Landroid/media/AudioRouting$OnRoutingChangedListener;Landroid/os/Handler;)V");
-    env->CallVoidMethod(mAudioTrackObj, jAddOnRoutingChangedListener, listener, handler);
-    return NO_ERROR;
-}
-
-status_t JAudioTrack::removeAudioDeviceCallback(jobject listener) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jmethodID jRemoveOnRoutingChangedListener = env->GetMethodID(mAudioTrackCls,
-            "removeOnRoutingChangedListener",
-            "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V");
-    env->CallVoidMethod(mAudioTrackObj, jRemoveOnRoutingChangedListener, listener);
-    return NO_ERROR;
-}
-
-void JAudioTrack::registerRoutingDelegates(
-        Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& routingDelegates) {
-    for (auto it = routingDelegates.begin(); it != routingDelegates.end(); it++) {
-        addAudioDeviceCallback(it->second->getJObject(), getHandler(it->second->getJObject()));
-    }
-}
-
-/////////////////////////////////////////////////////////////
-///                Static methods begin                   ///
-/////////////////////////////////////////////////////////////
-jobject JAudioTrack::getListener(const jobject routingDelegateObj) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate");
-    jmethodID jGetListener = env->GetMethodID(jRoutingDelegateCls,
-            "getListener", "()Landroid/media/AudioRouting$OnRoutingChangedListener;");
-    return env->CallObjectMethod(routingDelegateObj, jGetListener);
-}
-
-jobject JAudioTrack::getHandler(const jobject routingDelegateObj) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jclass jRoutingDelegateCls = env->FindClass("android/media/RoutingDelegate");
-    jmethodID jGetHandler = env->GetMethodID(jRoutingDelegateCls,
-        "getHandler", "()Landroid/os/Handler;");
-    return env->CallObjectMethod(routingDelegateObj, jGetHandler);
-}
-
-jobject JAudioTrack::findByKey(
-        Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    for (auto it = mp.begin(); it != mp.end(); it++) {
-        if (env->IsSameObject(it->first->getJObject(), key)) {
-            return it->second->getJObject();
-        }
-    }
-    return nullptr;
-}
-
-void JAudioTrack::eraseByKey(
-        Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    for (auto it = mp.begin(); it != mp.end(); it++) {
-        if (env->IsSameObject(it->first->getJObject(), key)) {
-            mp.erase(it);
-            return;
-        }
-    }
-}
-
-/////////////////////////////////////////////////////////////
-///                Private method begins                  ///
-/////////////////////////////////////////////////////////////
-
-jobject JAudioTrack::createVolumeShaperConfigurationObj(
-        const sp<media::VolumeShaper::Configuration>& config) {
-
-    // TODO: Java VolumeShaper's setId() / setOptionFlags() are hidden.
-    if (config == NULL || config->getType() == media::VolumeShaper::Configuration::TYPE_ID) {
-        return NULL;
-    }
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    // Referenced "android_media_VolumeShaper.h".
-    jfloatArray xarray = nullptr;
-    jfloatArray yarray = nullptr;
-    if (config->getType() == media::VolumeShaper::Configuration::TYPE_SCALE) {
-        // convert curve arrays
-        xarray = env->NewFloatArray(config->size());
-        yarray = env->NewFloatArray(config->size());
-        float * const x = env->GetFloatArrayElements(xarray, nullptr /* isCopy */);
-        float * const y = env->GetFloatArrayElements(yarray, nullptr /* isCopy */);
-        float *xptr = x, *yptr = y;
-        for (const auto &pt : *config.get()) {
-            *xptr++ = pt.first;
-            *yptr++ = pt.second;
-        }
-        env->ReleaseFloatArrayElements(xarray, x, 0 /* mode */);
-        env->ReleaseFloatArrayElements(yarray, y, 0 /* mode */);
-    }
-
-    jclass jBuilderCls = env->FindClass("android/media/VolumeShaper$Configuration$Builder");
-    jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
-    jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
-
-    jmethodID jSetDuration = env->GetMethodID(jBuilderCls, "setDuration",
-            "(L)Landroid/media/VolumeShaper$Configuration$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderCls, jSetDuration, (jlong) config->getDurationMs());
-
-    jmethodID jSetInterpolatorType = env->GetMethodID(jBuilderCls, "setInterpolatorType",
-            "(I)Landroid/media/VolumeShaper$Configuration$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderCls, jSetInterpolatorType,
-            config->getInterpolatorType());
-
-    jmethodID jSetCurve = env->GetMethodID(jBuilderCls, "setCurve",
-            "([F[F)Landroid/media/VolumeShaper$Configuration$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderCls, jSetCurve, xarray, yarray);
-
-    jmethodID jBuild = env->GetMethodID(jBuilderCls, "build",
-            "()Landroid/media/VolumeShaper$Configuration;");
-    return env->CallObjectMethod(jBuilderObj, jBuild);
-}
-
-jobject JAudioTrack::createVolumeShaperOperationObj(
-        const sp<media::VolumeShaper::Operation>& operation) {
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    jclass jBuilderCls = env->FindClass("android/media/VolumeShaper$Operation$Builder");
-    jmethodID jBuilderCtor = env->GetMethodID(jBuilderCls, "<init>", "()V");
-    jobject jBuilderObj = env->NewObject(jBuilderCls, jBuilderCtor);
-
-    // Set XOffset
-    jmethodID jSetXOffset = env->GetMethodID(jBuilderCls, "setXOffset",
-            "(F)Landroid/media/VolumeShaper$Operation$Builder;");
-    jBuilderObj = env->CallObjectMethod(jBuilderCls, jSetXOffset, operation->getXOffset());
-
-    int32_t flags = operation->getFlags();
-
-    if (operation->getReplaceId() >= 0) {
-        jmethodID jReplace = env->GetMethodID(jBuilderCls, "replace",
-                "(IB)Landroid/media/VolumeShaper$Operation$Builder;");
-        bool join = (flags | media::VolumeShaper::Operation::FLAG_JOIN) != 0;
-        jBuilderObj = env->CallObjectMethod(jBuilderCls, jReplace, operation->getReplaceId(), join);
-    }
-
-    if (flags | media::VolumeShaper::Operation::FLAG_REVERSE) {
-        jmethodID jReverse = env->GetMethodID(jBuilderCls, "reverse",
-                "()Landroid/media/VolumeShaper$Operation$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderCls, jReverse);
-    }
-
-    // TODO: VolumeShaper Javadoc says "Do not call terminate() directly". Can we call this?
-    if (flags | media::VolumeShaper::Operation::FLAG_TERMINATE) {
-        jmethodID jTerminate = env->GetMethodID(jBuilderCls, "terminate",
-                "()Landroid/media/VolumeShaper$Operation$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderCls, jTerminate);
-    }
-
-    if (flags | media::VolumeShaper::Operation::FLAG_DELAY) {
-        jmethodID jDefer = env->GetMethodID(jBuilderCls, "defer",
-                "()Landroid/media/VolumeShaper$Operation$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderCls, jDefer);
-    }
-
-    if (flags | media::VolumeShaper::Operation::FLAG_CREATE_IF_NECESSARY) {
-        jmethodID jCreateIfNeeded = env->GetMethodID(jBuilderCls, "createIfNeeded",
-                "()Landroid/media/VolumeShaper$Operation$Builder;");
-        jBuilderObj = env->CallObjectMethod(jBuilderCls, jCreateIfNeeded);
-    }
-
-    // TODO: Handle error case (can it be NULL?)
-    jmethodID jBuild = env->GetMethodID(jBuilderCls, "build",
-            "()Landroid/media/VolumeShaper$Operation;");
-    return env->CallObjectMethod(jBuilderObj, jBuild);
-}
-
-jobject JAudioTrack::createStreamEventCallback(callback_t cbf, void* user) {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jclass jCallbackCls = env->FindClass("android/media/MediaPlayer2$StreamEventCallback");
-    jmethodID jCallbackCtor = env->GetMethodID(jCallbackCls, "<init>", "(JJJ)V");
-    jobject jCallbackObj = env->NewObject(jCallbackCls, jCallbackCtor, this, cbf, user);
-    return jCallbackObj;
-}
-
-jobject JAudioTrack::createCallbackExecutor() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jclass jExecutorsCls = env->FindClass("java/util/concurrent/Executors");
-    jmethodID jNewSingleThreadExecutor = env->GetStaticMethodID(jExecutorsCls,
-            "newSingleThreadExecutor", "()Ljava/util/concurrent/ExecutorService;");
-    jobject jSingleThreadExecutorObj =
-            env->CallStaticObjectMethod(jExecutorsCls, jNewSingleThreadExecutor);
-    return jSingleThreadExecutorObj;
-}
-
-status_t JAudioTrack::javaToNativeStatus(int javaStatus) {
-    switch (javaStatus) {
-    case AUDIO_JAVA_SUCCESS:
-        return NO_ERROR;
-    case AUDIO_JAVA_BAD_VALUE:
-        return BAD_VALUE;
-    case AUDIO_JAVA_INVALID_OPERATION:
-        return INVALID_OPERATION;
-    case AUDIO_JAVA_PERMISSION_DENIED:
-        return PERMISSION_DENIED;
-    case AUDIO_JAVA_NO_INIT:
-        return NO_INIT;
-    case AUDIO_JAVA_WOULD_BLOCK:
-        return WOULD_BLOCK;
-    case AUDIO_JAVA_DEAD_OBJECT:
-        return DEAD_OBJECT;
-    default:
-        return UNKNOWN_ERROR;
-    }
-}
-
-} // namespace android
diff --git a/media/libmediaplayer2/JMedia2HTTPConnection.cpp b/media/libmediaplayer2/JMedia2HTTPConnection.cpp
deleted file mode 100644
index e1baa10..0000000
--- a/media/libmediaplayer2/JMedia2HTTPConnection.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2017, 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 "JMedia2HTTPConnection"
-#include <utils/Log.h>
-
-#include <mediaplayer2/JavaVMHelper.h>
-#include <mediaplayer2/JMedia2HTTPConnection.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <nativehelper/scoped_local_ref.h>
-
-#include "log/log.h"
-#include "jni.h"
-
-namespace android {
-
-static const size_t kBufferSize = 32768;
-
-JMedia2HTTPConnection::JMedia2HTTPConnection(JNIEnv *env, jobject thiz) {
-    mMedia2HTTPConnectionObj = env->NewGlobalRef(thiz);
-    CHECK(mMedia2HTTPConnectionObj != NULL);
-
-    ScopedLocalRef<jclass> media2HTTPConnectionClass(
-            env, env->GetObjectClass(mMedia2HTTPConnectionObj));
-    CHECK(media2HTTPConnectionClass.get() != NULL);
-
-    mConnectMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "connect",
-            "(Ljava/lang/String;Ljava/lang/String;)Z");
-    CHECK(mConnectMethod != NULL);
-
-    mDisconnectMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "disconnect",
-            "()V");
-    CHECK(mDisconnectMethod != NULL);
-
-    mReadAtMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "readAt",
-            "(J[BI)I");
-    CHECK(mReadAtMethod != NULL);
-
-    mGetSizeMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "getSize",
-            "()J");
-    CHECK(mGetSizeMethod != NULL);
-
-    mGetMIMETypeMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "getMIMEType",
-            "()Ljava/lang/String;");
-    CHECK(mGetMIMETypeMethod != NULL);
-
-    mGetUriMethod = env->GetMethodID(
-            media2HTTPConnectionClass.get(),
-            "getUri",
-            "()Ljava/lang/String;");
-    CHECK(mGetUriMethod != NULL);
-
-    ScopedLocalRef<jbyteArray> tmp(
-        env, env->NewByteArray(kBufferSize));
-    mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
-    CHECK(mByteArrayObj != NULL);
-}
-
-JMedia2HTTPConnection::~JMedia2HTTPConnection() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    env->DeleteGlobalRef(mMedia2HTTPConnectionObj);
-    env->DeleteGlobalRef(mByteArrayObj);
-}
-
-bool JMedia2HTTPConnection::connect(
-        const char *uri, const KeyedVector<String8, String8> *headers) {
-    String8 tmp("");
-    if (headers != NULL) {
-        for (size_t i = 0; i < headers->size(); ++i) {
-            tmp.append(headers->keyAt(i));
-            tmp.append(String8(": "));
-            tmp.append(headers->valueAt(i));
-            tmp.append(String8("\r\n"));
-        }
-    }
-
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    jstring juri = env->NewStringUTF(uri);
-    jstring jheaders = env->NewStringUTF(tmp.string());
-
-    jboolean ret =
-        env->CallBooleanMethod(mMedia2HTTPConnectionObj, mConnectMethod, juri, jheaders);
-
-    env->DeleteLocalRef(juri);
-    env->DeleteLocalRef(jheaders);
-
-    return (bool)ret;
-}
-
-void JMedia2HTTPConnection::disconnect() {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    env->CallVoidMethod(mMedia2HTTPConnectionObj, mDisconnectMethod);
-}
-
-ssize_t JMedia2HTTPConnection::readAt(off64_t offset, void *data, size_t size) {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-
-    if (size > kBufferSize) {
-        size = kBufferSize;
-    }
-
-    jint n = env->CallIntMethod(
-            mMedia2HTTPConnectionObj, mReadAtMethod, (jlong)offset, mByteArrayObj, (jint)size);
-
-    if (n > 0) {
-        env->GetByteArrayRegion(
-                mByteArrayObj,
-                0,
-                n,
-                (jbyte *)data);
-    }
-
-    return n;
-}
-
-off64_t JMedia2HTTPConnection::getSize() {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    return (off64_t)(env->CallLongMethod(mMedia2HTTPConnectionObj, mGetSizeMethod));
-}
-
-status_t JMedia2HTTPConnection::getMIMEType(String8 *mimeType) {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    jstring jmime = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetMIMETypeMethod);
-    jboolean flag = env->ExceptionCheck();
-    if (flag) {
-        env->ExceptionClear();
-        return UNKNOWN_ERROR;
-    }
-
-    const char *str = env->GetStringUTFChars(jmime, 0);
-    if (str != NULL) {
-        *mimeType = String8(str);
-    } else {
-        *mimeType = "application/octet-stream";
-    }
-    env->ReleaseStringUTFChars(jmime, str);
-    return OK;
-}
-
-status_t JMedia2HTTPConnection::getUri(String8 *uri) {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    jstring juri = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetUriMethod);
-    jboolean flag = env->ExceptionCheck();
-    if (flag) {
-        env->ExceptionClear();
-        return UNKNOWN_ERROR;
-    }
-
-    const char *str = env->GetStringUTFChars(juri, 0);
-    *uri = String8(str);
-    env->ReleaseStringUTFChars(juri, str);
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/JMedia2HTTPService.cpp b/media/libmediaplayer2/JMedia2HTTPService.cpp
deleted file mode 100644
index 20e3573..0000000
--- a/media/libmediaplayer2/JMedia2HTTPService.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017, 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 "JMedia2HTTPService"
-#include <utils/Log.h>
-
-#include <jni.h>
-
-#include <mediaplayer2/JavaVMHelper.h>
-#include <mediaplayer2/JMedia2HTTPService.h>
-#include <mediaplayer2/JMedia2HTTPConnection.h>
-#include <media/stagefright/foundation/ADebug.h>
-
-#include <nativehelper/scoped_local_ref.h>
-
-namespace android {
-
-JMedia2HTTPService::JMedia2HTTPService(JNIEnv *env, jobject thiz) {
-    mMedia2HTTPServiceObj = env->NewGlobalRef(thiz);
-    CHECK(mMedia2HTTPServiceObj != NULL);
-
-    ScopedLocalRef<jclass> media2HTTPServiceClass(env, env->GetObjectClass(mMedia2HTTPServiceObj));
-    CHECK(media2HTTPServiceClass.get() != NULL);
-
-    mMakeHTTPConnectionMethod = env->GetMethodID(
-            media2HTTPServiceClass.get(),
-            "makeHTTPConnection",
-            "()Landroid/media/Media2HTTPConnection;");
-    CHECK(mMakeHTTPConnectionMethod != NULL);
-}
-
-JMedia2HTTPService::~JMedia2HTTPService() {
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    env->DeleteGlobalRef(mMedia2HTTPServiceObj);
-}
-
-sp<MediaHTTPConnection> JMedia2HTTPService::makeHTTPConnection() {
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    jobject media2HTTPConnectionObj =
-        env->CallObjectMethod(mMedia2HTTPServiceObj, mMakeHTTPConnectionMethod);
-
-    return new JMedia2HTTPConnection(env, media2HTTPConnectionObj);
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/JavaVMHelper.cpp b/media/libmediaplayer2/JavaVMHelper.cpp
deleted file mode 100644
index 8d03ed0..0000000
--- a/media/libmediaplayer2/JavaVMHelper.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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_TAG "JavaVMHelper"
-
-#include "mediaplayer2/JavaVMHelper.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <utils/threads.h>
-
-#include <stdlib.h>
-
-namespace android {
-
-// static
-std::atomic<JavaVM *> JavaVMHelper::sJavaVM(NULL);
-
-/*
- * Makes the current thread visible to the VM.
- *
- * The JNIEnv pointer returned is only valid for the current thread, and
- * thus must be tucked into thread-local storage.
- */
-static int javaAttachThread(const char* threadName, JNIEnv** pEnv) {
-    JavaVMAttachArgs args;
-    JavaVM* vm;
-    jint result;
-
-    vm = JavaVMHelper::getJavaVM();
-    if (vm == NULL) {
-        return JNI_ERR;
-    }
-
-    args.version = JNI_VERSION_1_4;
-    args.name = (char*) threadName;
-    args.group = NULL;
-
-    result = vm->AttachCurrentThread(pEnv, (void*) &args);
-    if (result != JNI_OK) {
-        ALOGI("NOTE: attach of thread '%s' failed\n", threadName);
-    }
-
-    return result;
-}
-
-/*
- * Detach the current thread from the set visible to the VM.
- */
-static int javaDetachThread(void) {
-    JavaVM* vm;
-    jint result;
-
-    vm = JavaVMHelper::getJavaVM();
-    if (vm == NULL) {
-        return JNI_ERR;
-    }
-
-    result = vm->DetachCurrentThread();
-    if (result != JNI_OK) {
-        ALOGE("ERROR: thread detach failed\n");
-    }
-    return result;
-}
-
-/*
- * When starting a native thread that will be visible from the VM, we
- * bounce through this to get the right attach/detach action.
- * Note that this function calls free(args)
- */
-static int javaThreadShell(void* args) {
-    void* start = ((void**)args)[0];
-    void* userData = ((void **)args)[1];
-    char* name = (char*) ((void **)args)[2];        // we own this storage
-    free(args);
-    JNIEnv* env;
-    int result;
-
-    /* hook us into the VM */
-    if (javaAttachThread(name, &env) != JNI_OK) {
-        return -1;
-    }
-
-    /* start the thread running */
-    result = (*(android_thread_func_t)start)(userData);
-
-    /* unhook us */
-    javaDetachThread();
-    free(name);
-
-    return result;
-}
-
-/*
- * This is invoked from androidCreateThreadEtc() via the callback
- * set with androidSetCreateThreadFunc().
- *
- * We need to create the new thread in such a way that it gets hooked
- * into the VM before it really starts executing.
- */
-static int javaCreateThreadEtc(
-        android_thread_func_t entryFunction,
-        void* userData,
-        const char* threadName,
-        int32_t threadPriority,
-        size_t threadStackSize,
-        android_thread_id_t* threadId) {
-    void** args = (void**) malloc(3 * sizeof(void*));   // javaThreadShell must free
-    int result;
-
-    LOG_ALWAYS_FATAL_IF(threadName == nullptr, "threadName not provided to javaCreateThreadEtc");
-
-    args[0] = (void*) entryFunction;
-    args[1] = userData;
-    args[2] = (void*) strdup(threadName);   // javaThreadShell must free
-
-    result = androidCreateRawThreadEtc(javaThreadShell, args,
-        threadName, threadPriority, threadStackSize, threadId);
-    return result;
-}
-
-// static
-JNIEnv *JavaVMHelper::getJNIEnv() {
-    JNIEnv *env;
-    JavaVM *vm = sJavaVM.load();
-    CHECK(vm != NULL);
-
-    if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
-        return NULL;
-    }
-
-    return env;
-}
-
-//static
-JavaVM *JavaVMHelper::getJavaVM() {
-    return sJavaVM.load();
-}
-
-// static
-void JavaVMHelper::setJavaVM(JavaVM *vm) {
-    sJavaVM.store(vm);
-
-    // Ensure that Thread(/*canCallJava*/ true) in libutils is attached to the VM.
-    // This is supposed to be done by runtime, but when libutils is used with linker
-    // namespace, CreateThreadFunc should be initialized separately within the namespace.
-    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
deleted file mode 100644
index b4fa0c1..0000000
--- a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
-**
-** 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 "MediaPlayer2AudioOutput"
-#include <mediaplayer2/MediaPlayer2AudioOutput.h>
-
-#include <cutils/properties.h> // for property_get
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-
-namespace {
-
-const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
-
-} // anonymous namespace
-
-namespace android {
-
-// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
-/* static */ int MediaPlayer2AudioOutput::mMinBufferCount = 4;
-/* static */ bool MediaPlayer2AudioOutput::mIsOnEmulator = false;
-
-status_t MediaPlayer2AudioOutput::dump(int fd, const Vector<String16>& args) const {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    result.append(" MediaPlayer2AudioOutput\n");
-    snprintf(buffer, 255, "  volume(%f)\n", mVolume);
-    result.append(buffer);
-    snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
-            mMsecsPerFrame, (mJAudioTrack != nullptr) ? mJAudioTrack->latency() : -1);
-    result.append(buffer);
-    snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
-            mAuxEffectId, mSendLevel);
-    result.append(buffer);
-
-    ::write(fd, result.string(), result.size());
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->dump(fd, args);
-    }
-    return NO_ERROR;
-}
-
-MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(int32_t sessionId, uid_t uid, int pid,
-        const jobject attributes)
-    : mCallback(nullptr),
-      mCallbackCookie(nullptr),
-      mCallbackData(nullptr),
-      mVolume(1.0),
-      mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
-      mSampleRateHz(0),
-      mMsecsPerFrame(0),
-      mFrameSize(0),
-      mSessionId(sessionId),
-      mUid(uid),
-      mPid(pid),
-      mSendLevel(0.0),
-      mAuxEffectId(0),
-      mFlags(AUDIO_OUTPUT_FLAG_NONE) {
-    ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
-
-    if (attributes != nullptr) {
-        mAttributes = new JObjectHolder(attributes);
-    }
-
-    setMinBufferCount();
-    mRoutingDelegates.clear();
-}
-
-MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
-    close();
-    delete mCallbackData;
-}
-
-//static
-void MediaPlayer2AudioOutput::setMinBufferCount() {
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("ro.kernel.qemu", value, 0)) {
-        mIsOnEmulator = true;
-        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
-    }
-}
-
-// static
-bool MediaPlayer2AudioOutput::isOnEmulator() {
-    setMinBufferCount();  // benign race wrt other threads
-    return mIsOnEmulator;
-}
-
-// static
-int MediaPlayer2AudioOutput::getMinBufferCount() {
-    setMinBufferCount();  // benign race wrt other threads
-    return mMinBufferCount;
-}
-
-ssize_t MediaPlayer2AudioOutput::bufferSize() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mJAudioTrack->frameCount() * mFrameSize;
-}
-
-ssize_t MediaPlayer2AudioOutput::frameCount() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mJAudioTrack->frameCount();
-}
-
-ssize_t MediaPlayer2AudioOutput::channelCount() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mJAudioTrack->channelCount();
-}
-
-ssize_t MediaPlayer2AudioOutput::frameSize() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mFrameSize;
-}
-
-uint32_t MediaPlayer2AudioOutput::latency () const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return 0;
-    }
-    return mJAudioTrack->latency();
-}
-
-float MediaPlayer2AudioOutput::msecsPerFrame() const {
-    Mutex::Autolock lock(mLock);
-    return mMsecsPerFrame;
-}
-
-status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mJAudioTrack->getPosition(position);
-}
-
-status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    return mJAudioTrack->getTimestamp(ts);
-}
-
-// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
-// as it acquires locks and may query the audio driver.
-//
-// Some calls could conceivably retrieve extrapolated data instead of
-// accessing getTimestamp() or getPosition() every time a data buffer with
-// a media time is received.
-//
-// Calculate duration of played samples if played at normal rate (i.e., 1.0).
-int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr || mSampleRateHz == 0) {
-        return 0;
-    }
-
-    uint32_t numFramesPlayed;
-    int64_t numFramesPlayedAtUs;
-    AudioTimestamp ts;
-
-    status_t res = mJAudioTrack->getTimestamp(ts);
-
-    if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
-        numFramesPlayed = ts.mPosition;
-        numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
-        //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
-    } else {                         // case 2: transitory state on start of a new track
-                                     // case 3: transitory at new track or audio fast tracks.
-        numFramesPlayed = 0;
-        numFramesPlayedAtUs = nowUs;
-        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
-        //        numFramesPlayed, (long long)numFramesPlayedAtUs);
-    }
-
-    // CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
-    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
-    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
-            + nowUs - numFramesPlayedAtUs;
-    if (durationUs < 0) {
-        // Occurs when numFramesPlayed position is very small and the following:
-        // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
-        //     numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
-        // (2) In case 3, using getPosition and adding mAudioSink->latency() to
-        //     numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
-        //
-        // Both of these are transitory conditions.
-        ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
-        durationUs = 0;
-    }
-    ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
-            (long long)durationUs, (long long)nowUs,
-            numFramesPlayed, (long long)numFramesPlayedAtUs);
-    return durationUs;
-}
-
-status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return NO_INIT;
-    }
-    ExtendedTimestamp ets;
-    status_t status = mJAudioTrack->getTimestamp(&ets);
-    if (status == OK || status == WOULD_BLOCK) {
-        *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
-    }
-    return status;
-}
-
-void MediaPlayer2AudioOutput::setAudioAttributes(const jobject attributes) {
-    Mutex::Autolock lock(mLock);
-    mAttributes = (attributes == nullptr) ? nullptr : new JObjectHolder(attributes);
-}
-
-audio_stream_type_t MediaPlayer2AudioOutput::getAudioStreamType() const {
-    ALOGV("getAudioStreamType");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == nullptr) {
-        return AUDIO_STREAM_DEFAULT;
-    }
-    return mJAudioTrack->getAudioStreamType();
-}
-
-void MediaPlayer2AudioOutput::close_l() {
-    mJAudioTrack.clear();
-}
-
-status_t MediaPlayer2AudioOutput::open(
-        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-        audio_format_t format,
-        AudioCallback cb, void *cookie,
-        audio_output_flags_t flags,
-        const audio_offload_info_t *offloadInfo,
-        uint32_t suggestedFrameCount) {
-    ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
-                format, mSessionId, flags);
-
-    // offloading is only supported in callback mode for now.
-    // offloadInfo must be present if offload flag is set
-    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
-            ((cb == nullptr) || (offloadInfo == nullptr))) {
-        return BAD_VALUE;
-    }
-
-    // compute frame count for the AudioTrack internal buffer
-    const size_t frameCount =
-           ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
-
-    if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
-        channelMask = audio_channel_out_mask_from_count(channelCount);
-        if (0 == channelMask) {
-            ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
-            return NO_INIT;
-        }
-    }
-
-    Mutex::Autolock lock(mLock);
-    mCallback = cb;
-    mCallbackCookie = cookie;
-
-    sp<JAudioTrack> jT;
-    CallbackData *newcbd = nullptr;
-
-    ALOGV("creating new JAudioTrack");
-
-    if (mCallback != nullptr) {
-        newcbd = new CallbackData(this);
-        jT = new JAudioTrack(
-                 sampleRate,
-                 format,
-                 channelMask,
-                 CallbackWrapper,
-                 newcbd,
-                 frameCount,
-                 mSessionId,
-                 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
-                 1.0f);  // default value for maxRequiredSpeed
-    } else {
-        // TODO: Due to buffer memory concerns, we use a max target playback speed
-        // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
-        // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
-        const float targetSpeed =
-                std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
-        ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
-                "track target speed:%f clamped from playback speed:%f",
-                targetSpeed, mPlaybackRate.mSpeed);
-        jT = new JAudioTrack(
-                 sampleRate,
-                 format,
-                 channelMask,
-                 nullptr,
-                 nullptr,
-                 frameCount,
-                 mSessionId,
-                 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
-                 targetSpeed);
-    }
-
-    if (jT == 0) {
-        ALOGE("Unable to create audio track");
-        delete newcbd;
-        // t goes out of scope, so reference count drops to zero
-        return NO_INIT;
-    }
-
-    CHECK((jT != nullptr) && ((mCallback == nullptr) || (newcbd != nullptr)));
-
-    mCallbackData = newcbd;
-    ALOGV("setVolume");
-    jT->setVolume(mVolume);
-
-    mSampleRateHz = sampleRate;
-    mFlags = flags;
-    mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
-    mFrameSize = jT->frameSize();
-    mJAudioTrack = jT;
-
-    return updateTrack_l();
-}
-
-status_t MediaPlayer2AudioOutput::updateTrack_l() {
-    if (mJAudioTrack == nullptr) {
-        return NO_ERROR;
-    }
-
-    status_t res = NO_ERROR;
-    // Note some output devices may give us a direct track even though we don't specify it.
-    // Example: Line application b/17459982.
-    if ((mJAudioTrack->getFlags()
-            & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
-        res = mJAudioTrack->setPlaybackRate(mPlaybackRate);
-        if (res == NO_ERROR) {
-            mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
-            res = mJAudioTrack->attachAuxEffect(mAuxEffectId);
-        }
-    }
-    if (mPreferredDevice != nullptr) {
-        mJAudioTrack->setPreferredDevice(mPreferredDevice->getJObject());
-    }
-
-    mJAudioTrack->registerRoutingDelegates(mRoutingDelegates);
-
-    ALOGV("updateTrack_l() DONE status %d", res);
-    return res;
-}
-
-status_t MediaPlayer2AudioOutput::start() {
-    ALOGV("start");
-    Mutex::Autolock lock(mLock);
-    if (mCallbackData != nullptr) {
-        mCallbackData->endTrackSwitch();
-    }
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->setVolume(mVolume);
-        mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
-        status_t status = mJAudioTrack->start();
-        return status;
-    }
-    return NO_INIT;
-}
-
-ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
-    Mutex::Autolock lock(mLock);
-    LOG_ALWAYS_FATAL_IF(mCallback != nullptr, "Don't call write if supplying a callback.");
-
-    //ALOGV("write(%p, %u)", buffer, size);
-    if (mJAudioTrack != nullptr) {
-        return mJAudioTrack->write(buffer, size, blocking);
-    }
-    return NO_INIT;
-}
-
-void MediaPlayer2AudioOutput::stop() {
-    ALOGV("stop");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->stop();
-    }
-}
-
-void MediaPlayer2AudioOutput::flush() {
-    ALOGV("flush");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->flush();
-    }
-}
-
-void MediaPlayer2AudioOutput::pause() {
-    ALOGV("pause");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->pause();
-    }
-}
-
-void MediaPlayer2AudioOutput::close() {
-    ALOGV("close");
-    sp<JAudioTrack> track;
-    {
-        Mutex::Autolock lock(mLock);
-        track = mJAudioTrack;
-        close_l(); // clears mJAudioTrack
-    }
-    // destruction of the track occurs outside of mutex.
-}
-
-void MediaPlayer2AudioOutput::setVolume(float volume) {
-    ALOGV("setVolume(%f)", volume);
-    Mutex::Autolock lock(mLock);
-    mVolume = volume;
-    if (mJAudioTrack != nullptr) {
-        mJAudioTrack->setVolume(volume);
-    }
-}
-
-status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
-    ALOGV("setPlaybackRate(%f %f %d %d)",
-                rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == 0) {
-        // remember rate so that we can set it when the track is opened
-        mPlaybackRate = rate;
-        return OK;
-    }
-    status_t res = mJAudioTrack->setPlaybackRate(rate);
-    if (res != NO_ERROR) {
-        return res;
-    }
-    // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
-    CHECK_GT(rate.mSpeed, 0.f);
-    mPlaybackRate = rate;
-    if (mSampleRateHz != 0) {
-        mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
-    }
-    return res;
-}
-
-status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
-    ALOGV("getPlaybackRate");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == 0) {
-        return NO_INIT;
-    }
-    *rate = mJAudioTrack->getPlaybackRate();
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
-    ALOGV("setAuxEffectSendLevel(%f)", level);
-    Mutex::Autolock lock(mLock);
-    mSendLevel = level;
-    if (mJAudioTrack != nullptr) {
-        return mJAudioTrack->setAuxEffectSendLevel(level);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
-    ALOGV("attachAuxEffect(%d)", effectId);
-    Mutex::Autolock lock(mLock);
-    mAuxEffectId = effectId;
-    if (mJAudioTrack != nullptr) {
-        return mJAudioTrack->attachAuxEffect(effectId);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2AudioOutput::setPreferredDevice(jobject device) {
-    ALOGV("setPreferredDevice");
-    Mutex::Autolock lock(mLock);
-    status_t ret = NO_ERROR;
-    if (mJAudioTrack != nullptr) {
-        ret = mJAudioTrack->setPreferredDevice(device);
-    }
-    if (ret == NO_ERROR) {
-        mPreferredDevice = new JObjectHolder(device);
-    }
-    return ret;
-}
-
-jobject MediaPlayer2AudioOutput::getRoutedDevice() {
-    ALOGV("getRoutedDevice");
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack != nullptr) {
-        return mJAudioTrack->getRoutedDevice();
-    }
-    return nullptr;
-}
-
-status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
-    ALOGV("addAudioDeviceCallback");
-    Mutex::Autolock lock(mLock);
-    jobject listener = JAudioTrack::getListener(jRoutingDelegate);
-    if (JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
-        sp<JObjectHolder> listenerHolder = new JObjectHolder(listener);
-        jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
-        sp<JObjectHolder> routingDelegateHolder = new JObjectHolder(jRoutingDelegate);
-
-        mRoutingDelegates.push_back(std::pair<sp<JObjectHolder>, sp<JObjectHolder>>(
-                listenerHolder, routingDelegateHolder));
-
-        if (mJAudioTrack != nullptr) {
-            return mJAudioTrack->addAudioDeviceCallback(
-                    routingDelegateHolder->getJObject(), handler);
-        }
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2AudioOutput::removeAudioDeviceCallback(jobject listener) {
-    ALOGV("removeAudioDeviceCallback");
-    Mutex::Autolock lock(mLock);
-    jobject routingDelegate = nullptr;
-    if ((routingDelegate = JAudioTrack::findByKey(mRoutingDelegates, listener)) != nullptr) {
-        if (mJAudioTrack != nullptr) {
-            mJAudioTrack->removeAudioDeviceCallback(routingDelegate);
-        }
-        JAudioTrack::eraseByKey(mRoutingDelegates, listener);
-    }
-    return NO_ERROR;
-}
-
-// static
-void MediaPlayer2AudioOutput::CallbackWrapper(
-        int event, void *cookie, void *info) {
-    //ALOGV("callbackwrapper");
-    CallbackData *data = (CallbackData*)cookie;
-    // lock to ensure we aren't caught in the middle of a track switch.
-    data->lock();
-    MediaPlayer2AudioOutput *me = data->getOutput();
-    JAudioTrack::Buffer *buffer = (JAudioTrack::Buffer *)info;
-    if (me == nullptr) {
-        // no output set, likely because the track was scheduled to be reused
-        // by another player, but the format turned out to be incompatible.
-        data->unlock();
-        if (buffer != nullptr) {
-            buffer->mSize = 0;
-        }
-        return;
-    }
-
-    switch(event) {
-    case JAudioTrack::EVENT_MORE_DATA: {
-        size_t actualSize = (*me->mCallback)(
-                me, buffer->mData, buffer->mSize, me->mCallbackCookie,
-                CB_EVENT_FILL_BUFFER);
-
-        // Log when no data is returned from the callback.
-        // (1) We may have no data (especially with network streaming sources).
-        // (2) We may have reached the EOS and the audio track is not stopped yet.
-        // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
-        // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
-        //
-        // This is a benign busy-wait, with the next data request generated 10 ms or more later;
-        // nevertheless for power reasons, we don't want to see too many of these.
-
-        ALOGV_IF(actualSize == 0 && buffer->mSize > 0, "callbackwrapper: empty buffer returned");
-
-        buffer->mSize = actualSize;
-        } break;
-
-    case JAudioTrack::EVENT_STREAM_END:
-        // currently only occurs for offloaded callbacks
-        ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
-        (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_STREAM_END);
-        break;
-
-    case JAudioTrack::EVENT_NEW_IAUDIOTRACK :
-        ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
-        (*me->mCallback)(me,  nullptr /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
-        break;
-
-    case JAudioTrack::EVENT_UNDERRUN:
-        // This occurs when there is no data available, typically
-        // when there is a failure to supply data to the AudioTrack.  It can also
-        // occur in non-offloaded mode when the audio device comes out of standby.
-        //
-        // If an AudioTrack underruns it outputs silence. Since this happens suddenly
-        // it may sound like an audible pop or glitch.
-        //
-        // The underrun event is sent once per track underrun; the condition is reset
-        // when more data is sent to the AudioTrack.
-        ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
-        break;
-
-    default:
-        ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
-    }
-
-    data->unlock();
-}
-
-int32_t MediaPlayer2AudioOutput::getSessionId() const {
-    Mutex::Autolock lock(mLock);
-    return mSessionId;
-}
-
-void MediaPlayer2AudioOutput::setSessionId(const int32_t sessionId) {
-    Mutex::Autolock lock(mLock);
-    mSessionId = sessionId;
-}
-
-uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == 0) {
-        return 0;
-    }
-    return mJAudioTrack->getSampleRate();
-}
-
-int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const {
-    Mutex::Autolock lock(mLock);
-    if (mJAudioTrack == 0) {
-        return 0;
-    }
-    int64_t duration;
-    if (mJAudioTrack->getBufferDurationInUs(&duration) != OK) {
-        return 0;
-    }
-    return duration;
-}
-
-} // namespace android
diff --git a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h b/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
deleted file mode 100644
index 2ed4632..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/JAudioTrack.h
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * 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 ANDROID_JAUDIOTRACK_H
-#define ANDROID_JAUDIOTRACK_H
-
-#include <utility>
-#include <jni.h>
-#include <media/AudioResamplerPublic.h>
-#include <media/AudioSystem.h>
-#include <media/VolumeShaper.h>
-#include <system/audio.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <mediaplayer2/JObjectHolder.h>
-#include <media/AudioTimestamp.h>   // It has dependency on audio.h/Errors.h, but doesn't
-                                    // include them in it. Therefore it is included here at last.
-
-namespace android {
-
-class JAudioTrack : public RefBase {
-public:
-
-    /* Events used by AudioTrack callback function (callback_t).
-     * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*.
-     */
-    enum event_type {
-        EVENT_MORE_DATA = 0,        // Request to write more data to buffer.
-        EVENT_UNDERRUN = 1,         // Buffer underrun occurred. This will not occur for
-                                    // static tracks.
-        EVENT_NEW_IAUDIOTRACK = 6,  // IAudioTrack was re-created, either due to re-routing and
-                                    // voluntary invalidation by mediaserver, or mediaserver crash.
-        EVENT_STREAM_END = 7,       // Sent after all the buffers queued in AF and HW are played
-                                    // back (after stop is called) for an offloaded track.
-    };
-
-    class Buffer
-    {
-    public:
-        size_t      mSize;        // input/output in bytes.
-        void*       mData;        // pointer to the audio data.
-    };
-
-    /* As a convenience, if a callback is supplied, a handler thread
-     * is automatically created with the appropriate priority. This thread
-     * invokes the callback when a new buffer becomes available or various conditions occur.
-     *
-     * Parameters:
-     *
-     * event:   type of event notified (see enum AudioTrack::event_type).
-     * user:    Pointer to context for use by the callback receiver.
-     * info:    Pointer to optional parameter according to event type:
-     *          - EVENT_MORE_DATA: pointer to JAudioTrack::Buffer struct. The callback must not
-     *            write more bytes than indicated by 'size' field and update 'size' if fewer bytes
-     *            are written.
-     *          - EVENT_NEW_IAUDIOTRACK: unused.
-     *          - EVENT_STREAM_END: unused.
-     */
-
-    typedef void (*callback_t)(int event, void* user, void *info);
-
-    /* Creates an JAudioTrack object for non-offload mode.
-     * Once created, the track needs to be started before it can be used.
-     * Unspecified values are set to appropriate default values.
-     *
-     * Parameters:
-     *
-     * streamType:         Select the type of audio stream this track is attached to
-     *                     (e.g. AUDIO_STREAM_MUSIC).
-     * sampleRate:         Data source sampling rate in Hz.  Zero means to use the sink sample rate.
-     *                     A non-zero value must be specified if AUDIO_OUTPUT_FLAG_DIRECT is set.
-     *                     0 will not work with current policy implementation for direct output
-     *                     selection where an exact match is needed for sampling rate.
-     *                     (TODO: Check direct output after flags can be used in Java AudioTrack.)
-     * format:             Audio format. For mixed tracks, any PCM format supported by server is OK.
-     *                     For direct and offloaded tracks, the possible format(s) depends on the
-     *                     output sink.
-     *                     (TODO: How can we check whether a format is supported?)
-     * channelMask:        Channel mask, such that audio_is_output_channel(channelMask) is true.
-     * cbf:                Callback function. If not null, this function is called periodically
-     *                     to provide new data and inform of marker, position updates, etc.
-     * user:               Context for use by the callback receiver.
-     * frameCount:         Minimum size of track PCM buffer in frames. This defines the
-     *                     application's contribution to the latency of the track.
-     *                     The actual size selected by the JAudioTrack could be larger if the
-     *                     requested size is not compatible with current audio HAL configuration.
-     *                     Zero means to use a default value.
-     * sessionId:          Specific session ID, or zero to use default.
-     * pAttributes:        If not NULL, supersedes streamType for use case selection.
-     * maxRequiredSpeed:   For PCM tracks, this creates an appropriate buffer size that will allow
-     *                     maxRequiredSpeed playback. Values less than 1.0f and greater than
-     *                     AUDIO_TIMESTRETCH_SPEED_MAX will be clamped.  For non-PCM tracks
-     *                     and direct or offloaded tracks, this parameter is ignored.
-     *                     (TODO: Handle this after offload / direct track is supported.)
-     *
-     * TODO: Revive removed arguments after offload mode is supported.
-     */
-    JAudioTrack(uint32_t sampleRate,
-                audio_format_t format,
-                audio_channel_mask_t channelMask,
-                callback_t cbf,
-                void* user,
-                size_t frameCount = 0,
-                int32_t sessionId  = AUDIO_SESSION_ALLOCATE,
-                const jobject pAttributes = NULL,
-                float maxRequiredSpeed = 1.0f);
-
-    /*
-       // Q. May be used in AudioTrack.setPreferredDevice(AudioDeviceInfo)?
-       audio_port_handle_t selectedDeviceId,
-
-       // TODO: No place to use these values.
-       int32_t notificationFrames,
-       const audio_offload_info_t *offloadInfo,
-    */
-
-    virtual ~JAudioTrack();
-
-    size_t frameCount();
-    size_t channelCount();
-
-    /* Returns this track's estimated latency in milliseconds.
-     * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
-     * and audio hardware driver.
-     */
-    uint32_t latency();
-
-    /* Return the total number of frames played since playback start.
-     * The counter will wrap (overflow) periodically, e.g. every ~27 hours at 44.1 kHz.
-     * It is reset to zero by flush(), reload(), and stop().
-     *
-     * Parameters:
-     *
-     * position: Address where to return play head position.
-     *
-     * Returned status (from utils/Errors.h) can be:
-     *  - NO_ERROR: successful operation
-     *  - BAD_VALUE: position is NULL
-     */
-    status_t getPosition(uint32_t *position);
-
-    // TODO: Does this comment apply same to Java AudioTrack::getTimestamp?
-    // Changed the return type from status_t to bool, since Java AudioTrack::getTimestamp returns
-    // boolean. Will Java getTimestampWithStatus() be public?
-    /* Poll for a timestamp on demand.
-     * Use if EVENT_NEW_TIMESTAMP is not delivered often enough for your needs,
-     * or if you need to get the most recent timestamp outside of the event callback handler.
-     * Caution: calling this method too often may be inefficient;
-     * if you need a high resolution mapping between frame position and presentation time,
-     * consider implementing that at application level, based on the low resolution timestamps.
-     * Returns NO_ERROR if timestamp is valid.
-     *         NO_INIT if finds error, and timestamp parameter will be undefined on return.
-     */
-    status_t getTimestamp(AudioTimestamp& timestamp);
-
-    // TODO: This doc is just copied from AudioTrack.h. Revise it after implemenation.
-    /* Return the extended timestamp, with additional timebase info and improved drain behavior.
-     *
-     * This is similar to the AudioTrack.java API:
-     * getTimestamp(@NonNull AudioTimestamp timestamp, @AudioTimestamp.Timebase int timebase)
-     *
-     * Some differences between this method and the getTimestamp(AudioTimestamp& timestamp) method
-     *
-     *   1. stop() by itself does not reset the frame position.
-     *      A following start() resets the frame position to 0.
-     *   2. flush() by itself does not reset the frame position.
-     *      The frame position advances by the number of frames flushed,
-     *      when the first frame after flush reaches the audio sink.
-     *   3. BOOTTIME clock offsets are provided to help synchronize with
-     *      non-audio streams, e.g. sensor data.
-     *   4. Position is returned with 64 bits of resolution.
-     *
-     * Parameters:
-     *  timestamp: A pointer to the caller allocated ExtendedTimestamp.
-     *
-     * Returns NO_ERROR    on success; timestamp is filled with valid data.
-     *         BAD_VALUE   if timestamp is NULL.
-     *         WOULD_BLOCK if called immediately after start() when the number
-     *                     of frames consumed is less than the
-     *                     overall hardware latency to physical output. In WOULD_BLOCK cases,
-     *                     one might poll again, or use getPosition(), or use 0 position and
-     *                     current time for the timestamp.
-     *                     If WOULD_BLOCK is returned, the timestamp is still
-     *                     modified with the LOCATION_CLIENT portion filled.
-     *         DEAD_OBJECT if AudioFlinger dies or the output device changes and
-     *                     the track cannot be automatically restored.
-     *                     The application needs to recreate the AudioTrack
-     *                     because the audio device changed or AudioFlinger died.
-     *                     This typically occurs for direct or offloaded tracks
-     *                     or if mDoNotReconnect is true.
-     *         INVALID_OPERATION  if called on a offloaded or direct track.
-     *                     Use getTimestamp(AudioTimestamp& timestamp) instead.
-     */
-    status_t getTimestamp(ExtendedTimestamp *timestamp);
-
-    /* Set source playback rate for timestretch
-     * 1.0 is normal speed: < 1.0 is slower, > 1.0 is faster
-     * 1.0 is normal pitch: < 1.0 is lower pitch, > 1.0 is higher pitch
-     *
-     * AUDIO_TIMESTRETCH_SPEED_MIN <= speed <= AUDIO_TIMESTRETCH_SPEED_MAX
-     * AUDIO_TIMESTRETCH_PITCH_MIN <= pitch <= AUDIO_TIMESTRETCH_PITCH_MAX
-     *
-     * Speed increases the playback rate of media, but does not alter pitch.
-     * Pitch increases the "tonal frequency" of media, but does not affect the playback rate.
-     */
-    status_t setPlaybackRate(const AudioPlaybackRate &playbackRate);
-
-    /* Return current playback rate */
-    const AudioPlaybackRate getPlaybackRate();
-
-    /* Sets the volume shaper object */
-    media::VolumeShaper::Status applyVolumeShaper(
-            const sp<media::VolumeShaper::Configuration>& configuration,
-            const sp<media::VolumeShaper::Operation>& operation);
-
-    /* Set the send level for this track. An auxiliary effect should be attached
-     * to the track with attachEffect(). Level must be >= 0.0 and <= 1.0.
-     */
-    status_t setAuxEffectSendLevel(float level);
-
-    /* Attach track auxiliary output to specified effect. Use effectId = 0
-     * to detach track from effect.
-     *
-     * Parameters:
-     *
-     * effectId: effectId obtained from AudioEffect::id().
-     *
-     * Returned status (from utils/Errors.h) can be:
-     *  - NO_ERROR: successful operation
-     *  - INVALID_OPERATION: The effect is not an auxiliary effect.
-     *  - BAD_VALUE: The specified effect ID is invalid.
-     */
-    status_t attachAuxEffect(int effectId);
-
-    /* Set volume for this track, mostly used for games' sound effects
-     * left and right volumes. Levels must be >= 0.0 and <= 1.0.
-     * This is the older API.  New applications should use setVolume(float) when possible.
-     */
-    status_t setVolume(float left, float right);
-
-    /* Set volume for all channels. This is the preferred API for new applications,
-     * especially for multi-channel content.
-     */
-    status_t setVolume(float volume);
-
-    // TODO: Does this comment equally apply to the Java AudioTrack::play()?
-    /* After it's created the track is not active. Call start() to
-     * make it active. If set, the callback will start being called.
-     * If the track was previously paused, volume is ramped up over the first mix buffer.
-     */
-    status_t start();
-
-    // TODO: Does this comment still applies? It seems not. (obtainBuffer, AudioFlinger, ...)
-    /* As a convenience we provide a write() interface to the audio buffer.
-     * Input parameter 'size' is in byte units.
-     * This is implemented on top of obtainBuffer/releaseBuffer. For best
-     * performance use callbacks. Returns actual number of bytes written >= 0,
-     * or one of the following negative status codes:
-     *      INVALID_OPERATION   AudioTrack is configured for static buffer or streaming mode
-     *      BAD_VALUE           size is invalid
-     *      WOULD_BLOCK         when obtainBuffer() returns same, or
-     *                          AudioTrack was stopped during the write
-     *      DEAD_OBJECT         when AudioFlinger dies or the output device changes and
-     *                          the track cannot be automatically restored.
-     *                          The application needs to recreate the AudioTrack
-     *                          because the audio device changed or AudioFlinger died.
-     *                          This typically occurs for direct or offload tracks
-     *                          or if mDoNotReconnect is true.
-     *      or any other error code returned by IAudioTrack::start() or restoreTrack_l().
-     * Default behavior is to only return when all data has been transferred. Set 'blocking' to
-     * false for the method to return immediately without waiting to try multiple times to write
-     * the full content of the buffer.
-     */
-    ssize_t write(const void* buffer, size_t size, bool blocking = true);
-
-    // TODO: Does this comment equally apply to the Java AudioTrack::stop()?
-    /* Stop a track.
-     * In static buffer mode, the track is stopped immediately.
-     * In streaming mode, the callback will cease being called.  Note that obtainBuffer() still
-     * works and will fill up buffers until the pool is exhausted, and then will return WOULD_BLOCK.
-     * In streaming mode the stop does not occur immediately: any data remaining in the buffer
-     * is first drained, mixed, and output, and only then is the track marked as stopped.
-     */
-    void stop();
-    bool stopped() const;
-
-    // TODO: Does this comment equally apply to the Java AudioTrack::flush()?
-    /* Flush a stopped or paused track. All previously buffered data is discarded immediately.
-     * This has the effect of draining the buffers without mixing or output.
-     * Flush is intended for streaming mode, for example before switching to non-contiguous content.
-     * This function is a no-op if the track is not stopped or paused, or uses a static buffer.
-     */
-    void flush();
-
-    // TODO: Does this comment equally apply to the Java AudioTrack::pause()?
-    // At least we are not using obtainBuffer.
-    /* Pause a track. After pause, the callback will cease being called and
-     * obtainBuffer returns WOULD_BLOCK. Note that obtainBuffer() still works
-     * and will fill up buffers until the pool is exhausted.
-     * Volume is ramped down over the next mix buffer following the pause request,
-     * and then the track is marked as paused. It can be resumed with ramp up by start().
-     */
-    void pause();
-
-    bool isPlaying() const;
-
-    /* Return current source sample rate in Hz.
-     * If specified as zero in constructor, this will be the sink sample rate.
-     */
-    uint32_t getSampleRate();
-
-    /* Returns the buffer duration in microseconds at current playback rate. */
-    status_t getBufferDurationInUs(int64_t *duration);
-
-    audio_format_t format();
-
-    size_t frameSize();
-
-    /*
-     * Dumps the state of an audio track.
-     * Not a general-purpose API; intended only for use by media player service to dump its tracks.
-     */
-    status_t dump(int fd, const Vector<String16>& args) const;
-
-    /* Returns the AudioDeviceInfo used by the output to which this AudioTrack is
-     * attached.
-     */
-    jobject getRoutedDevice();
-
-    /* Returns the ID of the audio session this AudioTrack belongs to. */
-    int32_t getAudioSessionId();
-
-    /* Sets the preferred audio device to use for output of this AudioTrack.
-     *
-     * Parameters:
-     * Device: an AudioDeviceInfo object.
-     *
-     * Returned value:
-     *  - NO_ERROR: successful operation
-     *  - BAD_VALUE: failed to set the device
-     */
-    status_t setPreferredDevice(jobject device);
-
-    // TODO: Add AUDIO_OUTPUT_FLAG_DIRECT when it is possible to check.
-    // TODO: Add AUDIO_FLAG_HW_AV_SYNC when it is possible to check.
-    /* Returns the flags */
-    audio_output_flags_t getFlags() const { return mFlags; }
-
-    /* We don't keep stream type here,
-     * instead, we keep attributes and call getVolumeControlStream() to get stream type
-     */
-    audio_stream_type_t getAudioStreamType();
-
-    /* Obtain the pending duration in milliseconds for playback of pure PCM data remaining in
-     * AudioTrack.
-     *
-     * Returns NO_ERROR if successful.
-     *         INVALID_OPERATION if the AudioTrack does not contain pure PCM data.
-     *         BAD_VALUE if msec is nullptr.
-     */
-    status_t pendingDuration(int32_t *msec);
-
-    /* Adds an AudioDeviceCallback. The caller will be notified when the audio device to which this
-     * AudioTrack is routed is updated.
-     * Replaces any previously installed callback.
-     *
-     * Parameters:
-     * Listener: the listener to receive notification of rerouting events.
-     * Handler: the handler to handler the rerouting events.
-     *
-     * Returns NO_ERROR if successful.
-     *         (TODO) INVALID_OPERATION if the same callback is already installed.
-     *         (TODO) NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable
-     *         (TODO) BAD_VALUE if the callback is NULL
-     */
-    status_t addAudioDeviceCallback(jobject listener, jobject rd);
-
-    /* Removes an AudioDeviceCallback.
-     *
-     * Parameters:
-     * Listener: the listener to receive notification of rerouting events.
-     *
-     * Returns NO_ERROR if successful.
-     *         (TODO) INVALID_OPERATION if the callback is not installed
-     *         (TODO) BAD_VALUE if the callback is NULL
-     */
-    status_t removeAudioDeviceCallback(jobject listener);
-
-    /* Register all backed-up routing delegates.
-     *
-     * Parameters:
-     * routingDelegates: backed-up routing delegates
-     *
-     */
-    void registerRoutingDelegates(
-            Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& routingDelegates);
-
-    /* get listener from RoutingDelegate object
-     */
-    static jobject getListener(const jobject routingDelegateObj);
-
-    /* get handler from RoutingDelegate object
-     */
-    static jobject getHandler(const jobject routingDelegateObj);
-
-    /*
-     * Parameters:
-     * map and key
-     *
-     * Returns value if key is in the map
-     *         nullptr if key is not in the map
-     */
-    static jobject findByKey(
-            Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key);
-
-    /*
-     * Parameters:
-     * map and key
-     */
-    static void eraseByKey(
-            Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>>& mp, const jobject key);
-
-private:
-    audio_output_flags_t mFlags;
-
-    jclass mAudioTrackCls;
-    jobject mAudioTrackObj;
-
-    /* Creates a Java VolumeShaper.Configuration object from VolumeShaper::Configuration */
-    jobject createVolumeShaperConfigurationObj(
-            const sp<media::VolumeShaper::Configuration>& config);
-
-    /* Creates a Java VolumeShaper.Operation object from VolumeShaper::Operation */
-    jobject createVolumeShaperOperationObj(
-            const sp<media::VolumeShaper::Operation>& operation);
-
-    /* Creates a Java StreamEventCallback object */
-    jobject createStreamEventCallback(callback_t cbf, void* user);
-
-    /* Creates a Java Executor object for running a callback */
-    jobject createCallbackExecutor();
-
-    status_t javaToNativeStatus(int javaStatus);
-};
-
-}; // namespace android
-
-#endif // ANDROID_JAUDIOTRACK_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h
deleted file mode 100644
index 15f7f83..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPConnection.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017, 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 _J_MEDIA2_HTTP_CONNECTION_H_
-#define _J_MEDIA2_HTTP_CONNECTION_H_
-
-#include "jni.h"
-
-#include <media/MediaHTTPConnection.h>
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct JMedia2HTTPConnection : public MediaHTTPConnection {
-    JMedia2HTTPConnection(JNIEnv *env, jobject thiz);
-
-    virtual bool connect(
-            const char *uri, const KeyedVector<String8, String8> *headers) override;
-
-    virtual void disconnect() override;
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size) override;
-    virtual off64_t getSize() override;
-    virtual status_t getMIMEType(String8 *mimeType) override;
-    virtual status_t getUri(String8 *uri) override;
-
-protected:
-    virtual ~JMedia2HTTPConnection();
-
-private:
-    jobject mMedia2HTTPConnectionObj;
-    jmethodID mConnectMethod;
-    jmethodID mDisconnectMethod;
-    jmethodID mReadAtMethod;
-    jmethodID mGetSizeMethod;
-    jmethodID mGetMIMETypeMethod;
-    jmethodID mGetUriMethod;
-
-    jbyteArray mByteArrayObj;
-
-    DISALLOW_EVIL_CONSTRUCTORS(JMedia2HTTPConnection);
-};
-
-}  // namespace android
-
-#endif  // _J_MEDIA2_HTTP_CONNECTION_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h b/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h
deleted file mode 100644
index bf61a7f..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/JMedia2HTTPService.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2017, 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 _J_MEDIA2_HTTP_SERVICE_H_
-#define _J_MEDIA2_HTTP_SERVICE_H_
-
-#include <jni.h>
-#include <utils/RefBase.h>
-
-#include <media/MediaHTTPService.h>
-#include <media/MediaHTTPConnection.h>
-#include <media/stagefright/foundation/ABase.h>
-
-namespace android {
-
-struct JMedia2HTTPService : public MediaHTTPService {
-    JMedia2HTTPService(JNIEnv *env, jobject thiz);
-
-    virtual sp<MediaHTTPConnection> makeHTTPConnection() override;
-
-protected:
-    virtual ~JMedia2HTTPService();
-
-private:
-    jobject mMedia2HTTPServiceObj;
-
-    jmethodID mMakeHTTPConnectionMethod;
-
-    DISALLOW_EVIL_CONSTRUCTORS(JMedia2HTTPService);
-};
-
-}  // namespace android
-
-#endif  // _J_MEDIA2_HTTP_SERVICE_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/JObjectHolder.h b/media/libmediaplayer2/include/mediaplayer2/JObjectHolder.h
deleted file mode 100644
index 93d8b40..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/JObjectHolder.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 JOBJECT_HOLDER_H_
-
-#define JOBJECT_HOLDER_H_
-
-#include "jni.h"
-#include <mediaplayer2/JavaVMHelper.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-// Helper class for managing global reference of jobject.
-struct JObjectHolder : public RefBase {
-    JObjectHolder(jobject obj) {
-        JNIEnv *env = JavaVMHelper::getJNIEnv();
-        mJObject = reinterpret_cast<jobject>(env->NewGlobalRef(obj));
-    }
-
-    virtual ~JObjectHolder() {
-        JNIEnv *env = JavaVMHelper::getJNIEnv();
-        env->DeleteGlobalRef(mJObject);
-    }
-
-    jobject getJObject() { return mJObject; }
-
-private:
-    jobject mJObject;
-};
-
-}  //" android
-
-#endif  // JOBJECT_HOLDER_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h b/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
deleted file mode 100644
index 4b56aca..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 JAVA_VM_HELPER_H_
-
-#define JAVA_VM_HELPER_H_
-
-#include "jni.h"
-
-#include <atomic>
-
-namespace android {
-
-struct JavaVMHelper {
-    static JNIEnv *getJNIEnv();
-    static JavaVM *getJavaVM();
-    static void setJavaVM(JavaVM *vm);
-
-private:
-    // Once a valid JavaVM has been set, it should never be reset or changed.
-    // However, as it may be accessed from multiple threads, access needs to be
-    // synchronized.
-    static std::atomic<JavaVM *> sJavaVM;
-};
-
-}  // namespace android
-
-#endif  // JAVA_VM_HELPER_H_
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
deleted file mode 100644
index f38b7cc..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-**
-** 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 ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
-#define ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
-
-#include <mediaplayer2/MediaPlayer2Interface.h>
-#include <mediaplayer2/JAudioTrack.h>
-#include <mediaplayer2/JObjectHolder.h>
-
-#include <utility>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-#include "jni.h"
-
-namespace android {
-
-class AudioTrack;
-
-class MediaPlayer2AudioOutput : public MediaPlayer2Interface::AudioSink
-{
-    class CallbackData;
-
-public:
-    MediaPlayer2AudioOutput(int32_t sessionId,
-                            uid_t uid,
-                            int pid,
-                            const jobject attributes);
-    virtual ~MediaPlayer2AudioOutput();
-
-    virtual bool ready() const {
-        return mJAudioTrack != nullptr;
-    }
-    virtual ssize_t bufferSize() const;
-    virtual ssize_t frameCount() const;
-    virtual ssize_t channelCount() const;
-    virtual ssize_t frameSize() const;
-    virtual uint32_t latency() const;
-    virtual float msecsPerFrame() const;
-    virtual status_t getPosition(uint32_t *position) const;
-    virtual status_t getTimestamp(AudioTimestamp &ts) const;
-    virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
-    virtual status_t getFramesWritten(uint32_t *frameswritten) const;
-    virtual int32_t getSessionId() const;
-    virtual void setSessionId(const int32_t id);
-    virtual uint32_t getSampleRate() const;
-    virtual int64_t getBufferDurationInUs() const;
-
-    virtual status_t open(
-            uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-            audio_format_t format,
-            AudioCallback cb, void *cookie,
-            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-            const audio_offload_info_t *offloadInfo = NULL,
-            uint32_t suggestedFrameCount = 0);
-
-    virtual status_t start();
-    virtual ssize_t write(const void* buffer, size_t size, bool blocking = true);
-    virtual void stop();
-    virtual void flush();
-    virtual void pause();
-    virtual void close();
-    void setAudioAttributes(const jobject attributes);
-    virtual audio_stream_type_t getAudioStreamType() const;
-
-    void setVolume(float volume);
-    virtual status_t setPlaybackRate(const AudioPlaybackRate& rate);
-    virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
-
-    status_t setAuxEffectSendLevel(float level);
-    status_t attachAuxEffect(int effectId);
-    virtual status_t dump(int fd, const Vector<String16>& args) const;
-
-    static bool isOnEmulator();
-    static int getMinBufferCount();
-    virtual bool needsTrailingPadding() {
-        return true;
-        // TODO: return correct value.
-        //return mNextOutput == NULL;
-    }
-    // AudioRouting
-    virtual status_t setPreferredDevice(jobject device);
-    virtual jobject getRoutedDevice();
-    virtual status_t addAudioDeviceCallback(jobject routingDelegate);
-    virtual status_t removeAudioDeviceCallback(jobject listener);
-
-private:
-    static void setMinBufferCount();
-    static void CallbackWrapper(int event, void *me, void *info);
-    void deleteRecycledTrack_l();
-    void close_l();
-    status_t updateTrack_l();
-
-    sp<JAudioTrack>         mJAudioTrack;
-    AudioCallback           mCallback;
-    void *                  mCallbackCookie;
-    CallbackData *          mCallbackData;
-    sp<JObjectHolder>       mAttributes;
-    float                   mVolume;
-    AudioPlaybackRate       mPlaybackRate;
-    uint32_t                mSampleRateHz; // sample rate of the content, as set in open()
-    float                   mMsecsPerFrame;
-    size_t                  mFrameSize;
-    int32_t                 mSessionId;
-    uid_t                   mUid;
-    int                     mPid;
-    float                   mSendLevel;
-    int                     mAuxEffectId;
-    audio_output_flags_t    mFlags;
-    sp<JObjectHolder>       mPreferredDevice;
-    mutable Mutex           mLock;
-
-    // <listener, routingDelegate>
-    Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>> mRoutingDelegates;
-
-    // static variables below not protected by mutex
-    static bool             mIsOnEmulator;
-    static int              mMinBufferCount;  // 12 for emulator; otherwise 4
-
-    // CallbackData is what is passed to the AudioTrack as the "user" data.
-    // We need to be able to target this to a different Output on the fly,
-    // so we can't use the Output itself for this.
-    class CallbackData {
-        friend MediaPlayer2AudioOutput;
-    public:
-        explicit CallbackData(MediaPlayer2AudioOutput *cookie) {
-            mData = cookie;
-            mSwitching = false;
-        }
-        MediaPlayer2AudioOutput *getOutput() const {
-            return mData;
-        }
-        void setOutput(MediaPlayer2AudioOutput* newcookie) {
-            mData = newcookie;
-        }
-        // lock/unlock are used by the callback before accessing the payload of this object
-        void lock() const {
-            mLock.lock();
-        }
-        void unlock() const {
-            mLock.unlock();
-        }
-
-        // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over
-        // to the next sink.
-
-        // tryBeginTrackSwitch() returns true only if it obtains the lock.
-        bool tryBeginTrackSwitch() {
-            LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called");
-            if (mLock.tryLock() != OK) {
-                return false;
-            }
-            mSwitching = true;
-            return true;
-        }
-        void endTrackSwitch() {
-            if (mSwitching) {
-                mLock.unlock();
-            }
-            mSwitching = false;
-        }
-
-    private:
-        MediaPlayer2AudioOutput *mData;
-        mutable Mutex mLock; // a recursive mutex might make this unnecessary.
-        bool mSwitching;
-        DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
-    };
-};
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
deleted file mode 100644
index 7804a62..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2017 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 ANDROID_MEDIAPLAYER2INTERFACE_H
-#define ANDROID_MEDIAPLAYER2INTERFACE_H
-
-#ifdef __cplusplus
-
-#include <sys/types.h>
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/RefBase.h>
-#include <jni.h>
-
-#include <media/AVSyncSettings.h>
-#include <media/AudioResamplerPublic.h>
-#include <media/AudioSystem.h>
-#include <media/AudioTimestamp.h>
-#include <media/BufferingSettings.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <mediaplayer2/MediaPlayer2Types.h>
-
-#include "jni.h"
-#include "mediaplayer2.pb.h"
-
-using android::media::MediaPlayer2Proto::PlayerMessage;
-
-// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
-// global, and not in android::
-struct sockaddr_in;
-
-namespace android {
-
-struct DataSourceDesc;
-class Parcel;
-struct ANativeWindowWrapper;
-
-#define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
-#define DEFAULT_AUDIOSINK_SAMPLERATE 44100
-
-// when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open()
-#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
-
-// duration below which we do not allow deep audio buffering
-#define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
-
-class MediaPlayer2InterfaceListener: public RefBase
-{
-public:
-    virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
-           const PlayerMessage *obj) = 0;
-};
-
-class MediaPlayer2Interface : public AHandler {
-public:
-    // AudioSink: abstraction layer for audio output
-    class AudioSink : public RefBase {
-    public:
-        enum cb_event_t {
-            CB_EVENT_FILL_BUFFER,   // Request to write more data to buffer.
-            CB_EVENT_STREAM_END,    // Sent after all the buffers queued in AF and HW are played
-                                    // back (after stop is called)
-            CB_EVENT_TEAR_DOWN      // The AudioTrack was invalidated due to use case change:
-                                    // Need to re-evaluate offloading options
-        };
-
-        // Callback returns the number of bytes actually written to the buffer.
-        typedef size_t (*AudioCallback)(
-                AudioSink *audioSink, void *buffer, size_t size, void *cookie, cb_event_t event);
-
-        virtual ~AudioSink() {}
-        virtual bool ready() const = 0; // audio output is open and ready
-        virtual ssize_t bufferSize() const = 0;
-        virtual ssize_t frameCount() const = 0;
-        virtual ssize_t channelCount() const = 0;
-        virtual ssize_t frameSize() const = 0;
-        virtual uint32_t latency() const = 0;
-        virtual float msecsPerFrame() const = 0;
-        virtual status_t getPosition(uint32_t *position) const = 0;
-        virtual status_t getTimestamp(AudioTimestamp &ts) const = 0;
-        virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const = 0;
-        virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0;
-        virtual int32_t getSessionId() const = 0;
-        virtual audio_stream_type_t getAudioStreamType() const = 0;
-        virtual uint32_t getSampleRate() const = 0;
-        virtual int64_t getBufferDurationInUs() const = 0;
-
-        // If no callback is specified, use the "write" API below to submit
-        // audio data.
-        virtual status_t open(
-                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-                audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
-                AudioCallback cb = NULL,
-                void *cookie = NULL,
-                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                const audio_offload_info_t *offloadInfo = NULL,
-                uint32_t suggestedFrameCount = 0) = 0;
-
-        virtual status_t start() = 0;
-
-        /* Input parameter |size| is in byte units stored in |buffer|.
-         * Data is copied over and actual number of bytes written (>= 0)
-         * is returned, or no data is copied and a negative status code
-         * is returned (even when |blocking| is true).
-         * When |blocking| is false, AudioSink will immediately return after
-         * part of or full |buffer| is copied over.
-         * When |blocking| is true, AudioSink will wait to copy the entire
-         * buffer, unless an error occurs or the copy operation is
-         * prematurely stopped.
-         */
-        virtual ssize_t write(const void* buffer, size_t size, bool blocking = true) = 0;
-
-        virtual void stop() = 0;
-        virtual void flush() = 0;
-        virtual void pause() = 0;
-        virtual void close() = 0;
-
-        virtual status_t setPlaybackRate(const AudioPlaybackRate& rate) = 0;
-        virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */) = 0;
-        virtual bool needsTrailingPadding() {
-            return true;
-        }
-
-        virtual status_t setParameters(const String8& /* keyValuePairs */) {
-            return NO_ERROR;
-        }
-        virtual String8 getParameters(const String8& /* keys */) {
-            return String8::empty();
-        }
-
-        // AudioRouting
-        virtual status_t    setPreferredDevice(jobject device);
-        virtual jobject     getRoutedDevice();
-        virtual status_t    addAudioDeviceCallback(jobject routingDelegate);
-        virtual status_t    removeAudioDeviceCallback(jobject listener);
-    };
-
-    MediaPlayer2Interface() : mListener(NULL) { }
-    virtual ~MediaPlayer2Interface() { }
-    virtual status_t initCheck() = 0;
-
-    virtual void setAudioSink(const sp<AudioSink>& audioSink) {
-        mAudioSink = audioSink;
-    }
-
-    virtual status_t setDataSource(const sp<DataSourceDesc> &dsd) = 0;
-
-    virtual status_t prepareNextDataSource(const sp<DataSourceDesc> &dsd) = 0;
-
-    virtual status_t playNextDataSource(int64_t srcId) = 0;
-
-    // pass the buffered native window to the media player service
-    virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
-
-    virtual status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
-        *buffering = BufferingSettings();
-        return OK;
-    }
-    virtual status_t setBufferingSettings(const BufferingSettings& /* buffering */) {
-        return OK;
-    }
-
-    virtual status_t prepareAsync() = 0;
-    virtual status_t start() = 0;
-    virtual status_t pause() = 0;
-    virtual bool isPlaying() = 0;
-    virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate) {
-        // by default, players only support setting rate to the default
-        if (!isAudioPlaybackRateEqual(rate, AUDIO_PLAYBACK_RATE_DEFAULT)) {
-            return BAD_VALUE;
-        }
-        return OK;
-    }
-    virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
-        *rate = AUDIO_PLAYBACK_RATE_DEFAULT;
-        return OK;
-    }
-    virtual status_t setSyncSettings(const AVSyncSettings& sync, float /* videoFps */) {
-        // By default, players only support setting sync source to default; all other sync
-        // settings are ignored. There is no requirement for getters to return set values.
-        if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
-            return BAD_VALUE;
-        }
-        return OK;
-    }
-    virtual status_t getSyncSettings(
-            AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
-        *sync = AVSyncSettings();
-        *videoFps = -1.f;
-        return OK;
-    }
-    virtual status_t seekTo(
-            int64_t msec, MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) = 0;
-    virtual status_t getCurrentPosition(int64_t *msec) = 0;
-    virtual status_t getDuration(int64_t *msec) = 0;
-    virtual status_t reset() = 0;
-    virtual status_t notifyAt(int64_t /* mediaTimeUs */) {
-        return INVALID_OPERATION;
-    }
-    virtual status_t setLooping(int loop) = 0;
-    virtual status_t setParameter(int key, const Parcel &request) = 0;
-    virtual status_t getParameter(int key, Parcel *reply) = 0;
-
-    virtual status_t getMetrics(char **buffer, size_t *length) = 0;
-
-    // Invoke a generic method on the player by using opaque parcels
-    // for the request and reply.
-    //
-    // @param request Parcel that is positioned at the start of the
-    //                data sent by the java layer.
-    // @param[out] reply Parcel to hold the reply data. Cannot be null.
-    // @return OK if the call was successful.
-    virtual status_t invoke(const PlayerMessage &request, PlayerMessage *reply) = 0;
-
-    void setListener(const sp<MediaPlayer2InterfaceListener> &listener) {
-        Mutex::Autolock autoLock(mListenerLock);
-        mListener = listener;
-    }
-
-    void sendEvent(int64_t srcId, int msg, int ext1=0, int ext2=0, const PlayerMessage *obj=NULL) {
-        sp<MediaPlayer2InterfaceListener> listener;
-        {
-            Mutex::Autolock autoLock(mListenerLock);
-            listener = mListener;
-        }
-
-        if (listener) {
-            listener->notify(srcId, msg, ext1, ext2, obj);
-        }
-    }
-
-    virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
-        return INVALID_OPERATION;
-    }
-
-    virtual void onMessageReceived(const sp<AMessage> & /* msg */) override { }
-
-    // Modular DRM
-    virtual status_t prepareDrm(int64_t /*srcId*/, const uint8_t /* uuid */[16],
-                                const Vector<uint8_t>& /* drmSessionId */) {
-        return INVALID_OPERATION;
-    }
-    virtual status_t releaseDrm(int64_t /*srcId*/) {
-        return INVALID_OPERATION;
-    }
-
-protected:
-    sp<AudioSink> mAudioSink;
-
-private:
-    Mutex mListenerLock;
-    sp<MediaPlayer2InterfaceListener> mListener;
-};
-
-}; // namespace android
-
-#endif // __cplusplus
-
-
-#endif // ANDROID_MEDIAPLAYER2INTERFACE_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
deleted file mode 100644
index 2430289..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Types.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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 ANDROID_MEDIAPLAYER2_TYPES_H
-#define ANDROID_MEDIAPLAYER2_TYPES_H
-
-#include <media/mediaplayer_common.h>
-
-#include <media/MediaSource.h>
-
-namespace android {
-
-typedef MediaSource::ReadOptions::SeekMode MediaPlayer2SeekMode;
-
-enum media2_event_type {
-    MEDIA2_NOP               = 0, // interface test message
-    MEDIA2_PREPARED          = 1,
-    MEDIA2_PLAYBACK_COMPLETE = 2,
-    MEDIA2_BUFFERING_UPDATE  = 3,
-    MEDIA2_SEEK_COMPLETE     = 4,
-    MEDIA2_SET_VIDEO_SIZE    = 5,
-    MEDIA2_STARTED           = 6,
-    MEDIA2_PAUSED            = 7,
-    MEDIA2_SKIPPED           = 8,
-    MEDIA2_NOTIFY_TIME       = 98,
-    MEDIA2_TIMED_TEXT        = 99,
-    MEDIA2_ERROR             = 100,
-    MEDIA2_INFO              = 200,
-    MEDIA2_SUBTITLE_DATA     = 201,
-    MEDIA2_META_DATA         = 202,
-    MEDIA2_DRM_INFO          = 210,
-};
-
-// Generic error codes for the media player framework.  Errors are fatal, the
-// playback must abort.
-//
-// Errors are communicated back to the client using the
-// MediaPlayer2Listener::notify method defined below.
-// In this situation, 'notify' is invoked with the following:
-//   'msg' is set to MEDIA_ERROR.
-//   'ext1' should be a value from the enum media2_error_type.
-//   'ext2' contains an implementation dependant error code to provide
-//          more details. Should default to 0 when not used.
-//
-// The codes are distributed as follow:
-//   0xx: Reserved
-//   1xx: Android Player errors. Something went wrong inside the MediaPlayer2.
-//   2xx: Media errors (e.g Codec not supported). There is a problem with the
-//        media itself.
-//   3xx: Runtime errors. Some extraordinary condition arose making the playback
-//        impossible.
-//
-enum media2_error_type {
-    // 0xx
-    MEDIA2_ERROR_UNKNOWN = 1,
-    // 1xx
-    // MEDIA2_ERROR_SERVER_DIED = 100,
-    // 2xx
-    MEDIA2_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
-    // 3xx
-    MEDIA2_ERROR_FAILED_TO_SET_DATA_SOURCE = 300,
-};
-
-
-// Info and warning codes for the media player framework.  These are non fatal,
-// the playback is going on but there might be some user visible issues.
-//
-// Info and warning messages are communicated back to the client using the
-// MediaPlayer2Listener::notify method defined below.  In this situation,
-// 'notify' is invoked with the following:
-//   'msg' is set to MEDIA_INFO.
-//   'ext1' should be a value from the enum media2_info_type.
-//   'ext2' contains an implementation dependant info code to provide
-//          more details. Should default to 0 when not used.
-//
-// The codes are distributed as follow:
-//   0xx: Reserved
-//   7xx: Android Player info/warning (e.g player lagging behind.)
-//   8xx: Media info/warning (e.g media badly interleaved.)
-//
-enum media2_info_type {
-    // 0xx
-    MEDIA2_INFO_UNKNOWN = 1,
-    // The player just started the playback of this data source.
-    MEDIA2_INFO_DATA_SOURCE_START = 2,
-    // The player just pushed the very first video frame for rendering
-    MEDIA2_INFO_VIDEO_RENDERING_START = 3,
-    // The player just pushed the very first audio frame for rendering
-    MEDIA2_INFO_AUDIO_RENDERING_START = 4,
-    // The player just completed the playback of this data source
-    MEDIA2_INFO_DATA_SOURCE_END = 5,
-    // The player just completed the playback of all data sources.
-    // But this is not visible in native code. Just keep this entry for completeness.
-    MEDIA2_INFO_DATA_SOURCE_LIST_END = 6,
-    // The player just completed an iteration of playback loop. This event is sent only when
-    // looping is enabled.
-    MEDIA2_INFO_DATA_SOURCE_REPEAT = 7,
-
-    //1xx
-    // The player just prepared a data source.
-    MEDIA2_INFO_PREPARED = 100,
-    // The player just completed a call play().
-    MEDIA2_INFO_COMPLETE_CALL_PLAY = 101,
-    // The player just completed a call pause().
-    MEDIA2_INFO_COMPLETE_CALL_PAUSE = 102,
-    // The player just completed a call seekTo.
-    MEDIA2_INFO_COMPLETE_CALL_SEEK = 103,
-
-    // 7xx
-    // The video is too complex for the decoder: it can't decode frames fast
-    // enough. Possibly only the audio plays fine at this stage.
-    MEDIA2_INFO_VIDEO_TRACK_LAGGING = 700,
-    // MediaPlayer2 is temporarily pausing playback internally in order to
-    // buffer more data.
-    MEDIA2_INFO_BUFFERING_START = 701,
-    // MediaPlayer2 is resuming playback after filling buffers.
-    MEDIA2_INFO_BUFFERING_END = 702,
-    // Bandwidth in recent past
-    MEDIA2_INFO_NETWORK_BANDWIDTH = 703,
-
-    // 8xx
-    // Bad interleaving means that a media has been improperly interleaved or not
-    // interleaved at all, e.g has all the video samples first then all the audio
-    // ones. Video is playing but a lot of disk seek may be happening.
-    MEDIA2_INFO_BAD_INTERLEAVING = 800,
-    // The media is not seekable (e.g live stream).
-    MEDIA2_INFO_NOT_SEEKABLE = 801,
-    // New media metadata is available.
-    MEDIA2_INFO_METADATA_UPDATE = 802,
-    // Audio can not be played.
-    MEDIA2_INFO_PLAY_AUDIO_ERROR = 804,
-    // Video can not be played.
-    MEDIA2_INFO_PLAY_VIDEO_ERROR = 805,
-
-    //9xx
-    MEDIA2_INFO_TIMED_TEXT_ERROR = 900,
-};
-
-// Do not change these values without updating their counterparts in MediaPlayer2.java
-enum mediaplayer2_states {
-    MEDIAPLAYER2_STATE_IDLE         = 1001,
-    MEDIAPLAYER2_STATE_PREPARED     = 1002,
-    MEDIAPLAYER2_STATE_PAUSED       = 1003,
-    MEDIAPLAYER2_STATE_PLAYING      = 1004,
-    MEDIAPLAYER2_STATE_ERROR        = 1005,
-};
-
-enum media_player2_internal_states {
-    MEDIA_PLAYER2_STATE_ERROR        = 0,
-    MEDIA_PLAYER2_IDLE               = 1 << 0,
-    MEDIA_PLAYER2_INITIALIZED        = 1 << 1,
-    MEDIA_PLAYER2_PREPARING          = 1 << 2,
-    MEDIA_PLAYER2_PREPARED           = 1 << 3,
-    MEDIA_PLAYER2_STARTED            = 1 << 4,
-    MEDIA_PLAYER2_PAUSED             = 1 << 5,
-    MEDIA_PLAYER2_PLAYBACK_COMPLETE  = 1 << 6
-};
-
-// Keep KEY_PARAMETER_* in sync with MediaPlayer2.java.
-// The same enum space is used for both set and get, in case there are future keys that
-// can be both set and get.  But as of now, all parameters are either set only or get only.
-enum media2_parameter_keys {
-    // Streaming/buffering parameters
-    MEDIA2_KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,            // set only
-
-    // Return a Parcel containing a single int, which is the channel count of the
-    // audio track, or zero for error (e.g. no audio track) or unknown.
-    MEDIA2_KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200,                   // get only
-
-    // Playback rate expressed in permille (1000 is normal speed), saved as int32_t, with negative
-    // values used for rewinding or reverse playback.
-    MEDIA2_KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300,                // set only
-
-    // Set a Parcel containing the value of a parcelled Java AudioAttribute instance
-    MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400                       // set only
-};
-
-// Keep INVOKE_ID_* in sync with MediaPlayer2.java.
-enum media_player2_invoke_ids {
-    MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO = 1,
-    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE = 2,
-    MEDIA_PLAYER2_INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3,
-    MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK = 4,
-    MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK = 5,
-    MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE = 6,
-    MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK = 7
-};
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2_TYPES_H
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
deleted file mode 100644
index 1e8a1d5..0000000
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2017 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 ANDROID_MEDIAPLAYER2_H
-#define ANDROID_MEDIAPLAYER2_H
-
-#include <media/AVSyncSettings.h>
-#include <media/AudioResamplerPublic.h>
-#include <media/BufferingSettings.h>
-#include <media/mediaplayer_common.h>
-#include <mediaplayer2/MediaPlayer2Interface.h>
-#include <mediaplayer2/MediaPlayer2Types.h>
-#include <mediaplayer2/JObjectHolder.h>
-
-#include <jni.h>
-#include <utils/Errors.h>
-#include <utils/Mutex.h>
-#include <utils/RefBase.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-#include <system/audio-base.h>
-
-#include "jni.h"
-
-namespace android {
-
-struct ANativeWindowWrapper;
-struct DataSourceDesc;
-class MediaPlayer2AudioOutput;
-
-// ref-counted object for callbacks
-class MediaPlayer2Listener: virtual public RefBase
-{
-public:
-    virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
-            const PlayerMessage *obj = NULL) = 0;
-};
-
-class MediaPlayer2 : public MediaPlayer2InterfaceListener
-{
-public:
-    ~MediaPlayer2();
-
-    static sp<MediaPlayer2> Create(int32_t sessionId, jobject context);
-    static status_t DumpAll(int fd, const Vector<String16>& args);
-
-            void            disconnect();
-
-            status_t        getSrcId(int64_t *srcId);
-            status_t        setDataSource(const sp<DataSourceDesc> &dsd);
-            status_t        prepareNextDataSource(const sp<DataSourceDesc> &dsd);
-            status_t        playNextDataSource(int64_t srcId);
-            status_t        setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww);
-            status_t        setListener(const sp<MediaPlayer2Listener>& listener);
-            status_t        getBufferingSettings(BufferingSettings* buffering /* nonnull */);
-            status_t        setBufferingSettings(const BufferingSettings& buffering);
-            status_t        prepareAsync();
-            status_t        start();
-            status_t        pause();
-            bool            isPlaying();
-            mediaplayer2_states getState();
-            status_t        setPlaybackSettings(const AudioPlaybackRate& rate);
-            status_t        getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
-            status_t        setSyncSettings(const AVSyncSettings& sync, float videoFpsHint);
-            status_t        getSyncSettings(
-                                    AVSyncSettings* sync /* nonnull */,
-                                    float* videoFps /* nonnull */);
-            status_t        getVideoWidth(int *w);
-            status_t        getVideoHeight(int *h);
-            status_t        seekTo(
-                    int64_t msec,
-                    MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC);
-            status_t        notifyAt(int64_t mediaTimeUs);
-            status_t        getCurrentPosition(int64_t *msec);
-            status_t        getDuration(int64_t srcId, int64_t *msec);
-            status_t        reset();
-            status_t        setAudioStreamType(audio_stream_type_t type);
-            status_t        getAudioStreamType(audio_stream_type_t *type);
-            status_t        setLooping(int loop);
-            bool            isLooping();
-            status_t        setVolume(float volume);
-            void            notify(int64_t srcId, int msg, int ext1, int ext2,
-                                   const PlayerMessage *obj = NULL);
-            status_t        invoke(const PlayerMessage &request, PlayerMessage *reply);
-            status_t        setAudioSessionId(int32_t sessionId);
-            int32_t         getAudioSessionId();
-            status_t        setAuxEffectSendLevel(float level);
-            status_t        attachAuxEffect(int effectId);
-            status_t        setAudioAttributes(const jobject attributes);
-            jobject         getAudioAttributes();
-            status_t        getParameter(int key, Parcel* reply);
-            status_t        getMetrics(char **buffer, size_t *length);
-
-            // Modular DRM
-            status_t        prepareDrm(int64_t srcId,
-                                       const uint8_t uuid[16],
-                                       const Vector<uint8_t>& drmSessionId);
-            status_t        releaseDrm(int64_t srcId);
-            // AudioRouting
-            status_t        setPreferredDevice(jobject device);
-            jobject         getRoutedDevice();
-            status_t        addAudioDeviceCallback(jobject routingDelegate);
-            status_t        removeAudioDeviceCallback(jobject listener);
-
-            status_t        dump(int fd, const Vector<String16>& args);
-
-private:
-    MediaPlayer2(int32_t sessionId, jobject context);
-    bool init();
-
-    // Disconnect from the currently connected ANativeWindow.
-    void disconnectNativeWindow_l();
-
-    status_t setAudioAttributes_l(const jobject attributes);
-
-    void clear_l();
-    status_t seekTo_l(int64_t msec, MediaPlayer2SeekMode mode);
-    status_t prepareAsync_l();
-    status_t getDuration_l(int64_t *msec);
-    status_t reset_l();
-    status_t checkState_l();
-
-    pid_t                       mPid;
-    uid_t                       mUid;
-    sp<MediaPlayer2Interface>   mPlayer;
-    sp<MediaPlayer2AudioOutput> mAudioOutput;
-    int64_t                     mSrcId;
-    thread_id_t                 mLockThreadId;
-    mutable Mutex               mLock;
-    Mutex                       mNotifyLock;
-    sp<MediaPlayer2Listener>    mListener;
-    media_player2_internal_states mCurrentState;
-    bool                        mTransitionToNext;
-    int64_t                     mCurrentPosition;
-    MediaPlayer2SeekMode        mCurrentSeekMode;
-    int64_t                     mSeekPosition;
-    MediaPlayer2SeekMode        mSeekMode;
-    audio_stream_type_t         mStreamType;
-    bool                        mLoop;
-    float                       mVolume;
-    int                         mVideoWidth;
-    int                         mVideoHeight;
-    int32_t                     mAudioSessionId;
-    sp<JObjectHolder>           mAudioAttributes;
-    sp<JObjectHolder>           mContext;
-    float                       mSendLevel;
-    sp<ANativeWindowWrapper>    mConnectedWindow;
-};
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAPLAYER2_H
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
deleted file mode 100644
index de65f8d..0000000
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ /dev/null
@@ -1,1261 +0,0 @@
-/*
-**
-** Copyright 2017, 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 "MediaPlayer2Native"
-
-#include <android/binder_ibinder.h>
-#include <media/AudioSystem.h>
-#include <media/DataSourceDesc.h>
-#include <media/MemoryLeakTrackUtil.h>
-#include <media/NdkWrapper.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooperRoster.h>
-#include <mediaplayer2/MediaPlayer2AudioOutput.h>
-#include <mediaplayer2/mediaplayer2.h>
-
-#include <utils/Log.h>
-#include <utils/SortedVector.h>
-#include <utils/String8.h>
-
-#include <system/audio.h>
-#include <system/window.h>
-
-#include <nuplayer2/NuPlayer2Driver.h>
-
-#include <dirent.h>
-#include <sys/stat.h>
-
-namespace android {
-
-extern ALooperRoster gLooperRoster;
-
-namespace {
-
-const int kDumpLockRetries = 50;
-const int kDumpLockSleepUs = 20000;
-
-class proxyListener : public MediaPlayer2InterfaceListener {
-public:
-    proxyListener(const wp<MediaPlayer2> &player)
-        : mPlayer(player) { }
-
-    ~proxyListener() { };
-
-    virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
-            const PlayerMessage *obj) override {
-        sp<MediaPlayer2> player = mPlayer.promote();
-        if (player != NULL) {
-            player->notify(srcId, msg, ext1, ext2, obj);
-        }
-    }
-
-private:
-    wp<MediaPlayer2> mPlayer;
-};
-
-Mutex sRecordLock;
-SortedVector<wp<MediaPlayer2> > *sPlayers;
-
-void ensureInit_l() {
-    if (sPlayers == NULL) {
-        sPlayers = new SortedVector<wp<MediaPlayer2> >();
-    }
-}
-
-void addPlayer(const wp<MediaPlayer2>& player) {
-    Mutex::Autolock lock(sRecordLock);
-    ensureInit_l();
-    sPlayers->add(player);
-}
-
-void removePlayer(const wp<MediaPlayer2>& player) {
-    Mutex::Autolock lock(sRecordLock);
-    ensureInit_l();
-    sPlayers->remove(player);
-}
-
-/**
- * The only arguments this understands right now are -c, -von and -voff,
- * which are parsed by ALooperRoster::dump()
- */
-status_t dumpPlayers(int fd, const Vector<String16>& args) {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
-
-    {
-        Mutex::Autolock lock(sRecordLock);
-        ensureInit_l();
-        for (int i = 0, n = sPlayers->size(); i < n; ++i) {
-            sp<MediaPlayer2> p = (*sPlayers)[i].promote();
-            if (p != 0) {
-                p->dump(fd, args);
-            }
-            players.add(p);
-        }
-    }
-
-    result.append(" Files opened and/or mapped:\n");
-    snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
-    FILE *f = fopen(buffer, "r");
-    if (f) {
-        while (!feof(f)) {
-            fgets(buffer, SIZE, f);
-            if (strstr(buffer, " /storage/") ||
-                strstr(buffer, " /system/sounds/") ||
-                strstr(buffer, " /data/") ||
-                strstr(buffer, " /system/media/")) {
-                result.append("  ");
-                result.append(buffer);
-            }
-        }
-        fclose(f);
-    } else {
-        result.append("couldn't open ");
-        result.append(buffer);
-        result.append("\n");
-    }
-
-    snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
-    DIR *d = opendir(buffer);
-    if (d) {
-        struct dirent *ent;
-        while((ent = readdir(d)) != NULL) {
-            if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
-                snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
-                struct stat s;
-                if (lstat(buffer, &s) == 0) {
-                    if ((s.st_mode & S_IFMT) == S_IFLNK) {
-                        char linkto[256];
-                        int len = readlink(buffer, linkto, sizeof(linkto));
-                        if(len > 0) {
-                            if(len > 255) {
-                                linkto[252] = '.';
-                                linkto[253] = '.';
-                                linkto[254] = '.';
-                                linkto[255] = 0;
-                            } else {
-                                linkto[len] = 0;
-                            }
-                            if (strstr(linkto, "/storage/") == linkto ||
-                                strstr(linkto, "/system/sounds/") == linkto ||
-                                strstr(linkto, "/data/") == linkto ||
-                                strstr(linkto, "/system/media/") == linkto) {
-                                result.append("  ");
-                                result.append(buffer);
-                                result.append(" -> ");
-                                result.append(linkto);
-                                result.append("\n");
-                            }
-                        }
-                    } else {
-                        result.append("  unexpected type for ");
-                        result.append(buffer);
-                        result.append("\n");
-                    }
-                }
-            }
-        }
-        closedir(d);
-    } else {
-        result.append("couldn't open ");
-        result.append(buffer);
-        result.append("\n");
-    }
-
-    gLooperRoster.dump(fd, args);
-
-    bool dumpMem = false;
-    bool unreachableMemory = false;
-    for (size_t i = 0; i < args.size(); i++) {
-        if (args[i] == String16("-m")) {
-            dumpMem = true;
-        } else if (args[i] == String16("--unreachable")) {
-            unreachableMemory = true;
-        }
-    }
-    if (dumpMem) {
-        result.append("\nDumping memory:\n");
-        std::string s = dumpMemoryAddresses(100 /* limit */);
-        result.append(s.c_str(), s.size());
-    }
-    if (unreachableMemory) {
-        result.append("\nDumping unreachable memory:\n");
-        // TODO - should limit be an argument parameter?
-        // TODO: enable GetUnreachableMemoryString if it's part of stable API
-        //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
-        //result.append(s.c_str(), s.size());
-    }
-
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-}  // anonymous namespace
-
-//static
-sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) {
-    sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context);
-
-    if (!player->init()) {
-        return NULL;
-    }
-
-    ALOGV("Create new player(%p)", player.get());
-
-    addPlayer(player);
-    return player;
-}
-
-// static
-status_t MediaPlayer2::DumpAll(int fd, const Vector<String16>& args) {
-    return dumpPlayers(fd, args);
-}
-
-MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) {
-    ALOGV("constructor");
-    mSrcId = 0;
-    mLockThreadId = 0;
-    mListener = NULL;
-    mStreamType = AUDIO_STREAM_MUSIC;
-    mAudioAttributes = NULL;
-    mContext = new JObjectHolder(context);
-    mCurrentPosition = -1;
-    mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-    mSeekPosition = -1;
-    mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-    mCurrentState = MEDIA_PLAYER2_IDLE;
-    mTransitionToNext = false;
-    mLoop = false;
-    mVolume = 1.0;
-    mVideoWidth = mVideoHeight = 0;
-    mSendLevel = 0;
-
-    mPid = AIBinder_getCallingPid();
-    mUid = AIBinder_getCallingUid();
-
-    mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
-}
-
-MediaPlayer2::~MediaPlayer2() {
-    ALOGV("destructor");
-    disconnect();
-    removePlayer(this);
-}
-
-bool MediaPlayer2::init() {
-    // TODO: after merge with NuPlayer2Driver, MediaPlayer2 will have its own
-    // looper for notification.
-    return true;
-}
-
-void MediaPlayer2::disconnect() {
-    ALOGV("disconnect");
-    sp<MediaPlayer2Interface> p;
-    {
-        Mutex::Autolock _l(mLock);
-        p = mPlayer;
-        mPlayer.clear();
-    }
-
-    if (p != 0) {
-        p->setListener(NULL);
-        p->reset();
-    }
-
-    {
-        Mutex::Autolock _l(mLock);
-        disconnectNativeWindow_l();
-    }
-}
-
-void MediaPlayer2::clear_l() {
-    mCurrentPosition = -1;
-    mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-    mSeekPosition = -1;
-    mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-    mVideoWidth = mVideoHeight = 0;
-}
-
-status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener) {
-    ALOGV("setListener");
-    Mutex::Autolock _l(mLock);
-    mListener = listener;
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::getSrcId(int64_t *srcId) {
-    if (srcId == NULL) {
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock _l(mLock);
-    *srcId = mSrcId;
-    return OK;
-}
-
-status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd) {
-    if (dsd == NULL) {
-        return BAD_VALUE;
-    }
-    // Microsecond is used in NuPlayer2.
-    if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
-        dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
-        ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
-    }
-    if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
-        dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
-        ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
-    }
-    ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
-
-    sp<MediaPlayer2Interface> oldPlayer;
-
-    {
-        Mutex::Autolock _l(mLock);
-        if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
-              || mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
-            ALOGE("setDataSource called in wrong state %d", mCurrentState);
-            return INVALID_OPERATION;
-        }
-
-        sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext);
-        status_t err = player->initCheck();
-        if (err != NO_ERROR) {
-            ALOGE("Failed to create player object, initCheck failed(%d)", err);
-            return err;
-        }
-
-        clear_l();
-
-        player->setListener(new proxyListener(this));
-        player->setAudioSink(mAudioOutput);
-
-        err = player->setDataSource(dsd);
-        if (err != OK) {
-            ALOGE("setDataSource error: %d", err);
-            return err;
-        }
-
-        sp<MediaPlayer2Interface> oldPlayer = mPlayer;
-        mPlayer = player;
-        mSrcId = dsd->mId;
-        mCurrentState = MEDIA_PLAYER2_INITIALIZED;
-    }
-
-    if (oldPlayer != NULL) {
-        oldPlayer->setListener(NULL);
-        oldPlayer->reset();
-    }
-
-    return OK;
-}
-
-status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
-    if (dsd == NULL) {
-        return BAD_VALUE;
-    }
-    ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
-
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-        return INVALID_OPERATION;
-    }
-    return mPlayer->prepareNextDataSource(dsd);
-}
-
-status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
-    ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
-
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-        return INVALID_OPERATION;
-    }
-    mSrcId = srcId;
-    mTransitionToNext = true;
-    return mPlayer->playNextDataSource(srcId);
-}
-
-status_t MediaPlayer2::invoke(const PlayerMessage &request, PlayerMessage *reply) {
-    Mutex::Autolock _l(mLock);
-    const bool hasBeenInitialized =
-            (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
-            ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
-    if ((mPlayer == NULL) || !hasBeenInitialized) {
-        ALOGE("invoke() failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
-        return INVALID_OPERATION;
-    }
-    return mPlayer->invoke(request, reply);
-}
-
-void MediaPlayer2::disconnectNativeWindow_l() {
-    if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
-        status_t err = native_window_api_disconnect(
-                mConnectedWindow->getANativeWindow(), NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
-                  strerror(-err), err);
-        }
-    }
-    mConnectedWindow.clear();
-}
-
-status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) {
-    ANativeWindow *anw = (nww == NULL ? NULL : nww->getANativeWindow());
-    ALOGV("setVideoSurfaceTexture(%p)", anw);
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return NO_INIT;
-    }
-
-    if (anw != NULL) {
-        if (mConnectedWindow != NULL
-            && mConnectedWindow->getANativeWindow() == anw) {
-            return OK;
-        }
-        status_t err = native_window_api_connect(anw, NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGE("setVideoSurfaceTexture failed: %d", err);
-            // Note that we must do the reset before disconnecting from the ANW.
-            // Otherwise queue/dequeue calls could be made on the disconnected
-            // ANW, which may result in errors.
-            mPlayer->reset();
-            disconnectNativeWindow_l();
-            return err;
-        }
-    }
-
-    // Note that we must set the player's new GraphicBufferProducer before
-    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
-    // on the disconnected ANW, which may result in errors.
-    status_t err = mPlayer->setVideoSurfaceTexture(nww);
-
-    disconnectNativeWindow_l();
-
-    if (err == OK) {
-        mConnectedWindow = nww;
-        mLock.unlock();
-    } else if (anw != NULL) {
-        mLock.unlock();
-        status_t err = native_window_api_disconnect(anw, NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
-                  strerror(-err), err);
-        }
-    }
-
-    return err;
-}
-
-status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */) {
-    ALOGV("getBufferingSettings");
-
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return NO_INIT;
-    }
-
-    status_t ret = mPlayer->getBufferingSettings(buffering);
-    if (ret == NO_ERROR) {
-        ALOGV("getBufferingSettings{%s}", buffering->toString().string());
-    } else {
-        ALOGE("getBufferingSettings returned %d", ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
-    ALOGV("setBufferingSettings{%s}", buffering.toString().string());
-
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return NO_INIT;
-    }
-    return mPlayer->setBufferingSettings(buffering);
-}
-
-status_t MediaPlayer2::setAudioAttributes_l(const jobject attributes) {
-    if (mAudioOutput != NULL) {
-        mAudioOutput->setAudioAttributes(attributes);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::prepareAsync() {
-    ALOGV("prepareAsync");
-    Mutex::Autolock _l(mLock);
-    if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_INITIALIZED)) {
-        if (mAudioAttributes != NULL) {
-            status_t err = setAudioAttributes_l(mAudioAttributes->getJObject());
-            if (err != OK) {
-                return err;
-            }
-        }
-        mCurrentState = MEDIA_PLAYER2_PREPARING;
-        return mPlayer->prepareAsync();
-    }
-    ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
-    return INVALID_OPERATION;
-}
-
-status_t MediaPlayer2::start() {
-    ALOGV("start");
-
-    status_t ret = NO_ERROR;
-    Mutex::Autolock _l(mLock);
-
-    mLockThreadId = getThreadId();
-
-    if (mCurrentState & MEDIA_PLAYER2_STARTED) {
-        ret = NO_ERROR;
-    } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
-                    MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
-        mPlayer->setLooping(mLoop);
-
-        if (mAudioOutput != 0) {
-            mAudioOutput->setVolume(mVolume);
-        }
-
-        if (mAudioOutput != 0) {
-            mAudioOutput->setAuxEffectSendLevel(mSendLevel);
-        }
-        mCurrentState = MEDIA_PLAYER2_STARTED;
-        ret = mPlayer->start();
-        if (ret != NO_ERROR) {
-            mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
-        } else {
-            if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
-                ALOGV("playback completed immediately following start()");
-            }
-        }
-    } else {
-        ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
-        ret = INVALID_OPERATION;
-    }
-
-    mLockThreadId = 0;
-
-    return ret;
-}
-
-status_t MediaPlayer2::pause() {
-    ALOGV("pause");
-    Mutex::Autolock _l(mLock);
-    if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
-        return NO_ERROR;
-    if ((mPlayer != 0) && (mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED))) {
-        status_t ret = mPlayer->pause();
-        if (ret != NO_ERROR) {
-            mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
-        } else {
-            mCurrentState = MEDIA_PLAYER2_PAUSED;
-            mTransitionToNext = false;
-        }
-        return ret;
-    }
-    ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
-    return INVALID_OPERATION;
-}
-
-bool MediaPlayer2::isPlaying() {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer != 0) {
-        bool temp = mPlayer->isPlaying();
-        ALOGV("isPlaying: %d", temp);
-        if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
-            ALOGE("internal/external state mismatch corrected");
-            mCurrentState = MEDIA_PLAYER2_PAUSED;
-        } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
-            ALOGE("internal/external state mismatch corrected");
-            mCurrentState = MEDIA_PLAYER2_STARTED;
-        }
-        return temp;
-    }
-    ALOGV("isPlaying: no active player");
-    return false;
-}
-
-mediaplayer2_states MediaPlayer2::getState() {
-    Mutex::Autolock _l(mLock);
-    if (mCurrentState & MEDIA_PLAYER2_STATE_ERROR) {
-        return MEDIAPLAYER2_STATE_ERROR;
-    }
-    if (mPlayer == 0
-        || (mCurrentState &
-            (MEDIA_PLAYER2_IDLE | MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_PREPARING))) {
-        return MEDIAPLAYER2_STATE_IDLE;
-    }
-    if (mCurrentState & MEDIA_PLAYER2_STARTED) {
-        return MEDIAPLAYER2_STATE_PLAYING;
-    }
-    if (mCurrentState & (MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE)) {
-        return MEDIAPLAYER2_STATE_PAUSED;
-    }
-    // now only mCurrentState & MEDIA_PLAYER2_PREPARED is true
-    return MEDIAPLAYER2_STATE_PREPARED;
-}
-
-status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate) {
-    ALOGV("setPlaybackSettings: %f %f %d %d",
-            rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
-    // Negative speed and pitch does not make sense. Further validation will
-    // be done by the respective mediaplayers.
-    if (rate.mSpeed <= 0.f || rate.mPitch < 0.f) {
-        return BAD_VALUE;
-    }
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-
-    status_t err = mPlayer->setPlaybackSettings(rate);
-    return err;
-}
-
-status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-    status_t ret = mPlayer->getPlaybackSettings(rate);
-    if (ret == NO_ERROR) {
-        ALOGV("getPlaybackSettings(%f, %f, %d, %d)",
-                rate->mSpeed, rate->mPitch, rate->mFallbackMode, rate->mStretchMode);
-    } else {
-        ALOGV("getPlaybackSettings returned %d", ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) {
-    ALOGV("setSyncSettings: %u %u %f %f",
-            sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return INVALID_OPERATION;
-    return mPlayer->setSyncSettings(sync, videoFpsHint);
-}
-
-status_t MediaPlayer2::getSyncSettings(
-        AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-    status_t ret = mPlayer->getSyncSettings(sync, videoFps);
-    if (ret == NO_ERROR) {
-        ALOGV("getSyncSettings(%u, %u, %f, %f)",
-                sync->mSource, sync->mAudioAdjustMode, sync->mTolerance, *videoFps);
-    } else {
-        ALOGV("getSyncSettings returned %d", ret);
-    }
-    return ret;
-
-}
-
-status_t MediaPlayer2::getVideoWidth(int *w) {
-    ALOGV("getVideoWidth");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-    *w = mVideoWidth;
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::getVideoHeight(int *h) {
-    ALOGV("getVideoHeight");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-    *h = mVideoHeight;
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::getCurrentPosition(int64_t *msec) {
-    ALOGV("getCurrentPosition");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) {
-        return INVALID_OPERATION;
-    }
-    if (mCurrentPosition >= 0) {
-        ALOGV("Using cached seek position: %lld", (long long)mCurrentPosition);
-        *msec = mCurrentPosition;
-        return NO_ERROR;
-    }
-    status_t ret = mPlayer->getCurrentPosition(msec);
-    if (ret == NO_ERROR) {
-        ALOGV("getCurrentPosition = %lld", (long long)*msec);
-    } else {
-        ALOGE("getCurrentPosition returned %d", ret);
-    }
-    return ret;
-}
-
-status_t MediaPlayer2::getDuration(int64_t srcId, int64_t *msec) {
-    Mutex::Autolock _l(mLock);
-    // TODO: cache duration for currentSrcId and nextSrcId, and return correct
-    // value for nextSrcId.
-    if (srcId != mSrcId) {
-        *msec = -1;
-        return OK;
-    }
-
-    ALOGV("getDuration_l");
-    bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
-            MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
-    if (mPlayer == 0 || !isValidState) {
-        ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
-                mPlayer.get(), mCurrentState);
-        return INVALID_OPERATION;
-    }
-    int64_t durationMs;
-    status_t ret = mPlayer->getDuration(&durationMs);
-
-    if (ret == NO_ERROR) {
-        ALOGV("getDuration = %lld", (long long)durationMs);
-    } else {
-        ALOGE("getDuration returned %d", ret);
-        // Do not enter error state just because no duration was available.
-        durationMs = -1;
-    }
-
-    if (msec) {
-        *msec = durationMs;
-    }
-    return OK;
-}
-
-status_t MediaPlayer2::seekTo_l(int64_t msec, MediaPlayer2SeekMode mode) {
-    ALOGV("seekTo (%lld, %d)", (long long)msec, mode);
-    if ((mPlayer == 0) || !(mCurrentState & (MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
-            MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
-        ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u",
-              mPlayer.get(), mCurrentState);
-        return INVALID_OPERATION;
-    }
-    if (msec < 0) {
-        ALOGW("Attempt to seek to invalid position: %lld", (long long)msec);
-        msec = 0;
-    }
-
-    int64_t durationMs;
-    status_t err = mPlayer->getDuration(&durationMs);
-
-    if (err != OK) {
-        ALOGW("Stream has no duration and is therefore not seekable.");
-        return err;
-    }
-
-    if (msec > durationMs) {
-        ALOGW("Attempt to seek to past end of file: request = %lld, durationMs = %lld",
-              (long long)msec, (long long)durationMs);
-
-        msec = durationMs;
-    }
-
-    // cache duration
-    mCurrentPosition = msec;
-    mCurrentSeekMode = mode;
-    if (mSeekPosition < 0) {
-        mSeekPosition = msec;
-        mSeekMode = mode;
-        return mPlayer->seekTo(msec, mode);
-    }
-    ALOGV("Seek in progress - queue up seekTo[%lld, %d]", (long long)msec, mode);
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
-    mLockThreadId = getThreadId();
-    Mutex::Autolock _l(mLock);
-    status_t result = seekTo_l(msec, mode);
-    mLockThreadId = 0;
-
-    return result;
-}
-
-status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs) {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer != 0) {
-        return INVALID_OPERATION;
-    }
-
-    return mPlayer->notifyAt(mediaTimeUs);
-}
-
-status_t MediaPlayer2::reset_l() {
-    mLoop = false;
-    if (mCurrentState == MEDIA_PLAYER2_IDLE) {
-        return NO_ERROR;
-    }
-    if (mPlayer != 0) {
-        status_t ret = mPlayer->reset();
-        if (ret != NO_ERROR) {
-            ALOGE("reset() failed with return code (%d)", ret);
-            mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
-        } else {
-            mPlayer->setListener(NULL);
-            mCurrentState = MEDIA_PLAYER2_IDLE;
-            mTransitionToNext = false;
-        }
-        // setDataSource has to be called again to create a
-        // new mediaplayer.
-        mPlayer = 0;
-        return ret;
-    }
-    clear_l();
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2::reset() {
-    ALOGV("reset");
-    mLockThreadId = getThreadId();
-    Mutex::Autolock _l(mLock);
-    status_t result = reset_l();
-    mLockThreadId = 0;
-
-    return result;
-}
-
-status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type) {
-    ALOGV("MediaPlayer2::setAudioStreamType");
-    Mutex::Autolock _l(mLock);
-    if (mStreamType == type) return NO_ERROR;
-    if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
-                MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
-        // Can't change the stream type after prepare
-        ALOGE("setAudioStream called in state %d", mCurrentState);
-        return INVALID_OPERATION;
-    }
-    // cache
-    mStreamType = type;
-    return OK;
-}
-
-status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type) {
-    ALOGV("getAudioStreamType");
-    Mutex::Autolock _l(mLock);
-    *type = mStreamType;
-    return OK;
-}
-
-status_t MediaPlayer2::setLooping(int loop) {
-    ALOGV("MediaPlayer2::setLooping");
-    Mutex::Autolock _l(mLock);
-    mLoop = (loop != 0);
-    if (mPlayer != 0) {
-        return mPlayer->setLooping(loop);
-    }
-    return OK;
-}
-
-bool MediaPlayer2::isLooping() {
-    ALOGV("isLooping");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer != 0) {
-        return mLoop;
-    }
-    ALOGV("isLooping: no active player");
-    return false;
-}
-
-status_t MediaPlayer2::setVolume(float volume) {
-    ALOGV("MediaPlayer2::setVolume(%f)", volume);
-    Mutex::Autolock _l(mLock);
-    mVolume = volume;
-    if (mAudioOutput != 0) {
-        mAudioOutput->setVolume(volume);
-    }
-    return OK;
-}
-
-status_t MediaPlayer2::setAudioSessionId(int32_t sessionId) {
-    ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
-    Mutex::Autolock _l(mLock);
-    if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
-        ALOGE("setAudioSessionId called in state %d", mCurrentState);
-        return INVALID_OPERATION;
-    }
-    if (sessionId < 0) {
-        return BAD_VALUE;
-    }
-    if (mAudioOutput != NULL && sessionId != mAudioOutput->getSessionId()) {
-        mAudioOutput->setSessionId(sessionId);
-    }
-    return NO_ERROR;
-}
-
-int32_t MediaPlayer2::getAudioSessionId() {
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput != NULL) {
-        return mAudioOutput->getSessionId();
-    }
-    return 0;
-}
-
-status_t MediaPlayer2::setAuxEffectSendLevel(float level) {
-    ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
-    Mutex::Autolock _l(mLock);
-    mSendLevel = level;
-    if (mAudioOutput != 0) {
-        return mAudioOutput->setAuxEffectSendLevel(level);
-    }
-    return OK;
-}
-
-status_t MediaPlayer2::attachAuxEffect(int effectId) {
-    ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput == 0 ||
-        (mCurrentState & MEDIA_PLAYER2_IDLE) ||
-        (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
-        ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
-        return INVALID_OPERATION;
-    }
-
-    return mAudioOutput->attachAuxEffect(effectId);
-}
-
-// always call with lock held
-status_t MediaPlayer2::checkState_l() {
-    if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
-            MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
-        // Can't change the audio attributes after prepare
-        ALOGE("trying to set audio attributes called in state %d", mCurrentState);
-        return INVALID_OPERATION;
-    }
-    return OK;
-}
-
-status_t MediaPlayer2::setAudioAttributes(const jobject attributes) {
-    ALOGV("MediaPlayer2::setAudioAttributes");
-    status_t status = INVALID_OPERATION;
-    Mutex::Autolock _l(mLock);
-    if (checkState_l() != OK) {
-        return status;
-    }
-    mAudioAttributes = new JObjectHolder(attributes);
-    status = setAudioAttributes_l(attributes);
-    return status;
-}
-
-jobject MediaPlayer2::getAudioAttributes() {
-    ALOGV("MediaPlayer2::getAudioAttributes)");
-    Mutex::Autolock _l(mLock);
-    return mAudioAttributes != NULL ? mAudioAttributes->getJObject() : NULL;
-}
-
-status_t MediaPlayer2::getParameter(int key, Parcel *reply) {
-    ALOGV("MediaPlayer2::getParameter(%d)", key);
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGV("getParameter: no active player");
-        return INVALID_OPERATION;
-    }
-
-    status_t status =  mPlayer->getParameter(key, reply);
-    if (status != OK) {
-        ALOGD("getParameter returns %d", status);
-    }
-    return status;
-}
-
-// for mediametrics
-status_t MediaPlayer2::getMetrics(char **buffer, size_t *length) {
-    ALOGD("MediaPlayer2::getMetrics()");
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        ALOGV("getMetrics: no active player");
-        return INVALID_OPERATION;
-    }
-
-    status_t status =  mPlayer->getMetrics(buffer, length);
-    if (status != OK) {
-        ALOGD("getMetrics returns %d", status);
-    }
-    return status;
-}
-
-void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *obj) {
-    ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
-          (long long)srcId, msg, ext1, ext2);
-
-    bool send = true;
-    bool locked = false;
-
-    // TODO: In the future, we might be on the same thread if the app is
-    // running in the same process as the media server. In that case,
-    // this will deadlock.
-    //
-    // The threadId hack below works around this for the care of prepare,
-    // seekTo, start, and reset within the same process.
-    // FIXME: Remember, this is a hack, it's not even a hack that is applied
-    // consistently for all use-cases, this needs to be revisited.
-    if (mLockThreadId != getThreadId()) {
-        mLock.lock();
-        locked = true;
-    }
-
-    // Allows calls from JNI in idle state to notify errors
-    if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
-        ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
-              (long long)srcId, msg, ext1, ext2);
-        if (locked) mLock.unlock();   // release the lock when done.
-        return;
-    }
-
-    switch (msg) {
-    case MEDIA2_NOP: // interface test message
-        break;
-    case MEDIA2_PREPARED:
-        ALOGV("MediaPlayer2::notify() prepared, srcId=%lld", (long long)srcId);
-        if (srcId == mSrcId) {
-            mCurrentState = MEDIA_PLAYER2_PREPARED;
-        }
-        break;
-    case MEDIA2_DRM_INFO:
-        ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
-              (long long)srcId, msg, ext1, ext2, obj);
-        break;
-    case MEDIA2_PLAYBACK_COMPLETE:
-        ALOGV("playback complete");
-        if (mCurrentState == MEDIA_PLAYER2_IDLE) {
-            ALOGE("playback complete in idle state");
-        }
-        if (!mLoop && srcId == mSrcId) {
-            mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
-        }
-        break;
-    case MEDIA2_ERROR:
-        // Always log errors.
-        // ext1: Media framework error code.
-        // ext2: Implementation dependant error code.
-        ALOGE("error (%d, %d)", ext1, ext2);
-        mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
-        break;
-    case MEDIA2_INFO:
-        // ext1: Media framework error code.
-        // ext2: Implementation dependant error code.
-        if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
-            ALOGW("info/warning (%d, %d)", ext1, ext2);
-
-            if (ext1 == MEDIA2_INFO_DATA_SOURCE_START && srcId == mSrcId && mTransitionToNext) {
-                mCurrentState = MEDIA_PLAYER2_STARTED;
-                mTransitionToNext = false;
-            }
-        }
-        break;
-    case MEDIA2_SEEK_COMPLETE:
-        ALOGV("Received seek complete");
-        if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
-            ALOGV("Executing queued seekTo(%lld, %d)",
-                  (long long)mCurrentPosition, mCurrentSeekMode);
-            mSeekPosition = -1;
-            mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-            seekTo_l(mCurrentPosition, mCurrentSeekMode);
-        }
-        else {
-            ALOGV("All seeks complete - return to regularly scheduled program");
-            mCurrentPosition = mSeekPosition = -1;
-            mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
-        }
-        break;
-    case MEDIA2_BUFFERING_UPDATE:
-        ALOGV("buffering %d", ext1);
-        break;
-    case MEDIA2_SET_VIDEO_SIZE:
-        ALOGV("New video size %d x %d", ext1, ext2);
-        mVideoWidth = ext1;
-        mVideoHeight = ext2;
-        break;
-    case MEDIA2_NOTIFY_TIME:
-        ALOGV("Received notify time message");
-        break;
-    case MEDIA2_TIMED_TEXT:
-        ALOGV("Received timed text message");
-        break;
-    case MEDIA2_SUBTITLE_DATA:
-        ALOGV("Received subtitle data message");
-        break;
-    case MEDIA2_META_DATA:
-        ALOGV("Received timed metadata message");
-        break;
-    default:
-        ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
-        break;
-    }
-
-    sp<MediaPlayer2Listener> listener = mListener;
-    if (locked) mLock.unlock();
-
-    // this prevents re-entrant calls into client code
-    if ((listener != 0) && send) {
-        Mutex::Autolock _l(mNotifyLock);
-        ALOGV("callback application");
-        listener->notify(srcId, msg, ext1, ext2, obj);
-        ALOGV("back from callback");
-    }
-}
-
-// Modular DRM
-status_t MediaPlayer2::prepareDrm(
-        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
-    // TODO change to ALOGV
-    ALOGD("prepareDrm: uuid: %p  drmSessionId: %p(%zu)", uuid,
-            drmSessionId.array(), drmSessionId.size());
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    // Only allowed it in player's preparing/prepared state.
-    // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
-    // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
-    // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
-    if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
-        ALOGW("prepareDrm(%lld) called in non-prepare state(%d)", (long long)srcId, mCurrentState);
-        if (srcId == mSrcId) {
-            return INVALID_OPERATION;
-        }
-    }
-
-    if (drmSessionId.isEmpty()) {
-        ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
-        return INVALID_OPERATION;
-    }
-
-    // Passing down to mediaserver mainly for creating the crypto
-    status_t status = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
-    ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
-
-    // TODO change to ALOGV
-    ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
-
-    return status;
-}
-
-status_t MediaPlayer2::releaseDrm(int64_t srcId) {
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == NULL) {
-        return NO_INIT;
-    }
-
-    // Not allowing releaseDrm in an active/resumable state
-    if (mCurrentState & (MEDIA_PLAYER2_STARTED |
-                         MEDIA_PLAYER2_PAUSED |
-                         MEDIA_PLAYER2_PLAYBACK_COMPLETE |
-                         MEDIA_PLAYER2_STATE_ERROR)) {
-        ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
-        return INVALID_OPERATION;
-    }
-
-    status_t status = mPlayer->releaseDrm(srcId);
-    // TODO change to ALOGV
-    ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
-    if (status != OK) {
-        ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
-        // Overriding to OK so the client proceed with its own cleanup
-        // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
-        status = OK;
-    }
-
-    return status;
-}
-
-status_t MediaPlayer2::setPreferredDevice(jobject device) {
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput == NULL) {
-        ALOGV("setPreferredDevice: audio sink not init");
-        return NO_INIT;
-    }
-    return mAudioOutput->setPreferredDevice(device);
-}
-
-jobject MediaPlayer2::getRoutedDevice() {
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput == NULL) {
-        ALOGV("getRoutedDevice: audio sink not init");
-        return nullptr;
-    }
-    return mAudioOutput->getRoutedDevice();
-}
-
-status_t MediaPlayer2::addAudioDeviceCallback(jobject routingDelegate) {
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput == NULL) {
-        ALOGV("addAudioDeviceCallback: player not init");
-        return NO_INIT;
-    }
-    return mAudioOutput->addAudioDeviceCallback(routingDelegate);
-}
-
-status_t MediaPlayer2::removeAudioDeviceCallback(jobject listener) {
-    Mutex::Autolock _l(mLock);
-    if (mAudioOutput == NULL) {
-        ALOGV("addAudioDeviceCallback: player not init");
-        return NO_INIT;
-    }
-    return mAudioOutput->removeAudioDeviceCallback(listener);
-}
-
-status_t MediaPlayer2::dump(int fd, const Vector<String16>& args) {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    result.append(" MediaPlayer2\n");
-    snprintf(buffer, 255, "  pid(%d), looping(%s)\n", mPid, mLoop?"true": "false");
-    result.append(buffer);
-
-    sp<MediaPlayer2Interface> player;
-    sp<MediaPlayer2AudioOutput> audioOutput;
-    bool locked = false;
-    for (int i = 0; i < kDumpLockRetries; ++i) {
-        if (mLock.tryLock() == NO_ERROR) {
-            locked = true;
-            break;
-        }
-        usleep(kDumpLockSleepUs);
-    }
-
-    if (locked) {
-        player = mPlayer;
-        audioOutput = mAudioOutput;
-        mLock.unlock();
-    } else {
-        result.append("  lock is taken, no dump from player and audio output\n");
-    }
-    write(fd, result.string(), result.size());
-
-    if (player != NULL) {
-        player->dump(fd, args);
-    }
-    if (audioOutput != 0) {
-        audioOutput->dump(fd, args);
-    }
-    write(fd, "\n", 1);
-    return NO_ERROR;
-}
-
-} // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/Android.bp b/media/libmediaplayer2/nuplayer2/Android.bp
deleted file mode 100644
index 0f69b2e..0000000
--- a/media/libmediaplayer2/nuplayer2/Android.bp
+++ /dev/null
@@ -1,72 +0,0 @@
-cc_library_static {
-
-    srcs: [
-        "JMediaPlayer2Utils.cpp",
-        "JWakeLock.cpp",
-        "GenericSource2.cpp",
-        "HTTPLiveSource2.cpp",
-        "NuPlayer2.cpp",
-        "NuPlayer2CCDecoder.cpp",
-        "NuPlayer2Decoder.cpp",
-        "NuPlayer2DecoderBase.cpp",
-        "NuPlayer2DecoderPassThrough.cpp",
-        "NuPlayer2Driver.cpp",
-        "NuPlayer2Drm.cpp",
-        "NuPlayer2Renderer.cpp",
-        "RTSPSource2.cpp",
-    ],
-
-    header_libs: [
-        "libbase_headers",
-        "libmediaplayer2_headers",
-        "media_plugin_headers",
-    ],
-
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-        "frameworks/av/media/libstagefright/httplive",
-        "frameworks/av/media/libstagefright/include",
-        "frameworks/av/media/libstagefright/mpeg2ts",
-        "frameworks/av/media/libstagefright/rtsp",
-        "frameworks/av/media/libstagefright/timedtext",
-        "frameworks/av/media/ndk",
-        "frameworks/base/core/jni",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-
-    product_variables: {
-        debuggable: {
-            cflags: [
-                "-DENABLE_STAGEFRIGHT_EXPERIMENTS",
-            ],
-        }
-    },
-
-    shared_libs: [
-        "libbinder",
-        "libui",
-        "libgui",
-        "libmedia",
-        "libmediametrics",
-        "libmediandk",
-        "libmediandk_utils",
-        "libpowermanager",
-    ],
-
-    static_libs: [
-        "libmedia_helper",
-        "libmediaplayer2-protos",
-        "libmedia2_jni_core",
-    ],
-
-    name: "libstagefright_nuplayer2",
-
-    sanitize: {
-        cfi: true,
-    },
-
-}
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
deleted file mode 100644
index 9552580..0000000
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ /dev/null
@@ -1,1547 +0,0 @@
-/*
- * Copyright 2017 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 "GenericSource2"
-
-#include "GenericSource2.h"
-#include "NuPlayer2Drm.h"
-
-#include "AnotherPacketSource.h"
-#include <cutils/properties.h>
-#include <media/DataSource.h>
-#include <media/MediaBufferHolder.h>
-#include <media/NdkWrapper.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaClock.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/NdkUtils.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-static const int kInitialMarkMs        = 5000;  // 5secs
-
-//static const int kPausePlaybackMarkMs  = 2000;  // 2secs
-static const int kResumePlaybackMarkMs = 15000;  // 15secs
-
-NuPlayer2::GenericSource2::GenericSource2(
-        const sp<AMessage> &notify,
-        uid_t uid,
-        const sp<MediaClock> &mediaClock)
-    : Source(notify),
-      mAudioTimeUs(0),
-      mAudioLastDequeueTimeUs(0),
-      mVideoTimeUs(0),
-      mVideoLastDequeueTimeUs(0),
-      mPrevBufferPercentage(-1),
-      mPollBufferingGeneration(0),
-      mSentPauseOnBuffering(false),
-      mAudioDataGeneration(0),
-      mVideoDataGeneration(0),
-      mFetchSubtitleDataGeneration(0),
-      mFetchTimedTextDataGeneration(0),
-      mDurationUs(-1ll),
-      mAudioIsVorbis(false),
-      mIsSecure(false),
-      mIsStreaming(false),
-      mUID(uid),
-      mMediaClock(mediaClock),
-      mFd(-1),
-      mBitrate(-1ll),
-      mPendingReadBufferTypes(0) {
-    ALOGV("GenericSource2");
-    CHECK(mediaClock != NULL);
-
-    mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
-    mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
-    resetDataSource();
-}
-
-void NuPlayer2::GenericSource2::resetDataSource() {
-    ALOGV("resetDataSource");
-
-    mDisconnected = false;
-    mUri.clear();
-    mUriHeaders.clear();
-    if (mFd >= 0) {
-        close(mFd);
-        mFd = -1;
-    }
-    mOffset = 0;
-    mLength = 0;
-    mStarted = false;
-    mPreparing = false;
-
-    mIsDrmProtected = false;
-    mIsDrmReleased = false;
-    mIsSecure = false;
-    mMimes.clear();
-}
-
-status_t NuPlayer2::GenericSource2::setDataSource(
-        const char *url,
-        const KeyedVector<String8, String8> *headers) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("setDataSource url: %s", url);
-
-    resetDataSource();
-
-    mUri = url;
-
-    if (headers) {
-        mUriHeaders = *headers;
-    }
-
-    // delay data source creation to prepareAsync() to avoid blocking
-    // the calling thread in setDataSource for any significant time.
-    return OK;
-}
-
-status_t NuPlayer2::GenericSource2::setDataSource(
-        int fd, int64_t offset, int64_t length) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
-
-    resetDataSource();
-
-    mFd = dup(fd);
-    mOffset = offset;
-    mLength = length;
-
-    // delay data source creation to prepareAsync() to avoid blocking
-    // the calling thread in setDataSource for any significant time.
-    return OK;
-}
-
-status_t NuPlayer2::GenericSource2::setDataSource(const sp<DataSource>& source) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("setDataSource (source: %p)", source.get());
-
-    resetDataSource();
-    mDataSourceWrapper = new AMediaDataSourceWrapper(source);
-    return OK;
-}
-
-sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
-    Mutex::Autolock _l(mLock);
-    return mFileMeta;
-}
-
-status_t NuPlayer2::GenericSource2::initFromDataSource() {
-    mExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
-    CHECK(mFd >=0 || mDataSourceWrapper != NULL);
-    sp<AMediaDataSourceWrapper> aSourceWrapper = mDataSourceWrapper;
-    const int fd = mFd;
-
-    mLock.unlock();
-    // This might take long time if data source is not reliable.
-    status_t err;
-    if (aSourceWrapper != NULL) {
-        err = mExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
-    } else {
-        err = mExtractor->setDataSource(fd, mOffset, mLength);
-    }
-
-    if (err != OK) {
-        ALOGE("initFromDataSource, failed to set extractor data source!");
-        mLock.lock();
-        return UNKNOWN_ERROR;
-    }
-
-    size_t numtracks = mExtractor->getTrackCount();
-    if (numtracks == 0) {
-        ALOGE("initFromDataSource, source has no track!");
-        mLock.lock();
-        return UNKNOWN_ERROR;
-    }
-
-    mFileMeta = convertMediaFormatWrapperToMetaData(mExtractor->getFormat());
-    mLock.lock();
-    if (mFileMeta != NULL) {
-        int64_t duration;
-        if (mFileMeta->findInt64(kKeyDuration, &duration)) {
-            mDurationUs = duration;
-        }
-    }
-
-    int32_t totalBitrate = 0;
-
-    mMimes.clear();
-
-    for (size_t i = 0; i < numtracks; ++i) {
-
-        sp<AMediaFormatWrapper> trackFormat = mExtractor->getTrackFormat(i);
-        if (trackFormat == NULL) {
-            ALOGE("no metadata for track %zu", i);
-            return UNKNOWN_ERROR;
-        }
-
-        sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
-        if (aSourceWrapper != NULL) {
-            trackExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
-        } else {
-            trackExtractor->setDataSource(fd, mOffset, mLength);
-        }
-
-        const char *mime;
-        sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
-        CHECK(meta->findCString(kKeyMIMEType, &mime));
-
-        ALOGV("initFromDataSource track[%zu]: %s", i, mime);
-
-        // Do the string compare immediately with "mime",
-        // we can't assume "mime" would stay valid after another
-        // extractor operation, some extractors might modify meta
-        // during getTrack() and make it invalid.
-        if (!strncasecmp(mime, "audio/", 6)) {
-            if (mAudioTrack.mExtractor == NULL) {
-                mAudioTrack.mIndex = i;
-                mAudioTrack.mExtractor = trackExtractor;
-                mAudioTrack.mExtractor->selectTrack(i);
-                mAudioTrack.mPackets = new AnotherPacketSource(meta);
-
-                if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
-                    mAudioIsVorbis = true;
-                } else {
-                    mAudioIsVorbis = false;
-                }
-
-                mMimes.add(String8(mime));
-            }
-        } else if (!strncasecmp(mime, "video/", 6)) {
-            if (mVideoTrack.mExtractor == NULL) {
-                mVideoTrack.mIndex = i;
-                mVideoTrack.mExtractor = trackExtractor;
-                mVideoTrack.mExtractor->selectTrack(i);
-                mVideoTrack.mPackets = new AnotherPacketSource(meta);
-
-                // video always at the beginning
-                mMimes.insertAt(String8(mime), 0);
-            }
-        }
-
-        mExtractors.push(trackExtractor);
-        int64_t durationUs;
-        if (meta->findInt64(kKeyDuration, &durationUs)) {
-            if (durationUs > mDurationUs) {
-                mDurationUs = durationUs;
-            }
-        }
-
-        int32_t bitrate;
-        if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
-            totalBitrate += bitrate;
-        } else {
-            totalBitrate = -1;
-        }
-    }
-
-    ALOGV("initFromDataSource mExtractors.size(): %zu  mIsSecure: %d  mime[0]: %s", mExtractors.size(),
-            mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
-
-    if (mExtractors.size() == 0) {
-        ALOGE("b/23705695");
-        return UNKNOWN_ERROR;
-    }
-
-    // Modular DRM: The return value doesn't affect source initialization.
-    (void)checkDrmInfo();
-
-    mBitrate = totalBitrate;
-
-    return OK;
-}
-
-status_t NuPlayer2::GenericSource2::getBufferingSettings(
-        BufferingSettings* buffering /* nonnull */) {
-    {
-        Mutex::Autolock _l(mLock);
-        *buffering = mBufferingSettings;
-    }
-
-    ALOGV("getBufferingSettings{%s}", buffering->toString().string());
-    return OK;
-}
-
-status_t NuPlayer2::GenericSource2::setBufferingSettings(const BufferingSettings& buffering) {
-    ALOGV("setBufferingSettings{%s}", buffering.toString().string());
-
-    Mutex::Autolock _l(mLock);
-    mBufferingSettings = buffering;
-    return OK;
-}
-
-int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
-    if (mAudioTrack.mExtractor != NULL) {
-        return mAudioTimeUs;
-    } else if (mVideoTrack.mExtractor != NULL) {
-        return mVideoTimeUs;
-    } else {
-        return 0;
-    }
-}
-
-bool NuPlayer2::GenericSource2::isStreaming() const {
-    Mutex::Autolock _l(mLock);
-    return mIsStreaming;
-}
-
-NuPlayer2::GenericSource2::~GenericSource2() {
-    ALOGV("~GenericSource2");
-    if (mLooper != NULL) {
-        mLooper->unregisterHandler(id());
-        mLooper->stop();
-    }
-    if (mDataSourceWrapper != NULL) {
-        mDataSourceWrapper->close();
-    }
-    resetDataSource();
-}
-
-void NuPlayer2::GenericSource2::prepareAsync(int64_t startTimeUs) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
-
-    if (mLooper == NULL) {
-        mLooper = new ALooper;
-        mLooper->setName("generic2");
-        mLooper->start(false, /* runOnCallingThread */
-                       true,  /* canCallJava */
-                       PRIORITY_DEFAULT);
-
-        mLooper->registerHandler(this);
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
-    msg->setInt64("startTimeUs", startTimeUs);
-
-    msg->post();
-}
-
-void NuPlayer2::GenericSource2::onPrepareAsync(int64_t startTimeUs) {
-    ALOGV("onPrepareAsync: mFd %d mUri %s mDataSourceWrapper: %p",
-            mFd, mUri.c_str(), mDataSourceWrapper.get());
-
-    if (!mUri.empty()) {
-        const char* uri = mUri.c_str();
-        size_t numheaders = mUriHeaders.size();
-        const char **key_values = numheaders ? new const char *[numheaders * 2] : NULL;
-        for (size_t i = 0; i < numheaders; ++i) {
-            key_values[i * 2] = mUriHeaders.keyAt(i).c_str();
-            key_values[i * 2 + 1] =  mUriHeaders.valueAt(i).c_str();
-        }
-        mLock.unlock();
-        AMediaDataSource *aSource = AMediaDataSource_newUri(uri, numheaders, key_values);
-        mLock.lock();
-        mDataSourceWrapper = aSource ? new AMediaDataSourceWrapper(aSource) : NULL;
-        delete[] key_values;
-        // For cached streaming cases, we need to wait for enough
-        // buffering before reporting prepared.
-        mIsStreaming = !strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8);
-    }
-
-    if (mDisconnected || (mFd < 0 && mDataSourceWrapper == NULL)) {
-        ALOGE("mDisconnected(%d) or Failed to create data source!", mDisconnected);
-        notifyPreparedAndCleanup(UNKNOWN_ERROR);
-        return;
-    }
-
-    // init extractor from data source
-    status_t err = initFromDataSource();
-    if (mFd >= 0) {
-        close(mFd);
-        mFd = -1;
-    }
-
-    if (err != OK) {
-        ALOGE("Failed to init from data source!");
-        notifyPreparedAndCleanup(err);
-        return;
-    }
-
-    if (mVideoTrack.mExtractor != NULL) {
-        sp<MetaData> meta = getFormatMeta_l(false /* audio */);
-        sp<AMessage> msg = new AMessage;
-        err = convertMetaDataToMessage(meta, &msg);
-        if(err != OK) {
-            notifyPreparedAndCleanup(err);
-            return;
-        }
-        notifyVideoSizeChanged(msg);
-    }
-
-    notifyFlagsChanged(
-            // FLAG_SECURE will be known if/when prepareDrm is called by the app
-            // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
-            FLAG_CAN_PAUSE |
-            FLAG_CAN_SEEK_BACKWARD |
-            FLAG_CAN_SEEK_FORWARD |
-            FLAG_CAN_SEEK);
-
-    doSeek(startTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
-    finishPrepareAsync();
-
-    ALOGV("onPrepareAsync: Done");
-}
-
-void NuPlayer2::GenericSource2::finishPrepareAsync() {
-    ALOGV("finishPrepareAsync");
-
-    if (mIsStreaming) {
-        mPreparing = true;
-        ++mPollBufferingGeneration;
-        schedulePollBuffering();
-    } else {
-        notifyPrepared();
-    }
-
-    if (mAudioTrack.mExtractor != NULL) {
-        postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
-    }
-
-    if (mVideoTrack.mExtractor != NULL) {
-        postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
-    }
-}
-
-void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
-    if (err != OK) {
-        mDataSourceWrapper.clear();
-
-        mBitrate = -1;
-        mPrevBufferPercentage = -1;
-        ++mPollBufferingGeneration;
-    }
-    notifyPrepared(err);
-}
-
-void NuPlayer2::GenericSource2::start() {
-    Mutex::Autolock _l(mLock);
-    ALOGI("start");
-
-    if (mAudioTrack.mExtractor != NULL) {
-        postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
-    }
-
-    if (mVideoTrack.mExtractor != NULL) {
-        postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
-    }
-
-    mStarted = true;
-}
-
-void NuPlayer2::GenericSource2::stop() {
-    Mutex::Autolock _l(mLock);
-    mStarted = false;
-}
-
-void NuPlayer2::GenericSource2::pause() {
-    Mutex::Autolock _l(mLock);
-    mStarted = false;
-}
-
-void NuPlayer2::GenericSource2::resume() {
-    Mutex::Autolock _l(mLock);
-    mStarted = true;
-}
-
-void NuPlayer2::GenericSource2::disconnect() {
-    {
-        Mutex::Autolock _l(mLock);
-        mDisconnected = true;
-    }
-    if (mDataSourceWrapper != NULL) {
-        mDataSourceWrapper->close();
-    }
-}
-
-status_t NuPlayer2::GenericSource2::feedMoreTSData() {
-    return OK;
-}
-
-void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
-    Mutex::Autolock _l(mLock);
-    switch (msg->what()) {
-      case kWhatPrepareAsync:
-      {
-          int64_t startTimeUs;
-          CHECK(msg->findInt64("startTimeUs", &startTimeUs));
-          onPrepareAsync(startTimeUs);
-          break;
-      }
-      case kWhatFetchSubtitleData:
-      {
-          fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
-                  mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
-          break;
-      }
-
-      case kWhatFetchTimedTextData:
-      {
-          fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
-                  mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
-          break;
-      }
-
-      case kWhatSendSubtitleData:
-      {
-          sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
-                  mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
-          break;
-      }
-
-      case kWhatSendGlobalTimedTextData:
-      {
-          sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
-          break;
-      }
-      case kWhatSendTimedTextData:
-      {
-          sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
-                  mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
-          break;
-      }
-
-      case kWhatChangeAVSource:
-      {
-          int32_t trackIndex;
-          CHECK(msg->findInt32("trackIndex", &trackIndex));
-          const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
-
-          Track* track;
-          AString mime;
-          media_track_type trackType, counterpartType;
-          sp<AMediaFormatWrapper> format = extractor->getTrackFormat(trackIndex);
-          format->getString(AMEDIAFORMAT_KEY_MIME, &mime);
-          if (!strncasecmp(mime.c_str(), "audio/", 6)) {
-              track = &mAudioTrack;
-              trackType = MEDIA_TRACK_TYPE_AUDIO;
-              counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
-          } else {
-              CHECK(!strncasecmp(mime.c_str(), "video/", 6));
-              track = &mVideoTrack;
-              trackType = MEDIA_TRACK_TYPE_VIDEO;
-              counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
-          }
-
-
-          track->mExtractor = extractor;
-          track->mExtractor->selectSingleTrack(trackIndex);
-          track->mIndex = trackIndex;
-          ++mAudioDataGeneration;
-          ++mVideoDataGeneration;
-
-          int64_t timeUs, actualTimeUs;
-          const bool formatChange = true;
-          if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
-              timeUs = mAudioLastDequeueTimeUs;
-          } else {
-              timeUs = mVideoLastDequeueTimeUs;
-          }
-          readBuffer(trackType, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
-                  &actualTimeUs, formatChange);
-          readBuffer(counterpartType, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
-                  NULL, !formatChange);
-          ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
-
-          break;
-      }
-
-      case kWhatSeek:
-      {
-          onSeek(msg);
-          break;
-      }
-
-      case kWhatReadBuffer:
-      {
-          onReadBuffer(msg);
-          break;
-      }
-
-      case kWhatPollBuffering:
-      {
-          int32_t generation;
-          CHECK(msg->findInt32("generation", &generation));
-          if (generation == mPollBufferingGeneration) {
-              onPollBuffering();
-          }
-          break;
-      }
-
-      default:
-          Source::onMessageReceived(msg);
-          break;
-    }
-}
-
-void NuPlayer2::GenericSource2::fetchTextData(
-        uint32_t sendWhat,
-        media_track_type type,
-        int32_t curGen,
-        const sp<AnotherPacketSource>& packets,
-        const sp<AMessage>& msg) {
-    int32_t msgGeneration;
-    CHECK(msg->findInt32("generation", &msgGeneration));
-    if (msgGeneration != curGen) {
-        // stale
-        return;
-    }
-
-    int32_t avail;
-    if (packets->hasBufferAvailable(&avail)) {
-        return;
-    }
-
-    int64_t timeUs;
-    CHECK(msg->findInt64("timeUs", &timeUs));
-
-    int64_t subTimeUs = 0;
-    readBuffer(type, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
-
-    status_t eosResult;
-    if (!packets->hasBufferAvailable(&eosResult)) {
-        return;
-    }
-
-    if (msg->what() == kWhatFetchSubtitleData) {
-        subTimeUs -= 1000000ll;  // send subtile data one second earlier
-    }
-    sp<AMessage> msg2 = new AMessage(sendWhat, this);
-    msg2->setInt32("generation", msgGeneration);
-    mMediaClock->addTimer(msg2, subTimeUs);
-}
-
-void NuPlayer2::GenericSource2::sendTextData(
-        uint32_t what,
-        media_track_type type,
-        int32_t curGen,
-        const sp<AnotherPacketSource>& packets,
-        const sp<AMessage>& msg) {
-    int32_t msgGeneration;
-    CHECK(msg->findInt32("generation", &msgGeneration));
-    if (msgGeneration != curGen) {
-        // stale
-        return;
-    }
-
-    int64_t subTimeUs;
-    if (packets->nextBufferTime(&subTimeUs) != OK) {
-        return;
-    }
-
-    int64_t nextSubTimeUs;
-    readBuffer(type, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
-
-    sp<ABuffer> buffer;
-    status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
-    if (dequeueStatus == OK) {
-        sp<AMessage> notify = dupNotify();
-        notify->setInt32("what", what);
-        notify->setBuffer("buffer", buffer);
-        notify->post();
-
-        if (msg->what() == kWhatSendSubtitleData) {
-            nextSubTimeUs -= 1000000ll;  // send subtile data one second earlier
-        }
-        mMediaClock->addTimer(msg, nextSubTimeUs);
-    }
-}
-
-void NuPlayer2::GenericSource2::sendGlobalTextData(
-        uint32_t what,
-        int32_t curGen,
-        sp<AMessage> msg) {
-    int32_t msgGeneration;
-    CHECK(msg->findInt32("generation", &msgGeneration));
-    if (msgGeneration != curGen) {
-        // stale
-        return;
-    }
-
-    void *data = NULL;
-    size_t size = 0;
-    if (mTimedTextTrack.mExtractor->getTrackFormat(mTimedTextTrack.mIndex)->getBuffer(
-                    "text", &data, &size)) {
-        mGlobalTimedText = new ABuffer(size);
-        if (mGlobalTimedText->data()) {
-            memcpy(mGlobalTimedText->data(), data, size);
-            sp<AMessage> globalMeta = mGlobalTimedText->meta();
-            globalMeta->setInt64("timeUs", 0);
-            globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
-            globalMeta->setInt32("global", 1);
-            sp<AMessage> notify = dupNotify();
-            notify->setInt32("what", what);
-            notify->setBuffer("buffer", mGlobalTimedText);
-            notify->post();
-        }
-    }
-}
-
-sp<AMessage> NuPlayer2::GenericSource2::getFormat(bool audio) {
-    Mutex::Autolock _l(mLock);
-    return getFormat_l(audio);
-}
-
-sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
-    Mutex::Autolock _l(mLock);
-    return getFormatMeta_l(audio);
-}
-
-sp<AMessage> NuPlayer2::GenericSource2::getFormat_l(bool audio) {
-    sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
-    size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
-
-    if (extractor == NULL) {
-        return NULL;
-    }
-
-    return extractor->getTrackFormat(trackIndex)->toAMessage();
-}
-
-sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
-    sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
-    size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
-
-    if (extractor == NULL) {
-        return NULL;
-    }
-
-    return convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
-}
-
-status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
-        bool audio, sp<ABuffer> *accessUnit) {
-    Mutex::Autolock _l(mLock);
-    // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
-    // the codec's crypto object has gone away (b/37960096).
-    // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
-    if (!mStarted && mIsDrmReleased) {
-        return -EWOULDBLOCK;
-    }
-
-    Track *track = audio ? &mAudioTrack : &mVideoTrack;
-
-    if (track->mExtractor == NULL) {
-        return -EWOULDBLOCK;
-    }
-
-    status_t finalResult;
-    if (!track->mPackets->hasBufferAvailable(&finalResult)) {
-        if (finalResult == OK) {
-            postReadBuffer(
-                    audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
-            return -EWOULDBLOCK;
-        }
-        return finalResult;
-    }
-
-    status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
-
-    // start pulling in more buffers if cache is running low
-    // so that decoder has less chance of being starved
-    if (!mIsStreaming) {
-        if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
-            postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
-        }
-    } else {
-        int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
-        // TODO: maxRebufferingMarkMs could be larger than
-        // mBufferingSettings.mResumePlaybackMarkMs
-        int64_t restartBufferingMarkUs =
-             mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
-        if (finalResult == OK) {
-            if (durationUs < restartBufferingMarkUs) {
-                postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
-            }
-            if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
-                && !mSentPauseOnBuffering && !mPreparing) {
-                mSentPauseOnBuffering = true;
-                sp<AMessage> notify = dupNotify();
-                notify->setInt32("what", kWhatPauseOnBufferingStart);
-                notify->post();
-            }
-        }
-    }
-
-    if (result != OK) {
-        if (mSubtitleTrack.mExtractor != NULL) {
-            mSubtitleTrack.mPackets->clear();
-            mFetchSubtitleDataGeneration++;
-        }
-        if (mTimedTextTrack.mExtractor != NULL) {
-            mTimedTextTrack.mPackets->clear();
-            mFetchTimedTextDataGeneration++;
-        }
-        return result;
-    }
-
-    int64_t timeUs;
-    status_t eosResult; // ignored
-    CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
-    if (audio) {
-        mAudioLastDequeueTimeUs = timeUs;
-    } else {
-        mVideoLastDequeueTimeUs = timeUs;
-    }
-
-    if (mSubtitleTrack.mExtractor != NULL
-            && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
-        sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
-        msg->setInt64("timeUs", timeUs);
-        msg->setInt32("generation", mFetchSubtitleDataGeneration);
-        msg->post();
-    }
-
-    if (mTimedTextTrack.mExtractor != NULL
-            && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
-        sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
-        msg->setInt64("timeUs", timeUs);
-        msg->setInt32("generation", mFetchTimedTextDataGeneration);
-        msg->post();
-    }
-
-    return result;
-}
-
-status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
-    Mutex::Autolock _l(mLock);
-    *durationUs = mDurationUs;
-    return OK;
-}
-
-size_t NuPlayer2::GenericSource2::getTrackCount() const {
-    Mutex::Autolock _l(mLock);
-    return mExtractors.size();
-}
-
-sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
-    Mutex::Autolock _l(mLock);
-    size_t trackCount = mExtractors.size();
-    if (trackIndex >= trackCount) {
-        return NULL;
-    }
-
-    sp<AMessage> format = mExtractors.itemAt(trackIndex)->getTrackFormat(trackIndex)->toAMessage();
-    if (format == NULL) {
-        ALOGE("no metadata for track %zu", trackIndex);
-        return NULL;
-    }
-
-    AString mime;
-    CHECK(format->findString(AMEDIAFORMAT_KEY_MIME, &mime));
-
-    int32_t trackType;
-    if (!strncasecmp(mime.c_str(), "video/", 6)) {
-        trackType = MEDIA_TRACK_TYPE_VIDEO;
-    } else if (!strncasecmp(mime.c_str(), "audio/", 6)) {
-        trackType = MEDIA_TRACK_TYPE_AUDIO;
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP)) {
-        trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
-    } else {
-        trackType = MEDIA_TRACK_TYPE_UNKNOWN;
-    }
-    format->setInt32("type", trackType);
-
-    AString lang;
-    if (!format->findString("language", &lang)) {
-        format->setString("language", "und");
-    }
-
-    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-        int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
-        format->findInt32(AMEDIAFORMAT_KEY_IS_AUTOSELECT, &isAutoselect);
-        format->findInt32(AMEDIAFORMAT_KEY_IS_DEFAULT, &isDefault);
-        format->findInt32(AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE, &isForced);
-
-        format->setInt32("auto", !!isAutoselect);
-        format->setInt32("default", !!isDefault);
-        format->setInt32("forced", !!isForced);
-    }
-
-    return format;
-}
-
-ssize_t NuPlayer2::GenericSource2::getSelectedTrack(media_track_type type) const {
-    Mutex::Autolock _l(mLock);
-    const Track *track = NULL;
-    switch (type) {
-    case MEDIA_TRACK_TYPE_VIDEO:
-        track = &mVideoTrack;
-        break;
-    case MEDIA_TRACK_TYPE_AUDIO:
-        track = &mAudioTrack;
-        break;
-    case MEDIA_TRACK_TYPE_TIMEDTEXT:
-        track = &mTimedTextTrack;
-        break;
-    case MEDIA_TRACK_TYPE_SUBTITLE:
-        track = &mSubtitleTrack;
-        break;
-    default:
-        break;
-    }
-
-    if (track != NULL && track->mExtractor != NULL) {
-        return track->mIndex;
-    }
-
-    return -1;
-}
-
-status_t NuPlayer2::GenericSource2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
-
-    if (trackIndex >= mExtractors.size()) {
-        return BAD_INDEX;
-    }
-
-    if (!select) {
-        Track* track = NULL;
-        if (mSubtitleTrack.mExtractor != NULL && trackIndex == mSubtitleTrack.mIndex) {
-            track = &mSubtitleTrack;
-            mFetchSubtitleDataGeneration++;
-        } else if (mTimedTextTrack.mExtractor != NULL && trackIndex == mTimedTextTrack.mIndex) {
-            track = &mTimedTextTrack;
-            mFetchTimedTextDataGeneration++;
-        }
-        if (track == NULL) {
-            return INVALID_OPERATION;
-        }
-        track->mExtractor = NULL;
-        track->mPackets->clear();
-        return OK;
-    }
-
-    const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
-    sp<MetaData> meta = convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
-    const char *mime;
-    CHECK(meta->findCString(kKeyMIMEType, &mime));
-    if (!strncasecmp(mime, "text/", 5)) {
-        bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
-        Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
-        if (track->mExtractor != NULL && track->mIndex == trackIndex) {
-            return OK;
-        }
-        track->mIndex = trackIndex;
-        track->mExtractor = mExtractors.itemAt(trackIndex);
-        track->mExtractor->selectSingleTrack(trackIndex);
-        if (track->mPackets == NULL) {
-            track->mPackets = new AnotherPacketSource(meta);
-        } else {
-            track->mPackets->clear();
-            track->mPackets->setFormat(meta);
-
-        }
-
-        if (isSubtitle) {
-            mFetchSubtitleDataGeneration++;
-        } else {
-            mFetchTimedTextDataGeneration++;
-        }
-
-        status_t eosResult; // ignored
-        if (mSubtitleTrack.mExtractor != NULL
-                && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
-            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
-            msg->setInt64("timeUs", timeUs);
-            msg->setInt32("generation", mFetchSubtitleDataGeneration);
-            msg->post();
-        }
-
-        sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
-        msg2->setInt32("generation", mFetchTimedTextDataGeneration);
-        msg2->post();
-
-        if (mTimedTextTrack.mExtractor != NULL
-                && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
-            sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
-            msg->setInt64("timeUs", timeUs);
-            msg->setInt32("generation", mFetchTimedTextDataGeneration);
-            msg->post();
-        }
-
-        return OK;
-    } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
-        bool audio = !strncasecmp(mime, "audio/", 6);
-        Track *track = audio ? &mAudioTrack : &mVideoTrack;
-        if (track->mExtractor != NULL && track->mIndex == trackIndex) {
-            return OK;
-        }
-
-        sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
-        msg->setInt32("trackIndex", trackIndex);
-        msg->post();
-        return OK;
-    }
-
-    return INVALID_OPERATION;
-}
-
-status_t NuPlayer2::GenericSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
-    ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
-    sp<AMessage> msg = new AMessage(kWhatSeek, this);
-    msg->setInt64("seekTimeUs", seekTimeUs);
-    msg->setInt32("mode", mode);
-
-    // Need to call readBuffer on |mLooper| to ensure the calls to
-    // IMediaSource::read* are serialized. Note that IMediaSource::read*
-    // is called without |mLock| acquired and MediaSource is not thread safe.
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-
-    return err;
-}
-
-void NuPlayer2::GenericSource2::onSeek(const sp<AMessage>& msg) {
-    int64_t seekTimeUs;
-    int32_t mode;
-    CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
-    CHECK(msg->findInt32("mode", &mode));
-
-    sp<AMessage> response = new AMessage;
-    status_t err = doSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
-    response->setInt32("err", err);
-
-    sp<AReplyToken> replyID;
-    CHECK(msg->senderAwaitsResponse(&replyID));
-    response->postReply(replyID);
-}
-
-status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
-    if (mVideoTrack.mExtractor != NULL) {
-        ++mVideoDataGeneration;
-
-        int64_t actualTimeUs;
-        readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
-
-        if (mode != MediaPlayer2SeekMode::SEEK_CLOSEST) {
-            seekTimeUs = actualTimeUs;
-        }
-        mVideoLastDequeueTimeUs = actualTimeUs;
-    }
-
-    if (mAudioTrack.mExtractor != NULL) {
-        ++mAudioDataGeneration;
-        readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
-        mAudioLastDequeueTimeUs = seekTimeUs;
-    }
-
-    if (mSubtitleTrack.mExtractor != NULL) {
-        mSubtitleTrack.mPackets->clear();
-        mFetchSubtitleDataGeneration++;
-    }
-
-    if (mTimedTextTrack.mExtractor != NULL) {
-        mTimedTextTrack.mPackets->clear();
-        mFetchTimedTextDataGeneration++;
-    }
-
-    ++mPollBufferingGeneration;
-    schedulePollBuffering();
-    return OK;
-}
-
-sp<ABuffer> NuPlayer2::GenericSource2::mediaBufferToABuffer(
-        MediaBufferBase* mb,
-        media_track_type trackType) {
-    bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
-    size_t outLength = mb->range_length();
-
-    if (audio && mAudioIsVorbis) {
-        outLength += sizeof(int32_t);
-    }
-
-    sp<ABuffer> ab;
-
-    if (mIsDrmProtected)   {
-        // Modular DRM
-        // Enabled for both video/audio so 1) media buffer is reused without extra copying
-        // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
-
-        // data is already provided in the buffer
-        ab = new ABuffer(NULL, mb->range_length());
-        ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
-
-        // Modular DRM: Required b/c of the above add_ref.
-        // If ref>0, there must be an observer, or it'll crash at release().
-        // TODO: MediaBuffer might need to be revised to ease such need.
-        mb->setObserver(this);
-        // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
-        // Extra increment (since we want to keep mb alive and attached to ab beyond this function
-        // call. This is to counter the effect of mb->release() towards the end.
-        mb->add_ref();
-
-    } else {
-        ab = new ABuffer(outLength);
-        memcpy(ab->data(),
-               (const uint8_t *)mb->data() + mb->range_offset(),
-               mb->range_length());
-    }
-
-    if (audio && mAudioIsVorbis) {
-        int32_t numPageSamples;
-        if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
-            numPageSamples = -1;
-        }
-
-        uint8_t* abEnd = ab->data() + mb->range_length();
-        memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
-    }
-
-    sp<AMessage> meta = ab->meta();
-
-    int64_t timeUs;
-    CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
-    meta->setInt64("timeUs", timeUs);
-
-    if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
-        int32_t layerId;
-        if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
-            meta->setInt32("temporal-layer-id", layerId);
-        }
-    }
-
-    if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
-        AString mime;
-        sp<AMediaExtractorWrapper> extractor = mTimedTextTrack.mExtractor;
-        size_t trackIndex = mTimedTextTrack.mIndex;
-        CHECK(extractor != NULL
-                && extractor->getTrackFormat(trackIndex)->getString(AMEDIAFORMAT_KEY_MIME, &mime));
-        meta->setString("mime", mime.c_str());
-    }
-
-    int64_t durationUs;
-    if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64("durationUs", durationUs);
-    }
-
-    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-        meta->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, mSubtitleTrack.mIndex);
-    }
-
-    uint32_t dataType; // unused
-    const void *seiData;
-    size_t seiLength;
-    if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
-        sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
-        meta->setBuffer("sei", sei);
-    }
-
-    const void *mpegUserDataPointer;
-    size_t mpegUserDataLength;
-    if (mb->meta_data().findData(
-            kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
-        sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
-        meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
-    }
-
-    mb->release();
-    mb = NULL;
-
-    return ab;
-}
-
-int32_t NuPlayer2::GenericSource2::getDataGeneration(media_track_type type) const {
-    int32_t generation = -1;
-    switch (type) {
-    case MEDIA_TRACK_TYPE_VIDEO:
-        generation = mVideoDataGeneration;
-        break;
-    case MEDIA_TRACK_TYPE_AUDIO:
-        generation = mAudioDataGeneration;
-        break;
-    case MEDIA_TRACK_TYPE_TIMEDTEXT:
-        generation = mFetchTimedTextDataGeneration;
-        break;
-    case MEDIA_TRACK_TYPE_SUBTITLE:
-        generation = mFetchSubtitleDataGeneration;
-        break;
-    default:
-        break;
-    }
-
-    return generation;
-}
-
-void NuPlayer2::GenericSource2::postReadBuffer(media_track_type trackType) {
-    if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
-        mPendingReadBufferTypes |= (1 << trackType);
-        sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
-        msg->setInt32("trackType", trackType);
-        msg->post();
-    }
-}
-
-void NuPlayer2::GenericSource2::onReadBuffer(const sp<AMessage>& msg) {
-    int32_t tmpType;
-    CHECK(msg->findInt32("trackType", &tmpType));
-    media_track_type trackType = (media_track_type)tmpType;
-    mPendingReadBufferTypes &= ~(1 << trackType);
-    readBuffer(trackType);
-}
-
-void NuPlayer2::GenericSource2::readBuffer(
-        media_track_type trackType, int64_t seekTimeUs, MediaPlayer2SeekMode mode,
-        int64_t *actualTimeUs, bool formatChange) {
-    Track *track;
-    size_t maxBuffers = 1;
-    switch (trackType) {
-        case MEDIA_TRACK_TYPE_VIDEO:
-            track = &mVideoTrack;
-            maxBuffers = 8;  // too large of a number may influence seeks
-            break;
-        case MEDIA_TRACK_TYPE_AUDIO:
-            track = &mAudioTrack;
-            maxBuffers = 64;
-            break;
-        case MEDIA_TRACK_TYPE_SUBTITLE:
-            track = &mSubtitleTrack;
-            break;
-        case MEDIA_TRACK_TYPE_TIMEDTEXT:
-            track = &mTimedTextTrack;
-            break;
-        default:
-            TRESPASS();
-    }
-
-    if (track->mExtractor == NULL) {
-        return;
-    }
-
-    if (actualTimeUs) {
-        *actualTimeUs = seekTimeUs;
-    }
-
-
-    bool seeking = false;
-    sp<AMediaExtractorWrapper> extractor = track->mExtractor;
-    if (seekTimeUs >= 0) {
-        extractor->seekTo(seekTimeUs, mode);
-        seeking = true;
-    }
-
-    int32_t generation = getDataGeneration(trackType);
-    for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
-        Vector<sp<ABuffer> > aBuffers;
-
-        mLock.unlock();
-
-        sp<AMediaFormatWrapper> format;
-        ssize_t sampleSize = -1;
-        status_t err = extractor->getSampleFormat(format);
-        if (err == OK) {
-            sampleSize = extractor->getSampleSize();
-        }
-
-        if (err != OK || sampleSize < 0) {
-            mLock.lock();
-            track->mPackets->signalEOS(err != OK ? err : ERROR_END_OF_STREAM);
-            break;
-        }
-
-        sp<ABuffer> abuf = new ABuffer(sampleSize);
-        sampleSize = extractor->readSampleData(abuf);
-        mLock.lock();
-
-        // in case track has been changed since we don't have lock for some time.
-        if (generation != getDataGeneration(trackType)) {
-            break;
-        }
-
-        int64_t timeUs = extractor->getSampleTime();
-        if (timeUs < 0) {
-            track->mPackets->signalEOS(ERROR_MALFORMED);
-            break;
-        }
-
-        sp<AMessage> meta = abuf->meta();
-        format->writeToAMessage(meta);
-        meta->setInt64("timeUs", timeUs);
-        if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
-            mAudioTimeUs = timeUs;
-        } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
-            mVideoTimeUs = timeUs;
-        }
-
-        sp<AMediaCodecCryptoInfoWrapper> cryptInfo = extractor->getSampleCryptoInfo();
-        if (cryptInfo != NULL) {
-            meta->setObject("cryptInfo", cryptInfo);
-        }
-
-        queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
-
-        if (numBuffers == 0 && actualTimeUs != nullptr) {
-            *actualTimeUs = timeUs;
-        }
-        if (seeking) {
-            if (meta != nullptr && mode == MediaPlayer2SeekMode::SEEK_CLOSEST
-                    && seekTimeUs > timeUs) {
-                sp<AMessage> extra = new AMessage;
-                extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
-                meta->setMessage("extra", extra);
-            }
-        }
-
-        track->mPackets->queueAccessUnit(abuf);
-        formatChange = false;
-        seeking = false;
-        ++numBuffers;
-        extractor->advance();
-
-    }
-
-    if (mIsStreaming
-        && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
-        status_t finalResult;
-        int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
-
-        // TODO: maxRebufferingMarkMs could be larger than
-        // mBufferingSettings.mResumePlaybackMarkMs
-        int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
-            : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
-        if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
-            if (mPreparing || mSentPauseOnBuffering) {
-                Track *counterTrack =
-                    (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
-                if (counterTrack->mExtractor != NULL) {
-                    durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
-                }
-                if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
-                    if (mPreparing) {
-                        notifyPrepared();
-                        mPreparing = false;
-                    } else {
-                        mSentPauseOnBuffering = false;
-                        sp<AMessage> notify = dupNotify();
-                        notify->setInt32("what", kWhatResumeOnBufferingEnd);
-                        notify->post();
-                    }
-                }
-            }
-            return;
-        }
-
-        postReadBuffer(trackType);
-    }
-}
-
-void NuPlayer2::GenericSource2::queueDiscontinuityIfNeeded(
-        bool seeking, bool formatChange, media_track_type trackType, Track *track) {
-    // formatChange && seeking: track whose source is changed during selection
-    // formatChange && !seeking: track whose source is not changed during selection
-    // !formatChange: normal seek
-    if ((seeking || formatChange)
-            && (trackType == MEDIA_TRACK_TYPE_AUDIO
-            || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
-        ATSParser::DiscontinuityType type = (formatChange && seeking)
-                ? ATSParser::DISCONTINUITY_FORMATCHANGE
-                : ATSParser::DISCONTINUITY_NONE;
-        track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
-    }
-}
-
-void NuPlayer2::GenericSource2::notifyBufferingUpdate(int32_t percentage) {
-    // Buffering percent could go backward as it's estimated from remaining
-    // data and last access time. This could cause the buffering position
-    // drawn on media control to jitter slightly. Remember previously reported
-    // percentage and don't allow it to go backward.
-    if (percentage < mPrevBufferPercentage) {
-        percentage = mPrevBufferPercentage;
-    } else if (percentage > 100) {
-        percentage = 100;
-    }
-
-    mPrevBufferPercentage = percentage;
-
-    ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
-
-    sp<AMessage> notify = dupNotify();
-    notify->setInt32("what", kWhatBufferingUpdate);
-    notify->setInt32("percentage", percentage);
-    notify->post();
-}
-
-void NuPlayer2::GenericSource2::schedulePollBuffering() {
-    if (mIsStreaming) {
-        sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
-        msg->setInt32("generation", mPollBufferingGeneration);
-        // Enquires buffering status every second.
-        msg->post(1000000ll);
-    }
-}
-
-void NuPlayer2::GenericSource2::onPollBuffering() {
-    int64_t cachedDurationUs = -1ll;
-
-    sp<AMediaExtractorWrapper> extractor;
-    if (mVideoTrack.mExtractor != NULL) {
-        extractor = mVideoTrack.mExtractor;
-    } else if (mAudioTrack.mExtractor != NULL) {
-        extractor = mAudioTrack.mExtractor;
-    }
-
-    if (extractor != NULL) {
-        cachedDurationUs = extractor->getCachedDuration();
-    }
-
-    if (cachedDurationUs >= 0ll) {
-        ssize_t sampleSize = extractor->getSampleSize();
-        if (sampleSize >= 0ll) {
-            int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
-            int percentage = 100.0 * cachedPosUs / mDurationUs;
-            if (percentage > 100) {
-                percentage = 100;
-            }
-
-            notifyBufferingUpdate(percentage);
-            ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
-        } else {
-            notifyBufferingUpdate(100);
-            ALOGV("onPollBuffering: EOS");
-        }
-    }
-
-    schedulePollBuffering();
-}
-
-// Modular DRM
-status_t NuPlayer2::GenericSource2::prepareDrm(
-        const uint8_t uuid[16],
-        const Vector<uint8_t> &drmSessionId,
-        sp<AMediaCryptoWrapper> *outCrypto) {
-    Mutex::Autolock _l(mLock);
-    ALOGV("prepareDrm");
-
-    mIsDrmProtected = false;
-    mIsDrmReleased = false;
-    mIsSecure = false;
-
-    status_t status = OK;
-    sp<AMediaCryptoWrapper> crypto =
-        new AMediaCryptoWrapper(uuid, drmSessionId.array(), drmSessionId.size());
-    if (crypto == NULL) {
-        ALOGE("prepareDrm: failed to create crypto.");
-        return UNKNOWN_ERROR;
-    }
-    ALOGV("prepareDrm: crypto created for uuid: %s",
-            DrmUUID::toHexString(uuid).string());
-
-    *outCrypto = crypto;
-    // as long a there is an active crypto
-    mIsDrmProtected = true;
-
-    if (mMimes.size() == 0) {
-        status = UNKNOWN_ERROR;
-        ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
-        return status;
-    }
-
-    // first mime in this list is either the video track, or the first audio track
-    const char *mime = mMimes[0].string();
-    mIsSecure = crypto->requiresSecureDecoderComponent(mime);
-    ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s  isSecure: %d",
-            mime, mIsSecure);
-
-    // Checking the member flags while in the looper to send out the notification.
-    // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
-    notifyFlagsChanged(
-            (mIsSecure ? FLAG_SECURE : 0) |
-            // Setting "protected screen" only for L1: b/38390836
-            (mIsSecure ? FLAG_PROTECTED : 0) |
-            FLAG_CAN_PAUSE |
-            FLAG_CAN_SEEK_BACKWARD |
-            FLAG_CAN_SEEK_FORWARD |
-            FLAG_CAN_SEEK);
-
-    if (status == OK) {
-        ALOGV("prepareDrm: mCrypto: %p", outCrypto->get());
-        ALOGD("prepareDrm ret: %d ", status);
-    } else {
-        ALOGE("prepareDrm err: %d", status);
-    }
-    return status;
-}
-
-status_t NuPlayer2::GenericSource2::releaseDrm() {
-    Mutex::Autolock _l(mLock);
-    ALOGV("releaseDrm");
-
-    if (mIsDrmProtected) {
-        mIsDrmProtected = false;
-        // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
-        mIsDrmReleased = true;
-        ALOGV("releaseDrm: mIsDrmProtected is reset.");
-    } else {
-        ALOGE("releaseDrm: mIsDrmProtected is already false.");
-    }
-
-    return OK;
-}
-
-status_t NuPlayer2::GenericSource2::checkDrmInfo()
-{
-    // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
-    // same source without being reset (called by prepareAsync/initFromDataSource)
-    mIsDrmReleased = false;
-
-    if (mExtractor == NULL) {
-        ALOGV("checkDrmInfo: No extractor");
-        return OK; // letting the caller responds accordingly
-    }
-
-    PsshInfo *psshInfo = mExtractor->getPsshInfo();
-    if (psshInfo == NULL) {
-        ALOGV("checkDrmInfo: No PSSH");
-        return OK; // source without DRM info
-    }
-
-    PlayerMessage playerMsg;
-    status_t ret = NuPlayer2Drm::retrieveDrmInfo(psshInfo, &playerMsg);
-    ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH drm info size: %d", (int)playerMsg.ByteSize());
-
-    if (ret != OK) {
-        ALOGE("checkDrmInfo: failed to retrive DrmInfo %d", ret);
-        return UNKNOWN_ERROR;
-    }
-
-    int size = playerMsg.ByteSize();
-    sp<ABuffer> drmInfoBuf = new ABuffer(size);
-    playerMsg.SerializeToArray(drmInfoBuf->data(), size);
-    drmInfoBuf->setRange(0, size);
-    notifyDrmInfo(drmInfoBuf);
-
-    return OK;
-}
-
-void NuPlayer2::GenericSource2::signalBufferReturned(MediaBufferBase *buffer)
-{
-    //ALOGV("signalBufferReturned %p  refCount: %d", buffer, buffer->localRefcount());
-
-    buffer->setObserver(NULL);
-    buffer->release(); // this leads to delete since that there is no observor
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.h b/media/libmediaplayer2/nuplayer2/GenericSource2.h
deleted file mode 100644
index ade1aa3..0000000
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2017 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 GENERIC_SOURCE2_H_
-
-#define GENERIC_SOURCE2_H_
-
-#include "NuPlayer2.h"
-#include "NuPlayer2Source.h"
-
-#include "ATSParser.h"
-
-#include <media/stagefright/MediaBuffer.h>
-#include <mediaplayer2/mediaplayer2.h>
-#include <media/NdkMediaDataSource.h>
-#include <media/NdkMediaExtractor.h>
-#include <media/NdkWrapper.h>
-
-namespace android {
-
-class DecryptHandle;
-struct AnotherPacketSource;
-struct ARTSPController;
-class DataSource;
-class IDataSource;
-class IMediaSource;
-struct MediaSource;
-class MediaBuffer;
-struct MediaClock;
-
-struct NuPlayer2::GenericSource2 : public NuPlayer2::Source,
-                                   public MediaBufferObserver // Modular DRM
-{
-    GenericSource2(const sp<AMessage> &notify, uid_t uid,
-                   const sp<MediaClock> &mediaClock);
-
-    status_t setDataSource(
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    status_t setDataSource(int fd, int64_t offset, int64_t length);
-
-    status_t setDataSource(const sp<DataSource>& dataSource);
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) override;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
-    virtual void prepareAsync(int64_t startTimeUs);
-
-    virtual void start();
-    virtual void stop();
-    virtual void pause();
-    virtual void resume();
-
-    virtual void disconnect();
-
-    virtual status_t feedMoreTSData();
-
-    virtual sp<MetaData> getFileFormatMeta() const;
-
-    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
-
-    virtual status_t getDuration(int64_t *durationUs);
-    virtual size_t getTrackCount() const;
-    virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
-    virtual ssize_t getSelectedTrack(media_track_type type) const;
-    virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
-    virtual status_t seekTo(
-        int64_t seekTimeUs,
-        MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
-
-    virtual bool isStreaming() const;
-
-    // Modular DRM
-    virtual void signalBufferReturned(MediaBufferBase *buffer);
-
-    virtual status_t prepareDrm(
-            const uint8_t uuid[16],
-            const Vector<uint8_t> &drmSessionId,
-            sp<AMediaCryptoWrapper> *outCrypto);
-
-    virtual status_t releaseDrm();
-
-
-protected:
-    virtual ~GenericSource2();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    virtual sp<AMessage> getFormat(bool audio);
-    virtual sp<MetaData> getFormatMeta(bool audio);
-
-private:
-    enum {
-        kWhatPrepareAsync,
-        kWhatFetchSubtitleData,
-        kWhatFetchTimedTextData,
-        kWhatSendSubtitleData,
-        kWhatSendGlobalTimedTextData,
-        kWhatSendTimedTextData,
-        kWhatChangeAVSource,
-        kWhatPollBuffering,
-        kWhatSeek,
-        kWhatReadBuffer,
-        kWhatStart,
-        kWhatResume,
-        kWhatSecureDecodersInstantiated,
-    };
-
-    struct Track {
-        size_t mIndex;
-        sp<AMediaExtractorWrapper> mExtractor;
-        sp<AnotherPacketSource> mPackets;
-    };
-
-    int64_t mAudioTimeUs;
-    int64_t mAudioLastDequeueTimeUs;
-    int64_t mVideoTimeUs;
-    int64_t mVideoLastDequeueTimeUs;
-
-    BufferingSettings mBufferingSettings;
-    int32_t mPrevBufferPercentage;
-    int32_t mPollBufferingGeneration;
-    bool mSentPauseOnBuffering;
-
-    int32_t mAudioDataGeneration;
-    int32_t mVideoDataGeneration;
-    int32_t mFetchSubtitleDataGeneration;
-    int32_t mFetchTimedTextDataGeneration;
-    int64_t mDurationUs;
-    bool mAudioIsVorbis;
-    // Secure codec is required.
-    bool mIsSecure;
-    bool mIsStreaming;
-    uid_t mUID;
-    const sp<MediaClock> mMediaClock;
-    AString mUri;
-    KeyedVector<String8, String8> mUriHeaders;
-    int mFd;
-    int64_t mOffset;
-    int64_t mLength;
-
-    bool mDisconnected;
-    sp<MetaData> mFileMeta;
-    sp<AMediaDataSourceWrapper> mDataSourceWrapper;
-    sp<AMediaExtractorWrapper> mExtractor;
-    Vector<sp<AMediaExtractorWrapper> > mExtractors;
-    bool mStarted;
-    bool mPreparing;
-    int64_t mBitrate;
-    uint32_t mPendingReadBufferTypes;
-    sp<ABuffer> mGlobalTimedText;
-
-    Track mVideoTrack;
-    Track mAudioTrack;
-    Track mSubtitleTrack;
-    Track mTimedTextTrack;
-
-    mutable Mutex mLock;
-
-    sp<ALooper> mLooper;
-
-    void resetDataSource();
-
-    status_t initFromDataSource();
-    int64_t getLastReadPosition();
-
-    void notifyPreparedAndCleanup(status_t err);
-    void onSecureDecodersInstantiated(status_t err);
-    void finishPrepareAsync();
-    status_t startSources();
-
-    void onSeek(const sp<AMessage>& msg);
-    status_t doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode);
-
-    void onPrepareAsync(int64_t startTimeUs);
-
-    void fetchTextData(
-            uint32_t what, media_track_type type,
-            int32_t curGen, const sp<AnotherPacketSource>& packets, const sp<AMessage>& msg);
-
-    void sendGlobalTextData(
-            uint32_t what,
-            int32_t curGen, sp<AMessage> msg);
-
-    void sendTextData(
-            uint32_t what, media_track_type type,
-            int32_t curGen, const sp<AnotherPacketSource>& packets, const sp<AMessage>& msg);
-
-    sp<ABuffer> mediaBufferToABuffer(
-            MediaBufferBase *mbuf,
-            media_track_type trackType);
-
-    void postReadBuffer(media_track_type trackType);
-    void onReadBuffer(const sp<AMessage>& msg);
-    // When |mode| is MediaPlayer2SeekMode::SEEK_CLOSEST, the buffer read shall
-    // include an item indicating skipping rendering all buffers with timestamp
-    // earlier than |seekTimeUs|.
-    // For other modes, the buffer read will not include the item as above in order
-    // to facilitate fast seek operation.
-    void readBuffer(
-            media_track_type trackType,
-            int64_t seekTimeUs = -1ll,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC,
-            int64_t *actualTimeUs = NULL, bool formatChange = false);
-
-    void queueDiscontinuityIfNeeded(
-            bool seeking, bool formatChange, media_track_type trackType, Track *track);
-
-    void schedulePollBuffering();
-    void onPollBuffering();
-    void notifyBufferingUpdate(int32_t percentage);
-
-    sp<AMessage> getFormat_l(bool audio);
-    sp<MetaData> getFormatMeta_l(bool audio);
-    int32_t getDataGeneration(media_track_type type) const;
-
-    // Modular DRM
-    // The source is DRM protected and is prepared for DRM.
-    bool mIsDrmProtected;
-    // releaseDrm has been processed.
-    bool mIsDrmReleased;
-    Vector<String8> mMimes;
-
-    status_t checkDrmInfo();
-
-    DISALLOW_EVIL_CONSTRUCTORS(GenericSource2);
-};
-
-}  // namespace android
-
-#endif  // GENERIC_SOURCE2_H_
diff --git a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
deleted file mode 100644
index e53900b..0000000
--- a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright 2017 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 "HTTPLiveSource2"
-#include <utils/Log.h>
-
-#include "HTTPLiveSource2.h"
-
-#include "AnotherPacketSource.h"
-#include "LiveDataSource.h"
-
-#include <media/MediaHTTPService.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/Utils.h>
-
-// default buffer prepare/ready/underflow marks
-static const int kReadyMarkMs     = 5000;  // 5 seconds
-static const int kPrepareMarkMs   = 1500;  // 1.5 seconds
-
-namespace android {
-
-NuPlayer2::HTTPLiveSource2::HTTPLiveSource2(
-        const sp<AMessage> &notify,
-        const sp<MediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers)
-    : Source(notify),
-      mHTTPService(httpService),
-      mURL(url),
-      mFlags(0),
-      mFinalResult(OK),
-      mOffset(0),
-      mFetchSubtitleDataGeneration(0),
-      mFetchMetaDataGeneration(0),
-      mHasMetadata(false),
-      mMetadataSelected(false) {
-    mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
-    mBufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
-    if (headers) {
-        mExtraHeaders = *headers;
-
-        ssize_t index =
-            mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
-
-        if (index >= 0) {
-            mFlags |= kFlagIncognito;
-
-            mExtraHeaders.removeItemsAt(index);
-        }
-    }
-}
-
-NuPlayer2::HTTPLiveSource2::~HTTPLiveSource2() {
-    if (mLiveSession != NULL) {
-        mLiveSession->disconnect();
-
-        mLiveLooper->unregisterHandler(mLiveSession->id());
-        mLiveLooper->unregisterHandler(id());
-        mLiveLooper->stop();
-
-        mLiveSession.clear();
-        mLiveLooper.clear();
-    }
-}
-
-status_t NuPlayer2::HTTPLiveSource2::getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) {
-    *buffering = mBufferingSettings;
-
-    return OK;
-}
-
-status_t NuPlayer2::HTTPLiveSource2::setBufferingSettings(const BufferingSettings& buffering) {
-    mBufferingSettings = buffering;
-
-    if (mLiveSession != NULL) {
-        mLiveSession->setBufferingSettings(mBufferingSettings);
-    }
-
-    return OK;
-}
-
-// TODO: fetch data starting from |startTimeUs|
-void NuPlayer2::HTTPLiveSource2::prepareAsync(int64_t /* startTimeUs */) {
-    if (mLiveLooper == NULL) {
-        mLiveLooper = new ALooper;
-        mLiveLooper->setName("http live2");
-        mLiveLooper->start(false, /* runOnCallingThread */
-                           true /* canCallJava */);
-
-        mLiveLooper->registerHandler(this);
-    }
-
-    sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
-
-    mLiveSession = new LiveSession(
-            notify,
-            (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
-            mHTTPService);
-
-    mLiveLooper->registerHandler(mLiveSession);
-
-    mLiveSession->setBufferingSettings(mBufferingSettings);
-    mLiveSession->connectAsync(
-            mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
-}
-
-void NuPlayer2::HTTPLiveSource2::start() {
-}
-
-sp<MetaData> NuPlayer2::HTTPLiveSource2::getFormatMeta(bool audio) {
-    sp<MetaData> meta;
-    if (mLiveSession != NULL) {
-        mLiveSession->getStreamFormatMeta(
-                audio ? LiveSession::STREAMTYPE_AUDIO
-                      : LiveSession::STREAMTYPE_VIDEO,
-                &meta);
-    }
-
-    return meta;
-}
-
-sp<AMessage> NuPlayer2::HTTPLiveSource2::getFormat(bool audio) {
-    sp<MetaData> meta;
-    status_t err = -EWOULDBLOCK;
-    if (mLiveSession != NULL) {
-        err = mLiveSession->getStreamFormatMeta(
-                audio ? LiveSession::STREAMTYPE_AUDIO
-                      : LiveSession::STREAMTYPE_VIDEO,
-                &meta);
-    }
-
-    sp<AMessage> format;
-    if (err == -EWOULDBLOCK) {
-        format = new AMessage();
-        format->setInt32("err", err);
-        return format;
-    }
-
-    if (err != OK || convertMetaDataToMessage(meta, &format) != OK) {
-        return NULL;
-    }
-    return format;
-}
-
-status_t NuPlayer2::HTTPLiveSource2::feedMoreTSData() {
-    return OK;
-}
-
-status_t NuPlayer2::HTTPLiveSource2::dequeueAccessUnit(
-        bool audio, sp<ABuffer> *accessUnit) {
-    return mLiveSession->dequeueAccessUnit(
-            audio ? LiveSession::STREAMTYPE_AUDIO
-                  : LiveSession::STREAMTYPE_VIDEO,
-            accessUnit);
-}
-
-status_t NuPlayer2::HTTPLiveSource2::getDuration(int64_t *durationUs) {
-    return mLiveSession->getDuration(durationUs);
-}
-
-size_t NuPlayer2::HTTPLiveSource2::getTrackCount() const {
-    return mLiveSession->getTrackCount();
-}
-
-sp<AMessage> NuPlayer2::HTTPLiveSource2::getTrackInfo(size_t trackIndex) const {
-    return mLiveSession->getTrackInfo(trackIndex);
-}
-
-ssize_t NuPlayer2::HTTPLiveSource2::getSelectedTrack(media_track_type type) const {
-    if (mLiveSession == NULL) {
-        return -1;
-    } else if (type == MEDIA_TRACK_TYPE_METADATA) {
-        // MEDIA_TRACK_TYPE_METADATA is always last track
-        // mMetadataSelected can only be true when mHasMetadata is true
-        return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
-    } else {
-        return mLiveSession->getSelectedTrack(type);
-    }
-}
-
-status_t NuPlayer2::HTTPLiveSource2::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
-    if (mLiveSession == NULL) {
-        return INVALID_OPERATION;
-    }
-
-    status_t err = INVALID_OPERATION;
-    bool postFetchMsg = false, isSub = false;
-    if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
-        err = mLiveSession->selectTrack(trackIndex, select);
-        postFetchMsg = select;
-        isSub = true;
-    } else {
-        // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
-        if (mMetadataSelected && !select) {
-            err = OK;
-        } else if (!mMetadataSelected && select) {
-            postFetchMsg = true;
-            err = OK;
-        } else {
-            err = BAD_VALUE; // behave as LiveSession::selectTrack
-        }
-
-        mMetadataSelected = select;
-    }
-
-    if (err == OK) {
-        int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
-        generation++;
-        if (postFetchMsg) {
-            int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
-            sp<AMessage> msg = new AMessage(what, this);
-            msg->setInt32("generation", generation);
-            msg->post();
-        }
-    }
-
-    // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
-    // selected track, or unselecting a non-selected track. In this case it's an
-    // no-op so we return OK.
-    return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
-}
-
-status_t NuPlayer2::HTTPLiveSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
-    if (mLiveSession->isSeekable()) {
-        return mLiveSession->seekTo(seekTimeUs, mode);
-    } else {
-        return INVALID_OPERATION;
-    }
-}
-
-void NuPlayer2::HTTPLiveSource2::pollForRawData(
-        const sp<AMessage> &msg, int32_t currentGeneration,
-        LiveSession::StreamType fetchType, int32_t pushWhat) {
-
-    int32_t generation;
-    CHECK(msg->findInt32("generation", &generation));
-
-    if (generation != currentGeneration) {
-        return;
-    }
-
-    sp<ABuffer> buffer;
-    while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
-
-        sp<AMessage> notify = dupNotify();
-        notify->setInt32("what", pushWhat);
-        notify->setBuffer("buffer", buffer);
-
-        int64_t timeUs, baseUs, delayUs;
-        CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
-        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-        delayUs = baseUs + timeUs - ALooper::GetNowUs();
-
-        if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
-            notify->post();
-            msg->post(delayUs > 0LL ? delayUs : 0LL);
-            return;
-        } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
-            if (delayUs < -1000000LL) { // 1 second
-                continue;
-            }
-            notify->post();
-            // push all currently available metadata buffers in each invocation of pollForRawData
-            // continue;
-        } else {
-            TRESPASS();
-        }
-    }
-
-    // try again in 1 second
-    msg->post(1000000LL);
-}
-
-void NuPlayer2::HTTPLiveSource2::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatSessionNotify:
-        {
-            onSessionNotify(msg);
-            break;
-        }
-
-        case kWhatFetchSubtitleData:
-        {
-            pollForRawData(
-                    msg, mFetchSubtitleDataGeneration,
-                    /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
-                    /* push */ kWhatSubtitleData);
-
-            break;
-        }
-
-        case kWhatFetchMetaData:
-        {
-            if (!mMetadataSelected) {
-                break;
-            }
-
-            pollForRawData(
-                    msg, mFetchMetaDataGeneration,
-                    /* fetch */ LiveSession::STREAMTYPE_METADATA,
-                    /* push */ kWhatTimedMetaData);
-
-            break;
-        }
-
-        default:
-            Source::onMessageReceived(msg);
-            break;
-    }
-}
-
-void NuPlayer2::HTTPLiveSource2::onSessionNotify(const sp<AMessage> &msg) {
-    int32_t what;
-    CHECK(msg->findInt32("what", &what));
-
-    switch (what) {
-        case LiveSession::kWhatPrepared:
-        {
-            // notify the current size here if we have it, otherwise report an initial size of (0,0)
-            sp<AMessage> format = getFormat(false /* audio */);
-            int32_t width;
-            int32_t height;
-            if (format != NULL &&
-                    format->findInt32("width", &width) && format->findInt32("height", &height)) {
-                notifyVideoSizeChanged(format);
-            } else {
-                notifyVideoSizeChanged();
-            }
-
-            uint32_t flags = 0;
-            if (mLiveSession->isSeekable()) {
-                flags |= FLAG_CAN_PAUSE;
-                flags |= FLAG_CAN_SEEK;
-                flags |= FLAG_CAN_SEEK_BACKWARD;
-                flags |= FLAG_CAN_SEEK_FORWARD;
-            }
-
-            if (mLiveSession->hasDynamicDuration()) {
-                flags |= FLAG_DYNAMIC_DURATION;
-            }
-
-            notifyFlagsChanged(flags);
-
-            notifyPrepared();
-            break;
-        }
-
-        case LiveSession::kWhatPreparationFailed:
-        {
-            status_t err;
-            CHECK(msg->findInt32("err", &err));
-
-            notifyPrepared(err);
-            break;
-        }
-
-        case LiveSession::kWhatStreamsChanged:
-        {
-            uint32_t changedMask;
-            CHECK(msg->findInt32(
-                        "changedMask", (int32_t *)&changedMask));
-
-            bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
-            bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
-
-            sp<AMessage> reply;
-            CHECK(msg->findMessage("reply", &reply));
-
-            sp<AMessage> notify = dupNotify();
-            notify->setInt32("what", kWhatQueueDecoderShutdown);
-            notify->setInt32("audio", audio);
-            notify->setInt32("video", video);
-            notify->setMessage("reply", reply);
-            notify->post();
-            break;
-        }
-
-        case LiveSession::kWhatBufferingStart:
-        {
-            sp<AMessage> notify = dupNotify();
-            notify->setInt32("what", kWhatPauseOnBufferingStart);
-            notify->post();
-            break;
-        }
-
-        case LiveSession::kWhatBufferingEnd:
-        {
-            sp<AMessage> notify = dupNotify();
-            notify->setInt32("what", kWhatResumeOnBufferingEnd);
-            notify->post();
-            break;
-        }
-
-
-        case LiveSession::kWhatBufferingUpdate:
-        {
-            sp<AMessage> notify = dupNotify();
-            int32_t percentage;
-            CHECK(msg->findInt32("percentage", &percentage));
-            notify->setInt32("what", kWhatBufferingUpdate);
-            notify->setInt32("percentage", percentage);
-            notify->post();
-            break;
-        }
-
-        case LiveSession::kWhatMetadataDetected:
-        {
-            if (!mHasMetadata) {
-                mHasMetadata = true;
-
-                sp<AMessage> notify = dupNotify();
-                // notification without buffer triggers MEDIA2_INFO_METADATA_UPDATE
-                notify->setInt32("what", kWhatTimedMetaData);
-                notify->post();
-            }
-            break;
-        }
-
-        case LiveSession::kWhatError:
-        {
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-}
-
-}  // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h
deleted file mode 100644
index 8fc71e2..0000000
--- a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2017 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 HTTP_LIVE_SOURCE2_H_
-
-#define HTTP_LIVE_SOURCE2_H_
-
-#include "NuPlayer2.h"
-#include "NuPlayer2Source.h"
-
-#include "LiveSession.h"
-
-namespace android {
-
-struct LiveSession;
-
-struct NuPlayer2::HTTPLiveSource2 : public NuPlayer2::Source {
-    HTTPLiveSource2(
-            const sp<AMessage> &notify,
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) override;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
-    virtual void prepareAsync(int64_t startTimeUs);
-    virtual void start();
-
-    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
-    virtual sp<MetaData> getFormatMeta(bool audio);
-    virtual sp<AMessage> getFormat(bool audio);
-
-    virtual status_t feedMoreTSData();
-    virtual status_t getDuration(int64_t *durationUs);
-    virtual size_t getTrackCount() const;
-    virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
-    virtual ssize_t getSelectedTrack(media_track_type /* type */) const;
-    virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
-    virtual status_t seekTo(
-            int64_t seekTimeUs,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
-
-protected:
-    virtual ~HTTPLiveSource2();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
-    enum Flags {
-        // Don't log any URLs.
-        kFlagIncognito = 1,
-    };
-
-    enum {
-        kWhatSessionNotify,
-        kWhatFetchSubtitleData,
-        kWhatFetchMetaData,
-    };
-
-    sp<MediaHTTPService> mHTTPService;
-    AString mURL;
-    KeyedVector<String8, String8> mExtraHeaders;
-    uint32_t mFlags;
-    status_t mFinalResult;
-    off64_t mOffset;
-    sp<ALooper> mLiveLooper;
-    sp<LiveSession> mLiveSession;
-    int32_t mFetchSubtitleDataGeneration;
-    int32_t mFetchMetaDataGeneration;
-    bool mHasMetadata;
-    bool mMetadataSelected;
-    BufferingSettings mBufferingSettings;
-
-    void onSessionNotify(const sp<AMessage> &msg);
-    void pollForRawData(
-            const sp<AMessage> &msg, int32_t currentGeneration,
-            LiveSession::StreamType fetchType, int32_t pushWhat);
-
-    DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource2);
-};
-
-}  // namespace android
-
-#endif  // HTTP_LIVE_SOURCE2_H_
diff --git a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp
deleted file mode 100644
index 89703de..0000000
--- a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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 "JMediaPlayer2Utils"
-
-#include "JMediaPlayer2Utils.h"
-#include <mediaplayer2/JavaVMHelper.h>
-
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/Utils.h>
-#include <utils/Log.h>
-
-#include "log/log.h"
-
-namespace android {
-
-static const int64_t kOffloadMinDurationSec = 60;
-
-// static
-bool JMediaPlayer2Utils::isOffloadedAudioPlaybackSupported(
-        const sp<MetaData>& meta, bool hasVideo, bool isStreaming, audio_stream_type_t streamType)
-{
-    if (hasVideo || streamType != AUDIO_STREAM_MUSIC) {
-        return false;
-    }
-
-    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
-    if (OK != getAudioOffloadInfo(meta, hasVideo, isStreaming, streamType, &info)) {
-        return false;
-    }
-
-    if (info.duration_us < kOffloadMinDurationSec * 1000000) {
-        return false;
-    }
-
-    int32_t audioFormat = audioFormatFromNative(info.format);
-    int32_t channelMask = outChannelMaskFromNative(info.channel_mask);
-    if (audioFormat == ENCODING_INVALID || channelMask == CHANNEL_INVALID) {
-        return false;
-    }
-
-    JNIEnv* env = JavaVMHelper::getJNIEnv();
-    jclass jMP2UtilsCls = env->FindClass("android/media/MediaPlayer2Utils");
-    jmethodID jSetAudioOutputDeviceById = env->GetStaticMethodID(
-            jMP2UtilsCls, "isOffloadedAudioPlaybackSupported", "(III)Z");
-    jboolean result = env->CallStaticBooleanMethod(
-            jMP2UtilsCls, jSetAudioOutputDeviceById, audioFormat, info.sample_rate, channelMask);
-    return result;
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h b/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h
deleted file mode 100644
index fcbd43c..0000000
--- a/media/libmediaplayer2/nuplayer2/JMediaPlayer2Utils.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 _J_MEDIAPLAYER2_UTILS2_H_
-#define _J_MEDIAPLAYER2_UTILS2_H_
-
-#include <media/stagefright/MetaData.h>
-
-#include "jni.h"
-#include "android_media_AudioFormat.h"
-
-namespace android {
-
-struct JMediaPlayer2Utils {
-    static bool isOffloadedAudioPlaybackSupported(
-            const sp<MetaData>& meta, bool hasVideo, bool isStreaming,
-            audio_stream_type_t streamType);
-};
-
-}  // namespace android
-
-#endif  // _J_MEDIAPLAYER2_UTILS2_H_
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
deleted file mode 100644
index 983d77e..0000000
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2017 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 "JWakeLock"
-#include <utils/Log.h>
-
-#include "JWakeLock.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-
-namespace android {
-
-JWakeLock::JWakeLock(const sp<JObjectHolder> &context) :
-    mWakeLockCount(0),
-    mWakeLock(NULL),
-    mContext(context) {}
-
-JWakeLock::~JWakeLock() {
-    clearJavaWakeLock();
-}
-
-bool JWakeLock::acquire() {
-    if (mWakeLockCount == 0) {
-        if (mWakeLock == NULL) {
-            JNIEnv *env = JavaVMHelper::getJNIEnv();
-            jclass jContextCls = env->FindClass("android/content/Context");
-            jclass jPowerManagerCls = env->FindClass("android/os/PowerManager");
-
-            jmethodID jGetSystemService = env->GetMethodID(jContextCls,
-                    "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-            jobject javaPowerManagerObj = env->CallObjectMethod(mContext->getJObject(),
-                    jGetSystemService, env->NewStringUTF("power"));
-
-            jfieldID jPARTIAL_WAKE_LOCK = env->GetStaticFieldID(jPowerManagerCls,
-                    "PARTIAL_WAKE_LOCK", "I");
-            jint PARTIAL_WAKE_LOCK = env->GetStaticIntField(jPowerManagerCls, jPARTIAL_WAKE_LOCK);
-
-            jmethodID jNewWakeLock = env->GetMethodID(jPowerManagerCls,
-                    "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;");
-            jobject javaWakeLock = env->CallObjectMethod(javaPowerManagerObj,
-                    jNewWakeLock, PARTIAL_WAKE_LOCK, env->NewStringUTF("JWakeLock"));
-            mWakeLock = new JObjectHolder(javaWakeLock);
-            env->DeleteLocalRef(javaPowerManagerObj);
-            env->DeleteLocalRef(javaWakeLock);
-        }
-        if (mWakeLock != NULL) {
-            JNIEnv *env = JavaVMHelper::getJNIEnv();
-            jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
-            jmethodID jAcquire = env->GetMethodID(wakeLockCls, "acquire", "()V");
-            env->CallVoidMethod(mWakeLock->getJObject(), jAcquire);
-            mWakeLockCount++;
-            return true;
-        }
-    } else {
-        mWakeLockCount++;
-        return true;
-    }
-    return false;
-}
-
-void JWakeLock::release(bool force) {
-    if (mWakeLockCount == 0) {
-        return;
-    }
-    if (force) {
-        // Force wakelock release below by setting reference count to 1.
-        mWakeLockCount = 1;
-    }
-    if (--mWakeLockCount == 0) {
-        if (mWakeLock != NULL) {
-            JNIEnv *env = JavaVMHelper::getJNIEnv();
-            jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
-            jmethodID jRelease = env->GetMethodID(wakeLockCls, "release", "()V");
-            env->CallVoidMethod(mWakeLock->getJObject(), jRelease);
-        }
-    }
-}
-
-void JWakeLock::clearJavaWakeLock() {
-    release(true);
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.h b/media/libmediaplayer2/nuplayer2/JWakeLock.h
deleted file mode 100644
index 36c542e..0000000
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017 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 J_WAKELOCK_H_
-#define J_WAKELOCK_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <mediaplayer2/JObjectHolder.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class JWakeLock : public RefBase {
-
-public:
-    JWakeLock(const sp<JObjectHolder> &context);
-
-    // NOTE: acquire and release are not thread safe
-
-    // returns true if wakelock was acquired
-    bool acquire();
-    void release(bool force = false);
-
-    virtual ~JWakeLock();
-
-private:
-    uint32_t                mWakeLockCount;
-    sp<JObjectHolder>       mWakeLock;
-    const sp<JObjectHolder> mContext;
-
-    void clearJavaWakeLock();
-
-    DISALLOW_EVIL_CONSTRUCTORS(JWakeLock);
-};
-
-}  // namespace android
-
-#endif  // J_WAKELOCK_H_
diff --git a/media/libmediaplayer2/nuplayer2/NOTICE b/media/libmediaplayer2/nuplayer2/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/media/libmediaplayer2/nuplayer2/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-2008, 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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
deleted file mode 100644
index d608d4a..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ /dev/null
@@ -1,3308 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2"
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-
-#include "NuPlayer2.h"
-
-#include "HTTPLiveSource2.h"
-#include "JMediaPlayer2Utils.h"
-#include "NuPlayer2CCDecoder.h"
-#include "NuPlayer2Decoder.h"
-#include "NuPlayer2DecoderBase.h"
-#include "NuPlayer2DecoderPassThrough.h"
-#include "NuPlayer2Driver.h"
-#include "NuPlayer2Renderer.h"
-#include "NuPlayer2Source.h"
-#include "RTSPSource2.h"
-#include "GenericSource2.h"
-#include "TextDescriptions2.h"
-
-#include "ATSParser.h"
-
-#include <cutils/properties.h>
-
-#include <media/AudioParameter.h>
-#include <media/AudioResamplerPublic.h>
-#include <media/AVSyncSettings.h>
-#include <media/DataSourceDesc.h>
-#include <media/MediaCodecBuffer.h>
-#include <media/NdkWrapper.h>
-
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaClock.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-#include "ESDS.h"
-#include <media/stagefright/Utils.h>
-
-#include <system/window.h>
-
-namespace android {
-
-static status_t sendMetaDataToHal(sp<MediaPlayer2Interface::AudioSink>& sink,
-                                  const sp<MetaData>& meta) {
-    int32_t sampleRate = 0;
-    int32_t bitRate = 0;
-    int32_t channelMask = 0;
-    int32_t delaySamples = 0;
-    int32_t paddingSamples = 0;
-
-    AudioParameter param = AudioParameter();
-
-    if (meta->findInt32(kKeySampleRate, &sampleRate)) {
-        param.addInt(String8(AUDIO_OFFLOAD_CODEC_SAMPLE_RATE), sampleRate);
-    }
-    if (meta->findInt32(kKeyChannelMask, &channelMask)) {
-        param.addInt(String8(AUDIO_OFFLOAD_CODEC_NUM_CHANNEL), channelMask);
-    }
-    if (meta->findInt32(kKeyBitRate, &bitRate)) {
-        param.addInt(String8(AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE), bitRate);
-    }
-    if (meta->findInt32(kKeyEncoderDelay, &delaySamples)) {
-        param.addInt(String8(AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES), delaySamples);
-    }
-    if (meta->findInt32(kKeyEncoderPadding, &paddingSamples)) {
-        param.addInt(String8(AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES), paddingSamples);
-    }
-
-    ALOGV("sendMetaDataToHal: bitRate %d, sampleRate %d, chanMask %d,"
-          "delaySample %d, paddingSample %d", bitRate, sampleRate,
-          channelMask, delaySamples, paddingSamples);
-
-    sink->setParameters(param.toString());
-    return OK;
-}
-
-
-struct NuPlayer2::Action : public RefBase {
-    Action() {}
-
-    virtual void execute(NuPlayer2 *player) = 0;
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(Action);
-};
-
-struct NuPlayer2::SeekAction : public Action {
-    explicit SeekAction(int64_t seekTimeUs, MediaPlayer2SeekMode mode)
-        : mSeekTimeUs(seekTimeUs),
-          mMode(mode) {
-    }
-
-    virtual void execute(NuPlayer2 *player) {
-        player->performSeek(mSeekTimeUs, mMode);
-    }
-
-private:
-    int64_t mSeekTimeUs;
-    MediaPlayer2SeekMode mMode;
-
-    DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
-};
-
-struct NuPlayer2::ResumeDecoderAction : public Action {
-    explicit ResumeDecoderAction(bool needNotify)
-        : mNeedNotify(needNotify) {
-    }
-
-    virtual void execute(NuPlayer2 *player) {
-        player->performResumeDecoders(mNeedNotify);
-    }
-
-private:
-    bool mNeedNotify;
-
-    DISALLOW_EVIL_CONSTRUCTORS(ResumeDecoderAction);
-};
-
-struct NuPlayer2::SetSurfaceAction : public Action {
-    explicit SetSurfaceAction(const sp<ANativeWindowWrapper> &nww)
-        : mNativeWindow(nww) {
-    }
-
-    virtual void execute(NuPlayer2 *player) {
-        player->performSetSurface(mNativeWindow);
-    }
-
-private:
-    sp<ANativeWindowWrapper> mNativeWindow;
-
-    DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
-};
-
-struct NuPlayer2::FlushDecoderAction : public Action {
-    FlushDecoderAction(FlushCommand audio, FlushCommand video)
-        : mAudio(audio),
-          mVideo(video) {
-    }
-
-    virtual void execute(NuPlayer2 *player) {
-        player->performDecoderFlush(mAudio, mVideo);
-    }
-
-private:
-    FlushCommand mAudio;
-    FlushCommand mVideo;
-
-    DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction);
-};
-
-struct NuPlayer2::PostMessageAction : public Action {
-    explicit PostMessageAction(const sp<AMessage> &msg)
-        : mMessage(msg) {
-    }
-
-    virtual void execute(NuPlayer2 *) {
-        mMessage->post();
-    }
-
-private:
-    sp<AMessage> mMessage;
-
-    DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction);
-};
-
-// Use this if there's no state necessary to save in order to execute
-// the action.
-struct NuPlayer2::SimpleAction : public Action {
-    typedef void (NuPlayer2::*ActionFunc)();
-
-    explicit SimpleAction(ActionFunc func)
-        : mFunc(func) {
-    }
-
-    virtual void execute(NuPlayer2 *player) {
-        (player->*mFunc)();
-    }
-
-private:
-    ActionFunc mFunc;
-
-    DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-NuPlayer2::NuPlayer2(
-        pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context)
-    : mPID(pid),
-      mUID(uid),
-      mMediaClock(mediaClock),
-      mOffloadAudio(false),
-      mAudioDecoderGeneration(0),
-      mVideoDecoderGeneration(0),
-      mRendererGeneration(0),
-      mEOSMonitorGeneration(0),
-      mLastStartedPlayingTimeNs(0),
-      mPreviousSeekTimeUs(0),
-      mAudioEOS(false),
-      mVideoEOS(false),
-      mScanSourcesPending(false),
-      mScanSourcesGeneration(0),
-      mPollDurationGeneration(0),
-      mTimedTextGeneration(0),
-      mFlushingAudio(NONE),
-      mFlushingVideo(NONE),
-      mResumePending(false),
-      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
-      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
-      mVideoFpsHint(-1.f),
-      mStarted(false),
-      mPrepared(false),
-      mResetting(false),
-      mSourceStarted(false),
-      mAudioDecoderError(false),
-      mVideoDecoderError(false),
-      mPaused(false),
-      mPausedByClient(true),
-      mPausedForBuffering(false),
-      mContext(context) {
-    CHECK(mediaClock != NULL);
-    clearFlushComplete();
-}
-
-NuPlayer2::~NuPlayer2() {
-}
-
-void NuPlayer2::setDriver(const wp<NuPlayer2Driver> &driver) {
-    mDriver = driver;
-}
-
-static bool IsHTTPLiveURL(const char *url) {
-    if (!strncasecmp("http://", url, 7)
-            || !strncasecmp("https://", url, 8)
-            || !strncasecmp("file://", url, 7)) {
-        size_t len = strlen(url);
-        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
-            return true;
-        }
-
-        if (strstr(url,"m3u8")) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-status_t NuPlayer2::createNuPlayer2Source(const sp<DataSourceDesc> &dsd,
-                                          sp<Source> *source,
-                                          DATA_SOURCE_TYPE *dataSourceType) {
-    status_t err = NO_ERROR;
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-    notify->setInt64("srcId", dsd->mId);
-
-    switch (dsd->mType) {
-        case DataSourceDesc::TYPE_URL:
-        {
-            const char *url = dsd->mUrl.c_str();
-            size_t len = strlen(url);
-
-            const sp<MediaHTTPService> &httpService = dsd->mHttpService;
-            KeyedVector<String8, String8> *headers = &(dsd->mHeaders);
-
-            if (IsHTTPLiveURL(url)) {
-                *source = new HTTPLiveSource2(notify, httpService, url, headers);
-                ALOGV("createNuPlayer2Source HTTPLiveSource2 %s", url);
-                *dataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
-            } else if (!strncasecmp(url, "rtsp://", 7)) {
-                *source = new RTSPSource2(
-                        notify, httpService, url, headers, mUID);
-                ALOGV("createNuPlayer2Source RTSPSource2 %s", url);
-                *dataSourceType = DATA_SOURCE_TYPE_RTSP;
-            } else if ((!strncasecmp(url, "http://", 7)
-                        || !strncasecmp(url, "https://", 8))
-                            && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
-                            || strstr(url, ".sdp?"))) {
-                *source = new RTSPSource2(
-                        notify, httpService, url, headers, mUID, true);
-                ALOGV("createNuPlayer2Source RTSPSource2 http/https/.sdp %s", url);
-                *dataSourceType = DATA_SOURCE_TYPE_RTSP;
-            } else {
-                ALOGV("createNuPlayer2Source GenericSource2 %s", url);
-
-                sp<GenericSource2> genericSource =
-                        new GenericSource2(notify, mUID, mMediaClock);
-
-                err = genericSource->setDataSource(url, headers);
-
-                if (err == OK) {
-                    *source = genericSource;
-                } else {
-                    *source = NULL;
-                    ALOGE("Failed to create NuPlayer2Source!");
-                }
-
-                // regardless of success/failure
-                *dataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
-            }
-            break;
-        }
-
-        case DataSourceDesc::TYPE_FD:
-        {
-            sp<GenericSource2> genericSource =
-                    new GenericSource2(notify, mUID, mMediaClock);
-
-            ALOGV("createNuPlayer2Source fd %d/%lld/%lld source: %p",
-                  dsd->mFD, (long long)dsd->mFDOffset, (long long)dsd->mFDLength,
-                  genericSource.get());
-
-            err = genericSource->setDataSource(dsd->mFD, dsd->mFDOffset, dsd->mFDLength);
-
-            if (err != OK) {
-                ALOGE("Failed to create NuPlayer2Source!");
-                *source = NULL;
-            } else {
-                *source = genericSource;
-            }
-
-            *dataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
-            break;
-        }
-
-        case DataSourceDesc::TYPE_CALLBACK:
-        {
-            sp<GenericSource2> genericSource =
-                    new GenericSource2(notify, mUID, mMediaClock);
-            err = genericSource->setDataSource(dsd->mCallbackSource);
-
-            if (err != OK) {
-                ALOGE("Failed to create NuPlayer2Source!");
-                *source = NULL;
-            } else {
-                *source = genericSource;
-            }
-
-            *dataSourceType = DATA_SOURCE_TYPE_MEDIA;
-            break;
-        }
-
-        default:
-            err = BAD_TYPE;
-            *source = NULL;
-            *dataSourceType = DATA_SOURCE_TYPE_NONE;
-            ALOGE("invalid data source type!");
-            break;
-    }
-
-    return err;
-}
-
-void NuPlayer2::setDataSourceAsync(const sp<DataSourceDesc> &dsd) {
-    DATA_SOURCE_TYPE dataSourceType;
-    sp<Source> source;
-    createNuPlayer2Source(dsd, &source, &dataSourceType);
-
-    // TODO: currently NuPlayer2Driver makes blocking call to setDataSourceAsync
-    // and expects notifySetDataSourceCompleted regardless of success or failure.
-    // This will be changed since setDataSource should be asynchronous at JAVA level.
-    // When it succeeds, app will get onInfo notification. Otherwise, onError
-    // will be called.
-    /*
-    if (err != OK) {
-        notifyListener(dsd->mId, MEDIA2_ERROR, MEDIA2_ERROR_FAILED_TO_SET_DATA_SOURCE, err);
-        return;
-    }
-
-    // Now, source != NULL.
-    */
-
-    mCurrentSourceInfo.mDataSourceType = dataSourceType;
-
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
-    msg->setObject("source", source);
-    msg->setInt64("srcId", dsd->mId);
-    msg->setInt64("startTimeUs", dsd->mStartPositionMs * 1000);
-    msg->setInt64("endTimeUs", dsd->mEndPositionMs * 1000);
-    msg->post();
-}
-
-void NuPlayer2::prepareNextDataSourceAsync(const sp<DataSourceDesc> &dsd) {
-    DATA_SOURCE_TYPE dataSourceType;
-    sp<Source> source;
-    createNuPlayer2Source(dsd, &source, &dataSourceType);
-
-    /*
-    if (err != OK) {
-        notifyListener(dsd->mId, MEDIA2_ERROR, MEDIA2_ERROR_FAILED_TO_SET_DATA_SOURCE, err);
-        return;
-    }
-
-    // Now, source != NULL.
-    */
-
-    mNextSourceInfo.mDataSourceType = dataSourceType;
-
-    sp<AMessage> msg = new AMessage(kWhatPrepareNextDataSource, this);
-    msg->setObject("source", source);
-    msg->setInt64("srcId", dsd->mId);
-    msg->setInt64("startTimeUs", dsd->mStartPositionMs * 1000);
-    msg->setInt64("endTimeUs", dsd->mEndPositionMs * 1000);
-    msg->post();
-}
-
-void NuPlayer2::playNextDataSource(int64_t srcId) {
-    disconnectSource();
-
-    sp<AMessage> msg = new AMessage(kWhatPlayNextDataSource, this);
-    msg->setInt64("srcId", srcId);
-    msg->post();
-}
-
-status_t NuPlayer2::getBufferingSettings(
-        BufferingSettings *buffering /* nonnull */) {
-    sp<AMessage> msg = new AMessage(kWhatGetBufferingSettings, this);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-        if (err == OK) {
-            readFromAMessage(response, buffering);
-        }
-    }
-    return err;
-}
-
-status_t NuPlayer2::setBufferingSettings(const BufferingSettings& buffering) {
-    sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
-    writeToAMessage(msg, buffering);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-void NuPlayer2::prepareAsync() {
-    ALOGV("prepareAsync");
-
-    (new AMessage(kWhatPrepare, this))->post();
-}
-
-void NuPlayer2::setVideoSurfaceTextureAsync(const sp<ANativeWindowWrapper> &nww) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
-
-    if (nww == NULL || nww->getANativeWindow() == NULL) {
-        msg->setObject("surface", NULL);
-    } else {
-        msg->setObject("surface", nww);
-    }
-
-    msg->post();
-}
-
-void NuPlayer2::setAudioSink(const sp<MediaPlayer2Interface::AudioSink> &sink) {
-    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, this);
-    msg->setObject("sink", sink);
-    msg->post();
-}
-
-void NuPlayer2::start() {
-    (new AMessage(kWhatStart, this))->post();
-}
-
-status_t NuPlayer2::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    // do some cursory validation of the settings here. audio modes are
-    // only validated when set on the audiosink.
-     if (rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN
-            || rate.mSpeed > AUDIO_TIMESTRETCH_SPEED_MAX
-            || rate.mPitch < AUDIO_TIMESTRETCH_SPEED_MIN
-            || rate.mPitch > AUDIO_TIMESTRETCH_SPEED_MAX) {
-        return BAD_VALUE;
-    }
-    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
-    writeToAMessage(msg, rate);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-status_t NuPlayer2::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-        if (err == OK) {
-            readFromAMessage(response, rate);
-        }
-    }
-    return err;
-}
-
-status_t NuPlayer2::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
-    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
-    writeToAMessage(msg, sync, videoFpsHint);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-status_t NuPlayer2::getSyncSettings(
-        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
-    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-        if (err == OK) {
-            readFromAMessage(response, sync, videoFps);
-        }
-    }
-    return err;
-}
-
-void NuPlayer2::pause() {
-    (new AMessage(kWhatPause, this))->post();
-}
-
-void NuPlayer2::resetAsync() {
-    disconnectSource();
-    (new AMessage(kWhatReset, this))->post();
-}
-
-void NuPlayer2::disconnectSource() {
-    sp<Source> source;
-    {
-        Mutex::Autolock autoLock(mSourceLock);
-        source = mCurrentSourceInfo.mSource;
-    }
-
-    if (source != NULL) {
-        // During a reset, the data source might be unresponsive already, we need to
-        // disconnect explicitly so that reads exit promptly.
-        // We can't queue the disconnect request to the looper, as it might be
-        // queued behind a stuck read and never gets processed.
-        // Doing a disconnect outside the looper to allows the pending reads to exit
-        // (either successfully or with error).
-        source->disconnect();
-    }
-
-}
-
-status_t NuPlayer2::notifyAt(int64_t mediaTimeUs) {
-    sp<AMessage> notify = new AMessage(kWhatNotifyTime, this);
-    notify->setInt64("timerUs", mediaTimeUs);
-    mMediaClock->addTimer(notify, mediaTimeUs);
-    return OK;
-}
-
-void NuPlayer2::seekToAsync(int64_t seekTimeUs, MediaPlayer2SeekMode mode, bool needNotify) {
-    sp<AMessage> msg = new AMessage(kWhatSeek, this);
-    msg->setInt64("seekTimeUs", seekTimeUs);
-    msg->setInt32("mode", mode);
-    msg->setInt32("needNotify", needNotify);
-    msg->post();
-}
-
-void NuPlayer2::rewind() {
-    sp<AMessage> msg = new AMessage(kWhatRewind, this);
-    msg->post();
-}
-
-void NuPlayer2::writeTrackInfo(
-        PlayerMessage* reply, const sp<AMessage>& format) const {
-    if (format == NULL) {
-        ALOGE("NULL format");
-        return;
-    }
-    int32_t trackType;
-    if (!format->findInt32("type", &trackType)) {
-        ALOGE("no track type");
-        return;
-    }
-
-    AString mime;
-    if (!format->findString("mime", &mime)) {
-        // Java MediaPlayer only uses mimetype for subtitle and timedtext tracks.
-        // If we can't find the mimetype here it means that we wouldn't be needing
-        // the mimetype on the Java end. We still write a placeholder mime to keep the
-        // (de)serialization logic simple.
-        if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
-            mime = "audio/";
-        } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
-            mime = "video/";
-        } else {
-            ALOGE("unknown track type: %d", trackType);
-            return;
-        }
-    }
-
-    AString lang;
-    if (!format->findString("language", &lang)) {
-        ALOGE("no language");
-        return;
-    }
-
-    reply->add_values()->set_int32_value(trackType);
-    reply->add_values()->set_string_value(mime.c_str());
-    reply->add_values()->set_string_value(lang.c_str());
-
-    if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-        int32_t isAuto, isDefault, isForced;
-        CHECK(format->findInt32("auto", &isAuto));
-        CHECK(format->findInt32("default", &isDefault));
-        CHECK(format->findInt32("forced", &isForced));
-
-        reply->add_values()->set_int32_value(isAuto);
-        reply->add_values()->set_int32_value(isDefault);
-        reply->add_values()->set_int32_value(isForced);
-    }
-}
-
-void NuPlayer2::onMessageReceived(const sp<AMessage> &msg) {
-
-    switch (msg->what()) {
-        case kWhatSetDataSource:
-        {
-            ALOGV("kWhatSetDataSource");
-
-            CHECK(mCurrentSourceInfo.mSource == NULL);
-
-            status_t err = OK;
-            sp<RefBase> obj;
-            CHECK(msg->findObject("source", &obj));
-            if (obj != NULL) {
-                Mutex::Autolock autoLock(mSourceLock);
-                CHECK(msg->findInt64("srcId", &mCurrentSourceInfo.mSrcId));
-                CHECK(msg->findInt64("startTimeUs", &mCurrentSourceInfo.mStartTimeUs));
-                CHECK(msg->findInt64("endTimeUs", &mCurrentSourceInfo.mEndTimeUs));
-                mCurrentSourceInfo.mSource = static_cast<Source *>(obj.get());
-            } else {
-                err = UNKNOWN_ERROR;
-                ALOGE("kWhatSetDataSource, source should not be NULL");
-            }
-
-            CHECK(mDriver != NULL);
-            sp<NuPlayer2Driver> driver = mDriver.promote();
-            if (driver != NULL) {
-                driver->notifySetDataSourceCompleted(mCurrentSourceInfo.mSrcId, err);
-            }
-            break;
-        }
-
-        case kWhatPrepareNextDataSource:
-        {
-            ALOGV("kWhatPrepareNextDataSource");
-
-            status_t err = OK;
-            sp<RefBase> obj;
-            CHECK(msg->findObject("source", &obj));
-            if (obj != NULL) {
-                Mutex::Autolock autoLock(mSourceLock);
-                CHECK(msg->findInt64("srcId", &mNextSourceInfo.mSrcId));
-                CHECK(msg->findInt64("startTimeUs", &mNextSourceInfo.mStartTimeUs));
-                CHECK(msg->findInt64("endTimeUs", &mNextSourceInfo.mEndTimeUs));
-                mNextSourceInfo.mSource = static_cast<Source *>(obj.get());
-                mNextSourceInfo.mSource->prepareAsync(mNextSourceInfo.mStartTimeUs);
-            } else {
-                err = UNKNOWN_ERROR;
-            }
-
-            break;
-        }
-
-        case kWhatPlayNextDataSource:
-        {
-            ALOGV("kWhatPlayNextDataSource");
-            int64_t srcId;
-            CHECK(msg->findInt64("srcId", &srcId));
-            if (srcId != mNextSourceInfo.mSrcId) {
-                notifyListener(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, 0);
-                return;
-            }
-
-            mResetting = true;
-            stopPlaybackTimer("kWhatPlayNextDataSource");
-            stopRebufferingTimer(true);
-
-            mDeferredActions.push_back(
-                    new FlushDecoderAction(
-                        FLUSH_CMD_SHUTDOWN /* audio */,
-                        FLUSH_CMD_SHUTDOWN /* video */));
-
-            mDeferredActions.push_back(
-                    new SimpleAction(&NuPlayer2::performPlayNextDataSource));
-
-            processDeferredActions();
-            break;
-        }
-
-        case kWhatEOSMonitor:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            int32_t reason;
-            CHECK(msg->findInt32("reason", &reason));
-
-            if (generation != mEOSMonitorGeneration || reason != MediaClock::TIMER_REASON_REACHED) {
-                break;  // stale or reset
-            }
-
-            ALOGV("kWhatEOSMonitor");
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
-            break;
-        }
-
-        case kWhatGetBufferingSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            ALOGV("kWhatGetBufferingSettings");
-            BufferingSettings buffering;
-            status_t err = OK;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                err = mCurrentSourceInfo.mSource->getBufferingSettings(&buffering);
-            } else {
-                err = INVALID_OPERATION;
-            }
-            sp<AMessage> response = new AMessage;
-            if (err == OK) {
-                writeToAMessage(response, buffering);
-            }
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatSetBufferingSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            ALOGV("kWhatSetBufferingSettings");
-            BufferingSettings buffering;
-            readFromAMessage(msg, &buffering);
-            status_t err = OK;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                err = mCurrentSourceInfo.mSource->setBufferingSettings(buffering);
-            } else {
-                err = INVALID_OPERATION;
-            }
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatPrepare:
-        {
-            ALOGV("onMessageReceived kWhatPrepare");
-
-            mCurrentSourceInfo.mSource->prepareAsync(mCurrentSourceInfo.mStartTimeUs);
-            break;
-        }
-
-        case kWhatGetTrackInfo:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            int64_t srcId;
-            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
-
-            PlayerMessage* reply;
-            CHECK(msg->findPointer("reply", (void**)&reply));
-
-            // TODO: use correct source info based on srcId.
-            size_t inbandTracks = 0;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
-            }
-
-            size_t ccTracks = 0;
-            if (mCCDecoder != NULL) {
-                ccTracks = mCCDecoder->getTrackCount();
-            }
-
-            // total track count
-            reply->add_values()->set_int32_value(inbandTracks + ccTracks);
-
-            // write inband tracks
-            for (size_t i = 0; i < inbandTracks; ++i) {
-                writeTrackInfo(reply, mCurrentSourceInfo.mSource->getTrackInfo(i));
-            }
-
-            // write CC track
-            for (size_t i = 0; i < ccTracks; ++i) {
-                writeTrackInfo(reply, mCCDecoder->getTrackInfo(i));
-            }
-
-            sp<AMessage> response = new AMessage;
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatGetSelectedTrack:
-        {
-            int64_t srcId;
-            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
-
-            int32_t type32;
-            CHECK(msg->findInt32("type", (int32_t*)&type32));
-            media_track_type type = (media_track_type)type32;
-
-            // TODO: use correct source info based on srcId.
-            size_t inbandTracks = 0;
-            status_t err = INVALID_OPERATION;
-            ssize_t selectedTrack = -1;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                err = OK;
-                inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
-                selectedTrack = mCurrentSourceInfo.mSource->getSelectedTrack(type);
-            }
-
-            if (selectedTrack == -1 && mCCDecoder != NULL) {
-                err = OK;
-                selectedTrack = mCCDecoder->getSelectedTrack(type);
-                if (selectedTrack != -1) {
-                    selectedTrack += inbandTracks;
-                }
-            }
-
-            PlayerMessage* reply;
-            CHECK(msg->findPointer("reply", (void**)&reply));
-            reply->add_values()->set_int32_value(selectedTrack);
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatSelectTrack:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            int64_t srcId;
-            size_t trackIndex;
-            int32_t select;
-            int64_t timeUs;
-            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
-            CHECK(msg->findSize("trackIndex", &trackIndex));
-            CHECK(msg->findInt32("select", &select));
-            CHECK(msg->findInt64("timeUs", &timeUs));
-
-            status_t err = INVALID_OPERATION;
-
-            // TODO: use correct source info based on srcId.
-            size_t inbandTracks = 0;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
-            }
-            size_t ccTracks = 0;
-            if (mCCDecoder != NULL) {
-                ccTracks = mCCDecoder->getTrackCount();
-            }
-
-            if (trackIndex < inbandTracks) {
-                err = mCurrentSourceInfo.mSource->selectTrack(trackIndex, select, timeUs);
-
-                if (!select && err == OK) {
-                    int32_t type;
-                    sp<AMessage> info = mCurrentSourceInfo.mSource->getTrackInfo(trackIndex);
-                    if (info != NULL
-                            && info->findInt32("type", &type)
-                            && type == MEDIA_TRACK_TYPE_TIMEDTEXT) {
-                        ++mTimedTextGeneration;
-                    }
-                }
-            } else {
-                trackIndex -= inbandTracks;
-
-                if (trackIndex < ccTracks) {
-                    err = mCCDecoder->selectTrack(trackIndex, select);
-                }
-            }
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatPollDuration:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-
-            if (generation != mPollDurationGeneration) {
-                // stale
-                break;
-            }
-
-            int64_t durationUs;
-            if (mDriver != NULL && mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
-                sp<NuPlayer2Driver> driver = mDriver.promote();
-                if (driver != NULL) {
-                    driver->notifyDuration(mCurrentSourceInfo.mSrcId, durationUs);
-                }
-            }
-
-            msg->post(1000000LL);  // poll again in a second.
-            break;
-        }
-
-        case kWhatSetVideoSurface:
-        {
-
-            sp<RefBase> obj;
-            CHECK(msg->findObject("surface", &obj));
-            sp<ANativeWindowWrapper> nww = static_cast<ANativeWindowWrapper *>(obj.get());
-
-            ALOGD("onSetVideoSurface(%p, %s video decoder)",
-                    (nww == NULL ? NULL : nww->getANativeWindow()),
-                    (mCurrentSourceInfo.mSource != NULL && mStarted
-                            && mCurrentSourceInfo.mSource->getFormat(false /* audio */) != NULL
-                            && mVideoDecoder != NULL) ? "have" : "no");
-
-            // Need to check mStarted before calling mCurrentSourceInfo.mSource->getFormat
-            // because NuPlayer2 might be in preparing state and it could take long time.
-            // When mStarted is true, mCurrentSourceInfo.mSource must have been set.
-            if (mCurrentSourceInfo.mSource == NULL || !mStarted
-                    || mCurrentSourceInfo.mSource->getFormat(false /* audio */) == NULL
-                    // NOTE: mVideoDecoder's mNativeWindow is always non-null
-                    || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(nww) == OK)) {
-                performSetSurface(nww);
-                break;
-            }
-
-            mDeferredActions.push_back(
-                    new FlushDecoderAction(
-                            (obj != NULL ? FLUSH_CMD_FLUSH : FLUSH_CMD_NONE) /* audio */,
-                                           FLUSH_CMD_SHUTDOWN /* video */));
-
-            mDeferredActions.push_back(new SetSurfaceAction(nww));
-
-            if (obj != NULL) {
-                if (mStarted) {
-                    // Issue a seek to refresh the video screen only if started otherwise
-                    // the extractor may not yet be started and will assert.
-                    // If the video decoder is not set (perhaps audio only in this case)
-                    // do not perform a seek as it is not needed.
-                    int64_t currentPositionUs = 0;
-                    if (getCurrentPosition(&currentPositionUs) == OK) {
-                        mDeferredActions.push_back(
-                                new SeekAction(currentPositionUs,
-                                        MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */));
-                    }
-                }
-
-                // If there is a new surface texture, instantiate decoders
-                // again if possible.
-                mDeferredActions.push_back(
-                        new SimpleAction(&NuPlayer2::performScanSources));
-
-                // After a flush without shutdown, decoder is paused.
-                // Don't resume it until source seek is done, otherwise it could
-                // start pulling stale data too soon.
-                mDeferredActions.push_back(
-                        new ResumeDecoderAction(false /* needNotify */));
-            }
-
-            processDeferredActions();
-            break;
-        }
-
-        case kWhatSetAudioSink:
-        {
-            ALOGV("kWhatSetAudioSink");
-
-            sp<RefBase> obj;
-            CHECK(msg->findObject("sink", &obj));
-
-            mAudioSink = static_cast<MediaPlayer2Interface::AudioSink *>(obj.get());
-            break;
-        }
-
-        case kWhatStart:
-        {
-            ALOGV("kWhatStart");
-            if (mStarted) {
-                // do not resume yet if the source is still buffering
-                if (!mPausedForBuffering) {
-                    onResume();
-                }
-            } else {
-                onStart(true /* play */);
-            }
-            mPausedByClient = false;
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
-            break;
-        }
-
-        case kWhatConfigPlayback:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AudioPlaybackRate rate /* sanitized */;
-            readFromAMessage(msg, &rate);
-            status_t err = OK;
-            if (mRenderer != NULL) {
-                // AudioSink allows only 1.f and 0.f for offload mode.
-                // For other speed, switch to non-offload mode.
-                if (mOffloadAudio && (rate.mSpeed != 1.f || rate.mPitch != 1.f)) {
-                    int64_t currentPositionUs;
-                    if (getCurrentPosition(&currentPositionUs) != OK) {
-                        currentPositionUs = mPreviousSeekTimeUs;
-                    }
-
-                    // Set mPlaybackSettings so that the new audio decoder can
-                    // be created correctly.
-                    mPlaybackSettings = rate;
-                    if (!mPaused) {
-                        mRenderer->pause();
-                    }
-                    restartAudio(
-                            currentPositionUs, true /* forceNonOffload */,
-                            true /* needsToCreateAudioDecoder */);
-                    if (!mPaused) {
-                        mRenderer->resume();
-                    }
-                }
-
-                err = mRenderer->setPlaybackSettings(rate);
-            }
-            if (err == OK) {
-                mPlaybackSettings = rate;
-
-                if (mVideoDecoder != NULL) {
-                    sp<AMessage> params = new AMessage();
-                    params->setFloat("playback-speed", mPlaybackSettings.mSpeed);
-                    mVideoDecoder->setParameters(params);
-                }
-            }
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatGetPlaybackSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AudioPlaybackRate rate = mPlaybackSettings;
-            status_t err = OK;
-            if (mRenderer != NULL) {
-                err = mRenderer->getPlaybackSettings(&rate);
-            }
-            if (err == OK) {
-                // get playback settings used by renderer, as it may be
-                // slightly off due to audiosink not taking small changes.
-                mPlaybackSettings = rate;
-            }
-            sp<AMessage> response = new AMessage;
-            if (err == OK) {
-                writeToAMessage(response, rate);
-            }
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatConfigSync:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            ALOGV("kWhatConfigSync");
-            AVSyncSettings sync;
-            float videoFpsHint;
-            readFromAMessage(msg, &sync, &videoFpsHint);
-            status_t err = OK;
-            if (mRenderer != NULL) {
-                err = mRenderer->setSyncSettings(sync, videoFpsHint);
-            }
-            if (err == OK) {
-                mSyncSettings = sync;
-                mVideoFpsHint = videoFpsHint;
-            }
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatGetSyncSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AVSyncSettings sync = mSyncSettings;
-            float videoFps = mVideoFpsHint;
-            status_t err = OK;
-            if (mRenderer != NULL) {
-                err = mRenderer->getSyncSettings(&sync, &videoFps);
-                if (err == OK) {
-                    mSyncSettings = sync;
-                    mVideoFpsHint = videoFps;
-                }
-            }
-            sp<AMessage> response = new AMessage;
-            if (err == OK) {
-                writeToAMessage(response, sync, videoFps);
-            }
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatScanSources:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mScanSourcesGeneration) {
-                // Drop obsolete msg.
-                break;
-            }
-
-            mScanSourcesPending = false;
-
-            ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
-                 mAudioDecoder != NULL, mVideoDecoder != NULL);
-
-            bool mHadAnySourcesBefore =
-                (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
-            bool rescan = false;
-
-            // initialize video before audio because successful initialization of
-            // video may change deep buffer mode of audio.
-            if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
-                if (instantiateDecoder(false, &mVideoDecoder) == -EWOULDBLOCK) {
-                    rescan = true;
-                }
-            }
-
-            // Don't try to re-open audio sink if there's an existing decoder.
-            if (mAudioSink != NULL && mAudioDecoder == NULL) {
-                if (instantiateDecoder(true, &mAudioDecoder) == -EWOULDBLOCK) {
-                    rescan = true;
-                }
-            }
-
-            if (!mHadAnySourcesBefore
-                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
-                // This is the first time we've found anything playable.
-
-                if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
-                    schedulePollDuration();
-                }
-            }
-
-            status_t err;
-            if ((err = mCurrentSourceInfo.mSource->feedMoreTSData()) != OK) {
-                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
-                    // We're not currently decoding anything (no audio or
-                    // video tracks found) and we just ran out of input data.
-
-                    if (err == ERROR_END_OF_STREAM) {
-                        notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
-                    } else {
-                        notifyListener(
-                                mCurrentSourceInfo.mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
-                    }
-                }
-                break;
-            }
-
-            if (rescan) {
-                msg->post(100000LL);
-                mScanSourcesPending = true;
-            }
-            break;
-        }
-
-        case kWhatVideoNotify:
-        case kWhatAudioNotify:
-        {
-            bool audio = msg->what() == kWhatAudioNotify;
-
-            int32_t currentDecoderGeneration =
-                (audio? mAudioDecoderGeneration : mVideoDecoderGeneration);
-            int32_t requesterGeneration = currentDecoderGeneration - 1;
-            CHECK(msg->findInt32("generation", &requesterGeneration));
-
-            if (requesterGeneration != currentDecoderGeneration) {
-                ALOGV("got message from old %s decoder, generation(%d:%d)",
-                        audio ? "audio" : "video", requesterGeneration,
-                        currentDecoderGeneration);
-                sp<AMessage> reply;
-                if (!(msg->findMessage("reply", &reply))) {
-                    return;
-                }
-
-                reply->setInt32("err", INFO_DISCONTINUITY);
-                reply->post();
-                return;
-            }
-
-            int32_t what;
-            CHECK(msg->findInt32("what", &what));
-
-            if (what == DecoderBase::kWhatInputDiscontinuity) {
-                int32_t formatChange;
-                CHECK(msg->findInt32("formatChange", &formatChange));
-
-                ALOGV("%s discontinuity: formatChange %d",
-                        audio ? "audio" : "video", formatChange);
-
-                if (formatChange) {
-                    mDeferredActions.push_back(
-                            new FlushDecoderAction(
-                                audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
-                                audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
-                }
-
-                mDeferredActions.push_back(
-                        new SimpleAction(
-                                &NuPlayer2::performScanSources));
-
-                processDeferredActions();
-            } else if (what == DecoderBase::kWhatEOS) {
-                int32_t err;
-                CHECK(msg->findInt32("err", &err));
-
-                if (err == ERROR_END_OF_STREAM) {
-                    ALOGV("got %s decoder EOS", audio ? "audio" : "video");
-                } else {
-                    ALOGV("got %s decoder EOS w/ error %d",
-                         audio ? "audio" : "video",
-                         err);
-                }
-
-                mRenderer->queueEOS(audio, err);
-            } else if (what == DecoderBase::kWhatFlushCompleted) {
-                ALOGV("decoder %s flush completed", audio ? "audio" : "video");
-
-                handleFlushComplete(audio, true /* isDecoder */);
-                finishFlushIfPossible();
-            } else if (what == DecoderBase::kWhatVideoSizeChanged) {
-                sp<AMessage> format;
-                CHECK(msg->findMessage("format", &format));
-
-                sp<AMessage> inputFormat =
-                        mCurrentSourceInfo.mSource->getFormat(false /* audio */);
-
-                setVideoScalingMode(mVideoScalingMode);
-                updateVideoSize(mCurrentSourceInfo.mSrcId, inputFormat, format);
-            } else if (what == DecoderBase::kWhatShutdownCompleted) {
-                ALOGV("%s shutdown completed", audio ? "audio" : "video");
-                if (audio) {
-                    Mutex::Autolock autoLock(mDecoderLock);
-                    mAudioDecoder.clear();
-                    mAudioDecoderError = false;
-                    ++mAudioDecoderGeneration;
-
-                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
-                    mFlushingAudio = SHUT_DOWN;
-                } else {
-                    Mutex::Autolock autoLock(mDecoderLock);
-                    mVideoDecoder.clear();
-                    mVideoDecoderError = false;
-                    ++mVideoDecoderGeneration;
-
-                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
-                    mFlushingVideo = SHUT_DOWN;
-                }
-
-                finishFlushIfPossible();
-            } else if (what == DecoderBase::kWhatResumeCompleted) {
-                finishResume();
-            } else if (what == DecoderBase::kWhatError) {
-                status_t err;
-                if (!msg->findInt32("err", &err) || err == OK) {
-                    err = UNKNOWN_ERROR;
-                }
-
-                // Decoder errors can be due to Source (e.g. from streaming),
-                // or from decoding corrupted bitstreams, or from other decoder
-                // MediaCodec operations (e.g. from an ongoing reset or seek).
-                // They may also be due to openAudioSink failure at
-                // decoder start or after a format change.
-                //
-                // We try to gracefully shut down the affected decoder if possible,
-                // rather than trying to force the shutdown with something
-                // similar to performReset(). This method can lead to a hang
-                // if MediaCodec functions block after an error, but they should
-                // typically return INVALID_OPERATION instead of blocking.
-
-                FlushStatus *flushing = audio ? &mFlushingAudio : &mFlushingVideo;
-                ALOGE("received error(%#x) from %s decoder, flushing(%d), now shutting down",
-                        err, audio ? "audio" : "video", *flushing);
-
-                switch (*flushing) {
-                    case NONE:
-                        mDeferredActions.push_back(
-                                new FlushDecoderAction(
-                                    audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
-                                    audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
-                        processDeferredActions();
-                        break;
-                    case FLUSHING_DECODER:
-                        *flushing = FLUSHING_DECODER_SHUTDOWN; // initiate shutdown after flush.
-                        break; // Wait for flush to complete.
-                    case FLUSHING_DECODER_SHUTDOWN:
-                        break; // Wait for flush to complete.
-                    case SHUTTING_DOWN_DECODER:
-                        break; // Wait for shutdown to complete.
-                    case FLUSHED:
-                        getDecoder(audio)->initiateShutdown(); // In the middle of a seek.
-                        *flushing = SHUTTING_DOWN_DECODER;     // Shut down.
-                        break;
-                    case SHUT_DOWN:
-                        finishFlushIfPossible();  // Should not occur.
-                        break;                    // Finish anyways.
-                }
-                if (mCurrentSourceInfo.mSource != nullptr) {
-                    if (audio) {
-                        if (mVideoDecoderError
-                                || mCurrentSourceInfo.mSource->getFormat(false /* audio */) == NULL
-                                || mNativeWindow == NULL
-                                || mNativeWindow->getANativeWindow() == NULL
-                                || mVideoDecoder == NULL) {
-                            // When both audio and video have error, or this stream has only audio
-                            // which has error, notify client of error.
-                            notifyListener(
-                                    mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
-                                    MEDIA2_ERROR_UNKNOWN, err);
-                        } else {
-                            // Only audio track has error. Video track could be still good to play.
-                            notifyListener(
-                                    mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
-                                    MEDIA2_INFO_PLAY_AUDIO_ERROR, err);
-                        }
-                        mAudioDecoderError = true;
-                    } else {
-                        if (mAudioDecoderError
-                                || mCurrentSourceInfo.mSource->getFormat(true /* audio */) == NULL
-                                || mAudioSink == NULL || mAudioDecoder == NULL) {
-                            // When both audio and video have error, or this stream has only video
-                            // which has error, notify client of error.
-                            notifyListener(
-                                    mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
-                                    MEDIA2_ERROR_UNKNOWN, err);
-                        } else {
-                            // Only video track has error. Audio track could be still good to play.
-                            notifyListener(
-                                    mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
-                                    MEDIA2_INFO_PLAY_VIDEO_ERROR, err);
-                        }
-                        mVideoDecoderError = true;
-                    }
-                }
-            } else {
-                ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
-                      what,
-                      what >> 24,
-                      (what >> 16) & 0xff,
-                      (what >> 8) & 0xff,
-                      what & 0xff);
-            }
-
-            break;
-        }
-
-        case kWhatRendererNotify:
-        {
-            int32_t requesterGeneration = mRendererGeneration - 1;
-            CHECK(msg->findInt32("generation", &requesterGeneration));
-            if (requesterGeneration != mRendererGeneration) {
-                ALOGV("got message from old renderer, generation(%d:%d)",
-                        requesterGeneration, mRendererGeneration);
-                return;
-            }
-
-            int32_t what;
-            CHECK(msg->findInt32("what", &what));
-
-            if (what == Renderer::kWhatEOS) {
-                int32_t audio;
-                CHECK(msg->findInt32("audio", &audio));
-
-                int32_t finalResult;
-                CHECK(msg->findInt32("finalResult", &finalResult));
-
-                if (audio) {
-                    mAudioEOS = true;
-                } else {
-                    mVideoEOS = true;
-                }
-
-                if (finalResult == ERROR_END_OF_STREAM) {
-                    ALOGV("reached %s EOS", audio ? "audio" : "video");
-                } else {
-                    ALOGE("%s track encountered an error (%d)",
-                         audio ? "audio" : "video", finalResult);
-
-                    notifyListener(
-                            mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
-                            MEDIA2_ERROR_UNKNOWN, finalResult);
-                }
-
-                if ((mAudioEOS || mAudioDecoder == NULL)
-                        && (mVideoEOS || mVideoDecoder == NULL)) {
-                    notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
-                }
-            } else if (what == Renderer::kWhatFlushComplete) {
-                int32_t audio;
-                CHECK(msg->findInt32("audio", &audio));
-
-                if (audio) {
-                    mAudioEOS = false;
-                } else {
-                    mVideoEOS = false;
-                }
-
-                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
-                if (audio && (mFlushingAudio == NONE || mFlushingAudio == FLUSHED
-                        || mFlushingAudio == SHUT_DOWN)) {
-                    // Flush has been handled by tear down.
-                    break;
-                }
-                handleFlushComplete(audio, false /* isDecoder */);
-                finishFlushIfPossible();
-            } else if (what == Renderer::kWhatVideoRenderingStart) {
-                notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO,
-                               MEDIA2_INFO_VIDEO_RENDERING_START, 0);
-            } else if (what == Renderer::kWhatMediaRenderingStart) {
-                ALOGV("media rendering started");
-                notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
-            } else if (what == Renderer::kWhatAudioTearDown) {
-                int32_t reason;
-                CHECK(msg->findInt32("reason", &reason));
-                ALOGV("Tear down audio with reason %d.", reason);
-                if (reason == Renderer::kDueToTimeout && !(mPaused && mOffloadAudio)) {
-                    // TimeoutWhenPaused is only for offload mode.
-                    ALOGW("Receive a stale message for teardown.");
-                    break;
-                }
-                int64_t positionUs;
-                if (!msg->findInt64("positionUs", &positionUs)) {
-                    positionUs = mPreviousSeekTimeUs;
-                }
-
-                restartAudio(
-                        positionUs, reason == Renderer::kForceNonOffload /* forceNonOffload */,
-                        reason != Renderer::kDueToTimeout /* needsToCreateAudioDecoder */);
-            }
-            break;
-        }
-
-        case kWhatMoreDataQueued:
-        {
-            break;
-        }
-
-        case kWhatReset:
-        {
-            ALOGV("kWhatReset");
-
-            mResetting = true;
-            stopPlaybackTimer("kWhatReset");
-            stopRebufferingTimer(true);
-
-            mDeferredActions.push_back(
-                    new FlushDecoderAction(
-                        FLUSH_CMD_SHUTDOWN /* audio */,
-                        FLUSH_CMD_SHUTDOWN /* video */));
-
-            mDeferredActions.push_back(
-                    new SimpleAction(&NuPlayer2::performReset));
-
-            processDeferredActions();
-            break;
-        }
-
-        case kWhatNotifyTime:
-        {
-            ALOGV("kWhatNotifyTime");
-            int64_t timerUs;
-            CHECK(msg->findInt64("timerUs", &timerUs));
-
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_NOTIFY_TIME, timerUs, 0);
-            break;
-        }
-
-        case kWhatSeek:
-        {
-            int64_t seekTimeUs;
-            int32_t mode;
-            int32_t needNotify;
-            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
-            CHECK(msg->findInt32("mode", &mode));
-            CHECK(msg->findInt32("needNotify", &needNotify));
-
-            ALOGV("kWhatSeek seekTimeUs=%lld us, mode=%d, needNotify=%d",
-                    (long long)seekTimeUs, mode, needNotify);
-
-            if (!mStarted) {
-                if (!mSourceStarted) {
-                    mSourceStarted = true;
-                    mCurrentSourceInfo.mSource->start();
-                }
-                if (seekTimeUs > 0) {
-                    performSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
-                }
-
-                if (needNotify) {
-                    notifyDriverSeekComplete(mCurrentSourceInfo.mSrcId);
-                }
-                break;
-            }
-
-            // seeks can take a while, so we essentially paused
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);
-
-            mDeferredActions.push_back(
-                    new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
-                                           FLUSH_CMD_FLUSH /* video */));
-
-            mDeferredActions.push_back(
-                    new SeekAction(seekTimeUs, (MediaPlayer2SeekMode)mode));
-
-            // After a flush without shutdown, decoder is paused.
-            // Don't resume it until source seek is done, otherwise it could
-            // start pulling stale data too soon.
-            mDeferredActions.push_back(
-                    new ResumeDecoderAction(needNotify));
-
-            processDeferredActions();
-            break;
-        }
-
-        case kWhatRewind:
-        {
-            ALOGV("kWhatRewind");
-
-            int64_t seekTimeUs = mCurrentSourceInfo.mStartTimeUs;
-            int32_t mode = MediaPlayer2SeekMode::SEEK_CLOSEST;
-
-            if (!mStarted) {
-                if (!mSourceStarted) {
-                    mSourceStarted = true;
-                    mCurrentSourceInfo.mSource->start();
-                }
-                performSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
-                break;
-            }
-
-            // seeks can take a while, so we essentially paused
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);
-
-            mDeferredActions.push_back(
-                    new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
-                                           FLUSH_CMD_FLUSH /* video */));
-
-            mDeferredActions.push_back(
-                    new SeekAction(seekTimeUs, (MediaPlayer2SeekMode)mode));
-
-            // After a flush without shutdown, decoder is paused.
-            // Don't resume it until source seek is done, otherwise it could
-            // start pulling stale data too soon.
-            mDeferredActions.push_back(
-                    new ResumeDecoderAction(false /* needNotify */));
-
-            processDeferredActions();
-            break;
-        }
-
-        case kWhatPause:
-        {
-            if (!mStarted) {
-                onStart(false /* play */);
-            }
-            onPause();
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);
-            mPausedByClient = true;
-            break;
-        }
-
-        case kWhatSourceNotify:
-        {
-            onSourceNotify(msg);
-            break;
-        }
-
-        case kWhatClosedCaptionNotify:
-        {
-            onClosedCaptionNotify(msg);
-            break;
-        }
-
-        case kWhatPrepareDrm:
-        {
-            status_t status = onPrepareDrm(msg);
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("status", status);
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatReleaseDrm:
-        {
-            status_t status = onReleaseDrm(msg);
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("status", status);
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            response->postReply(replyID);
-            break;
-        }
-
-        default:
-            TRESPASS();
-            break;
-    }
-}
-
-void NuPlayer2::onResume() {
-    if (!mPaused || mResetting) {
-        ALOGD_IF(mResetting, "resetting, onResume discarded");
-        return;
-    }
-    mPaused = false;
-    if (mCurrentSourceInfo.mSource != NULL) {
-        mCurrentSourceInfo.mSource->resume();
-    } else {
-        ALOGW("resume called when source is gone or not set");
-    }
-    // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if
-    // needed.
-    if (audioDecoderStillNeeded() && mAudioDecoder == NULL) {
-        instantiateDecoder(true /* audio */, &mAudioDecoder);
-    }
-    if (mRenderer != NULL) {
-        mRenderer->resume();
-    } else {
-        ALOGW("resume called when renderer is gone or not set");
-    }
-
-    startPlaybackTimer("onresume");
-}
-
-void NuPlayer2::onStart(bool play) {
-    ALOGV("onStart: mCrypto: %p", mCurrentSourceInfo.mCrypto.get());
-
-    if (!mSourceStarted) {
-        mSourceStarted = true;
-        mCurrentSourceInfo.mSource->start();
-    }
-
-    mOffloadAudio = false;
-    mAudioEOS = false;
-    mVideoEOS = false;
-    mStarted = true;
-    mPaused = false;
-
-    uint32_t flags = 0;
-
-    if (mCurrentSourceInfo.mSource->isRealTime()) {
-        flags |= Renderer::FLAG_REAL_TIME;
-    }
-
-    bool hasAudio = (mCurrentSourceInfo.mSource->getFormat(true /* audio */) != NULL);
-    bool hasVideo = (mCurrentSourceInfo.mSource->getFormat(false /* audio */) != NULL);
-    if (!hasAudio && !hasVideo) {
-        ALOGE("no metadata for either audio or video source");
-        mCurrentSourceInfo.mSource->stop();
-        mSourceStarted = false;
-        notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_ERROR,
-                       MEDIA2_ERROR_UNKNOWN, ERROR_MALFORMED);
-        return;
-    }
-    ALOGV_IF(!hasAudio, "no metadata for audio source");  // video only stream
-
-    sp<MetaData> audioMeta = mCurrentSourceInfo.mSource->getFormatMeta(true /* audio */);
-
-    audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
-    if (mAudioSink != NULL) {
-        streamType = mAudioSink->getAudioStreamType();
-    }
-
-    mOffloadAudio =
-        JMediaPlayer2Utils::isOffloadedAudioPlaybackSupported(
-                audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
-                && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
-
-    // Modular DRM: Disabling audio offload if the source is protected
-    if (mOffloadAudio && mCurrentSourceInfo.mIsDrmProtected) {
-        mOffloadAudio = false;
-        ALOGV("onStart: Disabling mOffloadAudio now that the source is protected.");
-    }
-
-    if (mOffloadAudio) {
-        flags |= Renderer::FLAG_OFFLOAD_AUDIO;
-    }
-
-    sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
-    ++mRendererGeneration;
-    notify->setInt32("generation", mRendererGeneration);
-    mRenderer = new Renderer(mAudioSink, mMediaClock, notify, mContext, flags);
-    mRendererLooper = new ALooper;
-    mRendererLooper->setName("NuPlayer2Renderer");
-    mRendererLooper->start(false, true, ANDROID_PRIORITY_AUDIO);
-    mRendererLooper->registerHandler(mRenderer);
-
-    status_t err = mRenderer->setPlaybackSettings(mPlaybackSettings);
-    if (err != OK) {
-        mCurrentSourceInfo.mSource->stop();
-        mSourceStarted = false;
-        notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
-        return;
-    }
-
-    float rate = getFrameRate();
-    if (rate > 0) {
-        mRenderer->setVideoFrameRate(rate);
-    }
-
-    addEndTimeMonitor();
-    // Renderer is created in paused state.
-    if (play) {
-        mRenderer->resume();
-    }
-
-    if (mVideoDecoder != NULL) {
-        mVideoDecoder->setRenderer(mRenderer);
-    }
-    if (mAudioDecoder != NULL) {
-        mAudioDecoder->setRenderer(mRenderer);
-    }
-
-    startPlaybackTimer("onstart");
-    notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
-
-    postScanSources();
-}
-
-void NuPlayer2::addEndTimeMonitor() {
-    ++mEOSMonitorGeneration;
-
-    if (mCurrentSourceInfo.mEndTimeUs == DataSourceDesc::kMaxTimeUs) {
-        return;
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatEOSMonitor, this);
-    msg->setInt32("generation", mEOSMonitorGeneration);
-    mMediaClock->addTimer(msg, mCurrentSourceInfo.mEndTimeUs);
-}
-
-void NuPlayer2::startPlaybackTimer(const char *where) {
-    Mutex::Autolock autoLock(mPlayingTimeLock);
-    if (mLastStartedPlayingTimeNs == 0) {
-        mLastStartedPlayingTimeNs = systemTime();
-        ALOGV("startPlaybackTimer() time %20" PRId64 " (%s)",  mLastStartedPlayingTimeNs, where);
-    }
-}
-
-void NuPlayer2::stopPlaybackTimer(const char *where) {
-    Mutex::Autolock autoLock(mPlayingTimeLock);
-
-    ALOGV("stopPlaybackTimer()  time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
-
-    if (mLastStartedPlayingTimeNs != 0) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            int64_t now = systemTime();
-            int64_t played = now - mLastStartedPlayingTimeNs;
-            ALOGV("stopPlaybackTimer()  log  %20" PRId64 "", played);
-
-            if (played > 0) {
-                driver->notifyMorePlayingTimeUs(mCurrentSourceInfo.mSrcId, (played+500)/1000);
-            }
-        }
-        mLastStartedPlayingTimeNs = 0;
-    }
-}
-
-void NuPlayer2::startRebufferingTimer() {
-    Mutex::Autolock autoLock(mPlayingTimeLock);
-    if (mLastStartedRebufferingTimeNs == 0) {
-        mLastStartedRebufferingTimeNs = systemTime();
-        ALOGV("startRebufferingTimer() time %20" PRId64 "",  mLastStartedRebufferingTimeNs);
-    }
-}
-
-void NuPlayer2::stopRebufferingTimer(bool exitingPlayback) {
-    Mutex::Autolock autoLock(mPlayingTimeLock);
-
-    ALOGV("stopRebufferTimer()  time %20" PRId64 " (exiting %d)",
-          mLastStartedRebufferingTimeNs, exitingPlayback);
-
-    if (mLastStartedRebufferingTimeNs != 0) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            int64_t now = systemTime();
-            int64_t rebuffered = now - mLastStartedRebufferingTimeNs;
-            ALOGV("stopRebufferingTimer()  log  %20" PRId64 "", rebuffered);
-
-            if (rebuffered > 0) {
-                driver->notifyMoreRebufferingTimeUs(
-                        mCurrentSourceInfo.mSrcId, (rebuffered+500)/1000);
-                if (exitingPlayback) {
-                    driver->notifyRebufferingWhenExit(mCurrentSourceInfo.mSrcId, true);
-                }
-            }
-        }
-        mLastStartedRebufferingTimeNs = 0;
-    }
-}
-
-void NuPlayer2::onPause() {
-
-    stopPlaybackTimer("onPause");
-
-    if (mPaused) {
-        return;
-    }
-    mPaused = true;
-    if (mCurrentSourceInfo.mSource != NULL) {
-        mCurrentSourceInfo.mSource->pause();
-    } else {
-        ALOGW("pause called when source is gone or not set");
-    }
-    if (mRenderer != NULL) {
-        mRenderer->pause();
-    } else {
-        ALOGW("pause called when renderer is gone or not set");
-    }
-
-}
-
-bool NuPlayer2::audioDecoderStillNeeded() {
-    // Audio decoder is no longer needed if it's in shut/shutting down status.
-    return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
-}
-
-void NuPlayer2::handleFlushComplete(bool audio, bool isDecoder) {
-    // We wait for both the decoder flush and the renderer flush to complete
-    // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.
-
-    mFlushComplete[audio][isDecoder] = true;
-    if (!mFlushComplete[audio][!isDecoder]) {
-        return;
-    }
-
-    FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
-    switch (*state) {
-        case FLUSHING_DECODER:
-        {
-            *state = FLUSHED;
-            break;
-        }
-
-        case FLUSHING_DECODER_SHUTDOWN:
-        {
-            *state = SHUTTING_DOWN_DECODER;
-
-            ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
-            getDecoder(audio)->initiateShutdown();
-            break;
-        }
-
-        default:
-            // decoder flush completes only occur in a flushing state.
-            LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
-            break;
-    }
-}
-
-void NuPlayer2::finishFlushIfPossible() {
-    if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
-            && mFlushingAudio != SHUT_DOWN) {
-        return;
-    }
-
-    if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED
-            && mFlushingVideo != SHUT_DOWN) {
-        return;
-    }
-
-    ALOGV("both audio and video are flushed now.");
-
-    mFlushingAudio = NONE;
-    mFlushingVideo = NONE;
-
-    clearFlushComplete();
-
-    processDeferredActions();
-}
-
-void NuPlayer2::postScanSources() {
-    if (mScanSourcesPending) {
-        return;
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatScanSources, this);
-    msg->setInt32("generation", mScanSourcesGeneration);
-    msg->post();
-
-    mScanSourcesPending = true;
-}
-
-void NuPlayer2::tryOpenAudioSinkForOffload(
-        const sp<AMessage> &format, const sp<MetaData> &audioMeta, bool hasVideo) {
-    // Note: This is called early in NuPlayer2 to determine whether offloading
-    // is possible; otherwise the decoders call the renderer openAudioSink directly.
-
-    status_t err = mRenderer->openAudioSink(
-            format, true /* offloadOnly */, hasVideo,
-            AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mCurrentSourceInfo.mSource->isStreaming());
-    if (err != OK) {
-        // Any failure we turn off mOffloadAudio.
-        mOffloadAudio = false;
-    } else if (mOffloadAudio) {
-        sendMetaDataToHal(mAudioSink, audioMeta);
-    }
-}
-
-void NuPlayer2::closeAudioSink() {
-    mRenderer->closeAudioSink();
-}
-
-void NuPlayer2::restartAudio(
-        int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
-    if (mAudioDecoder != NULL) {
-        mAudioDecoder->pause();
-        Mutex::Autolock autoLock(mDecoderLock);
-        mAudioDecoder.clear();
-        mAudioDecoderError = false;
-        ++mAudioDecoderGeneration;
-    }
-    if (mFlushingAudio == FLUSHING_DECODER) {
-        mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
-        mFlushingAudio = FLUSHED;
-        finishFlushIfPossible();
-    } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
-            || mFlushingAudio == SHUTTING_DOWN_DECODER) {
-        mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
-        mFlushingAudio = SHUT_DOWN;
-        finishFlushIfPossible();
-        needsToCreateAudioDecoder = false;
-    }
-    if (mRenderer == NULL) {
-        return;
-    }
-    closeAudioSink();
-    mRenderer->flush(true /* audio */, false /* notifyComplete */);
-    if (mVideoDecoder != NULL) {
-        mDeferredActions.push_back(
-                new FlushDecoderAction(FLUSH_CMD_NONE /* audio */,
-                                       FLUSH_CMD_FLUSH /* video */));
-        mDeferredActions.push_back(
-                new SeekAction(currentPositionUs,
-                MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */));
-        // After a flush without shutdown, decoder is paused.
-        // Don't resume it until source seek is done, otherwise it could
-        // start pulling stale data too soon.
-        mDeferredActions.push_back(new ResumeDecoderAction(false));
-        processDeferredActions();
-    } else {
-        performSeek(currentPositionUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */);
-    }
-
-    if (forceNonOffload) {
-        mRenderer->signalDisableOffloadAudio();
-        mOffloadAudio = false;
-    }
-    if (needsToCreateAudioDecoder) {
-        instantiateDecoder(true /* audio */, &mAudioDecoder, !forceNonOffload);
-    }
-}
-
-void NuPlayer2::determineAudioModeChange(const sp<AMessage> &audioFormat) {
-    if (mCurrentSourceInfo.mSource == NULL || mAudioSink == NULL) {
-        return;
-    }
-
-    if (mRenderer == NULL) {
-        ALOGW("No renderer can be used to determine audio mode. Use non-offload for safety.");
-        mOffloadAudio = false;
-        return;
-    }
-
-    sp<MetaData> audioMeta = mCurrentSourceInfo.mSource->getFormatMeta(true /* audio */);
-    sp<AMessage> videoFormat = mCurrentSourceInfo.mSource->getFormat(false /* audio */);
-    audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
-    const bool hasVideo = (videoFormat != NULL);
-    bool canOffload = JMediaPlayer2Utils::isOffloadedAudioPlaybackSupported(
-            audioMeta, hasVideo, mCurrentSourceInfo.mSource->isStreaming(), streamType)
-                    && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
-
-    // Modular DRM: Disabling audio offload if the source is protected
-    if (canOffload && mCurrentSourceInfo.mIsDrmProtected) {
-        canOffload = false;
-        ALOGV("determineAudioModeChange: Disabling mOffloadAudio b/c the source is protected.");
-    }
-
-    if (canOffload) {
-        if (!mOffloadAudio) {
-            mRenderer->signalEnableOffloadAudio();
-        }
-        // open audio sink early under offload mode.
-        tryOpenAudioSinkForOffload(audioFormat, audioMeta, hasVideo);
-    } else {
-        if (mOffloadAudio) {
-            mRenderer->signalDisableOffloadAudio();
-            mOffloadAudio = false;
-        }
-    }
-}
-
-status_t NuPlayer2::instantiateDecoder(
-        bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange) {
-    // The audio decoder could be cleared by tear down. If still in shut down
-    // process, no need to create a new audio decoder.
-    if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
-        return OK;
-    }
-
-    sp<AMessage> format = mCurrentSourceInfo.mSource->getFormat(audio);
-
-    if (format == NULL) {
-        return UNKNOWN_ERROR;
-    } else {
-        status_t err;
-        if (format->findInt32("err", &err) && err) {
-            return err;
-        }
-    }
-
-    format->setInt32("priority", 0 /* realtime */);
-
-    if (!audio) {
-        AString mime;
-        CHECK(format->findString("mime", &mime));
-
-        sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this);
-        if (mCCDecoder == NULL) {
-            mCCDecoder = new CCDecoder(ccNotify);
-        }
-
-        if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) {
-            format->setInt32("secure", true);
-        }
-
-        if (mCurrentSourceInfo.mSourceFlags & Source::FLAG_PROTECTED) {
-            format->setInt32("protected", true);
-        }
-
-        float rate = getFrameRate();
-        if (rate > 0) {
-            format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
-        }
-    }
-
-    Mutex::Autolock autoLock(mDecoderLock);
-
-    if (audio) {
-        sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
-        ++mAudioDecoderGeneration;
-        notify->setInt32("generation", mAudioDecoderGeneration);
-
-        if (checkAudioModeChange) {
-            determineAudioModeChange(format);
-        }
-        if (mOffloadAudio) {
-            mCurrentSourceInfo.mSource->setOffloadAudio(true /* offload */);
-
-            const bool hasVideo = (mCurrentSourceInfo.mSource->getFormat(false /*audio */) != NULL);
-            format->setInt32("has-video", hasVideo);
-            *decoder = new DecoderPassThrough(notify, mCurrentSourceInfo.mSource, mRenderer);
-            ALOGV("instantiateDecoder audio DecoderPassThrough  hasVideo: %d", hasVideo);
-        } else {
-            mCurrentSourceInfo.mSource->setOffloadAudio(false /* offload */);
-
-            *decoder = new Decoder(notify, mCurrentSourceInfo.mSource, mPID, mUID, mRenderer);
-            ALOGV("instantiateDecoder audio Decoder");
-        }
-        mAudioDecoderError = false;
-    } else {
-        sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
-        ++mVideoDecoderGeneration;
-        notify->setInt32("generation", mVideoDecoderGeneration);
-
-        *decoder = new Decoder(
-                notify, mCurrentSourceInfo.mSource, mPID, mUID, mRenderer, mNativeWindow,
-                mCCDecoder);
-        mVideoDecoderError = false;
-
-        // enable FRC if high-quality AV sync is requested, even if not
-        // directly queuing to display, as this will even improve textureview
-        // playback.
-        {
-            if (property_get_bool("persist.sys.media.avsync", false)) {
-                format->setInt32("auto-frc", 1);
-            }
-        }
-    }
-    (*decoder)->init();
-
-    // Modular DRM
-    if (mCurrentSourceInfo.mIsDrmProtected) {
-        format->setObject("crypto", mCurrentSourceInfo.mCrypto);
-        ALOGV("instantiateDecoder: mCrypto: %p isSecure: %d",
-                mCurrentSourceInfo.mCrypto.get(),
-                (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) != 0);
-    }
-
-    (*decoder)->configure(format);
-
-    if (!audio) {
-        sp<AMessage> params = new AMessage();
-        float rate = getFrameRate();
-        if (rate > 0) {
-            params->setFloat("frame-rate-total", rate);
-        }
-
-        sp<MetaData> fileMeta = getFileMeta();
-        if (fileMeta != NULL) {
-            int32_t videoTemporalLayerCount;
-            if (fileMeta->findInt32(kKeyTemporalLayerCount, &videoTemporalLayerCount)
-                    && videoTemporalLayerCount > 0) {
-                params->setInt32("temporal-layer-count", videoTemporalLayerCount);
-            }
-        }
-
-        if (params->countEntries() > 0) {
-            (*decoder)->setParameters(params);
-        }
-    }
-    return OK;
-}
-
-void NuPlayer2::updateVideoSize(
-        int64_t srcId,
-        const sp<AMessage> &inputFormat,
-        const sp<AMessage> &outputFormat) {
-    if (inputFormat == NULL) {
-        ALOGW("Unknown video size, reporting 0x0!");
-        notifyListener(srcId, MEDIA2_SET_VIDEO_SIZE, 0, 0);
-        return;
-    }
-    int32_t err = OK;
-    inputFormat->findInt32("err", &err);
-    if (err == -EWOULDBLOCK) {
-        ALOGW("Video meta is not available yet!");
-        return;
-    }
-    if (err != OK) {
-        ALOGW("Something is wrong with video meta!");
-        return;
-    }
-
-    int32_t displayWidth, displayHeight;
-    if (outputFormat != NULL) {
-        int32_t width, height;
-        CHECK(outputFormat->findInt32("width", &width));
-        CHECK(outputFormat->findInt32("height", &height));
-
-        int32_t cropLeft, cropTop, cropRight, cropBottom;
-        CHECK(outputFormat->findRect(
-                    "crop",
-                    &cropLeft, &cropTop, &cropRight, &cropBottom));
-
-        displayWidth = cropRight - cropLeft + 1;
-        displayHeight = cropBottom - cropTop + 1;
-
-        ALOGV("Video output format changed to %d x %d "
-             "(crop: %d x %d @ (%d, %d))",
-             width, height,
-             displayWidth,
-             displayHeight,
-             cropLeft, cropTop);
-    } else {
-        CHECK(inputFormat->findInt32("width", &displayWidth));
-        CHECK(inputFormat->findInt32("height", &displayHeight));
-
-        ALOGV("Video input format %d x %d", displayWidth, displayHeight);
-    }
-
-    // Take into account sample aspect ratio if necessary:
-    int32_t sarWidth, sarHeight;
-    if (inputFormat->findInt32("sar-width", &sarWidth)
-            && inputFormat->findInt32("sar-height", &sarHeight)
-            && sarWidth > 0 && sarHeight > 0) {
-        ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight);
-
-        displayWidth = (displayWidth * sarWidth) / sarHeight;
-
-        ALOGV("display dimensions %d x %d", displayWidth, displayHeight);
-    } else {
-        int32_t width, height;
-        if (inputFormat->findInt32("display-width", &width)
-                && inputFormat->findInt32("display-height", &height)
-                && width > 0 && height > 0
-                && displayWidth > 0 && displayHeight > 0) {
-            if (displayHeight * (int64_t)width / height > (int64_t)displayWidth) {
-                displayHeight = (int32_t)(displayWidth * (int64_t)height / width);
-            } else {
-                displayWidth = (int32_t)(displayHeight * (int64_t)width / height);
-            }
-            ALOGV("Video display width and height are overridden to %d x %d",
-                 displayWidth, displayHeight);
-        }
-    }
-
-    int32_t rotationDegrees;
-    if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) {
-        rotationDegrees = 0;
-    }
-
-    if (rotationDegrees == 90 || rotationDegrees == 270) {
-        int32_t tmp = displayWidth;
-        displayWidth = displayHeight;
-        displayHeight = tmp;
-    }
-
-    notifyListener(
-            srcId,
-            MEDIA2_SET_VIDEO_SIZE,
-            displayWidth,
-            displayHeight);
-}
-
-void NuPlayer2::notifyListener(
-        int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
-    if (mDriver == NULL) {
-        return;
-    }
-
-    sp<NuPlayer2Driver> driver = mDriver.promote();
-
-    if (driver == NULL) {
-        return;
-    }
-
-    driver->notifyListener(srcId, msg, ext1, ext2, in);
-}
-
-void NuPlayer2::flushDecoder(bool audio, bool needShutdown) {
-    ALOGV("[%s] flushDecoder needShutdown=%d",
-          audio ? "audio" : "video", needShutdown);
-
-    const sp<DecoderBase> &decoder = getDecoder(audio);
-    if (decoder == NULL) {
-        ALOGI("flushDecoder %s without decoder present",
-             audio ? "audio" : "video");
-        return;
-    }
-
-    // Make sure we don't continue to scan sources until we finish flushing.
-    ++mScanSourcesGeneration;
-    if (mScanSourcesPending) {
-        if (!needShutdown) {
-            mDeferredActions.push_back(
-                    new SimpleAction(&NuPlayer2::performScanSources));
-        }
-        mScanSourcesPending = false;
-    }
-
-    decoder->signalFlush();
-
-    FlushStatus newStatus =
-        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
-
-    mFlushComplete[audio][false /* isDecoder */] = (mRenderer == NULL);
-    mFlushComplete[audio][true /* isDecoder */] = false;
-    if (audio) {
-        ALOGE_IF(mFlushingAudio != NONE,
-                "audio flushDecoder() is called in state %d", mFlushingAudio);
-        mFlushingAudio = newStatus;
-    } else {
-        ALOGE_IF(mFlushingVideo != NONE,
-                "video flushDecoder() is called in state %d", mFlushingVideo);
-        mFlushingVideo = newStatus;
-    }
-}
-
-void NuPlayer2::queueDecoderShutdown(
-        bool audio, bool video, const sp<AMessage> &reply) {
-    ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
-
-    mDeferredActions.push_back(
-            new FlushDecoderAction(
-                audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
-                video ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE));
-
-    mDeferredActions.push_back(
-            new SimpleAction(&NuPlayer2::performScanSources));
-
-    mDeferredActions.push_back(new PostMessageAction(reply));
-
-    processDeferredActions();
-}
-
-status_t NuPlayer2::setVideoScalingMode(int32_t mode) {
-    mVideoScalingMode = mode;
-    if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
-        status_t ret = native_window_set_scaling_mode(
-                mNativeWindow->getANativeWindow(), mVideoScalingMode);
-        if (ret != OK) {
-            ALOGE("Failed to set scaling mode (%d): %s",
-                -ret, strerror(-ret));
-            return ret;
-        }
-    }
-    return OK;
-}
-
-status_t NuPlayer2::getTrackInfo(int64_t srcId, PlayerMessage* reply) const {
-    sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
-    msg->setInt64("srcId", srcId);
-    msg->setPointer("reply", reply);
-
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    return err;
-}
-
-status_t NuPlayer2::getSelectedTrack(int64_t srcId, int32_t type, PlayerMessage* reply) const {
-    sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
-    msg->setPointer("reply", reply);
-    msg->setInt64("srcId", srcId);
-    msg->setInt32("type", type);
-
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-status_t NuPlayer2::selectTrack(int64_t srcId, size_t trackIndex, bool select, int64_t timeUs) {
-    sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
-    msg->setInt64("srcId", srcId);
-    msg->setSize("trackIndex", trackIndex);
-    msg->setInt32("select", select);
-    msg->setInt64("timeUs", timeUs);
-
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-
-    if (err != OK) {
-        return err;
-    }
-
-    if (!response->findInt32("err", &err)) {
-        err = OK;
-    }
-
-    return err;
-}
-
-status_t NuPlayer2::getCurrentPosition(int64_t *mediaUs) {
-    sp<Renderer> renderer = mRenderer;
-    if (renderer == NULL) {
-        return NO_INIT;
-    }
-
-    return renderer->getCurrentPosition(mediaUs);
-}
-
-void NuPlayer2::getStats(Vector<sp<AMessage> > *mTrackStats) {
-    CHECK(mTrackStats != NULL);
-
-    mTrackStats->clear();
-
-    Mutex::Autolock autoLock(mDecoderLock);
-    if (mVideoDecoder != NULL) {
-        mTrackStats->push_back(mVideoDecoder->getStats());
-    }
-    if (mAudioDecoder != NULL) {
-        mTrackStats->push_back(mAudioDecoder->getStats());
-    }
-}
-
-sp<MetaData> NuPlayer2::getFileMeta() {
-    return mCurrentSourceInfo.mSource->getFileFormatMeta();
-}
-
-float NuPlayer2::getFrameRate() {
-    sp<MetaData> meta = mCurrentSourceInfo.mSource->getFormatMeta(false /* audio */);
-    if (meta == NULL) {
-        return 0;
-    }
-    int32_t rate;
-    if (!meta->findInt32(kKeyFrameRate, &rate)) {
-        // fall back to try file meta
-        sp<MetaData> fileMeta = getFileMeta();
-        if (fileMeta == NULL) {
-            ALOGW("source has video meta but not file meta");
-            return -1;
-        }
-        int32_t fileMetaRate;
-        if (!fileMeta->findInt32(kKeyFrameRate, &fileMetaRate)) {
-            return -1;
-        }
-        return fileMetaRate;
-    }
-    return rate;
-}
-
-void NuPlayer2::schedulePollDuration() {
-    sp<AMessage> msg = new AMessage(kWhatPollDuration, this);
-    msg->setInt32("generation", mPollDurationGeneration);
-    msg->post();
-}
-
-void NuPlayer2::cancelPollDuration() {
-    ++mPollDurationGeneration;
-}
-
-void NuPlayer2::processDeferredActions() {
-    while (!mDeferredActions.empty()) {
-        // We won't execute any deferred actions until we're no longer in
-        // an intermediate state, i.e. one more more decoders are currently
-        // flushing or shutting down.
-
-        if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
-            // We're currently flushing, postpone the reset until that's
-            // completed.
-
-            ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
-                  mFlushingAudio, mFlushingVideo);
-
-            break;
-        }
-
-        sp<Action> action = *mDeferredActions.begin();
-        mDeferredActions.erase(mDeferredActions.begin());
-
-        action->execute(this);
-    }
-}
-
-void NuPlayer2::performSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
-    ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), mode=%d",
-          (long long)seekTimeUs, seekTimeUs / 1E6, mode);
-
-    if (mCurrentSourceInfo.mSource == NULL) {
-        // This happens when reset occurs right before the loop mode
-        // asynchronously seeks to the start of the stream.
-        LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL,
-                "mCurrentSourceInfo.mSource is NULL and decoders not NULL audio(%p) video(%p)",
-                mAudioDecoder.get(), mVideoDecoder.get());
-        return;
-    }
-    mPreviousSeekTimeUs = seekTimeUs;
-    mCurrentSourceInfo.mSource->seekTo(seekTimeUs, mode);
-    ++mTimedTextGeneration;
-
-    // everything's flushed, continue playback.
-}
-
-void NuPlayer2::performDecoderFlush(FlushCommand audio, FlushCommand video) {
-    ALOGV("performDecoderFlush audio=%d, video=%d", audio, video);
-
-    if ((audio == FLUSH_CMD_NONE || mAudioDecoder == NULL)
-            && (video == FLUSH_CMD_NONE || mVideoDecoder == NULL)) {
-        return;
-    }
-
-    if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) {
-        flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN));
-    }
-
-    if (video != FLUSH_CMD_NONE && mVideoDecoder != NULL) {
-        flushDecoder(false /* audio */, (video == FLUSH_CMD_SHUTDOWN));
-    }
-}
-
-void NuPlayer2::performReset() {
-    ALOGV("performReset");
-
-    CHECK(mAudioDecoder == NULL);
-    CHECK(mVideoDecoder == NULL);
-
-    stopPlaybackTimer("performReset");
-    stopRebufferingTimer(true);
-
-    cancelPollDuration();
-
-    ++mScanSourcesGeneration;
-    mScanSourcesPending = false;
-
-    if (mRendererLooper != NULL) {
-        if (mRenderer != NULL) {
-            mRendererLooper->unregisterHandler(mRenderer->id());
-        }
-        mRendererLooper->stop();
-        mRendererLooper.clear();
-    }
-    mRenderer.clear();
-    ++mRendererGeneration;
-
-    resetSourceInfo(mCurrentSourceInfo);
-    resetSourceInfo(mNextSourceInfo);
-
-    if (mDriver != NULL) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            driver->notifyResetComplete(mCurrentSourceInfo.mSrcId);
-        }
-    }
-
-    mStarted = false;
-    mPrepared = false;
-    mResetting = false;
-    mSourceStarted = false;
-
-}
-
-void NuPlayer2::performPlayNextDataSource() {
-    ALOGV("performPlayNextDataSource");
-
-    CHECK(mAudioDecoder == NULL);
-    CHECK(mVideoDecoder == NULL);
-
-    stopPlaybackTimer("performPlayNextDataSource");
-    stopRebufferingTimer(true);
-
-    cancelPollDuration();
-
-    ++mScanSourcesGeneration;
-    mScanSourcesPending = false;
-
-    ++mRendererGeneration;
-
-    if (mCurrentSourceInfo.mSource != NULL) {
-        mCurrentSourceInfo.mSource->stop();
-    }
-
-    long previousSrcId;
-    {
-        Mutex::Autolock autoLock(mSourceLock);
-        previousSrcId = mCurrentSourceInfo.mSrcId;
-
-        mCurrentSourceInfo = mNextSourceInfo;
-        mNextSourceInfo = SourceInfo();
-        mNextSourceInfo.mSrcId = ~mCurrentSourceInfo.mSrcId;  // to distinguish the two sources.
-    }
-
-    if (mDriver != NULL) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            notifyListener(previousSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_END, 0);
-
-            int64_t durationUs;
-            if (mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
-                driver->notifyDuration(mCurrentSourceInfo.mSrcId, durationUs);
-            }
-            notifyListener(
-                    mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
-        }
-    }
-
-    mStarted = false;
-    mPrepared = true;  // TODO: what if it's not prepared
-    mResetting = false;
-    mSourceStarted = false;
-
-    addEndTimeMonitor();
-
-    if (mRenderer != NULL) {
-        mRenderer->resume();
-    }
-
-    onStart(true /* play */);
-    mPausedByClient = false;
-    notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_STARTED, 0, 0);
-}
-
-void NuPlayer2::performScanSources() {
-    ALOGV("performScanSources");
-
-    if (!mStarted) {
-        return;
-    }
-
-    if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
-        postScanSources();
-    }
-}
-
-void NuPlayer2::performSetSurface(const sp<ANativeWindowWrapper> &nww) {
-    ALOGV("performSetSurface");
-
-    mNativeWindow = nww;
-
-    // XXX - ignore error from setVideoScalingMode for now
-    setVideoScalingMode(mVideoScalingMode);
-
-    if (mDriver != NULL) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            driver->notifySetSurfaceComplete(mCurrentSourceInfo.mSrcId);
-        }
-    }
-}
-
-void NuPlayer2::performResumeDecoders(bool needNotify) {
-    if (needNotify) {
-        mResumePending = true;
-        if (mVideoDecoder == NULL) {
-            // if audio-only, we can notify seek complete now,
-            // as the resume operation will be relatively fast.
-            finishResume();
-        }
-    }
-
-    if (mVideoDecoder != NULL) {
-        // When there is continuous seek, MediaPlayer will cache the seek
-        // position, and send down new seek request when previous seek is
-        // complete. Let's wait for at least one video output frame before
-        // notifying seek complete, so that the video thumbnail gets updated
-        // when seekbar is dragged.
-        mVideoDecoder->signalResume(needNotify);
-    }
-
-    if (mAudioDecoder != NULL) {
-        mAudioDecoder->signalResume(false /* needNotify */);
-    }
-}
-
-void NuPlayer2::finishResume() {
-    if (mResumePending) {
-        mResumePending = false;
-        notifyDriverSeekComplete(mCurrentSourceInfo.mSrcId);
-    }
-}
-
-void NuPlayer2::notifyDriverSeekComplete(int64_t srcId) {
-    if (mDriver != NULL) {
-        sp<NuPlayer2Driver> driver = mDriver.promote();
-        if (driver != NULL) {
-            driver->notifySeekComplete(srcId);
-        }
-    }
-}
-
-void NuPlayer2::onSourceNotify(const sp<AMessage> &msg) {
-    int32_t what;
-    CHECK(msg->findInt32("what", &what));
-
-    int64_t srcId;
-    CHECK(msg->findInt64("srcId", &srcId));
-    switch (what) {
-        case Source::kWhatPrepared:
-        {
-            ALOGV("NuPlayer2::onSourceNotify Source::kWhatPrepared source:%p, Id(%lld)",
-                  mCurrentSourceInfo.mSource.get(), (long long)srcId);
-            if (srcId == mCurrentSourceInfo.mSrcId) {
-                if (mCurrentSourceInfo.mSource == NULL) {
-                    // This is a stale notification from a source that was
-                    // asynchronously preparing when the client called reset().
-                    // We handled the reset, the source is gone.
-                    break;
-                }
-
-                int32_t err;
-                CHECK(msg->findInt32("err", &err));
-
-                if (err != OK) {
-                    // shut down potential secure codecs in case client never calls reset
-                    mDeferredActions.push_back(
-                            new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
-                                                   FLUSH_CMD_SHUTDOWN /* video */));
-                    processDeferredActions();
-                } else {
-                    mPrepared = true;
-                }
-
-                sp<NuPlayer2Driver> driver = mDriver.promote();
-                if (driver != NULL) {
-                    // notify duration first, so that it's definitely set when
-                    // the app received the "prepare complete" callback.
-                    int64_t durationUs;
-                    if (mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
-                        driver->notifyDuration(srcId, durationUs);
-                    }
-                    driver->notifyPrepareCompleted(srcId, err);
-                }
-            } else if (srcId == mNextSourceInfo.mSrcId) {
-                if (mNextSourceInfo.mSource == NULL) {
-                    break;  // stale
-                }
-
-                sp<NuPlayer2Driver> driver = mDriver.promote();
-                if (driver != NULL) {
-                    int32_t err;
-                    CHECK(msg->findInt32("err", &err));
-                    driver->notifyPrepareCompleted(srcId, err);
-                }
-            }
-
-            break;
-        }
-
-        // Modular DRM
-        case Source::kWhatDrmInfo:
-        {
-            PlayerMessage playerMsg;
-            sp<ABuffer> drmInfo;
-            CHECK(msg->findBuffer("drmInfo", &drmInfo));
-            playerMsg.ParseFromArray(drmInfo->data(), drmInfo->size());
-
-            ALOGV("onSourceNotify() kWhatDrmInfo MEDIA2_DRM_INFO drmInfo: %p  playerMsg size: %d",
-                    drmInfo.get(), playerMsg.ByteSize());
-
-            notifyListener(srcId, MEDIA2_DRM_INFO, 0 /* ext1 */, 0 /* ext2 */, &playerMsg);
-
-            break;
-        }
-
-        case Source::kWhatFlagsChanged:
-        {
-            uint32_t flags;
-            CHECK(msg->findInt32("flags", (int32_t *)&flags));
-
-            sp<NuPlayer2Driver> driver = mDriver.promote();
-            if (driver != NULL) {
-
-                ALOGV("onSourceNotify() kWhatFlagsChanged  FLAG_CAN_PAUSE: %d  "
-                        "FLAG_CAN_SEEK_BACKWARD: %d \n\t\t\t\t FLAG_CAN_SEEK_FORWARD: %d  "
-                        "FLAG_CAN_SEEK: %d  FLAG_DYNAMIC_DURATION: %d \n"
-                        "\t\t\t\t FLAG_SECURE: %d  FLAG_PROTECTED: %d",
-                        (flags & Source::FLAG_CAN_PAUSE) != 0,
-                        (flags & Source::FLAG_CAN_SEEK_BACKWARD) != 0,
-                        (flags & Source::FLAG_CAN_SEEK_FORWARD) != 0,
-                        (flags & Source::FLAG_CAN_SEEK) != 0,
-                        (flags & Source::FLAG_DYNAMIC_DURATION) != 0,
-                        (flags & Source::FLAG_SECURE) != 0,
-                        (flags & Source::FLAG_PROTECTED) != 0);
-
-                if ((flags & NuPlayer2::Source::FLAG_CAN_SEEK) == 0) {
-                    driver->notifyListener(
-                            srcId, MEDIA2_INFO, MEDIA2_INFO_NOT_SEEKABLE, 0);
-                }
-                if (srcId == mCurrentSourceInfo.mSrcId) {
-                    driver->notifyFlagsChanged(srcId, flags);
-                }
-            }
-
-            if (srcId == mCurrentSourceInfo.mSrcId) {
-                if ((mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
-                        && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
-                    cancelPollDuration();
-                } else if (!(mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
-                        && (flags & Source::FLAG_DYNAMIC_DURATION)
-                        && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
-                    schedulePollDuration();
-                }
-
-                mCurrentSourceInfo.mSourceFlags = flags;
-            } else if (srcId == mNextSourceInfo.mSrcId) {
-                // TODO: handle duration polling for next source.
-                mNextSourceInfo.mSourceFlags = flags;
-            }
-            break;
-        }
-
-        case Source::kWhatVideoSizeChanged:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-
-            updateVideoSize(srcId, format);
-            break;
-        }
-
-        case Source::kWhatBufferingUpdate:
-        {
-            int32_t percentage;
-            CHECK(msg->findInt32("percentage", &percentage));
-
-            notifyListener(srcId, MEDIA2_BUFFERING_UPDATE, percentage, 0);
-            break;
-        }
-
-        case Source::kWhatPauseOnBufferingStart:
-        {
-            // ignore if not playing
-            if (mStarted) {
-                ALOGI("buffer low, pausing...");
-
-                startRebufferingTimer();
-                mPausedForBuffering = true;
-                onPause();
-            }
-            notifyListener(srcId, MEDIA2_INFO, MEDIA2_INFO_BUFFERING_START, 0);
-            break;
-        }
-
-        case Source::kWhatResumeOnBufferingEnd:
-        {
-            // ignore if not playing
-            if (mStarted) {
-                ALOGI("buffer ready, resuming...");
-
-                stopRebufferingTimer(false);
-                mPausedForBuffering = false;
-
-                // do not resume yet if client didn't unpause
-                if (!mPausedByClient) {
-                    onResume();
-                }
-            }
-            notifyListener(srcId, MEDIA2_INFO, MEDIA2_INFO_BUFFERING_END, 0);
-            break;
-        }
-
-        case Source::kWhatCacheStats:
-        {
-            int32_t kbps;
-            CHECK(msg->findInt32("bandwidth", &kbps));
-
-            notifyListener(srcId, MEDIA2_INFO, MEDIA2_INFO_NETWORK_BANDWIDTH, kbps);
-            break;
-        }
-
-        case Source::kWhatSubtitleData:
-        {
-            sp<ABuffer> buffer;
-            CHECK(msg->findBuffer("buffer", &buffer));
-
-            sendSubtitleData(buffer, 0 /* baseIndex */);
-            break;
-        }
-
-        case Source::kWhatTimedMetaData:
-        {
-            sp<ABuffer> buffer;
-            if (!msg->findBuffer("buffer", &buffer)) {
-                notifyListener(srcId, MEDIA2_INFO, MEDIA2_INFO_METADATA_UPDATE, 0);
-            } else {
-                sendTimedMetaData(buffer);
-            }
-            break;
-        }
-
-        case Source::kWhatTimedTextData:
-        {
-            int32_t generation;
-            if (msg->findInt32("generation", &generation)
-                    && generation != mTimedTextGeneration) {
-                break;
-            }
-
-            sp<ABuffer> buffer;
-            CHECK(msg->findBuffer("buffer", &buffer));
-
-            sp<NuPlayer2Driver> driver = mDriver.promote();
-            if (driver == NULL) {
-                break;
-            }
-
-            int64_t posMs;
-            int64_t timeUs, posUs;
-            driver->getCurrentPosition(&posMs);
-            posUs = posMs * 1000LL;
-            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
-            if (posUs < timeUs) {
-                if (!msg->findInt32("generation", &generation)) {
-                    msg->setInt32("generation", mTimedTextGeneration);
-                }
-                msg->post(timeUs - posUs);
-            } else {
-                sendTimedTextData(buffer);
-            }
-            break;
-        }
-
-        case Source::kWhatQueueDecoderShutdown:
-        {
-            int32_t audio, video;
-            CHECK(msg->findInt32("audio", &audio));
-            CHECK(msg->findInt32("video", &video));
-
-            sp<AMessage> reply;
-            CHECK(msg->findMessage("reply", &reply));
-
-            queueDecoderShutdown(audio, video, reply);
-            break;
-        }
-
-        case Source::kWhatDrmNoLicense:
-        {
-            notifyListener(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-}
-
-void NuPlayer2::onClosedCaptionNotify(const sp<AMessage> &msg) {
-    int32_t what;
-    CHECK(msg->findInt32("what", &what));
-
-    switch (what) {
-        case NuPlayer2::CCDecoder::kWhatClosedCaptionData:
-        {
-            sp<ABuffer> buffer;
-            CHECK(msg->findBuffer("buffer", &buffer));
-
-            size_t inbandTracks = 0;
-            if (mCurrentSourceInfo.mSource != NULL) {
-                inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
-            }
-
-            sendSubtitleData(buffer, inbandTracks);
-            break;
-        }
-
-        case NuPlayer2::CCDecoder::kWhatTrackAdded:
-        {
-            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_METADATA_UPDATE, 0);
-
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-
-
-}
-
-void NuPlayer2::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) {
-    int32_t trackIndex;
-    int64_t timeUs, durationUs;
-    CHECK(buffer->meta()->findInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, &trackIndex));
-    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-    CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
-
-    PlayerMessage playerMsg;
-    playerMsg.add_values()->set_int32_value(trackIndex + baseIndex);
-    playerMsg.add_values()->set_int64_value(timeUs);
-    playerMsg.add_values()->set_int64_value(durationUs);
-    playerMsg.add_values()->set_bytes_value(buffer->data(), buffer->size());
-
-    notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_SUBTITLE_DATA, 0, 0, &playerMsg);
-}
-
-void NuPlayer2::sendTimedMetaData(const sp<ABuffer> &buffer) {
-    int64_t timeUs;
-    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
-    PlayerMessage playerMsg;
-    playerMsg.add_values()->set_int64_value(timeUs);
-    playerMsg.add_values()->set_bytes_value(buffer->data(), buffer->size());
-
-    notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_META_DATA, 0, 0, &playerMsg);
-}
-
-void NuPlayer2::sendTimedTextData(const sp<ABuffer> &buffer) {
-    const void *data;
-    size_t size = 0;
-    int64_t timeUs;
-    int32_t flag = TextDescriptions2::IN_BAND_TEXT_3GPP;
-
-    AString mime;
-    CHECK(buffer->meta()->findString("mime", &mime));
-    CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0);
-
-    data = buffer->data();
-    size = buffer->size();
-
-    PlayerMessage playerMsg;
-    if (size > 0) {
-        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-        int32_t global = 0;
-        if (buffer->meta()->findInt32("global", &global) && global) {
-            flag |= TextDescriptions2::GLOBAL_DESCRIPTIONS;
-        } else {
-            flag |= TextDescriptions2::LOCAL_DESCRIPTIONS;
-        }
-        TextDescriptions2::getPlayerMessageOfDescriptions(
-                (const uint8_t *)data, size, flag, timeUs / 1000, &playerMsg);
-    }
-
-    if (playerMsg.values_size() > 0) {
-        notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_TIMED_TEXT, 0, 0, &playerMsg);
-    } else {  // send an empty timed text
-        notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_TIMED_TEXT, 0, 0);
-    }
-}
-
-const char *NuPlayer2::getDataSourceType() {
-    switch (mCurrentSourceInfo.mDataSourceType) {
-        case DATA_SOURCE_TYPE_HTTP_LIVE:
-            return "HTTPLive";
-
-        case DATA_SOURCE_TYPE_RTSP:
-            return "RTSP";
-
-        case DATA_SOURCE_TYPE_GENERIC_URL:
-            return "GenURL";
-
-        case DATA_SOURCE_TYPE_GENERIC_FD:
-            return "GenFD";
-
-        case DATA_SOURCE_TYPE_MEDIA:
-            return "Media";
-
-        case DATA_SOURCE_TYPE_NONE:
-        default:
-            return "None";
-    }
- }
-
-NuPlayer2::SourceInfo* NuPlayer2::getSourceInfoByIdInMsg(const sp<AMessage> &msg) {
-    int64_t srcId;
-    CHECK(msg->findInt64("srcId", &srcId));
-    if (mCurrentSourceInfo.mSrcId == srcId) {
-        return &mCurrentSourceInfo;
-    } else if (mNextSourceInfo.mSrcId == srcId) {
-        return &mNextSourceInfo;
-    } else {
-        return NULL;
-    }
-}
-
-void NuPlayer2::resetSourceInfo(NuPlayer2::SourceInfo &srcInfo) {
-    if (srcInfo.mSource != NULL) {
-        srcInfo.mSource->stop();
-
-        Mutex::Autolock autoLock(mSourceLock);
-        srcInfo.mSource.clear();
-    }
-    // Modular DRM
-    ALOGD("performReset mCrypto: %p", srcInfo.mCrypto.get());
-    srcInfo.mCrypto.clear();
-    srcInfo.mIsDrmProtected = false;
-}
-
-// Modular DRM begin
-status_t NuPlayer2::prepareDrm(
-        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
-{
-    ALOGV("prepareDrm ");
-
-    // Passing to the looper anyway; called in a pre-config prepared state so no race on mCrypto
-    sp<AMessage> msg = new AMessage(kWhatPrepareDrm, this);
-    // synchronous call so just passing the address but with local copies of "const" args
-    uint8_t UUID[16];
-    memcpy(UUID, uuid, sizeof(UUID));
-    Vector<uint8_t> sessionId = drmSessionId;
-    msg->setInt64("srcId", srcId);
-    msg->setPointer("uuid", (void*)UUID);
-    msg->setPointer("drmSessionId", (void*)&sessionId);
-
-    sp<AMessage> response;
-    status_t status = msg->postAndAwaitResponse(&response);
-
-    if (status == OK && response != NULL) {
-        CHECK(response->findInt32("status", &status));
-        ALOGV("prepareDrm ret: %d ", status);
-    } else {
-        ALOGE("prepareDrm err: %d", status);
-    }
-
-    return status;
-}
-
-status_t NuPlayer2::releaseDrm(int64_t srcId)
-{
-    ALOGV("releaseDrm ");
-
-    sp<AMessage> msg = new AMessage(kWhatReleaseDrm, this);
-    msg->setInt64("srcId", srcId);
-
-    sp<AMessage> response;
-    status_t status = msg->postAndAwaitResponse(&response);
-
-    if (status == OK && response != NULL) {
-        CHECK(response->findInt32("status", &status));
-        ALOGV("releaseDrm ret: %d ", status);
-    } else {
-        ALOGE("releaseDrm err: %d", status);
-    }
-
-    return status;
-}
-
-status_t NuPlayer2::onPrepareDrm(const sp<AMessage> &msg)
-{
-    // TODO change to ALOGV
-    ALOGD("onPrepareDrm ");
-
-    status_t status = INVALID_OPERATION;
-    SourceInfo *srcInfo = getSourceInfoByIdInMsg(msg);
-    if (srcInfo == NULL) {
-        return status;
-    }
-
-    int64_t srcId = srcInfo->mSrcId;
-    if (srcInfo->mSource == NULL) {
-        ALOGE("onPrepareDrm: srcInfo(%lld) No source. onPrepareDrm failed with %d.",
-                (long long)srcId, status);
-        return status;
-    }
-
-    uint8_t *uuid;
-    Vector<uint8_t> *drmSessionId;
-    CHECK(msg->findPointer("uuid", (void**)&uuid));
-    CHECK(msg->findPointer("drmSessionId", (void**)&drmSessionId));
-
-    status = OK;
-    sp<AMediaCryptoWrapper> crypto = NULL;
-
-    status = srcInfo->mSource->prepareDrm(uuid, *drmSessionId, &crypto);
-    if (crypto == NULL) {
-        ALOGE("onPrepareDrm: srcInfo(%lld).mSource->prepareDrm failed. status: %d",
-                (long long)srcId, status);
-        return status;
-    }
-    ALOGV("onPrepareDrm: srcInfo(%lld).mSource->prepareDrm succeeded", (long long)srcId);
-
-    if (srcInfo->mCrypto != NULL) {
-        ALOGE("onPrepareDrm: srcInfo(%lld) Unexpected. Already having mCrypto: %p",
-                (long long)srcId, srcInfo->mCrypto.get());
-        srcInfo->mCrypto.clear();
-    }
-
-    srcInfo->mCrypto = crypto;
-    srcInfo->mIsDrmProtected = true;
-    // TODO change to ALOGV
-    ALOGD("onPrepareDrm: mCrypto: %p", srcInfo->mCrypto.get());
-
-    return status;
-}
-
-status_t NuPlayer2::onReleaseDrm(const sp<AMessage> &msg)
-{
-    // TODO change to ALOGV
-    ALOGD("onReleaseDrm ");
-    SourceInfo *srcInfo = getSourceInfoByIdInMsg(msg);;
-    if (srcInfo == NULL) {
-        return INVALID_OPERATION;
-    }
-
-    int64_t srcId = srcInfo->mSrcId;
-    if (!srcInfo->mIsDrmProtected) {
-        ALOGW("onReleaseDrm: srcInfo(%lld) Unexpected. mIsDrmProtected is already false.",
-                (long long)srcId);
-    }
-
-    srcInfo->mIsDrmProtected = false;
-
-    status_t status;
-    if (srcInfo->mCrypto != NULL) {
-        // notifying the source first before removing crypto from codec
-        if (srcInfo->mSource != NULL) {
-            srcInfo->mSource->releaseDrm();
-        }
-
-        status=OK;
-        // first making sure the codecs have released their crypto reference
-        const sp<DecoderBase> &videoDecoder = getDecoder(false/*audio*/);
-        if (videoDecoder != NULL) {
-            status = videoDecoder->releaseCrypto();
-            ALOGV("onReleaseDrm: video decoder ret: %d", status);
-        }
-
-        const sp<DecoderBase> &audioDecoder = getDecoder(true/*audio*/);
-        if (audioDecoder != NULL) {
-            status_t status_audio = audioDecoder->releaseCrypto();
-            if (status == OK) {   // otherwise, returning the first error
-                status = status_audio;
-            }
-            ALOGV("onReleaseDrm: audio decoder ret: %d", status_audio);
-        }
-
-        // TODO change to ALOGV
-        ALOGD("onReleaseDrm: mCrypto: %p", srcInfo->mCrypto.get());
-        srcInfo->mCrypto.clear();
-    } else {   // srcInfo->mCrypto == NULL
-        ALOGE("onReleaseDrm: Unexpected. There is no crypto.");
-        status = INVALID_OPERATION;
-    }
-
-    return status;
-}
-// Modular DRM end
-////////////////////////////////////////////////////////////////////////////////
-
-sp<AMessage> NuPlayer2::Source::getFormat(bool audio) {
-    sp<MetaData> meta = getFormatMeta(audio);
-
-    if (meta == NULL) {
-        return NULL;
-    }
-
-    sp<AMessage> msg = new AMessage;
-
-    if(convertMetaDataToMessage(meta, &msg) == OK) {
-        return msg;
-    }
-    return NULL;
-}
-
-void NuPlayer2::Source::notifyFlagsChanged(uint32_t flags) {
-    sp<AMessage> notify = dupNotify();
-    notify->setInt32("what", kWhatFlagsChanged);
-    notify->setInt32("flags", flags);
-    notify->post();
-}
-
-void NuPlayer2::Source::notifyVideoSizeChanged(const sp<AMessage> &format) {
-    sp<AMessage> notify = dupNotify();
-    notify->setInt32("what", kWhatVideoSizeChanged);
-    notify->setMessage("format", format);
-    notify->post();
-}
-
-void NuPlayer2::Source::notifyPrepared(status_t err) {
-    ALOGV("Source::notifyPrepared %d", err);
-    sp<AMessage> notify = dupNotify();
-    notify->setInt32("what", kWhatPrepared);
-    notify->setInt32("err", err);
-    notify->post();
-}
-
-void NuPlayer2::Source::notifyDrmInfo(const sp<ABuffer> &drmInfoBuffer)
-{
-    ALOGV("Source::notifyDrmInfo");
-
-    sp<AMessage> notify = dupNotify();
-    notify->setInt32("what", kWhatDrmInfo);
-    notify->setBuffer("drmInfo", drmInfoBuffer);
-
-    notify->post();
-}
-
-void NuPlayer2::Source::onMessageReceived(const sp<AMessage> & /* msg */) {
-    TRESPASS();
-}
-
-NuPlayer2::SourceInfo::SourceInfo()
-    : mDataSourceType(DATA_SOURCE_TYPE_NONE),
-      mSrcId(0),
-      mSourceFlags(0),
-      mStartTimeUs(0),
-      mEndTimeUs(DataSourceDesc::kMaxTimeUs) {
-}
-
-NuPlayer2::SourceInfo & NuPlayer2::SourceInfo::operator=(const NuPlayer2::SourceInfo &other) {
-    mSource = other.mSource;
-    mCrypto = other.mCrypto;
-    mDataSourceType = (DATA_SOURCE_TYPE)other.mDataSourceType;
-    mSrcId = other.mSrcId;
-    mSourceFlags = other.mSourceFlags;
-    mStartTimeUs = other.mStartTimeUs;
-    mEndTimeUs = other.mEndTimeUs;
-    mIsDrmProtected = other.mIsDrmProtected;
-    return *this;
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
deleted file mode 100644
index b8fb988..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright 2017 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 NU_PLAYER2_H_
-
-#define NU_PLAYER2_H_
-
-#include <media/AudioResamplerPublic.h>
-#include <media/stagefright/foundation/AHandler.h>
-
-#include <mediaplayer2/MediaPlayer2Interface.h>
-#include <mediaplayer2/JObjectHolder.h>
-
-#include "mediaplayer2.pb.h"
-
-using android::media::MediaPlayer2Proto::PlayerMessage;
-
-namespace android {
-
-struct ABuffer;
-struct AMediaCryptoWrapper;
-struct AMessage;
-struct ANativeWindowWrapper;
-struct AudioPlaybackRate;
-struct AVSyncSettings;
-struct DataSourceDesc;
-struct MediaClock;
-struct MediaHTTPService;
-class MetaData;
-struct NuPlayer2Driver;
-
-struct NuPlayer2 : public AHandler {
-    explicit NuPlayer2(pid_t pid, uid_t uid,
-            const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context);
-
-    void setDriver(const wp<NuPlayer2Driver> &driver);
-
-    void setDataSourceAsync(const sp<DataSourceDesc> &dsd);
-    void prepareNextDataSourceAsync(const sp<DataSourceDesc> &dsd);
-    void playNextDataSource(int64_t srcId);
-
-    status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
-    status_t setBufferingSettings(const BufferingSettings& buffering);
-
-    void prepareAsync();
-
-    void setVideoSurfaceTextureAsync(const sp<ANativeWindowWrapper> &nww);
-
-    void setAudioSink(const sp<MediaPlayer2Interface::AudioSink> &sink);
-    status_t setPlaybackSettings(const AudioPlaybackRate &rate);
-    status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-    status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint);
-    status_t getSyncSettings(AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */);
-
-    void start();
-
-    void pause();
-
-    // Will notify the driver through "notifyResetComplete" once finished.
-    void resetAsync();
-
-    // Request a notification when specified media time is reached.
-    status_t notifyAt(int64_t mediaTimeUs);
-
-    // Will notify the driver through "notifySeekComplete" once finished
-    // and needNotify is true.
-    void seekToAsync(
-            int64_t seekTimeUs,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC,
-            bool needNotify = false);
-    void rewind();
-
-    status_t setVideoScalingMode(int32_t mode);
-    status_t getTrackInfo(int64_t srcId, PlayerMessage* reply) const;
-    status_t getSelectedTrack(int64_t srcId, int32_t type, PlayerMessage* reply) const;
-    status_t selectTrack(int64_t srcId, size_t trackIndex, bool select, int64_t timeUs);
-    status_t getCurrentPosition(int64_t *mediaUs);
-    void getStats(Vector<sp<AMessage> > *mTrackStats);
-
-    sp<MetaData> getFileMeta();
-    float getFrameRate();
-
-    // Modular DRM
-    status_t prepareDrm(int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
-    status_t releaseDrm(int64_t srcId);
-
-    const char *getDataSourceType();
-
-protected:
-    virtual ~NuPlayer2();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-public:
-    struct StreamListener;
-    struct Source;
-
-private:
-    struct Decoder;
-    struct DecoderBase;
-    struct DecoderPassThrough;
-    struct CCDecoder;
-    struct GenericSource2;
-    struct HTTPLiveSource2;
-    struct Renderer;
-    struct RTSPSource2;
-    struct Action;
-    struct SeekAction;
-    struct SetSurfaceAction;
-    struct ResumeDecoderAction;
-    struct FlushDecoderAction;
-    struct PostMessageAction;
-    struct SimpleAction;
-
-    enum {
-        kWhatSetDataSource              = '=DaS',
-        kWhatPrepare                    = 'prep',
-        kWhatPrepareNextDataSource      = 'pNDS',
-        kWhatPlayNextDataSource         = 'plNS',
-        kWhatSetVideoSurface            = '=VSu',
-        kWhatSetAudioSink               = '=AuS',
-        kWhatMoreDataQueued             = 'more',
-        kWhatConfigPlayback             = 'cfPB',
-        kWhatConfigSync                 = 'cfSy',
-        kWhatGetPlaybackSettings        = 'gPbS',
-        kWhatGetSyncSettings            = 'gSyS',
-        kWhatStart                      = 'strt',
-        kWhatScanSources                = 'scan',
-        kWhatVideoNotify                = 'vidN',
-        kWhatAudioNotify                = 'audN',
-        kWhatClosedCaptionNotify        = 'capN',
-        kWhatRendererNotify             = 'renN',
-        kWhatReset                      = 'rset',
-        kWhatNotifyTime                 = 'nfyT',
-        kWhatSeek                       = 'seek',
-        kWhatPause                      = 'paus',
-        kWhatResume                     = 'rsme',
-        kWhatPollDuration               = 'polD',
-        kWhatSourceNotify               = 'srcN',
-        kWhatGetTrackInfo               = 'gTrI',
-        kWhatGetSelectedTrack           = 'gSel',
-        kWhatSelectTrack                = 'selT',
-        kWhatGetBufferingSettings       = 'gBus',
-        kWhatSetBufferingSettings       = 'sBuS',
-        kWhatPrepareDrm                 = 'pDrm',
-        kWhatReleaseDrm                 = 'rDrm',
-        kWhatRewind                     = 'reWd',
-        kWhatEOSMonitor                 = 'eosM',
-    };
-
-    typedef enum {
-        DATA_SOURCE_TYPE_NONE,
-        DATA_SOURCE_TYPE_HTTP_LIVE,
-        DATA_SOURCE_TYPE_RTSP,
-        DATA_SOURCE_TYPE_GENERIC_URL,
-        DATA_SOURCE_TYPE_GENERIC_FD,
-        DATA_SOURCE_TYPE_MEDIA,
-    } DATA_SOURCE_TYPE;
-
-    struct SourceInfo {
-        SourceInfo();
-        SourceInfo &operator=(const SourceInfo &);
-
-        sp<Source> mSource;
-        std::atomic<DATA_SOURCE_TYPE> mDataSourceType;
-        int64_t mSrcId;
-        uint32_t mSourceFlags;
-        int64_t mStartTimeUs;
-        int64_t mEndTimeUs;
-        // Modular DRM
-        sp<AMediaCryptoWrapper> mCrypto;
-        bool mIsDrmProtected = false;
-    };
-
-    wp<NuPlayer2Driver> mDriver;
-    pid_t mPID;
-    uid_t mUID;
-    const sp<MediaClock> mMediaClock;
-    Mutex mSourceLock;  // guard |mSource|.
-    SourceInfo mCurrentSourceInfo;
-    SourceInfo mNextSourceInfo;
-    sp<ANativeWindowWrapper> mNativeWindow;
-    sp<MediaPlayer2Interface::AudioSink> mAudioSink;
-    sp<DecoderBase> mVideoDecoder;
-    bool mOffloadAudio;
-    sp<DecoderBase> mAudioDecoder;
-    Mutex mDecoderLock;  // guard |mAudioDecoder| and |mVideoDecoder|.
-    sp<CCDecoder> mCCDecoder;
-    sp<Renderer> mRenderer;
-    sp<ALooper> mRendererLooper;
-    int32_t mAudioDecoderGeneration;
-    int32_t mVideoDecoderGeneration;
-    int32_t mRendererGeneration;
-    int32_t mEOSMonitorGeneration;
-
-    Mutex mPlayingTimeLock;
-    int64_t mLastStartedPlayingTimeNs;
-    void stopPlaybackTimer(const char *where);
-    void startPlaybackTimer(const char *where);
-
-    int64_t mLastStartedRebufferingTimeNs;
-    void startRebufferingTimer();
-    void stopRebufferingTimer(bool exitingPlayback);
-
-    int64_t mPreviousSeekTimeUs;
-
-    List<sp<Action> > mDeferredActions;
-
-    bool mAudioEOS;
-    bool mVideoEOS;
-
-    bool mScanSourcesPending;
-    int32_t mScanSourcesGeneration;
-
-    int32_t mPollDurationGeneration;
-    int32_t mTimedTextGeneration;
-
-    enum FlushStatus {
-        NONE,
-        FLUSHING_DECODER,
-        FLUSHING_DECODER_SHUTDOWN,
-        SHUTTING_DOWN_DECODER,
-        FLUSHED,
-        SHUT_DOWN,
-    };
-
-    enum FlushCommand {
-        FLUSH_CMD_NONE,
-        FLUSH_CMD_FLUSH,
-        FLUSH_CMD_SHUTDOWN,
-    };
-
-    // Status of flush responses from the decoder and renderer.
-    bool mFlushComplete[2][2];
-
-    FlushStatus mFlushingAudio;
-    FlushStatus mFlushingVideo;
-
-    // Status of flush responses from the decoder and renderer.
-    bool mResumePending;
-
-    int32_t mVideoScalingMode;
-
-    AudioPlaybackRate mPlaybackSettings;
-    AVSyncSettings mSyncSettings;
-    float mVideoFpsHint;
-    bool mStarted;
-    bool mPrepared;
-    bool mResetting;
-    bool mSourceStarted;
-    bool mAudioDecoderError;
-    bool mVideoDecoderError;
-
-    // Actual pause state, either as requested by client or due to buffering.
-    bool mPaused;
-
-    // Pause state as requested by client. Note that if mPausedByClient is
-    // true, mPaused is always true; if mPausedByClient is false, mPaused could
-    // still become true, when we pause internally due to buffering.
-    bool mPausedByClient;
-
-    // Pause state as requested by source (internally) due to buffering
-    bool mPausedForBuffering;
-
-    // Passed from JAVA
-    const sp<JObjectHolder> mContext;
-
-    inline const sp<DecoderBase> &getDecoder(bool audio) {
-        return audio ? mAudioDecoder : mVideoDecoder;
-    }
-
-    inline void clearFlushComplete() {
-        mFlushComplete[0][0] = false;
-        mFlushComplete[0][1] = false;
-        mFlushComplete[1][0] = false;
-        mFlushComplete[1][1] = false;
-    }
-
-    void disconnectSource();
-
-    status_t createNuPlayer2Source(const sp<DataSourceDesc> &dsd,
-                                   sp<Source> *source,
-                                   DATA_SOURCE_TYPE *dataSourceType);
-
-    void tryOpenAudioSinkForOffload(
-            const sp<AMessage> &format, const sp<MetaData> &audioMeta, bool hasVideo);
-    void closeAudioSink();
-    void restartAudio(
-            int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder);
-    void determineAudioModeChange(const sp<AMessage> &audioFormat);
-
-    status_t instantiateDecoder(
-            bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange = true);
-
-    void updateVideoSize(
-            int64_t srcId,
-            const sp<AMessage> &inputFormat,
-            const sp<AMessage> &outputFormat = NULL);
-
-    void notifyListener(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in = NULL);
-
-    void addEndTimeMonitor();
-
-    void handleFlushComplete(bool audio, bool isDecoder);
-    void finishFlushIfPossible();
-
-    void onStart(bool play);
-    void onResume();
-    void onPause();
-
-    bool audioDecoderStillNeeded();
-
-    void flushDecoder(bool audio, bool needShutdown);
-
-    void finishResume();
-    void notifyDriverSeekComplete(int64_t srcId);
-
-    void postScanSources();
-
-    void schedulePollDuration();
-    void cancelPollDuration();
-
-    void processDeferredActions();
-
-    void performSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode);
-    void performDecoderFlush(FlushCommand audio, FlushCommand video);
-    void performReset();
-    void performPlayNextDataSource();
-    void performScanSources();
-    void performSetSurface(const sp<ANativeWindowWrapper> &nw);
-    void performResumeDecoders(bool needNotify);
-
-    void onSourceNotify(const sp<AMessage> &msg);
-    void onClosedCaptionNotify(const sp<AMessage> &msg);
-
-    void queueDecoderShutdown(
-            bool audio, bool video, const sp<AMessage> &reply);
-
-    void sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex);
-    void sendTimedMetaData(const sp<ABuffer> &buffer);
-    void sendTimedTextData(const sp<ABuffer> &buffer);
-
-    void writeTrackInfo(PlayerMessage* reply, const sp<AMessage>& format) const;
-
-    status_t onPrepareDrm(const sp<AMessage> &msg);
-    status_t onReleaseDrm(const sp<AMessage> &msg);
-
-    SourceInfo* getSourceInfoByIdInMsg(const sp<AMessage> &msg);
-    void resetSourceInfo(SourceInfo &srcInfo);
-
-    DISALLOW_EVIL_CONSTRUCTORS(NuPlayer2);
-};
-
-}  // namespace android
-
-#endif  // NU_PLAYER2_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp
deleted file mode 100644
index 98c3403..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2CCDecoder"
-#include <utils/Log.h>
-#include <inttypes.h>
-
-#include "NuPlayer2CCDecoder.h"
-
-#include <media/NdkMediaFormat.h>
-#include <media/stagefright/foundation/ABitReader.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/MediaDefs.h>
-
-namespace android {
-
-// In CEA-708B, the maximum bandwidth of CC is set to 9600bps.
-static const size_t kMaxBandwithSizeBytes = 9600 / 8;
-
-struct CCData {
-    CCData(uint8_t type, uint8_t data1, uint8_t data2)
-        : mType(type), mData1(data1), mData2(data2) {
-    }
-    bool getChannel(size_t *channel) const {
-        if (mData1 >= 0x10 && mData1 <= 0x1f) {
-            *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0);
-            return true;
-        }
-        return false;
-    }
-
-    uint8_t mType;
-    uint8_t mData1;
-    uint8_t mData2;
-};
-
-static bool isNullPad(CCData *cc) {
-    return cc->mData1 < 0x10 && cc->mData2 < 0x10;
-}
-
-static void dumpBytePair(const sp<ABuffer> &ccBuf) __attribute__ ((unused));
-static void dumpBytePair(const sp<ABuffer> &ccBuf) {
-    size_t offset = 0;
-    AString out;
-
-    while (offset < ccBuf->size()) {
-        char tmp[128];
-
-        CCData *cc = (CCData *) (ccBuf->data() + offset);
-
-        if (isNullPad(cc)) {
-            // 1 null pad or XDS metadata, ignore
-            offset += sizeof(CCData);
-            continue;
-        }
-
-        if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
-            // 2 basic chars
-            snprintf(tmp, sizeof(tmp), "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
-                 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
-            // 1 special char
-            snprintf(tmp, sizeof(tmp), "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
-            // 1 Spanish/French char
-            snprintf(tmp, sizeof(tmp), "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
-            // 1 Portuguese/German/Danish char
-            snprintf(tmp, sizeof(tmp), "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
-            // Mid-Row Codes (Table 69)
-            snprintf(tmp, sizeof(tmp), "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
-                  && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
-                  ||
-                   ((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
-                  && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
-            // Misc Control Codes (Table 70)
-            snprintf(tmp, sizeof(tmp), "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 & 0x70) == 0x10
-                && (cc->mData2 & 0x40) == 0x40
-                && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
-            // Preamble Address Codes (Table 71)
-            snprintf(tmp, sizeof(tmp), "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else {
-            snprintf(tmp, sizeof(tmp), "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        }
-
-        if (out.size() > 0) {
-            out.append(", ");
-        }
-
-        out.append(tmp);
-
-        offset += sizeof(CCData);
-    }
-
-    ALOGI("%s", out.c_str());
-}
-
-NuPlayer2::CCDecoder::CCDecoder(const sp<AMessage> &notify)
-    : mNotify(notify),
-      mSelectedTrack(-1),
-      mDTVCCPacket(new ABuffer(kMaxBandwithSizeBytes)) {
-    mDTVCCPacket->setRange(0, 0);
-
-    // In CEA-608, streams from packets which have the value 0 of cc_type contain CC1 and CC2, and
-    // streams from packets which have the value 1 of cc_type contain CC3 and CC4.
-    // The following array indicates the current transmitting channels for each value of cc_type.
-    mLine21Channels[0] = 0; // CC1
-    mLine21Channels[1] = 2; // CC3
-}
-
-size_t NuPlayer2::CCDecoder::getTrackCount() const {
-    return mTracks.size();
-}
-
-sp<AMessage> NuPlayer2::CCDecoder::getTrackInfo(size_t index) const {
-    if (!isTrackValid(index)) {
-        return NULL;
-    }
-
-    sp<AMessage> format = new AMessage();
-
-    CCTrack track = mTracks[index];
-
-    format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE);
-    format->setString("language", "und");
-
-    switch (track.mTrackType) {
-        case kTrackTypeCEA608:
-            format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608);
-            break;
-        case kTrackTypeCEA708:
-            format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_708);
-            break;
-        default:
-            ALOGE("Unknown track type: %d", track.mTrackType);
-            return NULL;
-    }
-
-    // For CEA-608 CC1, field 0 channel 0
-    bool isDefaultAuto = track.mTrackType == kTrackTypeCEA608
-            && track.mTrackChannel == 0;
-    // For CEA-708, Primary Caption Service.
-    bool isDefaultOnly = track.mTrackType == kTrackTypeCEA708
-            && track.mTrackChannel == 1;
-    format->setInt32("auto", isDefaultAuto);
-    format->setInt32("default", isDefaultAuto || isDefaultOnly);
-    format->setInt32("forced", 0);
-
-    return format;
-}
-
-status_t NuPlayer2::CCDecoder::selectTrack(size_t index, bool select) {
-    if (!isTrackValid(index)) {
-        return BAD_VALUE;
-    }
-
-    if (select) {
-        if (mSelectedTrack == (ssize_t)index) {
-            ALOGE("track %zu already selected", index);
-            return BAD_VALUE;
-        }
-        ALOGV("selected track %zu", index);
-        mSelectedTrack = index;
-    } else {
-        if (mSelectedTrack != (ssize_t)index) {
-            ALOGE("track %zu is not selected", index);
-            return BAD_VALUE;
-        }
-        ALOGV("unselected track %zu", index);
-        mSelectedTrack = -1;
-    }
-
-    // Clear the previous track payloads
-    mCCMap.clear();
-
-    return OK;
-}
-
-ssize_t NuPlayer2::CCDecoder::getSelectedTrack(media_track_type type) const {
-    if (mSelectedTrack != -1) {
-        CCTrack track = mTracks[mSelectedTrack];
-        if (track.mTrackType == kTrackTypeCEA608 || track.mTrackType == kTrackTypeCEA708) {
-            return (type == MEDIA_TRACK_TYPE_SUBTITLE ? mSelectedTrack : -1);
-        }
-        return (type == MEDIA_TRACK_TYPE_UNKNOWN ? mSelectedTrack : -1);
-    }
-
-    return -1;
-}
-
-bool NuPlayer2::CCDecoder::isSelected() const {
-    return mSelectedTrack >= 0 && mSelectedTrack < (int32_t)getTrackCount();
-}
-
-bool NuPlayer2::CCDecoder::isTrackValid(size_t index) const {
-    return index < getTrackCount();
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
-    sp<ABuffer> sei;
-    if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
-        return false;
-    }
-
-    int64_t timeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
-    bool trackAdded = false;
-
-    const NALPosition *nal = (NALPosition *)sei->data();
-
-    for (size_t i = 0; i < sei->size() / sizeof(NALPosition); ++i, ++nal) {
-        trackAdded |= parseSEINalUnit(
-                timeUs, accessUnit->data() + nal->nalOffset, nal->nalSize);
-    }
-
-    return trackAdded;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::parseSEINalUnit(int64_t timeUs, const uint8_t *data, size_t size) {
-    unsigned nalType = data[0] & 0x1f;
-
-    // the buffer should only have SEI in it
-    if (nalType != 6) {
-        return false;
-    }
-
-    bool trackAdded = false;
-    NALBitReader br(data + 1, size - 1);
-
-    // sei_message()
-    while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
-        uint32_t payload_type = 0;
-        size_t payload_size = 0;
-        uint8_t last_byte;
-
-        do {
-            last_byte = br.getBits(8);
-            payload_type += last_byte;
-        } while (last_byte == 0xFF);
-
-        do {
-            last_byte = br.getBits(8);
-            payload_size += last_byte;
-        } while (last_byte == 0xFF);
-
-        if (payload_size > SIZE_MAX / 8
-                || !br.atLeastNumBitsLeft(payload_size * 8)) {
-            ALOGV("Malformed SEI payload");
-            break;
-        }
-
-        // sei_payload()
-        if (payload_type == 4) {
-            bool isCC = false;
-            if (payload_size > 1 + 2 + 4 + 1) {
-                // user_data_registered_itu_t_t35()
-
-                // ATSC A/72: 6.4.2
-                uint8_t itu_t_t35_country_code = br.getBits(8);
-                uint16_t itu_t_t35_provider_code = br.getBits(16);
-                uint32_t user_identifier = br.getBits(32);
-                uint8_t user_data_type_code = br.getBits(8);
-
-                payload_size -= 1 + 2 + 4 + 1;
-
-                isCC = itu_t_t35_country_code == 0xB5
-                        && itu_t_t35_provider_code == 0x0031
-                        && user_identifier == 'GA94'
-                        && user_data_type_code == 0x3;
-            }
-
-            if (isCC && payload_size > 2) {
-                trackAdded |= parseMPEGCCData(timeUs, br.data(), br.numBitsLeft() / 8);
-            } else {
-                ALOGV("Malformed SEI payload type 4");
-            }
-        } else {
-            ALOGV("Unsupported SEI payload type %d", payload_type);
-        }
-
-        // skipping remaining bits of this payload
-        br.skipBits(payload_size * 8);
-    }
-
-    return trackAdded;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::extractFromMPEGUserData(const sp<ABuffer> &accessUnit) {
-    sp<ABuffer> mpegUserData;
-    if (!accessUnit->meta()->findBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, &mpegUserData)
-            || mpegUserData == NULL) {
-        return false;
-    }
-
-    int64_t timeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
-    bool trackAdded = false;
-
-    const size_t *userData = (size_t *)mpegUserData->data();
-
-    for (size_t i = 0; i < mpegUserData->size() / sizeof(size_t); ++i) {
-        trackAdded |= parseMPEGUserDataUnit(
-                timeUs, accessUnit->data() + userData[i], accessUnit->size() - userData[i]);
-    }
-
-    return trackAdded;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::parseMPEGUserDataUnit(int64_t timeUs, const uint8_t *data, size_t size) {
-    ABitReader br(data + 4, 5);
-
-    uint32_t user_identifier = br.getBits(32);
-    uint8_t user_data_type = br.getBits(8);
-
-    if (user_identifier == 'GA94' && user_data_type == 0x3) {
-        return parseMPEGCCData(timeUs, data + 9, size - 9);
-    }
-
-    return false;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::parseMPEGCCData(int64_t timeUs, const uint8_t *data, size_t size) {
-    bool trackAdded = false;
-
-    // MPEG_cc_data()
-    // ATSC A/53 Part 4: 6.2.3.1
-    ABitReader br(data, size);
-
-    if (br.numBitsLeft() <= 16) {
-        return false;
-    }
-
-    br.skipBits(1);
-    bool process_cc_data_flag = br.getBits(1);
-    br.skipBits(1);
-    size_t cc_count = br.getBits(5);
-    br.skipBits(8);
-
-    if (!process_cc_data_flag || 3 * 8 * cc_count >= br.numBitsLeft()) {
-        return false;
-    }
-
-    sp<ABuffer> line21CCBuf = NULL;
-
-    for (size_t i = 0; i < cc_count; ++i) {
-        br.skipBits(5);
-        bool cc_valid = br.getBits(1);
-        uint8_t cc_type = br.getBits(2);
-
-        if (cc_valid) {
-            if (cc_type == 3) {
-                if (mDTVCCPacket->size() > 0) {
-                    trackAdded |= parseDTVCCPacket(
-                            timeUs, mDTVCCPacket->data(), mDTVCCPacket->size());
-                    mDTVCCPacket->setRange(0, 0);
-                }
-                if (mDTVCCPacket->size() + 2 > mDTVCCPacket->capacity()) {
-                    return false;
-                }
-                memcpy(mDTVCCPacket->data() + mDTVCCPacket->size(), br.data(), 2);
-                mDTVCCPacket->setRange(0, mDTVCCPacket->size() + 2);
-                br.skipBits(16);
-            } else if (mDTVCCPacket->size() > 0 && cc_type == 2) {
-                if (mDTVCCPacket->size() + 2 > mDTVCCPacket->capacity()) {
-                    return false;
-                }
-                memcpy(mDTVCCPacket->data() + mDTVCCPacket->size(), br.data(), 2);
-                mDTVCCPacket->setRange(0, mDTVCCPacket->size() + 2);
-                br.skipBits(16);
-            } else if (cc_type == 0 || cc_type == 1) {
-                uint8_t cc_data_1 = br.getBits(8) & 0x7f;
-                uint8_t cc_data_2 = br.getBits(8) & 0x7f;
-
-                CCData cc(cc_type, cc_data_1, cc_data_2);
-
-                if (isNullPad(&cc)) {
-                    continue;
-                }
-
-                size_t channel;
-                if (cc.getChannel(&channel)) {
-                    mLine21Channels[cc_type] = channel;
-
-                    // create a new track if it does not exist.
-                    getTrackIndex(kTrackTypeCEA608, channel, &trackAdded);
-                }
-
-                if (isSelected() && mTracks[mSelectedTrack].mTrackType == kTrackTypeCEA608
-                        && mTracks[mSelectedTrack].mTrackChannel == mLine21Channels[cc_type]) {
-                    if (line21CCBuf == NULL) {
-                        line21CCBuf = new ABuffer((cc_count - i) * sizeof(CCData));
-                        line21CCBuf->setRange(0, 0);
-                    }
-                    if (line21CCBuf->size() + sizeof(cc) > line21CCBuf->capacity()) {
-                        return false;
-                    }
-                    memcpy(line21CCBuf->data() + line21CCBuf->size(), &cc, sizeof(cc));
-                    line21CCBuf->setRange(0, line21CCBuf->size() + sizeof(CCData));
-                }
-            } else {
-                br.skipBits(16);
-            }
-        } else {
-            if ((cc_type == 3 || cc_type == 2) && mDTVCCPacket->size() > 0) {
-                trackAdded |= parseDTVCCPacket(timeUs, mDTVCCPacket->data(), mDTVCCPacket->size());
-                mDTVCCPacket->setRange(0, 0);
-            }
-            br.skipBits(16);
-        }
-    }
-
-    if (isSelected() && mTracks[mSelectedTrack].mTrackType == kTrackTypeCEA608
-            && line21CCBuf != NULL && line21CCBuf->size() > 0) {
-        mCCMap.add(timeUs, line21CCBuf);
-    }
-
-    return trackAdded;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer2::CCDecoder::parseDTVCCPacket(int64_t timeUs, const uint8_t *data, size_t size) {
-    // CEA-708B 5 DTVCC Packet Layer.
-    ABitReader br(data, size);
-    br.skipBits(2);
-
-    size_t packet_size = br.getBits(6);
-    if (packet_size == 0) packet_size = 64;
-    packet_size *= 2;
-
-    if (size != packet_size) {
-        return false;
-    }
-
-    bool trackAdded = false;
-
-    while (br.numBitsLeft() >= 16) {
-        // CEA-708B Figure 5 and 6.
-        uint8_t service_number = br.getBits(3);
-        size_t block_size = br.getBits(5);
-
-        if (service_number == 64) {
-            br.skipBits(2);
-            service_number = br.getBits(6);
-
-            if (service_number < 64) {
-                return trackAdded;
-            }
-        }
-
-        if (br.numBitsLeft() < block_size * 8) {
-            return trackAdded;
-        }
-
-        if (block_size > 0) {
-            size_t trackIndex = getTrackIndex(kTrackTypeCEA708, service_number, &trackAdded);
-            if (mSelectedTrack == (ssize_t)trackIndex) {
-                sp<ABuffer> ccPacket = new ABuffer(block_size);
-                if (ccPacket->capacity() == 0) {
-                    return false;
-                }
-                memcpy(ccPacket->data(), br.data(), block_size);
-                mCCMap.add(timeUs, ccPacket);
-            }
-        }
-        br.skipBits(block_size * 8);
-    }
-
-    return trackAdded;
-}
-
-// return the track index for a given type and channel.
-// if the track does not exist, creates a new one.
-size_t NuPlayer2::CCDecoder::getTrackIndex(
-        int32_t trackType, size_t channel, bool *trackAdded) {
-    CCTrack track(trackType, channel);
-    ssize_t index = mTrackIndices.indexOfKey(track);
-
-    if (index < 0) {
-        // A new track is added.
-        index = mTracks.size();
-        mTrackIndices.add(track, index);
-        mTracks.add(track);
-        *trackAdded = true;
-        return index;
-    }
-
-    return mTrackIndices.valueAt(index);
-}
-
-void NuPlayer2::CCDecoder::decode(const sp<ABuffer> &accessUnit) {
-    if (extractFromMPEGUserData(accessUnit) || extractFromSEI(accessUnit)) {
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatTrackAdded);
-        msg->post();
-    }
-    // TODO: extract CC from other sources
-}
-
-void NuPlayer2::CCDecoder::display(int64_t timeUs) {
-    if (!isSelected()) {
-        return;
-    }
-
-    ssize_t index = mCCMap.indexOfKey(timeUs);
-    if (index < 0) {
-        ALOGV("cc for timestamp %" PRId64 " not found", timeUs);
-        return;
-    }
-
-    sp<ABuffer> ccBuf;
-
-    if (index == 0) {
-        ccBuf = mCCMap.valueAt(index);
-    } else {
-        size_t size = 0;
-
-        for (ssize_t i = 0; i <= index; ++i) {
-            size += mCCMap.valueAt(i)->size();
-        }
-
-        ccBuf = new ABuffer(size);
-        ccBuf->setRange(0, 0);
-
-        if (ccBuf->capacity() > 0) {
-            for (ssize_t i = 0; i <= index; ++i) {
-                sp<ABuffer> buf = mCCMap.valueAt(i);
-                memcpy(ccBuf->data() + ccBuf->size(), buf->data(), buf->size());
-                ccBuf->setRange(0, ccBuf->size() + buf->size());
-            }
-        }
-    }
-
-    if (ccBuf->size() > 0) {
-#if 0
-        dumpBytePair(ccBuf);
-#endif
-
-        ccBuf->meta()->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, mSelectedTrack);
-        ccBuf->meta()->setInt64("timeUs", timeUs);
-        ccBuf->meta()->setInt64("durationUs", 0LL);
-
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatClosedCaptionData);
-        msg->setBuffer("buffer", ccBuf);
-        msg->post();
-    }
-
-    // remove all entries before timeUs
-    mCCMap.removeItemsAt(0, index + 1);
-}
-
-void NuPlayer2::CCDecoder::flush() {
-    mCCMap.clear();
-    mDTVCCPacket->setRange(0, 0);
-}
-
-int32_t NuPlayer2::CCDecoder::CCTrack::compare(const NuPlayer2::CCDecoder::CCTrack& rhs) const {
-    int32_t cmp = mTrackType - rhs.mTrackType;
-    if (cmp != 0) return cmp;
-    return mTrackChannel - rhs.mTrackChannel;
-}
-
-bool NuPlayer2::CCDecoder::CCTrack::operator<(const NuPlayer2::CCDecoder::CCTrack& rhs) const {
-    return compare(rhs) < 0;
-}
-
-bool NuPlayer2::CCDecoder::CCTrack::operator==(const NuPlayer2::CCDecoder::CCTrack& rhs) const {
-    return compare(rhs) == 0;
-}
-
-bool NuPlayer2::CCDecoder::CCTrack::operator!=(const NuPlayer2::CCDecoder::CCTrack& rhs) const {
-    return compare(rhs) != 0;
-}
-
-}  // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.h b/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.h
deleted file mode 100644
index 97834d1..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_CCDECODER_H_
-
-#define NUPLAYER2_CCDECODER_H_
-
-#include "NuPlayer2.h"
-
-namespace android {
-
-struct NuPlayer2::CCDecoder : public RefBase {
-    enum {
-        kWhatClosedCaptionData,
-        kWhatTrackAdded,
-    };
-
-    enum {
-        kTrackTypeCEA608,
-        kTrackTypeCEA708,
-    };
-
-    explicit CCDecoder(const sp<AMessage> &notify);
-
-    size_t getTrackCount() const;
-    sp<AMessage> getTrackInfo(size_t index) const;
-    status_t selectTrack(size_t index, bool select);
-    ssize_t getSelectedTrack(media_track_type type) const;
-    bool isSelected() const;
-    void decode(const sp<ABuffer> &accessUnit);
-    void display(int64_t timeUs);
-    void flush();
-
-private:
-    // CC track identifier.
-    struct CCTrack {
-        CCTrack() : mTrackType(0), mTrackChannel(0) { }
-
-        CCTrack(const int32_t trackType, const size_t trackChannel)
-            : mTrackType(trackType), mTrackChannel(trackChannel) { }
-
-        int32_t mTrackType;
-        size_t mTrackChannel;
-
-        // The ordering of CCTracks is to build a map of track to index.
-        // It is necessary to find the index of the matched CCTrack when CC data comes.
-        int compare(const NuPlayer2::CCDecoder::CCTrack& rhs) const;
-        inline bool operator<(const NuPlayer2::CCDecoder::CCTrack& rhs) const;
-        inline bool operator==(const NuPlayer2::CCDecoder::CCTrack& rhs) const;
-        inline bool operator!=(const NuPlayer2::CCDecoder::CCTrack& rhs) const;
-    };
-
-    sp<AMessage> mNotify;
-    KeyedVector<int64_t, sp<ABuffer> > mCCMap;
-    ssize_t mSelectedTrack;
-    KeyedVector<CCTrack, size_t> mTrackIndices;
-    Vector<CCTrack> mTracks;
-
-    // CEA-608 closed caption
-    size_t mLine21Channels[2]; // The current channels of NTSC_CC_FIELD_{1, 2}
-
-    // CEA-708 closed caption
-    sp<ABuffer> mDTVCCPacket;
-
-    bool isTrackValid(size_t index) const;
-    size_t getTrackIndex(int32_t trackType, size_t channel, bool *trackAdded);
-
-    // Extract from H.264 SEIs
-    bool extractFromSEI(const sp<ABuffer> &accessUnit);
-    bool parseSEINalUnit(int64_t timeUs, const uint8_t *data, size_t size);
-
-    // Extract from MPEG user data
-    bool extractFromMPEGUserData(const sp<ABuffer> &accessUnit);
-    bool parseMPEGUserDataUnit(int64_t timeUs, const uint8_t *data, size_t size);
-
-    // Extract CC tracks from MPEG_cc_data
-    bool parseMPEGCCData(int64_t timeUs, const uint8_t *data, size_t size);
-    bool parseDTVCCPacket(int64_t timeUs, const uint8_t *data, size_t size);
-
-    DISALLOW_EVIL_CONSTRUCTORS(CCDecoder);
-};
-
-}  // namespace android
-
-#endif  // NUPLAYER2_CCDECODER_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
deleted file mode 100644
index 66bfae5..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
+++ /dev/null
@@ -1,1315 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2Decoder"
-#include <utils/Log.h>
-#include <inttypes.h>
-
-#include <algorithm>
-
-#include "NuPlayer2CCDecoder.h"
-#include "NuPlayer2Decoder.h"
-#include "NuPlayer2Drm.h"
-#include "NuPlayer2Renderer.h"
-#include "NuPlayer2Source.h"
-
-#include <cutils/properties.h>
-#include <media/MediaBufferHolder.h>
-#include <media/MediaCodecBuffer.h>
-#include <media/NdkMediaCodec.h>
-#include <media/NdkWrapper.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/SurfaceUtils.h>
-
-#include <system/window.h>
-#include "ATSParser.h"
-
-namespace android {
-
-static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
-
-// The default total video frame rate of a stream when that info is not available from
-// the source.
-static float kDefaultVideoFrameRateTotal = 30.f;
-
-static inline bool getAudioDeepBufferSetting() {
-    return property_get_bool("media.stagefright.audio.deep", false /* default_value */);
-}
-
-NuPlayer2::Decoder::Decoder(
-        const sp<AMessage> &notify,
-        const sp<Source> &source,
-        pid_t pid,
-        uid_t uid,
-        const sp<Renderer> &renderer,
-        const sp<ANativeWindowWrapper> &nww,
-        const sp<CCDecoder> &ccDecoder)
-    : DecoderBase(notify),
-      mNativeWindow(nww),
-      mSource(source),
-      mRenderer(renderer),
-      mCCDecoder(ccDecoder),
-      mPid(pid),
-      mUid(uid),
-      mSkipRenderingUntilMediaTimeUs(-1LL),
-      mNumFramesTotal(0LL),
-      mNumInputFramesDropped(0LL),
-      mNumOutputFramesDropped(0LL),
-      mVideoWidth(0),
-      mVideoHeight(0),
-      mIsAudio(true),
-      mIsVideoAVC(false),
-      mIsSecure(false),
-      mIsEncrypted(false),
-      mIsEncryptedObservedEarlier(false),
-      mFormatChangePending(false),
-      mTimeChangePending(false),
-      mFrameRateTotal(kDefaultVideoFrameRateTotal),
-      mPlaybackSpeed(1.0f),
-      mNumVideoTemporalLayerTotal(1), // decode all layers
-      mNumVideoTemporalLayerAllowed(1),
-      mCurrentMaxVideoTemporalLayerId(0),
-      mResumePending(false),
-      mComponentName("decoder") {
-    mVideoTemporalLayerAggregateFps[0] = mFrameRateTotal;
-}
-
-NuPlayer2::Decoder::~Decoder() {
-    // Need to stop looper first since mCodec could be accessed on the mDecoderLooper.
-    stopLooper();
-    if (mCodec != NULL) {
-        mCodec->release();
-    }
-    releaseAndResetMediaBuffers();
-}
-
-sp<AMessage> NuPlayer2::Decoder::getStats() const {
-    mStats->setInt64("frames-total", mNumFramesTotal);
-    mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
-    mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
-    mStats->setFloat("frame-rate-total", mFrameRateTotal);
-
-    // i'm mutexed right now.
-    // make our own copy, so we aren't victim to any later changes.
-    sp<AMessage> copiedStats = mStats->dup();
-    return copiedStats;
-}
-
-status_t NuPlayer2::Decoder::setVideoSurface(const sp<ANativeWindowWrapper> &nww) {
-    if (nww == NULL || nww->getANativeWindow() == NULL
-        || ADebug::isExperimentEnabled("legacy-setsurface")) {
-        return BAD_VALUE;
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
-
-    msg->setObject("surface", nww);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-void NuPlayer2::Decoder::onMessageReceived(const sp<AMessage> &msg) {
-    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
-
-    switch (msg->what()) {
-        case kWhatCodecNotify:
-        {
-            int32_t cbID;
-            CHECK(msg->findInt32("callbackID", &cbID));
-
-            ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",
-                    mIsAudio ? "audio" : "video", cbID, mPaused);
-
-            if (mPaused) {
-                break;
-            }
-
-            switch (cbID) {
-                case AMediaCodecWrapper::CB_INPUT_AVAILABLE:
-                {
-                    int32_t index;
-                    CHECK(msg->findInt32("index", &index));
-
-                    handleAnInputBuffer(index);
-                    break;
-                }
-
-                case AMediaCodecWrapper::CB_OUTPUT_AVAILABLE:
-                {
-                    int32_t index;
-                    size_t offset;
-                    size_t size;
-                    int64_t timeUs;
-                    int32_t flags;
-
-                    CHECK(msg->findInt32("index", &index));
-                    CHECK(msg->findSize("offset", &offset));
-                    CHECK(msg->findSize("size", &size));
-                    CHECK(msg->findInt64("timeUs", &timeUs));
-                    CHECK(msg->findInt32("flags", &flags));
-
-                    handleAnOutputBuffer(index, offset, size, timeUs, flags);
-                    break;
-                }
-
-                case AMediaCodecWrapper::CB_OUTPUT_FORMAT_CHANGED:
-                {
-                    sp<AMessage> format;
-                    CHECK(msg->findMessage("format", &format));
-
-                    handleOutputFormatChange(format);
-                    break;
-                }
-
-                case AMediaCodecWrapper::CB_ERROR:
-                {
-                    status_t err;
-                    CHECK(msg->findInt32("err", &err));
-                    ALOGE("Decoder (%s) reported error : 0x%x",
-                            mIsAudio ? "audio" : "video", err);
-
-                    handleError(err);
-                    break;
-                }
-
-                default:
-                {
-                    TRESPASS();
-                    break;
-                }
-            }
-
-            break;
-        }
-
-        case kWhatRenderBuffer:
-        {
-            if (!isStaleReply(msg)) {
-                onRenderBuffer(msg);
-            }
-            break;
-        }
-
-        case kWhatAudioOutputFormatChanged:
-        {
-            if (!isStaleReply(msg)) {
-                status_t err;
-                if (msg->findInt32("err", &err) && err != OK) {
-                    ALOGE("Renderer reported 0x%x when changing audio output format", err);
-                    handleError(err);
-                }
-            }
-            break;
-        }
-
-        case kWhatSetVideoSurface:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            sp<RefBase> obj;
-            CHECK(msg->findObject("surface", &obj));
-            sp<ANativeWindowWrapper> nww =
-                static_cast<ANativeWindowWrapper *>(obj.get()); // non-null
-            if (nww == NULL || nww->getANativeWindow() == NULL) {
-                break;
-            }
-            int32_t err = INVALID_OPERATION;
-            // NOTE: in practice mNativeWindow is always non-null,
-            // but checking here for completeness
-            if (mCodec != NULL
-                && mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
-                // TODO: once AwesomePlayer is removed, remove this automatic connecting
-                // to the surface by MediaPlayerService.
-                //
-                // at this point MediaPlayer2Manager::client has already connected to the
-                // surface, which MediaCodec does not expect
-                err = native_window_api_disconnect(nww->getANativeWindow(),
-                                                   NATIVE_WINDOW_API_MEDIA);
-                if (err == OK) {
-                    err = mCodec->setOutputSurface(nww);
-                    ALOGI_IF(err, "codec setOutputSurface returned: %d", err);
-                    if (err == OK) {
-                        // reconnect to the old surface as MPS::Client will expect to
-                        // be able to disconnect from it.
-                        (void)native_window_api_connect(mNativeWindow->getANativeWindow(),
-                                                        NATIVE_WINDOW_API_MEDIA);
-
-                        mNativeWindow = nww;
-                    }
-                }
-                if (err != OK) {
-                    // reconnect to the new surface on error as MPS::Client will expect to
-                    // be able to disconnect from it.
-                    (void)native_window_api_connect(nww->getANativeWindow(),
-                                                    NATIVE_WINDOW_API_MEDIA);
-                }
-            }
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatDrmReleaseCrypto:
-        {
-            ALOGV("kWhatDrmReleaseCrypto");
-            onReleaseCrypto(msg);
-            break;
-        }
-
-        default:
-            DecoderBase::onMessageReceived(msg);
-            break;
-    }
-}
-
-void NuPlayer2::Decoder::onConfigure(const sp<AMessage> &format) {
-    ALOGV("[%s] onConfigure (format=%s)", mComponentName.c_str(), format->debugString().c_str());
-    CHECK(mCodec == NULL);
-
-    mFormatChangePending = false;
-    mTimeChangePending = false;
-
-    ++mBufferGeneration;
-
-    AString mime;
-    CHECK(format->findString("mime", &mime));
-
-    mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
-    mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
-
-    mComponentName = mime;
-    mComponentName.append(" decoder");
-    ALOGV("[%s] onConfigure (nww=%p)", mComponentName.c_str(),
-          (mNativeWindow == NULL ? NULL : mNativeWindow->getANativeWindow()));
-
-    mCodec = AMediaCodecWrapper::CreateDecoderByType(mime);
-    int32_t secure = 0;
-    if (format->findInt32("secure", &secure) && secure != 0) {
-        if (mCodec != NULL) {
-            if (mCodec->getName(&mComponentName) == OK) {
-                mComponentName.append(".secure");
-                mCodec->release();
-                ALOGI("[%s] creating", mComponentName.c_str());
-                mCodec = AMediaCodecWrapper::CreateCodecByName(mComponentName);
-            } else {
-                mCodec = NULL;
-            }
-        }
-    }
-    if (mCodec == NULL) {
-        ALOGE("Failed to create %s%s decoder",
-                (secure ? "secure " : ""), mime.c_str());
-        handleError(NO_INIT);
-        return;
-    }
-    mIsSecure = secure;
-
-    mCodec->getName(&mComponentName);
-
-    status_t err;
-    if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
-        // disconnect from surface as MediaCodec will reconnect
-        err = native_window_api_disconnect(mNativeWindow->getANativeWindow(),
-                                           NATIVE_WINDOW_API_MEDIA);
-        // We treat this as a warning, as this is a preparatory step.
-        // Codec will try to connect to the surface, which is where
-        // any error signaling will occur.
-        ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
-    }
-
-    // Modular DRM
-    sp<RefBase> objCrypto;
-    format->findObject("crypto", &objCrypto);
-    sp<AMediaCryptoWrapper> crypto = static_cast<AMediaCryptoWrapper *>(objCrypto.get());
-    // non-encrypted source won't have a crypto
-    mIsEncrypted = (crypto != NULL);
-    // configure is called once; still using OR in case the behavior changes.
-    mIsEncryptedObservedEarlier = mIsEncryptedObservedEarlier || mIsEncrypted;
-    ALOGV("onConfigure mCrypto: %p, mIsSecure: %d", crypto.get(), mIsSecure);
-
-    err = mCodec->configure(
-            AMediaFormatWrapper::Create(format),
-            mNativeWindow,
-            crypto,
-            0 /* flags */);
-
-    if (err != OK) {
-        ALOGE("Failed to configure [%s] decoder (err=%d)", mComponentName.c_str(), err);
-        mCodec->release();
-        mCodec.clear();
-        handleError(err);
-        return;
-    }
-    rememberCodecSpecificData(format);
-
-    // the following should work in configured state
-    sp<AMediaFormatWrapper> outputFormat = mCodec->getOutputFormat();
-    if (outputFormat == NULL) {
-        handleError(INVALID_OPERATION);
-        return;
-    }
-    mInputFormat = mCodec->getInputFormat();
-    if (mInputFormat == NULL) {
-        handleError(INVALID_OPERATION);
-        return;
-    }
-
-    mStats->setString("mime", mime.c_str());
-    mStats->setString("component-name", mComponentName.c_str());
-
-    if (!mIsAudio) {
-        int32_t width, height;
-        if (outputFormat->getInt32("width", &width)
-                && outputFormat->getInt32("height", &height)) {
-            mStats->setInt32("width", width);
-            mStats->setInt32("height", height);
-        }
-    }
-
-    sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
-    mCodec->setCallback(reply);
-
-    err = mCodec->start();
-    if (err != OK) {
-        ALOGE("Failed to start [%s] decoder (err=%d)", mComponentName.c_str(), err);
-        mCodec->release();
-        mCodec.clear();
-        handleError(err);
-        return;
-    }
-
-    releaseAndResetMediaBuffers();
-
-    mPaused = false;
-    mResumePending = false;
-}
-
-void NuPlayer2::Decoder::onSetParameters(const sp<AMessage> &params) {
-    bool needAdjustLayers = false;
-    float frameRateTotal;
-    if (params->findFloat("frame-rate-total", &frameRateTotal)
-            && mFrameRateTotal != frameRateTotal) {
-        needAdjustLayers = true;
-        mFrameRateTotal = frameRateTotal;
-    }
-
-    int32_t numVideoTemporalLayerTotal;
-    if (params->findInt32("temporal-layer-count", &numVideoTemporalLayerTotal)
-            && numVideoTemporalLayerTotal >= 0
-            && numVideoTemporalLayerTotal <= kMaxNumVideoTemporalLayers
-            && mNumVideoTemporalLayerTotal != numVideoTemporalLayerTotal) {
-        needAdjustLayers = true;
-        mNumVideoTemporalLayerTotal = std::max(numVideoTemporalLayerTotal, 1);
-    }
-
-    if (needAdjustLayers && mNumVideoTemporalLayerTotal > 1) {
-        // TODO: For now, layer fps is calculated for some specific architectures.
-        // But it really should be extracted from the stream.
-        mVideoTemporalLayerAggregateFps[0] =
-            mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - 1));
-        for (int32_t i = 1; i < mNumVideoTemporalLayerTotal; ++i) {
-            mVideoTemporalLayerAggregateFps[i] =
-                mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - i))
-                + mVideoTemporalLayerAggregateFps[i - 1];
-        }
-    }
-
-    float playbackSpeed;
-    if (params->findFloat("playback-speed", &playbackSpeed)
-            && mPlaybackSpeed != playbackSpeed) {
-        needAdjustLayers = true;
-        mPlaybackSpeed = playbackSpeed;
-    }
-
-    if (needAdjustLayers) {
-        float decodeFrameRate = mFrameRateTotal;
-        // enable temporal layering optimization only if we know the layering depth
-        if (mNumVideoTemporalLayerTotal > 1) {
-            int32_t layerId;
-            for (layerId = 0; layerId < mNumVideoTemporalLayerTotal - 1; ++layerId) {
-                if (mVideoTemporalLayerAggregateFps[layerId] * mPlaybackSpeed
-                        >= kDisplayRefreshingRate * 0.9) {
-                    break;
-                }
-            }
-            mNumVideoTemporalLayerAllowed = layerId + 1;
-            decodeFrameRate = mVideoTemporalLayerAggregateFps[layerId];
-        }
-        ALOGV("onSetParameters: allowed layers=%d, decodeFps=%g",
-                mNumVideoTemporalLayerAllowed, decodeFrameRate);
-
-        if (mCodec == NULL) {
-            ALOGW("onSetParameters called before codec is created.");
-            return;
-        }
-
-        sp<AMediaFormatWrapper> codecParams = new AMediaFormatWrapper();
-        codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
-        mCodec->setParameters(codecParams);
-    }
-}
-
-void NuPlayer2::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
-    mRenderer = renderer;
-}
-
-void NuPlayer2::Decoder::onResume(bool notifyComplete) {
-    mPaused = false;
-
-    if (notifyComplete) {
-        mResumePending = true;
-    }
-
-    if (mCodec == NULL) {
-        ALOGE("[%s] onResume without a valid codec", mComponentName.c_str());
-        handleError(NO_INIT);
-        return;
-    }
-    mCodec->start();
-}
-
-void NuPlayer2::Decoder::doFlush(bool notifyComplete) {
-    if (mCCDecoder != NULL) {
-        mCCDecoder->flush();
-    }
-
-    if (mRenderer != NULL) {
-        mRenderer->flush(mIsAudio, notifyComplete);
-        mRenderer->signalTimeDiscontinuity();
-    }
-
-    status_t err = OK;
-    if (mCodec != NULL) {
-        err = mCodec->flush();
-        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
-        ++mBufferGeneration;
-    }
-
-    if (err != OK) {
-        ALOGE("failed to flush [%s] (err=%d)", mComponentName.c_str(), err);
-        handleError(err);
-        // finish with posting kWhatFlushCompleted.
-        // we attempt to release the buffers even if flush fails.
-    }
-    releaseAndResetMediaBuffers();
-    mPaused = true;
-}
-
-
-void NuPlayer2::Decoder::onFlush() {
-    doFlush(true);
-
-    if (isDiscontinuityPending()) {
-        // This could happen if the client starts seeking/shutdown
-        // after we queued an EOS for discontinuities.
-        // We can consider discontinuity handled.
-        finishHandleDiscontinuity(false /* flushOnTimeChange */);
-    }
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFlushCompleted);
-    notify->post();
-}
-
-void NuPlayer2::Decoder::onShutdown(bool notifyComplete) {
-    status_t err = OK;
-
-    // if there is a pending resume request, notify complete now
-    notifyResumeCompleteIfNecessary();
-
-    if (mCodec != NULL) {
-        err = mCodec->release();
-        mCodec = NULL;
-        ++mBufferGeneration;
-
-        if (mNativeWindow != NULL && mNativeWindow->getANativeWindow() != NULL) {
-            // reconnect to surface as MediaCodec disconnected from it
-            status_t error = native_window_api_connect(mNativeWindow->getANativeWindow(),
-                                                       NATIVE_WINDOW_API_MEDIA);
-            ALOGW_IF(error != NO_ERROR,
-                    "[%s] failed to connect to native window, error=%d",
-                    mComponentName.c_str(), error);
-        }
-        mComponentName = "decoder";
-    }
-
-    releaseAndResetMediaBuffers();
-
-    if (err != OK) {
-        ALOGE("failed to release [%s] (err=%d)", mComponentName.c_str(), err);
-        handleError(err);
-        // finish with posting kWhatShutdownCompleted.
-    }
-
-    if (notifyComplete) {
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatShutdownCompleted);
-        notify->post();
-        mPaused = true;
-    }
-}
-
-/*
- * returns true if we should request more data
- */
-bool NuPlayer2::Decoder::doRequestBuffers() {
-    if (isDiscontinuityPending()) {
-        return false;
-    }
-    status_t err = OK;
-    while (err == OK && !mDequeuedInputBuffers.empty()) {
-        size_t bufferIx = *mDequeuedInputBuffers.begin();
-        sp<AMessage> msg = new AMessage();
-        msg->setSize("buffer-ix", bufferIx);
-        err = fetchInputData(msg);
-        if (err != OK && err != ERROR_END_OF_STREAM) {
-            // if EOS, need to queue EOS buffer
-            break;
-        }
-        mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
-
-        if (!mPendingInputMessages.empty()
-                || !onInputBufferFetched(msg)) {
-            mPendingInputMessages.push_back(msg);
-        }
-    }
-
-    return err == -EWOULDBLOCK
-            && mSource->feedMoreTSData() == OK;
-}
-
-void NuPlayer2::Decoder::handleError(int32_t err)
-{
-    // We cannot immediately release the codec due to buffers still outstanding
-    // in the renderer.  We signal to the player the error so it can shutdown/release the
-    // decoder after flushing and increment the generation to discard unnecessary messages.
-
-    ++mBufferGeneration;
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatError);
-    notify->setInt32("err", err);
-    notify->post();
-}
-
-status_t NuPlayer2::Decoder::releaseCrypto()
-{
-    ALOGV("releaseCrypto");
-
-    sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
-
-    sp<AMessage> response;
-    status_t status = msg->postAndAwaitResponse(&response);
-    if (status == OK && response != NULL) {
-        CHECK(response->findInt32("status", &status));
-        ALOGV("releaseCrypto ret: %d ", status);
-    } else {
-        ALOGE("releaseCrypto err: %d", status);
-    }
-
-    return status;
-}
-
-void NuPlayer2::Decoder::onReleaseCrypto(const sp<AMessage>& msg)
-{
-    status_t status = INVALID_OPERATION;
-    if (mCodec != NULL) {
-        status = mCodec->releaseCrypto();
-    } else {
-        // returning OK if the codec has been already released
-        status = OK;
-        ALOGE("onReleaseCrypto No mCodec. err: %d", status);
-    }
-
-    sp<AMessage> response = new AMessage;
-    response->setInt32("status", status);
-    // Clearing the state as it's tied to crypto. mIsEncryptedObservedEarlier is sticky though
-    // and lasts for the lifetime of this codec. See its use in fetchInputData.
-    mIsEncrypted = false;
-
-    sp<AReplyToken> replyID;
-    CHECK(msg->senderAwaitsResponse(&replyID));
-    response->postReply(replyID);
-}
-
-bool NuPlayer2::Decoder::handleAnInputBuffer(size_t index) {
-    if (isDiscontinuityPending()) {
-        return false;
-    }
-
-    if (mCodec == NULL) {
-        ALOGE("[%s] handleAnInputBuffer without a valid codec", mComponentName.c_str());
-        handleError(NO_INIT);
-        return false;
-    }
-
-    size_t bufferSize = 0;
-    uint8_t *bufferBase = mCodec->getInputBuffer(index, &bufferSize);
-
-    if (bufferBase == NULL) {
-        ALOGE("[%s] handleAnInputBuffer, failed to get input buffer", mComponentName.c_str());
-        handleError(UNKNOWN_ERROR);
-        return false;
-    }
-
-    sp<MediaCodecBuffer> buffer =
-        new MediaCodecBuffer(NULL /* format */, new ABuffer(bufferBase, bufferSize));
-
-    if (index >= mInputBuffers.size()) {
-        for (size_t i = mInputBuffers.size(); i <= index; ++i) {
-            mInputBuffers.add();
-            mMediaBuffers.add();
-            mInputBufferIsDequeued.add();
-            mMediaBuffers.editItemAt(i) = NULL;
-            mInputBufferIsDequeued.editItemAt(i) = false;
-        }
-    }
-    mInputBuffers.editItemAt(index) = buffer;
-
-    //CHECK_LT(bufferIx, mInputBuffers.size());
-
-    if (mMediaBuffers[index] != NULL) {
-        mMediaBuffers[index]->release();
-        mMediaBuffers.editItemAt(index) = NULL;
-    }
-    mInputBufferIsDequeued.editItemAt(index) = true;
-
-    if (!mCSDsToSubmit.isEmpty()) {
-        sp<AMessage> msg = new AMessage();
-        msg->setSize("buffer-ix", index);
-
-        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
-        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
-        msg->setBuffer("buffer", buffer);
-        mCSDsToSubmit.removeAt(0);
-        if (!onInputBufferFetched(msg)) {
-            handleError(UNKNOWN_ERROR);
-            return false;
-        }
-        return true;
-    }
-
-    while (!mPendingInputMessages.empty()) {
-        sp<AMessage> msg = *mPendingInputMessages.begin();
-        if (!onInputBufferFetched(msg)) {
-            break;
-        }
-        mPendingInputMessages.erase(mPendingInputMessages.begin());
-    }
-
-    if (!mInputBufferIsDequeued.editItemAt(index)) {
-        return true;
-    }
-
-    mDequeuedInputBuffers.push_back(index);
-
-    onRequestInputBuffers();
-    return true;
-}
-
-bool NuPlayer2::Decoder::handleAnOutputBuffer(
-        size_t index,
-        size_t offset,
-        size_t size,
-        int64_t timeUs,
-        int32_t flags) {
-    if (mCodec == NULL) {
-        ALOGE("[%s] handleAnOutputBuffer without a valid codec", mComponentName.c_str());
-        handleError(NO_INIT);
-        return false;
-    }
-
-//    CHECK_LT(bufferIx, mOutputBuffers.size());
-
-    size_t bufferSize = 0;
-    uint8_t *bufferBase = mCodec->getOutputBuffer(index, &bufferSize);
-
-    if (bufferBase == NULL) {
-        ALOGE("[%s] handleAnOutputBuffer, failed to get output buffer", mComponentName.c_str());
-        handleError(UNKNOWN_ERROR);
-        return false;
-    }
-
-    sp<MediaCodecBuffer> buffer =
-        new MediaCodecBuffer(NULL /* format */, new ABuffer(bufferBase, bufferSize));
-
-    if (index >= mOutputBuffers.size()) {
-        for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
-            mOutputBuffers.add();
-        }
-    }
-
-    mOutputBuffers.editItemAt(index) = buffer;
-
-    buffer->setRange(offset, size);
-    buffer->meta()->clear();
-    buffer->meta()->setInt64("timeUs", timeUs);
-
-    bool eos = flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
-    // we do not expect CODECCONFIG or SYNCFRAME for decoder
-
-    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
-    reply->setSize("buffer-ix", index);
-    reply->setInt32("generation", mBufferGeneration);
-
-    if (eos) {
-        ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
-
-        buffer->meta()->setInt32("eos", true);
-        reply->setInt32("eos", true);
-    }
-
-    mNumFramesTotal += !mIsAudio;
-
-    if (mSkipRenderingUntilMediaTimeUs >= 0) {
-        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
-            ALOGV("[%s] dropping buffer at time %lld as requested.",
-                     mComponentName.c_str(), (long long)timeUs);
-
-            reply->post();
-            if (eos) {
-                notifyResumeCompleteIfNecessary();
-                if (mRenderer != NULL && !isDiscontinuityPending()) {
-                    mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
-                }
-            }
-            return true;
-        }
-
-        mSkipRenderingUntilMediaTimeUs = -1;
-    }
-
-    // wait until 1st frame comes out to signal resume complete
-    notifyResumeCompleteIfNecessary();
-
-    if (mRenderer != NULL) {
-        // send the buffer to renderer.
-        mRenderer->queueBuffer(mIsAudio, buffer, reply);
-        if (eos && !isDiscontinuityPending()) {
-            mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
-        }
-    }
-
-    return true;
-}
-
-void NuPlayer2::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
-    if (!mIsAudio) {
-        int32_t width, height;
-        if (format->findInt32("width", &width)
-                && format->findInt32("height", &height)) {
-            mStats->setInt32("width", width);
-            mStats->setInt32("height", height);
-        }
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatVideoSizeChanged);
-        notify->setMessage("format", format);
-        notify->post();
-    } else if (mRenderer != NULL) {
-        uint32_t flags;
-        int64_t durationUs;
-        bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
-        if (getAudioDeepBufferSetting() // override regardless of source duration
-                || (mSource->getDuration(&durationUs) == OK
-                        && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
-            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        } else {
-            flags = AUDIO_OUTPUT_FLAG_NONE;
-        }
-
-        sp<AMessage> reply = new AMessage(kWhatAudioOutputFormatChanged, this);
-        reply->setInt32("generation", mBufferGeneration);
-        mRenderer->changeAudioFormat(
-                format, false /* offloadOnly */, hasVideo,
-                flags, mSource->isStreaming(), reply);
-    }
-}
-
-void NuPlayer2::Decoder::releaseAndResetMediaBuffers() {
-    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
-        if (mMediaBuffers[i] != NULL) {
-            mMediaBuffers[i]->release();
-            mMediaBuffers.editItemAt(i) = NULL;
-        }
-    }
-    mMediaBuffers.resize(mInputBuffers.size());
-    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
-        mMediaBuffers.editItemAt(i) = NULL;
-    }
-    mInputBufferIsDequeued.clear();
-    mInputBufferIsDequeued.resize(mInputBuffers.size());
-    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
-        mInputBufferIsDequeued.editItemAt(i) = false;
-    }
-
-    mPendingInputMessages.clear();
-    mDequeuedInputBuffers.clear();
-    mSkipRenderingUntilMediaTimeUs = -1;
-}
-
-bool NuPlayer2::Decoder::isStaleReply(const sp<AMessage> &msg) {
-    int32_t generation;
-    CHECK(msg->findInt32("generation", &generation));
-    return generation != mBufferGeneration;
-}
-
-status_t NuPlayer2::Decoder::fetchInputData(sp<AMessage> &reply) {
-    sp<ABuffer> accessUnit;
-    bool dropAccessUnit = true;
-    do {
-        status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
-
-        if (err == -EWOULDBLOCK) {
-            return err;
-        } else if (err != OK) {
-            if (err == INFO_DISCONTINUITY) {
-                int32_t type;
-                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
-
-                bool formatChange =
-                    (mIsAudio &&
-                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
-                    || (!mIsAudio &&
-                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
-
-                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
-
-                ALOGI("%s discontinuity (format=%d, time=%d)",
-                        mIsAudio ? "audio" : "video", formatChange, timeChange);
-
-                bool seamlessFormatChange = false;
-                sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
-                if (formatChange) {
-                    seamlessFormatChange =
-                        supportsSeamlessFormatChange(newFormat);
-                    // treat seamless format change separately
-                    formatChange = !seamlessFormatChange;
-                }
-
-                // For format or time change, return EOS to queue EOS input,
-                // then wait for EOS on output.
-                if (formatChange /* not seamless */) {
-                    mFormatChangePending = true;
-                    err = ERROR_END_OF_STREAM;
-                } else if (timeChange) {
-                    rememberCodecSpecificData(newFormat);
-                    mTimeChangePending = true;
-                    err = ERROR_END_OF_STREAM;
-                } else if (seamlessFormatChange) {
-                    // reuse existing decoder and don't flush
-                    rememberCodecSpecificData(newFormat);
-                    continue;
-                } else {
-                    // This stream is unaffected by the discontinuity
-                    return -EWOULDBLOCK;
-                }
-            }
-
-            // reply should only be returned without a buffer set
-            // when there is an error (including EOS)
-            CHECK(err != OK);
-
-            reply->setInt32("err", err);
-            return ERROR_END_OF_STREAM;
-        }
-
-        dropAccessUnit = false;
-        if (!mIsAudio && !mIsEncrypted) {
-            // Extra safeguard if higher-level behavior changes. Otherwise, not required now.
-            // Preventing the buffer from being processed (and sent to codec) if this is a later
-            // round of playback but this time without prepareDrm. Or if there is a race between
-            // stop (which is not blocking) and releaseDrm allowing buffers being processed after
-            // Crypto has been released (GenericSource currently prevents this race though).
-            // Particularly doing this check before IsAVCReferenceFrame call to prevent parsing
-            // of encrypted data.
-            if (mIsEncryptedObservedEarlier) {
-                ALOGE("fetchInputData: mismatched mIsEncrypted/mIsEncryptedObservedEarlier (0/1)");
-
-                return INVALID_OPERATION;
-            }
-
-            int32_t layerId = 0;
-            bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
-            if (mRenderer->getVideoLateByUs() > 100000LL
-                    && mIsVideoAVC
-                    && !IsAVCReferenceFrame(accessUnit)) {
-                dropAccessUnit = true;
-            } else if (haveLayerId && mNumVideoTemporalLayerTotal > 1) {
-                // Add only one layer each time.
-                if (layerId > mCurrentMaxVideoTemporalLayerId + 1
-                        || layerId >= mNumVideoTemporalLayerAllowed) {
-                    dropAccessUnit = true;
-                    ALOGV("dropping layer(%d), speed=%g, allowed layer count=%d, max layerId=%d",
-                            layerId, mPlaybackSpeed, mNumVideoTemporalLayerAllowed,
-                            mCurrentMaxVideoTemporalLayerId);
-                } else if (layerId > mCurrentMaxVideoTemporalLayerId) {
-                    mCurrentMaxVideoTemporalLayerId = layerId;
-                } else if (layerId == 0 && mNumVideoTemporalLayerTotal > 1
-                        && IsIDR(accessUnit->data(), accessUnit->size())) {
-                    mCurrentMaxVideoTemporalLayerId = mNumVideoTemporalLayerTotal - 1;
-                }
-            }
-            if (dropAccessUnit) {
-                if (layerId <= mCurrentMaxVideoTemporalLayerId && layerId > 0) {
-                    mCurrentMaxVideoTemporalLayerId = layerId - 1;
-                }
-                ++mNumInputFramesDropped;
-            }
-        }
-    } while (dropAccessUnit);
-
-    // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
-#if 0
-    int64_t mediaTimeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
-    ALOGV("[%s] feeding input buffer at media time %.3f",
-         mIsAudio ? "audio" : "video",
-         mediaTimeUs / 1E6);
-#endif
-
-    if (mCCDecoder != NULL) {
-        mCCDecoder->decode(accessUnit);
-    }
-
-    reply->setBuffer("buffer", accessUnit);
-
-    return OK;
-}
-
-bool NuPlayer2::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
-    if (mCodec == NULL) {
-        ALOGE("[%s] onInputBufferFetched without a valid codec", mComponentName.c_str());
-        handleError(NO_INIT);
-        return false;
-    }
-
-    size_t bufferIx;
-    CHECK(msg->findSize("buffer-ix", &bufferIx));
-    CHECK_LT(bufferIx, mInputBuffers.size());
-    sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
-
-    sp<ABuffer> buffer;
-    bool hasBuffer = msg->findBuffer("buffer", &buffer);
-    bool needsCopy = true;
-
-    if (buffer == NULL /* includes !hasBuffer */) {
-        int32_t streamErr = ERROR_END_OF_STREAM;
-        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
-
-        CHECK(streamErr != OK);
-
-        // attempt to queue EOS
-        status_t err = mCodec->queueInputBuffer(
-                bufferIx,
-                0,
-                0,
-                0,
-                AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
-        if (err == OK) {
-            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
-        } else if (streamErr == ERROR_END_OF_STREAM) {
-            streamErr = err;
-            // err will not be ERROR_END_OF_STREAM
-        }
-
-        if (streamErr != ERROR_END_OF_STREAM) {
-            ALOGE("Stream error for [%s] (err=%d), EOS %s queued",
-                    mComponentName.c_str(),
-                    streamErr,
-                    err == OK ? "successfully" : "unsuccessfully");
-            handleError(streamErr);
-        }
-    } else {
-        sp<AMessage> extra;
-        if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
-            int64_t resumeAtMediaTimeUs;
-            if (extra->findInt64(
-                        "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
-                ALOGI("[%s] suppressing rendering until %lld us",
-                        mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
-                mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
-            }
-        }
-
-        int64_t timeUs = 0;
-        uint32_t flags = 0;
-        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
-        int32_t eos, csd;
-        // we do not expect SYNCFRAME for decoder
-        if (buffer->meta()->findInt32("eos", &eos) && eos) {
-            flags |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
-        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
-            flags |= AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
-        }
-
-        // Modular DRM
-        MediaBufferBase *mediaBuf = NULL;
-        sp<AMediaCodecCryptoInfoWrapper> cryptInfo;
-
-        // copy into codec buffer
-        if (needsCopy) {
-            if (buffer->size() > codecBuffer->capacity()) {
-                handleError(ERROR_BUFFER_TOO_SMALL);
-                mDequeuedInputBuffers.push_back(bufferIx);
-                return false;
-            }
-
-            if (buffer->data() != NULL) {
-                codecBuffer->setRange(0, buffer->size());
-                memcpy(codecBuffer->data(), buffer->data(), buffer->size());
-            } else { // No buffer->data()
-                //Modular DRM
-                sp<RefBase> holder;
-                if (buffer->meta()->findObject("mediaBufferHolder", &holder)) {
-                    mediaBuf = (holder != nullptr) ?
-                        static_cast<MediaBufferHolder*>(holder.get())->mediaBuffer() : nullptr;
-                }
-                if (mediaBuf != NULL) {
-                    if (mediaBuf->size() > codecBuffer->capacity()) {
-                        handleError(ERROR_BUFFER_TOO_SMALL);
-                        mDequeuedInputBuffers.push_back(bufferIx);
-                        return false;
-                    }
-
-                    codecBuffer->setRange(0, mediaBuf->size());
-                    memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
-
-                    MetaDataBase &meta_data = mediaBuf->meta_data();
-                    cryptInfo = AMediaCodecCryptoInfoWrapper::Create(meta_data);
-                } else { // No mediaBuf
-                    ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
-                            buffer.get());
-                    handleError(UNKNOWN_ERROR);
-                    return false;
-                }
-            } // buffer->data()
-        } // needsCopy
-
-        sp<RefBase> cryptInfoObj;
-        if (buffer->meta()->findObject("cryptInfo", &cryptInfoObj)) {
-            cryptInfo = static_cast<AMediaCodecCryptoInfoWrapper *>(cryptInfoObj.get());
-        }
-
-        status_t err;
-        if (cryptInfo != NULL) {
-            err = mCodec->queueSecureInputBuffer(
-                    bufferIx,
-                    codecBuffer->offset(),
-                    cryptInfo,
-                    timeUs,
-                    flags);
-            // synchronous call so done with cryptInfo here
-        } else {
-            err = mCodec->queueInputBuffer(
-                    bufferIx,
-                    codecBuffer->offset(),
-                    codecBuffer->size(),
-                    timeUs,
-                    flags);
-        } // no cryptInfo
-
-        if (err != OK) {
-            ALOGE("onInputBufferFetched: queue%sInputBuffer failed for [%s] (err=%d)",
-                    (cryptInfo != NULL ? "Secure" : ""),
-                    mComponentName.c_str(), err);
-            handleError(err);
-        } else {
-            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
-        }
-
-    }   // buffer != NULL
-    return true;
-}
-
-void NuPlayer2::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
-    status_t err;
-    int32_t render;
-    size_t bufferIx;
-    int32_t eos;
-    CHECK(msg->findSize("buffer-ix", &bufferIx));
-
-    if (!mIsAudio) {
-        int64_t timeUs;
-        sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
-        buffer->meta()->findInt64("timeUs", &timeUs);
-
-        if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
-            mCCDecoder->display(timeUs);
-        }
-    }
-
-    if (mCodec == NULL) {
-        err = NO_INIT;
-    } else if (msg->findInt32("render", &render) && render) {
-        int64_t timestampNs;
-        CHECK(msg->findInt64("timestampNs", &timestampNs));
-        err = mCodec->releaseOutputBufferAtTime(bufferIx, timestampNs);
-    } else {
-        mNumOutputFramesDropped += !mIsAudio;
-        err = mCodec->releaseOutputBuffer(bufferIx, false /* render */);
-    }
-    if (err != OK) {
-        ALOGE("failed to release output buffer for [%s] (err=%d)",
-                mComponentName.c_str(), err);
-        handleError(err);
-    }
-    if (msg->findInt32("eos", &eos) && eos
-            && isDiscontinuityPending()) {
-        finishHandleDiscontinuity(true /* flushOnTimeChange */);
-    }
-}
-
-bool NuPlayer2::Decoder::isDiscontinuityPending() const {
-    return mFormatChangePending || mTimeChangePending;
-}
-
-void NuPlayer2::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
-    ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
-            mFormatChangePending, mTimeChangePending, flushOnTimeChange);
-
-    // If we have format change, pause and wait to be killed;
-    // If we have time change only, flush and restart fetching.
-
-    if (mFormatChangePending) {
-        mPaused = true;
-    } else if (mTimeChangePending) {
-        if (flushOnTimeChange) {
-            doFlush(false /* notifyComplete */);
-            signalResume(false /* notifyComplete */);
-        }
-    }
-
-    // Notify NuPlayer2 to either shutdown decoder, or rescan sources
-    sp<AMessage> msg = mNotify->dup();
-    msg->setInt32("what", kWhatInputDiscontinuity);
-    msg->setInt32("formatChange", mFormatChangePending);
-    msg->post();
-
-    mFormatChangePending = false;
-    mTimeChangePending = false;
-}
-
-bool NuPlayer2::Decoder::supportsSeamlessAudioFormatChange(
-        const sp<AMessage> &targetFormat) const {
-    if (targetFormat == NULL) {
-        return true;
-    }
-
-    AString mime;
-    if (!targetFormat->findString("mime", &mime)) {
-        return false;
-    }
-
-    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
-        // field-by-field comparison
-        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
-        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
-            int32_t oldVal, newVal;
-            if (!mInputFormat->getInt32(keys[i], &oldVal) ||
-                    !targetFormat->findInt32(keys[i], &newVal) ||
-                    oldVal != newVal) {
-                return false;
-            }
-        }
-
-        sp<ABuffer> newBuf;
-        uint8_t *oldBufData = NULL;
-        size_t oldBufSize = 0;
-        if (mInputFormat->getBuffer("csd-0", (void**)&oldBufData, &oldBufSize) &&
-                targetFormat->findBuffer("csd-0", &newBuf)) {
-            if (oldBufSize != newBuf->size()) {
-                return false;
-            }
-            return !memcmp(oldBufData, newBuf->data(), oldBufSize);
-        }
-    }
-    return false;
-}
-
-bool NuPlayer2::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
-    if (mInputFormat == NULL) {
-        return false;
-    }
-
-    if (targetFormat == NULL) {
-        return true;
-    }
-
-    AString oldMime, newMime;
-    if (!mInputFormat->getString("mime", &oldMime)
-            || !targetFormat->findString("mime", &newMime)
-            || !(oldMime == newMime)) {
-        return false;
-    }
-
-    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
-    bool seamless;
-    if (audio) {
-        seamless = supportsSeamlessAudioFormatChange(targetFormat);
-    } else {
-        int32_t isAdaptive;
-        seamless = (mCodec != NULL &&
-                mInputFormat->getInt32("adaptive-playback", &isAdaptive) &&
-                isAdaptive);
-    }
-
-    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
-    return seamless;
-}
-
-void NuPlayer2::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
-    if (format == NULL) {
-        return;
-    }
-    mCSDsForCurrentFormat.clear();
-    for (int32_t i = 0; ; ++i) {
-        AString tag = "csd-";
-        tag.append(i);
-        sp<ABuffer> buffer;
-        if (!format->findBuffer(tag.c_str(), &buffer)) {
-            break;
-        }
-        mCSDsForCurrentFormat.push(buffer);
-    }
-}
-
-void NuPlayer2::Decoder::notifyResumeCompleteIfNecessary() {
-    if (mResumePending) {
-        mResumePending = false;
-
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatResumeCompleted);
-        notify->post();
-    }
-}
-
-}  // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.h
deleted file mode 100644
index fdfb10e..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_DECODER_H_
-#define NUPLAYER2_DECODER_H_
-
-#include "NuPlayer2.h"
-
-#include "NuPlayer2DecoderBase.h"
-
-namespace android {
-
-class MediaCodecBuffer;
-
-struct AMediaCodecWrapper;
-struct AMediaFormatWrapper;
-
-struct NuPlayer2::Decoder : public DecoderBase {
-    Decoder(const sp<AMessage> &notify,
-            const sp<Source> &source,
-            pid_t pid,
-            uid_t uid,
-            const sp<Renderer> &renderer = NULL,
-            const sp<ANativeWindowWrapper> &nww = NULL,
-            const sp<CCDecoder> &ccDecoder = NULL);
-
-    virtual sp<AMessage> getStats() const;
-
-    // sets the output surface of video decoders.
-    virtual status_t setVideoSurface(const sp<ANativeWindowWrapper> &nww);
-
-    virtual status_t releaseCrypto();
-
-protected:
-    virtual ~Decoder();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    virtual void onConfigure(const sp<AMessage> &format);
-    virtual void onSetParameters(const sp<AMessage> &params);
-    virtual void onSetRenderer(const sp<Renderer> &renderer);
-    virtual void onResume(bool notifyComplete);
-    virtual void onFlush();
-    virtual void onShutdown(bool notifyComplete);
-    virtual bool doRequestBuffers();
-
-private:
-    enum {
-        kWhatCodecNotify         = 'cdcN',
-        kWhatRenderBuffer        = 'rndr',
-        kWhatSetVideoSurface     = 'sSur',
-        kWhatAudioOutputFormatChanged = 'aofc',
-        kWhatDrmReleaseCrypto    = 'rDrm',
-    };
-
-    enum {
-        kMaxNumVideoTemporalLayers = 32,
-    };
-
-    sp<ANativeWindowWrapper> mNativeWindow;
-
-    sp<Source> mSource;
-    sp<Renderer> mRenderer;
-    sp<CCDecoder> mCCDecoder;
-
-    sp<AMediaFormatWrapper> mInputFormat;
-    sp<AMediaCodecWrapper> mCodec;
-
-    List<sp<AMessage> > mPendingInputMessages;
-
-    Vector<sp<MediaCodecBuffer> > mInputBuffers;
-    Vector<sp<MediaCodecBuffer> > mOutputBuffers;
-    Vector<sp<ABuffer> > mCSDsForCurrentFormat;
-    Vector<sp<ABuffer> > mCSDsToSubmit;
-    Vector<bool> mInputBufferIsDequeued;
-    Vector<MediaBuffer *> mMediaBuffers;
-    Vector<size_t> mDequeuedInputBuffers;
-
-    const pid_t mPid;
-    const uid_t mUid;
-    int64_t mSkipRenderingUntilMediaTimeUs;
-    int64_t mNumFramesTotal;
-    int64_t mNumInputFramesDropped;
-    int64_t mNumOutputFramesDropped;
-    int32_t mVideoWidth;
-    int32_t mVideoHeight;
-    bool mIsAudio;
-    bool mIsVideoAVC;
-    bool mIsSecure;
-    bool mIsEncrypted;
-    bool mIsEncryptedObservedEarlier;
-    bool mFormatChangePending;
-    bool mTimeChangePending;
-    float mFrameRateTotal;
-    float mPlaybackSpeed;
-    int32_t mNumVideoTemporalLayerTotal;
-    int32_t mNumVideoTemporalLayerAllowed;
-    int32_t mCurrentMaxVideoTemporalLayerId;
-    float mVideoTemporalLayerAggregateFps[kMaxNumVideoTemporalLayers];
-
-    bool mResumePending;
-    AString mComponentName;
-
-    void handleError(int32_t err);
-    bool handleAnInputBuffer(size_t index);
-    bool handleAnOutputBuffer(
-            size_t index,
-            size_t offset,
-            size_t size,
-            int64_t timeUs,
-            int32_t flags);
-    void handleOutputFormatChange(const sp<AMessage> &format);
-
-    void releaseAndResetMediaBuffers();
-    bool isStaleReply(const sp<AMessage> &msg);
-
-    void doFlush(bool notifyComplete);
-    status_t fetchInputData(sp<AMessage> &reply);
-    bool onInputBufferFetched(const sp<AMessage> &msg);
-    void onRenderBuffer(const sp<AMessage> &msg);
-
-    bool supportsSeamlessFormatChange(const sp<AMessage> &to) const;
-    bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const;
-    void rememberCodecSpecificData(const sp<AMessage> &format);
-    bool isDiscontinuityPending() const;
-    void finishHandleDiscontinuity(bool flushOnTimeChange);
-
-    void notifyResumeCompleteIfNecessary();
-
-    void onReleaseCrypto(const sp<AMessage>& msg);
-
-    DISALLOW_EVIL_CONSTRUCTORS(Decoder);
-};
-
-}  // namespace android
-
-#endif  // NUPLAYER2_DECODER_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp
deleted file mode 100644
index 914f29f..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2DecoderBase"
-#include <utils/Log.h>
-#include <inttypes.h>
-
-#include "NuPlayer2DecoderBase.h"
-
-#include "NuPlayer2Renderer.h"
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-namespace android {
-
-NuPlayer2::DecoderBase::DecoderBase(const sp<AMessage> &notify)
-    :  mNotify(notify),
-       mBufferGeneration(0),
-       mPaused(false),
-       mStats(new AMessage),
-       mRequestInputBuffersPending(false) {
-    // Every decoder has its own looper because MediaCodec operations
-    // are blocking, but NuPlayer2 needs asynchronous operations.
-    mDecoderLooper = new ALooper;
-    mDecoderLooper->setName("NP2Decoder");
-    mDecoderLooper->start(false, /* runOnCallingThread */
-                          true,  /* canCallJava */
-                          ANDROID_PRIORITY_AUDIO);
-}
-
-NuPlayer2::DecoderBase::~DecoderBase() {
-    stopLooper();
-}
-
-static
-status_t PostAndAwaitResponse(
-        const sp<AMessage> &msg, sp<AMessage> *response) {
-    status_t err = msg->postAndAwaitResponse(response);
-
-    if (err != OK) {
-        return err;
-    }
-
-    if (!(*response)->findInt32("err", &err)) {
-        err = OK;
-    }
-
-    return err;
-}
-
-void NuPlayer2::DecoderBase::configure(const sp<AMessage> &format) {
-    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
-    msg->setMessage("format", format);
-    msg->post();
-}
-
-void NuPlayer2::DecoderBase::init() {
-    mDecoderLooper->registerHandler(this);
-}
-
-void NuPlayer2::DecoderBase::stopLooper() {
-    mDecoderLooper->unregisterHandler(id());
-    mDecoderLooper->stop();
-}
-
-void NuPlayer2::DecoderBase::setParameters(const sp<AMessage> &params) {
-    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
-    msg->setMessage("params", params);
-    msg->post();
-}
-
-void NuPlayer2::DecoderBase::setRenderer(const sp<Renderer> &renderer) {
-    sp<AMessage> msg = new AMessage(kWhatSetRenderer, this);
-    msg->setObject("renderer", renderer);
-    msg->post();
-}
-
-void NuPlayer2::DecoderBase::pause() {
-    sp<AMessage> msg = new AMessage(kWhatPause, this);
-
-    sp<AMessage> response;
-    PostAndAwaitResponse(msg, &response);
-}
-
-void NuPlayer2::DecoderBase::signalFlush() {
-    (new AMessage(kWhatFlush, this))->post();
-}
-
-void NuPlayer2::DecoderBase::signalResume(bool notifyComplete) {
-    sp<AMessage> msg = new AMessage(kWhatResume, this);
-    msg->setInt32("notifyComplete", notifyComplete);
-    msg->post();
-}
-
-void NuPlayer2::DecoderBase::initiateShutdown() {
-    (new AMessage(kWhatShutdown, this))->post();
-}
-
-void NuPlayer2::DecoderBase::onRequestInputBuffers() {
-    if (mRequestInputBuffersPending) {
-        return;
-    }
-
-    // doRequestBuffers() return true if we should request more data
-    if (doRequestBuffers()) {
-        mRequestInputBuffersPending = true;
-
-        sp<AMessage> msg = new AMessage(kWhatRequestInputBuffers, this);
-        msg->post(10 * 1000LL);
-    }
-}
-
-void NuPlayer2::DecoderBase::onMessageReceived(const sp<AMessage> &msg) {
-
-    switch (msg->what()) {
-        case kWhatConfigure:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-            onConfigure(format);
-            break;
-        }
-
-        case kWhatSetParameters:
-        {
-            sp<AMessage> params;
-            CHECK(msg->findMessage("params", &params));
-            onSetParameters(params);
-            break;
-        }
-
-        case kWhatSetRenderer:
-        {
-            sp<RefBase> obj;
-            CHECK(msg->findObject("renderer", &obj));
-            onSetRenderer(static_cast<Renderer *>(obj.get()));
-            break;
-        }
-
-        case kWhatPause:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            mPaused = true;
-
-            (new AMessage)->postReply(replyID);
-            break;
-        }
-
-        case kWhatRequestInputBuffers:
-        {
-            mRequestInputBuffersPending = false;
-            onRequestInputBuffers();
-            break;
-        }
-
-        case kWhatFlush:
-        {
-            onFlush();
-            break;
-        }
-
-        case kWhatResume:
-        {
-            int32_t notifyComplete;
-            CHECK(msg->findInt32("notifyComplete", &notifyComplete));
-
-            onResume(notifyComplete);
-            break;
-        }
-
-        case kWhatShutdown:
-        {
-            onShutdown(true);
-            break;
-        }
-
-        default:
-            TRESPASS();
-            break;
-    }
-}
-
-void NuPlayer2::DecoderBase::handleError(int32_t err)
-{
-    // We cannot immediately release the codec due to buffers still outstanding
-    // in the renderer.  We signal to the player the error so it can shutdown/release the
-    // decoder after flushing and increment the generation to discard unnecessary messages.
-
-    ++mBufferGeneration;
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatError);
-    notify->setInt32("err", err);
-    notify->post();
-}
-
-}  // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.h b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.h
deleted file mode 100644
index 1e57f0d..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_DECODER_BASE_H_
-
-#define NUPLAYER2_DECODER_BASE_H_
-
-#include "NuPlayer2.h"
-
-#include <media/stagefright/foundation/AHandler.h>
-
-namespace android {
-
-struct ABuffer;
-struct ANativeWindowWrapper;
-struct MediaCodec;
-class MediaBuffer;
-class MediaCodecBuffer;
-
-struct NuPlayer2::DecoderBase : public AHandler {
-    explicit DecoderBase(const sp<AMessage> &notify);
-
-    void configure(const sp<AMessage> &format);
-    void init();
-    void setParameters(const sp<AMessage> &params);
-
-    // Synchronous call to ensure decoder will not request or send out data.
-    void pause();
-
-    void setRenderer(const sp<Renderer> &renderer);
-    virtual status_t setVideoSurface(const sp<ANativeWindowWrapper> &) { return INVALID_OPERATION; }
-
-    void signalFlush();
-    void signalResume(bool notifyComplete);
-    void initiateShutdown();
-
-    virtual sp<AMessage> getStats() const {
-        return mStats;
-    }
-
-    virtual status_t releaseCrypto() {
-        return INVALID_OPERATION;
-    }
-
-    enum {
-        kWhatInputDiscontinuity  = 'inDi',
-        kWhatVideoSizeChanged    = 'viSC',
-        kWhatFlushCompleted      = 'flsC',
-        kWhatShutdownCompleted   = 'shDC',
-        kWhatResumeCompleted     = 'resC',
-        kWhatEOS                 = 'eos ',
-        kWhatError               = 'err ',
-    };
-
-protected:
-
-    virtual ~DecoderBase();
-
-    void stopLooper();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    virtual void onConfigure(const sp<AMessage> &format) = 0;
-    virtual void onSetParameters(const sp<AMessage> &params) = 0;
-    virtual void onSetRenderer(const sp<Renderer> &renderer) = 0;
-    virtual void onResume(bool notifyComplete) = 0;
-    virtual void onFlush() = 0;
-    virtual void onShutdown(bool notifyComplete) = 0;
-
-    void onRequestInputBuffers();
-    virtual bool doRequestBuffers() = 0;
-    virtual void handleError(int32_t err);
-
-    sp<AMessage> mNotify;
-    int32_t mBufferGeneration;
-    bool mPaused;
-    sp<AMessage> mStats;
-
-private:
-    enum {
-        kWhatConfigure           = 'conf',
-        kWhatSetParameters       = 'setP',
-        kWhatSetRenderer         = 'setR',
-        kWhatPause               = 'paus',
-        kWhatRequestInputBuffers = 'reqB',
-        kWhatFlush               = 'flus',
-        kWhatShutdown            = 'shuD',
-    };
-
-    sp<ALooper> mDecoderLooper;
-    bool mRequestInputBuffersPending;
-
-    DISALLOW_EVIL_CONSTRUCTORS(DecoderBase);
-};
-
-}  // namespace android
-
-#endif  // NUPLAYER2_DECODER_BASE_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp
deleted file mode 100644
index 0514e88..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2DecoderPassThrough"
-#include <utils/Log.h>
-#include <inttypes.h>
-
-#include "NuPlayer2DecoderPassThrough.h"
-
-#include "NuPlayer2Renderer.h"
-#include "NuPlayer2Source.h"
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include "ATSParser.h"
-
-namespace android {
-
-// TODO optimize buffer size for power consumption
-// The offload read buffer size is 32 KB but 24 KB uses less power.
-static const size_t kAggregateBufferSizeBytes = 24 * 1024;
-static const size_t kMaxCachedBytes = 200000;
-
-NuPlayer2::DecoderPassThrough::DecoderPassThrough(
-        const sp<AMessage> &notify,
-        const sp<Source> &source,
-        const sp<Renderer> &renderer)
-    : DecoderBase(notify),
-      mSource(source),
-      mRenderer(renderer),
-      mSkipRenderingUntilMediaTimeUs(-1LL),
-      mReachedEOS(true),
-      mPendingAudioErr(OK),
-      mPendingBuffersToDrain(0),
-      mCachedBytes(0),
-      mComponentName("pass through decoder") {
-    ALOGW_IF(renderer == NULL, "expect a non-NULL renderer");
-}
-
-NuPlayer2::DecoderPassThrough::~DecoderPassThrough() {
-}
-
-void NuPlayer2::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
-    ALOGV("[%s] onConfigure", mComponentName.c_str());
-    mCachedBytes = 0;
-    mPendingBuffersToDrain = 0;
-    mReachedEOS = false;
-    ++mBufferGeneration;
-
-    onRequestInputBuffers();
-
-    int32_t hasVideo = 0;
-    format->findInt32("has-video", &hasVideo);
-
-    // The audio sink is already opened before the PassThrough decoder is created.
-    // Opening again might be relevant if decoder is instantiated after shutdown and
-    // format is different.
-    status_t err = mRenderer->openAudioSink(
-            format, true /* offloadOnly */, hasVideo,
-            AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */, mSource->isStreaming());
-    if (err != OK) {
-        handleError(err);
-    }
-}
-
-void NuPlayer2::DecoderPassThrough::onSetParameters(const sp<AMessage> &/*params*/) {
-    ALOGW("onSetParameters() called unexpectedly");
-}
-
-void NuPlayer2::DecoderPassThrough::onSetRenderer(
-        const sp<Renderer> &renderer) {
-    // renderer can't be changed during offloading
-    ALOGW_IF(renderer != mRenderer,
-            "ignoring request to change renderer");
-}
-
-bool NuPlayer2::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
-    int32_t generation;
-    CHECK(msg->findInt32("generation", &generation));
-    return generation != mBufferGeneration;
-}
-
-bool NuPlayer2::DecoderPassThrough::isDoneFetching() const {
-    ALOGV("[%s] mCachedBytes = %zu, mReachedEOS = %d mPaused = %d",
-            mComponentName.c_str(), mCachedBytes, mReachedEOS, mPaused);
-
-    return mCachedBytes >= kMaxCachedBytes || mReachedEOS || mPaused;
-}
-
-/*
- * returns true if we should request more data
- */
-bool NuPlayer2::DecoderPassThrough::doRequestBuffers() {
-    status_t err = OK;
-    while (!isDoneFetching()) {
-        sp<AMessage> msg = new AMessage();
-
-        err = fetchInputData(msg);
-        if (err != OK) {
-            break;
-        }
-
-        onInputBufferFetched(msg);
-    }
-
-    return err == -EWOULDBLOCK
-            && mSource->feedMoreTSData() == OK;
-}
-
-status_t NuPlayer2::DecoderPassThrough::dequeueAccessUnit(sp<ABuffer> *accessUnit) {
-    status_t err;
-
-    // Did we save an accessUnit earlier because of a discontinuity?
-    if (mPendingAudioAccessUnit != NULL) {
-        *accessUnit = mPendingAudioAccessUnit;
-        mPendingAudioAccessUnit.clear();
-        err = mPendingAudioErr;
-        ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit");
-    } else {
-        err = mSource->dequeueAccessUnit(true /* audio */, accessUnit);
-    }
-
-    if (err == INFO_DISCONTINUITY || err == ERROR_END_OF_STREAM) {
-        if (mAggregateBuffer != NULL) {
-            // We already have some data so save this for later.
-            mPendingAudioErr = err;
-            mPendingAudioAccessUnit = *accessUnit;
-            (*accessUnit).clear();
-            ALOGD("return aggregated buffer and save err(=%d) for later", err);
-            err = OK;
-        }
-    }
-
-    return err;
-}
-
-sp<ABuffer> NuPlayer2::DecoderPassThrough::aggregateBuffer(
-        const sp<ABuffer> &accessUnit) {
-    sp<ABuffer> aggregate;
-
-    if (accessUnit == NULL) {
-        // accessUnit is saved to mPendingAudioAccessUnit
-        // return current mAggregateBuffer
-        aggregate = mAggregateBuffer;
-        mAggregateBuffer.clear();
-        return aggregate;
-    }
-
-    size_t smallSize = accessUnit->size();
-    if ((mAggregateBuffer == NULL)
-            // Don't bother if only room for a few small buffers.
-            && (smallSize < (kAggregateBufferSizeBytes / 3))) {
-        // Create a larger buffer for combining smaller buffers from the extractor.
-        mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
-        mAggregateBuffer->setRange(0, 0); // start empty
-    }
-
-    if (mAggregateBuffer != NULL) {
-        int64_t timeUs;
-        int64_t dummy;
-        bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
-        bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
-        // Will the smaller buffer fit?
-        size_t bigSize = mAggregateBuffer->size();
-        size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
-        // Should we save this small buffer for the next big buffer?
-        // If the first small buffer did not have a timestamp then save
-        // any buffer that does have a timestamp until the next big buffer.
-        if ((smallSize > roomLeft)
-            || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
-            mPendingAudioErr = OK;
-            mPendingAudioAccessUnit = accessUnit;
-            aggregate = mAggregateBuffer;
-            mAggregateBuffer.clear();
-        } else {
-            // Grab time from first small buffer if available.
-            if ((bigSize == 0) && smallTimestampValid) {
-                mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
-            }
-            // Append small buffer to the bigger buffer.
-            memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
-            bigSize += smallSize;
-            mAggregateBuffer->setRange(0, bigSize);
-
-            ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
-                    smallSize, bigSize, mAggregateBuffer->capacity());
-        }
-    } else {
-        // decided not to aggregate
-        aggregate = accessUnit;
-    }
-
-    return aggregate;
-}
-
-status_t NuPlayer2::DecoderPassThrough::fetchInputData(sp<AMessage> &reply) {
-    sp<ABuffer> accessUnit;
-
-    do {
-        status_t err = dequeueAccessUnit(&accessUnit);
-
-        if (err == -EWOULDBLOCK) {
-            // Flush out the aggregate buffer to try to avoid underrun.
-            accessUnit = aggregateBuffer(NULL /* accessUnit */);
-            if (accessUnit != NULL) {
-                break;
-            }
-            return err;
-        } else if (err != OK) {
-            if (err == INFO_DISCONTINUITY) {
-                int32_t type;
-                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
-
-                bool formatChange =
-                        (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
-
-                bool timeChange =
-                        (type & ATSParser::DISCONTINUITY_TIME) != 0;
-
-                ALOGI("audio discontinuity (formatChange=%d, time=%d)",
-                        formatChange, timeChange);
-
-                if (formatChange || timeChange) {
-                    sp<AMessage> msg = mNotify->dup();
-                    msg->setInt32("what", kWhatInputDiscontinuity);
-                    // will perform seamless format change,
-                    // only notify NuPlayer2 to scan sources
-                    msg->setInt32("formatChange", false);
-                    msg->post();
-                }
-
-                if (timeChange) {
-                    doFlush(false /* notifyComplete */);
-                    err = OK;
-                } else if (formatChange) {
-                    // do seamless format change
-                    err = OK;
-                } else {
-                    // This stream is unaffected by the discontinuity
-                    return -EWOULDBLOCK;
-                }
-            }
-
-            reply->setInt32("err", err);
-            return OK;
-        }
-
-        accessUnit = aggregateBuffer(accessUnit);
-    } while (accessUnit == NULL);
-
-#if 0
-    int64_t mediaTimeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
-    ALOGV("feeding audio input buffer at media time %.2f secs",
-         mediaTimeUs / 1E6);
-#endif
-
-    reply->setBuffer("buffer", accessUnit);
-
-    return OK;
-}
-
-void NuPlayer2::DecoderPassThrough::onInputBufferFetched(
-        const sp<AMessage> &msg) {
-    if (mReachedEOS) {
-        return;
-    }
-
-    sp<ABuffer> buffer;
-    bool hasBuffer = msg->findBuffer("buffer", &buffer);
-    if (buffer == NULL) {
-        int32_t streamErr = ERROR_END_OF_STREAM;
-        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
-        if (streamErr == OK) {
-            return;
-        }
-
-        if (streamErr != ERROR_END_OF_STREAM) {
-            handleError(streamErr);
-        }
-        mReachedEOS = true;
-        if (mRenderer != NULL) {
-            mRenderer->queueEOS(true /* audio */, ERROR_END_OF_STREAM);
-        }
-        return;
-    }
-
-    sp<AMessage> extra;
-    if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
-        int64_t resumeAtMediaTimeUs;
-        if (extra->findInt64(
-                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
-            ALOGI("[%s] suppressing rendering until %lld us",
-                    mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
-            mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
-        }
-    }
-
-    int32_t bufferSize = buffer->size();
-    mCachedBytes += bufferSize;
-
-    int64_t timeUs = 0;
-    CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-    if (mSkipRenderingUntilMediaTimeUs >= 0) {
-        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
-            ALOGV("[%s] dropping buffer at time %lld as requested.",
-                     mComponentName.c_str(), (long long)timeUs);
-
-            onBufferConsumed(bufferSize);
-            return;
-        }
-
-        mSkipRenderingUntilMediaTimeUs = -1;
-    }
-
-    if (mRenderer == NULL) {
-        onBufferConsumed(bufferSize);
-        return;
-    }
-
-    sp<AMessage> reply = new AMessage(kWhatBufferConsumed, this);
-    reply->setInt32("generation", mBufferGeneration);
-    reply->setInt32("size", bufferSize);
-
-    sp<MediaCodecBuffer> mcBuffer = new MediaCodecBuffer(nullptr, buffer);
-    mcBuffer->meta()->setInt64("timeUs", timeUs);
-
-    mRenderer->queueBuffer(true /* audio */, mcBuffer, reply);
-
-    ++mPendingBuffersToDrain;
-    ALOGV("onInputBufferFilled: #ToDrain = %zu, cachedBytes = %zu",
-            mPendingBuffersToDrain, mCachedBytes);
-}
-
-void NuPlayer2::DecoderPassThrough::onBufferConsumed(int32_t size) {
-    --mPendingBuffersToDrain;
-    mCachedBytes -= size;
-    ALOGV("onBufferConsumed: #ToDrain = %zu, cachedBytes = %zu",
-            mPendingBuffersToDrain, mCachedBytes);
-    onRequestInputBuffers();
-}
-
-void NuPlayer2::DecoderPassThrough::onResume(bool notifyComplete) {
-    mPaused = false;
-
-    onRequestInputBuffers();
-
-    if (notifyComplete) {
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatResumeCompleted);
-        notify->post();
-    }
-}
-
-void NuPlayer2::DecoderPassThrough::doFlush(bool notifyComplete) {
-    ++mBufferGeneration;
-    mSkipRenderingUntilMediaTimeUs = -1;
-    mPendingAudioAccessUnit.clear();
-    mPendingAudioErr = OK;
-    mAggregateBuffer.clear();
-
-    if (mRenderer != NULL) {
-        mRenderer->flush(true /* audio */, notifyComplete);
-        mRenderer->signalTimeDiscontinuity();
-    }
-
-    mPendingBuffersToDrain = 0;
-    mCachedBytes = 0;
-    mReachedEOS = false;
-}
-
-void NuPlayer2::DecoderPassThrough::onFlush() {
-    doFlush(true /* notifyComplete */);
-
-    mPaused = true;
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFlushCompleted);
-    notify->post();
-
-}
-
-void NuPlayer2::DecoderPassThrough::onShutdown(bool notifyComplete) {
-    ++mBufferGeneration;
-    mSkipRenderingUntilMediaTimeUs = -1;
-
-    if (notifyComplete) {
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatShutdownCompleted);
-        notify->post();
-    }
-
-    mReachedEOS = true;
-}
-
-void NuPlayer2::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
-    ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
-            msg->debugString().c_str());
-
-    switch (msg->what()) {
-        case kWhatBufferConsumed:
-        {
-            if (!isStaleReply(msg)) {
-                int32_t size;
-                CHECK(msg->findInt32("size", &size));
-                onBufferConsumed(size);
-            }
-            break;
-        }
-
-        default:
-            DecoderBase::onMessageReceived(msg);
-            break;
-    }
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.h b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.h
deleted file mode 100644
index 838c60a..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_DECODER_PASS_THROUGH_H_
-
-#define NUPLAYER2_DECODER_PASS_THROUGH_H_
-
-#include "NuPlayer2.h"
-
-#include "NuPlayer2DecoderBase.h"
-
-namespace android {
-
-struct NuPlayer2::DecoderPassThrough : public DecoderBase {
-    DecoderPassThrough(const sp<AMessage> &notify,
-                       const sp<Source> &source,
-                       const sp<Renderer> &renderer);
-
-protected:
-
-    virtual ~DecoderPassThrough();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    virtual void onConfigure(const sp<AMessage> &format);
-    virtual void onSetParameters(const sp<AMessage> &params);
-    virtual void onSetRenderer(const sp<Renderer> &renderer);
-    virtual void onResume(bool notifyComplete);
-    virtual void onFlush();
-    virtual void onShutdown(bool notifyComplete);
-    virtual bool doRequestBuffers();
-
-private:
-    enum {
-        kWhatBufferConsumed     = 'bufC',
-    };
-
-    sp<Source> mSource;
-    sp<Renderer> mRenderer;
-    int64_t mSkipRenderingUntilMediaTimeUs;
-
-    bool    mReachedEOS;
-
-    // Used by feedDecoderInputData to aggregate small buffers into
-    // one large buffer.
-    sp<ABuffer> mPendingAudioAccessUnit;
-    status_t    mPendingAudioErr;
-    sp<ABuffer> mAggregateBuffer;
-
-    // mPendingBuffersToDrain are only for debugging. It can be removed
-    // when the power investigation is done.
-    size_t  mPendingBuffersToDrain;
-    size_t  mCachedBytes;
-    AString mComponentName;
-
-    bool isStaleReply(const sp<AMessage> &msg);
-    bool isDoneFetching() const;
-
-    status_t dequeueAccessUnit(sp<ABuffer> *accessUnit);
-    sp<ABuffer> aggregateBuffer(const sp<ABuffer> &accessUnit);
-    status_t fetchInputData(sp<AMessage> &reply);
-    void doFlush(bool notifyComplete);
-
-    void onInputBufferFetched(const sp<AMessage> &msg);
-    void onBufferConsumed(int32_t size);
-
-    DISALLOW_EVIL_CONSTRUCTORS(DecoderPassThrough);
-};
-
-}  // namespace android
-
-#endif  // NUPLAYER2_DECODER_PASS_THROUGH_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
deleted file mode 100644
index 1876496..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2Driver"
-#include <inttypes.h>
-#include <android-base/macros.h>
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-#include "NuPlayer2Driver.h"
-
-#include "NuPlayer2.h"
-#include "NuPlayer2Source.h"
-
-#include <media/DataSourceDesc.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/stagefright/MediaClock.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-#include <media/IMediaAnalyticsService.h>
-
-using google::protobuf::RepeatedPtrField;
-using android::media::MediaPlayer2Proto::Value;
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleepUs = 20000;
-
-namespace android {
-
-struct PlayerMessageWrapper : public RefBase {
-    static sp<PlayerMessageWrapper> Create(const PlayerMessage *p) {
-        if (p != NULL) {
-            sp<PlayerMessageWrapper> pw = new PlayerMessageWrapper();
-            pw->copyFrom(p);
-            return pw;
-        }
-        return NULL;
-    }
-
-    const PlayerMessage *getPlayerMessage() {
-        return mPlayerMessage;
-    }
-
-protected:
-    virtual ~PlayerMessageWrapper() {
-        if (mPlayerMessage != NULL) {
-            delete mPlayerMessage;
-        }
-    }
-
-private:
-    PlayerMessageWrapper()
-        : mPlayerMessage(NULL) { }
-
-    void copyFrom(const PlayerMessage *p) {
-        if (mPlayerMessage == NULL) {
-            mPlayerMessage = new PlayerMessage;
-        }
-        mPlayerMessage->CopyFrom(*p);
-    }
-
-    PlayerMessage *mPlayerMessage;
-};
-
-// key for media statistics
-static const char *kKeyPlayer = "nuplayer2";
-// attrs for media statistics
-    // NB: these are matched with public Java API constants defined
-    // in frameworks/base/media/java/android/media/MediaPlayer2.java
-    // These must be kept synchronized with the constants there.
-static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
-static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
-static const char *kPlayerWidth = "android.media.mediaplayer.width";
-static const char *kPlayerHeight = "android.media.mediaplayer.height";
-static const char *kPlayerFrames = "android.media.mediaplayer.frames";
-static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
-static const char *kPlayerFrameRate = "android.media.mediaplayer.fps";
-static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
-static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
-static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
-static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
-static const char *kPlayerError = "android.media.mediaplayer.err";
-static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
-
-// NB: These are not yet exposed as public Java API constants.
-static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
-static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
-//
-static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
-static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
-static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
-
-static const char *kPlayerVersion = "android.media.mediaplayer.version";
-
-
-NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
-    : mState(STATE_IDLE),
-      mAsyncResult(UNKNOWN_ERROR),
-      mSrcId(0),
-      mSetSurfaceInProgress(false),
-      mDurationUs(-1),
-      mPositionUs(-1),
-      mSeekInProgress(false),
-      mPlayingTimeUs(0),
-      mRebufferingTimeUs(0),
-      mRebufferingEvents(0),
-      mRebufferingAtExit(false),
-      mLooper(new ALooper),
-      mNuPlayer2Looper(new ALooper),
-      mMediaClock(new MediaClock),
-      mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
-      mPlayerFlags(0),
-      mMetricsHandle(0),
-      mPlayerVersion(0),
-      mClientUid(uid),
-      mAtEOS(false),
-      mLooping(false),
-      mAutoLoop(false) {
-    ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
-    mLooper->setName("NuPlayer2Driver Looper");
-    mNuPlayer2Looper->setName("NuPlayer2 Looper");
-
-    mMediaClock->init();
-
-    // XXX: what version are we?
-    // Ideally, this ticks with the apk version info for the APEX packaging
-
-    // set up media metrics record
-    mMetricsHandle = mediametrics_create(kKeyPlayer);
-    mediametrics_setUid(mMetricsHandle, mClientUid);
-    mediametrics_setInt64(mMetricsHandle, kPlayerVersion, mPlayerVersion);
-
-    mNuPlayer2Looper->start(
-            false, /* runOnCallingThread */
-            true,  /* canCallJava */
-            PRIORITY_AUDIO);
-
-    mNuPlayer2Looper->registerHandler(mPlayer);
-
-    mPlayer->setDriver(this);
-}
-
-NuPlayer2Driver::~NuPlayer2Driver() {
-    ALOGV("~NuPlayer2Driver(%p)", this);
-    mNuPlayer2Looper->stop();
-    mLooper->stop();
-
-    // finalize any pending metrics, usually a no-op.
-    updateMetrics("destructor");
-    logMetrics("destructor");
-
-    mediametrics_delete(mMetricsHandle);
-}
-
-status_t NuPlayer2Driver::initCheck() {
-    mLooper->start(
-            false, /* runOnCallingThread */
-            true,  /* canCallJava */
-            PRIORITY_AUDIO);
-
-    mLooper->registerHandler(this);
-    return OK;
-}
-
-status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
-    ALOGV("setDataSource(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    if (mState != STATE_IDLE) {
-        return INVALID_OPERATION;
-    }
-
-    mSrcId = dsd->mId;
-    mState = STATE_SET_DATASOURCE_PENDING;
-
-    mPlayer->setDataSourceAsync(dsd);
-
-    while (mState == STATE_SET_DATASOURCE_PENDING) {
-        mCondition.wait(mLock);
-    }
-
-    return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
-    ALOGV("prepareNextDataSource(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    mPlayer->prepareNextDataSourceAsync(dsd);
-
-    return OK;
-}
-
-status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
-    ALOGV("playNextDataSource(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    mSrcId = srcId;
-    mPlayer->playNextDataSource(srcId);
-
-    return OK;
-}
-
-status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
-    ALOGV("setVideoSurfaceTexture(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    if (mSetSurfaceInProgress) {
-        return INVALID_OPERATION;
-    }
-
-    switch (mState) {
-        case STATE_SET_DATASOURCE_PENDING:
-        case STATE_RESET_IN_PROGRESS:
-            return INVALID_OPERATION;
-
-        default:
-            break;
-    }
-
-    mSetSurfaceInProgress = true;
-
-    mPlayer->setVideoSurfaceTextureAsync(nww);
-
-    while (mSetSurfaceInProgress) {
-        mCondition.wait(mLock);
-    }
-
-    return OK;
-}
-
-status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
-    ALOGV("getBufferingSettings(%p)", this);
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (mState == STATE_IDLE) {
-            return INVALID_OPERATION;
-        }
-    }
-
-    return mPlayer->getBufferingSettings(buffering);
-}
-
-status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
-    ALOGV("setBufferingSettings(%p)", this);
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (mState == STATE_IDLE) {
-            return INVALID_OPERATION;
-        }
-    }
-
-    return mPlayer->setBufferingSettings(buffering);
-}
-
-status_t NuPlayer2Driver::prepareAsync() {
-    ALOGV("prepareAsync(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    switch (mState) {
-        case STATE_UNPREPARED:
-            mState = STATE_PREPARING;
-            mPlayer->prepareAsync();
-            return OK;
-        default:
-            return INVALID_OPERATION;
-    };
-}
-
-status_t NuPlayer2Driver::start() {
-    ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
-    Mutex::Autolock autoLock(mLock);
-    return start_l();
-}
-
-status_t NuPlayer2Driver::start_l() {
-    switch (mState) {
-        case STATE_PAUSED:
-        case STATE_PREPARED:
-        {
-            mPlayer->start();
-            FALLTHROUGH_INTENDED;
-        }
-
-        case STATE_RUNNING:
-        {
-            if (mAtEOS) {
-                mPlayer->rewind();
-                mAtEOS = false;
-                mPositionUs = -1;
-            }
-            break;
-        }
-
-        default:
-            return INVALID_OPERATION;
-    }
-
-    mState = STATE_RUNNING;
-
-    return OK;
-}
-
-status_t NuPlayer2Driver::pause() {
-    ALOGD("pause(%p)", this);
-    // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
-    // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
-    // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
-    // getCurrentPosition here.
-    int64_t unused;
-    getCurrentPosition(&unused);
-
-    Mutex::Autolock autoLock(mLock);
-
-    switch (mState) {
-        case STATE_PAUSED:
-            return OK;
-
-        case STATE_PREPARED:
-        case STATE_RUNNING:
-            mState = STATE_PAUSED;
-            mPlayer->pause();
-            break;
-
-        default:
-            return INVALID_OPERATION;
-    }
-
-    return OK;
-}
-
-bool NuPlayer2Driver::isPlaying() {
-    return mState == STATE_RUNNING && !mAtEOS;
-}
-
-status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    status_t err = mPlayer->setPlaybackSettings(rate);
-    if (err == OK) {
-        // try to update position
-        int64_t unused;
-        getCurrentPosition(&unused);
-    }
-    return err;
-}
-
-status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
-    return mPlayer->getPlaybackSettings(rate);
-}
-
-status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
-    return mPlayer->setSyncSettings(sync, videoFpsHint);
-}
-
-status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
-    return mPlayer->getSyncSettings(sync, videoFps);
-}
-
-status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
-    ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
-    Mutex::Autolock autoLock(mLock);
-
-    int64_t seekTimeUs = msec * 1000LL;
-
-    switch (mState) {
-        case STATE_PREPARED:
-        case STATE_PAUSED:
-        case STATE_RUNNING:
-        {
-            mAtEOS = false;
-            mSeekInProgress = true;
-            mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
-            break;
-        }
-
-        default:
-            return INVALID_OPERATION;
-    }
-
-    mPositionUs = seekTimeUs;
-    return OK;
-}
-
-status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
-    int64_t tempUs = 0;
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
-            tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
-            *msec = divRound(tempUs, (int64_t)(1000));
-            return OK;
-        }
-    }
-
-    status_t ret = mPlayer->getCurrentPosition(&tempUs);
-
-    Mutex::Autolock autoLock(mLock);
-    // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
-    // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
-    // position value that's different the seek to position.
-    if (ret != OK) {
-        tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
-    } else {
-        mPositionUs = tempUs;
-    }
-    *msec = divRound(tempUs, (int64_t)(1000));
-    return OK;
-}
-
-status_t NuPlayer2Driver::getDuration(int64_t *msec) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mDurationUs < 0) {
-        return UNKNOWN_ERROR;
-    }
-
-    *msec = (mDurationUs + 500LL) / 1000;
-
-    return OK;
-}
-
-void NuPlayer2Driver::updateMetrics(const char *where) {
-    if (where == NULL) {
-        where = "unknown";
-    }
-    ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
-
-    // gather the final stats for this record
-    Vector<sp<AMessage>> trackStats;
-    mPlayer->getStats(&trackStats);
-
-    if (trackStats.size() > 0) {
-        for (size_t i = 0; i < trackStats.size(); ++i) {
-            const sp<AMessage> &stats = trackStats.itemAt(i);
-
-            AString mime;
-            stats->findString("mime", &mime);
-
-            AString name;
-            stats->findString("component-name", &name);
-
-            if (mime.startsWith("video/")) {
-                int32_t width, height;
-                mediametrics_setCString(mMetricsHandle, kPlayerVMime, mime.c_str());
-                if (!name.empty()) {
-                    mediametrics_setCString(mMetricsHandle, kPlayerVCodec, name.c_str());
-                }
-
-                if (stats->findInt32("width", &width)
-                        && stats->findInt32("height", &height)) {
-                    mediametrics_setInt32(mMetricsHandle, kPlayerWidth, width);
-                    mediametrics_setInt32(mMetricsHandle, kPlayerHeight, height);
-                }
-
-                int64_t numFramesTotal = 0;
-                int64_t numFramesDropped = 0;
-                stats->findInt64("frames-total", &numFramesTotal);
-                stats->findInt64("frames-dropped-output", &numFramesDropped);
-
-                mediametrics_setInt64(mMetricsHandle, kPlayerFrames, numFramesTotal);
-                mediametrics_setInt64(mMetricsHandle, kPlayerFramesDropped, numFramesDropped);
-
-                float frameRate = 0;
-                if (stats->findFloat("frame-rate-output", &frameRate)) {
-                    mediametrics_setInt64(mMetricsHandle, kPlayerFrameRate, frameRate);
-                }
-
-            } else if (mime.startsWith("audio/")) {
-                mediametrics_setCString(mMetricsHandle, kPlayerAMime, mime.c_str());
-                if (!name.empty()) {
-                    mediametrics_setCString(mMetricsHandle, kPlayerACodec, name.c_str());
-                }
-            }
-        }
-    }
-
-    // always provide duration and playing time, even if they have 0/unknown values.
-
-    // getDuration() uses mLock for mutex -- careful where we use it.
-    int64_t duration_ms = -1;
-    getDuration(&duration_ms);
-    mediametrics_setInt64(mMetricsHandle, kPlayerDuration, duration_ms);
-
-    mediametrics_setInt64(mMetricsHandle, kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
-
-    if (mRebufferingEvents != 0) {
-        mediametrics_setInt64(mMetricsHandle, kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
-        mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingCount, mRebufferingEvents);
-        mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingAtExit, mRebufferingAtExit);
-    }
-
-    mediametrics_setCString(mMetricsHandle, kPlayerDataSourceType, mPlayer->getDataSourceType());
-}
-
-
-void NuPlayer2Driver::logMetrics(const char *where) {
-    if (where == NULL) {
-        where = "unknown";
-    }
-    ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
-
-    if (mMetricsHandle == 0 || mediametrics_isEnabled() == false) {
-        return;
-    }
-
-    // log only non-empty records
-    // we always updateMetrics() before we get here
-    // and that always injects 3 fields (duration, playing time, and
-    // datasource) into the record.
-    // So the canonical "empty" record has 3 elements in it.
-    if (mediametrics_count(mMetricsHandle) > 3) {
-        mediametrics_selfRecord(mMetricsHandle);
-        // re-init in case we prepare() and start() again.
-        mediametrics_delete(mMetricsHandle);
-        mMetricsHandle = mediametrics_create(kKeyPlayer);
-        mediametrics_setUid(mMetricsHandle, mClientUid);
-        mediametrics_setInt64(mMetricsHandle, kPlayerVersion, mPlayerVersion);
-    } else {
-        ALOGV("did not have anything to record");
-    }
-}
-
-status_t NuPlayer2Driver::reset() {
-    ALOGD("reset(%p) at state %d", this, mState);
-
-    updateMetrics("reset");
-    logMetrics("reset");
-
-    Mutex::Autolock autoLock(mLock);
-
-    switch (mState) {
-        case STATE_IDLE:
-            return OK;
-
-        case STATE_SET_DATASOURCE_PENDING:
-        case STATE_RESET_IN_PROGRESS:
-            return INVALID_OPERATION;
-
-        case STATE_PREPARING:
-        {
-            notifyListener_l(mSrcId, MEDIA2_PREPARED);
-            break;
-        }
-
-        default:
-            break;
-    }
-
-    mState = STATE_RESET_IN_PROGRESS;
-    mPlayer->resetAsync();
-
-    while (mState == STATE_RESET_IN_PROGRESS) {
-        mCondition.wait(mLock);
-    }
-
-    mDurationUs = -1;
-    mPositionUs = -1;
-    mLooping = false;
-    mPlayingTimeUs = 0;
-    mRebufferingTimeUs = 0;
-    mRebufferingEvents = 0;
-    mRebufferingAtExit = false;
-
-    return OK;
-}
-
-status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
-    ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
-    return mPlayer->notifyAt(mediaTimeUs);
-}
-
-status_t NuPlayer2Driver::setLooping(int loop) {
-    mLooping = loop != 0;
-    return OK;
-}
-
-status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
-    if (response == NULL) {
-        ALOGE("reply is a NULL pointer");
-        return BAD_VALUE;
-    }
-
-    RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
-    int32_t methodId = (it++)->int32_value();
-
-    switch (methodId) {
-        case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
-        {
-            int mode = (it++)->int32_value();
-            return mPlayer->setVideoScalingMode(mode);
-        }
-
-        case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
-        {
-            int64_t srcId = (it++)->int64_value();
-            return mPlayer->getTrackInfo(srcId, response);
-        }
-
-        case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
-        {
-            int64_t srcId = (it++)->int64_value();
-            int trackIndex = (it++)->int32_value();
-            int64_t msec = 0;
-            // getCurrentPosition should always return OK
-            getCurrentPosition(&msec);
-            return mPlayer->selectTrack(srcId, trackIndex, true /* select */, msec * 1000LL);
-        }
-
-        case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
-        {
-            int64_t srcId = (it++)->int64_value();
-            int trackIndex = (it++)->int32_value();
-            return mPlayer->selectTrack(
-                    srcId, trackIndex, false /* select */, 0xdeadbeef /* not used */);
-        }
-
-        case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
-        {
-            int64_t srcId = (it++)->int64_value();
-            int32_t type = (it++)->int32_value();
-            return mPlayer->getSelectedTrack(srcId, type, response);
-        }
-
-        default:
-        {
-            return INVALID_OPERATION;
-        }
-    }
-}
-
-void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
-    mPlayer->setAudioSink(audioSink);
-    mAudioSink = audioSink;
-}
-
-status_t NuPlayer2Driver::setParameter(
-        int /* key */, const Parcel & /* request */) {
-    return INVALID_OPERATION;
-}
-
-status_t NuPlayer2Driver::getParameter(int key __unused, Parcel *reply __unused) {
-    return INVALID_OPERATION;
-}
-
-status_t NuPlayer2Driver::getMetrics(char **buffer, size_t *length) {
-    updateMetrics("api");
-    if (mediametrics_getAttributes(mMetricsHandle, buffer, length))
-        return OK;
-    else
-        return FAILED_TRANSACTION;
-}
-
-void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
-    ALOGD("notifyResetComplete(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
-    mState = STATE_IDLE;
-    mCondition.broadcast();
-}
-
-void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
-    ALOGV("notifySetSurfaceComplete(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK(mSetSurfaceInProgress);
-    mSetSurfaceInProgress = false;
-
-    mCondition.broadcast();
-}
-
-void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
-    Mutex::Autolock autoLock(mLock);
-    mDurationUs = durationUs;
-}
-
-void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
-    Mutex::Autolock autoLock(mLock);
-    mPlayingTimeUs += playingUs;
-}
-
-void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
-    Mutex::Autolock autoLock(mLock);
-    mRebufferingTimeUs += rebufferingUs;
-    mRebufferingEvents++;
-}
-
-void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
-    Mutex::Autolock autoLock(mLock);
-    mRebufferingAtExit = status;
-}
-
-void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
-    ALOGV("notifySeekComplete(%p)", this);
-    Mutex::Autolock autoLock(mLock);
-    mSeekInProgress = false;
-    notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
-}
-
-status_t NuPlayer2Driver::dump(
-        int fd, const Vector<String16> & /* args */) const {
-
-    Vector<sp<AMessage> > trackStats;
-    mPlayer->getStats(&trackStats);
-
-    AString logString(" NuPlayer2\n");
-    char buf[256] = {0};
-
-    bool locked = false;
-    for (int i = 0; i < kDumpLockRetries; ++i) {
-        if (mLock.tryLock() == NO_ERROR) {
-            locked = true;
-            break;
-        }
-        usleep(kDumpLockSleepUs);
-    }
-
-    if (locked) {
-        snprintf(buf, sizeof(buf), "  state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
-                mState, mAtEOS, mLooping, mAutoLoop);
-        mLock.unlock();
-    } else {
-        snprintf(buf, sizeof(buf), "  NPD(%p) lock is taken\n", this);
-    }
-    logString.append(buf);
-
-    for (size_t i = 0; i < trackStats.size(); ++i) {
-        const sp<AMessage> &stats = trackStats.itemAt(i);
-
-        AString mime;
-        if (stats->findString("mime", &mime)) {
-            snprintf(buf, sizeof(buf), "  mime(%s)\n", mime.c_str());
-            logString.append(buf);
-        }
-
-        AString name;
-        if (stats->findString("component-name", &name)) {
-            snprintf(buf, sizeof(buf), "    decoder(%s)\n", name.c_str());
-            logString.append(buf);
-        }
-
-        if (mime.startsWith("video/")) {
-            int32_t width, height;
-            if (stats->findInt32("width", &width)
-                    && stats->findInt32("height", &height)) {
-                snprintf(buf, sizeof(buf), "    resolution(%d x %d)\n", width, height);
-                logString.append(buf);
-            }
-
-            int64_t numFramesTotal = 0;
-            int64_t numFramesDropped = 0;
-
-            stats->findInt64("frames-total", &numFramesTotal);
-            stats->findInt64("frames-dropped-output", &numFramesDropped);
-            snprintf(buf, sizeof(buf), "    numFramesTotal(%lld), numFramesDropped(%lld), "
-                     "percentageDropped(%.2f%%)\n",
-                     (long long)numFramesTotal,
-                     (long long)numFramesDropped,
-                     numFramesTotal == 0
-                            ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
-            logString.append(buf);
-        }
-    }
-
-    ALOGI("%s", logString.c_str());
-
-    if (fd >= 0) {
-        FILE *out = fdopen(dup(fd), "w");
-        fprintf(out, "%s", logString.c_str());
-        fclose(out);
-        out = NULL;
-    }
-
-    return OK;
-}
-
-void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatNotifyListener: {
-            int64_t srcId;
-            int32_t msgId;
-            int32_t ext1 = 0;
-            int32_t ext2 = 0;
-            CHECK(msg->findInt64("srcId", &srcId));
-            CHECK(msg->findInt32("messageId", &msgId));
-            msg->findInt32("ext1", &ext1);
-            msg->findInt32("ext2", &ext2);
-            sp<PlayerMessageWrapper> in;
-            sp<RefBase> obj;
-            if (msg->findObject("obj", &obj) && obj != NULL) {
-                in = static_cast<PlayerMessageWrapper *>(obj.get());
-            }
-            sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
-            break;
-        }
-        default:
-            break;
-    }
-}
-
-void NuPlayer2Driver::notifyListener(
-        int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
-    Mutex::Autolock autoLock(mLock);
-    notifyListener_l(srcId, msg, ext1, ext2, in);
-}
-
-void NuPlayer2Driver::notifyListener_l(
-        int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
-    ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
-            this, (long long)srcId, msg, ext1, ext2,
-            (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
-    if (srcId == mSrcId) {
-        switch (msg) {
-            case MEDIA2_PLAYBACK_COMPLETE:
-            {
-                if (mState != STATE_RESET_IN_PROGRESS) {
-                    if (mAutoLoop) {
-                        audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
-                        if (mAudioSink != NULL) {
-                            streamType = mAudioSink->getAudioStreamType();
-                        }
-                        if (streamType == AUDIO_STREAM_NOTIFICATION) {
-                            ALOGW("disabling auto-loop for notification");
-                            mAutoLoop = false;
-                        }
-                    }
-                    if (mLooping || mAutoLoop) {
-                        mPlayer->rewind();
-                        if (mAudioSink != NULL) {
-                            // The renderer has stopped the sink at the end in order to play out
-                            // the last little bit of audio. In looping mode, we need to restart it.
-                            mAudioSink->start();
-                        }
-
-                        sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
-                        notify->setInt64("srcId", srcId);
-                        notify->setInt32("messageId", MEDIA2_INFO);
-                        notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
-                        notify->post();
-                        return;
-                    }
-                    if (property_get_bool("persist.debug.sf.stats", false)) {
-                        Vector<String16> args;
-                        dump(-1, args);
-                    }
-                    mPlayer->pause();
-                    mState = STATE_PAUSED;
-                }
-                FALLTHROUGH_INTENDED;
-            }
-
-            case MEDIA2_ERROR:
-            {
-                // when we have an error, add it to the analytics for this playback.
-                // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
-                // [test against msg is due to fall through from previous switch value]
-                if (msg == MEDIA2_ERROR) {
-                    mediametrics_setInt32(mMetricsHandle, kPlayerError, ext1);
-                    if (ext2 != 0) {
-                        mediametrics_setInt32(mMetricsHandle, kPlayerErrorCode, ext2);
-                    }
-                    mediametrics_setCString(mMetricsHandle, kPlayerErrorState, stateString(mState).c_str());
-                }
-                mAtEOS = true;
-                break;
-            }
-
-            default:
-                break;
-        }
-    }
-
-    sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
-    notify->setInt64("srcId", srcId);
-    notify->setInt32("messageId", msg);
-    notify->setInt32("ext1", ext1);
-    notify->setInt32("ext2", ext2);
-    notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
-    notify->post();
-}
-
-void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
-
-    mAsyncResult = err;
-    mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
-    mCondition.broadcast();
-}
-
-void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
-    ALOGV("notifyPrepareCompleted %d", err);
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (srcId != mSrcId) {
-        if (err == OK) {
-            notifyListener_l(srcId, MEDIA2_PREPARED);
-        } else {
-            notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
-        }
-        return;
-    }
-
-    if (mState != STATE_PREPARING) {
-        // We were preparing asynchronously when the client called
-        // reset(), we sent a premature "prepared" notification and
-        // then initiated the reset. This notification is stale.
-        CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
-        return;
-    }
-
-    CHECK_EQ(mState, STATE_PREPARING);
-
-    mAsyncResult = err;
-
-    if (err == OK) {
-        // update state before notifying client, so that if client calls back into NuPlayer2Driver
-        // in response, NuPlayer2Driver has the right state
-        mState = STATE_PREPARED;
-        notifyListener_l(srcId, MEDIA2_PREPARED);
-    } else {
-        mState = STATE_UNPREPARED;
-        notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
-    }
-
-    sp<MetaData> meta = mPlayer->getFileMeta();
-    int32_t loop;
-    if (meta != NULL
-            && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
-        mAutoLoop = true;
-    }
-
-    mCondition.broadcast();
-}
-
-void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
-    Mutex::Autolock autoLock(mLock);
-
-    mPlayerFlags = flags;
-}
-
-// Modular DRM
-status_t NuPlayer2Driver::prepareDrm(
-        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
-{
-    ALOGV("prepareDrm(%p) state: %d", this, mState);
-
-    // leaving the state verification for mediaplayer.cpp
-    status_t ret = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
-
-    ALOGV("prepareDrm ret: %d", ret);
-
-    return ret;
-}
-
-status_t NuPlayer2Driver::releaseDrm(int64_t srcId)
-{
-    ALOGV("releaseDrm(%p) state: %d", this, mState);
-
-    // leaving the state verification for mediaplayer.cpp
-    status_t ret = mPlayer->releaseDrm(srcId);
-
-    ALOGV("releaseDrm ret: %d", ret);
-
-    return ret;
-}
-
-std::string NuPlayer2Driver::stateString(State state) {
-    const char *rval = NULL;
-    char rawbuffer[16];  // allows "%d"
-
-    switch (state) {
-        case STATE_IDLE: rval = "IDLE"; break;
-        case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
-        case STATE_UNPREPARED: rval = "UNPREPARED"; break;
-        case STATE_PREPARING: rval = "PREPARING"; break;
-        case STATE_PREPARED: rval = "PREPARED"; break;
-        case STATE_RUNNING: rval = "RUNNING"; break;
-        case STATE_PAUSED: rval = "PAUSED"; break;
-        case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
-        default:
-            // yes, this buffer is shared and vulnerable to races
-            snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
-            rval = rawbuffer;
-            break;
-    }
-
-    return rval;
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
deleted file mode 100644
index c97e247..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2017 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 <mediaplayer2/MediaPlayer2Interface.h>
-
-#include <media/MediaMetrics.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediaplayer2/JObjectHolder.h>
-
-namespace android {
-
-struct ALooper;
-struct MediaClock;
-struct NuPlayer2;
-
-struct NuPlayer2Driver : public MediaPlayer2Interface {
-    explicit NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context);
-
-    virtual status_t initCheck() override;
-
-    virtual status_t setDataSource(const sp<DataSourceDesc> &dsd) override;
-    virtual status_t prepareNextDataSource(const sp<DataSourceDesc> &dsd) override;
-    virtual status_t playNextDataSource(int64_t srcId) override;
-
-    virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) override;
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) override;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
-    virtual status_t prepareAsync() override;
-    virtual status_t start() override;
-    virtual status_t pause() override;
-    virtual bool isPlaying() override;
-    virtual status_t setPlaybackSettings(const AudioPlaybackRate &rate) override;
-    virtual status_t getPlaybackSettings(AudioPlaybackRate *rate) override;
-    virtual status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) override;
-    virtual status_t getSyncSettings(AVSyncSettings *sync, float *videoFps) override;
-    virtual status_t seekTo(
-            int64_t msec,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
-    virtual status_t getCurrentPosition(int64_t *msec) override;
-    virtual status_t getDuration(int64_t *msec) override;
-    virtual status_t reset() override;
-    virtual status_t notifyAt(int64_t mediaTimeUs) override;
-    virtual status_t setLooping(int loop) override;
-    virtual status_t invoke(const PlayerMessage &request, PlayerMessage *response) override;
-    virtual void setAudioSink(const sp<AudioSink> &audioSink) override;
-    virtual status_t setParameter(int key, const Parcel &request) override;
-    virtual status_t getParameter(int key, Parcel *reply) override;
-    virtual status_t getMetrics(char **buf, size_t *length) override;
-
-    virtual status_t dump(int fd, const Vector<String16> &args) const override;
-
-    virtual void onMessageReceived(const sp<AMessage> &msg) override;
-
-    void notifySetDataSourceCompleted(int64_t srcId, status_t err);
-    void notifyPrepareCompleted(int64_t srcId, status_t err);
-    void notifyResetComplete(int64_t srcId);
-    void notifySetSurfaceComplete(int64_t srcId);
-    void notifyDuration(int64_t srcId, int64_t durationUs);
-    void notifyMorePlayingTimeUs(int64_t srcId, int64_t timeUs);
-    void notifyMoreRebufferingTimeUs(int64_t srcId, int64_t timeUs);
-    void notifyRebufferingWhenExit(int64_t srcId, bool status);
-    void notifySeekComplete(int64_t srcId);
-    void notifyListener(int64_t srcId, int msg, int ext1 = 0, int ext2 = 0,
-                        const PlayerMessage *in = NULL);
-    void notifyFlagsChanged(int64_t srcId, uint32_t flags);
-
-    // Modular DRM
-    virtual status_t prepareDrm(
-            int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
-    virtual status_t releaseDrm(int64_t srcId);
-
-protected:
-    virtual ~NuPlayer2Driver();
-
-private:
-    enum State {
-        STATE_IDLE,
-        STATE_SET_DATASOURCE_PENDING,
-        STATE_UNPREPARED,
-        STATE_PREPARING,
-        STATE_PREPARED,
-        STATE_RUNNING,
-        STATE_PAUSED,
-        STATE_RESET_IN_PROGRESS,
-    };
-
-    std::string stateString(State state);
-
-    enum {
-        kWhatNotifyListener,
-    };
-
-    mutable Mutex mLock;
-    Condition mCondition;
-
-    State mState;
-
-    status_t mAsyncResult;
-
-    // The following are protected through "mLock"
-    // >>>
-    int64_t mSrcId;
-    bool mSetSurfaceInProgress;
-    int64_t mDurationUs;
-    int64_t mPositionUs;
-    bool mSeekInProgress;
-    int64_t mPlayingTimeUs;
-    int64_t mRebufferingTimeUs;
-    int32_t mRebufferingEvents;
-    bool mRebufferingAtExit;
-    // <<<
-
-    sp<ALooper> mLooper;
-    sp<ALooper> mNuPlayer2Looper;
-    const sp<MediaClock> mMediaClock;
-    const sp<NuPlayer2> mPlayer;
-    sp<AudioSink> mAudioSink;
-    uint32_t mPlayerFlags;
-
-    mediametrics_handle_t mMetricsHandle;
-    int64_t mPlayerVersion;
-    uid_t mClientUid;
-
-    bool mAtEOS;
-    bool mLooping;
-    bool mAutoLoop;
-
-    void updateMetrics(const char *where);
-    void logMetrics(const char *where);
-
-    status_t start_l();
-    void notifyListener_l(int64_t srcId, int msg, int ext1 = 0, int ext2 = 0,
-                          const PlayerMessage *in = NULL);
-
-    DISALLOW_EVIL_CONSTRUCTORS(NuPlayer2Driver);
-};
-
-}  // namespace android
-
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp
deleted file mode 100644
index f41a431..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2017 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 "NuPlayer2Drm"
-
-#include "NuPlayer2Drm.h"
-
-#include <media/NdkWrapper.h>
-#include <utils/Log.h>
-#include <sstream>
-
-namespace android {
-
-Vector<DrmUUID> NuPlayer2Drm::parsePSSH(const void *pssh, size_t psshsize)
-{
-    Vector<DrmUUID> drmSchemes, empty;
-    const int DATALEN_SIZE = 4;
-
-    // the format of the buffer is 1 or more of:
-    //    {
-    //        16 byte uuid
-    //        4 byte data length N
-    //        N bytes of data
-    //    }
-    // Determine the number of entries in the source data.
-    // Since we got the data from stagefright, we trust it is valid and properly formatted.
-
-    const uint8_t *data = (const uint8_t*)pssh;
-    size_t len = psshsize;
-    size_t numentries = 0;
-    while (len > 0) {
-        if (len < DrmUUID::UUID_SIZE) {
-            ALOGE("ParsePSSH: invalid PSSH data");
-            return empty;
-        }
-
-        const uint8_t *uuidPtr = data;
-
-        // skip uuid
-        data += DrmUUID::UUID_SIZE;
-        len -= DrmUUID::UUID_SIZE;
-
-        // get data length
-        if (len < DATALEN_SIZE) {
-            ALOGE("ParsePSSH: invalid PSSH data");
-            return empty;
-        }
-
-        uint32_t datalen = *((uint32_t*)data);
-        data += DATALEN_SIZE;
-        len -= DATALEN_SIZE;
-
-        if (len < datalen) {
-            ALOGE("ParsePSSH: invalid PSSH data");
-            return empty;
-        }
-
-        // skip the data
-        data += datalen;
-        len -= datalen;
-
-        DrmUUID _uuid(uuidPtr);
-        drmSchemes.add(_uuid);
-
-        ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
-                _uuid.toHexString().string(),
-                DrmUUID::arrayToHex(data, datalen).string()
-             );
-
-        numentries++;
-    }
-
-    return drmSchemes;
-}
-
-Vector<DrmUUID> NuPlayer2Drm::getSupportedDrmSchemes(const void *pssh, size_t psshsize)
-{
-    Vector<DrmUUID> psshDRMs = parsePSSH(pssh, psshsize);
-
-    Vector<DrmUUID> supportedDRMs;
-    for (size_t i = 0; i < psshDRMs.size(); i++) {
-        DrmUUID uuid = psshDRMs[i];
-        if (AMediaDrmWrapper::isCryptoSchemeSupported(uuid.ptr(), NULL)) {
-            supportedDRMs.add(uuid);
-        }
-    }
-
-    ALOGV("getSupportedDrmSchemes: psshDRMs: %zu supportedDRMs: %zu",
-            psshDRMs.size(), supportedDRMs.size());
-
-    return supportedDRMs;
-}
-
-sp<ABuffer> NuPlayer2Drm::retrieveDrmInfo(const void *pssh, uint32_t psshsize)
-{
-    std::ostringstream buf;
-
-    // 1) PSSH bytes
-    buf.write(reinterpret_cast<const char *>(&psshsize), sizeof(psshsize));
-    buf.write(reinterpret_cast<const char *>(pssh), psshsize);
-
-    ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  PSSH: size: %u %s", psshsize,
-            DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());
-
-    // 2) supportedDRMs
-    Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
-    uint32_t n = supportedDRMs.size();
-    buf.write(reinterpret_cast<char *>(&n), sizeof(n));
-    for (size_t i = 0; i < n; i++) {
-        DrmUUID uuid = supportedDRMs[i];
-        buf.write(reinterpret_cast<const char *>(&n), sizeof(n));
-        buf.write(reinterpret_cast<const char *>(uuid.ptr()), DrmUUID::UUID_SIZE);
-
-        ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  supportedScheme[%zu] %s", i,
-                uuid.toHexString().string());
-    }
-
-    sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(buf.str().c_str(), buf.tellp());
-    return drmInfoBuffer;
-}
-
-status_t NuPlayer2Drm::retrieveDrmInfo(PsshInfo *psshInfo, PlayerMessage *playerMsg)
-{
-    std::ostringstream pssh, drmInfo;
-
-    // 0) Generate PSSH bytes
-    for (size_t i = 0; i < psshInfo->numentries; i++) {
-        PsshEntry *entry = &psshInfo->entries[i];
-        uint32_t datalen = entry->datalen;
-        pssh.write(reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
-        pssh.write(reinterpret_cast<const char *>(&datalen), sizeof(datalen));
-        pssh.write(reinterpret_cast<const char *>(entry->data), datalen);
-    }
-
-    uint32_t psshSize = pssh.tellp();
-    std::string psshBase = pssh.str();
-    const auto* psshPtr = reinterpret_cast<const uint8_t*>(psshBase.c_str());
-    ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  PSSH: size: %u %s", psshSize,
-            DrmUUID::arrayToHex(psshPtr, psshSize).string());
-
-    // 1) Write PSSH bytes
-    playerMsg->add_values()->set_bytes_value(
-            reinterpret_cast<const char *>(pssh.str().c_str()), psshSize);
-
-    // 2) Write supportedDRMs
-    uint32_t numentries = psshInfo->numentries;
-    playerMsg->add_values()->set_int32_value(numentries);
-    for (size_t i = 0; i < numentries; i++) {
-        PsshEntry *entry = &psshInfo->entries[i];
-        playerMsg->add_values()->set_bytes_value(
-                reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
-        ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  supportedScheme[%zu] %s", i,
-                DrmUUID::arrayToHex((const uint8_t*)&entry->uuid, sizeof(AMediaUUID)).string());
-    }
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.h
deleted file mode 100644
index 968d1be..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_DRM_H_
-#define NUPLAYER2_DRM_H_
-
-#include <media/NdkMediaExtractor.h>
-#include <media/stagefright/foundation/ABuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-
-#include "mediaplayer2.pb.h"
-
-using android::media::MediaPlayer2Proto::PlayerMessage;
-
-namespace android {
-
-    struct DrmUUID {
-        static const int UUID_SIZE = 16;
-
-        DrmUUID() {
-            memset(this->uuid, 0, sizeof(uuid));
-        }
-
-        // to allow defining Vector/KeyedVector of UUID type
-        DrmUUID(const DrmUUID &a) {
-            memcpy(this->uuid, a.uuid, sizeof(uuid));
-        }
-
-        // to allow defining Vector/KeyedVector of UUID type
-        DrmUUID(const uint8_t uuid_in[UUID_SIZE]) {
-            memcpy(this->uuid, uuid_in, sizeof(uuid));
-        }
-
-        const uint8_t *ptr() const {
-            return uuid;
-        }
-
-        String8 toHexString() const {
-            return arrayToHex(uuid, UUID_SIZE);
-        }
-
-        static String8 toHexString(const uint8_t uuid_in[UUID_SIZE]) {
-            return arrayToHex(uuid_in, UUID_SIZE);
-        }
-
-        static String8 arrayToHex(const uint8_t *array, int bytes) {
-            String8 result;
-            for (int i = 0; i < bytes; i++) {
-                result.appendFormat("%02x", array[i]);
-            }
-
-            return result;
-        }
-
-    protected:
-        uint8_t uuid[UUID_SIZE];
-    };
-
-
-    struct NuPlayer2Drm {
-
-        // static helpers - internal
-
-    protected:
-        static Vector<DrmUUID> parsePSSH(const void *pssh, size_t psshsize);
-        static Vector<DrmUUID> getSupportedDrmSchemes(const void *pssh, size_t psshsize);
-
-        // static helpers - public
-
-    public:
-        static sp<ABuffer> retrieveDrmInfo(const void *pssh, uint32_t psshsize);
-        static status_t retrieveDrmInfo(PsshInfo *, PlayerMessage *);
-
-    };  // NuPlayer2Drm
-
-}   // android
-
-#endif     //NUPLAYER2_DRM_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
deleted file mode 100644
index fd459df..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ /dev/null
@@ -1,2096 +0,0 @@
-/*
- * Copyright (C) 2010 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 "NuPlayer2Renderer"
-#include <utils/Log.h>
-
-#include "JWakeLock.h"
-#include "NuPlayer2Renderer.h"
-#include <algorithm>
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/MediaClock.h>
-#include <media/stagefright/MediaCodecConstants.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/VideoFrameScheduler2.h>
-#include <media/MediaCodecBuffer.h>
-
-#include <inttypes.h>
-
-namespace android {
-
-/*
- * Example of common configuration settings in shell script form
-
-   #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
-   adb shell setprop audio.offload.disable 1
-
-   #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
-   adb shell setprop audio.offload.video 1
-
-   #Use audio callbacks for PCM data
-   adb shell setprop media.stagefright.audio.cbk 1
-
-   #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
-   adb shell setprop media.stagefright.audio.deep 1
-
-   #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
-   adb shell setprop media.stagefright.audio.sink 1000
-
- * These configurations take effect for the next track played (not the current track).
- */
-
-static inline bool getUseAudioCallbackSetting() {
-    return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
-}
-
-static inline int32_t getAudioSinkPcmMsSetting() {
-    return property_get_int32(
-            "media.stagefright.audio.sink", 500 /* default_value */);
-}
-
-// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
-// is closed to allow the audio DSP to power down.
-static const int64_t kOffloadPauseMaxUs = 10000000LL;
-
-// Maximum allowed delay from AudioSink, 1.5 seconds.
-static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000LL;
-
-static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
-
-// Default video frame display duration when only video exists.
-// Used to set max media time in MediaClock.
-static const int64_t kDefaultVideoFrameIntervalUs = 100000LL;
-
-// static
-const NuPlayer2::Renderer::PcmInfo NuPlayer2::Renderer::AUDIO_PCMINFO_INITIALIZER = {
-        AUDIO_CHANNEL_NONE,
-        AUDIO_OUTPUT_FLAG_NONE,
-        AUDIO_FORMAT_INVALID,
-        0, // mNumChannels
-        0 // mSampleRate
-};
-
-// static
-const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000LL;
-
-static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
-    switch (pcmEncoding) {
-    case kAudioEncodingPcmFloat:
-        return AUDIO_FORMAT_PCM_FLOAT;
-    case kAudioEncodingPcm16bit:
-        return AUDIO_FORMAT_PCM_16_BIT;
-    case kAudioEncodingPcm8bit:
-        return AUDIO_FORMAT_PCM_8_BIT;  // TODO: do we want to support this?
-    default:
-        ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
-        return AUDIO_FORMAT_INVALID;
-    }
-}
-
-NuPlayer2::Renderer::Renderer(
-        const sp<MediaPlayer2Interface::AudioSink> &sink,
-        const sp<MediaClock> &mediaClock,
-        const sp<AMessage> &notify,
-        const sp<JObjectHolder> &context,
-        uint32_t flags)
-    : mAudioSink(sink),
-      mUseVirtualAudioSink(false),
-      mNotify(notify),
-      mFlags(flags),
-      mNumFramesWritten(0),
-      mDrainAudioQueuePending(false),
-      mDrainVideoQueuePending(false),
-      mAudioQueueGeneration(0),
-      mVideoQueueGeneration(0),
-      mAudioDrainGeneration(0),
-      mVideoDrainGeneration(0),
-      mAudioEOSGeneration(0),
-      mMediaClock(mediaClock),
-      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
-      mAudioFirstAnchorTimeMediaUs(-1),
-      mAnchorTimeMediaUs(-1),
-      mAnchorNumFramesWritten(-1),
-      mVideoLateByUs(0LL),
-      mNextVideoTimeMediaUs(-1),
-      mHasAudio(false),
-      mHasVideo(false),
-      mNotifyCompleteAudio(false),
-      mNotifyCompleteVideo(false),
-      mSyncQueues(false),
-      mPaused(true),
-      mPauseDrainAudioAllowedUs(0),
-      mVideoSampleReceived(false),
-      mVideoRenderingStarted(false),
-      mVideoRenderingStartGeneration(0),
-      mAudioRenderingStartGeneration(0),
-      mRenderingDataDelivered(false),
-      mNextAudioClockUpdateTimeUs(-1),
-      mLastAudioMediaTimeUs(-1),
-      mAudioOffloadPauseTimeoutGeneration(0),
-      mAudioTornDown(false),
-      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
-      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
-      mTotalBuffersQueued(0),
-      mLastAudioBufferDrained(0),
-      mUseAudioCallback(false),
-      mWakeLock(new JWakeLock(context)) {
-    CHECK(mediaClock != NULL);
-    mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
-}
-
-NuPlayer2::Renderer::~Renderer() {
-    if (offloadingAudio()) {
-        mAudioSink->stop();
-        mAudioSink->flush();
-        mAudioSink->close();
-    }
-
-    // Try to avoid racing condition in case callback is still on.
-    Mutex::Autolock autoLock(mLock);
-    if (mUseAudioCallback) {
-        flushQueue(&mAudioQueue);
-        flushQueue(&mVideoQueue);
-    }
-    mWakeLock.clear();
-    mVideoScheduler.clear();
-    mNotify.clear();
-    mAudioSink.clear();
-}
-
-void NuPlayer2::Renderer::queueBuffer(
-        bool audio,
-        const sp<MediaCodecBuffer> &buffer,
-        const sp<AMessage> &notifyConsumed) {
-    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
-    msg->setInt32("queueGeneration", getQueueGeneration(audio));
-    msg->setInt32("audio", static_cast<int32_t>(audio));
-    msg->setObject("buffer", buffer);
-    msg->setMessage("notifyConsumed", notifyConsumed);
-    msg->post();
-}
-
-void NuPlayer2::Renderer::queueEOS(bool audio, status_t finalResult) {
-    CHECK_NE(finalResult, (status_t)OK);
-
-    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
-    msg->setInt32("queueGeneration", getQueueGeneration(audio));
-    msg->setInt32("audio", static_cast<int32_t>(audio));
-    msg->setInt32("finalResult", finalResult);
-    msg->post();
-}
-
-status_t NuPlayer2::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
-    writeToAMessage(msg, rate);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-status_t NuPlayer2::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
-    if (rate.mSpeed <= 0.f) {
-        ALOGW("playback rate cannot be %f", rate.mSpeed);
-        return BAD_VALUE;
-    }
-
-    if (mAudioSink != NULL && mAudioSink->ready()) {
-        status_t err = mAudioSink->setPlaybackRate(rate);
-        if (err != OK) {
-            ALOGW("failed to get playback rate from audio sink, err(%d)", err);
-            return err;
-        }
-    }
-    mPlaybackSettings = rate;
-    mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
-    return OK;
-}
-
-status_t NuPlayer2::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-        if (err == OK) {
-            readFromAMessage(response, rate);
-        }
-    }
-    return err;
-}
-
-status_t NuPlayer2::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    if (mAudioSink != NULL && mAudioSink->ready()) {
-        status_t err = mAudioSink->getPlaybackRate(rate);
-        if (err == OK) {
-            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
-                ALOGW("correcting mismatch in internal/external playback rate, %f vs %f",
-                      rate->mSpeed, mPlaybackSettings.mSpeed);
-            }
-            // get playback settings used by audiosink, as it may be
-            // slightly off due to audiosink not taking small changes.
-            mPlaybackSettings = *rate;
-        }
-        return err;
-    }
-    *rate = mPlaybackSettings;
-    return OK;
-}
-
-status_t NuPlayer2::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
-    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
-    writeToAMessage(msg, sync, videoFpsHint);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-    return err;
-}
-
-status_t NuPlayer2::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
-    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
-        return BAD_VALUE;
-    }
-    // TODO: support sync sources
-    return INVALID_OPERATION;
-}
-
-status_t NuPlayer2::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
-    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-        if (err == OK) {
-            readFromAMessage(response, sync, videoFps);
-        }
-    }
-    return err;
-}
-
-status_t NuPlayer2::Renderer::onGetSyncSettings(
-        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
-    *sync = mSyncSettings;
-    *videoFps = -1.f;
-    return OK;
-}
-
-void NuPlayer2::Renderer::flush(bool audio, bool notifyComplete) {
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (audio) {
-            mNotifyCompleteAudio |= notifyComplete;
-            clearAudioFirstAnchorTime_l();
-            ++mAudioQueueGeneration;
-            ++mAudioDrainGeneration;
-        } else {
-            mNotifyCompleteVideo |= notifyComplete;
-            ++mVideoQueueGeneration;
-            ++mVideoDrainGeneration;
-            mNextVideoTimeMediaUs = -1;
-        }
-
-        mMediaClock->clearAnchor();
-        mVideoLateByUs = 0;
-        mSyncQueues = false;
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatFlush, this);
-    msg->setInt32("audio", static_cast<int32_t>(audio));
-    msg->post();
-}
-
-void NuPlayer2::Renderer::signalTimeDiscontinuity() {
-}
-
-void NuPlayer2::Renderer::signalDisableOffloadAudio() {
-    (new AMessage(kWhatDisableOffloadAudio, this))->post();
-}
-
-void NuPlayer2::Renderer::signalEnableOffloadAudio() {
-    (new AMessage(kWhatEnableOffloadAudio, this))->post();
-}
-
-void NuPlayer2::Renderer::pause() {
-    (new AMessage(kWhatPause, this))->post();
-}
-
-void NuPlayer2::Renderer::resume() {
-    (new AMessage(kWhatResume, this))->post();
-}
-
-void NuPlayer2::Renderer::setVideoFrameRate(float fps) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
-    msg->setFloat("frame-rate", fps);
-    msg->post();
-}
-
-// Called on any threads without mLock acquired.
-status_t NuPlayer2::Renderer::getCurrentPosition(int64_t *mediaUs) {
-    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
-    if (result == OK) {
-        return result;
-    }
-
-    // MediaClock has not started yet. Try to start it if possible.
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (mAudioFirstAnchorTimeMediaUs == -1) {
-            return result;
-        }
-
-        AudioTimestamp ts;
-        status_t res = mAudioSink->getTimestamp(ts);
-        if (res != OK) {
-            return result;
-        }
-
-        // AudioSink has rendered some frames.
-        int64_t nowUs = ALooper::GetNowUs();
-        int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
-                + mAudioFirstAnchorTimeMediaUs;
-        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
-    }
-
-    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
-}
-
-void NuPlayer2::Renderer::clearAudioFirstAnchorTime_l() {
-    mAudioFirstAnchorTimeMediaUs = -1;
-    mMediaClock->setStartingTimeMedia(-1);
-}
-
-void NuPlayer2::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
-    if (mAudioFirstAnchorTimeMediaUs == -1) {
-        mAudioFirstAnchorTimeMediaUs = mediaUs;
-        mMediaClock->setStartingTimeMedia(mediaUs);
-    }
-}
-
-// Called on renderer looper.
-void NuPlayer2::Renderer::clearAnchorTime() {
-    mMediaClock->clearAnchor();
-    mAnchorTimeMediaUs = -1;
-    mAnchorNumFramesWritten = -1;
-}
-
-void NuPlayer2::Renderer::setVideoLateByUs(int64_t lateUs) {
-    Mutex::Autolock autoLock(mLock);
-    mVideoLateByUs = lateUs;
-}
-
-int64_t NuPlayer2::Renderer::getVideoLateByUs() {
-    Mutex::Autolock autoLock(mLock);
-    return mVideoLateByUs;
-}
-
-status_t NuPlayer2::Renderer::openAudioSink(
-        const sp<AMessage> &format,
-        bool offloadOnly,
-        bool hasVideo,
-        uint32_t flags,
-        bool *isOffloaded,
-        bool isStreaming) {
-    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
-    msg->setMessage("format", format);
-    msg->setInt32("offload-only", offloadOnly);
-    msg->setInt32("has-video", hasVideo);
-    msg->setInt32("flags", flags);
-    msg->setInt32("isStreaming", isStreaming);
-
-    sp<AMessage> response;
-    status_t postStatus = msg->postAndAwaitResponse(&response);
-
-    int32_t err;
-    if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
-        err = INVALID_OPERATION;
-    } else if (err == OK && isOffloaded != NULL) {
-        int32_t offload;
-        CHECK(response->findInt32("offload", &offload));
-        *isOffloaded = (offload != 0);
-    }
-    return err;
-}
-
-void NuPlayer2::Renderer::closeAudioSink() {
-    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
-
-    sp<AMessage> response;
-    msg->postAndAwaitResponse(&response);
-}
-
-void NuPlayer2::Renderer::changeAudioFormat(
-        const sp<AMessage> &format,
-        bool offloadOnly,
-        bool hasVideo,
-        uint32_t flags,
-        bool isStreaming,
-        const sp<AMessage> &notify) {
-    sp<AMessage> meta = new AMessage;
-    meta->setMessage("format", format);
-    meta->setInt32("offload-only", offloadOnly);
-    meta->setInt32("has-video", hasVideo);
-    meta->setInt32("flags", flags);
-    meta->setInt32("isStreaming", isStreaming);
-
-    sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
-    msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
-    msg->setMessage("notify", notify);
-    msg->setMessage("meta", meta);
-    msg->post();
-}
-
-void NuPlayer2::Renderer::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatOpenAudioSink:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-
-            int32_t offloadOnly;
-            CHECK(msg->findInt32("offload-only", &offloadOnly));
-
-            int32_t hasVideo;
-            CHECK(msg->findInt32("has-video", &hasVideo));
-
-            uint32_t flags;
-            CHECK(msg->findInt32("flags", (int32_t *)&flags));
-
-            uint32_t isStreaming;
-            CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
-
-            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
-
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->setInt32("offload", offloadingAudio());
-
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            response->postReply(replyID);
-
-            break;
-        }
-
-        case kWhatCloseAudioSink:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            onCloseAudioSink();
-
-            sp<AMessage> response = new AMessage;
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatStopAudioSink:
-        {
-            mAudioSink->stop();
-            break;
-        }
-
-        case kWhatChangeAudioFormat:
-        {
-            int32_t queueGeneration;
-            CHECK(msg->findInt32("queueGeneration", &queueGeneration));
-
-            sp<AMessage> notify;
-            CHECK(msg->findMessage("notify", &notify));
-
-            if (offloadingAudio()) {
-                ALOGW("changeAudioFormat should NOT be called in offload mode");
-                notify->setInt32("err", INVALID_OPERATION);
-                notify->post();
-                break;
-            }
-
-            sp<AMessage> meta;
-            CHECK(msg->findMessage("meta", &meta));
-
-            if (queueGeneration != getQueueGeneration(true /* audio */)
-                    || mAudioQueue.empty()) {
-                onChangeAudioFormat(meta, notify);
-                break;
-            }
-
-            QueueEntry entry;
-            entry.mNotifyConsumed = notify;
-            entry.mMeta = meta;
-
-            Mutex::Autolock autoLock(mLock);
-            mAudioQueue.push_back(entry);
-            postDrainAudioQueue_l();
-
-            break;
-        }
-
-        case kWhatDrainAudioQueue:
-        {
-            mDrainAudioQueuePending = false;
-
-            int32_t generation;
-            CHECK(msg->findInt32("drainGeneration", &generation));
-            if (generation != getDrainGeneration(true /* audio */)) {
-                break;
-            }
-
-            if (onDrainAudioQueue()) {
-                uint32_t numFramesPlayed;
-                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
-                         (status_t)OK);
-
-                // Handle AudioTrack race when start is immediately called after flush.
-                uint32_t numFramesPendingPlayout =
-                    (mNumFramesWritten > numFramesPlayed ?
-                        mNumFramesWritten - numFramesPlayed : 0);
-
-                // This is how long the audio sink will have data to
-                // play back.
-                int64_t delayUs =
-                    mAudioSink->msecsPerFrame()
-                        * numFramesPendingPlayout * 1000ll;
-                if (mPlaybackSettings.mSpeed > 1.0f) {
-                    delayUs /= mPlaybackSettings.mSpeed;
-                }
-
-                // Let's give it more data after about half that time
-                // has elapsed.
-                delayUs /= 2;
-                // check the buffer size to estimate maximum delay permitted.
-                const int64_t maxDrainDelayUs = std::max(
-                        mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
-                ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
-                        (long long)delayUs, (long long)maxDrainDelayUs);
-                Mutex::Autolock autoLock(mLock);
-                postDrainAudioQueue_l(delayUs);
-            }
-            break;
-        }
-
-        case kWhatDrainVideoQueue:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("drainGeneration", &generation));
-            if (generation != getDrainGeneration(false /* audio */)) {
-                break;
-            }
-
-            mDrainVideoQueuePending = false;
-
-            onDrainVideoQueue();
-
-            postDrainVideoQueue();
-            break;
-        }
-
-        case kWhatPostDrainVideoQueue:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("drainGeneration", &generation));
-            if (generation != getDrainGeneration(false /* audio */)) {
-                break;
-            }
-
-            mDrainVideoQueuePending = false;
-            postDrainVideoQueue();
-            break;
-        }
-
-        case kWhatQueueBuffer:
-        {
-            onQueueBuffer(msg);
-            break;
-        }
-
-        case kWhatQueueEOS:
-        {
-            onQueueEOS(msg);
-            break;
-        }
-
-        case kWhatEOS:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("audioEOSGeneration", &generation));
-            if (generation != mAudioEOSGeneration) {
-                break;
-            }
-            status_t finalResult;
-            CHECK(msg->findInt32("finalResult", &finalResult));
-            notifyEOS(true /* audio */, finalResult);
-            break;
-        }
-
-        case kWhatConfigPlayback:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AudioPlaybackRate rate;
-            readFromAMessage(msg, &rate);
-            status_t err = onConfigPlayback(rate);
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatGetPlaybackSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
-            status_t err = onGetPlaybackSettings(&rate);
-            sp<AMessage> response = new AMessage;
-            if (err == OK) {
-                writeToAMessage(response, rate);
-            }
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatConfigSync:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-            AVSyncSettings sync;
-            float videoFpsHint;
-            readFromAMessage(msg, &sync, &videoFpsHint);
-            status_t err = onConfigSync(sync, videoFpsHint);
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatGetSyncSettings:
-        {
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            ALOGV("kWhatGetSyncSettings");
-            AVSyncSettings sync;
-            float videoFps = -1.f;
-            status_t err = onGetSyncSettings(&sync, &videoFps);
-            sp<AMessage> response = new AMessage;
-            if (err == OK) {
-                writeToAMessage(response, sync, videoFps);
-            }
-            response->setInt32("err", err);
-            response->postReply(replyID);
-            break;
-        }
-
-        case kWhatFlush:
-        {
-            onFlush(msg);
-            break;
-        }
-
-        case kWhatDisableOffloadAudio:
-        {
-            onDisableOffloadAudio();
-            break;
-        }
-
-        case kWhatEnableOffloadAudio:
-        {
-            onEnableOffloadAudio();
-            break;
-        }
-
-        case kWhatPause:
-        {
-            onPause();
-            break;
-        }
-
-        case kWhatResume:
-        {
-            onResume();
-            break;
-        }
-
-        case kWhatSetVideoFrameRate:
-        {
-            float fps;
-            CHECK(msg->findFloat("frame-rate", &fps));
-            onSetVideoFrameRate(fps);
-            break;
-        }
-
-        case kWhatAudioTearDown:
-        {
-            int32_t reason;
-            CHECK(msg->findInt32("reason", &reason));
-
-            onAudioTearDown((AudioTearDownReason)reason);
-            break;
-        }
-
-        case kWhatAudioOffloadPauseTimeout:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("drainGeneration", &generation));
-            if (generation != mAudioOffloadPauseTimeoutGeneration) {
-                break;
-            }
-            ALOGV("Audio Offload tear down due to pause timeout.");
-            onAudioTearDown(kDueToTimeout);
-            mWakeLock->release();
-            break;
-        }
-
-        default:
-            TRESPASS();
-            break;
-    }
-}
-
-void NuPlayer2::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
-    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
-        return;
-    }
-
-    if (mAudioQueue.empty()) {
-        return;
-    }
-
-    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
-    if (mPaused) {
-        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
-        if (diffUs > delayUs) {
-            delayUs = diffUs;
-        }
-    }
-
-    mDrainAudioQueuePending = true;
-    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
-    msg->setInt32("drainGeneration", mAudioDrainGeneration);
-    msg->post(delayUs);
-}
-
-void NuPlayer2::Renderer::prepareForMediaRenderingStart_l() {
-    mAudioRenderingStartGeneration = mAudioDrainGeneration;
-    mVideoRenderingStartGeneration = mVideoDrainGeneration;
-    mRenderingDataDelivered = false;
-}
-
-void NuPlayer2::Renderer::notifyIfMediaRenderingStarted_l() {
-    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
-        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
-        mRenderingDataDelivered = true;
-        if (mPaused) {
-            return;
-        }
-        mVideoRenderingStartGeneration = -1;
-        mAudioRenderingStartGeneration = -1;
-
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatMediaRenderingStart);
-        notify->post();
-    }
-}
-
-// static
-size_t NuPlayer2::Renderer::AudioSinkCallback(
-        MediaPlayer2Interface::AudioSink * /* audioSink */,
-        void *buffer,
-        size_t size,
-        void *cookie,
-        MediaPlayer2Interface::AudioSink::cb_event_t event) {
-    NuPlayer2::Renderer *me = (NuPlayer2::Renderer *)cookie;
-
-    switch (event) {
-        case MediaPlayer2Interface::AudioSink::CB_EVENT_FILL_BUFFER:
-        {
-            return me->fillAudioBuffer(buffer, size);
-            break;
-        }
-
-        case MediaPlayer2Interface::AudioSink::CB_EVENT_STREAM_END:
-        {
-            ALOGV("AudioSink::CB_EVENT_STREAM_END");
-            me->notifyEOSCallback();
-            break;
-        }
-
-        case MediaPlayer2Interface::AudioSink::CB_EVENT_TEAR_DOWN:
-        {
-            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
-            me->notifyAudioTearDown(kDueToError);
-            break;
-        }
-    }
-
-    return 0;
-}
-
-void NuPlayer2::Renderer::notifyEOSCallback() {
-    Mutex::Autolock autoLock(mLock);
-
-    if (!mUseAudioCallback) {
-        return;
-    }
-
-    notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
-}
-
-size_t NuPlayer2::Renderer::fillAudioBuffer(void *buffer, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (!mUseAudioCallback) {
-        return 0;
-    }
-
-    bool hasEOS = false;
-
-    size_t sizeCopied = 0;
-    bool firstEntry = true;
-    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
-    while (sizeCopied < size && !mAudioQueue.empty()) {
-        entry = &*mAudioQueue.begin();
-
-        if (entry->mBuffer == NULL) { // EOS
-            hasEOS = true;
-            mAudioQueue.erase(mAudioQueue.begin());
-            break;
-        }
-
-        if (firstEntry && entry->mOffset == 0) {
-            firstEntry = false;
-            int64_t mediaTimeUs;
-            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
-            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
-            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
-        }
-
-        size_t copy = entry->mBuffer->size() - entry->mOffset;
-        size_t sizeRemaining = size - sizeCopied;
-        if (copy > sizeRemaining) {
-            copy = sizeRemaining;
-        }
-
-        memcpy((char *)buffer + sizeCopied,
-               entry->mBuffer->data() + entry->mOffset,
-               copy);
-
-        entry->mOffset += copy;
-        if (entry->mOffset == entry->mBuffer->size()) {
-            entry->mNotifyConsumed->post();
-            mAudioQueue.erase(mAudioQueue.begin());
-            entry = NULL;
-        }
-        sizeCopied += copy;
-
-        notifyIfMediaRenderingStarted_l();
-    }
-
-    if (mAudioFirstAnchorTimeMediaUs >= 0) {
-        int64_t nowUs = ALooper::GetNowUs();
-        int64_t nowMediaUs =
-            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
-        // we don't know how much data we are queueing for offloaded tracks.
-        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
-    }
-
-    // for non-offloaded audio, we need to compute the frames written because
-    // there is no EVENT_STREAM_END notification. The frames written gives
-    // an estimate on the pending played out duration.
-    if (!offloadingAudio()) {
-        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
-    }
-
-    if (hasEOS) {
-        (new AMessage(kWhatStopAudioSink, this))->post();
-        // As there is currently no EVENT_STREAM_END callback notification for
-        // non-offloaded audio tracks, we need to post the EOS ourselves.
-        if (!offloadingAudio()) {
-            int64_t postEOSDelayUs = 0;
-            if (mAudioSink->needsTrailingPadding()) {
-                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
-            }
-            ALOGV("fillAudioBuffer: notifyEOS_l "
-                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
-                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
-            notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
-        }
-    }
-    return sizeCopied;
-}
-
-void NuPlayer2::Renderer::drainAudioQueueUntilLastEOS() {
-    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
-    bool foundEOS = false;
-    while (it != mAudioQueue.end()) {
-        int32_t eos;
-        QueueEntry *entry = &*it++;
-        if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
-                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
-            itEOS = it;
-            foundEOS = true;
-        }
-    }
-
-    if (foundEOS) {
-        // post all replies before EOS and drop the samples
-        for (it = mAudioQueue.begin(); it != itEOS; it++) {
-            if (it->mBuffer == nullptr) {
-                if (it->mNotifyConsumed == nullptr) {
-                    // delay doesn't matter as we don't even have an AudioTrack
-                    notifyEOS(true /* audio */, it->mFinalResult);
-                } else {
-                    // TAG for re-opening audio sink.
-                    onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
-                }
-            } else {
-                it->mNotifyConsumed->post();
-            }
-        }
-        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
-    }
-}
-
-bool NuPlayer2::Renderer::onDrainAudioQueue() {
-    // do not drain audio during teardown as queued buffers may be invalid.
-    if (mAudioTornDown) {
-        return false;
-    }
-    // TODO: This call to getPosition checks if AudioTrack has been created
-    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
-    // CHECKs on getPosition will fail.
-    // We still need to figure out why AudioTrack is not created when
-    // this function is called. One possible reason could be leftover
-    // audio. Another possible place is to check whether decoder
-    // has received INFO_FORMAT_CHANGED as the first buffer since
-    // AudioSink is opened there, and possible interactions with flush
-    // immediately after start. Investigate error message
-    // "vorbis_dsp_synthesis returned -135", along with RTSP.
-    uint32_t numFramesPlayed;
-    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
-        // When getPosition fails, renderer will not reschedule the draining
-        // unless new samples are queued.
-        // If we have pending EOS (or "eos" marker for discontinuities), we need
-        // to post these now as NuPlayer2Decoder might be waiting for it.
-        drainAudioQueueUntilLastEOS();
-
-        ALOGW("onDrainAudioQueue(): audio sink is not ready");
-        return false;
-    }
-
-#if 0
-    ssize_t numFramesAvailableToWrite =
-        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
-
-    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
-        ALOGI("audio sink underrun");
-    } else {
-        ALOGV("audio queue has %d frames left to play",
-             mAudioSink->frameCount() - numFramesAvailableToWrite);
-    }
-#endif
-
-    uint32_t prevFramesWritten = mNumFramesWritten;
-    while (!mAudioQueue.empty()) {
-        QueueEntry *entry = &*mAudioQueue.begin();
-
-        if (entry->mBuffer == NULL) {
-            if (entry->mNotifyConsumed != nullptr) {
-                // TAG for re-open audio sink.
-                onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
-                mAudioQueue.erase(mAudioQueue.begin());
-                continue;
-            }
-
-            // EOS
-            if (mPaused) {
-                // Do not notify EOS when paused.
-                // This is needed to avoid switch to next clip while in pause.
-                ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
-                return false;
-            }
-
-            int64_t postEOSDelayUs = 0;
-            if (mAudioSink->needsTrailingPadding()) {
-                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
-            }
-            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
-            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
-
-            mAudioQueue.erase(mAudioQueue.begin());
-            entry = NULL;
-            if (mAudioSink->needsTrailingPadding()) {
-                // If we're not in gapless playback (i.e. through setNextPlayer), we
-                // need to stop the track here, because that will play out the last
-                // little bit at the end of the file. Otherwise short files won't play.
-                mAudioSink->stop();
-                mNumFramesWritten = 0;
-            }
-            return false;
-        }
-
-        mLastAudioBufferDrained = entry->mBufferOrdinal;
-
-        // ignore 0-sized buffer which could be EOS marker with no data
-        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
-            int64_t mediaTimeUs;
-            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
-            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
-                    mediaTimeUs / 1E6);
-            onNewAudioMediaTime(mediaTimeUs);
-        }
-
-        size_t copy = entry->mBuffer->size() - entry->mOffset;
-
-        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
-                                            copy, false /* blocking */);
-        if (written < 0) {
-            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
-            if (written == WOULD_BLOCK) {
-                ALOGV("AudioSink write would block when writing %zu bytes", copy);
-            } else {
-                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
-                // This can only happen when AudioSink was opened with doNotReconnect flag set to
-                // true, in which case the NuPlayer2 will handle the reconnect.
-                notifyAudioTearDown(kDueToError);
-            }
-            break;
-        }
-
-        entry->mOffset += written;
-        size_t remainder = entry->mBuffer->size() - entry->mOffset;
-        if ((ssize_t)remainder < mAudioSink->frameSize()) {
-            if (remainder > 0) {
-                ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
-                        remainder);
-                entry->mOffset += remainder;
-                copy -= remainder;
-            }
-
-            entry->mNotifyConsumed->post();
-            mAudioQueue.erase(mAudioQueue.begin());
-
-            entry = NULL;
-        }
-
-        size_t copiedFrames = written / mAudioSink->frameSize();
-        mNumFramesWritten += copiedFrames;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-            int64_t maxTimeMedia;
-            maxTimeMedia =
-                mAnchorTimeMediaUs +
-                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
-                                * 1000LL * mAudioSink->msecsPerFrame());
-            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
-
-            notifyIfMediaRenderingStarted_l();
-        }
-
-        if (written != (ssize_t)copy) {
-            // A short count was received from AudioSink::write()
-            //
-            // AudioSink write is called in non-blocking mode.
-            // It may return with a short count when:
-            //
-            // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
-            //    discarded.
-            // 2) The data to be copied exceeds the available buffer in AudioSink.
-            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
-            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
-
-            // (Case 1)
-            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
-            // needs to fail, as we should not carry over fractional frames between calls.
-            CHECK_EQ(copy % mAudioSink->frameSize(), 0u);
-
-            // (Case 2, 3, 4)
-            // Return early to the caller.
-            // Beware of calling immediately again as this may busy-loop if you are not careful.
-            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
-            break;
-        }
-    }
-
-    // calculate whether we need to reschedule another write.
-    bool reschedule = !mAudioQueue.empty()
-            && (!mPaused
-                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
-    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
-    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
-    return reschedule;
-}
-
-int64_t NuPlayer2::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
-    int32_t sampleRate = offloadingAudio() ?
-            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
-    if (sampleRate == 0) {
-        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
-        return 0;
-    }
-    return (int64_t)(numFrames * 1000000LL / sampleRate);
-}
-
-// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
-int64_t NuPlayer2::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
-    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
-    if (mUseVirtualAudioSink) {
-        int64_t nowUs = ALooper::GetNowUs();
-        int64_t mediaUs;
-        if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
-            return 0LL;
-        } else {
-            return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
-        }
-    }
-
-    const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
-    int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
-    if (pendingUs < 0) {
-        // This shouldn't happen unless the timestamp is stale.
-        ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
-                "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
-                __func__, (long long)pendingUs,
-                (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
-        pendingUs = 0;
-    }
-    return pendingUs;
-}
-
-int64_t NuPlayer2::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
-    int64_t realUs;
-    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
-        // If failed to get current position, e.g. due to audio clock is
-        // not ready, then just play out video immediately without delay.
-        return nowUs;
-    }
-    return realUs;
-}
-
-void NuPlayer2::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
-    Mutex::Autolock autoLock(mLock);
-    // TRICKY: vorbis decoder generates multiple frames with the same
-    // timestamp, so only update on the first frame with a given timestamp
-    if (mediaTimeUs == mAnchorTimeMediaUs) {
-        return;
-    }
-    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
-
-    // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
-    if (mNextAudioClockUpdateTimeUs == -1) {
-        AudioTimestamp ts;
-        if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
-            mNextAudioClockUpdateTimeUs = 0; // start our clock updates
-        }
-    }
-    int64_t nowUs = ALooper::GetNowUs();
-    if (mNextAudioClockUpdateTimeUs >= 0) {
-        if (nowUs >= mNextAudioClockUpdateTimeUs) {
-            int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
-            mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
-            mUseVirtualAudioSink = false;
-            mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
-        }
-    } else {
-        int64_t unused;
-        if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
-                && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
-                        > kMaxAllowedAudioSinkDelayUs)) {
-            // Enough data has been sent to AudioSink, but AudioSink has not rendered
-            // any data yet. Something is wrong with AudioSink, e.g., the device is not
-            // connected to audio out.
-            // Switch to system clock. This essentially creates a virtual AudioSink with
-            // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
-            // This virtual AudioSink renders audio data starting from the very first sample
-            // and it's paced by system clock.
-            ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
-            mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
-            mUseVirtualAudioSink = true;
-        }
-    }
-    mAnchorNumFramesWritten = mNumFramesWritten;
-    mAnchorTimeMediaUs = mediaTimeUs;
-}
-
-// Called without mLock acquired.
-void NuPlayer2::Renderer::postDrainVideoQueue() {
-    if (mDrainVideoQueuePending
-            || getSyncQueues()
-            || (mPaused && mVideoSampleReceived)) {
-        return;
-    }
-
-    if (mVideoQueue.empty()) {
-        return;
-    }
-
-    QueueEntry &entry = *mVideoQueue.begin();
-
-    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
-    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
-
-    if (entry.mBuffer == NULL) {
-        // EOS doesn't carry a timestamp.
-        msg->post();
-        mDrainVideoQueuePending = true;
-        return;
-    }
-
-    int64_t nowUs = ALooper::GetNowUs();
-    if (mFlags & FLAG_REAL_TIME) {
-        int64_t realTimeUs;
-        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &realTimeUs));
-
-        realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
-
-        int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
-
-        int64_t delayUs = realTimeUs - nowUs;
-
-        ALOGW_IF(delayUs > 500000, "unusually high delayUs: %lld", (long long)delayUs);
-        // post 2 display refreshes before rendering is due
-        msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
-
-        mDrainVideoQueuePending = true;
-        return;
-    }
-
-    int64_t mediaTimeUs;
-    CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (mAnchorTimeMediaUs < 0) {
-            mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
-            mAnchorTimeMediaUs = mediaTimeUs;
-        }
-    }
-    mNextVideoTimeMediaUs = mediaTimeUs;
-    if (!mHasAudio) {
-        // smooth out videos >= 10fps
-        mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
-    }
-
-    if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
-        msg->post();
-    } else {
-        int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
-
-        // post 2 display refreshes before rendering is due
-        mMediaClock->addTimer(msg, mediaTimeUs, -twoVsyncsUs);
-    }
-
-    mDrainVideoQueuePending = true;
-}
-
-void NuPlayer2::Renderer::onDrainVideoQueue() {
-    if (mVideoQueue.empty()) {
-        return;
-    }
-
-    QueueEntry *entry = &*mVideoQueue.begin();
-
-    if (entry->mBuffer == NULL) {
-        // EOS
-
-        notifyEOS(false /* audio */, entry->mFinalResult);
-
-        mVideoQueue.erase(mVideoQueue.begin());
-        entry = NULL;
-
-        setVideoLateByUs(0);
-        return;
-    }
-
-    int64_t nowUs = ALooper::GetNowUs();
-    int64_t realTimeUs;
-    int64_t mediaTimeUs = -1;
-    if (mFlags & FLAG_REAL_TIME) {
-        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
-    } else {
-        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
-
-        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
-    }
-    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
-
-    bool tooLate = false;
-
-    if (!mPaused) {
-        setVideoLateByUs(nowUs - realTimeUs);
-        tooLate = (mVideoLateByUs > 40000);
-
-        if (tooLate) {
-            ALOGV("video late by %lld us (%.2f secs)",
-                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
-        } else {
-            int64_t mediaUs = 0;
-            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
-            ALOGV("rendering video at media time %.2f secs",
-                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
-                    mediaUs) / 1E6);
-
-            if (!(mFlags & FLAG_REAL_TIME)
-                    && mLastAudioMediaTimeUs != -1
-                    && mediaTimeUs > mLastAudioMediaTimeUs) {
-                // If audio ends before video, video continues to drive media clock.
-                // Also smooth out videos >= 10fps.
-                mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
-            }
-        }
-    } else {
-        setVideoLateByUs(0);
-        if (!mVideoSampleReceived && !mHasAudio) {
-            // This will ensure that the first frame after a flush won't be used as anchor
-            // when renderer is in paused state, because resume can happen any time after seek.
-            clearAnchorTime();
-        }
-    }
-
-    // Always render the first video frame while keeping stats on A/V sync.
-    if (!mVideoSampleReceived) {
-        realTimeUs = nowUs;
-        tooLate = false;
-    }
-
-    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
-    entry->mNotifyConsumed->setInt32("render", !tooLate);
-    entry->mNotifyConsumed->post();
-    mVideoQueue.erase(mVideoQueue.begin());
-    entry = NULL;
-
-    mVideoSampleReceived = true;
-
-    if (!mPaused) {
-        if (!mVideoRenderingStarted) {
-            mVideoRenderingStarted = true;
-            notifyVideoRenderingStart();
-        }
-        Mutex::Autolock autoLock(mLock);
-        notifyIfMediaRenderingStarted_l();
-    }
-}
-
-void NuPlayer2::Renderer::notifyVideoRenderingStart() {
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatVideoRenderingStart);
-    notify->post();
-}
-
-void NuPlayer2::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
-    Mutex::Autolock autoLock(mLock);
-    notifyEOS_l(audio, finalResult, delayUs);
-}
-
-void NuPlayer2::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
-    if (audio && delayUs > 0) {
-        sp<AMessage> msg = new AMessage(kWhatEOS, this);
-        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
-        msg->setInt32("finalResult", finalResult);
-        msg->post(delayUs);
-        return;
-    }
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatEOS);
-    notify->setInt32("audio", static_cast<int32_t>(audio));
-    notify->setInt32("finalResult", finalResult);
-    notify->post(delayUs);
-
-    if (audio) {
-        // Video might outlive audio. Clear anchor to enable video only case.
-        mAnchorTimeMediaUs = -1;
-        mHasAudio = false;
-        if (mNextVideoTimeMediaUs >= 0) {
-            int64_t mediaUs = 0;
-            int64_t nowUs = ALooper::GetNowUs();
-            status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
-            if (result == OK) {
-                if (mNextVideoTimeMediaUs > mediaUs) {
-                    mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
-                }
-            } else {
-                mMediaClock->updateAnchor(
-                        mNextVideoTimeMediaUs, nowUs,
-                        mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
-            }
-        }
-    }
-}
-
-void NuPlayer2::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
-    sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
-    msg->setInt32("reason", reason);
-    msg->post();
-}
-
-void NuPlayer2::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
-    int32_t audio;
-    CHECK(msg->findInt32("audio", &audio));
-
-    if (dropBufferIfStale(audio, msg)) {
-        return;
-    }
-
-    if (audio) {
-        mHasAudio = true;
-    } else {
-        mHasVideo = true;
-    }
-
-    if (mHasVideo) {
-        if (mVideoScheduler == NULL) {
-            mVideoScheduler = new VideoFrameScheduler2();
-            mVideoScheduler->init();
-        }
-    }
-
-    sp<RefBase> obj;
-    CHECK(msg->findObject("buffer", &obj));
-    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
-
-    sp<AMessage> notifyConsumed;
-    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
-
-    QueueEntry entry;
-    entry.mBuffer = buffer;
-    entry.mNotifyConsumed = notifyConsumed;
-    entry.mOffset = 0;
-    entry.mFinalResult = OK;
-    entry.mBufferOrdinal = ++mTotalBuffersQueued;
-
-    if (audio) {
-        Mutex::Autolock autoLock(mLock);
-        mAudioQueue.push_back(entry);
-        postDrainAudioQueue_l();
-    } else {
-        mVideoQueue.push_back(entry);
-        postDrainVideoQueue();
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
-        return;
-    }
-
-    sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
-    sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
-
-    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
-        // EOS signalled on either queue.
-        syncQueuesDone_l();
-        return;
-    }
-
-    int64_t firstAudioTimeUs;
-    int64_t firstVideoTimeUs;
-    CHECK(firstAudioBuffer->meta()
-            ->findInt64("timeUs", &firstAudioTimeUs));
-    CHECK(firstVideoBuffer->meta()
-            ->findInt64("timeUs", &firstVideoTimeUs));
-
-    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
-
-    ALOGV("queueDiff = %.2f secs", diff / 1E6);
-
-    if (diff > 100000LL) {
-        // Audio data starts More than 0.1 secs before video.
-        // Drop some audio.
-
-        (*mAudioQueue.begin()).mNotifyConsumed->post();
-        mAudioQueue.erase(mAudioQueue.begin());
-        return;
-    }
-
-    syncQueuesDone_l();
-}
-
-void NuPlayer2::Renderer::syncQueuesDone_l() {
-    if (!mSyncQueues) {
-        return;
-    }
-
-    mSyncQueues = false;
-
-    if (!mAudioQueue.empty()) {
-        postDrainAudioQueue_l();
-    }
-
-    if (!mVideoQueue.empty()) {
-        mLock.unlock();
-        postDrainVideoQueue();
-        mLock.lock();
-    }
-}
-
-void NuPlayer2::Renderer::onQueueEOS(const sp<AMessage> &msg) {
-    int32_t audio;
-    CHECK(msg->findInt32("audio", &audio));
-
-    if (dropBufferIfStale(audio, msg)) {
-        return;
-    }
-
-    int32_t finalResult;
-    CHECK(msg->findInt32("finalResult", &finalResult));
-
-    QueueEntry entry;
-    entry.mOffset = 0;
-    entry.mFinalResult = finalResult;
-
-    if (audio) {
-        Mutex::Autolock autoLock(mLock);
-        if (mAudioQueue.empty() && mSyncQueues) {
-            syncQueuesDone_l();
-        }
-        mAudioQueue.push_back(entry);
-        postDrainAudioQueue_l();
-    } else {
-        if (mVideoQueue.empty() && getSyncQueues()) {
-            Mutex::Autolock autoLock(mLock);
-            syncQueuesDone_l();
-        }
-        mVideoQueue.push_back(entry);
-        postDrainVideoQueue();
-    }
-}
-
-void NuPlayer2::Renderer::onFlush(const sp<AMessage> &msg) {
-    int32_t audio, notifyComplete;
-    CHECK(msg->findInt32("audio", &audio));
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        if (audio) {
-            notifyComplete = mNotifyCompleteAudio;
-            mNotifyCompleteAudio = false;
-            mLastAudioMediaTimeUs = -1;
-
-            mHasAudio = false;
-            if (mNextVideoTimeMediaUs >= 0) {
-                int64_t nowUs = ALooper::GetNowUs();
-                mMediaClock->updateAnchor(
-                        mNextVideoTimeMediaUs, nowUs,
-                        mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
-            }
-        } else {
-            notifyComplete = mNotifyCompleteVideo;
-            mNotifyCompleteVideo = false;
-            mVideoRenderingStarted = false;
-        }
-
-        // If we're currently syncing the queues, i.e. dropping audio while
-        // aligning the first audio/video buffer times and only one of the
-        // two queues has data, we may starve that queue by not requesting
-        // more buffers from the decoder. If the other source then encounters
-        // a discontinuity that leads to flushing, we'll never find the
-        // corresponding discontinuity on the other queue.
-        // Therefore we'll stop syncing the queues if at least one of them
-        // is flushed.
-        syncQueuesDone_l();
-    }
-    clearAnchorTime();
-
-    ALOGV("flushing %s", audio ? "audio" : "video");
-    if (audio) {
-        {
-            Mutex::Autolock autoLock(mLock);
-            flushQueue(&mAudioQueue);
-
-            ++mAudioDrainGeneration;
-            ++mAudioEOSGeneration;
-            prepareForMediaRenderingStart_l();
-
-            // the frame count will be reset after flush.
-            clearAudioFirstAnchorTime_l();
-        }
-
-        mDrainAudioQueuePending = false;
-
-        if (offloadingAudio()) {
-            mAudioSink->pause();
-            mAudioSink->flush();
-            if (!mPaused) {
-                mAudioSink->start();
-            }
-        } else {
-            mAudioSink->pause();
-            mAudioSink->flush();
-            // Call stop() to signal to the AudioSink to completely fill the
-            // internal buffer before resuming playback.
-            // FIXME: this is ignored after flush().
-            mAudioSink->stop();
-            if (mPaused) {
-                // Race condition: if renderer is paused and audio sink is stopped,
-                // we need to make sure that the audio track buffer fully drains
-                // before delivering data.
-                // FIXME: remove this if we can detect if stop() is complete.
-                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
-                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
-            } else {
-                mAudioSink->start();
-            }
-            mNumFramesWritten = 0;
-        }
-        mNextAudioClockUpdateTimeUs = -1;
-    } else {
-        flushQueue(&mVideoQueue);
-
-        mDrainVideoQueuePending = false;
-
-        if (mVideoScheduler != NULL) {
-            mVideoScheduler->restart();
-        }
-
-        Mutex::Autolock autoLock(mLock);
-        ++mVideoDrainGeneration;
-        prepareForMediaRenderingStart_l();
-    }
-
-    mVideoSampleReceived = false;
-
-    if (notifyComplete) {
-        notifyFlushComplete(audio);
-    }
-}
-
-void NuPlayer2::Renderer::flushQueue(List<QueueEntry> *queue) {
-    while (!queue->empty()) {
-        QueueEntry *entry = &*queue->begin();
-
-        if (entry->mBuffer != NULL) {
-            entry->mNotifyConsumed->post();
-        } else if (entry->mNotifyConsumed != nullptr) {
-            // Is it needed to open audio sink now?
-            onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
-        }
-
-        queue->erase(queue->begin());
-        entry = NULL;
-    }
-}
-
-void NuPlayer2::Renderer::notifyFlushComplete(bool audio) {
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFlushComplete);
-    notify->setInt32("audio", static_cast<int32_t>(audio));
-    notify->post();
-}
-
-bool NuPlayer2::Renderer::dropBufferIfStale(
-        bool audio, const sp<AMessage> &msg) {
-    int32_t queueGeneration;
-    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
-
-    if (queueGeneration == getQueueGeneration(audio)) {
-        return false;
-    }
-
-    sp<AMessage> notifyConsumed;
-    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
-        notifyConsumed->post();
-    }
-
-    return true;
-}
-
-void NuPlayer2::Renderer::onAudioSinkChanged() {
-    if (offloadingAudio()) {
-        return;
-    }
-    CHECK(!mDrainAudioQueuePending);
-    mNumFramesWritten = 0;
-    mAnchorNumFramesWritten = -1;
-    uint32_t written;
-    if (mAudioSink->getFramesWritten(&written) == OK) {
-        mNumFramesWritten = written;
-    }
-}
-
-void NuPlayer2::Renderer::onDisableOffloadAudio() {
-    Mutex::Autolock autoLock(mLock);
-    mFlags &= ~FLAG_OFFLOAD_AUDIO;
-    ++mAudioDrainGeneration;
-    if (mAudioRenderingStartGeneration != -1) {
-        prepareForMediaRenderingStart_l();
-    }
-}
-
-void NuPlayer2::Renderer::onEnableOffloadAudio() {
-    Mutex::Autolock autoLock(mLock);
-    mFlags |= FLAG_OFFLOAD_AUDIO;
-    ++mAudioDrainGeneration;
-    if (mAudioRenderingStartGeneration != -1) {
-        prepareForMediaRenderingStart_l();
-    }
-}
-
-void NuPlayer2::Renderer::onPause() {
-    if (mPaused) {
-        return;
-    }
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        // we do not increment audio drain generation so that we fill audio buffer during pause.
-        ++mVideoDrainGeneration;
-        prepareForMediaRenderingStart_l();
-        mPaused = true;
-        mMediaClock->setPlaybackRate(0.0);
-    }
-
-    mDrainAudioQueuePending = false;
-    mDrainVideoQueuePending = false;
-
-    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
-    mAudioSink->pause();
-    startAudioOffloadPauseTimeout();
-
-    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
-          mAudioQueue.size(), mVideoQueue.size());
-}
-
-void NuPlayer2::Renderer::onResume() {
-    if (!mPaused) {
-        return;
-    }
-
-    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
-    cancelAudioOffloadPauseTimeout();
-    if (mAudioSink->ready()) {
-        status_t err = mAudioSink->start();
-        if (err != OK) {
-            ALOGE("cannot start AudioSink err %d", err);
-            notifyAudioTearDown(kDueToError);
-        }
-    }
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        mPaused = false;
-        // rendering started message may have been delayed if we were paused.
-        if (mRenderingDataDelivered) {
-            notifyIfMediaRenderingStarted_l();
-        }
-        // configure audiosink as we did not do it when pausing
-        if (mAudioSink != NULL && mAudioSink->ready()) {
-            mAudioSink->setPlaybackRate(mPlaybackSettings);
-        }
-
-        mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
-
-        if (!mAudioQueue.empty()) {
-            postDrainAudioQueue_l();
-        }
-    }
-
-    if (!mVideoQueue.empty()) {
-        postDrainVideoQueue();
-    }
-}
-
-void NuPlayer2::Renderer::onSetVideoFrameRate(float fps) {
-    if (mVideoScheduler == NULL) {
-        mVideoScheduler = new VideoFrameScheduler2();
-    }
-    mVideoScheduler->init(fps);
-}
-
-int32_t NuPlayer2::Renderer::getQueueGeneration(bool audio) {
-    Mutex::Autolock autoLock(mLock);
-    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
-}
-
-int32_t NuPlayer2::Renderer::getDrainGeneration(bool audio) {
-    Mutex::Autolock autoLock(mLock);
-    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
-}
-
-bool NuPlayer2::Renderer::getSyncQueues() {
-    Mutex::Autolock autoLock(mLock);
-    return mSyncQueues;
-}
-
-void NuPlayer2::Renderer::onAudioTearDown(AudioTearDownReason reason) {
-    if (mAudioTornDown) {
-        return;
-    }
-    mAudioTornDown = true;
-
-    int64_t currentPositionUs;
-    sp<AMessage> notify = mNotify->dup();
-    if (getCurrentPosition(&currentPositionUs) == OK) {
-        notify->setInt64("positionUs", currentPositionUs);
-    }
-
-    mAudioSink->stop();
-    mAudioSink->flush();
-
-    notify->setInt32("what", kWhatAudioTearDown);
-    notify->setInt32("reason", reason);
-    notify->post();
-}
-
-void NuPlayer2::Renderer::startAudioOffloadPauseTimeout() {
-    if (offloadingAudio()) {
-        mWakeLock->acquire();
-        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
-        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
-        msg->post(kOffloadPauseMaxUs);
-    }
-}
-
-void NuPlayer2::Renderer::cancelAudioOffloadPauseTimeout() {
-    // We may have called startAudioOffloadPauseTimeout() without
-    // the AudioSink open and with offloadingAudio enabled.
-    //
-    // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
-    // we always release the wakelock and increment the pause timeout generation.
-    //
-    // Note: The acquired wakelock prevents the device from suspending
-    // immediately after offload pause (in case a resume happens shortly thereafter).
-    mWakeLock->release(true);
-    ++mAudioOffloadPauseTimeoutGeneration;
-}
-
-status_t NuPlayer2::Renderer::onOpenAudioSink(
-        const sp<AMessage> &format,
-        bool offloadOnly,
-        bool hasVideo,
-        uint32_t flags,
-        bool isStreaming) {
-    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
-            offloadOnly, offloadingAudio());
-
-    bool audioSinkChanged = false;
-
-    int32_t numChannels;
-    CHECK(format->findInt32("channel-count", &numChannels));
-
-    int32_t channelMask;
-    if (!format->findInt32("channel-mask", &channelMask)) {
-        // signal to the AudioSink to derive the mask from count.
-        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
-    }
-
-    int32_t sampleRate;
-    CHECK(format->findInt32("sample-rate", &sampleRate));
-
-    // read pcm encoding from MediaCodec output format, if available
-    int32_t pcmEncoding;
-    audio_format_t audioFormat =
-            format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
-                    audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
-
-    if (offloadingAudio()) {
-        AString mime;
-        CHECK(format->findString("mime", &mime));
-        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
-
-        if (err != OK) {
-            ALOGE("Couldn't map mime \"%s\" to a valid "
-                    "audio_format", mime.c_str());
-            onDisableOffloadAudio();
-        } else {
-            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
-                    mime.c_str(), audioFormat);
-
-            int avgBitRate = -1;
-            format->findInt32("bitrate", &avgBitRate);
-
-            int32_t aacProfile = -1;
-            if (audioFormat == AUDIO_FORMAT_AAC
-                    && format->findInt32("aac-profile", &aacProfile)) {
-                // Redefine AAC format as per aac profile
-                mapAACProfileToAudioFormat(
-                        audioFormat,
-                        aacProfile);
-            }
-
-            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
-            offloadInfo.duration_us = -1;
-            format->findInt64(
-                    "durationUs", &offloadInfo.duration_us);
-            offloadInfo.sample_rate = sampleRate;
-            offloadInfo.channel_mask = channelMask;
-            offloadInfo.format = audioFormat;
-            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
-            offloadInfo.bit_rate = avgBitRate;
-            offloadInfo.has_video = hasVideo;
-            offloadInfo.is_streaming = isStreaming;
-
-            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
-                ALOGV("openAudioSink: no change in offload mode");
-                // no change from previous configuration, everything ok.
-                return OK;
-            }
-            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
-
-            ALOGV("openAudioSink: try to open AudioSink in offload mode");
-            uint32_t offloadFlags = flags;
-            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-            audioSinkChanged = true;
-            mAudioSink->close();
-
-            err = mAudioSink->open(
-                    sampleRate,
-                    numChannels,
-                    (audio_channel_mask_t)channelMask,
-                    audioFormat,
-                    &NuPlayer2::Renderer::AudioSinkCallback,
-                    this,
-                    (audio_output_flags_t)offloadFlags,
-                    &offloadInfo);
-
-            if (err == OK) {
-                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
-            }
-
-            if (err == OK) {
-                // If the playback is offloaded to h/w, we pass
-                // the HAL some metadata information.
-                // We don't want to do this for PCM because it
-                // will be going through the AudioFlinger mixer
-                // before reaching the hardware.
-                // TODO
-                mCurrentOffloadInfo = offloadInfo;
-                if (!mPaused) { // for preview mode, don't start if paused
-                    err = mAudioSink->start();
-                }
-                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
-            }
-            if (err != OK) {
-                // Clean up, fall back to non offload mode.
-                mAudioSink->close();
-                onDisableOffloadAudio();
-                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
-                ALOGV("openAudioSink: offload failed");
-                if (offloadOnly) {
-                    notifyAudioTearDown(kForceNonOffload);
-                }
-            } else {
-                mUseAudioCallback = true;  // offload mode transfers data through callback
-                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
-            }
-        }
-    }
-    if (!offloadOnly && !offloadingAudio()) {
-        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
-        uint32_t pcmFlags = flags;
-        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-
-        const PcmInfo info = {
-                (audio_channel_mask_t)channelMask,
-                (audio_output_flags_t)pcmFlags,
-                audioFormat,
-                numChannels,
-                sampleRate
-        };
-        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
-            ALOGV("openAudioSink: no change in pcm mode");
-            // no change from previous configuration, everything ok.
-            return OK;
-        }
-
-        audioSinkChanged = true;
-        mAudioSink->close();
-        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
-        // Note: It is possible to set up the callback, but not use it to send audio data.
-        // This requires a fix in AudioSink to explicitly specify the transfer mode.
-        mUseAudioCallback = getUseAudioCallbackSetting();
-        if (mUseAudioCallback) {
-            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
-        }
-
-        // Compute the desired buffer size.
-        // For callback mode, the amount of time before wakeup is about half the buffer size.
-        const uint32_t frameCount =
-                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
-
-        // We should always be able to set our playback settings if the sink is closed.
-        LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
-                "onOpenAudioSink: can't set playback rate on closed sink");
-        status_t err = mAudioSink->open(
-                    sampleRate,
-                    numChannels,
-                    (audio_channel_mask_t)channelMask,
-                    audioFormat,
-                    mUseAudioCallback ? &NuPlayer2::Renderer::AudioSinkCallback : NULL,
-                    mUseAudioCallback ? this : NULL,
-                    (audio_output_flags_t)pcmFlags,
-                    NULL,
-                    frameCount);
-        if (err != OK) {
-            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
-            mAudioSink->close();
-            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
-            return err;
-        }
-        mCurrentPcmInfo = info;
-        if (!mPaused) { // for preview mode, don't start if paused
-            mAudioSink->start();
-        }
-    }
-    if (audioSinkChanged) {
-        onAudioSinkChanged();
-    }
-    mAudioTornDown = false;
-    return OK;
-}
-
-void NuPlayer2::Renderer::onCloseAudioSink() {
-    mAudioSink->close();
-    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
-    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
-}
-
-void NuPlayer2::Renderer::onChangeAudioFormat(
-        const sp<AMessage> &meta, const sp<AMessage> &notify) {
-    sp<AMessage> format;
-    CHECK(meta->findMessage("format", &format));
-
-    int32_t offloadOnly;
-    CHECK(meta->findInt32("offload-only", &offloadOnly));
-
-    int32_t hasVideo;
-    CHECK(meta->findInt32("has-video", &hasVideo));
-
-    uint32_t flags;
-    CHECK(meta->findInt32("flags", (int32_t *)&flags));
-
-    uint32_t isStreaming;
-    CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
-
-    status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
-
-    if (err != OK) {
-        notify->setInt32("err", err);
-    }
-    notify->post();
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
deleted file mode 100644
index d065dee..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_RENDERER_H_
-
-#define NUPLAYER2_RENDERER_H_
-
-#include <media/AudioResamplerPublic.h>
-#include <media/AVSyncSettings.h>
-#include <mediaplayer2/JObjectHolder.h>
-
-#include "NuPlayer2.h"
-
-namespace android {
-
-class  JWakeLock;
-struct MediaClock;
-class MediaCodecBuffer;
-struct VideoFrameSchedulerBase;
-
-struct NuPlayer2::Renderer : public AHandler {
-    enum Flags {
-        FLAG_REAL_TIME = 1,
-        FLAG_OFFLOAD_AUDIO = 2,
-    };
-    Renderer(const sp<MediaPlayer2Interface::AudioSink> &sink,
-             const sp<MediaClock> &mediaClock,
-             const sp<AMessage> &notify,
-             const sp<JObjectHolder> &context,
-             uint32_t flags = 0);
-
-    static size_t AudioSinkCallback(
-            MediaPlayer2Interface::AudioSink *audioSink,
-            void *data, size_t size, void *me,
-            MediaPlayer2Interface::AudioSink::cb_event_t event);
-
-    void queueBuffer(
-            bool audio,
-            const sp<MediaCodecBuffer> &buffer,
-            const sp<AMessage> &notifyConsumed);
-
-    void queueEOS(bool audio, status_t finalResult);
-
-    status_t setPlaybackSettings(const AudioPlaybackRate &rate /* sanitized */);
-    status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-    status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint);
-    status_t getSyncSettings(AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */);
-
-    void flush(bool audio, bool notifyComplete);
-
-    void signalTimeDiscontinuity();
-
-    void signalDisableOffloadAudio();
-    void signalEnableOffloadAudio();
-
-    void pause();
-    void resume();
-
-    void setVideoFrameRate(float fps);
-
-    status_t getCurrentPosition(int64_t *mediaUs);
-    int64_t getVideoLateByUs();
-
-    status_t openAudioSink(
-            const sp<AMessage> &format,
-            bool offloadOnly,
-            bool hasVideo,
-            uint32_t flags,
-            bool *isOffloaded,
-            bool isStreaming);
-    void closeAudioSink();
-
-    // re-open audio sink after all pending audio buffers played.
-    void changeAudioFormat(
-            const sp<AMessage> &format,
-            bool offloadOnly,
-            bool hasVideo,
-            uint32_t flags,
-            bool isStreaming,
-            const sp<AMessage> &notify);
-
-    enum {
-        kWhatEOS                      = 'eos ',
-        kWhatFlushComplete            = 'fluC',
-        kWhatPosition                 = 'posi',
-        kWhatVideoRenderingStart      = 'vdrd',
-        kWhatMediaRenderingStart      = 'mdrd',
-        kWhatAudioTearDown            = 'adTD',
-        kWhatAudioOffloadPauseTimeout = 'aOPT',
-    };
-
-    enum AudioTearDownReason {
-        kDueToError = 0,   // Could restart with either offload or non-offload.
-        kDueToTimeout,
-        kForceNonOffload,  // Restart only with non-offload.
-    };
-
-protected:
-    virtual ~Renderer();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
-    enum {
-        kWhatDrainAudioQueue     = 'draA',
-        kWhatDrainVideoQueue     = 'draV',
-        kWhatPostDrainVideoQueue = 'pDVQ',
-        kWhatQueueBuffer         = 'queB',
-        kWhatQueueEOS            = 'qEOS',
-        kWhatConfigPlayback      = 'cfPB',
-        kWhatConfigSync          = 'cfSy',
-        kWhatGetPlaybackSettings = 'gPbS',
-        kWhatGetSyncSettings     = 'gSyS',
-        kWhatFlush               = 'flus',
-        kWhatPause               = 'paus',
-        kWhatResume              = 'resm',
-        kWhatOpenAudioSink       = 'opnA',
-        kWhatCloseAudioSink      = 'clsA',
-        kWhatChangeAudioFormat   = 'chgA',
-        kWhatStopAudioSink       = 'stpA',
-        kWhatDisableOffloadAudio = 'noOA',
-        kWhatEnableOffloadAudio  = 'enOA',
-        kWhatSetVideoFrameRate   = 'sVFR',
-    };
-
-    // if mBuffer != nullptr, it's a buffer containing real data.
-    // else if mNotifyConsumed == nullptr, it's EOS.
-    // else it's a tag for re-opening audio sink in different format.
-    struct QueueEntry {
-        sp<MediaCodecBuffer> mBuffer;
-        sp<AMessage> mMeta;
-        sp<AMessage> mNotifyConsumed;
-        size_t mOffset;
-        status_t mFinalResult;
-        int32_t mBufferOrdinal;
-    };
-
-    static const int64_t kMinPositionUpdateDelayUs;
-
-    sp<MediaPlayer2Interface::AudioSink> mAudioSink;
-    bool mUseVirtualAudioSink;
-    sp<AMessage> mNotify;
-    Mutex mLock;
-    uint32_t mFlags;
-    List<QueueEntry> mAudioQueue;
-    List<QueueEntry> mVideoQueue;
-    uint32_t mNumFramesWritten;
-    sp<VideoFrameSchedulerBase> mVideoScheduler;
-
-    bool mDrainAudioQueuePending;
-    bool mDrainVideoQueuePending;
-    int32_t mAudioQueueGeneration;
-    int32_t mVideoQueueGeneration;
-    int32_t mAudioDrainGeneration;
-    int32_t mVideoDrainGeneration;
-    int32_t mAudioEOSGeneration;
-
-    const sp<MediaClock> mMediaClock;
-
-    AudioPlaybackRate mPlaybackSettings;
-    AVSyncSettings mSyncSettings;
-    float mVideoFpsHint;
-
-    int64_t mAudioFirstAnchorTimeMediaUs;
-    int64_t mAnchorTimeMediaUs;
-    int64_t mAnchorNumFramesWritten;
-    int64_t mVideoLateByUs;
-    int64_t mNextVideoTimeMediaUs;
-    bool mHasAudio;
-    bool mHasVideo;
-
-    bool mNotifyCompleteAudio;
-    bool mNotifyCompleteVideo;
-
-    bool mSyncQueues;
-
-    // modified on only renderer's thread.
-    bool mPaused;
-    int64_t mPauseDrainAudioAllowedUs; // time when we can drain/deliver audio in pause mode.
-
-    bool mVideoSampleReceived;
-    bool mVideoRenderingStarted;
-    int32_t mVideoRenderingStartGeneration;
-    int32_t mAudioRenderingStartGeneration;
-    bool mRenderingDataDelivered;
-
-    int64_t mNextAudioClockUpdateTimeUs;
-    // the media timestamp of last audio sample right before EOS.
-    int64_t mLastAudioMediaTimeUs;
-
-    int32_t mAudioOffloadPauseTimeoutGeneration;
-    bool mAudioTornDown;
-    audio_offload_info_t mCurrentOffloadInfo;
-
-    struct PcmInfo {
-        audio_channel_mask_t mChannelMask;
-        audio_output_flags_t mFlags;
-        audio_format_t mFormat;
-        int32_t mNumChannels;
-        int32_t mSampleRate;
-    };
-    PcmInfo mCurrentPcmInfo;
-    static const PcmInfo AUDIO_PCMINFO_INITIALIZER;
-
-    int32_t mTotalBuffersQueued;
-    int32_t mLastAudioBufferDrained;
-    bool mUseAudioCallback;
-
-    sp<JWakeLock> mWakeLock;
-
-    status_t getCurrentPositionOnLooper(int64_t *mediaUs);
-    status_t getCurrentPositionOnLooper(
-            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-    bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
-    status_t getCurrentPositionFromAnchor(
-            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-
-    void notifyEOSCallback();
-    size_t fillAudioBuffer(void *buffer, size_t size);
-
-    bool onDrainAudioQueue();
-    void drainAudioQueueUntilLastEOS();
-    int64_t getPendingAudioPlayoutDurationUs(int64_t nowUs);
-    void postDrainAudioQueue_l(int64_t delayUs = 0);
-
-    void clearAnchorTime();
-    void clearAudioFirstAnchorTime_l();
-    void setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs);
-    void setVideoLateByUs(int64_t lateUs);
-
-    void onNewAudioMediaTime(int64_t mediaTimeUs);
-    int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
-
-    void onDrainVideoQueue();
-    void postDrainVideoQueue();
-
-    void prepareForMediaRenderingStart_l();
-    void notifyIfMediaRenderingStarted_l();
-
-    void onQueueBuffer(const sp<AMessage> &msg);
-    void onQueueEOS(const sp<AMessage> &msg);
-    void onFlush(const sp<AMessage> &msg);
-    void onAudioSinkChanged();
-    void onDisableOffloadAudio();
-    void onEnableOffloadAudio();
-    status_t onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */);
-    status_t onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-    status_t onConfigSync(const AVSyncSettings &sync, float videoFpsHint);
-    status_t onGetSyncSettings(AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */);
-
-    void onPause();
-    void onResume();
-    void onSetVideoFrameRate(float fps);
-    int32_t getQueueGeneration(bool audio);
-    int32_t getDrainGeneration(bool audio);
-    bool getSyncQueues();
-    void onAudioTearDown(AudioTearDownReason reason);
-    status_t onOpenAudioSink(
-            const sp<AMessage> &format,
-            bool offloadOnly,
-            bool hasVideo,
-            uint32_t flags,
-            bool isStreaming);
-    void onCloseAudioSink();
-    void onChangeAudioFormat(const sp<AMessage> &meta, const sp<AMessage> &notify);
-
-    void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
-    void notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs = 0);
-    void notifyFlushComplete(bool audio);
-    void notifyPosition();
-    void notifyVideoLateBy(int64_t lateByUs);
-    void notifyVideoRenderingStart();
-    void notifyAudioTearDown(AudioTearDownReason reason);
-
-    void flushQueue(List<QueueEntry> *queue);
-    bool dropBufferIfStale(bool audio, const sp<AMessage> &msg);
-    void syncQueuesDone_l();
-
-    bool offloadingAudio() const { return (mFlags & FLAG_OFFLOAD_AUDIO) != 0; }
-
-    void startAudioOffloadPauseTimeout();
-    void cancelAudioOffloadPauseTimeout();
-
-    int64_t getDurationUsIfPlayedAtSampleRate(uint32_t numFrames);
-
-    DISALLOW_EVIL_CONSTRUCTORS(Renderer);
-};
-
-} // namespace android
-
-#endif  // NUPLAYER2_RENDERER_H_
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h
deleted file mode 100644
index 9298a99..0000000
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Source.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2017 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 NUPLAYER2_SOURCE_H_
-
-#define NUPLAYER2_SOURCE_H_
-
-#include "NuPlayer2.h"
-
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MetaData.h>
-#include <mediaplayer2/mediaplayer2.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-struct ABuffer;
-struct AMediaCryptoWrapper;
-class MediaBuffer;
-
-struct NuPlayer2::Source : public AHandler {
-    enum Flags {
-        FLAG_CAN_PAUSE          = 1,
-        FLAG_CAN_SEEK_BACKWARD  = 2,  // the "10 sec back button"
-        FLAG_CAN_SEEK_FORWARD   = 4,  // the "10 sec forward button"
-        FLAG_CAN_SEEK           = 8,  // the "seek bar"
-        FLAG_DYNAMIC_DURATION   = 16,
-        FLAG_SECURE             = 32, // Secure codec is required.
-        FLAG_PROTECTED          = 64, // The screen needs to be protected (screenshot is disabled).
-    };
-
-    enum {
-        kWhatPrepared,
-        kWhatFlagsChanged,
-        kWhatVideoSizeChanged,
-        kWhatBufferingUpdate,
-        kWhatPauseOnBufferingStart,
-        kWhatResumeOnBufferingEnd,
-        kWhatCacheStats,
-        kWhatSubtitleData,
-        kWhatTimedTextData,
-        kWhatTimedMetaData,
-        kWhatQueueDecoderShutdown,
-        kWhatDrmNoLicense,
-        // Modular DRM
-        kWhatDrmInfo,
-    };
-
-    // The provides message is used to notify the player about various
-    // events.
-    explicit Source(const sp<AMessage> &notify)
-        : mNotify(notify) {
-    }
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) = 0;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
-
-    virtual void prepareAsync(int64_t startTimeUs) = 0;
-
-    virtual void start() = 0;
-    virtual void stop() {}
-    virtual void pause() {}
-    virtual void resume() {}
-
-    // Explicitly disconnect the underling data source
-    virtual void disconnect() {}
-
-    // Returns OK iff more data was available,
-    // an error or ERROR_END_OF_STREAM if not.
-    virtual status_t feedMoreTSData() = 0;
-
-    // Returns non-NULL format when the specified track exists.
-    // When the format has "err" set to -EWOULDBLOCK, source needs more time to get valid meta data.
-    // Returns NULL if the specified track doesn't exist or is invalid;
-    virtual sp<AMessage> getFormat(bool audio);
-
-    virtual sp<MetaData> getFormatMeta(bool /* audio */) { return NULL; }
-    virtual sp<MetaData> getFileFormatMeta() const { return NULL; }
-
-    virtual status_t dequeueAccessUnit(
-            bool audio, sp<ABuffer> *accessUnit) = 0;
-
-    virtual status_t getDuration(int64_t * /* durationUs */) {
-        return INVALID_OPERATION;
-    }
-
-    virtual size_t getTrackCount() const {
-        return 0;
-    }
-
-    virtual sp<AMessage> getTrackInfo(size_t /* trackIndex */) const {
-        return NULL;
-    }
-
-    virtual ssize_t getSelectedTrack(media_track_type /* type */) const {
-        return INVALID_OPERATION;
-    }
-
-    virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */, int64_t /* timeUs*/) {
-        return INVALID_OPERATION;
-    }
-
-    virtual status_t seekTo(
-            int64_t /* seekTimeUs */,
-            MediaPlayer2SeekMode /* mode */ = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) {
-        return INVALID_OPERATION;
-    }
-
-    virtual bool isRealTime() const {
-        return false;
-    }
-
-    virtual bool isStreaming() const {
-        return true;
-    }
-
-    virtual void setOffloadAudio(bool /* offload */) {}
-
-    // Modular DRM
-    virtual status_t prepareDrm(
-            const uint8_t /* uuid */[16], const Vector<uint8_t> & /* drmSessionId */,
-            sp<AMediaCryptoWrapper> * /* crypto */) {
-        return INVALID_OPERATION;
-    }
-
-    virtual status_t releaseDrm() {
-        return INVALID_OPERATION;
-    }
-
-protected:
-    virtual ~Source() {}
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    sp<AMessage> dupNotify() const { return mNotify->dup(); }
-
-    void notifyFlagsChanged(uint32_t flags);
-    void notifyVideoSizeChanged(const sp<AMessage> &format = NULL);
-    void notifyPrepared(status_t err = OK);
-    // Modular DRM
-    void notifyDrmInfo(const sp<ABuffer> &buffer);
-
-private:
-    sp<AMessage> mNotify;
-
-    DISALLOW_EVIL_CONSTRUCTORS(Source);
-};
-
-}  // namespace android
-
-#endif  // NUPLAYER2_SOURCE_H_
-
diff --git a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp b/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
deleted file mode 100644
index a70269e..0000000
--- a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright 2017 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 "RTSPSource2"
-#include <utils/Log.h>
-
-#include "RTSPSource2.h"
-
-#include "AnotherPacketSource.h"
-#include "MyHandler.h"
-#include "SDPLoader.h"
-
-#include <media/MediaHTTPService.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-const int64_t kNearEOSTimeoutUs = 2000000LL; // 2 secs
-
-// Default Buffer Underflow/Prepare/StartServer/Overflow Marks
-static const int kUnderflowMarkMs   =  1000;  // 1 second
-static const int kPrepareMarkMs     =  3000;  // 3 seconds
-//static const int kStartServerMarkMs =  5000;
-static const int kOverflowMarkMs    = 10000;  // 10 seconds
-
-NuPlayer2::RTSPSource2::RTSPSource2(
-        const sp<AMessage> &notify,
-        const sp<MediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers,
-        uid_t uid,
-        bool isSDP)
-    : Source(notify),
-      mHTTPService(httpService),
-      mURL(url),
-      mUID(uid),
-      mFlags(0),
-      mIsSDP(isSDP),
-      mState(DISCONNECTED),
-      mFinalResult(OK),
-      mDisconnectReplyID(0),
-      mBuffering(false),
-      mInPreparationPhase(true),
-      mEOSPending(false),
-      mSeekGeneration(0),
-      mEOSTimeoutAudio(0),
-      mEOSTimeoutVideo(0) {
-    mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
-    mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
-    if (headers) {
-        mExtraHeaders = *headers;
-
-        ssize_t index =
-            mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
-
-        if (index >= 0) {
-            mFlags |= kFlagIncognito;
-
-            mExtraHeaders.removeItemsAt(index);
-        }
-    }
-}
-
-NuPlayer2::RTSPSource2::~RTSPSource2() {
-    if (mLooper != NULL) {
-        mLooper->unregisterHandler(id());
-        mLooper->stop();
-    }
-}
-
-status_t NuPlayer2::RTSPSource2::getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) {
-    Mutex::Autolock _l(mBufferingSettingsLock);
-    *buffering = mBufferingSettings;
-    return OK;
-}
-
-status_t NuPlayer2::RTSPSource2::setBufferingSettings(const BufferingSettings& buffering) {
-    Mutex::Autolock _l(mBufferingSettingsLock);
-    mBufferingSettings = buffering;
-    return OK;
-}
-
-// TODO: fetch data starting from |startTimeUs|
-void NuPlayer2::RTSPSource2::prepareAsync(int64_t /* startTimeUs */) {
-    if (mIsSDP && mHTTPService == NULL) {
-        notifyPrepared(BAD_VALUE);
-        return;
-    }
-
-    if (mLooper == NULL) {
-        mLooper = new ALooper;
-        mLooper->setName("rtsp2");
-        mLooper->start();
-
-        mLooper->registerHandler(this);
-    }
-
-    CHECK(mHandler == NULL);
-    CHECK(mSDPLoader == NULL);
-
-    sp<AMessage> notify = new AMessage(kWhatNotify, this);
-
-    CHECK_EQ(mState, (int)DISCONNECTED);
-    mState = CONNECTING;
-
-    if (mIsSDP) {
-        mSDPLoader = new SDPLoader(notify,
-                (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
-                mHTTPService);
-
-        mSDPLoader->load(
-                mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
-    } else {
-        mHandler = new MyHandler(mURL.c_str(), notify, true /* uidValid */, mUID);
-        mLooper->registerHandler(mHandler);
-
-        mHandler->connect();
-    }
-
-    startBufferingIfNecessary();
-}
-
-void NuPlayer2::RTSPSource2::start() {
-}
-
-void NuPlayer2::RTSPSource2::stop() {
-    if (mLooper == NULL) {
-        return;
-    }
-    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
-
-    sp<AMessage> dummy;
-    msg->postAndAwaitResponse(&dummy);
-}
-
-status_t NuPlayer2::RTSPSource2::feedMoreTSData() {
-    Mutex::Autolock _l(mBufferingLock);
-    return mFinalResult;
-}
-
-sp<MetaData> NuPlayer2::RTSPSource2::getFormatMeta(bool audio) {
-    sp<AnotherPacketSource> source = getSource(audio);
-
-    if (source == NULL) {
-        return NULL;
-    }
-
-    return source->getFormat();
-}
-
-bool NuPlayer2::RTSPSource2::haveSufficientDataOnAllTracks() {
-    // We're going to buffer at least 2 secs worth data on all tracks before
-    // starting playback (both at startup and after a seek).
-
-    static const int64_t kMinDurationUs = 2000000LL;
-
-    int64_t mediaDurationUs = 0;
-    getDuration(&mediaDurationUs);
-    if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
-            || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
-        return true;
-    }
-
-    status_t err;
-    int64_t durationUs;
-    if (mAudioTrack != NULL
-            && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
-                    < kMinDurationUs
-            && err == OK) {
-        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
-              durationUs / 1E6);
-        return false;
-    }
-
-    if (mVideoTrack != NULL
-            && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
-                    < kMinDurationUs
-            && err == OK) {
-        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
-              durationUs / 1E6);
-        return false;
-    }
-
-    return true;
-}
-
-status_t NuPlayer2::RTSPSource2::dequeueAccessUnit(
-        bool audio, sp<ABuffer> *accessUnit) {
-    if (!stopBufferingIfNecessary()) {
-        return -EWOULDBLOCK;
-    }
-
-    sp<AnotherPacketSource> source = getSource(audio);
-
-    if (source == NULL) {
-        return -EWOULDBLOCK;
-    }
-
-    status_t finalResult;
-    if (!source->hasBufferAvailable(&finalResult)) {
-        if (finalResult == OK) {
-
-            // If other source already signaled EOS, this source should also return EOS
-            if (sourceReachedEOS(!audio)) {
-                return ERROR_END_OF_STREAM;
-            }
-
-            // If this source has detected near end, give it some time to retrieve more
-            // data before returning EOS
-            int64_t mediaDurationUs = 0;
-            getDuration(&mediaDurationUs);
-            if (source->isFinished(mediaDurationUs)) {
-                int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
-                if (eosTimeout == 0) {
-                    setEOSTimeout(audio, ALooper::GetNowUs());
-                } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
-                    setEOSTimeout(audio, 0);
-                    return ERROR_END_OF_STREAM;
-                }
-                return -EWOULDBLOCK;
-            }
-
-            if (!sourceNearEOS(!audio)) {
-                // We should not enter buffering mode
-                // if any of the sources already have detected EOS.
-                startBufferingIfNecessary();
-            }
-
-            return -EWOULDBLOCK;
-        }
-        return finalResult;
-    }
-
-    setEOSTimeout(audio, 0);
-
-    return source->dequeueAccessUnit(accessUnit);
-}
-
-sp<AnotherPacketSource> NuPlayer2::RTSPSource2::getSource(bool audio) {
-    if (mTSParser != NULL) {
-        sp<MediaSource> source = mTSParser->getSource(
-                audio ? ATSParser::AUDIO : ATSParser::VIDEO);
-
-        return static_cast<AnotherPacketSource *>(source.get());
-    }
-
-    return audio ? mAudioTrack : mVideoTrack;
-}
-
-void NuPlayer2::RTSPSource2::setEOSTimeout(bool audio, int64_t timeout) {
-    if (audio) {
-        mEOSTimeoutAudio = timeout;
-    } else {
-        mEOSTimeoutVideo = timeout;
-    }
-}
-
-status_t NuPlayer2::RTSPSource2::getDuration(int64_t *durationUs) {
-    *durationUs = -1LL;
-
-    int64_t audioDurationUs;
-    if (mAudioTrack != NULL
-            && mAudioTrack->getFormat()->findInt64(
-                kKeyDuration, &audioDurationUs)
-            && audioDurationUs > *durationUs) {
-        *durationUs = audioDurationUs;
-    }
-
-    int64_t videoDurationUs;
-    if (mVideoTrack != NULL
-            && mVideoTrack->getFormat()->findInt64(
-                kKeyDuration, &videoDurationUs)
-            && videoDurationUs > *durationUs) {
-        *durationUs = videoDurationUs;
-    }
-
-    return OK;
-}
-
-status_t NuPlayer2::RTSPSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
-    sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
-    msg->setInt32("generation", ++mSeekGeneration);
-    msg->setInt64("timeUs", seekTimeUs);
-    msg->setInt32("mode", mode);
-
-    sp<AMessage> response;
-    status_t err = msg->postAndAwaitResponse(&response);
-    if (err == OK && response != NULL) {
-        CHECK(response->findInt32("err", &err));
-    }
-
-    return err;
-}
-
-void NuPlayer2::RTSPSource2::performSeek(int64_t seekTimeUs) {
-    if (mState != CONNECTED) {
-        finishSeek(INVALID_OPERATION);
-        return;
-    }
-
-    mState = SEEKING;
-    mHandler->seek(seekTimeUs);
-    mEOSPending = false;
-}
-
-void NuPlayer2::RTSPSource2::schedulePollBuffering() {
-    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
-    msg->post(1000000LL); // 1 second intervals
-}
-
-void NuPlayer2::RTSPSource2::checkBuffering(
-        bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
-    size_t numTracks = mTracks.size();
-    size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
-    preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
-
-    size_t count = numTracks;
-    for (size_t i = 0; i < count; ++i) {
-        status_t finalResult;
-        TrackInfo *info = &mTracks.editItemAt(i);
-        sp<AnotherPacketSource> src = info->mSource;
-        if (src == NULL) {
-            --numTracks;
-            continue;
-        }
-        int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
-
-        int64_t initialMarkUs;
-        int64_t maxRebufferingMarkUs;
-        {
-            Mutex::Autolock _l(mBufferingSettingsLock);
-            initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
-            // TODO: maxRebufferingMarkUs could be larger than
-            // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
-            maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
-        }
-        // isFinished when duration is 0 checks for EOS result only
-        if (bufferedDurationUs > initialMarkUs
-                || src->isFinished(/* duration */ 0)) {
-            ++preparedCount;
-        }
-
-        if (src->isFinished(/* duration */ 0)) {
-            ++overflowCount;
-            ++finishedCount;
-        } else {
-            // TODO: redefine kUnderflowMarkMs to a fair value,
-            if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
-                ++underflowCount;
-            }
-            if (bufferedDurationUs > maxRebufferingMarkUs) {
-                ++overflowCount;
-            }
-            int64_t startServerMarkUs =
-                    (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
-            if (bufferedDurationUs < startServerMarkUs) {
-                ++startCount;
-            }
-        }
-    }
-
-    *prepared    = (preparedCount == numTracks);
-    *underflow   = (underflowCount > 0);
-    *overflow    = (overflowCount == numTracks);
-    *startServer = (startCount > 0);
-    *finished    = (finishedCount > 0);
-}
-
-void NuPlayer2::RTSPSource2::onPollBuffering() {
-    bool prepared, underflow, overflow, startServer, finished;
-    checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
-
-    if (prepared && mInPreparationPhase) {
-        mInPreparationPhase = false;
-        notifyPrepared();
-    }
-
-    if (!mInPreparationPhase && underflow) {
-        startBufferingIfNecessary();
-    }
-
-    if (haveSufficientDataOnAllTracks()) {
-        stopBufferingIfNecessary();
-    }
-
-    if (overflow && mHandler != NULL) {
-        mHandler->pause();
-    }
-
-    if (startServer && mHandler != NULL) {
-        mHandler->resume();
-    }
-
-    if (finished && mHandler != NULL) {
-        mHandler->cancelAccessUnitTimeoutCheck();
-    }
-
-    schedulePollBuffering();
-}
-
-void NuPlayer2::RTSPSource2::signalSourceEOS(status_t result) {
-    const bool audio = true;
-    const bool video = false;
-
-    sp<AnotherPacketSource> source = getSource(audio);
-    if (source != NULL) {
-        source->signalEOS(result);
-    }
-
-    source = getSource(video);
-    if (source != NULL) {
-        source->signalEOS(result);
-    }
-}
-
-bool NuPlayer2::RTSPSource2::sourceReachedEOS(bool audio) {
-    sp<AnotherPacketSource> source = getSource(audio);
-    status_t finalResult;
-    return (source != NULL &&
-            !source->hasBufferAvailable(&finalResult) &&
-            finalResult == ERROR_END_OF_STREAM);
-}
-
-bool NuPlayer2::RTSPSource2::sourceNearEOS(bool audio) {
-    sp<AnotherPacketSource> source = getSource(audio);
-    int64_t mediaDurationUs = 0;
-    getDuration(&mediaDurationUs);
-    return (source != NULL && source->isFinished(mediaDurationUs));
-}
-
-void NuPlayer2::RTSPSource2::onSignalEOS(const sp<AMessage> &msg) {
-    int32_t generation;
-    CHECK(msg->findInt32("generation", &generation));
-
-    if (generation != mSeekGeneration) {
-        return;
-    }
-
-    if (mEOSPending) {
-        signalSourceEOS(ERROR_END_OF_STREAM);
-        mEOSPending = false;
-    }
-}
-
-void NuPlayer2::RTSPSource2::postSourceEOSIfNecessary() {
-    const bool audio = true;
-    const bool video = false;
-    // If a source has detected near end, give it some time to retrieve more
-    // data before signaling EOS
-    if (sourceNearEOS(audio) || sourceNearEOS(video)) {
-        if (!mEOSPending) {
-            sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
-            msg->setInt32("generation", mSeekGeneration);
-            msg->post(kNearEOSTimeoutUs);
-            mEOSPending = true;
-        }
-    }
-}
-
-void NuPlayer2::RTSPSource2::onMessageReceived(const sp<AMessage> &msg) {
-    if (msg->what() == kWhatDisconnect) {
-        sp<AReplyToken> replyID;
-        CHECK(msg->senderAwaitsResponse(&replyID));
-
-        mDisconnectReplyID = replyID;
-        finishDisconnectIfPossible();
-        return;
-    } else if (msg->what() == kWhatPerformSeek) {
-        int32_t generation;
-        CHECK(msg->findInt32("generation", &generation));
-        CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
-
-        if (generation != mSeekGeneration) {
-            // obsolete.
-            finishSeek(OK);
-            return;
-        }
-
-        int64_t seekTimeUs;
-        int32_t mode;
-        CHECK(msg->findInt64("timeUs", &seekTimeUs));
-        CHECK(msg->findInt32("mode", &mode));
-
-        // TODO: add "mode" to performSeek.
-        performSeek(seekTimeUs/*, (MediaPlayer2SeekMode)mode */);
-        return;
-    } else if (msg->what() == kWhatPollBuffering) {
-        onPollBuffering();
-        return;
-    } else if (msg->what() == kWhatSignalEOS) {
-        onSignalEOS(msg);
-        return;
-    }
-
-    CHECK_EQ(msg->what(), kWhatNotify);
-
-    int32_t what;
-    CHECK(msg->findInt32("what", &what));
-
-    switch (what) {
-        case MyHandler::kWhatConnected:
-        {
-            onConnected();
-
-            notifyVideoSizeChanged();
-
-            uint32_t flags = 0;
-
-            if (mHandler->isSeekable()) {
-                flags = FLAG_CAN_PAUSE
-                        | FLAG_CAN_SEEK
-                        | FLAG_CAN_SEEK_BACKWARD
-                        | FLAG_CAN_SEEK_FORWARD;
-            }
-
-            notifyFlagsChanged(flags);
-            schedulePollBuffering();
-            break;
-        }
-
-        case MyHandler::kWhatDisconnected:
-        {
-            onDisconnected(msg);
-            break;
-        }
-
-        case MyHandler::kWhatSeekDone:
-        {
-            mState = CONNECTED;
-            // Unblock seekTo here in case we attempted to seek in a live stream
-            finishSeek(OK);
-            break;
-        }
-
-        case MyHandler::kWhatSeekPaused:
-        {
-            sp<AnotherPacketSource> source = getSource(true /* audio */);
-            if (source != NULL) {
-                source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
-                        /* extra */ NULL,
-                        /* discard */ true);
-            }
-            source = getSource(false /* video */);
-            if (source != NULL) {
-                source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
-                        /* extra */ NULL,
-                        /* discard */ true);
-            };
-
-            status_t err = OK;
-            msg->findInt32("err", &err);
-
-            if (err == OK) {
-                int64_t timeUs;
-                CHECK(msg->findInt64("time", &timeUs));
-                mHandler->continueSeekAfterPause(timeUs);
-            } else {
-                finishSeek(err);
-            }
-            break;
-        }
-
-        case MyHandler::kWhatAccessUnit:
-        {
-            size_t trackIndex;
-            CHECK(msg->findSize("trackIndex", &trackIndex));
-
-            if (mTSParser == NULL) {
-                CHECK_LT(trackIndex, mTracks.size());
-            } else {
-                CHECK_EQ(trackIndex, 0u);
-            }
-
-            sp<ABuffer> accessUnit;
-            CHECK(msg->findBuffer("accessUnit", &accessUnit));
-
-            int32_t damaged;
-            if (accessUnit->meta()->findInt32("damaged", &damaged)
-                    && damaged) {
-                ALOGI("dropping damaged access unit.");
-                break;
-            }
-
-            if (mTSParser != NULL) {
-                size_t offset = 0;
-                status_t err = OK;
-                while (offset + 188 <= accessUnit->size()) {
-                    err = mTSParser->feedTSPacket(
-                            accessUnit->data() + offset, 188);
-                    if (err != OK) {
-                        break;
-                    }
-
-                    offset += 188;
-                }
-
-                if (offset < accessUnit->size()) {
-                    err = ERROR_MALFORMED;
-                }
-
-                if (err != OK) {
-                    signalSourceEOS(err);
-                }
-
-                postSourceEOSIfNecessary();
-                break;
-            }
-
-            TrackInfo *info = &mTracks.editItemAt(trackIndex);
-
-            sp<AnotherPacketSource> source = info->mSource;
-            if (source != NULL) {
-                uint32_t rtpTime;
-                CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
-
-                if (!info->mNPTMappingValid) {
-                    // This is a live stream, we didn't receive any normal
-                    // playtime mapping. We won't map to npt time.
-                    source->queueAccessUnit(accessUnit);
-                    break;
-                }
-
-                int64_t nptUs =
-                    ((double)rtpTime - (double)info->mRTPTime)
-                        / info->mTimeScale
-                        * 1000000LL
-                        + info->mNormalPlaytimeUs;
-
-                accessUnit->meta()->setInt64("timeUs", nptUs);
-
-                source->queueAccessUnit(accessUnit);
-            }
-            postSourceEOSIfNecessary();
-            break;
-        }
-
-        case MyHandler::kWhatEOS:
-        {
-            int32_t finalResult;
-            CHECK(msg->findInt32("finalResult", &finalResult));
-            CHECK_NE(finalResult, (status_t)OK);
-
-            if (mTSParser != NULL) {
-                signalSourceEOS(finalResult);
-            }
-
-            size_t trackIndex;
-            CHECK(msg->findSize("trackIndex", &trackIndex));
-            CHECK_LT(trackIndex, mTracks.size());
-
-            TrackInfo *info = &mTracks.editItemAt(trackIndex);
-            sp<AnotherPacketSource> source = info->mSource;
-            if (source != NULL) {
-                source->signalEOS(finalResult);
-            }
-
-            break;
-        }
-
-        case MyHandler::kWhatSeekDiscontinuity:
-        {
-            size_t trackIndex;
-            CHECK(msg->findSize("trackIndex", &trackIndex));
-            CHECK_LT(trackIndex, mTracks.size());
-
-            TrackInfo *info = &mTracks.editItemAt(trackIndex);
-            sp<AnotherPacketSource> source = info->mSource;
-            if (source != NULL) {
-                source->queueDiscontinuity(
-                        ATSParser::DISCONTINUITY_TIME,
-                        NULL,
-                        true /* discard */);
-            }
-
-            break;
-        }
-
-        case MyHandler::kWhatNormalPlayTimeMapping:
-        {
-            size_t trackIndex;
-            CHECK(msg->findSize("trackIndex", &trackIndex));
-            CHECK_LT(trackIndex, mTracks.size());
-
-            uint32_t rtpTime;
-            CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
-
-            int64_t nptUs;
-            CHECK(msg->findInt64("nptUs", &nptUs));
-
-            TrackInfo *info = &mTracks.editItemAt(trackIndex);
-            info->mRTPTime = rtpTime;
-            info->mNormalPlaytimeUs = nptUs;
-            info->mNPTMappingValid = true;
-            break;
-        }
-
-        case SDPLoader::kWhatSDPLoaded:
-        {
-            onSDPLoaded(msg);
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-}
-
-void NuPlayer2::RTSPSource2::onConnected() {
-    CHECK(mAudioTrack == NULL);
-    CHECK(mVideoTrack == NULL);
-
-    size_t numTracks = mHandler->countTracks();
-    for (size_t i = 0; i < numTracks; ++i) {
-        int32_t timeScale;
-        sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
-
-        const char *mime;
-        CHECK(format->findCString(kKeyMIMEType, &mime));
-
-        if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
-            // Very special case for MPEG2 Transport Streams.
-            CHECK_EQ(numTracks, 1u);
-
-            mTSParser = new ATSParser;
-            return;
-        }
-
-        bool isAudio = !strncasecmp(mime, "audio/", 6);
-        bool isVideo = !strncasecmp(mime, "video/", 6);
-
-        TrackInfo info;
-        info.mTimeScale = timeScale;
-        info.mRTPTime = 0;
-        info.mNormalPlaytimeUs = 0LL;
-        info.mNPTMappingValid = false;
-
-        if ((isAudio && mAudioTrack == NULL)
-                || (isVideo && mVideoTrack == NULL)) {
-            sp<AnotherPacketSource> source = new AnotherPacketSource(format);
-
-            if (isAudio) {
-                mAudioTrack = source;
-            } else {
-                mVideoTrack = source;
-            }
-
-            info.mSource = source;
-        }
-
-        mTracks.push(info);
-    }
-
-    mState = CONNECTED;
-}
-
-void NuPlayer2::RTSPSource2::onSDPLoaded(const sp<AMessage> &msg) {
-    status_t err;
-    CHECK(msg->findInt32("result", &err));
-
-    mSDPLoader.clear();
-
-    if (mDisconnectReplyID != 0) {
-        err = UNKNOWN_ERROR;
-    }
-
-    if (err == OK) {
-        sp<ASessionDescription> desc;
-        sp<RefBase> obj;
-        CHECK(msg->findObject("description", &obj));
-        desc = static_cast<ASessionDescription *>(obj.get());
-
-        AString rtspUri;
-        if (!desc->findAttribute(0, "a=control", &rtspUri)) {
-            ALOGE("Unable to find url in SDP");
-            err = UNKNOWN_ERROR;
-        } else {
-            sp<AMessage> notify = new AMessage(kWhatNotify, this);
-
-            mHandler = new MyHandler(rtspUri.c_str(), notify, true /* uidValid */, mUID);
-            mLooper->registerHandler(mHandler);
-
-            mHandler->loadSDP(desc);
-        }
-    }
-
-    if (err != OK) {
-        if (mState == CONNECTING) {
-            // We're still in the preparation phase, signal that it
-            // failed.
-            notifyPrepared(err);
-        }
-
-        mState = DISCONNECTED;
-        setError(err);
-
-        if (mDisconnectReplyID != 0) {
-            finishDisconnectIfPossible();
-        }
-    }
-}
-
-void NuPlayer2::RTSPSource2::onDisconnected(const sp<AMessage> &msg) {
-    if (mState == DISCONNECTED) {
-        return;
-    }
-
-    status_t err;
-    CHECK(msg->findInt32("result", &err));
-    CHECK_NE(err, (status_t)OK);
-
-    mLooper->unregisterHandler(mHandler->id());
-    mHandler.clear();
-
-    if (mState == CONNECTING) {
-        // We're still in the preparation phase, signal that it
-        // failed.
-        notifyPrepared(err);
-    }
-
-    mState = DISCONNECTED;
-    setError(err);
-
-    if (mDisconnectReplyID != 0) {
-        finishDisconnectIfPossible();
-    }
-}
-
-void NuPlayer2::RTSPSource2::finishDisconnectIfPossible() {
-    if (mState != DISCONNECTED) {
-        if (mHandler != NULL) {
-            mHandler->disconnect();
-        } else if (mSDPLoader != NULL) {
-            mSDPLoader->cancel();
-        }
-        return;
-    }
-
-    (new AMessage)->postReply(mDisconnectReplyID);
-    mDisconnectReplyID = 0;
-}
-
-void NuPlayer2::RTSPSource2::setError(status_t err) {
-    Mutex::Autolock _l(mBufferingLock);
-    mFinalResult = err;
-}
-
-void NuPlayer2::RTSPSource2::startBufferingIfNecessary() {
-    Mutex::Autolock _l(mBufferingLock);
-
-    if (!mBuffering) {
-        mBuffering = true;
-
-        sp<AMessage> notify = dupNotify();
-        notify->setInt32("what", kWhatPauseOnBufferingStart);
-        notify->post();
-    }
-}
-
-bool NuPlayer2::RTSPSource2::stopBufferingIfNecessary() {
-    Mutex::Autolock _l(mBufferingLock);
-
-    if (mBuffering) {
-        if (!haveSufficientDataOnAllTracks()) {
-            return false;
-        }
-
-        mBuffering = false;
-
-        sp<AMessage> notify = dupNotify();
-        notify->setInt32("what", kWhatResumeOnBufferingEnd);
-        notify->post();
-    }
-
-    return true;
-}
-
-void NuPlayer2::RTSPSource2::finishSeek(status_t err) {
-    if (mSeekReplyID == NULL) {
-        return;
-    }
-    sp<AMessage> seekReply = new AMessage;
-    seekReply->setInt32("err", err);
-    seekReply->postReply(mSeekReplyID);
-    mSeekReplyID = NULL;
-}
-
-}  // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/RTSPSource2.h b/media/libmediaplayer2/nuplayer2/RTSPSource2.h
deleted file mode 100644
index e5f1716..0000000
--- a/media/libmediaplayer2/nuplayer2/RTSPSource2.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2017 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 RTSP_SOURCE2_H_
-
-#define RTSP_SOURCE2_H_
-
-#include "NuPlayer2Source.h"
-
-#include "ATSParser.h"
-
-namespace android {
-
-struct ALooper;
-struct AReplyToken;
-struct AnotherPacketSource;
-struct MyHandler;
-struct SDPLoader;
-
-struct NuPlayer2::RTSPSource2 : public NuPlayer2::Source {
-    RTSPSource2(
-            const sp<AMessage> &notify,
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers,
-            uid_t uid = 0,
-            bool isSDP = false);
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) override;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
-    virtual void prepareAsync(int64_t startTimeUs);
-    virtual void start();
-    virtual void stop();
-
-    virtual status_t feedMoreTSData();
-
-    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
-
-    virtual status_t getDuration(int64_t *durationUs);
-    virtual status_t seekTo(
-            int64_t seekTimeUs,
-            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
-
-    void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
-    virtual ~RTSPSource2();
-
-    virtual sp<MetaData> getFormatMeta(bool audio);
-
-private:
-    enum {
-        kWhatNotify          = 'noti',
-        kWhatDisconnect      = 'disc',
-        kWhatPerformSeek     = 'seek',
-        kWhatPollBuffering   = 'poll',
-        kWhatSignalEOS       = 'eos ',
-    };
-
-    enum State {
-        DISCONNECTED,
-        CONNECTING,
-        CONNECTED,
-        SEEKING,
-    };
-
-    enum Flags {
-        // Don't log any URLs.
-        kFlagIncognito = 1,
-    };
-
-    struct TrackInfo {
-        sp<AnotherPacketSource> mSource;
-
-        int32_t mTimeScale;
-        uint32_t mRTPTime;
-        int64_t mNormalPlaytimeUs;
-        bool mNPTMappingValid;
-    };
-
-    sp<MediaHTTPService> mHTTPService;
-    AString mURL;
-    KeyedVector<String8, String8> mExtraHeaders;
-    uid_t mUID;
-    uint32_t mFlags;
-    bool mIsSDP;
-    State mState;
-    status_t mFinalResult;
-    sp<AReplyToken> mDisconnectReplyID;
-    Mutex mBufferingLock;
-    bool mBuffering;
-    bool mInPreparationPhase;
-    bool mEOSPending;
-
-    Mutex mBufferingSettingsLock;
-    BufferingSettings mBufferingSettings;
-
-    sp<ALooper> mLooper;
-    sp<MyHandler> mHandler;
-    sp<SDPLoader> mSDPLoader;
-
-    Vector<TrackInfo> mTracks;
-    sp<AnotherPacketSource> mAudioTrack;
-    sp<AnotherPacketSource> mVideoTrack;
-
-    sp<ATSParser> mTSParser;
-
-    int32_t mSeekGeneration;
-
-    int64_t mEOSTimeoutAudio;
-    int64_t mEOSTimeoutVideo;
-
-    sp<AReplyToken> mSeekReplyID;
-
-    sp<AnotherPacketSource> getSource(bool audio);
-
-    void onConnected();
-    void onSDPLoaded(const sp<AMessage> &msg);
-    void onDisconnected(const sp<AMessage> &msg);
-    void finishDisconnectIfPossible();
-
-    void performSeek(int64_t seekTimeUs);
-    void schedulePollBuffering();
-    void checkBuffering(
-            bool *prepared,
-            bool *underflow,
-            bool *overflow,
-            bool *startServer,
-            bool *finished);
-    void onPollBuffering();
-
-    bool haveSufficientDataOnAllTracks();
-
-    void setEOSTimeout(bool audio, int64_t timeout);
-    void setError(status_t err);
-    void startBufferingIfNecessary();
-    bool stopBufferingIfNecessary();
-    void finishSeek(status_t err);
-
-    void postSourceEOSIfNecessary();
-    void signalSourceEOS(status_t result);
-    void onSignalEOS(const sp<AMessage> &msg);
-
-    bool sourceNearEOS(bool audio);
-    bool sourceReachedEOS(bool audio);
-
-    DISALLOW_EVIL_CONSTRUCTORS(RTSPSource2);
-};
-
-}  // namespace android
-
-#endif  // RTSP_SOURCE2_H_
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 6709585..5301f5c 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -7,6 +7,7 @@
         "MediaPlayerService.cpp",
         "MediaRecorderClient.cpp",
         "MetadataRetrieverClient.cpp",
+        "StagefrightMetadataRetriever.cpp",
         "StagefrightRecorder.cpp",
         "TestPlayerStub.cpp",
     ],
@@ -21,11 +22,14 @@
         "libcodec2_client",
         "libcrypto",
         "libcutils",
+        "libdatasource",
         "libdl",
+        "libdrmframework",
         "libgui",
         "libhidlbase",
         "liblog",
         "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmediadrm",
         "libmediametrics",
@@ -44,6 +48,7 @@
     ],
 
     static_libs: [
+        "libplayerservice_datasource",
         "libstagefright_nuplayer",
         "libstagefright_rtsp",
         "libstagefright_timedtext",
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 1376ccc..05f7365 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -20,9 +20,9 @@
 #include <utils/Log.h>
 
 #include <cutils/properties.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/IMediaPlayer.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/Errors.h>
 #include <utils/misc.h>
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dfd3933..c0da0ce 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -48,6 +48,7 @@
 #include <utils/Vector.h>
 
 #include <codec2/hidl/client.h>
+#include <datasource/HTTPBase.h>
 #include <media/IMediaHTTPService.h>
 #include <media/IRemoteDisplay.h>
 #include <media/IRemoteDisplayClient.h>
@@ -56,16 +57,17 @@
 #include <media/MediaMetadataRetrieverInterface.h>
 #include <media/Metadata.h>
 #include <media/AudioTrack.h>
-#include <media/MemoryLeakTrackUtil.h>
 #include <media/stagefright/InterfaceUtils.h>
+#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooperRoster.h>
 #include <media/stagefright/SurfaceUtils.h>
 #include <mediautils/BatteryNotifier.h>
-
+#include <mediautils/MemoryLeakTrackUtil.h>
 #include <memunreachable/memunreachable.h>
 #include <system/audio.h>
 
@@ -80,7 +82,6 @@
 #include "TestPlayerStub.h"
 #include "nuplayer/NuPlayerDriver.h"
 
-#include "HTTPBase.h"
 
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleepUs = 20000;
@@ -264,6 +265,172 @@
     return ok;
 }
 
+static void dumpCodecDetails(int fd, const sp<IMediaCodecList> &codecList, bool queryDecoders) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    const char *codecType = queryDecoders? "Decoder" : "Encoder";
+    snprintf(buffer, SIZE - 1, "\n%s infos by media types:\n"
+             "=============================\n", codecType);
+    result.append(buffer);
+
+    size_t numCodecs = codecList->countCodecs();
+
+    // gather all media types supported by codec class, and link to codecs that support them
+    KeyedVector<AString, Vector<sp<MediaCodecInfo>>> allMediaTypes;
+    for (size_t codec_ix = 0; codec_ix < numCodecs; ++codec_ix) {
+        sp<MediaCodecInfo> info = codecList->getCodecInfo(codec_ix);
+        if (info->isEncoder() == !queryDecoders) {
+            Vector<AString> supportedMediaTypes;
+            info->getSupportedMediaTypes(&supportedMediaTypes);
+            if (!supportedMediaTypes.size()) {
+                snprintf(buffer, SIZE - 1, "warning: %s does not support any media types\n",
+                        info->getCodecName());
+                result.append(buffer);
+            } else {
+                for (const AString &mediaType : supportedMediaTypes) {
+                    if (allMediaTypes.indexOfKey(mediaType) < 0) {
+                        allMediaTypes.add(mediaType, Vector<sp<MediaCodecInfo>>());
+                    }
+                    allMediaTypes.editValueFor(mediaType).add(info);
+                }
+            }
+        }
+    }
+
+    KeyedVector<AString, bool> visitedCodecs;
+    for (size_t type_ix = 0; type_ix < allMediaTypes.size(); ++type_ix) {
+        const AString &mediaType = allMediaTypes.keyAt(type_ix);
+        snprintf(buffer, SIZE - 1, "\nMedia type '%s':\n", mediaType.c_str());
+        result.append(buffer);
+
+        for (const sp<MediaCodecInfo> &info : allMediaTypes.valueAt(type_ix)) {
+            sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(mediaType.c_str());
+            if (caps == NULL) {
+                snprintf(buffer, SIZE - 1, "warning: %s does not have capabilities for type %s\n",
+                        info->getCodecName(), mediaType.c_str());
+                result.append(buffer);
+                continue;
+            }
+            snprintf(buffer, SIZE - 1, "  %s \"%s\" supports\n",
+                       codecType, info->getCodecName());
+            result.append(buffer);
+
+            auto printList = [&](const char *type, const Vector<AString> &values){
+                snprintf(buffer, SIZE - 1, "    %s: [", type);
+                result.append(buffer);
+                for (size_t j = 0; j < values.size(); ++j) {
+                    snprintf(buffer, SIZE - 1, "\n      %s%s", values[j].c_str(),
+                            j == values.size() - 1 ? " " : ",");
+                    result.append(buffer);
+                }
+                result.append("]\n");
+            };
+
+            if (visitedCodecs.indexOfKey(info->getCodecName()) < 0) {
+                visitedCodecs.add(info->getCodecName(), true);
+                {
+                    Vector<AString> aliases;
+                    info->getAliases(&aliases);
+                    // quote alias
+                    for (AString &alias : aliases) {
+                        alias.insert("\"", 1, 0);
+                        alias.append('"');
+                    }
+                    printList("aliases", aliases);
+                }
+                {
+                    uint32_t attrs = info->getAttributes();
+                    Vector<AString> list;
+                    list.add(AStringPrintf("encoder: %d",
+                                           !!(attrs & MediaCodecInfo::kFlagIsEncoder)));
+                    list.add(AStringPrintf("vendor: %d",
+                                           !!(attrs & MediaCodecInfo::kFlagIsVendor)));
+                    list.add(AStringPrintf("software-only: %d",
+                                           !!(attrs & MediaCodecInfo::kFlagIsSoftwareOnly)));
+                    list.add(AStringPrintf("hw-accelerated: %d",
+                                           !!(attrs & MediaCodecInfo::kFlagIsHardwareAccelerated)));
+                    printList(AStringPrintf("attributes: %#x", attrs).c_str(), list);
+                }
+
+                snprintf(buffer, SIZE - 1, "    owner: \"%s\"\n", info->getOwnerName());
+                result.append(buffer);
+                snprintf(buffer, SIZE - 1, "    rank: %u\n", info->getRank());
+                result.append(buffer);
+            } else {
+                result.append("    aliases, attributes, owner, rank: see above\n");
+            }
+
+            {
+                Vector<AString> list;
+                Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+                caps->getSupportedProfileLevels(&profileLevels);
+                for (const MediaCodecInfo::ProfileLevel &pl : profileLevels) {
+                    const char *niceProfile =
+                        mediaType.equalsIgnoreCase(MIMETYPE_AUDIO_AAC)
+                            ? asString_AACObject(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
+                            ? asString_MPEG2Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
+                            ? asString_H263Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
+                            ? asString_MPEG4Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
+                            ? asString_AVCProfile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
+                            ? asString_VP8Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
+                            ? asString_HEVCProfile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
+                            ? asString_VP9Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
+                            ? asString_AV1Profile(pl.mProfile) : "??";
+                    const char *niceLevel =
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
+                            ? asString_MPEG2Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
+                            ? asString_H263Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
+                            ? asString_MPEG4Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
+                            ? asString_AVCLevel(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
+                            ? asString_VP8Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
+                            ? asString_HEVCTierLevel(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
+                            ? asString_VP9Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
+                            ? asString_AV1Level(pl.mLevel) : "??";
+
+                    list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
+                            pl.mProfile, pl.mLevel, niceProfile, niceLevel));
+                }
+                printList("profile/levels", list);
+            }
+
+            {
+                Vector<AString> list;
+                Vector<uint32_t> colors;
+                caps->getSupportedColorFormats(&colors);
+                for (uint32_t color : colors) {
+                    list.add(AStringPrintf("%#x (%s)", color,
+                            asString_ColorFormat((int32_t)color)));
+                }
+                printList("colors", list);
+            }
+
+            result.append("    details: ");
+            result.append(caps->getDetails()->debugString(6).c_str());
+            result.append("\n");
+        }
+    }
+    result.append("\n");
+    ::write(fd, result.string(), result.size());
+}
+
+
 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
 /* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
 /* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
@@ -423,7 +590,7 @@
     SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
 
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        snprintf(buffer, SIZE, "Permission Denial: "
+        snprintf(buffer, SIZE - 1, "Permission Denial: "
                 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
@@ -452,11 +619,11 @@
         }
 
         result.append(" Files opened and/or mapped:\n");
-        snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+        snprintf(buffer, SIZE - 1, "/proc/%d/maps", getpid());
         FILE *f = fopen(buffer, "r");
         if (f) {
             while (!feof(f)) {
-                fgets(buffer, SIZE, f);
+                fgets(buffer, SIZE - 1, f);
                 if (strstr(buffer, " /storage/") ||
                     strstr(buffer, " /system/sounds/") ||
                     strstr(buffer, " /data/") ||
@@ -472,13 +639,13 @@
             result.append("\n");
         }
 
-        snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+        snprintf(buffer, SIZE - 1, "/proc/%d/fd", getpid());
         DIR *d = opendir(buffer);
         if (d) {
             struct dirent *ent;
             while((ent = readdir(d)) != NULL) {
                 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
-                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+                    snprintf(buffer, SIZE - 1, "/proc/%d/fd/%s", getpid(), ent->d_name);
                     struct stat s;
                     if (lstat(buffer, &s) == 0) {
                         if ((s.st_mode & S_IFMT) == S_IFLNK) {
@@ -521,6 +688,10 @@
 
         gLooperRoster.dump(fd, args);
 
+        sp<IMediaCodecList> codecList = getCodecList();
+        dumpCodecDetails(fd, codecList, true /* decoders */);
+        dumpCodecDetails(fd, codecList, false /* !decoders */);
+
         bool dumpMem = false;
         bool unreachableMemory = false;
         for (size_t i = 0; i < args.size(); i++) {
@@ -543,6 +714,7 @@
         }
     }
     write(fd, result.string(), result.size());
+
     return NO_ERROR;
 }
 
@@ -2034,7 +2206,9 @@
                     targetSpeed,
                     mSelectedDeviceId);
         }
-
+        // Set caller name so it can be logged in destructor.
+        // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
+        t->setCallerName("media");
         if ((t == 0) || (t->initCheck() != NO_ERROR)) {
             ALOGE("Unable to create audio track");
             delete newcbd;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 49688ce..6431ca1 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -26,15 +26,17 @@
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
+#include <media/AudioResamplerPublic.h>
+#include <media/AudioSystem.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/Metadata.h>
 #include <media/stagefright/foundation/ABase.h>
 
+
 #include <system/audio.h>
 
 namespace android {
 
-struct AudioPlaybackRate;
 class AudioTrack;
 struct AVSyncSettings;
 class DeathNotifier;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 703da4b..9b1974b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -32,6 +32,7 @@
 #include <cutils/atomic.h>
 #include <cutils/properties.h> // for property_get
 #include <gui/IGraphicBufferProducer.h>
+#include <mediautils/ServiceUtilities.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <system/audio.h>
@@ -44,7 +45,6 @@
 namespace android {
 
 const char* cameraPermission = "android.permission.CAMERA";
-const char* recordAudioPermission = "android.permission.RECORD_AUDIO";
 
 static bool checkPermission(const char* permissionString) {
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
@@ -118,7 +118,16 @@
 status_t MediaRecorderClient::setAudioSource(int as)
 {
     ALOGV("setAudioSource(%d)", as);
-    if (!checkPermission(recordAudioPermission)) {
+    if (as < AUDIO_SOURCE_DEFAULT
+            || (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
+        ALOGE("Invalid audio source: %d", as);
+        return BAD_VALUE;
+    }
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+
+    if ((as == AUDIO_SOURCE_FM_TUNER && !captureAudioOutputAllowed(pid, uid))
+            || !recordingAllowed(String16(""), pid, uid)) {
         return PERMISSION_DENIED;
     }
     Mutex::Autolock lock(mLock);
@@ -129,6 +138,29 @@
     return mRecorder->setAudioSource((audio_source_t)as);
 }
 
+status_t MediaRecorderClient::setPrivacySensitive(bool privacySensitive)
+{
+    ALOGV("%s(%s)", __func__, privacySensitive ? "true" : "false");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        ALOGE("%s: recorder is not initialized", __func__);
+        return NO_INIT;
+    }
+    return mRecorder->setPrivacySensitive(privacySensitive);
+}
+
+status_t MediaRecorderClient::isPrivacySensitive(bool *privacySensitive) const
+{
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        ALOGE("%s: recorder is not initialized", __func__);
+        return NO_INIT;
+    }
+    status_t status = mRecorder->isPrivacySensitive(privacySensitive);
+    ALOGV("%s: status: %d enabled: %s", __func__, status, *privacySensitive ? "true" : "false");
+    return status;
+}
+
 status_t MediaRecorderClient::setOutputFormat(int of)
 {
     ALOGV("setOutputFormat(%d)", of);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 9e0f877..12257e5 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -51,6 +51,8 @@
     virtual     status_t   setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
     virtual     status_t   setVideoSource(int vs);
     virtual     status_t   setAudioSource(int as);
+                status_t   setPrivacySensitive(bool privacySensitive) override;
+                status_t   isPrivacySensitive(bool *privacySensitive) const override;
     virtual     status_t   setOutputFormat(int of);
     virtual     status_t   setVideoEncoder(int ve);
     virtual     status_t   setAudioEncoder(int ae);
@@ -98,7 +100,7 @@
     sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
 
     pid_t                  mPid;
-    Mutex                  mLock;
+    mutable Mutex          mLock;
     MediaRecorderBase      *mRecorder;
     sp<MediaPlayerService> mMediaPlayerService;
 };
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 40b17bf..fb228ca 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,6 +37,7 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <private/media/VideoFrame.h>
 #include "MetadataRetrieverClient.h"
 #include "StagefrightMetadataRetriever.h"
@@ -242,31 +243,27 @@
     sp<IMemory> frame = mRetriever->getImageRectAtIndex(
             index, colorFormat, left, top, right, bottom);
     if (frame == NULL) {
-        ALOGE("failed to extract image");
-        return NULL;
+        ALOGE("failed to extract image at index %d", index);
     }
     return frame;
 }
 
-status_t MetadataRetrieverClient::getFrameAtIndex(
-            std::vector<sp<IMemory> > *frames,
-            int frameIndex, int numFrames, int colorFormat, bool metaOnly) {
-    ALOGV("getFrameAtIndex: frameIndex(%d), numFrames(%d), colorFormat(%d), metaOnly(%d)",
-            frameIndex, numFrames, colorFormat, metaOnly);
+sp<IMemory> MetadataRetrieverClient::getFrameAtIndex(
+            int index, int colorFormat, bool metaOnly) {
+    ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
+            index, colorFormat, metaOnly);
     Mutex::Autolock lock(mLock);
     Mutex::Autolock glock(sLock);
     if (mRetriever == NULL) {
         ALOGE("retriever is not initialized");
-        return INVALID_OPERATION;
+        return NULL;
     }
 
-    status_t err = mRetriever->getFrameAtIndex(
-            frames, frameIndex, numFrames, colorFormat, metaOnly);
-    if (err != OK) {
-        frames->clear();
-        return err;
+    sp<IMemory> frame = mRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
+    if (frame == NULL) {
+        ALOGE("failed to extract frame at index %d", index);
     }
-    return OK;
+    return frame;
 }
 
 sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
@@ -296,7 +293,7 @@
         delete albumArt;
         return NULL;
     }
-    MediaAlbumArt::init((MediaAlbumArt *) mAlbumArt->pointer(),
+    MediaAlbumArt::init((MediaAlbumArt *) mAlbumArt->unsecurePointer(),
                         albumArt->size(), albumArt->data());
     delete albumArt;  // We've taken our copy.
     return mAlbumArt;
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 272d093..8020441 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -56,9 +56,8 @@
             int index, int colorFormat, bool metaOnly, bool thumbnail);
     virtual sp<IMemory>             getImageRectAtIndex(
             int index, int colorFormat, int left, int top, int right, int bottom);
-    virtual status_t getFrameAtIndex(
-                std::vector<sp<IMemory> > *frames,
-                int frameIndex, int numFrames, int colorFormat, bool metaOnly);
+    virtual sp<IMemory>             getFrameAtIndex(
+            int index, int colorFormat, bool metaOnly);
     virtual sp<IMemory>             extractAlbumArt();
     virtual const char*             extractMetadata(int keyCode);
 
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
new file mode 100644
index 0000000..41b6f72
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2009 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 "StagefrightMetadataRetriever"
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <cutils/properties.h>
+
+#include "StagefrightMetadataRetriever.h"
+#include "FrameDecoder.h"
+
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <media/IMediaHTTPService.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <media/CharacterEncodingDetector.h>
+
+namespace android {
+
+StagefrightMetadataRetriever::StagefrightMetadataRetriever()
+    : mParsedMetaData(false),
+      mAlbumArt(NULL),
+      mLastDecodedIndex(-1) {
+    ALOGV("StagefrightMetadataRetriever()");
+}
+
+StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
+    ALOGV("~StagefrightMetadataRetriever()");
+    clearMetadata();
+    if (mSource != NULL) {
+        mSource->close();
+    }
+}
+
+status_t StagefrightMetadataRetriever::setDataSource(
+        const sp<IMediaHTTPService> &httpService,
+        const char *uri,
+        const KeyedVector<String8, String8> *headers) {
+    ALOGV("setDataSource(%s)", uri);
+
+    clearMetadata();
+    mSource = PlayerServiceDataSourceFactory::getInstance()->CreateFromURI(
+            httpService, uri, headers);
+
+    if (mSource == NULL) {
+        ALOGE("Unable to create data source for '%s'.", uri);
+        return UNKNOWN_ERROR;
+    }
+
+    mExtractor = MediaExtractorFactory::Create(mSource);
+
+    if (mExtractor == NULL) {
+        ALOGE("Unable to instantiate an extractor for '%s'.", uri);
+
+        mSource.clear();
+
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
+status_t StagefrightMetadataRetriever::setDataSource(
+        int fd, int64_t offset, int64_t length) {
+    fd = dup(fd);
+
+    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
+
+    clearMetadata();
+    mSource = new PlayerServiceFileSource(fd, offset, length);
+
+    status_t err;
+    if ((err = mSource->initCheck()) != OK) {
+        mSource.clear();
+
+        return err;
+    }
+
+    mExtractor = MediaExtractorFactory::Create(mSource);
+
+    if (mExtractor == NULL) {
+        mSource.clear();
+
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+status_t StagefrightMetadataRetriever::setDataSource(
+        const sp<DataSource>& source, const char *mime) {
+    ALOGV("setDataSource(DataSource)");
+
+    clearMetadata();
+    mSource = source;
+    mExtractor = MediaExtractorFactory::Create(mSource, mime);
+
+    if (mExtractor == NULL) {
+        ALOGE("Failed to instantiate a MediaExtractor.");
+        mSource.clear();
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getImageAtIndex(
+        int index, int colorFormat, bool metaOnly, bool thumbnail) {
+    ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
+            index, colorFormat, metaOnly, thumbnail);
+
+    return getImageInternal(index, colorFormat, metaOnly, thumbnail, NULL);
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getImageRectAtIndex(
+        int index, int colorFormat, int left, int top, int right, int bottom) {
+    ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d) rect {%d, %d, %d, %d}",
+            index, colorFormat, left, top, right, bottom);
+
+    FrameRect rect = {left, top, right, bottom};
+
+    if (mDecoder != NULL && index == mLastDecodedIndex) {
+        return mDecoder->extractFrame(&rect);
+    }
+
+    return getImageInternal(
+            index, colorFormat, false /*metaOnly*/, false /*thumbnail*/, &rect);
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getImageInternal(
+        int index, int colorFormat, bool metaOnly, bool thumbnail, FrameRect* rect) {
+    mDecoder.clear();
+    mLastDecodedIndex = -1;
+
+    if (mExtractor.get() == NULL) {
+        ALOGE("no extractor.");
+        return NULL;
+    }
+
+    size_t n = mExtractor->countTracks();
+    size_t i;
+    int imageCount = 0;
+
+    for (i = 0; i < n; ++i) {
+        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
+        if (!meta) {
+            continue;
+        }
+        ALOGV("getting track %zu of %zu, meta=%s", i, n, meta->toString().c_str());
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!strncasecmp(mime, "image/", 6)) {
+            int32_t isPrimary;
+            if ((index < 0 && meta->findInt32(
+                    kKeyTrackIsDefault, &isPrimary) && isPrimary)
+                    || (index == imageCount++)) {
+                break;
+            }
+        }
+    }
+
+    if (i == n) {
+        ALOGE("image track not found.");
+        return NULL;
+    }
+
+    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
+    if (!trackMeta) {
+        return NULL;
+    }
+
+    if (metaOnly) {
+        return FrameDecoder::getMetadataOnly(trackMeta, colorFormat, thumbnail);
+    }
+
+    sp<IMediaSource> source = mExtractor->getTrack(i);
+
+    if (source.get() == NULL) {
+        ALOGE("unable to instantiate image track.");
+        return NULL;
+    }
+
+    const char *mime;
+    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+    ALOGV("extracting from %s track", mime);
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
+        mime = MEDIA_MIMETYPE_VIDEO_HEVC;
+        trackMeta = new MetaData(*trackMeta);
+        trackMeta->setCString(kKeyMIMEType, mime);
+    }
+
+    bool preferhw = property_get_bool(
+            "media.stagefright.thumbnail.prefer_hw_codecs", false);
+    uint32_t flags = preferhw ? 0 : MediaCodecList::kPreferSoftwareCodecs;
+    Vector<AString> matchingCodecs;
+    MediaCodecList::findMatchingCodecs(
+            mime,
+            false, /* encoder */
+            flags,
+            &matchingCodecs);
+
+    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+        const AString &componentName = matchingCodecs[i];
+        sp<ImageDecoder> decoder = new ImageDecoder(componentName, trackMeta, source);
+        int64_t frameTimeUs = thumbnail ? -1 : 0;
+        if (decoder->init(frameTimeUs, 0 /*option*/, colorFormat) == OK) {
+            sp<IMemory> frame = decoder->extractFrame(rect);
+
+            if (frame != NULL) {
+                if (rect != NULL) {
+                    // keep the decoder if slice decoding
+                    mDecoder = decoder;
+                    mLastDecodedIndex = index;
+                }
+                return frame;
+            }
+        }
+        ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str());
+    }
+
+    ALOGE("all codecs failed to extract frame.");
+    return NULL;
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getFrameAtTime(
+        int64_t timeUs, int option, int colorFormat, bool metaOnly) {
+    ALOGV("getFrameAtTime: %" PRId64 " us option: %d colorFormat: %d, metaOnly: %d",
+            timeUs, option, colorFormat, metaOnly);
+
+    return getFrameInternal(timeUs, option, colorFormat, metaOnly);
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getFrameAtIndex(
+        int frameIndex, int colorFormat, bool metaOnly) {
+    ALOGV("getFrameAtIndex: frameIndex %d, colorFormat: %d, metaOnly: %d",
+            frameIndex, colorFormat, metaOnly);
+    if (mDecoder != NULL && frameIndex == mLastDecodedIndex + 1) {
+        sp<IMemory> frame = mDecoder->extractFrame();
+        if (frame != nullptr) {
+            mLastDecodedIndex = frameIndex;
+        }
+        return frame;
+    }
+
+    return getFrameInternal(frameIndex,
+            MediaSource::ReadOptions::SEEK_FRAME_INDEX, colorFormat, metaOnly);
+}
+
+sp<IMemory> StagefrightMetadataRetriever::getFrameInternal(
+        int64_t timeUs, int option, int colorFormat, bool metaOnly) {
+    mDecoder.clear();
+    mLastDecodedIndex = -1;
+
+    if (mExtractor.get() == NULL) {
+        ALOGE("no extractor.");
+        return NULL;
+    }
+
+    sp<MetaData> fileMeta = mExtractor->getMetaData();
+
+    if (fileMeta == NULL) {
+        ALOGE("extractor doesn't publish metadata, failed to initialize?");
+        return NULL;
+    }
+
+    size_t n = mExtractor->countTracks();
+    size_t i;
+    for (i = 0; i < n; ++i) {
+        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
+        if (!meta) {
+            continue;
+        }
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!strncasecmp(mime, "video/", 6)) {
+            break;
+        }
+    }
+
+    if (i == n) {
+        ALOGE("no video track found.");
+        return NULL;
+    }
+
+    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
+            i, MediaExtractor::kIncludeExtensiveMetaData);
+    if (!trackMeta) {
+        return NULL;
+    }
+
+    if (metaOnly) {
+        return FrameDecoder::getMetadataOnly(trackMeta, colorFormat);
+    }
+
+    sp<IMediaSource> source = mExtractor->getTrack(i);
+
+    if (source.get() == NULL) {
+        ALOGV("unable to instantiate video track.");
+        return NULL;
+    }
+
+    const void *data;
+    uint32_t type;
+    size_t dataSize;
+    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
+            && mAlbumArt == NULL) {
+        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
+    }
+
+    const char *mime;
+    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+
+    bool preferhw = property_get_bool(
+            "media.stagefright.thumbnail.prefer_hw_codecs", false);
+    uint32_t flags = preferhw ? 0 : MediaCodecList::kPreferSoftwareCodecs;
+    Vector<AString> matchingCodecs;
+    MediaCodecList::findMatchingCodecs(
+            mime,
+            false, /* encoder */
+            flags,
+            &matchingCodecs);
+
+    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+        const AString &componentName = matchingCodecs[i];
+        sp<VideoFrameDecoder> decoder = new VideoFrameDecoder(componentName, trackMeta, source);
+        if (decoder->init(timeUs, option, colorFormat) == OK) {
+            sp<IMemory> frame = decoder->extractFrame();
+            if (frame != nullptr) {
+                // keep the decoder if seeking by frame index
+                if (option == MediaSource::ReadOptions::SEEK_FRAME_INDEX) {
+                    mDecoder = decoder;
+                    mLastDecodedIndex = timeUs;
+                }
+                return frame;
+            }
+        }
+        ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str());
+    }
+
+    ALOGE("all codecs failed to extract frame.");
+    return NULL;
+}
+
+MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
+    ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
+
+    if (mExtractor == NULL) {
+        return NULL;
+    }
+
+    if (!mParsedMetaData) {
+        parseMetaData();
+
+        mParsedMetaData = true;
+    }
+
+    if (mAlbumArt) {
+        return mAlbumArt->clone();
+    }
+
+    return NULL;
+}
+
+const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
+    if (mExtractor == NULL) {
+        return NULL;
+    }
+
+    if (!mParsedMetaData) {
+        parseMetaData();
+
+        mParsedMetaData = true;
+    }
+
+    ssize_t index = mMetaData.indexOfKey(keyCode);
+
+    if (index < 0) {
+        return NULL;
+    }
+
+    return mMetaData.valueAt(index).string();
+}
+
+void StagefrightMetadataRetriever::parseColorAspects(const sp<MetaData>& meta) {
+    sp<AMessage> format = new AMessage();
+    if (convertMetaDataToMessage(meta, &format) != OK) {
+        return;
+    }
+
+    int32_t standard, transfer, range;
+    if (format->findInt32("color-standard", &standard)
+            && format->findInt32("color-transfer", &transfer)
+            && format->findInt32("color-range", &range)) {
+        ALOGV("found color aspects : standard=%d, transfer=%d, range=%d",
+                standard, transfer, range);
+
+        mMetaData.add(METADATA_KEY_COLOR_STANDARD, String8::format("%d", standard));
+        mMetaData.add(METADATA_KEY_COLOR_TRANSFER, String8::format("%d", transfer));
+        mMetaData.add(METADATA_KEY_COLOR_RANGE, String8::format("%d", range));
+    }
+}
+
+void StagefrightMetadataRetriever::parseMetaData() {
+    sp<MetaData> meta = mExtractor->getMetaData();
+
+    if (meta == NULL) {
+        ALOGV("extractor doesn't publish metadata, failed to initialize?");
+        return;
+    }
+
+    struct Map {
+        int from;
+        int to;
+        const char *name;
+    };
+    static const Map kMap[] = {
+        { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL },
+        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" },
+        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" },
+        { kKeyAlbum, METADATA_KEY_ALBUM, "album" },
+        { kKeyArtist, METADATA_KEY_ARTIST, "artist" },
+        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" },
+        { kKeyAuthor, METADATA_KEY_AUTHOR, NULL },
+        { kKeyComposer, METADATA_KEY_COMPOSER, "composer" },
+        { kKeyDate, METADATA_KEY_DATE, NULL },
+        { kKeyGenre, METADATA_KEY_GENRE, "genre" },
+        { kKeyTitle, METADATA_KEY_TITLE, "title" },
+        { kKeyYear, METADATA_KEY_YEAR, "year" },
+        { kKeyWriter, METADATA_KEY_WRITER, "writer" },
+        { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" },
+        { kKeyLocation, METADATA_KEY_LOCATION, NULL },
+    };
+
+    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
+
+    CharacterEncodingDetector *detector = new CharacterEncodingDetector();
+
+    for (size_t i = 0; i < kNumMapEntries; ++i) {
+        const char *value;
+        if (meta->findCString(kMap[i].from, &value)) {
+            if (kMap[i].name) {
+                // add to charset detector
+                detector->addTag(kMap[i].name, value);
+            } else {
+                // directly add to output list
+                mMetaData.add(kMap[i].to, String8(value));
+            }
+        }
+    }
+
+    detector->detectAndConvert();
+    int size = detector->size();
+    if (size) {
+        for (int i = 0; i < size; i++) {
+            const char *name;
+            const char *value;
+            detector->getTag(i, &name, &value);
+            for (size_t j = 0; j < kNumMapEntries; ++j) {
+                if (kMap[j].name && !strcmp(kMap[j].name, name)) {
+                    mMetaData.add(kMap[j].to, String8(value));
+                }
+            }
+        }
+    }
+    delete detector;
+
+    const void *data;
+    uint32_t type;
+    size_t dataSize;
+    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
+            && mAlbumArt == NULL) {
+        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
+    }
+
+    size_t numTracks = mExtractor->countTracks();
+
+    char tmp[32];
+    sprintf(tmp, "%zu", numTracks);
+
+    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
+
+    float captureFps;
+    if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) {
+        sprintf(tmp, "%f", captureFps);
+        mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp));
+    }
+
+    int64_t exifOffset, exifSize;
+    if (meta->findInt64(kKeyExifOffset, &exifOffset)
+     && meta->findInt64(kKeyExifSize, &exifSize)) {
+        sprintf(tmp, "%lld", (long long)exifOffset);
+        mMetaData.add(METADATA_KEY_EXIF_OFFSET, String8(tmp));
+        sprintf(tmp, "%lld", (long long)exifSize);
+        mMetaData.add(METADATA_KEY_EXIF_LENGTH, String8(tmp));
+    }
+
+    bool hasAudio = false;
+    bool hasVideo = false;
+    int32_t videoWidth = -1;
+    int32_t videoHeight = -1;
+    int32_t videoFrameCount = 0;
+    int32_t audioBitrate = -1;
+    int32_t rotationAngle = -1;
+    int32_t imageCount = 0;
+    int32_t imagePrimary = 0;
+    int32_t imageWidth = -1;
+    int32_t imageHeight = -1;
+    int32_t imageRotation = -1;
+
+    // The overall duration is the duration of the longest track.
+    int64_t maxDurationUs = 0;
+    String8 timedTextLang;
+    for (size_t i = 0; i < numTracks; ++i) {
+        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
+        if (!trackMeta) {
+            continue;
+        }
+
+        int64_t durationUs;
+        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
+            if (durationUs > maxDurationUs) {
+                maxDurationUs = durationUs;
+            }
+        }
+
+        const char *mime;
+        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+                hasAudio = true;
+
+                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+                    audioBitrate = -1;
+                }
+
+                int32_t bitsPerSample = -1;
+                int32_t sampleRate = -1;
+                trackMeta->findInt32(kKeyBitsPerSample, &bitsPerSample);
+                trackMeta->findInt32(kKeySampleRate, &sampleRate);
+                if (bitsPerSample >= 0) {
+                    sprintf(tmp, "%d", bitsPerSample);
+                    mMetaData.add(METADATA_KEY_BITS_PER_SAMPLE, String8(tmp));
+                }
+                if (sampleRate >= 0) {
+                    sprintf(tmp, "%d", sampleRate);
+                    mMetaData.add(METADATA_KEY_SAMPLERATE, String8(tmp));
+                }
+            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+                hasVideo = true;
+
+                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+                if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
+                    rotationAngle = 0;
+                }
+                if (!trackMeta->findInt32(kKeyFrameCount, &videoFrameCount)) {
+                    videoFrameCount = 0;
+                }
+
+                parseColorAspects(trackMeta);
+            } else if (!strncasecmp("image/", mime, 6)) {
+                int32_t isPrimary;
+                if (trackMeta->findInt32(
+                        kKeyTrackIsDefault, &isPrimary) && isPrimary) {
+                    imagePrimary = imageCount;
+                    CHECK(trackMeta->findInt32(kKeyWidth, &imageWidth));
+                    CHECK(trackMeta->findInt32(kKeyHeight, &imageHeight));
+                    if (!trackMeta->findInt32(kKeyRotation, &imageRotation)) {
+                        imageRotation = 0;
+                    }
+                }
+                imageCount++;
+            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+                const char *lang;
+                if (trackMeta->findCString(kKeyMediaLanguage, &lang)) {
+                    timedTextLang.append(String8(lang));
+                    timedTextLang.append(String8(":"));
+                } else {
+                    ALOGE("No language found for timed text");
+                }
+            }
+        }
+    }
+
+    // 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()) {
+        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
+    }
+
+    // The duration value is a string representing the duration in ms.
+    sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000);
+    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
+
+    if (hasAudio) {
+        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+    }
+
+    if (hasVideo) {
+        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+        sprintf(tmp, "%d", videoWidth);
+        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+        sprintf(tmp, "%d", videoHeight);
+        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+
+        sprintf(tmp, "%d", rotationAngle);
+        mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp));
+
+        if (videoFrameCount > 0) {
+            sprintf(tmp, "%d", videoFrameCount);
+            mMetaData.add(METADATA_KEY_VIDEO_FRAME_COUNT, String8(tmp));
+        }
+    }
+
+    if (imageCount > 0) {
+        mMetaData.add(METADATA_KEY_HAS_IMAGE, String8("yes"));
+
+        sprintf(tmp, "%d", imageCount);
+        mMetaData.add(METADATA_KEY_IMAGE_COUNT, String8(tmp));
+
+        sprintf(tmp, "%d", imagePrimary);
+        mMetaData.add(METADATA_KEY_IMAGE_PRIMARY, String8(tmp));
+
+        sprintf(tmp, "%d", imageWidth);
+        mMetaData.add(METADATA_KEY_IMAGE_WIDTH, String8(tmp));
+
+        sprintf(tmp, "%d", imageHeight);
+        mMetaData.add(METADATA_KEY_IMAGE_HEIGHT, String8(tmp));
+
+        sprintf(tmp, "%d", imageRotation);
+        mMetaData.add(METADATA_KEY_IMAGE_ROTATION, String8(tmp));
+    }
+
+    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+        sprintf(tmp, "%d", audioBitrate);
+        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+    } else {
+        off64_t sourceSize;
+        if (mSource != NULL && mSource->getSize(&sourceSize) == OK) {
+            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+            sprintf(tmp, "%" PRId64, avgBitRate);
+            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+        }
+    }
+
+    if (numTracks == 1) {
+        const char *fileMIME;
+
+        if (meta->findCString(kKeyMIMEType, &fileMIME) &&
+                !strcasecmp(fileMIME, "video/x-matroska")) {
+            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
+            const char *trackMIME;
+            if (trackMeta != nullptr) {
+                CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
+            }
+            if (!strncasecmp("audio/", trackMIME, 6)) {
+                // The matroska file only contains a single audio track,
+                // rewrite its mime type.
+                mMetaData.add(
+                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
+            }
+        }
+    }
+}
+
+void StagefrightMetadataRetriever::clearMetadata() {
+    mParsedMetaData = false;
+    mMetaData.clear();
+    delete mAlbumArt;
+    mAlbumArt = NULL;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.h b/media/libmediaplayerservice/StagefrightMetadataRetriever.h
new file mode 100644
index 0000000..c09a501
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 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 STAGEFRIGHT_METADATA_RETRIEVER_H_
+
+#define STAGEFRIGHT_METADATA_RETRIEVER_H_
+
+#include <android/IMediaExtractor.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+class DataSource;
+struct FrameDecoder;
+struct FrameRect;
+
+struct StagefrightMetadataRetriever : public MediaMetadataRetrieverBase {
+    StagefrightMetadataRetriever();
+    virtual ~StagefrightMetadataRetriever();
+
+    virtual status_t setDataSource(
+            const sp<IMediaHTTPService> &httpService,
+            const char *url,
+            const KeyedVector<String8, String8> *headers);
+
+    virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t setDataSource(const sp<DataSource>& source, const char *mime);
+
+    virtual sp<IMemory> getFrameAtTime(
+            int64_t timeUs, int option, int colorFormat, bool metaOnly);
+    virtual sp<IMemory> getImageAtIndex(
+            int index, int colorFormat, bool metaOnly, bool thumbnail);
+    virtual sp<IMemory> getImageRectAtIndex(
+            int index, int colorFormat, int left, int top, int right, int bottom);
+    virtual sp<IMemory> getFrameAtIndex(
+            int index, int colorFormat, bool metaOnly);
+
+    virtual MediaAlbumArt *extractAlbumArt();
+    virtual const char *extractMetadata(int keyCode);
+
+private:
+    sp<DataSource> mSource;
+    sp<IMediaExtractor> mExtractor;
+
+    bool mParsedMetaData;
+    KeyedVector<int, String8> mMetaData;
+    MediaAlbumArt *mAlbumArt;
+
+    sp<FrameDecoder> mDecoder;
+    int mLastDecodedIndex;
+    void parseMetaData();
+    void parseColorAspects(const sp<MetaData>& meta);
+    // Delete album art and clear metadata.
+    void clearMetadata();
+
+    sp<IMemory> getFrameInternal(
+            int64_t timeUs, int option, int colorFormat, bool metaOnly);
+
+    sp<IMemory> getImageInternal(
+            int index, int colorFormat, bool metaOnly, bool thumbnail, FrameRect* rect);
+
+    StagefrightMetadataRetriever(const StagefrightMetadataRetriever &);
+
+    StagefrightMetadataRetriever &operator=(
+            const StagefrightMetadataRetriever &);
+};
+
+}  // namespace android
+
+#endif  // STAGEFRIGHT_METADATA_RETRIEVER_H_
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 63681fa..7897959 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -31,7 +31,7 @@
 #include <binder/IServiceManager.h>
 
 #include <media/IMediaPlayerService.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -115,6 +115,7 @@
       mWriter(NULL),
       mOutputFd(-1),
       mAudioSource((audio_source_t)AUDIO_SOURCE_CNT), // initialize with invalid value
+      mPrivacySensitive(PRIVACY_SENSITIVE_DEFAULT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mStarted(false),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
@@ -137,7 +138,7 @@
     }
 
     // log the current record, provided it has some information worth recording
-    // NB: this also reclaims & clears mAnalyticsItem.
+    // NB: this also reclaims & clears mMetricsItem.
     flushAndResetMetrics(false);
 }
 
@@ -146,69 +147,69 @@
 
     // we run as part of the media player service; what we really want to
     // know is the app which requested the recording.
-    mAnalyticsItem->setUid(mClientUid);
+    mMetricsItem->setUid(mClientUid);
 
     // populate the values from the raw fields.
 
     // TBD mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
     // TBD mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
     // TBD mVideoEncoder  = VIDEO_ENCODER_DEFAULT;
-    mAnalyticsItem->setInt32(kRecorderHeight, mVideoHeight);
-    mAnalyticsItem->setInt32(kRecorderWidth, mVideoWidth);
-    mAnalyticsItem->setInt32(kRecorderFrameRate, mFrameRate);
-    mAnalyticsItem->setInt32(kRecorderVideoBitrate, mVideoBitRate);
-    mAnalyticsItem->setInt32(kRecorderAudioSampleRate, mSampleRate);
-    mAnalyticsItem->setInt32(kRecorderAudioChannels, mAudioChannels);
-    mAnalyticsItem->setInt32(kRecorderAudioBitrate, mAudioBitRate);
+    mMetricsItem->setInt32(kRecorderHeight, mVideoHeight);
+    mMetricsItem->setInt32(kRecorderWidth, mVideoWidth);
+    mMetricsItem->setInt32(kRecorderFrameRate, mFrameRate);
+    mMetricsItem->setInt32(kRecorderVideoBitrate, mVideoBitRate);
+    mMetricsItem->setInt32(kRecorderAudioSampleRate, mSampleRate);
+    mMetricsItem->setInt32(kRecorderAudioChannels, mAudioChannels);
+    mMetricsItem->setInt32(kRecorderAudioBitrate, mAudioBitRate);
     // TBD mInterleaveDurationUs = 0;
-    mAnalyticsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
+    mMetricsItem->setInt32(kRecorderVideoIframeInterval, mIFramesIntervalSec);
     // TBD mAudioSourceNode = 0;
     // TBD mUse64BitFileOffset = false;
     if (mMovieTimeScale != -1)
-        mAnalyticsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
+        mMetricsItem->setInt32(kRecorderMovieTimescale, mMovieTimeScale);
     if (mAudioTimeScale != -1)
-        mAnalyticsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
+        mMetricsItem->setInt32(kRecorderAudioTimescale, mAudioTimeScale);
     if (mVideoTimeScale != -1)
-        mAnalyticsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
+        mMetricsItem->setInt32(kRecorderVideoTimescale, mVideoTimeScale);
     // TBD mCameraId        = 0;
     // TBD mStartTimeOffsetMs = -1;
-    mAnalyticsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
-    mAnalyticsItem->setInt32(kRecorderVideoLevel, mVideoEncoderLevel);
+    mMetricsItem->setInt32(kRecorderVideoProfile, mVideoEncoderProfile);
+    mMetricsItem->setInt32(kRecorderVideoLevel, mVideoEncoderLevel);
     // TBD mMaxFileDurationUs = 0;
     // TBD mMaxFileSizeBytes = 0;
     // TBD mTrackEveryTimeDurationUs = 0;
-    mAnalyticsItem->setInt32(kRecorderCaptureFpsEnable, mCaptureFpsEnable);
-    mAnalyticsItem->setDouble(kRecorderCaptureFps, mCaptureFps);
+    mMetricsItem->setInt32(kRecorderCaptureFpsEnable, mCaptureFpsEnable);
+    mMetricsItem->setDouble(kRecorderCaptureFps, mCaptureFps);
     // TBD mCameraSourceTimeLapse = NULL;
     // TBD mMetaDataStoredInVideoBuffers = kMetadataBufferTypeInvalid;
     // TBD mEncoderProfiles = MediaProfiles::getInstance();
-    mAnalyticsItem->setInt32(kRecorderRotation, mRotationDegrees);
+    mMetricsItem->setInt32(kRecorderRotation, mRotationDegrees);
     // PII mLatitudex10000 = -3600000;
     // PII mLongitudex10000 = -3600000;
     // TBD mTotalBitRate = 0;
 
     // duration information (recorded, paused, # of pauses)
-    mAnalyticsItem->setInt64(kRecorderDurationMs, (mDurationRecordedUs+500)/1000 );
+    mMetricsItem->setInt64(kRecorderDurationMs, (mDurationRecordedUs+500)/1000 );
     if (mNPauses != 0) {
-        mAnalyticsItem->setInt64(kRecorderPaused, (mDurationPausedUs+500)/1000 );
-        mAnalyticsItem->setInt32(kRecorderNumPauses, mNPauses);
+        mMetricsItem->setInt64(kRecorderPaused, (mDurationPausedUs+500)/1000 );
+        mMetricsItem->setInt32(kRecorderNumPauses, mNPauses);
     }
 }
 
 void StagefrightRecorder::flushAndResetMetrics(bool reinitialize) {
     ALOGV("flushAndResetMetrics");
     // flush anything we have, maybe setup a new record
-    if (mAnalyticsDirty && mAnalyticsItem != NULL) {
+    if (mAnalyticsDirty && mMetricsItem != NULL) {
         updateMetrics();
-        if (mAnalyticsItem->count() > 0) {
-            mAnalyticsItem->selfrecord();
+        if (mMetricsItem->count() > 0) {
+            mMetricsItem->selfrecord();
         }
-        delete mAnalyticsItem;
-        mAnalyticsItem = NULL;
+        delete mMetricsItem;
+        mMetricsItem = NULL;
     }
     mAnalyticsDirty = false;
     if (reinitialize) {
-        mAnalyticsItem = MediaAnalyticsItem::create(kKeyRecorder);
+        mMetricsItem = mediametrics::Item::create(kKeyRecorder);
     }
 }
 
@@ -232,18 +233,37 @@
 
 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
     ALOGV("setAudioSource: %d", as);
-    if (as < AUDIO_SOURCE_DEFAULT ||
-        (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
-        ALOGE("Invalid audio source: %d", as);
-        return BAD_VALUE;
-    }
 
     if (as == AUDIO_SOURCE_DEFAULT) {
         mAudioSource = AUDIO_SOURCE_MIC;
     } else {
         mAudioSource = as;
     }
+    // Reset privacy sensitive in case this is the second time audio source is set
+    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
+    return OK;
+}
 
+status_t StagefrightRecorder::setPrivacySensitive(bool privacySensitive) {
+    // privacy sensitive cannot be set before audio source is set
+    if (mAudioSource == AUDIO_SOURCE_CNT) {
+        return INVALID_OPERATION;
+    }
+    mPrivacySensitive = privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
+    return OK;
+}
+
+status_t StagefrightRecorder::isPrivacySensitive(bool *privacySensitive) const {
+    *privacySensitive = false;
+    if (mAudioSource == AUDIO_SOURCE_CNT) {
+        return INVALID_OPERATION;
+    }
+    if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
+         *privacySensitive = mAudioSource == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || mAudioSource == AUDIO_SOURCE_CAMCORDER;
+    } else {
+        *privacySensitive = mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED;
+    }
     return OK;
 }
 
@@ -1087,9 +1107,35 @@
         }
     }
 
+    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+    attr.source = mAudioSource;
+    // attr.flags AUDIO_FLAG_CAPTURE_PRIVATE is cleared by default
+    if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
+        if (attr.source == AUDIO_SOURCE_VOICE_COMMUNICATION
+                || attr.source == AUDIO_SOURCE_CAMCORDER) {
+            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+            mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
+        } else {
+            mPrivacySensitive = PRIVACY_SENSITIVE_DISABLED;
+        }
+    } else {
+        if (mAudioSource == AUDIO_SOURCE_REMOTE_SUBMIX
+                || mAudioSource == AUDIO_SOURCE_FM_TUNER
+                || mAudioSource == AUDIO_SOURCE_VOICE_DOWNLINK
+                || mAudioSource == AUDIO_SOURCE_VOICE_UPLINK
+                || mAudioSource == AUDIO_SOURCE_VOICE_CALL
+                || mAudioSource == AUDIO_SOURCE_ECHO_REFERENCE) {
+            ALOGE("Cannot request private capture with source: %d", mAudioSource);
+            return NULL;
+        }
+        if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
+            attr.flags |= AUDIO_FLAG_CAPTURE_PRIVATE;
+        }
+    }
+
     sp<AudioSource> audioSource =
         new AudioSource(
-                mAudioSource,
+                &attr,
                 mOpPackageName,
                 sourceSampleRate,
                 mAudioChannels,
@@ -1138,10 +1184,10 @@
     }
 
     // log audio mime type for media metrics
-    if (mAnalyticsItem != NULL) {
+    if (mMetricsItem != NULL) {
         AString audiomime;
         if (format->findString("mime", &audiomime)) {
-            mAnalyticsItem->setCString(kRecorderAudioMime, audiomime.c_str());
+            mMetricsItem->setCString(kRecorderAudioMime, audiomime.c_str());
         }
     }
 
@@ -1699,10 +1745,10 @@
     }
 
     // log video mime type for media metrics
-    if (mAnalyticsItem != NULL) {
+    if (mMetricsItem != NULL) {
         AString videomime;
         if (format->findString("mime", &videomime)) {
-            mAnalyticsItem->setCString(kRecorderVideoMime, videomime.c_str());
+            mMetricsItem->setCString(kRecorderVideoMime, videomime.c_str());
         }
     }
 
@@ -1956,7 +2002,6 @@
         (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
     }
     if (mOutputFormat != OUTPUT_FORMAT_WEBM) {
-        (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
         if (mTrackEveryTimeDurationUs > 0) {
             (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
         }
@@ -1964,6 +2009,10 @@
             (*meta)->setInt32(kKeyRotation, mRotationDegrees);
         }
     }
+    if (mOutputFormat == OUTPUT_FORMAT_MPEG_4 || mOutputFormat == OUTPUT_FORMAT_THREE_GPP) {
+        (*meta)->setInt32(kKeyEmptyTrackMalFormed, true);
+        (*meta)->setInt32(kKey4BitTrackIds, true);
+    }
 }
 
 status_t StagefrightRecorder::pause() {
@@ -2220,12 +2269,12 @@
         return BAD_VALUE;
     }
 
-    if (mAnalyticsItem == NULL) {
+    if (mMetricsItem == NULL) {
         return UNKNOWN_ERROR;
     }
 
     updateMetrics();
-    mAnalyticsItem->writeToParcel(reply);
+    mMetricsItem->writeToParcel(reply);
     return OK;
 }
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 8bf083a..a725bee 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -18,7 +18,7 @@
 
 #define STAGEFRIGHT_RECORDER_H_
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/MediaRecorderBase.h>
 #include <camera/CameraParameters.h>
 #include <utils/String8.h>
@@ -46,6 +46,8 @@
     virtual ~StagefrightRecorder();
     virtual status_t init();
     virtual status_t setAudioSource(audio_source_t as);
+            status_t setPrivacySensitive(bool privacySensitive) override;
+            status_t isPrivacySensitive(bool *privacySensitive) const override;
     virtual status_t setVideoSource(video_source vs);
     virtual status_t setOutputFormat(output_format of);
     virtual status_t setAudioEncoder(audio_encoder ae);
@@ -82,6 +84,13 @@
             status_t getPortId(audio_port_handle_t *portId) const override;
 
 private:
+
+    enum privacy_sensitive_t {
+        PRIVACY_SENSITIVE_DEFAULT = -1,
+        PRIVACY_SENSITIVE_DISABLED = 0,
+        PRIVACY_SENSITIVE_ENABLED = 1,
+    };
+
     mutable Mutex mLock;
     sp<hardware::ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
@@ -95,12 +104,13 @@
     int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
-    MediaAnalyticsItem *mAnalyticsItem;
+    mediametrics::Item *mMetricsItem;
     bool mAnalyticsDirty;
     void flushAndResetMetrics(bool reinitialize);
     void updateMetrics();
 
     audio_source_t mAudioSource;
+    privacy_sensitive_t mPrivacySensitive;
     video_source mVideoSource;
     output_format mOutputFormat;
     audio_encoder mAudioEncoder;
diff --git a/media/libmediaplayerservice/datasource/Android.bp b/media/libmediaplayerservice/datasource/Android.bp
new file mode 100644
index 0000000..71fa50b
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/Android.bp
@@ -0,0 +1,43 @@
+cc_library_static {
+    name: "libplayerservice_datasource",
+
+    srcs: [
+        "PlayerServiceDataSourceFactory.cpp",
+        "PlayerServiceFileSource.cpp",
+        "PlayerServiceMediaHTTP.cpp",
+    ],
+
+    header_libs: [
+        "media_ndk_headers",
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "libdatasource",
+        "libdrmframework",
+        "liblog",
+        "libutils",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
new file mode 100644
index 0000000..ef946e9
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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 "PlayerServuceDataSourceFactory"
+
+
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/PlayerServiceMediaHTTP.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::sInstance;
+// static
+Mutex PlayerServiceDataSourceFactory::sInstanceLock;
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new PlayerServiceDataSourceFactory();
+    }
+    return sInstance;
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateMediaHTTP(
+        const sp<MediaHTTPService> &httpService) {
+    if (httpService == NULL) {
+        return NULL;
+    }
+
+    sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
+    if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
+        return NULL;
+    } else {
+        return new PlayerServiceMediaHTTP(conn);
+    }
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateFileSource(const char *uri) {
+    return new PlayerServiceFileSource(uri);
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
new file mode 100644
index 0000000..4d95de5
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009 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 "PlayerServiceFileSource"
+#include <utils/Log.h>
+
+#include <datasource/PlayerServiceFileSource.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+PlayerServiceFileSource::PlayerServiceFileSource(const char *filename)
+    : FileSource(filename),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL),
+      mDrmBufOffset(0),
+      mDrmBufSize(0),
+      mDrmBuf(NULL){
+    (void) DrmInitialization(nullptr);
+}
+
+PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
+    : FileSource(fd, offset, length),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL),
+      mDrmBufOffset(0),
+      mDrmBufSize(0),
+      mDrmBuf(NULL) {
+    (void) DrmInitialization(nullptr);
+}
+
+PlayerServiceFileSource::~PlayerServiceFileSource() {
+    if (mDrmBuf != NULL) {
+        delete[] mDrmBuf;
+        mDrmBuf = NULL;
+    }
+
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+
+    if (mDrmManagerClient != NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+}
+
+ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) {
+    if (mFd < 0) {
+        return NO_INIT;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (mLength >= 0) {
+        if (offset < 0) {
+            return UNKNOWN_ERROR;
+        }
+        if (offset >= mLength) {
+            return 0;  // read beyond EOF.
+        }
+        uint64_t numAvailable = mLength - offset;
+        if ((uint64_t)size > numAvailable) {
+            size = numAvailable;
+        }
+    }
+
+    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
+            == mDecryptHandle->decryptApiType) {
+        return readAtDRM_l(offset, data, size);
+   } else {
+        return readAt_l(offset, data, size);
+    }
+}
+
+sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
+    if (getuid() == AID_MEDIA_EX) {
+       return NULL; // no DRM in media extractor
+    }
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                mFd, mOffset, mLength, mime);
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
+    size_t DRM_CACHE_SIZE = 1024;
+    if (mDrmBuf == NULL) {
+        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
+    }
+
+    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
+            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
+        /* Use buffered data */
+        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
+        return size;
+    } else if (size <= DRM_CACHE_SIZE) {
+        /* Buffer new data */
+        mDrmBufOffset =  offset + mOffset;
+        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
+                DRM_CACHE_SIZE, offset + mOffset);
+        if (mDrmBufSize > 0) {
+            int64_t dataRead = 0;
+            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
+            memcpy(data, (void*)mDrmBuf, dataRead);
+            return dataRead;
+        } else {
+            return mDrmBufSize;
+        }
+    } else {
+        /* Too big chunk to cache. Call DRM directly */
+        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
+    }
+}
+
+/* static */
+bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
+    std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
+    sp<DecryptHandle> decryptHandle =
+            drmClient->openDecryptSession(fd, offset, length, mime);
+    bool requiresDrm = false;
+    if (decryptHandle != nullptr) {
+        requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
+        drmClient->closeDecryptSession(decryptHandle);
+    }
+    return requiresDrm;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
new file mode 100644
index 0000000..f99a861
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 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 "PlayerServiceMediaHTTP"
+#include <utils/Log.h>
+
+#include <datasource/PlayerServiceMediaHTTP.h>
+
+#include <binder/IServiceManager.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/FoundationUtils.h>
+
+#include <media/MediaHTTPConnection.h>
+
+namespace android {
+
+PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
+    : MediaHTTP(conn),
+      mDrmManagerClient(NULL) {
+    (void) DrmInitialization(nullptr);
+}
+
+PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
+    clearDRMState_l();
+}
+
+// DRM...
+
+sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char *mime) {
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                String8(mLastURI.c_str()), mime);
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+void PlayerServiceMediaHTTP::clearDRMState_l() {
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
new file mode 100644
index 0000000..7d58c5c
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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 PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#define PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#include <datasource/DataSourceFactory.h>
+#include <media/DataSource.h>
+#include <sys/types.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaHTTPService;
+class String8;
+struct HTTPBase;
+
+class PlayerServiceDataSourceFactory : public DataSourceFactory {
+public:
+    static sp<PlayerServiceDataSourceFactory> getInstance();
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+
+private:
+    static sp<PlayerServiceDataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
+    PlayerServiceDataSourceFactory() {};
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
new file mode 100644
index 0000000..7ae8dda
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2009 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 PLAYER_SERVICE_FILE_SOURCE_H_
+
+#define PLAYER_SERVICE_FILE_SOURCE_H_
+
+#include <stdio.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+// FileSource implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) files.
+class PlayerServiceFileSource : public FileSource {
+public:
+    PlayerServiceFileSource(const char *filename);
+    // PlayerServiceFileSource takes ownership and will close the fd
+    PlayerServiceFileSource(int fd, int64_t offset, int64_t length);
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+    static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
+
+protected:
+    virtual ~PlayerServiceFileSource();
+
+private:
+    /*for DRM*/
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+    int64_t mDrmBufOffset;
+    ssize_t mDrmBufSize;
+    unsigned char *mDrmBuf;
+
+    sp<DecryptHandle> DrmInitialization(const char *mime);
+    ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
+
+    PlayerServiceFileSource(const PlayerServiceFileSource &);
+    PlayerServiceFileSource &operator=(const PlayerServiceFileSource &);
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_FILE_SOURCE_H_
+
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
new file mode 100644
index 0000000..2f94ada
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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 PLAYER_SERVICE_MEDIA_HTTP_H_
+
+#define PLAYER_SERVICE_MEDIA_HTTP_H_
+
+#include <datasource/MediaHTTP.h>
+#include <drm/DrmManagerClient.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+struct MediaHTTPConnection;
+
+// MediaHTTP implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) stream.
+struct PlayerServiceMediaHTTP : public MediaHTTP {
+    PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn);
+
+protected:
+    virtual ~PlayerServiceMediaHTTP();
+
+private:
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+
+    sp<DecryptHandle> DrmInitialization(const char *mime);
+    void clearDRMState_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP);
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_MEDIA_HTTP_H_
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index 0ad4d04..436cb31 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -27,7 +27,6 @@
 
 #include <media/mediaplayer.h>
 #include <media/AudioResamplerPublic.h>
-#include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
 #include <media/AVSyncSettings.h>
 #include <media/BufferingSettings.h>
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 23a19e7..32c97cf 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -18,6 +18,8 @@
     ],
 
     header_libs: [
+        "libmediadrm_headers",
+        "libmediametrics_headers",
         "media_plugin_headers",
     ],
 
@@ -45,6 +47,7 @@
 
     shared_libs: [
         "libbinder",
+        "libdatasource",
         "libui",
         "libgui",
         "libmedia",
@@ -52,6 +55,10 @@
         "libpowermanager",
     ],
 
+    static_libs: [
+        "libplayerservice_datasource",
+    ],
+
     name: "libstagefright_nuplayer",
 
     sanitize: {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 4653711..439dbe8 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -23,17 +23,20 @@
 #include "AnotherPacketSource.h"
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/NuCachedSource2.h>
 #include <media/DataSource.h>
 #include <media/MediaBufferHolder.h>
-#include <media/MediaSource.h>
-#include <media/IMediaExtractorService.h>
+#include <media/stagefright/MediaSource.h>
+#include <android/IMediaExtractorService.h>
 #include <media/IMediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/InterfaceUtils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MediaDefs.h>
@@ -41,8 +44,6 @@
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
-#include "../../libstagefright/include/NuCachedSource2.h"
-#include "../../libstagefright/include/HTTPBase.h"
 
 namespace android {
 
@@ -75,7 +76,6 @@
       mUIDValid(uidValid),
       mUID(uid),
       mMediaClock(mediaClock),
-      mFd(-1),
       mBitrate(-1LL),
       mPendingReadBufferTypes(0) {
     ALOGV("GenericSource");
@@ -98,10 +98,7 @@
     mUri.clear();
     mUriHeaders.clear();
     mSources.clear();
-    if (mFd >= 0) {
-        close(mFd);
-        mFd = -1;
-    }
+    mFd.reset();
     mOffset = 0;
     mLength = 0;
     mStarted = false;
@@ -137,11 +134,11 @@
 status_t NuPlayer::GenericSource::setDataSource(
         int fd, int64_t offset, int64_t length) {
     Mutex::Autolock _l(mLock);
-    ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
+    ALOGV("setDataSource %d/%lld/%lld (%s)", fd, (long long)offset, (long long)length, nameForFd(fd).c_str());
 
     resetDataSource();
 
-    mFd = dup(fd);
+    mFd.reset(dup(fd));
     mOffset = offset;
     mLength = length;
 
@@ -385,7 +382,8 @@
             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
                 sp<DataSource> httpSource;
                 mDisconnectLock.unlock();
-                httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
+                httpSource = PlayerServiceDataSourceFactory::getInstance()
+                        ->CreateMediaHTTP(mHTTPService);
                 if (httpSource == NULL) {
                     ALOGE("Failed to create http source!");
                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
@@ -401,9 +399,9 @@
             mLock.unlock();
             mDisconnectLock.unlock();
             // This might take long time if connection has some issue.
-            sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
-                   mHTTPService, uri, &mUriHeaders, &contentType,
-                   static_cast<HTTPBase *>(mHttpSource.get()));
+            sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
+                    ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
+                            static_cast<HTTPBase *>(mHttpSource.get()));
             mDisconnectLock.lock();
             mLock.lock();
             if (!mDisconnected) {
@@ -411,24 +409,20 @@
             }
         } else {
             if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+                    !PlayerServiceFileSource::requiresDrm(
+                            mFd.get(), mOffset, mLength, nullptr /* mime */)) {
                 sp<IBinder> binder =
                         defaultServiceManager()->getService(String16("media.extractor"));
                 if (binder != nullptr) {
                     ALOGD("FileSource remote");
                     sp<IMediaExtractorService> mediaExService(
                             interface_cast<IMediaExtractorService>(binder));
-                    sp<IDataSource> source =
-                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
+                    sp<IDataSource> source;
+                    mediaExService->makeIDataSource(base::unique_fd(dup(mFd.get())), mOffset, mLength, &source);
                     ALOGV("IDataSource(FileSource): %p %d %lld %lld",
-                            source.get(), mFd, (long long)mOffset, (long long)mLength);
+                            source.get(), mFd.get(), (long long)mOffset, (long long)mLength);
                     if (source.get() != nullptr) {
                         mDataSource = CreateDataSourceFromIDataSource(source);
-                        if (mDataSource != nullptr) {
-                            // Close the local file descriptor as it is not needed anymore.
-                            close(mFd);
-                            mFd = -1;
-                        }
                     } else {
                         ALOGW("extractor service cannot make data source");
                     }
@@ -438,12 +432,8 @@
             }
             if (mDataSource == nullptr) {
                 ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
+                mDataSource = new PlayerServiceFileSource(dup(mFd.get()), mOffset, mLength);
             }
-            // TODO: close should always be done on mFd, see the lines following
-            // CreateDataSourceFromIDataSource above,
-            // and the FileSource constructor should dup the mFd argument as needed.
-            mFd = -1;
         }
 
         if (mDataSource == NULL) {
@@ -782,7 +772,7 @@
         return;
     }
 
-    int64_t nextSubTimeUs;
+    int64_t nextSubTimeUs = 0;
     readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
 
     sp<ABuffer> buffer;
@@ -1169,7 +1159,7 @@
         readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
 
         if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
-            seekTimeUs = actualTimeUs;
+            seekTimeUs = std::max<int64_t>(0, actualTimeUs);
         }
         mVideoLastDequeueTimeUs = actualTimeUs;
     }
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 4d1905d..7a2ab8f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -23,6 +23,7 @@
 
 #include "ATSParser.h"
 
+#include <android-base/unique_fd.h>
 #include <media/mediaplayer.h>
 #include <media/stagefright/MediaBuffer.h>
 
@@ -154,7 +155,7 @@
     sp<IMediaHTTPService> mHTTPService;
     AString mUri;
     KeyedVector<String8, String8> mUriHeaders;
-    int mFd;
+    base::unique_fd mFd;
     int64_t mOffset;
     int64_t mLength;
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 3388097..c1c4b55 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1798,7 +1798,9 @@
 }
 
 void NuPlayer::closeAudioSink() {
-    mRenderer->closeAudioSink();
+    if (mRenderer != NULL) {
+        mRenderer->closeAudioSink();
+    }
 }
 
 void NuPlayer::restartAudio(
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 9f5be06..ef4354c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -19,7 +19,7 @@
 #define NU_PLAYER_H_
 
 #include <media/AudioResamplerPublic.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/foundation/AHandler.h>
 
@@ -27,7 +27,6 @@
 
 struct ABuffer;
 struct AMessage;
-struct AudioPlaybackRate;
 struct AVSyncSettings;
 class IDataSource;
 struct MediaClock;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2f0da2d..f734439 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -28,7 +28,7 @@
 #include "NuPlayerSource.h"
 
 #include <cutils/properties.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaBufferHolder.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -106,16 +106,17 @@
     releaseAndResetMediaBuffers();
 }
 
-sp<AMessage> NuPlayer::Decoder::getStats() const {
+sp<AMessage> NuPlayer::Decoder::getStats() {
 
+    Mutex::Autolock autolock(mStatsLock);
     mStats->setInt64("frames-total", mNumFramesTotal);
     mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
     mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
     mStats->setFloat("frame-rate-total", mFrameRateTotal);
 
-    // i'm mutexed right now.
     // make our own copy, so we aren't victim to any later changes.
     sp<AMessage> copiedStats = mStats->dup();
+
     return copiedStats;
 }
 
@@ -362,13 +363,17 @@
     CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
     CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
 
-    mStats->setString("mime", mime.c_str());
-    mStats->setString("component-name", mComponentName.c_str());
+    {
+        Mutex::Autolock autolock(mStatsLock);
+        mStats->setString("mime", mime.c_str());
+        mStats->setString("component-name", mComponentName.c_str());
+    }
 
     if (!mIsAudio) {
         int32_t width, height;
         if (mOutputFormat->findInt32("width", &width)
                 && mOutputFormat->findInt32("height", &height)) {
+            Mutex::Autolock autolock(mStatsLock);
             mStats->setInt32("width", width);
             mStats->setInt32("height", height);
         }
@@ -799,6 +804,7 @@
         int32_t width, height;
         if (format->findInt32("width", &width)
                 && format->findInt32("height", &height)) {
+            Mutex::Autolock autolock(mStatsLock);
             mStats->setInt32("width", width);
             mStats->setInt32("height", height);
         }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 3da2f0b..4a52b0c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -34,7 +34,7 @@
             const sp<Surface> &surface = NULL,
             const sp<CCDecoder> &ccDecoder = NULL);
 
-    virtual sp<AMessage> getStats() const;
+    virtual sp<AMessage> getStats();
 
     // sets the output surface of video decoders.
     virtual status_t setVideoSurface(const sp<Surface> &surface);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
index d44c396..a3e0046 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -47,7 +47,7 @@
     void signalResume(bool notifyComplete);
     void initiateShutdown();
 
-    virtual sp<AMessage> getStats() const {
+    virtual sp<AMessage> getStats() {
         return mStats;
     }
 
@@ -88,6 +88,7 @@
     int32_t mBufferGeneration;
     bool mPaused;
     sp<AMessage> mStats;
+    Mutex mStatsLock;
 
 private:
     enum {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index 0997e7d..793014e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -24,7 +24,7 @@
 #include "NuPlayerRenderer.h"
 #include "NuPlayerSource.h"
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 000881b..dc144b2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -33,8 +33,7 @@
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
-
-#include <media/IMediaAnalyticsService.h>
+#include <media/stagefright/FoundationUtils.h>
 
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleepUs = 20000;
@@ -86,7 +85,7 @@
       mMediaClock(new MediaClock),
       mPlayer(new NuPlayer(pid, mMediaClock)),
       mPlayerFlags(0),
-      mAnalyticsItem(NULL),
+      mMetricsItem(NULL),
       mClientUid(-1),
       mAtEOS(false),
       mLooping(false),
@@ -97,7 +96,7 @@
     mMediaClock->init();
 
     // set up an analytics record
-    mAnalyticsItem = MediaAnalyticsItem::create(kKeyPlayer);
+    mMetricsItem = mediametrics::Item::create(kKeyPlayer);
 
     mLooper->start(
             false, /* runOnCallingThread */
@@ -118,9 +117,9 @@
     logMetrics("destructor");
 
     Mutex::Autolock autoLock(mMetricsLock);
-    if (mAnalyticsItem != NULL) {
-        delete mAnalyticsItem;
-        mAnalyticsItem = NULL;
+    if (mMetricsItem != NULL) {
+        delete mMetricsItem;
+        mMetricsItem = NULL;
     }
 }
 
@@ -133,8 +132,8 @@
     mClientUid = uid;
 
     Mutex::Autolock autoLock(mMetricsLock);
-    if (mAnalyticsItem) {
-        mAnalyticsItem->setUid(mClientUid);
+    if (mMetricsItem) {
+        mMetricsItem->setUid(mClientUid);
     }
 
     return OK;
@@ -546,7 +545,9 @@
     }
     ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
 
-    // gather the final track statistics for this record
+    // avoid nested locks by gathering our data outside of the metrics lock.
+
+    // final track statistics for this record
     Vector<sp<AMessage>> trackStats;
     mPlayer->getStats(&trackStats);
 
@@ -569,22 +570,24 @@
         rebufferingAtExit = mRebufferingAtExit;
     }
 
-    // finish the rest of the gathering holding mLock;
+    // finish the rest of the gathering under our mutex to avoid metrics races.
     // some of the fields we read are updated under mLock.
-    // we also avoid any races within mAnalyticsItem machinery
     Mutex::Autolock autoLock(mMetricsLock);
 
-    mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
+    if (mMetricsItem == NULL) {
+        return;
+    }
 
-    mAnalyticsItem->setInt64(kPlayerPlaying, (playingTimeUs+500)/1000 );
+    mMetricsItem->setInt64(kPlayerDuration, duration_ms);
+    mMetricsItem->setInt64(kPlayerPlaying, (playingTimeUs+500)/1000 );
 
-    if (mRebufferingEvents != 0) {
-        mAnalyticsItem->setInt64(kPlayerRebuffering, (rebufferingTimeUs+500)/1000 );
-        mAnalyticsItem->setInt32(kPlayerRebufferingCount, rebufferingEvents);
-        mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, rebufferingAtExit);
-     }
+    if (rebufferingEvents != 0) {
+        mMetricsItem->setInt64(kPlayerRebuffering, (rebufferingTimeUs+500)/1000 );
+        mMetricsItem->setInt32(kPlayerRebufferingCount, rebufferingEvents);
+        mMetricsItem->setInt32(kPlayerRebufferingAtExit, rebufferingAtExit);
+    }
 
-    mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
+    mMetricsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
 
     if (trackStats.size() > 0) {
         for (size_t i = 0; i < trackStats.size(); ++i) {
@@ -598,15 +601,15 @@
 
             if (mime.startsWith("video/")) {
                 int32_t width, height;
-                mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
+                mMetricsItem->setCString(kPlayerVMime, mime.c_str());
                 if (!name.empty()) {
-                    mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
+                    mMetricsItem->setCString(kPlayerVCodec, name.c_str());
                 }
 
                 if (stats->findInt32("width", &width)
                         && stats->findInt32("height", &height)) {
-                    mAnalyticsItem->setInt32(kPlayerWidth, width);
-                    mAnalyticsItem->setInt32(kPlayerHeight, height);
+                    mMetricsItem->setInt32(kPlayerWidth, width);
+                    mMetricsItem->setInt32(kPlayerHeight, height);
                 }
 
                 int64_t numFramesTotal = 0;
@@ -614,18 +617,18 @@
                 stats->findInt64("frames-total", &numFramesTotal);
                 stats->findInt64("frames-dropped-output", &numFramesDropped);
 
-                mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
-                mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
+                mMetricsItem->setInt64(kPlayerFrames, numFramesTotal);
+                mMetricsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
 
                 float frameRate = 0;
                 if (stats->findFloat("frame-rate-total", &frameRate)) {
-                    mAnalyticsItem->setDouble(kPlayerFrameRate, (double) frameRate);
+                    mMetricsItem->setDouble(kPlayerFrameRate, (double) frameRate);
                 }
 
             } else if (mime.startsWith("audio/")) {
-                mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
+                mMetricsItem->setCString(kPlayerAMime, mime.c_str());
                 if (!name.empty()) {
-                    mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
+                    mMetricsItem->setCString(kPlayerACodec, name.c_str());
                 }
             }
         }
@@ -639,10 +642,10 @@
     }
     ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
 
-    // make sure that the stats are stable while we're writing them.
+    // ensure mMetricsItem stability while we write it out
     Mutex::Autolock autoLock(mMetricsLock);
 
-    if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
+    if (mMetricsItem == NULL || mMetricsItem->isEnabled() == false) {
         return;
     }
 
@@ -651,18 +654,18 @@
     // and that always injects 3 fields (duration, playing time, and
     // datasource) into the record.
     // So the canonical "empty" record has 3 elements in it.
-    if (mAnalyticsItem->count() > 3) {
+    if (mMetricsItem->count() > 3) {
 
-        mAnalyticsItem->selfrecord();
+        mMetricsItem->selfrecord();
 
         // re-init in case we prepare() and start() again.
-        delete mAnalyticsItem ;
-        mAnalyticsItem = MediaAnalyticsItem::create(kKeyPlayer);
-        if (mAnalyticsItem) {
-            mAnalyticsItem->setUid(mClientUid);
+        delete mMetricsItem ;
+        mMetricsItem = mediametrics::Item::create(kKeyPlayer);
+        if (mMetricsItem) {
+            mMetricsItem->setUid(mClientUid);
         }
     } else {
-        ALOGV("nothing to record (only %d fields)", mAnalyticsItem->count());
+        ALOGV("nothing to record (only %zu fields)", mMetricsItem->count());
     }
 }
 
@@ -805,10 +808,10 @@
         // gather current info all together, parcel it, and send it back
         updateMetrics("api");
 
-        // ensure mAnalyticsItem stability while writing to parcel
+        // ensure mMetricsItem stability while writing to parcel
         Mutex::Autolock autoLock(mMetricsLock);
-        if (mAnalyticsItem != NULL) {
-            mAnalyticsItem->writeToParcel(reply);
+        if (mMetricsItem != NULL) {
+            mMetricsItem->writeToParcel(reply);
         }
         return OK;
     }
@@ -1035,12 +1038,12 @@
             // [test against msg is due to fall through from previous switch value]
             if (msg == MEDIA_ERROR) {
                 Mutex::Autolock autoLock(mMetricsLock);
-                if (mAnalyticsItem != NULL) {
-                    mAnalyticsItem->setInt32(kPlayerError, ext1);
+                if (mMetricsItem != NULL) {
+                    mMetricsItem->setInt32(kPlayerError, ext1);
                     if (ext2 != 0) {
-                        mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
+                        mMetricsItem->setInt32(kPlayerErrorCode, ext2);
                     }
-                    mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
+                    mMetricsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
                 }
             }
             mAtEOS = true;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 37c53b0..f4b1968 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -16,7 +16,7 @@
 
 #include <media/MediaPlayerInterface.h>
 
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/stagefright/foundation/ABase.h>
 
 namespace android {
@@ -141,7 +141,7 @@
     sp<AudioSink> mAudioSink;
     uint32_t mPlayerFlags;
 
-    MediaAnalyticsItem *mAnalyticsItem;
+    mediametrics::Item *mMetricsItem;
     mutable Mutex mMetricsLock;
     uid_t mClientUid;
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 2d0c9e0..6788b56 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -19,8 +19,7 @@
 
 #include "NuPlayerDrm.h"
 
-#include <binder/IServiceManager.h>
-#include <mediadrm/IMediaDrmService.h>
+#include <mediadrm/DrmUtils.h>
 #include <utils/Log.h>
 
 
@@ -30,60 +29,13 @@
 
 sp<IDrm> NuPlayerDrm::CreateDrm(status_t *pstatus)
 {
-    status_t &status = *pstatus;
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.drm"));
-    ALOGV("CreateDrm binder %p", (binder != NULL ? binder.get() : 0));
-
-    sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
-    if (service == NULL) {
-        ALOGE("CreateDrm failed at IMediaDrmService");
-        return NULL;
-    }
-
-    sp<IDrm> drm = service->makeDrm();
-    if (drm == NULL) {
-        ALOGE("CreateDrm failed at makeDrm");
-        return NULL;
-    }
-
-    // this is before plugin creation so NO_INIT is fine
-    status = drm->initCheck();
-    if (status != OK && status != NO_INIT) {
-        ALOGE("CreateDrm failed drm->initCheck(): %d", status);
-        return NULL;
-    }
-    return drm;
+    return DrmUtils::MakeDrm(pstatus);
 }
 
 sp<ICrypto> NuPlayerDrm::createCrypto(status_t *pstatus)
 {
-    status_t &status = *pstatus;
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.drm"));
 
-    sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
-    if (service == NULL) {
-        status = UNKNOWN_ERROR;
-        ALOGE("CreateCrypto failed at IMediaDrmService");
-        return NULL;
-    }
-
-    sp<ICrypto> crypto = service->makeCrypto();
-    if (crypto == NULL) {
-        status = UNKNOWN_ERROR;
-        ALOGE("createCrypto failed");
-        return NULL;
-    }
-
-    // this is before plugin creation so NO_INIT is fine
-    status = crypto->initCheck();
-    if (status != OK && status != NO_INIT) {
-        ALOGE("createCrypto failed crypto->initCheck(): %d", status);
-        return NULL;
-    }
-
-    return crypto;
+    return DrmUtils::MakeCrypto(pstatus);
 }
 
 Vector<DrmUUID> NuPlayerDrm::parsePSSH(const void *pssh, size_t psshsize)
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
index 50f69ff..4360656 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
@@ -18,8 +18,8 @@
 #define NUPLAYER_DRM_H_
 
 #include <binder/Parcel.h>
-#include <media/ICrypto.h>
-#include <media/IDrm.h>
+#include <mediadrm/ICrypto.h>
+#include <mediadrm/IDrm.h>
 #include <media/stagefright/MetaData.h> // for CryptInfo
 
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 39be40d..c30f048 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -33,6 +33,7 @@
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/VideoFrameScheduler.h>
 #include <media/MediaCodecBuffer.h>
+#include <utils/SystemClock.h>
 
 #include <inttypes.h>
 
@@ -156,6 +157,7 @@
     CHECK(mediaClock != NULL);
     mPlaybackRate = mPlaybackSettings.mSpeed;
     mMediaClock->setPlaybackRate(mPlaybackRate);
+    (void)mSyncFlag.test_and_set();
 }
 
 NuPlayer::Renderer::~Renderer() {
@@ -326,9 +328,27 @@
         mSyncQueues = false;
     }
 
+    // Wait until the current job in the message queue is done, to make sure
+    // buffer processing from the old generation is finished. After the current
+    // job is finished, access to buffers are protected by generation.
+    Mutex::Autolock syncLock(mSyncLock);
+    int64_t syncCount = mSyncCount;
+    mSyncFlag.clear();
+
+    // Make sure message queue is not empty after mSyncFlag is cleared.
     sp<AMessage> msg = new AMessage(kWhatFlush, this);
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->post();
+
+    int64_t uptimeMs = uptimeMillis();
+    while (mSyncCount == syncCount) {
+        (void)mSyncCondition.waitRelative(mSyncLock, ms2ns(1000));
+        if (uptimeMillis() - uptimeMs > 1000) {
+            ALOGW("flush(): no wake-up from sync point for 1s; stop waiting to "
+                  "prevent being stuck indefinitely.");
+            break;
+        }
+    }
 }
 
 void NuPlayer::Renderer::signalTimeDiscontinuity() {
@@ -781,6 +801,11 @@
             TRESPASS();
             break;
     }
+    if (!mSyncFlag.test_and_set()) {
+        Mutex::Autolock syncLock(mSyncLock);
+        ++mSyncCount;
+        mSyncCondition.broadcast();
+    }
 }
 
 void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index a521f62..3d2b033 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -18,6 +18,8 @@
 
 #define NUPLAYER_RENDERER_H_
 
+#include <atomic>
+
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
 
@@ -220,6 +222,11 @@
 
     sp<AWakeLock> mWakeLock;
 
+    std::atomic_flag mSyncFlag = ATOMIC_FLAG_INIT;
+    Mutex mSyncLock;
+    Condition mSyncCondition;
+    int64_t mSyncCount{0};
+
     status_t getCurrentPositionOnLooper(int64_t *mediaUs);
     status_t getCurrentPositionOnLooper(
             int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 9f5ef78..f137c52 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -20,7 +20,7 @@
 
 #include "NuPlayer.h"
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MetaData.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index 7dcee72..a532603 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -152,7 +152,7 @@
     }
 
     memcpy(data,
-           (const uint8_t *)mem->pointer()
+           (const uint8_t *)mem->unsecurePointer()
             + entry->mOffset,
            copy);
 
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index bf14ec2..83da092 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -144,6 +144,10 @@
     if (mLooper == NULL) {
         return;
     }
+
+    // Close socket before posting message to RTSPSource message handler.
+    close(mHandler->getARTSPConnection()->getSocket());
+
     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
 
     sp<AMessage> dummy;
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 3250a48..bec27d3 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -24,7 +24,7 @@
 #include "AnotherPacketSource.h"
 #include "NuPlayerStreamListener.h"
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index f8c89e5..e845c33 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -6,14 +6,27 @@
 
     shared_libs: [
         "liblog",
+        "libbinder",
+        "libbinder_ndk",
+        "libmedia",
         "libmediaplayerservice",
         "libmediadrm",
+        "libresourcemanagerservice",
         "libutils",
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.1",
         "android.hardware.drm@1.2",
     ],
 
+    static_libs: [
+        "resourcemanager_aidl_interface-ndk_platform",
+    ],
+
+    include_dirs: [
+        "frameworks/av/include",
+        "frameworks/av/services/mediaresourcemanager",
+    ],
+
     cflags: [
         "-Werror",
         "-Wall",
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index d81ee05..f114046 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -16,18 +16,40 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "DrmSessionManager_test"
+#include <android/binder_auto_utils.h>
 #include <utils/Log.h>
 
 #include <gtest/gtest.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <aidl/android/media/BnResourceManagerService.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/ProcessInfoInterface.h>
-#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
 
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "ResourceManagerService.h"
+
 namespace android {
 
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::BnResourceManagerClient;
+using ::aidl::android::media::BnResourceManagerService;
+using ::aidl::android::media::MediaResourceParcel;
+using ::aidl::android::media::IResourceManagerClient;
+
+static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
+    Vector<uint8_t> aVec;
+    for (auto b : vec) {
+        aVec.push_back(b);
+    }
+    return aVec;
+}
+
 struct FakeProcessInfo : public ProcessInfoInterface {
     FakeProcessInfo() {}
     virtual ~FakeProcessInfo() {}
@@ -47,173 +69,128 @@
     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
 };
 
-struct FakeDrm : public DrmSessionClientInterface {
-    FakeDrm() {}
-    virtual ~FakeDrm() {}
+struct FakeDrm : public BnResourceManagerClient {
+    FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
+        : mSessionId(toAndroidVector(sessionId)),
+          mReclaimed(false),
+          mDrmSessionManager(manager) {}
 
-    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
-        mReclaimedSessions.push_back(sessionId);
-        return true;
+    Status reclaimResource(bool* _aidl_return) {
+        mReclaimed = true;
+        mDrmSessionManager->removeSession(mSessionId);
+        *_aidl_return = true;
+        return Status::ok();
     }
 
-    const Vector<Vector<uint8_t> >& reclaimedSessions() const {
-        return mReclaimedSessions;
+    Status getName(::std::string* _aidl_return) {
+        String8 name("FakeDrm[");
+        for (size_t i = 0; i < mSessionId.size(); ++i) {
+            name.appendFormat("%02x", mSessionId[i]);
+        }
+        name.append("]");
+        *_aidl_return = name;
+        return Status::ok();
     }
 
+    bool isReclaimed() const {
+        return mReclaimed;
+    }
+
+    const Vector<uint8_t> mSessionId;
+
 private:
-    Vector<Vector<uint8_t> > mReclaimedSessions;
+    bool mReclaimed;
+    const sp<DrmSessionManager> mDrmSessionManager;
 
     DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
 };
 
+struct FakeSystemCallback :
+        public ResourceManagerService::SystemCallbackInterface {
+    FakeSystemCallback() {}
+
+    virtual void noteStartVideo(int /*uid*/) override {}
+
+    virtual void noteStopVideo(int /*uid*/) override {}
+
+    virtual void noteResetVideo() override {}
+
+    virtual bool requestCpusetBoost(bool /*enable*/) override {
+        return true;
+    }
+
+protected:
+    virtual ~FakeSystemCallback() {}
+
+private:
+
+    DISALLOW_EVIL_CONSTRUCTORS(FakeSystemCallback);
+};
+
 static const int kTestPid1 = 30;
 static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
+static const std::vector<uint8_t> kTestSessionId1{1, 2, 3};
+static const std::vector<uint8_t> kTestSessionId2{4, 5, 6, 7, 8};
+static const std::vector<uint8_t> kTestSessionId3{9, 0};
 
 class DrmSessionManagerTest : public ::testing::Test {
 public:
     DrmSessionManagerTest()
-        : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
-          mTestDrm1(new FakeDrm()),
-          mTestDrm2(new FakeDrm()) {
-        GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
-        GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
-        GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
+        : mService(::ndk::SharedRefBase::make<ResourceManagerService>
+            (new FakeProcessInfo(), new FakeSystemCallback())),
+          mDrmSessionManager(new DrmSessionManager(mService)),
+          mTestDrm1(::ndk::SharedRefBase::make<FakeDrm>(
+                  kTestSessionId1, mDrmSessionManager)),
+          mTestDrm2(::ndk::SharedRefBase::make<FakeDrm>(
+                  kTestSessionId2, mDrmSessionManager)),
+          mTestDrm3(::ndk::SharedRefBase::make<FakeDrm>(
+                  kTestSessionId3, mDrmSessionManager)) {
     }
 
 protected:
-    static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
-        for (size_t i = 0; i < num; ++i) {
-            sessionId->push_back(ids[i]);
-        }
-    }
-
-    static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
-            const Vector<uint8_t>& sessionId, int64_t timeStamp) {
-        EXPECT_EQ(drm, info.drm);
-        EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
-        EXPECT_EQ(timeStamp, info.timeStamp);
-    }
-
     void addSession() {
-        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
-        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
-        const PidSessionInfosMap& map = sessionMap();
-        EXPECT_EQ(2u, map.size());
-        ssize_t index1 = map.indexOfKey(kTestPid1);
-        ASSERT_GE(index1, 0);
-        const SessionInfos& infos1 = map[index1];
-        EXPECT_EQ(1u, infos1.size());
-        ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
-        ssize_t index2 = map.indexOfKey(kTestPid2);
-        ASSERT_GE(index2, 0);
-        const SessionInfos& infos2 = map[index2];
-        EXPECT_EQ(2u, infos2.size());
-        ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
-        ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
+        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
+        mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
     }
 
-    const PidSessionInfosMap& sessionMap() {
-        return mDrmSessionManager->mSessionMap;
-    }
-
-    void testGetLowestPriority() {
-        int pid;
-        int priority;
-        EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
-        addSession();
-        EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
-        EXPECT_EQ(kTestPid1, pid);
-        FakeProcessInfo processInfo;
-        int priority1;
-        processInfo.getPriority(kTestPid1, &priority1);
-        EXPECT_EQ(priority1, priority);
-    }
-
-    void testGetLeastUsedSession() {
-        sp<DrmSessionClientInterface> drm;
-        Vector<uint8_t> sessionId;
-        EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
-        addSession();
-
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm1, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm2, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
-        // mSessionId2 is no longer the least used session.
-        mDrmSessionManager->useSession(mSessionId2);
-        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
-        EXPECT_EQ(mTestDrm2, drm);
-        EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
-    }
-
+    std::shared_ptr<ResourceManagerService> mService;
     sp<DrmSessionManager> mDrmSessionManager;
-    sp<FakeDrm> mTestDrm1;
-    sp<FakeDrm> mTestDrm2;
-    Vector<uint8_t> mSessionId1;
-    Vector<uint8_t> mSessionId2;
-    Vector<uint8_t> mSessionId3;
+    std::shared_ptr<FakeDrm> mTestDrm1;
+    std::shared_ptr<FakeDrm> mTestDrm2;
+    std::shared_ptr<FakeDrm> mTestDrm3;
 };
 
 TEST_F(DrmSessionManagerTest, addSession) {
     addSession();
+
+    EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
 }
 
 TEST_F(DrmSessionManagerTest, useSession) {
     addSession();
 
-    mDrmSessionManager->useSession(mSessionId1);
-    mDrmSessionManager->useSession(mSessionId3);
+    mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+    mDrmSessionManager->useSession(mTestDrm3->mSessionId);
 
-    const PidSessionInfosMap& map = sessionMap();
-    const SessionInfos& infos1 = map.valueFor(kTestPid1);
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
-    ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
+    EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
 }
 
 TEST_F(DrmSessionManagerTest, removeSession) {
     addSession();
 
-    mDrmSessionManager->removeSession(mSessionId2);
+    mDrmSessionManager->removeSession(mTestDrm2->mSessionId);
 
-    const PidSessionInfosMap& map = sessionMap();
-    EXPECT_EQ(2u, map.size());
-    const SessionInfos& infos1 = map.valueFor(kTestPid1);
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    EXPECT_EQ(1u, infos1.size());
-    EXPECT_EQ(1u, infos2.size());
-    // mSessionId2 has been removed.
-    ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
-    addSession();
-
-    sp<FakeDrm> drm = new FakeDrm;
-    const uint8_t ids[] = {123};
-    Vector<uint8_t> sessionId;
-    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
-    mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
-    mDrmSessionManager->removeDrm(mTestDrm2);
-
-    const PidSessionInfosMap& map = sessionMap();
-    const SessionInfos& infos2 = map.valueFor(kTestPid2);
-    EXPECT_EQ(1u, infos2.size());
-    // mTestDrm2 has been removed.
-    ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
+    EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+    EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
 }
 
 TEST_F(DrmSessionManagerTest, reclaimSession) {
@@ -224,30 +201,64 @@
     EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
 
     EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
-    EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
-    EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
-    mDrmSessionManager->removeSession(mSessionId1);
+    EXPECT_TRUE(mTestDrm1->isReclaimed());
 
     // add a session from a higher priority process.
-    sp<FakeDrm> drm = new FakeDrm;
-    const uint8_t ids[] = {1, 3, 5};
-    Vector<uint8_t> sessionId;
-    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
-    mDrmSessionManager->addSession(15, drm, sessionId);
+    const std::vector<uint8_t> sid{1, 3, 5};
+    std::shared_ptr<FakeDrm> drm =
+            ::ndk::SharedRefBase::make<FakeDrm>(sid, mDrmSessionManager);
+    mDrmSessionManager->addSession(15, drm, drm->mSessionId);
 
+    // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
+    mDrmSessionManager->useSession(mTestDrm3->mSessionId);
     EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
-    EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
-    // mSessionId2 is reclaimed.
-    EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
+    EXPECT_TRUE(mTestDrm2->isReclaimed());
+
+    EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
+    EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+    EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
+    EXPECT_TRUE(mDrmSessionManager->containsSession(drm->mSessionId));
 }
 
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
-    testGetLowestPriority();
-}
+TEST_F(DrmSessionManagerTest, reclaimAfterUse) {
+    // nothing to reclaim yet
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
 
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
-    testGetLeastUsedSession();
+    // add sessions from same pid
+    mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
+    mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+
+    // use some but not all sessions
+    mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+    mDrmSessionManager->useSession(mTestDrm1->mSessionId);
+    mDrmSessionManager->useSession(mTestDrm2->mSessionId);
+
+    // calling pid priority is too low
+    int lowPriorityPid = kTestPid2 + 1;
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(lowPriorityPid));
+
+    // unused session is reclaimed first
+    int highPriorityPid = kTestPid2 - 1;
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
+    EXPECT_FALSE(mTestDrm1->isReclaimed());
+    EXPECT_FALSE(mTestDrm2->isReclaimed());
+    EXPECT_TRUE(mTestDrm3->isReclaimed());
+    mDrmSessionManager->removeSession(mTestDrm3->mSessionId);
+
+    // less-used session is reclaimed next
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
+    EXPECT_FALSE(mTestDrm1->isReclaimed());
+    EXPECT_TRUE(mTestDrm2->isReclaimed());
+    EXPECT_TRUE(mTestDrm3->isReclaimed());
+
+    // most-used session still open
+    EXPECT_EQ(1u, mDrmSessionManager->getSessionCount());
+    EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
+    EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
+    EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
 }
 
 } // namespace android
diff --git a/media/libmediatranscoding/.clang-format b/media/libmediatranscoding/.clang-format
new file mode 100644
index 0000000..3198d00
--- /dev/null
+++ b/media/libmediatranscoding/.clang-format
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
\ No newline at end of file
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
new file mode 100644
index 0000000..f948bd8
--- /dev/null
+++ b/media/libmediatranscoding/Android.bp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// AIDL interfaces of MediaTranscoding.
+aidl_interface {
+    name: "mediatranscoding_aidl_interface",
+    unstable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/media/IMediaTranscodingService.aidl",
+        "aidl/android/media/ITranscodingServiceClient.aidl",
+        "aidl/android/media/TranscodingErrorCode.aidl",
+        "aidl/android/media/TranscodingJobPriority.aidl",
+        "aidl/android/media/TranscodingType.aidl",
+        "aidl/android/media/TranscodingVideoCodecType.aidl",
+        "aidl/android/media/TranscodingJobParcel.aidl",
+        "aidl/android/media/TranscodingRequestParcel.aidl",
+        "aidl/android/media/TranscodingResultParcel.aidl",
+    ],
+}
+
+cc_library_shared {
+    name: "libmediatranscoding",
+
+    srcs: [
+        "TranscodingClientManager.cpp"
+    ],
+
+    shared_libs: [
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    export_include_dirs: ["include"],
+
+    static_libs: [
+        "mediatranscoding_aidl_interface-ndk_platform",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libmediatranscoding/OWNERS b/media/libmediatranscoding/OWNERS
new file mode 100644
index 0000000..02287cb
--- /dev/null
+++ b/media/libmediatranscoding/OWNERS
@@ -0,0 +1,3 @@
+akersten@google.com
+hkuang@google.com
+lnilsson@google.com
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
new file mode 100644
index 0000000..7252437
--- /dev/null
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "TranscodingClientManager"
+
+#include <inttypes.h>
+#include <media/TranscodingClientManager.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using Status = ::ndk::ScopedAStatus;
+
+// static
+TranscodingClientManager& TranscodingClientManager::getInstance() {
+    static TranscodingClientManager gInstance{};
+    return gInstance;
+}
+
+// static
+void TranscodingClientManager::BinderDiedCallback(void* cookie) {
+    int32_t clientId = static_cast<int32_t>(reinterpret_cast<intptr_t>(cookie));
+    ALOGD("Client %" PRId32 " is dead", clientId);
+    // Don't check for pid validity since we know it's already dead.
+    TranscodingClientManager& manager = TranscodingClientManager::getInstance();
+    manager.removeClient(clientId);
+}
+
+TranscodingClientManager::TranscodingClientManager()
+    : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
+    ALOGD("TranscodingClientManager started");
+}
+
+TranscodingClientManager::~TranscodingClientManager() {
+    ALOGD("TranscodingClientManager exited");
+}
+
+bool TranscodingClientManager::isClientIdRegistered(int32_t clientId) const {
+    std::scoped_lock lock{mLock};
+    return mClientIdToClientInfoMap.find(clientId) != mClientIdToClientInfoMap.end();
+}
+
+void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
+    String8 result;
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "    Total num of Clients: %zu\n", mClientIdToClientInfoMap.size());
+    result.append(buffer);
+
+    if (mClientIdToClientInfoMap.size() > 0) {
+        snprintf(buffer, SIZE, "========== Dumping all clients =========\n");
+        result.append(buffer);
+    }
+
+    for (const auto& iter : mClientIdToClientInfoMap) {
+        const std::shared_ptr<ITranscodingServiceClient> client = iter.second->mClient;
+        std::string clientName;
+        Status status = client->getName(&clientName);
+        if (!status.isOk()) {
+            ALOGE("Failed to get client: %d information", iter.first);
+            continue;
+        }
+        snprintf(buffer, SIZE, "    -- Clients: %d  name: %s\n", iter.first, clientName.c_str());
+        result.append(buffer);
+    }
+
+    write(fd, result.string(), result.size());
+}
+
+status_t TranscodingClientManager::addClient(std::unique_ptr<ClientInfo> client) {
+    // Validate the client.
+    if (client == nullptr || client->mClientId < 0 || client->mClientPid < 0 ||
+        client->mClientUid < 0 || client->mClientOpPackageName.empty() ||
+        client->mClientOpPackageName == "") {
+        ALOGE("Invalid client");
+        return BAD_VALUE;
+    }
+
+    std::scoped_lock lock{mLock};
+
+    // Check if the client already exists.
+    if (mClientIdToClientInfoMap.count(client->mClientId) != 0) {
+        ALOGW("Client already exists.");
+        return ALREADY_EXISTS;
+    }
+
+    ALOGD("Adding client id %d pid: %d uid: %d %s", client->mClientId, client->mClientPid,
+          client->mClientUid, client->mClientOpPackageName.c_str());
+
+    AIBinder_linkToDeath(client->mClient->asBinder().get(), mDeathRecipient.get(),
+                         reinterpret_cast<void*>(client->mClientId));
+
+    // Adds the new client to the map.
+    mClientIdToClientInfoMap[client->mClientId] = std::move(client);
+
+    return OK;
+}
+
+status_t TranscodingClientManager::removeClient(int32_t clientId) {
+    ALOGD("Removing client id %d", clientId);
+    std::scoped_lock lock{mLock};
+
+    // Checks if the client is valid.
+    auto it = mClientIdToClientInfoMap.find(clientId);
+    if (it == mClientIdToClientInfoMap.end()) {
+        ALOGE("Client id %d does not exist", clientId);
+        return INVALID_OPERATION;
+    }
+
+    std::shared_ptr<ITranscodingServiceClient> client = it->second->mClient;
+
+    // Check if the client still live. If alive, unlink the death.
+    if (client) {
+        AIBinder_unlinkToDeath(client->asBinder().get(), mDeathRecipient.get(),
+                               reinterpret_cast<void*>(clientId));
+    }
+
+    // Erase the entry.
+    mClientIdToClientInfoMap.erase(it);
+
+    return OK;
+}
+
+size_t TranscodingClientManager::getNumOfClients() const {
+    std::scoped_lock lock{mLock};
+    return mClientIdToClientInfoMap.size();
+}
+
+}  // namespace android
diff --git a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
new file mode 100644
index 0000000..07b6c1a
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2019, 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.TranscodingJobParcel;
+import android.media.TranscodingRequestParcel;
+import android.media.ITranscodingServiceClient;
+
+/**
+ * Binder interface for MediaTranscodingService.
+ *
+ * {@hide}
+ */
+interface IMediaTranscodingService {
+    /**
+     * All MediaTranscoding service and device Binder calls may return a
+     * ServiceSpecificException with the following error codes
+     */
+    const int ERROR_PERMISSION_DENIED = 1;
+    const int ERROR_ALREADY_EXISTS = 2;
+    const int ERROR_ILLEGAL_ARGUMENT = 3;
+    const int ERROR_DISCONNECTED = 4;
+    const int ERROR_TIMED_OUT = 5;
+    const int ERROR_DISABLED = 6;
+    const int ERROR_INVALID_OPERATION = 7;
+
+    /**
+     * Default UID/PID values for non-privileged callers of
+     * registerClient().
+     */
+    const int USE_CALLING_UID = -1;
+    const int USE_CALLING_PID = -1;
+
+    /**
+     * Register the client with the MediaTranscodingService.
+     *
+     * Client must call this function to register itself with the service in order to perform
+     * transcoding. This function will return a unique positive Id assigned by the service.
+     * Client should save this Id and use it for all the transaction with the service.
+     *
+     * @param client interface for the MediaTranscodingService to call the client.
+     * @param opPackageName op package name of the client.
+     * @param clientUid user id of the client.
+     * @param clientPid process id of the client.
+     * @return a unique positive Id assigned to the client by the service, -1  means failed to
+     * register.
+     */
+    int registerClient(in ITranscodingServiceClient client,
+                       in String opPackageName,
+                       in int clientUid,
+                       in int clientPid);
+
+    /**
+    * Unregister the client with the MediaTranscodingService.
+    *
+    * Client will not be able to perform any more transcoding after unregister.
+    *
+    * @param clientId assigned Id of the client.
+    * @return true if succeeds, false otherwise.
+    */
+    boolean unregisterClient(in int clientId);
+
+    /**
+    * Returns the number of clients. This is used for debugging.
+    */
+    int getNumOfClients();
+
+    /**
+     * Submits a transcoding request to MediaTranscodingService.
+     *
+     * @param clientId assigned Id of the client.
+     * @param request a TranscodingRequest contains transcoding configuration.
+     * @param job(output variable) a TranscodingJob generated by the MediaTranscodingService.
+     * @return a unique positive jobId generated by the MediaTranscodingService, -1 means failure.
+     */
+    int submitRequest(in int clientId,
+                      in TranscodingRequestParcel request,
+                      out TranscodingJobParcel job);
+
+    /**
+     * Cancels a transcoding job.
+     *
+     * @param clientId assigned id of the client.
+     * @param jobId a TranscodingJob generated by the MediaTranscodingService.
+     * @return true if succeeds, false otherwise.
+     */
+    boolean cancelJob(in int clientId, in int jobId);
+
+    /**
+     * Queries the job detail associated with a jobId.
+     *
+     * @param jobId a TranscodingJob generated by the MediaTranscodingService.
+     * @param job(output variable) the TranscodingJob associated with the jobId.
+     * @return true if succeeds, false otherwise.
+     */
+    boolean getJobWithId(in int jobId, out TranscodingJobParcel job);
+}
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingServiceClient.aidl b/media/libmediatranscoding/aidl/android/media/ITranscodingServiceClient.aidl
new file mode 100644
index 0000000..e23c833
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/ITranscodingServiceClient.aidl
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2019, 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.TranscodingErrorCode;
+import android.media.TranscodingJobParcel;
+import android.media.TranscodingResultParcel;
+
+/**
+ * ITranscodingServiceClient interface for the MediaTranscodingervice to communicate with the
+ * client.
+ *
+ * {@hide}
+ */
+//TODO(hkuang): Implement the interface.
+interface ITranscodingServiceClient {
+    /**
+     * Retrieves the name of the client.
+     */
+    @utf8InCpp String getName();
+
+    /**
+    * Called when the transcoding associated with the jobId finished.
+    *
+    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param result contains the transcoded file stats and other transcoding metrics if requested.
+    */
+    oneway void onTranscodingFinished(in int jobId, in TranscodingResultParcel result);
+
+    /**
+    * Called when the transcoding associated with the jobId failed.
+    *
+    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param errorCode error code that indicates the error.
+    */
+    oneway void onTranscodingFailed(in int jobId, in TranscodingErrorCode errorCode);
+
+    /**
+    * Called when the transcoding configuration associated with the jobId gets updated, i.e. wait
+    * number in the job queue.
+    *
+    * <p> This will only be called if client set requestUpdate to be true in the TranscodingRequest
+    * submitted to the MediaTranscodingService.
+    *
+    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param oldAwaitNumber previous number of jobs ahead of current job.
+    * @param newAwaitNumber updated number of jobs ahead of current job.
+    */
+    oneway void onAwaitNumberOfJobsChanged(in int jobId,
+                                           in int oldAwaitNumber,
+                                           in int newAwaitNumber);
+
+    /**
+    * Called when there is an update on the progress of the TranscodingJob.
+    *
+    * <p> This will only be called if client set requestUpdate to be true in the TranscodingRequest
+    * submitted to the MediaTranscodingService.
+    *
+    * @param jobId jobId assigned by the MediaTranscodingService upon receiving request.
+    * @param progress an integer number ranging from 0 ~ 100 inclusive.
+    */
+    oneway void onProgressUpdate(in int jobId, in int progress);
+}
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
new file mode 100644
index 0000000..7f47fdc
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Type enums of video transcoding errors.
+ *
+ * {@hide}
+ */
+@Backing(type = "int")
+enum TranscodingErrorCode {
+    kUnknown = 0,
+    kUnsupported = 1,
+    kDecoderError = 2,
+    kEncoderError = 3,
+    kExtractorError = 4,
+    kMuxerError = 5,
+    kInvalidBitstream = 6
+}
\ No newline at end of file
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl
new file mode 100644
index 0000000..d912c38
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingJobParcel.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.TranscodingRequestParcel;
+
+/**
+ * TranscodingJob is generated by the MediaTranscodingService upon receiving a TranscodingRequest.
+ * It contains all the necessary configuration generated by the MediaTranscodingService for the
+ * TranscodingRequest.
+ *
+ * {@hide}
+ */
+//TODO(hkuang): Implement the parcelable.
+parcelable TranscodingJobParcel {
+    /**
+     * A unique positive Id generated by the MediaTranscodingService.
+     */
+    int jobId;
+
+    /**
+     * The request associated with the TranscodingJob.
+     */
+    TranscodingRequestParcel request;
+
+    /**
+    * Current number of jobs ahead of this job. The service schedules the job based on the priority
+    * passed from the client. Client could specify whether to receive updates when the
+    * awaitNumberOfJobs changes through setting requestProgressUpdate in the TranscodingRequest.
+    */
+    int awaitNumberOfJobs;
+}
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl
new file mode 100644
index 0000000..1a5d81a
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingJobPriority.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Priority of a transcoding job.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+enum TranscodingJobPriority {
+    // TODO(hkuang): define what each priority level actually mean.
+    kUnspecified = 0,
+    kLow = 1,
+    /**
+     * 2 ~ 20 is reserved for future use.
+     */
+    kNormal = 21,
+    /**
+     * 22 ~ 30 is reserved for future use.
+     */
+    kHigh = 31,
+}
\ No newline at end of file
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
new file mode 100644
index 0000000..7b7986d
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2019, 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.TranscodingJobPriority;
+import android.media.TranscodingType;
+
+/**
+ * TranscodingRequest contains the desired configuration for the transcoding.
+ *
+ * {@hide}
+ */
+//TODO(hkuang): Implement the parcelable.
+parcelable TranscodingRequestParcel {
+    /**
+     * Name of file to be transcoded.
+     */
+    @utf8InCpp String fileName;
+
+    /**
+     * Type of the transcoding.
+     */
+    TranscodingType transcodingType;
+
+    /**
+     * Input source file descriptor.
+     */
+    ParcelFileDescriptor inFd;
+
+    /**
+     * Output transcoded file descriptor.
+     */
+    ParcelFileDescriptor outFd;
+
+    /**
+     * Priority of this transcoding. Service will schedule the transcoding based on the priority.
+     */
+    TranscodingJobPriority priority;
+
+    /**
+     * Whether to receive update on progress and change of awaitNumJobs.
+     */
+    boolean requestUpdate;
+}
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
new file mode 100644
index 0000000..65c49e7
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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;
+
+/**
+ * Result of the transcoding.
+ *
+ * {@hide}
+ */
+//TODO(hkuang): Implement the parcelable.
+parcelable TranscodingResultParcel {
+    /**
+     * The jobId associated with the TranscodingResult.
+     */
+    int jobId;
+
+    /**
+     * Actual bitrate of the transcoded video in bits per second. This will only present for video
+     * transcoding. -1 means not available.
+     */
+    int actualBitrateBps;
+
+    // TODO(hkuang): Add more fields.
+}
\ No newline at end of file
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingType.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingType.aidl
new file mode 100644
index 0000000..9184c87
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingType.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Type of transcoding.
+ *
+ * {@hide}
+ */
+@Backing(type = "int")
+enum TranscodingType {
+    kUnknown = 0,
+    kVideoTranscoding = 1,
+    kImageTranscoding = 2,
+}
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl b/media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
new file mode 100644
index 0000000..5dab4f2
--- /dev/null
+++ b/media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2019, 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;
+
+/**
+ * Type enums of video codec type.
+ *
+ * {@hide}
+ */
+@Backing(type = "int")
+enum TranscodingVideoCodecType {
+    kUnspecified = 0,
+    kAvc = 1,
+    kHevc = 2,
+}
\ No newline at end of file
diff --git a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
new file mode 100644
index 0000000..0e8dcfd
--- /dev/null
+++ b/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
+#define ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
+
+#include <utils/Log.h>
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+namespace android {
+
+/*
+ * AdjustableMaxPriorityQueue is a custom max priority queue that helps managing jobs for
+ * MediaTranscodingService.
+ *
+ * AdjustableMaxPriorityQueue is a wrapper template around the STL's *_heap() functions.
+ * - Internally, it uses a std::vector<T> to store elements in a heap order.
+ * - Support adjusting item's priority while maintaining the heap property.
+ * - Support removing any item in the heap while maintaining the heap property. Note that the
+ *   removal complexity will be O(n) in worst case.
+ * - AdjustableMaxPriorityQueue needs T::operator<() at instantiation time
+ */
+template <class T, class Comparator = std::less<T>>
+class AdjustableMaxPriorityQueue {
+   public:
+    typedef typename std::vector<T>::iterator iterator;
+    typedef typename std::vector<T>::const_iterator const_iterator;
+
+    AdjustableMaxPriorityQueue();
+
+    /* Whether the queue is empty. */
+    bool empty() const;
+
+    /* Number of items in the queue. */
+    int size() const;
+
+    /* Return the top element in the queue. The queue still owns the element. */
+    const T& top() const;
+
+    /* Discards the element with highest value based on the given comparator. */
+    void pop();
+
+    /* Erases all the elements in the queue. */
+    void clear();
+
+    /*
+     * Returns the element with the highest value based on the given comparator. Queue transfer the
+     * ownership of the item to the caller. Client MUST call empty() to check whether there is
+     * element at the top before calling this.
+     */
+    T consume_top();
+
+    /* Adds an element to the heap. The queue will make a deep copy of the element. */
+    bool push(const T& item) { return pushInternal(item); }
+
+    /* Adds an element to the heap. The queue will take ownership of the element. */
+    bool push(T&& item) { return pushInternal(std::move(item)); }
+
+    /* Adds a new element to the AdjustableMaxPriorityQueue. This new element is constructed in
+     * place passing args as the arguments for its constructor. */
+    template <class... Args>
+    bool emplace(Args&&... args);
+
+    /* Remove an element from a AdjustableMaxPriorityQueue. */
+    void erase(iterator pos);
+
+    /*
+     * Rebuild a heap based on the given comparator. This MUST be called after changing the value
+     * of items.
+     */
+    void rebuild();
+
+    /*
+     * Iterators used for accessing and changing the priority.
+     * If you change the value of items through these access iterators BE SURE to call rebuild() to
+     * ensure the integrity of the heap is maintained.
+     * NOTE: The iterator pos will change after calling rebuild().
+     */
+    const iterator begin();
+    const iterator end();
+
+    /*
+     * Iterators used for accessing the priority.
+     */
+    const const_iterator begin() const;
+    const const_iterator end() const;
+
+    /* Return the backbone storage of this PriorityQueue. Mainly used for debugging. */
+    const std::vector<T>& getStorage() const { return mHeap; };
+
+   private:
+    std::vector<T> mHeap;
+
+    /* Implementation shared by both public push() methods. */
+    template <class Arg>
+    bool pushInternal(Arg&& item);
+};
+
+template <class T, class Comparator>
+AdjustableMaxPriorityQueue<T, Comparator>::AdjustableMaxPriorityQueue() {}
+
+template <class T, class Comparator>
+bool AdjustableMaxPriorityQueue<T, Comparator>::empty() const {
+    return mHeap.empty();
+}
+
+template <class T, class Comparator>
+int AdjustableMaxPriorityQueue<T, Comparator>::size() const {
+    return mHeap.size();
+}
+
+template <class T, class Comparator>
+const T& AdjustableMaxPriorityQueue<T, Comparator>::top() const {
+    DCHECK(!mHeap.empty());
+    return mHeap.front();
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a longer heap.
+// Complexity of this: Up to logarithmic in the distance between first and last.
+template <class T, class Comparator>
+template <class Arg>
+bool AdjustableMaxPriorityQueue<T, Comparator>::pushInternal(Arg&& item) {
+    mHeap.push_back(std::forward<Arg>(item));
+    std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
+    return true;
+}
+
+template <class T, class Comparator>
+template <class... Args>
+bool AdjustableMaxPriorityQueue<T, Comparator>::emplace(Args&&... args) {
+    mHeap.emplace_back(std::forward<Args>(args)...);
+    std::push_heap(mHeap.begin(), mHeap.end(), Comparator());
+    return true;
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
+// Complexity of this: Up to twice logarithmic in the distance between first and last.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::pop() {
+    DCHECK(!mHeap.empty());
+    std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
+    mHeap.pop_back();
+}
+
+// Compares elements and potentially swaps (or moves) them until rearranged as a shorter heap.
+// Complexity of this: Up to twice logarithmic in the distance between first and last.
+template <class T, class Comparator>
+T AdjustableMaxPriorityQueue<T, Comparator>::consume_top() {
+    DCHECK(!mHeap.empty());
+    std::pop_heap(mHeap.begin(), mHeap.end(), Comparator());
+    T to_return = std::move(mHeap.back());
+    mHeap.pop_back();
+    return to_return;
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
+AdjustableMaxPriorityQueue<T, Comparator>::begin() {
+    return mHeap.begin();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::iterator
+AdjustableMaxPriorityQueue<T, Comparator>::end() {
+    return mHeap.end();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
+AdjustableMaxPriorityQueue<T, Comparator>::begin() const {
+    return mHeap.begin();
+}
+
+template <class T, class Comparator>
+const typename AdjustableMaxPriorityQueue<T, Comparator>::const_iterator
+AdjustableMaxPriorityQueue<T, Comparator>::end() const {
+    return mHeap.end();
+}
+
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::clear() {
+    mHeap.erase(mHeap.begin(), mHeap.end());
+}
+
+// Complexity of this: At most 3*std::distance(first, last) comparisons.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::rebuild() {
+    std::make_heap(mHeap.begin(), mHeap.end(), Comparator());
+}
+
+// Remove a random element from a AdjustableMaxPriorityQueue.
+template <class T, class Comparator>
+void AdjustableMaxPriorityQueue<T, Comparator>::erase(iterator pos) {
+    DCHECK(!mHeap.empty());
+    mHeap.erase(pos);
+    rebuild();
+}
+
+}  // namespace android
+#endif  // ANDROID_MEDIA_ADJUSTABLE_MAX_PRIORITY_QUEUE_H
\ No newline at end of file
diff --git a/media/libmediatranscoding/include/media/TranscodingClientManager.h b/media/libmediatranscoding/include/media/TranscodingClientManager.h
new file mode 100644
index 0000000..eec120a
--- /dev/null
+++ b/media/libmediatranscoding/include/media/TranscodingClientManager.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H
+#define ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H
+
+#include <aidl/android/media/BnTranscodingServiceClient.h>
+#include <android/binder_ibinder.h>
+#include <sys/types.h>
+#include <utils/Condition.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+using ::aidl::android::media::ITranscodingServiceClient;
+
+class MediaTranscodingService;
+
+/*
+ * TranscodingClientManager manages all the transcoding clients across different processes.
+ *
+ * TranscodingClientManager is a global singleton that could only acquired by
+ * MediaTranscodingService. It manages all the clients's registration/unregistration and clients'
+ * information. It also bookkeeps all the clients' information. It also monitors to the death of the
+ * clients. Upon client's death, it will remove the client from it.
+ *
+ * TODO(hkuang): Hook up with ResourceManager for resource management.
+ * TODO(hkuang): Hook up with MediaMetrics to log all the transactions.
+ */
+class TranscodingClientManager {
+   public:
+    virtual ~TranscodingClientManager();
+
+    /**
+     * ClientInfo contains a single client's information.
+     */
+    struct ClientInfo {
+        /* The remote client that this ClientInfo is associated with. */
+        std::shared_ptr<ITranscodingServiceClient> mClient;
+        /* A unique positive Id assigned to the client by the service. */
+        int32_t mClientId;
+        /* Process id of the client */
+        int32_t mClientPid;
+        /* User id of the client. */
+        int32_t mClientUid;
+        /* Package name of the client. */
+        std::string mClientOpPackageName;
+
+        ClientInfo(const std::shared_ptr<ITranscodingServiceClient>& client, int64_t clientId,
+                   int32_t pid, int32_t uid, const std::string& opPackageName)
+            : mClient(client),
+              mClientId(clientId),
+              mClientPid(pid),
+              mClientUid(uid),
+              mClientOpPackageName(opPackageName) {}
+    };
+
+    /**
+     * Adds a new client to the manager.
+     *
+     * The client must have valid clientId, pid, uid and opPackageName, otherwise, this will return
+     * a non-zero errorcode. If the client has already been added, it will also return non-zero
+     * errorcode.
+     *
+     * @param client to be added to the manager.
+     * @return 0 if client is added successfully, non-zero errorcode otherwise.
+     */
+    status_t addClient(std::unique_ptr<ClientInfo> client);
+
+    /**
+     * Removes an existing client from the manager.
+     *
+     * If the client does not exist, this will return non-zero errorcode.
+     *
+     * @param clientId id of the client to be removed..
+     * @return 0 if client is removed successfully, non-zero errorcode otherwise.
+     */
+    status_t removeClient(int32_t clientId);
+
+    /**
+     * Gets the number of clients.
+     */
+    size_t getNumOfClients() const;
+
+    /**
+     * Checks if a client with clientId is already registered.
+     */
+    bool isClientIdRegistered(int32_t clientId) const;
+
+    /**
+     * Dump all the client information to the fd.
+     */
+    void dumpAllClients(int fd, const Vector<String16>& args);
+
+   private:
+    friend class MediaTranscodingService;
+    friend class TranscodingClientManagerTest;
+
+    /** Get the singleton instance of the TranscodingClientManager. */
+    static TranscodingClientManager& getInstance();
+
+    TranscodingClientManager();
+
+    static void BinderDiedCallback(void* cookie);
+
+    mutable std::mutex mLock;
+    std::unordered_map<int32_t, std::unique_ptr<ClientInfo>> mClientIdToClientInfoMap
+            GUARDED_BY(mLock);
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+
+}  // namespace android
+#endif  // ANDROID_MEDIA_TRANSCODING_SERVICE_H
diff --git a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
new file mode 100644
index 0000000..d58af4e
--- /dev/null
+++ b/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Unit Test for AdjustableMaxPriorityQueue
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AdjustableMaxPriorityQueueTest"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <media/AdjustableMaxPriorityQueue.h>
+#include <utils/Log.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <list>
+#include <queue>
+#include <unordered_map>
+
+namespace android {
+
+class IntUniquePtrComp {
+   public:
+    bool operator()(const std::unique_ptr<int>& lhs, const std::unique_ptr<int>& rhs) const {
+        return *lhs < *rhs;
+    }
+};
+
+// Test the heap property and make sure it is the same as std::priority_queue.
+TEST(AdjustableMaxPriorityQueueTest, BasicAPIS) {
+    AdjustableMaxPriorityQueue<std::pair<float, char*>> heap;
+    std::priority_queue<std::pair<float, char*>> pq;
+    AdjustableMaxPriorityQueue<std::pair<float, char*>> remove_queue;
+
+    // Push a set of values onto both AdjustableMaxPriorityQueue and priority_queue
+    // Also compute the sum of those values
+    double sum = 0;
+    for (int i = 0; i < 10; ++i) {
+        float value = 2.1 * i;
+        sum += value;
+        heap.push(std::pair<float, char*>(value, nullptr));
+        pq.push(std::pair<float, char*>(value, nullptr));
+        remove_queue.push(std::pair<float, char*>(value, nullptr));
+    }
+
+    // Test the iterator by using it to subtract all values from earlier sum
+    AdjustableMaxPriorityQueue<std::pair<float, char*>>::iterator it;
+    for (it = heap.begin(); it != heap.end(); ++it) {
+        sum -= it->first;
+    }
+    EXPECT_EQ(0, sum);
+
+    // Test the size();
+    EXPECT_EQ(10, heap.size());
+
+    // Testing pop() by popping values from both queues and compare if they are the same.
+    // Also check each pop is smaller than the previous pop max value.
+    float max = 1000;
+    while (!heap.empty()) {
+        float value = heap.top().first;
+        ALOGD("Value is %f ", value);
+        EXPECT_EQ(value, pq.top().first);
+        EXPECT_LE(value, max);
+        max = value;
+        heap.pop();
+        pq.pop();
+    }
+
+    // Test erase() by removing values and ensuring the heap
+    // condition is still met as miscellaneous elements are
+    // removed from the heap.
+    int iteration_mixer = 0;
+    float previous_value = remove_queue.top().first;
+
+    while (!remove_queue.empty()) {
+        int iteration_count = iteration_mixer % remove_queue.size();
+
+        AdjustableMaxPriorityQueue<std::pair<float, char*>>::iterator iterator =
+                remove_queue.begin();
+
+        // Empty loop as we just want to advance the iterator.
+        for (int i = 0; i < iteration_count; ++i, ++iterator) {
+        }
+
+        remove_queue.erase(iterator);
+        float value = remove_queue.top().first;
+        remove_queue.pop();
+
+        EXPECT_GE(previous_value, value);
+
+        ++iteration_mixer;
+        previous_value = value;
+    }
+}
+
+TEST(AdjustableMaxPriorityQueueTest, BasicWithMoveOnly) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+
+    auto smaller = std::make_unique<int>(1);
+    EXPECT_TRUE(heap.push(std::move(smaller)));
+    EXPECT_EQ(1, *heap.top());
+    EXPECT_EQ(1, heap.size());
+
+    auto bigger = std::make_unique<int>(2);
+    heap.push(std::move(bigger));
+    EXPECT_EQ(2, *heap.top());
+
+    auto biggest = std::make_unique<int>(3);
+    EXPECT_TRUE(heap.push(std::move(biggest)));
+
+    EXPECT_EQ(3, heap.size());
+    // Biggest should be on top.
+    EXPECT_EQ(3, *heap.top());
+
+    biggest = heap.consume_top();
+    EXPECT_EQ(3, *biggest);
+
+    bigger = heap.consume_top();
+    EXPECT_EQ(2, *bigger);
+
+    smaller = heap.consume_top();
+    EXPECT_EQ(1, *smaller);
+
+    EXPECT_TRUE(heap.empty());
+}
+
+TEST(AdjustableMaxPriorityQueueTest, TestChangingItem) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+    using HeapIterator =
+            AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp>::iterator;
+
+    int testValues[] = {1, 2, 3};
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, HeapIterator> itemToIterratorMap;
+
+    // Insert the test values into the heap.
+    for (auto value : testValues) {
+        auto item = std::make_unique<int>(value);
+        EXPECT_TRUE(heap.push(std::move(item)));
+    }
+
+    // Save each value and its pos in the heap into the map.
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Change the item with value 1 -> 4. And expects the 4 to be the top of the HEAP after that.
+    // After changing, the heap should contain [2,3,4].
+    auto newValue = std::make_unique<int>(4);
+    itemToIterratorMap[1]->swap(newValue);
+    heap.rebuild();
+    EXPECT_EQ(4, *heap.top());
+
+    // Change the item with value 2 -> 5. And expects the 5 to be the top of the HEAP after that.
+    auto newValue2 = std::make_unique<int>(5);
+    itemToIterratorMap[2]->swap(newValue2);
+    heap.rebuild();
+    EXPECT_EQ(5, *heap.top());
+}
+
+TEST(AdjustableMaxPriorityQueueTest, TestErasingItem) {
+    AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp> heap;
+    using HeapIterator =
+            AdjustableMaxPriorityQueue<std::unique_ptr<int>, IntUniquePtrComp>::iterator;
+
+    int testValues[] = {1, 2, 3};
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, HeapIterator> itemToIterratorMap;
+
+    // Insert the test values into the heap.
+    for (auto value : testValues) {
+        auto item = std::make_unique<int>(value);
+        EXPECT_TRUE(heap.push(std::move(item)));
+    }
+
+    // Save each value and its pos in the heap into the map.
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // The top of the heap must be 3.
+    EXPECT_EQ(3, *heap.top());
+
+    // Remove 3 and the top of the heap should be 2.
+    heap.erase(itemToIterratorMap[3]);
+    EXPECT_EQ(2, *heap.top());
+
+    // Reset the iter pos in the heap.
+    itemToIterratorMap.clear();
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Remove 2 and the top of the heap should be 1.
+    heap.erase(itemToIterratorMap[2]);
+    EXPECT_EQ(1, *heap.top());
+
+    // Reset the iter pos in the heap as iterator pos changed after
+    itemToIterratorMap.clear();
+    for (HeapIterator iter = heap.begin(); iter != heap.end(); iter++) {
+        itemToIterratorMap[*iter->get()] = iter;
+    }
+
+    // Remove 1 and the heap should be empty.
+    heap.erase(itemToIterratorMap[1]);
+    EXPECT_TRUE(heap.empty());
+}
+
+// Test the heap property and make sure it is the same as std::priority_queue.
+TEST(AdjustableMaxPriorityQueueTest, TranscodingJobTest) {
+    // Test data structure that mimics the Transcoding job.
+    struct TranscodingJob {
+        int32_t priority;
+        int64_t createTimeUs;
+    };
+
+    // The job is arranging according to priority with highest priority comes first.
+    // For the job with the same priority, the job with early createTime will come first.
+    class TranscodingJobComp {
+       public:
+        bool operator()(const std::unique_ptr<TranscodingJob>& lhs,
+                        const std::unique_ptr<TranscodingJob>& rhs) const {
+            if (lhs->priority != rhs->priority) {
+                return lhs->priority < rhs->priority;
+            }
+            return lhs->createTimeUs > rhs->createTimeUs;
+        }
+    };
+
+    // Map to save each value's position in the heap.
+    std::unordered_map<int, TranscodingJob*> jobIdToJobMap;
+
+    TranscodingJob testJobs[] = {
+            {1 /*priority*/, 66 /*createTimeUs*/},  // First job,
+            {2 /*priority*/, 67 /*createTimeUs*/},  // Second job,
+            {2 /*priority*/, 66 /*createTimeUs*/},  // Third job,
+            {3 /*priority*/, 68 /*createTimeUs*/},  // Fourth job.
+    };
+
+    AdjustableMaxPriorityQueue<std::unique_ptr<TranscodingJob>, TranscodingJobComp> jobQueue;
+
+    // Pushes all the jobs into the heap.
+    for (int jobId = 0; jobId < 4; ++jobId) {
+        auto newJob = std::make_unique<TranscodingJob>(testJobs[jobId]);
+        jobIdToJobMap[jobId] = newJob.get();
+        EXPECT_TRUE(jobQueue.push(std::move(newJob)));
+    }
+
+    // Check the job queue size.
+    EXPECT_EQ(4, jobQueue.size());
+
+    // Check the top and it should be Forth job: (3, 68)
+    const std::unique_ptr<TranscodingJob>& topJob = jobQueue.top();
+    EXPECT_EQ(3, topJob->priority);
+    EXPECT_EQ(68, topJob->createTimeUs);
+
+    // Consume the top.
+    std::unique_ptr<TranscodingJob> consumeJob = jobQueue.consume_top();
+
+    // Check the top and it should be Third Job (2, 66)
+    const std::unique_ptr<TranscodingJob>& topJob2 = jobQueue.top();
+    EXPECT_EQ(2, topJob2->priority);
+    EXPECT_EQ(66, topJob2->createTimeUs);
+
+    // Change the Second job's priority to 4 from (2, 67) -> (4, 67). It should becomes top of the
+    // queue.
+    jobIdToJobMap[1]->priority = 4;
+    jobQueue.rebuild();
+    const std::unique_ptr<TranscodingJob>& topJob3 = jobQueue.top();
+    EXPECT_EQ(4, topJob3->priority);
+    EXPECT_EQ(67, topJob3->createTimeUs);
+}
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
new file mode 100644
index 0000000..8191b00
--- /dev/null
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -0,0 +1,48 @@
+// Build the unit tests for libmediatranscoding.
+cc_defaults {
+    name: "libmediatranscoding_test_defaults",
+
+    header_libs: [
+        "libbase_headers",
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libmediatranscoding"
+    ],
+
+    static_libs: [
+        "mediatranscoding_aidl_interface-ndk_platform",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    test_suites: ["device-tests"],
+}
+
+//
+// TranscodingClientManager unit test
+//
+cc_test {
+    name: "TranscodingClientManager_tests",
+    defaults: ["libmediatranscoding_test_defaults"],
+
+    srcs: ["TranscodingClientManager_tests.cpp"],
+}
+
+//
+// AdjustableMaxPriorityQueue unit test
+//
+cc_test {
+    name: "AdjustableMaxPriorityQueue_tests",
+    defaults: ["libmediatranscoding_test_defaults"],
+
+    srcs: ["AdjustableMaxPriorityQueue_tests.cpp"],
+}
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
new file mode 100644
index 0000000..5d2419d
--- /dev/null
+++ b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Unit Test for TranscodingClientManager
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "TranscodingClientManagerTest"
+
+#include <aidl/android/media/BnTranscodingServiceClient.h>
+#include <aidl/android/media/IMediaTranscodingService.h>
+#include <aidl/android/media/ITranscodingServiceClient.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <media/TranscodingClientManager.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using Status = ::ndk::ScopedAStatus;
+using aidl::android::media::BnTranscodingServiceClient;
+using aidl::android::media::IMediaTranscodingService;
+using aidl::android::media::ITranscodingServiceClient;
+
+constexpr int32_t kInvalidClientId = -1;
+constexpr int32_t kInvalidClientPid = -1;
+constexpr int32_t kInvalidClientUid = -1;
+constexpr const char* kInvalidClientOpPackageName = "";
+
+constexpr int32_t kClientId = 1;
+constexpr int32_t kClientPid = 2;
+constexpr int32_t kClientUid = 3;
+constexpr const char* kClientOpPackageName = "TestClient";
+
+struct TestClient : public BnTranscodingServiceClient {
+    TestClient(const std::shared_ptr<IMediaTranscodingService>& service) : mService(service) {
+        ALOGD("TestClient Created");
+    }
+
+    Status getName(std::string* _aidl_return) override {
+        *_aidl_return = "test_client";
+        return Status::ok();
+    }
+
+    Status onTranscodingFinished(
+            int32_t /* in_jobId */,
+            const ::aidl::android::media::TranscodingResultParcel& /* in_result */) override {
+        return Status::ok();
+    }
+
+    Status onTranscodingFailed(
+            int32_t /* in_jobId */,
+            ::aidl::android::media::TranscodingErrorCode /*in_errorCode */) override {
+        return Status::ok();
+    }
+
+    Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
+                                      int32_t /* in_newAwaitNumber */) override {
+        return Status::ok();
+    }
+
+    Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
+        return Status::ok();
+    }
+
+    virtual ~TestClient() { ALOGI("TestClient destroyed"); };
+
+   private:
+    std::shared_ptr<IMediaTranscodingService> mService;
+    TestClient(const TestClient&) = delete;
+    TestClient& operator=(const TestClient&) = delete;
+};
+
+class TranscodingClientManagerTest : public ::testing::Test {
+   public:
+    TranscodingClientManagerTest() : mClientManager(TranscodingClientManager::getInstance()) {
+        ALOGD("TranscodingClientManagerTest created");
+    }
+
+    void SetUp() override {
+        ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
+        mService = IMediaTranscodingService::fromBinder(binder);
+        if (mService == nullptr) {
+            ALOGE("Failed to connect to the media.trascoding service.");
+            return;
+        }
+
+        mTestClient = ::ndk::SharedRefBase::make<TestClient>(mService);
+    }
+
+    void TearDown() override {
+        ALOGI("TranscodingClientManagerTest tear down");
+        mService = nullptr;
+    }
+
+    ~TranscodingClientManagerTest() { ALOGD("TranscodingClientManagerTest destroyed"); }
+
+    TranscodingClientManager& mClientManager;
+    std::shared_ptr<ITranscodingServiceClient> mTestClient = nullptr;
+    std::shared_ptr<IMediaTranscodingService> mService = nullptr;
+};
+
+TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientId) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    // Create a client with invalid client id.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client, kInvalidClientId, kClientPid, kClientUid, kClientOpPackageName);
+
+    // Add the client to the manager and expect failure.
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err != OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientPid) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    // Create a client with invalid Pid.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client, kClientId, kInvalidClientPid, kClientUid, kClientOpPackageName);
+
+    // Add the client to the manager and expect failure.
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err != OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientUid) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    // Create a client with invalid Uid.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client, kClientId, kClientPid, kInvalidClientUid, kClientOpPackageName);
+
+    // Add the client to the manager and expect failure.
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err != OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingWithInvalidClientPackageName) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    // Create a client with invalid packagename.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client, kClientId, kClientPid, kClientUid, kInvalidClientOpPackageName);
+
+    // Add the client to the manager and expect failure.
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err != OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingValidClient) {
+    std::shared_ptr<ITranscodingServiceClient> client1 =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
+
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err == OK);
+
+    size_t numOfClients = mClientManager.getNumOfClients();
+    EXPECT_EQ(numOfClients, 1);
+
+    err = mClientManager.removeClient(kClientId);
+    EXPECT_TRUE(err == OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingDupliacteClient) {
+    std::shared_ptr<ITranscodingServiceClient> client1 =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
+
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err == OK);
+
+    err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err != OK);
+
+    err = mClientManager.removeClient(kClientId);
+    EXPECT_TRUE(err == OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestAddingMultipleClient) {
+    std::shared_ptr<ITranscodingServiceClient> client1 =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo1 =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
+
+    status_t err = mClientManager.addClient(std::move(clientInfo1));
+    EXPECT_TRUE(err == OK);
+
+    std::shared_ptr<ITranscodingServiceClient> client2 =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo2 =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client2, kClientId + 1, kClientPid, kClientUid, kClientOpPackageName);
+
+    err = mClientManager.addClient(std::move(clientInfo2));
+    EXPECT_TRUE(err == OK);
+
+    std::shared_ptr<ITranscodingServiceClient> client3 =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    // Create a client with invalid packagename.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo3 =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client3, kClientId + 2, kClientPid, kClientUid, kClientOpPackageName);
+
+    err = mClientManager.addClient(std::move(clientInfo3));
+    EXPECT_TRUE(err == OK);
+
+    size_t numOfClients = mClientManager.getNumOfClients();
+    EXPECT_EQ(numOfClients, 3);
+
+    err = mClientManager.removeClient(kClientId);
+    EXPECT_TRUE(err == OK);
+
+    err = mClientManager.removeClient(kClientId + 1);
+    EXPECT_TRUE(err == OK);
+
+    err = mClientManager.removeClient(kClientId + 2);
+    EXPECT_TRUE(err == OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestRemovingNonExistClient) {
+    status_t err = mClientManager.removeClient(kInvalidClientId);
+    EXPECT_TRUE(err != OK);
+
+    err = mClientManager.removeClient(1000 /* clientId */);
+    EXPECT_TRUE(err != OK);
+}
+
+TEST_F(TranscodingClientManagerTest, TestCheckClientWithClientId) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+
+    std::unique_ptr<TranscodingClientManager::ClientInfo> clientInfo =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    client, kClientId, kClientPid, kClientUid, kClientOpPackageName);
+
+    status_t err = mClientManager.addClient(std::move(clientInfo));
+    EXPECT_TRUE(err == OK);
+
+    bool res = mClientManager.isClientIdRegistered(kClientId);
+    EXPECT_TRUE(res);
+
+    res = mClientManager.isClientIdRegistered(kInvalidClientId);
+    EXPECT_FALSE(res);
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
new file mode 100644
index 0000000..d8e4830
--- /dev/null
+++ b/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+    echo "Android build environment not set"
+    exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount && adb sync
+
+echo "========================================"
+
+echo "testing TranscodingClientManager"
+adb shell /data/nativetest64/TranscodingClientManager_tests/TranscodingClientManager_tests
+
+echo "testing AdjustableMaxPriorityQueue"
+adb shell /data/nativetest64/AdjustableMaxPriorityQueue_tests/AdjustableMaxPriorityQueue_tests
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index a4df38d..04ddcff 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -1,4 +1,3 @@
-
 cc_defaults {
     name: "libnbaio_mono_defaults",
     srcs: [
@@ -9,20 +8,27 @@
     header_libs: [
         "libaudioclient_headers",
         "libaudio_system_headers",
-        "libmedia_headers",
     ],
     export_header_lib_headers: [
         "libaudioclient_headers",
-        "libmedia_headers",
     ],
 
     shared_libs: [
         "libaudioutils",
+        "libcutils",
         "liblog",
         "libutils",
     ],
+    export_shared_lib_headers: [
+        "libaudioutils",
+    ],
 
     export_include_dirs: ["include_mono"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
 }
 
 // libnbaio_mono is the part of libnbaio that is available for vendors to use. Vendor modules can't
@@ -53,20 +59,7 @@
     // ],
     // static_libs: ["libsndfile"],
 
-    shared_libs: [
-        "libaudioutils",
-        "libbinder",
-        "libcutils",
-        "liblog",
-        "libutils",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-
-    include_dirs: ["system/media/audio_utils/include"],
+    header_libs: ["libaudiohal_headers"],
 
     export_include_dirs: ["include"],
 }
diff --git a/media/libnbaio/include_mono/media/nbaio/MonoPipe.h b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
index c51d0fe..926d84a 100644
--- a/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
+++ b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
@@ -19,7 +19,7 @@
 
 #include <time.h>
 #include <audio_utils/fifo.h>
-#include <media/SingleStateQueue.h>
+#include <media/nbaio/SingleStateQueue.h>
 #include <media/nbaio/NBAIO.h>
 
 namespace android {
diff --git a/media/libmedia/include/media/SingleStateQueue.h b/media/libnbaio/include_mono/media/nbaio/SingleStateQueue.h
similarity index 100%
rename from media/libmedia/include/media/SingleStateQueue.h
rename to media/libnbaio/include_mono/media/nbaio/SingleStateQueue.h
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index f556e37..67d028d 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -45,7 +45,12 @@
 }
 
 Reader::Reader(const sp<IMemory>& iMemory, size_t size, const std::string &name)
-    : Reader(iMemory != 0 ? (Shared *) iMemory->pointer() : NULL, size, name)
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    : Reader(iMemory != 0 ? (Shared *) iMemory->unsecurePointer() : NULL, size,
+             name)
 {
     mIMemory = iMemory;
 }
@@ -156,7 +161,8 @@
 
 bool Reader::isIMemory(const sp<IMemory>& iMemory) const
 {
-    return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer();
+    return iMemory != 0 && mIMemory != 0 &&
+           iMemory->unsecurePointer() == mIMemory->unsecurePointer();
 }
 
 // We make a set of the invalid types rather than the valid types when aligning
diff --git a/media/libnblog/ReportPerformance.cpp b/media/libnblog/ReportPerformance.cpp
index b050b83..aa678ba 100644
--- a/media/libnblog/ReportPerformance.cpp
+++ b/media/libnblog/ReportPerformance.cpp
@@ -30,7 +30,7 @@
 #include <sys/time.h>
 #include <utility>
 #include <json/json.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/nblog/Events.h>
 #include <media/nblog/PerformanceAnalysis.h>
 #include <media/nblog/ReportPerformance.h>
@@ -168,7 +168,7 @@
         return false;
     }
 
-    std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("audiothread"));
+    std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("audiothread"));
 
     const Histogram &workHist = data.workHist;
     if (workHist.totalCount() > 0) {
diff --git a/media/libnblog/Writer.cpp b/media/libnblog/Writer.cpp
index da3bd52..86d3b98 100644
--- a/media/libnblog/Writer.cpp
+++ b/media/libnblog/Writer.cpp
@@ -56,7 +56,11 @@
 }
 
 Writer::Writer(const sp<IMemory>& iMemory, size_t size)
-    : Writer(iMemory != 0 ? (Shared *) iMemory->pointer() : NULL, size)
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    : Writer(iMemory != 0 ? (Shared *) iMemory->unsecurePointer() : NULL, size)
 {
     mIMemory = iMemory;
 }
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index e173974..9c0a7a5 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -31,7 +31,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/mediarecorder.h>
 
 namespace android {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 44f246d..63ab654 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -24,6 +24,8 @@
 #include <inttypes.h>
 #include <utils/Trace.h>
 
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
+
 #include <gui/Surface.h>
 
 #include <media/stagefright/ACodec.h>
@@ -45,6 +47,7 @@
 #include <media/hardware/HardwareAPI.h>
 #include <media/MediaBufferHolder.h>
 #include <media/OMXBuffer.h>
+#include <media/omx/1.0/Conversion.h>
 #include <media/omx/1.0/WOmxNode.h>
 
 #include <hidlmemory/mapping.h>
@@ -63,7 +66,9 @@
 
 namespace android {
 
-using binder::Status;
+typedef hardware::media::omx::V1_0::IGraphicBufferSource HGraphicBufferSource;
+
+using hardware::media::omx::V1_0::Status;
 
 enum {
     kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
@@ -98,16 +103,11 @@
     }
 }
 
-static inline status_t statusFromBinderStatus(const Status &status) {
+static inline status_t statusFromBinderStatus(hardware::Return<Status> &&status) {
     if (status.isOk()) {
-        return OK;
-    }
-    status_t err;
-    if ((err = status.serviceSpecificErrorCode()) != OK) {
-        return err;
-    }
-    if ((err = status.transactionError()) != OK) {
-        return err;
+        return static_cast<status_t>(status.withDefault(Status::UNKNOWN_ERROR));
+    } else if (status.isDeadObject()) {
+        return DEAD_OBJECT;
     }
     // Other exception
     return UNKNOWN_ERROR;
@@ -1310,7 +1310,7 @@
     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
     status_t err = configureOutputBuffersFromNativeWindow(
             &bufferCount, &bufferSize, &minUndequeuedBuffers,
-            false /* preregister */);
+            mFlags & kFlagPreregisterMetadataBuffers /* preregister */);
     if (err != OK)
         return err;
     mNumUndequeuedBuffers = minUndequeuedBuffers;
@@ -1780,6 +1780,14 @@
         }
     }
 
+    int32_t lowLatency = 0;
+    if (msg->findInt32("low-latency", &lowLatency)) {
+        err = setLowLatency(lowLatency);
+        if (err != OK) {
+            return err;
+        }
+    }
+
     int32_t prependSPSPPS = 0;
     if (encoder && mIsVideo
             && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
@@ -1888,6 +1896,19 @@
             setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer);
             err = OK; // ignore error for now
         }
+
+        OMX_INDEXTYPE index;
+        if (mOMXNode->getExtensionIndex(
+                "OMX.google.android.index.preregisterMetadataBuffers", &index) == OK) {
+            OMX_CONFIG_BOOLEANTYPE param;
+            InitOMXParams(&param);
+            param.bEnabled = OMX_FALSE;
+            if (mOMXNode->getParameter(index, &param, sizeof(param)) == OK) {
+                if (param.bEnabled == OMX_TRUE) {
+                    mFlags |= kFlagPreregisterMetadataBuffers;
+                }
+            }
+        }
     }
     if (haveNativeWindow) {
         sp<ANativeWindow> nativeWindow =
@@ -2032,17 +2053,34 @@
     if (mIsVideo || mIsImage) {
         // determine need for software renderer
         bool usingSwRenderer = false;
-        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
-            usingSwRenderer = true;
-            haveNativeWindow = false;
-            (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
-        } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
-            err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
-            if (err != OK) {
-                return err;
+        if (haveNativeWindow) {
+            bool requiresSwRenderer = false;
+            OMX_PARAM_U32TYPE param;
+            InitOMXParams(&param);
+            param.nPortIndex = kPortIndexOutput;
+
+            status_t err = mOMXNode->getParameter(
+                    (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidRequiresSwRenderer,
+                    &param, sizeof(param));
+
+            if (err == OK && param.nU32 == 1) {
+                requiresSwRenderer = true;
             }
+
+            if (mComponentName.startsWith("OMX.google.") || requiresSwRenderer) {
+                usingSwRenderer = true;
+                haveNativeWindow = false;
+                (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
+            } else if (!storingMetadataInDecodedBuffers()) {
+                err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
+                if (err != OK) {
+                    return err;
+                }
+            }
+
         }
 
+
         if (encoder) {
             err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
         } else {
@@ -2160,12 +2198,20 @@
             }
             if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
                 // value is unknown
-                drc.targetRefLevel = -1;
+                drc.targetRefLevel = -2;
             }
             if (!msg->findInt32("aac-drc-effect-type", &drc.effectType)) {
                 // value is unknown
                 drc.effectType = -2; // valid values are -1 and over
             }
+            if (!msg->findInt32("aac-drc-album-mode", &drc.albumMode)) {
+                // value is unknown
+                drc.albumMode = -1; // valid values are 0 and 1
+            }
+            if (!msg->findInt32("aac-drc-output-loudness", &drc.outputLoudness)) {
+                // value is unknown
+                drc.outputLoudness = -1;
+            }
 
             err = setupAACCodec(
                     encoder, numChannels, sampleRate, bitrate, aacProfile,
@@ -2348,6 +2394,24 @@
     return err;
 }
 
+status_t ACodec::setLowLatency(int32_t lowLatency) {
+    if (mIsEncoder) {
+        ALOGE("encoder does not support low-latency");
+        return BAD_VALUE;
+    }
+
+    OMX_CONFIG_BOOLEANTYPE config;
+    InitOMXParams(&config);
+    config.bEnabled = (OMX_BOOL)(lowLatency != 0);
+    status_t err = mOMXNode->setConfig(
+            (OMX_INDEXTYPE)OMX_IndexConfigLowLatency,
+            &config, sizeof(config));
+    if (err != OK) {
+        ALOGE("decoder can not set low-latency to %d (err %d)", lowLatency, err);
+    }
+    return err;
+}
+
 status_t ACodec::setLatency(uint32_t latency) {
     OMX_PARAM_U32TYPE config;
     InitOMXParams(&config);
@@ -2410,7 +2474,7 @@
         }
         rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
     } else {
-        if (rateFloat > UINT_MAX) {
+        if (rateFloat > (float)UINT_MAX) {
             return BAD_VALUE;
         }
         rate = (OMX_U32)(rateFloat);
@@ -2837,6 +2901,8 @@
     presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
     presentation.nPCMLimiterEnable = pcmLimiterEnable;
     presentation.nDrcEffectType = drc.effectType;
+    presentation.nDrcAlbumMode = drc.albumMode;
+    presentation.nDrcOutputLoudness = drc.outputLoudness;
 
     status_t res = mOMXNode->setParameter(
             OMX_IndexParamAudioAac, &profile, sizeof(profile));
@@ -3316,6 +3382,7 @@
     { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
     { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
     { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC },
+    { MEDIA_MIMETYPE_VIDEO_AV1, OMX_VIDEO_CodingAV1 },
 };
 
 static status_t GetVideoCodingTypeFromMime(
@@ -6880,8 +6947,11 @@
         return err;
     }
 
+    using hardware::media::omx::V1_0::utils::TWOmxNode;
     err = statusFromBinderStatus(
-            mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
+            mCodec->mGraphicBufferSource->configure(
+                    new TWOmxNode(mCodec->mOMXNode),
+                    static_cast<hardware::graphics::common::V1_0::Dataspace>(dataSpace)));
     if (err != OK) {
         ALOGE("[%s] Unable to configure for node (err %d)",
               mCodec->mComponentName.c_str(), err);
@@ -6967,8 +7037,9 @@
         }
 
         err = statusFromBinderStatus(
-                mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32(
-                        *(ColorAspects *)colorAspectsBuffer->base())));
+                mCodec->mGraphicBufferSource->setColorAspects(
+                        hardware::media::omx::V1_0::utils::toHardwareColorAspects(
+                                *(ColorAspects *)colorAspectsBuffer->base())));
 
         if (err != OK) {
             ALOGE("[%s] Unable to configure color aspects (err %d)",
@@ -6984,8 +7055,10 @@
     ALOGV("onCreateInputSurface");
 
     sp<IGraphicBufferProducer> bufferProducer;
+    sp<HGraphicBufferSource> bufferSource;
     status_t err = mCodec->mOMX->createInputSurface(
-            &bufferProducer, &mCodec->mGraphicBufferSource);
+            &bufferProducer, &bufferSource);
+    mCodec->mGraphicBufferSource = bufferSource;
 
     if (err == OK) {
         err = setupInputSurface();
@@ -7018,8 +7091,12 @@
     }
 
     sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
-    mCodec->mGraphicBufferSource = surface->getBufferSource();
-    status_t err = setupInputSurface();
+    sp<HGraphicBufferSource> hgbs = HGraphicBufferSource::castFrom(surface->getHidlTarget());
+    status_t err = BAD_VALUE;
+    if (hgbs) {
+        mCodec->mGraphicBufferSource = hgbs;
+        err = setupInputSurface();
+    }
 
     if (err == OK) {
         mCodec->mCallback->onInputSurfaceAccepted(
@@ -7538,8 +7615,14 @@
         }
 
         int64_t stopTimeOffsetUs;
-        err = statusFromBinderStatus(
-                mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs));
+        hardware::Return<void> trans = mGraphicBufferSource->getStopTimeOffsetUs(
+                [&err, &stopTimeOffsetUs](auto status, auto result) {
+                    err = static_cast<status_t>(status);
+                    stopTimeOffsetUs = result;
+                });
+        if (!trans.isOk()) {
+            err = trans.isDeadObject() ? DEAD_OBJECT : UNKNOWN_ERROR;
+        }
 
         if (err != OK) {
             ALOGE("Failed to get stop time offset (err %d)", err);
@@ -7582,6 +7665,14 @@
         }
     }
 
+    int32_t lowLatency = 0;
+    if (params->findInt32("low-latency", &lowLatency)) {
+        status_t err = setLowLatency(lowLatency);
+        if (err != OK) {
+            return err;
+        }
+    }
+
     int32_t latency = 0;
     if (params->findInt32("latency", &latency) && latency > 0) {
         status_t err = setLatency(latency);
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 266a240..88b15ae 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -20,10 +20,16 @@
 
 #include <numeric>
 
+#include <C2Buffer.h>
+
+#include <Codec2BufferUtils.h>
+
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
 #include <binder/MemoryDealer.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <media/openmax/OMX_Core.h>
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaCodec.h>
@@ -41,6 +47,7 @@
 using hardware::hidl_vec;
 using namespace hardware::cas::V1_0;
 using namespace hardware::cas::native::V1_0;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
 using BufferInfo = ACodecBufferChannel::BufferInfo;
 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
 
@@ -87,15 +94,27 @@
 }
 
 status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
-    if (mDealer != nullptr) {
-        return -ENOSYS;
-    }
     std::shared_ptr<const std::vector<const BufferInfo>> array(
             std::atomic_load(&mInputBuffers));
     BufferInfoIterator it = findClientBuffer(array, buffer);
     if (it == array->end()) {
         return -ENOENT;
     }
+    if (it->mClientBuffer != it->mCodecBuffer) {
+        // Copy metadata from client to codec buffer.
+        it->mCodecBuffer->meta()->clear();
+        int64_t timeUs;
+        CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
+        it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
+        int32_t eos;
+        if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
+            it->mCodecBuffer->meta()->setInt32("eos", eos);
+        }
+        int32_t csd;
+        if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
+            it->mCodecBuffer->meta()->setInt32("csd", csd);
+        }
+    }
     ALOGV("queueInputBuffer #%d", it->mBufferId);
     sp<AMessage> msg = mInputBufferFilled->dup();
     msg->setObject("buffer", it->mCodecBuffer);
@@ -130,19 +149,24 @@
     }
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
-    if (mCrypto != NULL) {
-        ICrypto::DestinationBuffer destination;
+    if (numSubSamples == 1
+            && subSamples[0].mNumBytesOfClearData == 0
+            && subSamples[0].mNumBytesOfEncryptedData == 0) {
+        // We don't need to go through crypto or descrambler if the input is empty.
+        result = 0;
+    } else if (mCrypto != NULL) {
+        hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
-            destination.mType = ICrypto::kDestinationTypeNativeHandle;
-            destination.mHandle = secureHandle;
+            destination.type = DrmBufferType::NATIVE_HANDLE;
+            destination.secureMemory = hidl_handle(secureHandle);
         } else {
-            destination.mType = ICrypto::kDestinationTypeSharedMemory;
-            destination.mSharedMemory = mDecryptDestination;
+            destination.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
         }
 
-        ICrypto::SourceBuffer source;
-        source.mSharedMemory = it->mSharedEncryptedBuffer;
-        source.mHeapSeqNum = mHeapSeqNum;
+        hardware::drm::V1_0::SharedBuffer source;
+        IMemoryToSharedBuffer(it->mSharedEncryptedBuffer, mHeapSeqNum, &source);
 
         result = mCrypto->decrypt(key, iv, mode, pattern,
                 source, it->mClientBuffer->offset(),
@@ -152,8 +176,8 @@
             return result;
         }
 
-        if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
-            memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
+        if (destination.type == DrmBufferType::SHARED_MEMORY) {
+            memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
         }
     } else {
         // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
@@ -219,7 +243,8 @@
 
         if (dstBuffer.type == BufferType::SHARED_MEMORY) {
             memcpy(it->mCodecBuffer->base(),
-                    (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
+                    (uint8_t*)it->mSharedEncryptedBuffer->unsecurePointer(),
+                    result);
         }
     }
 
@@ -247,6 +272,192 @@
     return OK;
 }
 
+status_t ACodecBufferChannel::attachBuffer(
+        const std::shared_ptr<C2Buffer> &c2Buffer,
+        const sp<MediaCodecBuffer> &buffer) {
+    switch (c2Buffer->data().type()) {
+        case C2BufferData::LINEAR: {
+            if (c2Buffer->data().linearBlocks().size() != 1u) {
+                return -ENOSYS;
+            }
+            C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
+            C2ReadView view{block.map().get()};
+            size_t copyLength = std::min(size_t(view.capacity()), buffer->capacity());
+            ALOGV_IF(view.capacity() > buffer->capacity(),
+                    "view.capacity() = %zu, buffer->capacity() = %zu",
+                    view.capacity(), buffer->capacity());
+            memcpy(buffer->base(), view.data(), copyLength);
+            buffer->setRange(0, copyLength);
+            break;
+        }
+        case C2BufferData::GRAPHIC: {
+            sp<ABuffer> imageData;
+            if (!buffer->format()->findBuffer("image-data", &imageData)) {
+                return -ENOSYS;
+            }
+            if (c2Buffer->data().graphicBlocks().size() != 1u) {
+                return -ENOSYS;
+            }
+            C2ConstGraphicBlock block{c2Buffer->data().graphicBlocks().front()};
+            const C2GraphicView view{block.map().get()};
+            status_t err = ImageCopy(
+                    buffer->base(), (const MediaImage2 *)(imageData->base()), view);
+            if (err != OK) {
+                return err;
+            }
+            break;
+        }
+        case C2BufferData::LINEAR_CHUNKS:  [[fallthrough]];
+        case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
+        default:
+            return -ENOSYS;
+    }
+
+    return OK;
+}
+
+int32_t ACodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) {
+    CHECK(mCrypto);
+    auto it = mHeapSeqNumMap.find(memory);
+    int32_t heapSeqNum = -1;
+    if (it == mHeapSeqNumMap.end()) {
+        heapSeqNum = mCrypto->setHeap(memory);
+        mHeapSeqNumMap.emplace(memory, heapSeqNum);
+    } else {
+        heapSeqNum = it->second;
+    }
+    return heapSeqNum;
+}
+
+status_t ACodecBufferChannel::attachEncryptedBuffer(
+        const sp<hardware::HidlMemory> &memory,
+        bool secure,
+        const uint8_t *key,
+        const uint8_t *iv,
+        CryptoPlugin::Mode mode,
+        CryptoPlugin::Pattern pattern,
+        size_t offset,
+        const CryptoPlugin::SubSample *subSamples,
+        size_t numSubSamples,
+        const sp<MediaCodecBuffer> &buffer) {
+    std::shared_ptr<const std::vector<const BufferInfo>> array(
+            std::atomic_load(&mInputBuffers));
+    BufferInfoIterator it = findClientBuffer(array, buffer);
+    if (it == array->end()) {
+        return -ENOENT;
+    }
+
+    native_handle_t *secureHandle = NULL;
+    if (secure) {
+        sp<SecureBuffer> secureData =
+                static_cast<SecureBuffer *>(it->mCodecBuffer.get());
+        if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
+            return BAD_VALUE;
+        }
+        secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
+    }
+    size_t size = 0;
+    for (size_t i = 0; i < numSubSamples; ++i) {
+        size += subSamples[i].mNumBytesOfClearData + subSamples[i].mNumBytesOfEncryptedData;
+    }
+    ssize_t result = -1;
+    ssize_t codecDataOffset = 0;
+    if (mCrypto != NULL) {
+        AString errorDetailMsg;
+        hardware::drm::V1_0::DestinationBuffer destination;
+        if (secure) {
+            destination.type = DrmBufferType::NATIVE_HANDLE;
+            destination.secureMemory = hidl_handle(secureHandle);
+        } else {
+            destination.type = DrmBufferType::SHARED_MEMORY;
+            IMemoryToSharedBuffer(
+                    mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
+        }
+
+        int32_t heapSeqNum = getHeapSeqNum(memory);
+        hardware::drm::V1_0::SharedBuffer source{(uint32_t)heapSeqNum, offset, size};
+
+        result = mCrypto->decrypt(key, iv, mode, pattern,
+                source, it->mClientBuffer->offset(),
+                subSamples, numSubSamples, destination, &errorDetailMsg);
+
+        if (result < 0) {
+            return result;
+        }
+
+        if (destination.type == DrmBufferType::SHARED_MEMORY) {
+            memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
+        }
+    } else {
+        // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
+        // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
+        hidl_vec<SubSample> hidlSubSamples;
+        hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
+
+        hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
+                .heapBase = *memory,
+                .offset = (uint64_t) offset,
+                .size = size
+        };
+
+        DestinationBuffer dstBuffer;
+        if (secure) {
+            dstBuffer.type = BufferType::NATIVE_HANDLE;
+            dstBuffer.secureMemory = hidl_handle(secureHandle);
+        } else {
+            dstBuffer.type = BufferType::SHARED_MEMORY;
+            dstBuffer.nonsecureMemory = srcBuffer;
+        }
+
+        Status status = Status::OK;
+        hidl_string detailedError;
+        ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;
+
+        if (key != NULL) {
+            sctrl = (ScramblingControl)key[0];
+            // Adjust for the PES offset
+            codecDataOffset = key[2] | (key[3] << 8);
+        }
+
+        auto returnVoid = mDescrambler->descramble(
+                sctrl,
+                hidlSubSamples,
+                srcBuffer,
+                0,
+                dstBuffer,
+                0,
+                [&status, &result, &detailedError] (
+                        Status _status, uint32_t _bytesWritten,
+                        const hidl_string& _detailedError) {
+                    status = _status;
+                    result = (ssize_t)_bytesWritten;
+                    detailedError = _detailedError;
+                });
+
+        if (!returnVoid.isOk() || status != Status::OK || result < 0) {
+            ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
+                    returnVoid.description().c_str(), status, result);
+            return UNKNOWN_ERROR;
+        }
+
+        if (result < codecDataOffset) {
+            ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
+            return BAD_VALUE;
+        }
+
+        ALOGV("descramble succeeded, %zd bytes", result);
+
+        if (dstBuffer.type == BufferType::SHARED_MEMORY) {
+            memcpy(it->mCodecBuffer->base(),
+                    (uint8_t*)it->mSharedEncryptedBuffer->unsecurePointer(),
+                    result);
+        }
+    }
+
+    it->mCodecBuffer->setRange(codecDataOffset, result - codecDataOffset);
+    return OK;
+}
+
 status_t ACodecBufferChannel::renderOutputBuffer(
         const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
     std::shared_ptr<const std::vector<const BufferInfo>> array(
@@ -313,7 +524,8 @@
     }
     dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
     if (mCrypto != nullptr) {
-        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
+        sp<HidlMemory> hHeap = fromHeap(dealer->getMemoryHeap());
+        int32_t seqNum = mCrypto->setHeap(hHeap);
         if (seqNum >= 0) {
             mHeapSeqNum = seqNum;
             ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
@@ -429,4 +641,22 @@
             it->mClientBuffer);
 }
 
+void ACodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
+    if (mCrypto != nullptr) {
+        for (std::pair<wp<HidlMemory>, int32_t> entry : mHeapSeqNumMap) {
+            mCrypto->unsetHeap(entry.second);
+        }
+        mHeapSeqNumMap.clear();
+        if (mHeapSeqNum >= 0) {
+            mCrypto->unsetHeap(mHeapSeqNum);
+            mHeapSeqNum = -1;
+        }
+    }
+    mCrypto = crypto;
+}
+
+void ACodecBufferChannel::setDescrambler(const sp<IDescrambler> &descrambler) {
+    mDescrambler = descrambler;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 24f6f0b..a1aa5dd 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -26,7 +26,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/mediarecorder.h>
 
 namespace android {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 7eab230..3bccb7b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -2,10 +2,21 @@
     name: "libstagefright_headers",
     export_include_dirs: ["include"],
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
 }
 
 cc_library_static {
     name: "libstagefright_esds",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+    ],
+    min_sdk_version: "29",
 
     srcs: ["ESDS.cpp"],
 
@@ -19,12 +30,19 @@
         ],
         cfi: true,
     },
-
-    shared_libs: ["libmedia"],
+    shared_libs: [
+        "libstagefright_foundation",
+        "libutils"
+    ],
 }
 
 cc_library_static {
     name: "libstagefright_metadatautils",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+    ],
+    min_sdk_version: "29",
 
     srcs: ["MetaDataUtils.cpp"],
 
@@ -39,7 +57,11 @@
         cfi: true,
     },
 
-    shared_libs: ["libmedia", "libmediandk"],
+    header_libs: [
+        "libstagefright_foundation_headers",
+    ],
+    shared_libs: ["libmediandk"],
+    export_include_dirs: ["include"],
 }
 
 cc_library_shared {
@@ -51,6 +73,7 @@
         "CodecBase.cpp",
         "FrameRenderTracker.cpp",
         "MediaCodecListWriter.cpp",
+        "SkipCutBuffer.cpp",
     ],
 
     cflags: [
@@ -58,14 +81,22 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+        "media_ndk_headers",
+    ],
+
     shared_libs: [
         "libgui",
+        "libhidlallocatorutils",
         "liblog",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libstagefright_foundation",
         "libui",
         "libutils",
         "android.hardware.cas.native@1.0",
+        "android.hardware.drm@1.0",
     ],
 
     sanitize: {
@@ -79,6 +110,11 @@
 
 cc_library_static {
     name: "libstagefright_mpeg2extractor",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+    ],
+    min_sdk_version: "29",
 
     srcs: [
         "Utils.cpp",
@@ -88,14 +124,18 @@
 
     shared_libs: [
         "liblog",
-        "libmedia",
-        "libmedia_omx",
     ],
 
     export_include_dirs: [
         "include",
     ],
 
+    header_libs: [
+        "libaudioclient_headers",
+        "libmedia_headers",
+        "media_ndk_headers",
+    ],
+
     cflags: [
         "-Wno-multichar",
         "-Werror",
@@ -112,6 +152,53 @@
     },
 }
 
+cc_library_shared {
+    name: "libstagefright_framecapture_utils",
+
+    srcs: [
+        "FrameCaptureLayer.cpp",
+        "FrameCaptureProcessor.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libgui",
+        "liblog",
+        "libprocessgroup",
+        "libstagefright_foundation",
+        "libsync",
+        "libui",
+        "libutils",
+    ],
+
+    static_libs: [
+        "librenderengine",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Wno-multichar",
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        // TODO: re-enabled cfi for this lib after b/139945549 fixed
+        cfi: false,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
 cc_library {
     name: "libstagefright",
 
@@ -121,7 +208,6 @@
         "ACodecBufferChannel.cpp",
         "AHierarchicalStateMachine.cpp",
         "AMRWriter.cpp",
-        "AudioPlayer.cpp",
         "AudioSource.cpp",
         "BufferImpl.cpp",
         "CallbackDataSource.cpp",
@@ -129,12 +215,7 @@
         "CameraSource.cpp",
         "CameraSourceTimeLapse.cpp",
         "DataConverter.cpp",
-        "DataSourceFactory.cpp",
-        "DataURISource.cpp",
-        "ClearFileSource.cpp",
-        "FileSource.cpp",
         "FrameDecoder.cpp",
-        "HTTPBase.cpp",
         "HevcUtils.cpp",
         "InterfaceUtils.cpp",
         "JPEGSource.cpp",
@@ -151,10 +232,7 @@
         "MediaSource.cpp",
         "MediaSync.cpp",
         "MediaTrack.cpp",
-        "http/ClearMediaHTTP.cpp",
-        "http/MediaHTTP.cpp",
         "MediaMuxer.cpp",
-        "NuCachedSource2.cpp",
         "NuMediaExtractor.cpp",
         "OggWriter.cpp",
         "OMXClient.cpp",
@@ -162,37 +240,40 @@
         "RemoteMediaExtractor.cpp",
         "RemoteMediaSource.cpp",
         "SimpleDecodingSource.cpp",
-        "SkipCutBuffer.cpp",
         "StagefrightMediaScanner.cpp",
-        "StagefrightMetadataRetriever.cpp",
-        "StagefrightPluginLoader.cpp",
         "SurfaceUtils.cpp",
-        "Utils.cpp",
         "ThrottledSource.cpp",
+        "Utils.cpp",
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
     ],
 
     shared_libs: [
+        "libstagefright_framecapture_utils",
         "libaudioutils",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libcamera_client",
+        "libcodec2",
+        "libcodec2_vndk",
         "libcutils",
+        "libdatasource",
         "libdl",
         "libdl_android",
-        "libdrmframework",
         "libgui",
         "liblog",
         "libmedia",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmedia_omx_client",
         "libaudioclient",
         "libmediametrics",
-        "libmediautils",
         "libui",
         "libutils",
         "libmedia_helper",
+        "libsfplugin_ccodec",
+        "libsfplugin_ccodec_utils",
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx_utils",
@@ -202,10 +283,12 @@
         "libhidlmemory",
         "android.hidl.allocator@1.0",
         "android.hardware.cas.native@1.0",
+        "android.hardware.drm@1.0",
         "android.hardware.media.omx@1.0",
     ],
 
     static_libs: [
+        "libstagefright_esds",
         "libstagefright_color_conversion",
         "libyuv_static",
         "libstagefright_mediafilter",
@@ -213,13 +296,12 @@
         "libstagefright_timedtext",
         "libogg",
         "libwebm",
-        "libstagefright_esds",
         "libstagefright_id3",
-        "libFLAC",
     ],
 
     header_libs:[
-        "libnativeloader-dummy-headers",
+        "libmediadrm_headers",
+        "libnativeloader-headers",
         "libstagefright_xmlparser_headers",
         "media_ndk_headers",
     ],
@@ -259,62 +341,3 @@
         ],
     },
 }
-
-cc_library_static {
-    name: "libstagefright_player2",
-
-    srcs: [
-        "ClearFileSource.cpp",
-        "DataURISource.cpp",
-        "HTTPBase.cpp",
-        "HevcUtils.cpp",
-        "MediaClock.cpp",
-        "MediaSource.cpp",
-        "NdkUtils.cpp",
-        "Utils.cpp",
-        "VideoFrameSchedulerBase.cpp",
-        "VideoFrameScheduler2.cpp",
-        "http/ClearMediaHTTP.cpp",
-    ],
-
-    shared_libs: [
-        "libgui",
-        "liblog",
-        "libnetd_client",
-        "libutils",
-        "libstagefright_foundation",
-        "libandroid",
-    ],
-
-    static_libs: [
-        "libmedia_player2_util",
-        "libmedia2_jni_core",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    cflags: [
-        "-Wno-multichar",
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
-        "-Wall",
-    ],
-
-    product_variables: {
-        debuggable: {
-            // enable experiments only in userdebug and eng builds
-            cflags: ["-DENABLE_STAGEFRIGHT_EXPERIMENTS"],
-        },
-    },
-
-    sanitize: {
-        cfi: true,
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-}
-
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
deleted file mode 100644
index 199b57b..0000000
--- a/media/libstagefright/AudioPlayer.cpp
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * Copyright (C) 2009 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 <inttypes.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AudioPlayer"
-#include <utils/Log.h>
-#include <cutils/compiler.h>
-
-#include <binder/IPCThreadState.h>
-#include <media/AudioTrack.h>
-#include <media/MediaSource.h>
-#include <media/openmax/OMX_Audio.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALookup.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-AudioPlayer::AudioPlayer(
-        const sp<MediaPlayerBase::AudioSink> &audioSink,
-        uint32_t flags)
-    : mInputBuffer(NULL),
-      mSampleRate(0),
-      mLatencyUs(0),
-      mFrameSize(0),
-      mNumFramesPlayed(0),
-      mNumFramesPlayedSysTimeUs(ALooper::GetNowUs()),
-      mPositionTimeMediaUs(-1),
-      mPositionTimeRealUs(-1),
-      mSeeking(false),
-      mReachedEOS(false),
-      mFinalStatus(OK),
-      mSeekTimeUs(0),
-      mStarted(false),
-      mIsFirstBuffer(false),
-      mFirstBufferResult(OK),
-      mFirstBuffer(NULL),
-      mAudioSink(audioSink),
-      mPlaying(false),
-      mStartPosUs(0),
-      mCreateFlags(flags) {
-}
-
-AudioPlayer::~AudioPlayer() {
-    if (mStarted) {
-        reset();
-    }
-}
-
-void AudioPlayer::setSource(const sp<MediaSource> &source) {
-    CHECK(mSource == NULL);
-    mSource = source;
-}
-
-ALookup<audio_format_t, int32_t> sAudioFormatToPcmEncoding {
-    {
-        { AUDIO_FORMAT_PCM_16_BIT, kAudioEncodingPcm16bit },
-        { AUDIO_FORMAT_PCM_8_BIT,  kAudioEncodingPcm8bit  },
-        { AUDIO_FORMAT_PCM_FLOAT,  kAudioEncodingPcmFloat },
-    }
-};
-
-status_t AudioPlayer::start(bool sourceAlreadyStarted) {
-    CHECK(!mStarted);
-    CHECK(mSource != NULL);
-
-    status_t err;
-    if (!sourceAlreadyStarted) {
-        err = mSource->start();
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
-    // of playback, if there is one, getFormat below will retrieve the
-    // updated format, if there isn't, we'll stash away the valid buffer
-    // of data to be used on the first audio callback.
-
-    CHECK(mFirstBuffer == NULL);
-
-    MediaSource::ReadOptions options;
-    if (mSeeking) {
-        options.setSeekTo(mSeekTimeUs);
-        mSeeking = false;
-    }
-
-    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
-    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
-        ALOGV("INFO_FORMAT_CHANGED!!!");
-
-        CHECK(mFirstBuffer == NULL);
-        mFirstBufferResult = OK;
-        mIsFirstBuffer = false;
-    } else {
-        mIsFirstBuffer = true;
-    }
-
-    sp<MetaData> format = mSource->getFormat();
-
-    if (format == NULL) {
-        ALOGE("No metadata b/118620871");
-        android_errorWriteLog(0x534e4554, "118620871");
-        return BAD_VALUE;
-    }
-
-    const char *mime;
-    bool success = format->findCString(kKeyMIMEType, &mime);
-    CHECK(success);
-    CHECK(useOffload() || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
-
-    success = format->findInt32(kKeySampleRate, &mSampleRate);
-    CHECK(success);
-
-    int32_t numChannels, channelMask;
-    success = format->findInt32(kKeyChannelCount, &numChannels);
-    CHECK(success);
-
-    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
-        // log only when there's a risk of ambiguity of channel mask selection
-        ALOGI_IF(numChannels > 2,
-                "source format didn't specify channel mask, using (%d) channel order", numChannels);
-        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
-    }
-
-    audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
-    int32_t pcmEncoding;
-    if (format->findInt32(kKeyPcmEncoding, &pcmEncoding)) {
-        sAudioFormatToPcmEncoding.map(pcmEncoding, &audioFormat);
-    }
-
-    if (useOffload()) {
-        if (mapMimeToAudioFormat(audioFormat, mime) != OK) {
-            ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime);
-            audioFormat = AUDIO_FORMAT_INVALID;
-        } else {
-            ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, audioFormat);
-        }
-
-        int32_t aacaot = -1;
-        if ((audioFormat == AUDIO_FORMAT_AAC) && format->findInt32(kKeyAACAOT, &aacaot)) {
-            // Redefine AAC format corrosponding to aac profile
-            mapAACProfileToAudioFormat(audioFormat,(OMX_AUDIO_AACPROFILETYPE) aacaot);
-        }
-    }
-
-    int avgBitRate = -1;
-    format->findInt32(kKeyBitRate, &avgBitRate);
-
-    if (mAudioSink.get() != NULL) {
-
-        uint32_t flags = AUDIO_OUTPUT_FLAG_NONE;
-        audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
-
-        if (allowDeepBuffering()) {
-            flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        }
-        if (useOffload()) {
-            flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-
-            int64_t durationUs;
-            if (format->findInt64(kKeyDuration, &durationUs)) {
-                offloadInfo.duration_us = durationUs;
-            } else {
-                offloadInfo.duration_us = -1;
-            }
-
-            offloadInfo.sample_rate = mSampleRate;
-            offloadInfo.channel_mask = channelMask;
-            offloadInfo.format = audioFormat;
-            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
-            offloadInfo.bit_rate = avgBitRate;
-            offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0);
-            offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0);
-        }
-
-        status_t err = mAudioSink->open(
-                mSampleRate, numChannels, channelMask, audioFormat,
-                DEFAULT_AUDIOSINK_BUFFERCOUNT,
-                &AudioPlayer::AudioSinkCallback,
-                this,
-                (audio_output_flags_t)flags,
-                useOffload() ? &offloadInfo : NULL);
-
-        if (err == OK) {
-            mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
-            mFrameSize = mAudioSink->frameSize();
-
-            if (useOffload()) {
-                // If the playback is offloaded to h/w we pass the
-                // HAL some metadata information
-                // We don't want to do this for PCM because it will be going
-                // through the AudioFlinger mixer before reaching the hardware
-                sendMetaDataToHal(mAudioSink, format);
-            }
-
-            err = mAudioSink->start();
-            // do not alter behavior for non offloaded tracks: ignore start status.
-            if (!useOffload()) {
-                err = OK;
-            }
-        }
-
-        if (err != OK) {
-            if (mFirstBuffer != NULL) {
-                mFirstBuffer->release();
-                mFirstBuffer = NULL;
-            }
-
-            if (!sourceAlreadyStarted) {
-                mSource->stop();
-            }
-
-            return err;
-        }
-
-    } else {
-        // playing to an AudioTrack, set up mask if necessary
-        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
-                audio_channel_out_mask_from_count(numChannels) : channelMask;
-        if (0 == audioMask) {
-            return BAD_VALUE;
-        }
-
-        mAudioTrack = new AudioTrack(
-                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
-                0 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this,
-                0 /*notificationFrames*/);
-
-        if ((err = mAudioTrack->initCheck()) != OK) {
-            mAudioTrack.clear();
-
-            if (mFirstBuffer != NULL) {
-                mFirstBuffer->release();
-                mFirstBuffer = NULL;
-            }
-
-            if (!sourceAlreadyStarted) {
-                mSource->stop();
-            }
-
-            return err;
-        }
-
-        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
-        mFrameSize = mAudioTrack->frameSize();
-
-        mAudioTrack->start();
-    }
-
-    mStarted = true;
-    mPlaying = true;
-
-    return OK;
-}
-
-void AudioPlayer::pause(bool playPendingSamples) {
-    CHECK(mStarted);
-
-    if (playPendingSamples) {
-        if (mAudioSink.get() != NULL) {
-            mAudioSink->stop();
-        } else {
-            mAudioTrack->stop();
-        }
-
-        mNumFramesPlayed = 0;
-        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
-    } else {
-        if (mAudioSink.get() != NULL) {
-            mAudioSink->pause();
-        } else {
-            mAudioTrack->pause();
-        }
-    }
-
-    mPlaying = false;
-}
-
-status_t AudioPlayer::resume() {
-    CHECK(mStarted);
-    status_t err;
-
-    if (mAudioSink.get() != NULL) {
-        err = mAudioSink->start();
-    } else {
-        err = mAudioTrack->start();
-    }
-
-    if (err == OK) {
-        mPlaying = true;
-    }
-
-    return err;
-}
-
-void AudioPlayer::reset() {
-    CHECK(mStarted);
-
-    ALOGV("reset: mPlaying=%d mReachedEOS=%d useOffload=%d",
-                                mPlaying, mReachedEOS, useOffload() );
-
-    if (mAudioSink.get() != NULL) {
-        mAudioSink->stop();
-        // If we're closing and have reached EOS, we don't want to flush
-        // the track because if it is offloaded there could be a small
-        // amount of residual data in the hardware buffer which we must
-        // play to give gapless playback.
-        // But if we're resetting when paused or before we've reached EOS
-        // we can't be doing a gapless playback and there could be a large
-        // amount of data queued in the hardware if the track is offloaded,
-        // so we must flush to prevent a track switch being delayed playing
-        // the buffered data that we don't want now
-        if (!mPlaying || !mReachedEOS) {
-            mAudioSink->flush();
-        }
-
-        mAudioSink->close();
-    } else {
-        mAudioTrack->stop();
-
-        if (!mPlaying || !mReachedEOS) {
-            mAudioTrack->flush();
-        }
-
-        mAudioTrack.clear();
-    }
-
-    // Make sure to release any buffer we hold onto so that the
-    // source is able to stop().
-
-    if (mFirstBuffer != NULL) {
-        mFirstBuffer->release();
-        mFirstBuffer = NULL;
-    }
-
-    if (mInputBuffer != NULL) {
-        ALOGV("AudioPlayer releasing input buffer.");
-
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    mSource->stop();
-
-    // The following hack is necessary to ensure that the OMX
-    // component is completely released by the time we may try
-    // to instantiate it again.
-    // When offloading, the OMX component is not used so this hack
-    // is not needed
-    if (!useOffload()) {
-        wp<MediaSource> tmp = mSource;
-        mSource.clear();
-        while (tmp.promote() != NULL) {
-            usleep(1000);
-        }
-    } else {
-        mSource.clear();
-    }
-    IPCThreadState::self()->flushCommands();
-
-    mNumFramesPlayed = 0;
-    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
-    mPositionTimeMediaUs = -1;
-    mPositionTimeRealUs = -1;
-    mSeeking = false;
-    mSeekTimeUs = 0;
-    mReachedEOS = false;
-    mFinalStatus = OK;
-    mStarted = false;
-    mPlaying = false;
-    mStartPosUs = 0;
-}
-
-// static
-void AudioPlayer::AudioCallback(int event, void *user, void *info) {
-    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
-}
-
-bool AudioPlayer::reachedEOS(status_t *finalStatus) {
-    *finalStatus = OK;
-
-    Mutex::Autolock autoLock(mLock);
-    *finalStatus = mFinalStatus;
-    return mReachedEOS;
-}
-
-status_t AudioPlayer::setPlaybackRate(const AudioPlaybackRate &rate) {
-    if (mAudioSink.get() != NULL) {
-        return mAudioSink->setPlaybackRate(rate);
-    } else if (mAudioTrack != 0){
-        return mAudioTrack->setPlaybackRate(rate);
-    } else {
-        return NO_INIT;
-    }
-}
-
-status_t AudioPlayer::getPlaybackRate(AudioPlaybackRate *rate /* nonnull */) {
-    if (mAudioSink.get() != NULL) {
-        return mAudioSink->getPlaybackRate(rate);
-    } else if (mAudioTrack != 0) {
-        *rate = mAudioTrack->getPlaybackRate();
-        return OK;
-    } else {
-        return NO_INIT;
-    }
-}
-
-// static
-size_t AudioPlayer::AudioSinkCallback(
-        MediaPlayerBase::AudioSink * /* audioSink */,
-        void *buffer, size_t size, void *cookie,
-        MediaPlayerBase::AudioSink::cb_event_t event) {
-    AudioPlayer *me = (AudioPlayer *)cookie;
-
-    switch(event) {
-    case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
-        return me->fillBuffer(buffer, size);
-
-    case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
-        ALOGV("AudioSinkCallback: stream end");
-        me->mReachedEOS = true;
-        break;
-
-    case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
-        ALOGV("AudioSinkCallback: Tear down event");
-        break;
-    }
-
-    return 0;
-}
-
-void AudioPlayer::AudioCallback(int event, void *info) {
-    switch (event) {
-    case AudioTrack::EVENT_MORE_DATA:
-        {
-        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-        size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
-        buffer->size = numBytesWritten;
-        }
-        break;
-
-    case AudioTrack::EVENT_STREAM_END:
-        mReachedEOS = true;
-        break;
-    }
-}
-
-size_t AudioPlayer::fillBuffer(void *data, size_t size) {
-    if (mNumFramesPlayed == 0) {
-        ALOGV("AudioCallback");
-    }
-
-    if (mReachedEOS) {
-        return 0;
-    }
-
-    size_t size_done = 0;
-    size_t size_remaining = size;
-    while (size_remaining > 0) {
-        MediaSource::ReadOptions options;
-        bool refreshSeekTime = false;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-
-            if (mSeeking) {
-                if (mIsFirstBuffer) {
-                    if (mFirstBuffer != NULL) {
-                        mFirstBuffer->release();
-                        mFirstBuffer = NULL;
-                    }
-                    mIsFirstBuffer = false;
-                }
-
-                options.setSeekTo(mSeekTimeUs);
-                refreshSeekTime = true;
-
-                if (mInputBuffer != NULL) {
-                    mInputBuffer->release();
-                    mInputBuffer = NULL;
-                }
-
-                mSeeking = false;
-            }
-        }
-
-        if (mInputBuffer == NULL) {
-            status_t err;
-
-            if (mIsFirstBuffer) {
-                mInputBuffer = mFirstBuffer;
-                mFirstBuffer = NULL;
-                err = mFirstBufferResult;
-
-                mIsFirstBuffer = false;
-            } else {
-                err = mSource->read(&mInputBuffer, &options);
-            }
-
-            CHECK((err == OK && mInputBuffer != NULL)
-                   || (err != OK && mInputBuffer == NULL));
-
-            Mutex::Autolock autoLock(mLock);
-
-            if (err != OK) {
-                if (!mReachedEOS) {
-                    if (useOffload()) {
-                        // no more buffers to push - stop() and wait for STREAM_END
-                        // don't set mReachedEOS until stream end received
-                        if (mAudioSink != NULL) {
-                            mAudioSink->stop();
-                        } else {
-                            mAudioTrack->stop();
-                        }
-                    } else {
-                        mReachedEOS = true;
-                    }
-                }
-
-                mFinalStatus = err;
-                break;
-            }
-
-            if (mAudioSink != NULL) {
-                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
-            } else {
-                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
-            }
-
-            if(mInputBuffer->range_length() != 0) {
-                CHECK(mInputBuffer->meta_data().findInt64(
-                        kKeyTime, &mPositionTimeMediaUs));
-            }
-
-            // need to adjust the mStartPosUs for offload decoding since parser
-            // might not be able to get the exact seek time requested.
-            if (refreshSeekTime) {
-                if (useOffload()) {
-                    mStartPosUs = mPositionTimeMediaUs;
-                    ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
-                }
-                // clear seek time with mLock locked and once we have valid mPositionTimeMediaUs
-                // and mPositionTimeRealUs
-                // before clearing mSeekTimeUs check if a new seek request has been received while
-                // we were reading from the source with mLock released.
-                if (!mSeeking) {
-                    mSeekTimeUs = 0;
-                }
-            }
-
-            if (!useOffload()) {
-                mPositionTimeRealUs =
-                    ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
-                        / mSampleRate;
-                ALOGV("buffer->size() = %zu, "
-                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
-                     mInputBuffer->range_length(),
-                     mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
-            }
-
-        }
-
-        if (mInputBuffer->range_length() == 0) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
-            continue;
-        }
-
-        size_t copy = size_remaining;
-        if (copy > mInputBuffer->range_length()) {
-            copy = mInputBuffer->range_length();
-        }
-
-        memcpy((char *)data + size_done,
-               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
-               copy);
-
-        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
-                                mInputBuffer->range_length() - copy);
-
-        size_done += copy;
-        size_remaining -= copy;
-    }
-
-    if (useOffload()) {
-        // We must ask the hardware what it has played
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
-        ALOGV("mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
-             mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
-    }
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        mNumFramesPlayed += size_done / mFrameSize;
-        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
-    }
-
-    return size_done;
-}
-
-int64_t AudioPlayer::getOutputPlayPositionUs_l()
-{
-    uint32_t playedSamples = 0;
-    uint32_t sampleRate;
-    if (mAudioSink != NULL) {
-        mAudioSink->getPosition(&playedSamples);
-        sampleRate = mAudioSink->getSampleRate();
-    } else {
-        mAudioTrack->getPosition(&playedSamples);
-        sampleRate = mAudioTrack->getSampleRate();
-    }
-    if (sampleRate != 0) {
-        mSampleRate = sampleRate;
-    }
-
-    int64_t playedUs;
-    if (mSampleRate != 0) {
-        playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate;
-    } else {
-        playedUs = 0;
-    }
-
-    // HAL position is relative to the first buffer we sent at mStartPosUs
-    const int64_t renderedDuration = mStartPosUs + playedUs;
-    ALOGV("getOutputPlayPositionUs_l %" PRId64, renderedDuration);
-    return renderedDuration;
-}
-
-status_t AudioPlayer::seekTo(int64_t time_us) {
-    Mutex::Autolock autoLock(mLock);
-
-    ALOGV("seekTo( %" PRId64 " )", time_us);
-
-    mSeeking = true;
-    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
-    mReachedEOS = false;
-    mSeekTimeUs = time_us;
-    mStartPosUs = time_us;
-
-    // Flush resets the number of played frames
-    mNumFramesPlayed = 0;
-    mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
-
-    if (mAudioSink != NULL) {
-        if (mPlaying) {
-            mAudioSink->pause();
-        }
-        mAudioSink->flush();
-        if (mPlaying) {
-            mAudioSink->start();
-        }
-    } else {
-        if (mPlaying) {
-            mAudioTrack->pause();
-        }
-        mAudioTrack->flush();
-        if (mPlaying) {
-            mAudioTrack->start();
-        }
-    }
-
-    return OK;
-}
-
-}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d78d729..4bc861e 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -50,7 +50,7 @@
 }
 
 AudioSource::AudioSource(
-        audio_source_t inputSource, const String16 &opPackageName,
+        const audio_attributes_t *attr, const String16 &opPackageName,
         uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
         uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId,
         audio_microphone_direction_t selectedMicDirection,
@@ -92,7 +92,7 @@
         }
 
         mRecord = new AudioRecord(
-                    inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
+                    AUDIO_SOURCE_DEFAULT, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                     audio_channel_in_mask_from_count(channelCount),
                     opPackageName,
                     (size_t) (bufCount * frameCount),
@@ -104,10 +104,13 @@
                     AUDIO_INPUT_FLAG_NONE,
                     uid,
                     pid,
-                    NULL /*pAttributes*/,
+                    attr,
                     selectedDeviceId,
                     selectedMicDirection,
                     selectedMicFieldDimension);
+        // Set caller name so it can be logged in destructor.
+        // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_MEDIA
+        mRecord->setCallerName("media");
         mInitCheck = mRecord->initCheck();
         if (mInitCheck != OK) {
             mRecord.clear();
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
index b760273..b097324 100644
--- a/media/libstagefright/BufferImpl.cpp
+++ b/media/libstagefright/BufferImpl.cpp
@@ -21,7 +21,7 @@
 #include <binder/IMemory.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <utils/NativeHandle.h>
 
 #include "include/SecureBuffer.h"
@@ -32,7 +32,11 @@
 // SharedMemoryBuffer
 
 SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem)
-    : MediaCodecBuffer(format, new ABuffer(mem->pointer(), mem->size())),
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
+    : MediaCodecBuffer(format, new ABuffer(mem->unsecurePointer(), mem->size())),
       mMemory(mem) {
 }
 
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 92e6eb9..eb3cb45 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -20,9 +20,9 @@
 
 #include "include/CallbackDataSource.h"
 
+#include <android/IDataSource.h>
 #include <binder/IMemory.h>
 #include <binder/IPCThreadState.h>
-#include <media/IDataSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 
 #include <algorithm>
@@ -81,7 +81,8 @@
             return ERROR_OUT_OF_RANGE;
         }
         CHECK(numRead >= 0 && (size_t)numRead <= bufferSize);
-        memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead);
+        memcpy(((uint8_t*)data) + totalNumRead, mMemory->unsecurePointer(),
+            numRead);
         numLeft -= numRead;
         totalNumRead += numRead;
     }
@@ -113,10 +114,6 @@
     }
 }
 
-sp<DecryptHandle> CallbackDataSource::DrmInitialization(const char *mime) {
-    return mIDataSource->DrmInitialization(mime);
-}
-
 sp<IDataSource> CallbackDataSource::getIDataSource() const {
     return mIDataSource;
 }
@@ -190,14 +187,6 @@
     return mSource->flags();
 }
 
-sp<DecryptHandle> TinyCacheSource::DrmInitialization(const char *mime) {
-    // flush cache when DrmInitialization occurs since decrypted
-    // data may differ from what is in cache.
-    mCachedOffset = 0;
-    mCachedSize = 0;
-    return mSource->DrmInitialization(mime);
-}
-
 sp<IDataSource> TinyCacheSource::getIDataSource() const {
     return mSource->getIDataSource();
 }
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 41f5db0..9b3f420 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -89,7 +89,7 @@
 void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
                                     camera_frame_metadata_t * /* metadata */) {
     ALOGV("postData(%d, ptr:%p, size:%zu)",
-         msgType, dataPtr->pointer(), dataPtr->size());
+         msgType, dataPtr->unsecurePointer(), dataPtr->size());
 
     sp<CameraSource> source = mSource.promote();
     if (source.get() != NULL) {
@@ -966,8 +966,12 @@
 
         // Check if frame contains a VideoNativeHandleMetadata.
         if (frame->size() == sizeof(VideoNativeHandleMetadata)) {
-            VideoNativeHandleMetadata *metadata =
-                (VideoNativeHandleMetadata*)(frame->pointer());
+          // TODO: Using unsecurePointer() has some associated security pitfalls
+          //       (see declaration for details).
+          //       Either document why it is safe in this case or address the
+          //       issue (e.g. by copying).
+           VideoNativeHandleMetadata *metadata =
+                (VideoNativeHandleMetadata*)(frame->unsecurePointer());
             if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
                 handle = metadata->pHandle;
             }
@@ -1047,7 +1051,7 @@
     Mutex::Autolock autoLock(mLock);
     for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
          it != mFramesBeingEncoded.end(); ++it) {
-        if ((*it)->pointer() ==  buffer->data()) {
+        if ((*it)->unsecurePointer() ==  buffer->data()) {
             releaseOneRecordingFrame((*it));
             mFramesBeingEncoded.erase(it);
             ++mNumFramesEncoded;
@@ -1102,7 +1106,11 @@
         frameTime = *mFrameTimes.begin();
         mFrameTimes.erase(mFrameTimes.begin());
         mFramesBeingEncoded.push_back(frame);
-        *buffer = new MediaBuffer(frame->pointer(), frame->size());
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        *buffer = new MediaBuffer(frame->unsecurePointer(), frame->size());
         (*buffer)->setObserver(this);
         (*buffer)->add_ref();
         (*buffer)->meta_data().setInt64(kKeyTime, frameTime);
@@ -1248,7 +1256,7 @@
     mMemoryBases.erase(mMemoryBases.begin());
 
     // Wrap native handle in sp<IMemory> so it can be pushed to mFramesReceived.
-    VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->pointer());
+    VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->unsecurePointer());
     metadata->eType = kMetadataBufferTypeNativeHandleSource;
     metadata->pHandle = handle;
 
@@ -1296,7 +1304,11 @@
         mMemoryBases.erase(mMemoryBases.begin());
 
         // Wrap native handle in sp<IMemory> so it can be pushed to mFramesReceived.
-        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->pointer());
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->unsecurePointer());
         metadata->eType = kMetadataBufferTypeNativeHandleSource;
         metadata->pHandle = handle;
 
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 2a819ad..e0a6eb3 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -245,11 +245,11 @@
 
     ALOGV("createIMemoryCopy");
     size_t source_size = source_data->size();
-    void* source_pointer = source_data->pointer();
+    void* source_pointer = source_data->unsecurePointer();
 
     sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size);
     sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size);
-    memcpy(newMemory->pointer(), source_pointer, source_size);
+    memcpy(newMemory->unsecurePointer(), source_pointer, source_size);
     return newMemory;
 }
 
diff --git a/media/libstagefright/ClearFileSource.cpp b/media/libstagefright/ClearFileSource.cpp
deleted file mode 100644
index e3a2cb7..0000000
--- a/media/libstagefright/ClearFileSource.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 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 "ClearFileSource"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ClearFileSource.h>
-#include <media/stagefright/Utils.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-namespace android {
-
-ClearFileSource::ClearFileSource(const char *filename)
-    : mFd(-1),
-      mOffset(0),
-      mLength(-1),
-      mName("<null>") {
-
-    if (filename) {
-        mName = String8::format("FileSource(%s)", filename);
-    }
-    ALOGV("%s", filename);
-    mFd = open(filename, O_LARGEFILE | O_RDONLY);
-
-    if (mFd >= 0) {
-        mLength = lseek64(mFd, 0, SEEK_END);
-    } else {
-        ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
-    }
-}
-
-ClearFileSource::ClearFileSource(int fd, int64_t offset, int64_t length)
-    : mFd(fd),
-      mOffset(offset),
-      mLength(length),
-      mName("<null>") {
-    ALOGV("fd=%d (%s), offset=%lld, length=%lld",
-            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
-
-    if (mOffset < 0) {
-        mOffset = 0;
-    }
-    if (mLength < 0) {
-        mLength = 0;
-    }
-    if (mLength > INT64_MAX - mOffset) {
-        mLength = INT64_MAX - mOffset;
-    }
-    struct stat s;
-    if (fstat(fd, &s) == 0) {
-        if (mOffset > s.st_size) {
-            mOffset = s.st_size;
-            mLength = 0;
-        }
-        if (mOffset + mLength > s.st_size) {
-            mLength = s.st_size - mOffset;
-        }
-    }
-    if (mOffset != offset || mLength != length) {
-        ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld",
-                (long long) offset, (long long) length,
-                (long long) mOffset, (long long) mLength);
-    }
-
-    mName = String8::format(
-            "FileSource(fd(%s), %lld, %lld)",
-            nameForFd(fd).c_str(),
-            (long long) mOffset,
-            (long long) mLength);
-
-}
-
-ClearFileSource::~ClearFileSource() {
-    if (mFd >= 0) {
-        ::close(mFd);
-        mFd = -1;
-    }
-}
-
-status_t ClearFileSource::initCheck() const {
-    return mFd >= 0 ? OK : NO_INIT;
-}
-
-ssize_t ClearFileSource::readAt(off64_t offset, void *data, size_t size) {
-    if (mFd < 0) {
-        return NO_INIT;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (mLength >= 0) {
-        if (offset >= mLength) {
-            return 0;  // read beyond EOF.
-        }
-        uint64_t numAvailable = mLength - offset;
-        if ((uint64_t)size > numAvailable) {
-            size = numAvailable;
-        }
-    }
-    return readAt_l(offset, data, size);
-}
-
-ssize_t ClearFileSource::readAt_l(off64_t offset, void *data, size_t size) {
-    off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
-    if (result == -1) {
-        ALOGE("seek to %lld failed", (long long)(offset + mOffset));
-        return UNKNOWN_ERROR;
-    }
-
-    return ::read(mFd, data, size);
-}
-
-status_t ClearFileSource::getSize(off64_t *size) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mFd < 0) {
-        return NO_INIT;
-    }
-
-    *size = mLength;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index d0610b2..5b724aa 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -18,18 +18,26 @@
 #define LOG_TAG "CodecBase"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
-#include <media/ICrypto.h>
+#include <android/hardware/drm/1.0/types.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/ICrypto.h>
 #include <media/stagefright/CodecBase.h>
 #include <utils/Log.h>
 
 namespace android {
 
-void BufferChannelBase::setCrypto(const sp<ICrypto> &crypto) {
-    mCrypto = crypto;
-}
+void BufferChannelBase::IMemoryToSharedBuffer(
+        const sp<IMemory> &memory,
+        int32_t heapSeqNum,
+        hardware::drm::V1_0::SharedBuffer *buf) {
+    ssize_t offset;
+    size_t size;
 
-void BufferChannelBase::setDescrambler(const sp<IDescrambler> &descrambler) {
-    mDescrambler = descrambler;
+    sp<hardware::HidlMemory> hidlMemory;
+    hidlMemory = hardware::fromHeap(memory->getMemory(&offset, &size));
+    buf->bufferId = static_cast<uint32_t>(heapSeqNum);
+    buf->offset = offset >= 0 ? offset : 0;
+    buf->size = size;
 }
 
 } // namespace android
diff --git a/media/libstagefright/DataSourceFactory.cpp b/media/libstagefright/DataSourceFactory.cpp
deleted file mode 100644
index 54bf0cc..0000000
--- a/media/libstagefright/DataSourceFactory.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017 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 "DataSource"
-
-#include "include/HTTPBase.h"
-#include "include/NuCachedSource2.h"
-
-#include <media/MediaHTTPConnection.h>
-#include <media/MediaHTTPService.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/DataURISource.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/MediaHTTP.h>
-#include <utils/String8.h>
-
-namespace android {
-
-// static
-sp<DataSource> DataSourceFactory::CreateFromURI(
-        const sp<MediaHTTPService> &httpService,
-        const char *uri,
-        const KeyedVector<String8, String8> *headers,
-        String8 *contentType,
-        HTTPBase *httpSource) {
-    if (contentType != NULL) {
-        *contentType = "";
-    }
-
-    sp<DataSource> source;
-    if (!strncasecmp("file://", uri, 7)) {
-        source = new FileSource(uri + 7);
-    } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
-        if (httpService == NULL) {
-            ALOGE("Invalid http service!");
-            return NULL;
-        }
-
-        if (httpSource == NULL) {
-            sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
-            if (conn == NULL) {
-                ALOGE("Failed to make http connection from http service!");
-                return NULL;
-            }
-            httpSource = new MediaHTTP(conn);
-        }
-
-        String8 cacheConfig;
-        bool disconnectAtHighwatermark = false;
-        KeyedVector<String8, String8> nonCacheSpecificHeaders;
-        if (headers != NULL) {
-            nonCacheSpecificHeaders = *headers;
-            NuCachedSource2::RemoveCacheSpecificHeaders(
-                    &nonCacheSpecificHeaders,
-                    &cacheConfig,
-                    &disconnectAtHighwatermark);
-        }
-
-        if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
-            ALOGE("Failed to connect http source!");
-            return NULL;
-        }
-
-        if (contentType != NULL) {
-            *contentType = httpSource->getMIMEType();
-        }
-
-        source = NuCachedSource2::Create(
-                httpSource,
-                cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
-                disconnectAtHighwatermark);
-    } else if (!strncasecmp("data:", uri, 5)) {
-        source = DataURISource::Create(uri);
-    } else {
-        // Assume it's a filename.
-        source = new FileSource(uri);
-    }
-
-    if (source == NULL || source->initCheck() != OK) {
-        return NULL;
-    }
-
-    return source;
-}
-
-sp<DataSource> DataSourceFactory::CreateFromFd(int fd, int64_t offset, int64_t length) {
-    sp<FileSource> source = new FileSource(fd, offset, length);
-    return source->initCheck() != OK ? nullptr : source;
-}
-
-sp<DataSource> DataSourceFactory::CreateMediaHTTP(const sp<MediaHTTPService> &httpService) {
-    if (httpService == NULL) {
-        return NULL;
-    }
-
-    sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
-    if (conn == NULL) {
-        return NULL;
-    } else {
-        return new MediaHTTP(conn);
-    }
-}
-
-}  // namespace android
diff --git a/media/libstagefright/DataURISource.cpp b/media/libstagefright/DataURISource.cpp
deleted file mode 100644
index b975b38..0000000
--- a/media/libstagefright/DataURISource.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2014 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 <media/stagefright/DataURISource.h>
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/base64.h>
-
-namespace android {
-
-// static
-sp<DataURISource> DataURISource::Create(const char *uri) {
-    if (strncasecmp("data:", uri, 5)) {
-        return NULL;
-    }
-
-    const char *commaPos = strrchr(uri, ',');
-
-    if (commaPos == NULL) {
-        return NULL;
-    }
-
-    sp<ABuffer> buffer;
-
-    AString tmp(&uri[5], commaPos - &uri[5]);
-
-    if (tmp.endsWith(";base64")) {
-
-        // strip all CR and LF characters.
-        const char *src = commaPos+1;
-        int len = strlen(src) + 1;
-        char *cleansed = (char *) malloc(len);
-        if (cleansed == NULL) return NULL;
-        char *keeping = cleansed;
-        int left = len;
-        for (int i = 0; i < len ; i++)
-        {
-            const char c = *src++;
-            if (c == '\r' || c == '\n') {
-                continue;
-            }
-            *keeping++ = c;
-            left--;
-        }
-        memset(keeping, 0, left);
-
-        AString encoded(cleansed);
-        free(cleansed);
-
-        buffer = decodeBase64(encoded);
-
-        if (buffer == NULL) {
-            ALOGE("Malformed base64 encoded content found.");
-            return NULL;
-        }
-    } else {
-#if 0
-        size_t dataLen = strlen(uri) - tmp.size() - 6;
-        buffer = new ABuffer(dataLen);
-        memcpy(buffer->data(), commaPos + 1, dataLen);
-
-        // unescape
-#else
-        // MediaPlayer doesn't care for this right now as we don't
-        // play any text-based media.
-        return NULL;
-#endif
-    }
-
-    // We don't really care about charset or mime type.
-
-    return new DataURISource(buffer);
-}
-
-DataURISource::DataURISource(const sp<ABuffer> &buffer)
-    : mBuffer(buffer) {
-}
-
-DataURISource::~DataURISource() {
-}
-
-status_t DataURISource::initCheck() const {
-    return OK;
-}
-
-ssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) {
-    if ((offset < 0) || (offset >= (off64_t)mBuffer->size())) {
-        return 0;
-    }
-
-    size_t copy = mBuffer->size() - offset;
-    if (copy > size) {
-        copy = size;
-    }
-
-    memcpy(data, mBuffer->data() + offset, copy);
-
-    return copy;
-}
-
-status_t DataURISource::getSize(off64_t *size) {
-    *size = mBuffer->size();
-
-    return OK;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
deleted file mode 100644
index aee7fd8..0000000
--- a/media/libstagefright/FileSource.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2009 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 "FileSource"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/Utils.h>
-#include <private/android_filesystem_config.h>
-
-namespace android {
-
-FileSource::FileSource(const char *filename)
-    : ClearFileSource(filename),
-      mDecryptHandle(NULL),
-      mDrmManagerClient(NULL),
-      mDrmBufOffset(0),
-      mDrmBufSize(0),
-      mDrmBuf(NULL){
-}
-
-FileSource::FileSource(int fd, int64_t offset, int64_t length)
-    : ClearFileSource(fd, offset, length),
-      mDecryptHandle(NULL),
-      mDrmManagerClient(NULL),
-      mDrmBufOffset(0),
-      mDrmBufSize(0),
-      mDrmBuf(NULL) {
-}
-
-FileSource::~FileSource() {
-    if (mDrmBuf != NULL) {
-        delete[] mDrmBuf;
-        mDrmBuf = NULL;
-    }
-
-    if (mDecryptHandle != NULL) {
-        // To release mDecryptHandle
-        CHECK(mDrmManagerClient);
-        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
-        mDecryptHandle = NULL;
-    }
-
-    if (mDrmManagerClient != NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-}
-
-ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
-    if (mFd < 0) {
-        return NO_INIT;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (mLength >= 0) {
-        if (offset >= mLength) {
-            return 0;  // read beyond EOF.
-        }
-        uint64_t numAvailable = mLength - offset;
-        if ((uint64_t)size > numAvailable) {
-            size = numAvailable;
-        }
-    }
-
-    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
-            == mDecryptHandle->decryptApiType) {
-        return readAtDRM_l(offset, data, size);
-   } else {
-        return readAt_l(offset, data, size);
-    }
-}
-
-sp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
-    if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
-    if (mDrmManagerClient == NULL) {
-        mDrmManagerClient = new DrmManagerClient();
-    }
-
-    if (mDrmManagerClient == NULL) {
-        return NULL;
-    }
-
-    if (mDecryptHandle == NULL) {
-        mDecryptHandle = mDrmManagerClient->openDecryptSession(
-                mFd, mOffset, mLength, mime);
-    }
-
-    if (mDecryptHandle == NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-
-    return mDecryptHandle;
-}
-
-ssize_t FileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
-    size_t DRM_CACHE_SIZE = 1024;
-    if (mDrmBuf == NULL) {
-        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
-    }
-
-    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
-            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
-        /* Use buffered data */
-        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
-        return size;
-    } else if (size <= DRM_CACHE_SIZE) {
-        /* Buffer new data */
-        mDrmBufOffset =  offset + mOffset;
-        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
-                DRM_CACHE_SIZE, offset + mOffset);
-        if (mDrmBufSize > 0) {
-            int64_t dataRead = 0;
-            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
-            memcpy(data, (void*)mDrmBuf, dataRead);
-            return dataRead;
-        } else {
-            return mDrmBufSize;
-        }
-    } else {
-        /* Too big chunk to cache. Call DRM directly */
-        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
-    }
-}
-
-/* static */
-bool FileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
-    std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
-    sp<DecryptHandle> decryptHandle =
-            drmClient->openDecryptSession(fd, offset, length, mime);
-    bool requiresDrm = false;
-    if (decryptHandle != nullptr) {
-        requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
-        drmClient->closeDecryptSession(decryptHandle);
-    }
-    return requiresDrm;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/FrameCaptureLayer.cpp b/media/libstagefright/FrameCaptureLayer.cpp
new file mode 100644
index 0000000..d2cfd41
--- /dev/null
+++ b/media/libstagefright/FrameCaptureLayer.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2019 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 "FrameCaptureLayer"
+
+#include <include/FrameCaptureLayer.h>
+#include <media/stagefright/FrameCaptureProcessor.h>
+#include <gui/BufferQueue.h>
+#include <gui/GLConsumer.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/Surface.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <renderengine/RenderEngine.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static const int64_t kAcquireBufferTimeoutNs = 100000000LL;
+static constexpr float kDefaultMaxMasteringLuminance = 1000.0;
+static constexpr float kDefaultMaxContentLuminance = 1000.0;
+
+ui::Dataspace translateDataspace(ui::Dataspace dataspace) {
+    ui::Dataspace updatedDataspace = dataspace;
+    // translate legacy dataspaces to modern dataspaces
+    switch (dataspace) {
+        case ui::Dataspace::SRGB:
+            updatedDataspace = ui::Dataspace::V0_SRGB;
+            break;
+        case ui::Dataspace::SRGB_LINEAR:
+            updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+            break;
+        case ui::Dataspace::JFIF:
+            updatedDataspace = ui::Dataspace::V0_JFIF;
+            break;
+        case ui::Dataspace::BT601_625:
+            updatedDataspace = ui::Dataspace::V0_BT601_625;
+            break;
+        case ui::Dataspace::BT601_525:
+            updatedDataspace = ui::Dataspace::V0_BT601_525;
+            break;
+        case ui::Dataspace::BT709:
+            updatedDataspace = ui::Dataspace::V0_BT709;
+            break;
+        default:
+            break;
+    }
+
+    return updatedDataspace;
+}
+
+bool isHdrY410(const BufferItem &bi) {
+    ui::Dataspace dataspace = translateDataspace(static_cast<ui::Dataspace>(bi.mDataSpace));
+    // pixel format is HDR Y410 masquerading as RGBA_1010102
+    return ((dataspace == ui::Dataspace::BT2020_ITU_PQ ||
+            dataspace == ui::Dataspace::BT2020_ITU_HLG) &&
+            bi.mGraphicBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
+}
+
+struct FrameCaptureLayer::BufferLayer : public FrameCaptureProcessor::Layer {
+    BufferLayer(const BufferItem &bi) : mBufferItem(bi) {}
+    void getLayerSettings(
+            const Rect &sourceCrop, uint32_t textureName,
+            renderengine::LayerSettings *layerSettings) override;
+    BufferItem mBufferItem;
+};
+
+void FrameCaptureLayer::BufferLayer::getLayerSettings(
+        const Rect &sourceCrop, uint32_t textureName,
+        renderengine::LayerSettings *layerSettings) {
+    layerSettings->geometry.boundaries = sourceCrop.toFloatRect();
+    layerSettings->alpha = 1.0f;
+
+    layerSettings->sourceDataspace = translateDataspace(
+            static_cast<ui::Dataspace>(mBufferItem.mDataSpace));
+
+    // from BufferLayer
+    layerSettings->source.buffer.buffer = mBufferItem.mGraphicBuffer;
+    layerSettings->source.buffer.isOpaque = true;
+    layerSettings->source.buffer.fence = mBufferItem.mFence;
+    layerSettings->source.buffer.textureName = textureName;
+    layerSettings->source.buffer.usePremultipliedAlpha = false;
+    layerSettings->source.buffer.isY410BT2020 = isHdrY410(mBufferItem);
+    bool hasSmpte2086 = mBufferItem.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;
+    bool hasCta861_3 = mBufferItem.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;
+    layerSettings->source.buffer.maxMasteringLuminance = hasSmpte2086
+            ? mBufferItem.mHdrMetadata.smpte2086.maxLuminance
+                    : kDefaultMaxMasteringLuminance;
+    layerSettings->source.buffer.maxContentLuminance = hasCta861_3
+            ? mBufferItem.mHdrMetadata.cta8613.maxContentLightLevel
+                    : kDefaultMaxContentLuminance;
+
+    // Set filtering to false since the capture itself doesn't involve
+    // any scaling, metadata retriever JNI is scaling the bitmap if
+    // display size is different from decoded size. If that scaling
+    // needs to be handled by server side, consider enable this based
+    // display size vs decoded size.
+    const bool useFiltering = false;
+    layerSettings->source.buffer.useTextureFiltering = useFiltering;
+
+    float textureMatrix[16];
+    GLConsumer::computeTransformMatrix(
+            textureMatrix, mBufferItem.mGraphicBuffer,
+            mBufferItem.mCrop, mBufferItem.mTransform, useFiltering);
+
+    // Flip y-coordinates because GLConsumer expects OpenGL convention.
+    mat4 tr = mat4::translate(vec4(.5, .5, 0, 1)) * mat4::scale(vec4(1, -1, 1, 1)) *
+            mat4::translate(vec4(-.5, -.5, 0, 1));
+
+    layerSettings->source.buffer.textureTransform =
+            mat4(static_cast<const float*>(textureMatrix)) * tr;
+}
+
+status_t FrameCaptureLayer::init() {
+    if (FrameCaptureProcessor::getInstance() == nullptr) {
+        ALOGE("failed to get capture processor");
+        return ERROR_UNSUPPORTED;
+    }
+
+    // Mimic surfaceflinger's BufferQueueLayer::onFirstRef() to create a
+    // BufferQueue for encoder output
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    // We don't need HW_COMPOSER usage since we're not using hwc to compose.
+    // The buffer is only used as a GL texture.
+    consumer->setConsumerUsageBits(GraphicBuffer::USAGE_HW_TEXTURE);
+    consumer->setConsumerName(String8("FrameDecoder"));
+
+    status_t err = consumer->consumerConnect(
+            new BufferQueue::ProxyConsumerListener(this), false);
+    if (NO_ERROR != err) {
+        ALOGE("Error connecting to BufferQueue: %s (%d)", strerror(-err), err);
+        return err;
+    }
+
+    mConsumer = consumer;
+    mSurface = new Surface(producer);
+
+    return OK;
+}
+
+status_t FrameCaptureLayer::capture(const ui::PixelFormat reqPixelFormat,
+        const Rect &sourceCrop, sp<GraphicBuffer> *outBuffer) {
+    ALOGV("capture: reqPixelFormat %d, crop {%d, %d, %d, %d}", reqPixelFormat,
+            sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
+
+    BufferItem bi;
+    status_t err = acquireBuffer(&bi);
+    if (err != OK) {
+        return err;
+    }
+
+    // create out buffer
+    const uint32_t usage =
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+            GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+    sp<GraphicBuffer> buffer = new GraphicBuffer(
+            sourceCrop.getWidth(), sourceCrop.getHeight(),
+            static_cast<android_pixel_format>(reqPixelFormat),
+            1, usage, std::string("thumbnail"));
+
+    err = FrameCaptureProcessor::getInstance()->capture(
+            new BufferLayer(bi), sourceCrop, buffer);
+    if (err == OK) {
+        *outBuffer = buffer;
+    }
+
+    (void)releaseBuffer(bi);
+    return err;
+}
+
+FrameCaptureLayer::FrameCaptureLayer() : mFrameAvailable(false) {}
+
+void FrameCaptureLayer::onFrameAvailable(const BufferItem& /*item*/) {
+    ALOGV("onFrameAvailable");
+    Mutex::Autolock _lock(mLock);
+
+    mFrameAvailable = true;
+    mCondition.signal();
+}
+
+void FrameCaptureLayer::onBuffersReleased() {
+    ALOGV("onBuffersReleased");
+    Mutex::Autolock _lock(mLock);
+
+    uint64_t mask = 0;
+    mConsumer->getReleasedBuffers(&mask);
+    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        if (mask & (1ULL << i)) {
+            mSlotToBufferMap[i] = nullptr;
+        }
+    }
+}
+
+void FrameCaptureLayer::onSidebandStreamChanged() {
+    ALOGV("onSidebandStreamChanged");
+}
+
+status_t FrameCaptureLayer::acquireBuffer(BufferItem *bi) {
+    ALOGV("acquireBuffer");
+    Mutex::Autolock _lock(mLock);
+
+    if (!mFrameAvailable) {
+        // The output buffer is already released to the codec at this point.
+        // Use a small timeout of 100ms in case the buffer hasn't arrived
+        // at the consumer end of the output surface yet.
+        if (mCondition.waitRelative(mLock, kAcquireBufferTimeoutNs) != OK) {
+            ALOGE("wait for buffer timed out");
+            return TIMED_OUT;
+        }
+    }
+    mFrameAvailable = false;
+
+    status_t err = mConsumer->acquireBuffer(bi, 0);
+    if (err != OK) {
+        ALOGE("failed to acquire buffer!");
+        return err;
+    }
+
+    if (bi->mGraphicBuffer != nullptr) {
+        mSlotToBufferMap[bi->mSlot] = bi->mGraphicBuffer;
+    } else {
+        bi->mGraphicBuffer = mSlotToBufferMap[bi->mSlot];
+    }
+
+    if (bi->mGraphicBuffer == nullptr) {
+        ALOGE("acquired null buffer!");
+        return BAD_VALUE;
+    }
+    return OK;
+}
+
+status_t FrameCaptureLayer::releaseBuffer(const BufferItem &bi) {
+    ALOGV("releaseBuffer");
+    Mutex::Autolock _lock(mLock);
+
+    return mConsumer->releaseBuffer(bi.mSlot, bi.mFrameNumber,
+            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
+}
+
+}  // namespace android
diff --git a/media/libstagefright/FrameCaptureProcessor.cpp b/media/libstagefright/FrameCaptureProcessor.cpp
new file mode 100644
index 0000000..96c1195
--- /dev/null
+++ b/media/libstagefright/FrameCaptureProcessor.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2019 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 "FrameCaptureProcessor"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FrameCaptureProcessor.h>
+#include <media/stagefright/MediaErrors.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/Fence.h>
+#include <ui/PixelFormat.h>
+#include <utils/Log.h>
+
+namespace android {
+
+//static
+Mutex FrameCaptureProcessor::sLock;
+//static
+sp<FrameCaptureProcessor> FrameCaptureProcessor::sInstance;
+
+//static
+sp<FrameCaptureProcessor> FrameCaptureProcessor::getInstance() {
+    Mutex::Autolock _l(sLock);
+    if (sInstance == nullptr) {
+        sInstance = new FrameCaptureProcessor();
+        sInstance->createRenderEngine();
+    }
+    // init only once, if failed nullptr will be returned afterwards.
+    return (sInstance->initCheck() == OK) ? sInstance : nullptr;
+}
+
+//static
+status_t FrameCaptureProcessor::PostAndAwaitResponse(
+        const sp<AMessage> &msg, sp<AMessage> *response) {
+    status_t err = msg->postAndAwaitResponse(response);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (!(*response)->findInt32("err", &err)) {
+        err = OK;
+    }
+
+    return err;
+}
+
+//static
+void FrameCaptureProcessor::PostReplyWithError(
+        const sp<AReplyToken> &replyID, status_t err) {
+    sp<AMessage> response = new AMessage;
+    if (err != OK) {
+        response->setInt32("err", err);
+    }
+    response->postReply(replyID);
+}
+
+FrameCaptureProcessor::FrameCaptureProcessor()
+    : mInitStatus(NO_INIT), mTextureName(0) {}
+
+FrameCaptureProcessor::~FrameCaptureProcessor() {
+    if (mLooper != nullptr) {
+        mLooper->unregisterHandler(id());
+        mLooper->stop();
+    }
+}
+
+void FrameCaptureProcessor::createRenderEngine() {
+    // this method should only be called once, immediately after ctor
+    CHECK(mInitStatus == NO_INIT);
+
+    mLooper = new ALooper();
+    mLooper->setName("capture_looper");
+    mLooper->start(); // default priority
+    mLooper->registerHandler(this);
+
+    sp<AMessage> response;
+    status_t err = PostAndAwaitResponse(new AMessage(kWhatCreate, this), &response);
+    if (err != OK) {
+        mInitStatus = ERROR_UNSUPPORTED;
+
+        mLooper->unregisterHandler(id());
+        mLooper->stop();
+        mLooper.clear();
+        return;
+    }
+
+    // only need one texture name
+    mRE->genTextures(1, &mTextureName);
+
+    mInitStatus = OK;
+}
+
+status_t FrameCaptureProcessor::capture(
+        const sp<Layer> &layer, const Rect &sourceCrop, const sp<GraphicBuffer> &buffer) {
+    sp<AMessage> msg = new AMessage(kWhatCapture, this);
+    msg->setObject("layer", layer);
+    msg->setRect("crop", sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
+    msg->setObject("buffer", buffer);
+    sp<AMessage> response;
+    return PostAndAwaitResponse(msg, &response);
+}
+
+status_t FrameCaptureProcessor::onCreate() {
+    mRE = renderengine::RenderEngine::create(
+            renderengine::RenderEngineCreationArgs::Builder()
+                .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
+                .setImageCacheSize(2 /*maxFrameBufferAcquiredBuffers*/)
+                .setUseColorManagerment(true)
+                .setEnableProtectedContext(false)
+                .setPrecacheToneMapperShaderOnly(true)
+                .setContextPriority(renderengine::RenderEngine::ContextPriority::LOW)
+                .build());
+
+    if (mRE == nullptr) {
+        return ERROR_UNSUPPORTED;
+    }
+    return OK;
+}
+
+status_t FrameCaptureProcessor::onCapture(const sp<Layer> &layer,
+        const Rect &sourceCrop, const sp<GraphicBuffer> &buffer) {
+    renderengine::DisplaySettings clientCompositionDisplay;
+    std::vector<const renderengine::LayerSettings*> clientCompositionLayers;
+
+    clientCompositionDisplay.physicalDisplay = sourceCrop;
+    clientCompositionDisplay.clip = sourceCrop;
+
+    clientCompositionDisplay.outputDataspace = ui::Dataspace::V0_SRGB;
+    clientCompositionDisplay.maxLuminance = sDefaultMaxLumiance;
+    clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
+
+    // from Layer && BufferLayer
+    renderengine::LayerSettings layerSettings;
+
+    layer->getLayerSettings(sourceCrop, mTextureName, &layerSettings);
+
+    clientCompositionLayers.push_back(&layerSettings);
+
+    // Use an empty fence for the buffer fence, since we just created the buffer so
+    // there is no need for synchronization with the GPU.
+    base::unique_fd bufferFence;
+    base::unique_fd drawFence;
+    mRE->useProtectedContext(false);
+    status_t err = mRE->drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer.get(),
+            /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
+
+    sp<Fence> fence = new Fence(std::move(drawFence));
+
+    if (err != OK) {
+        ALOGE("drawLayers returned err %d", err);
+        return err;
+    }
+
+    err = fence->wait(500);
+    if (err != OK) {
+        ALOGW("wait for fence returned err %d", err);
+    }
+    return OK;
+}
+
+void FrameCaptureProcessor::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatCreate:
+        {
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
+            status_t err = onCreate();
+
+            PostReplyWithError(replyID, err);
+            break;
+        }
+        case kWhatCapture:
+        {
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
+            sp<RefBase> layerObj, bufferObj;
+            int32_t left, top, right, bottom;
+            CHECK(msg->findObject("layer", &layerObj));
+            CHECK(msg->findRect("crop", &left, &top, &right, &bottom));
+            CHECK(msg->findObject("buffer", &bufferObj));
+
+            sp<GraphicBuffer> buffer = static_cast<GraphicBuffer*>(bufferObj.get());
+            sp<Layer> layer = static_cast<Layer*>(layerObj.get());
+
+            PostReplyWithError(replyID,
+                    onCapture(layer, Rect(left, top, right, bottom), buffer));
+
+            break;
+        }
+        default:
+            TRESPASS();
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 18a6bd8..734f5bb 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -18,17 +18,20 @@
 #define LOG_TAG "FrameDecoder"
 
 #include "include/FrameDecoder.h"
+#include "include/FrameCaptureLayer.h"
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
 #include <gui/Surface.h>
 #include <inttypes.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaSource.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
 #include <media/stagefright/ColorConverter.h>
+#include <media/stagefright/FrameCaptureProcessor.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaDefs.h>
@@ -41,10 +44,11 @@
 
 static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
 static const size_t kRetryCount = 50; // must be >0
+static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
 
 sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
         int32_t width, int32_t height, int32_t tileWidth, int32_t tileHeight,
-        int32_t dstBpp, bool metaOnly = false) {
+        int32_t dstBpp, bool allocRotated, bool metaOnly) {
     int32_t rotationAngle;
     if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
         rotationAngle = 0;  // By default, no rotation
@@ -74,6 +78,14 @@
         displayHeight = height;
     }
 
+    if (allocRotated && (rotationAngle == 90 || rotationAngle == 270)) {
+        int32_t tmp;
+        tmp = width; width = height; height = tmp;
+        tmp = displayWidth; displayWidth = displayHeight; displayHeight = tmp;
+        tmp = tileWidth; tileWidth = tileHeight; tileHeight = tmp;
+        rotationAngle = 0;
+    }
+
     VideoFrame frame(width, height, displayWidth, displayHeight,
             tileWidth, tileHeight, rotationAngle, dstBpp, !metaOnly, iccSize);
 
@@ -88,12 +100,26 @@
         ALOGE("not enough memory for VideoFrame size=%zu", size);
         return NULL;
     }
-    VideoFrame* frameCopy = static_cast<VideoFrame*>(frameMem->pointer());
+    VideoFrame* frameCopy = static_cast<VideoFrame*>(frameMem->unsecurePointer());
     frameCopy->init(frame, iccData, iccSize);
 
     return frameMem;
 }
 
+sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
+        int32_t width, int32_t height, int32_t tileWidth, int32_t tileHeight,
+        int32_t dstBpp, bool allocRotated = false) {
+    return allocVideoFrame(trackMeta, width, height, tileWidth, tileHeight, dstBpp,
+            allocRotated, false /*metaOnly*/);
+}
+
+sp<IMemory> allocMetaFrame(const sp<MetaData>& trackMeta,
+        int32_t width, int32_t height, int32_t tileWidth, int32_t tileHeight,
+        int32_t dstBpp) {
+    return allocVideoFrame(trackMeta, width, height, tileWidth, tileHeight, dstBpp,
+            false /*allocRotated*/, true /*metaOnly*/);
+}
+
 bool findThumbnailInfo(
         const sp<MetaData> &trackMeta, int32_t *width, int32_t *height,
         uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) {
@@ -117,23 +143,27 @@
 bool getDstColorFormat(
         android_pixel_format_t colorFormat,
         OMX_COLOR_FORMATTYPE *dstFormat,
+        ui::PixelFormat *captureFormat,
         int32_t *dstBpp) {
     switch (colorFormat) {
         case HAL_PIXEL_FORMAT_RGB_565:
         {
             *dstFormat = OMX_COLOR_Format16bitRGB565;
+            *captureFormat = ui::PixelFormat::RGB_565;
             *dstBpp = 2;
             return true;
         }
         case HAL_PIXEL_FORMAT_RGBA_8888:
         {
             *dstFormat = OMX_COLOR_Format32BitRGBA8888;
+            *captureFormat = ui::PixelFormat::RGBA_8888;
             *dstBpp = 4;
             return true;
         }
         case HAL_PIXEL_FORMAT_BGRA_8888:
         {
             *dstFormat = OMX_COLOR_Format32bitBGRA8888;
+            *captureFormat = ui::PixelFormat::BGRA_8888;
             *dstBpp = 4;
             return true;
         }
@@ -150,9 +180,10 @@
 sp<IMemory> FrameDecoder::getMetadataOnly(
         const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) {
     OMX_COLOR_FORMATTYPE dstFormat;
+    ui::PixelFormat captureFormat;
     int32_t dstBpp;
-    if (!getDstColorFormat(
-            (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) {
+    if (!getDstColorFormat((android_pixel_format_t)colorFormat,
+            &dstFormat, &captureFormat, &dstBpp)) {
         return NULL;
     }
 
@@ -170,8 +201,19 @@
             tileWidth = tileHeight = 0;
         }
     }
-    return allocVideoFrame(trackMeta,
-            width, height, tileWidth, tileHeight, dstBpp, true /*metaOnly*/);
+
+    sp<IMemory> metaMem = allocMetaFrame(trackMeta, width, height, tileWidth, tileHeight, dstBpp);
+
+    // try to fill sequence meta's duration based on average frame rate,
+    // default to 33ms if frame rate is unavailable.
+    int32_t frameRate;
+    VideoFrame* meta = static_cast<VideoFrame*>(metaMem->unsecurePointer());
+    if (trackMeta->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) {
+        meta->mDurationUs = 1000000LL / frameRate;
+    } else {
+        meta->mDurationUs = kDefaultSampleDurationUs;
+    }
+    return metaMem;
 }
 
 FrameDecoder::FrameDecoder(
@@ -194,15 +236,31 @@
     }
 }
 
+bool isHDR(const sp<AMessage> &format) {
+    uint32_t standard, range, transfer;
+    if (!format->findInt32("color-standard", (int32_t*)&standard)) {
+        standard = 0;
+    }
+    if (!format->findInt32("color-range", (int32_t*)&range)) {
+        range = 0;
+    }
+    if (!format->findInt32("color-transfer", (int32_t*)&transfer)) {
+        transfer = 0;
+    }
+    return standard == ColorUtils::kColorStandardBT2020 &&
+            (transfer == ColorUtils::kColorTransferST2084 ||
+            transfer == ColorUtils::kColorTransferHLG);
+}
+
 status_t FrameDecoder::init(
-        int64_t frameTimeUs, size_t numFrames, int option, int colorFormat) {
-    if (!getDstColorFormat(
-            (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) {
+        int64_t frameTimeUs, int option, int colorFormat) {
+    if (!getDstColorFormat((android_pixel_format_t)colorFormat,
+            &mDstFormat, &mCaptureFormat, &mDstBpp)) {
         return ERROR_UNSUPPORTED;
     }
 
     sp<AMessage> videoFormat = onGetFormatAndSeekOptions(
-            frameTimeUs, numFrames, option, &mReadOptions);
+            frameTimeUs, option, &mReadOptions, &mSurface);
     if (videoFormat == NULL) {
         ALOGE("video format or seek mode not supported");
         return ERROR_UNSUPPORTED;
@@ -219,7 +277,7 @@
     }
 
     err = decoder->configure(
-            videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */);
+            videoFormat, mSurface, NULL /* crypto */, 0 /* flags */);
     if (err != OK) {
         ALOGW("configure returned error %d (%s)", err, asString(err));
         decoder->release();
@@ -253,19 +311,7 @@
         return NULL;
     }
 
-    return mFrames.size() > 0 ? mFrames[0] : NULL;
-}
-
-status_t FrameDecoder::extractFrames(std::vector<sp<IMemory> >* frames) {
-    status_t err = extractInternal();
-    if (err != OK) {
-        return err;
-    }
-
-    for (size_t i = 0; i < mFrames.size(); i++) {
-        frames->push_back(mFrames[i]);
-    }
-    return OK;
+    return mFrameMemory;
 }
 
 status_t FrameDecoder::extractInternal() {
@@ -379,8 +425,13 @@
                         ALOGE("failed to get output buffer %zu", index);
                         break;
                     }
-                    err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
-                    mDecoder->releaseOutputBuffer(index);
+                    if (mSurface != nullptr) {
+                        mDecoder->renderOutputBufferAndRelease(index);
+                        err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+                    } else {
+                        err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+                        mDecoder->releaseOutputBuffer(index);
+                    }
                 } else {
                     ALOGW("Received error %d (%s) instead of output", err, asString(err));
                     done = true;
@@ -404,22 +455,23 @@
         const sp<MetaData> &trackMeta,
         const sp<IMediaSource> &source)
     : FrameDecoder(componentName, trackMeta, source),
+      mFrame(NULL),
       mIsAvcOrHevc(false),
       mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
       mTargetTimeUs(-1LL),
-      mNumFrames(0),
-      mNumFramesDecoded(0) {
+      mDefaultSampleDurationUs(0) {
 }
 
 sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
-        int64_t frameTimeUs, size_t numFrames, int seekMode, MediaSource::ReadOptions *options) {
+        int64_t frameTimeUs, int seekMode,
+        MediaSource::ReadOptions *options,
+        sp<Surface> *window) {
     mSeekMode = static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
     if (mSeekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
             mSeekMode > MediaSource::ReadOptions::SEEK_FRAME_INDEX) {
         ALOGE("Unknown seek mode: %d", mSeekMode);
         return NULL;
     }
-    mNumFrames = numFrames;
 
     const char *mime;
     if (!trackMeta()->findCString(kKeyMIMEType, &mime)) {
@@ -460,6 +512,23 @@
         videoFormat->setInt32("android._num-input-buffers", 1);
         videoFormat->setInt32("android._num-output-buffers", 1);
     }
+
+    if (isHDR(videoFormat)) {
+        *window = initSurface();
+        if (*window == NULL) {
+            ALOGE("Failed to init surface control for HDR, fallback to non-hdr");
+        } else {
+            videoFormat->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
+        }
+    }
+
+    int32_t frameRate;
+    if (trackMeta()->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) {
+        mDefaultSampleDurationUs = 1000000LL / frameRate;
+    } else {
+        mDefaultSampleDurationUs = kDefaultSampleDurationUs;
+    }
+
     return videoFormat;
 }
 
@@ -480,6 +549,12 @@
         // option, in which case we need to actually decode to targetTimeUs.
         *flags |= MediaCodec::BUFFER_FLAG_EOS;
     }
+    int64_t durationUs;
+    if (sampleMeta.findInt64(kKeyDuration, &durationUs)) {
+        mSampleDurations.push_back(durationUs);
+    } else {
+        mSampleDurations.push_back(mDefaultSampleDurationUs);
+    }
     return OK;
 }
 
@@ -487,6 +562,11 @@
         const sp<MediaCodecBuffer> &videoFrameBuffer,
         const sp<AMessage> &outputFormat,
         int64_t timeUs, bool *done) {
+    int64_t durationUs = mDefaultSampleDurationUs;
+    if (!mSampleDurations.empty()) {
+        durationUs = *mSampleDurations.begin();
+        mSampleDurations.erase(mSampleDurations.begin());
+    }
     bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);
 
     // If this is not the target frame, skip color convert.
@@ -495,7 +575,7 @@
         return OK;
     }
 
-    *done = (++mNumFramesDecoded >= mNumFrames);
+    *done = true;
 
     if (outputFormat == NULL) {
         return ERROR_MALFORMED;
@@ -504,13 +584,22 @@
     int32_t width, height, stride, srcFormat;
     if (!outputFormat->findInt32("width", &width) ||
             !outputFormat->findInt32("height", &height) ||
-            !outputFormat->findInt32("stride", &stride) ||
             !outputFormat->findInt32("color-format", &srcFormat)) {
         ALOGE("format missing dimension or color: %s",
                 outputFormat->debugString().c_str());
         return ERROR_MALFORMED;
     }
 
+    if (!outputFormat->findInt32("stride", &stride)) {
+        if (mCaptureLayer == NULL) {
+            ALOGE("format must have stride for byte buffer mode: %s",
+                    outputFormat->debugString().c_str());
+            return ERROR_MALFORMED;
+        }
+        // for surface output, set stride to width, we don't actually need it.
+        stride = width;
+    }
+
     int32_t crop_left, crop_top, crop_right, crop_bottom;
     if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
         crop_left = crop_top = 0;
@@ -518,15 +607,25 @@
         crop_bottom = height - 1;
     }
 
-    sp<IMemory> frameMem = allocVideoFrame(
-            trackMeta(),
-            (crop_right - crop_left + 1),
-            (crop_bottom - crop_top + 1),
-            0,
-            0,
-            dstBpp());
-    addFrame(frameMem);
-    VideoFrame* frame = static_cast<VideoFrame*>(frameMem->pointer());
+    if (mFrame == NULL) {
+        sp<IMemory> frameMem = allocVideoFrame(
+                trackMeta(),
+                (crop_right - crop_left + 1),
+                (crop_bottom - crop_top + 1),
+                0,
+                0,
+                dstBpp(),
+                mCaptureLayer != nullptr /*allocRotated*/);
+        mFrame = static_cast<VideoFrame*>(frameMem->unsecurePointer());
+
+        setFrame(frameMem);
+    }
+
+    mFrame->mDurationUs = durationUs;
+
+    if (mCaptureLayer != nullptr) {
+        return captureSurface();
+    }
 
     ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
 
@@ -547,9 +646,11 @@
                 (const uint8_t *)videoFrameBuffer->data(),
                 width, height, stride,
                 crop_left, crop_top, crop_right, crop_bottom,
-                frame->getFlattenedData(),
-                frame->mWidth, frame->mHeight, frame->mRowBytes,
-                crop_left, crop_top, crop_right, crop_bottom);
+                mFrame->getFlattenedData(),
+                mFrame->mWidth, mFrame->mHeight, mFrame->mRowBytes,
+                // since the frame is allocated with top-left adjusted,
+                // the dst rect should start at {0,0} as well.
+                0, 0, mFrame->mWidth - 1, mFrame->mHeight - 1);
         return OK;
     }
 
@@ -558,6 +659,57 @@
     return ERROR_UNSUPPORTED;
 }
 
+sp<Surface> VideoFrameDecoder::initSurface() {
+    // create the consumer listener interface, and hold sp so that this
+    // interface lives as long as the GraphicBufferSource.
+    sp<FrameCaptureLayer> captureLayer = new FrameCaptureLayer();
+    if (captureLayer->init() != OK) {
+        ALOGE("failed to init capture layer");
+        return nullptr;
+    }
+    mCaptureLayer = captureLayer;
+
+    return captureLayer->getSurface();
+}
+
+status_t VideoFrameDecoder::captureSurface() {
+    sp<GraphicBuffer> outBuffer;
+    status_t err = mCaptureLayer->capture(
+            captureFormat(), Rect(0, 0, mFrame->mWidth, mFrame->mHeight), &outBuffer);
+
+    if (err != OK) {
+        ALOGE("failed to capture layer (err %d)", err);
+        return err;
+    }
+
+    ALOGV("capture: %dx%d, format %d, stride %d",
+            outBuffer->getWidth(),
+            outBuffer->getHeight(),
+            outBuffer->getPixelFormat(),
+            outBuffer->getStride());
+
+    uint8_t *base;
+    int32_t outBytesPerPixel, outBytesPerStride;
+    err = outBuffer->lock(
+            GraphicBuffer::USAGE_SW_READ_OFTEN,
+            reinterpret_cast<void**>(&base),
+            &outBytesPerPixel,
+            &outBytesPerStride);
+    if (err != OK) {
+        ALOGE("failed to lock graphic buffer: err %d", err);
+        return err;
+    }
+
+    uint8_t *dst = mFrame->getFlattenedData();
+    for (size_t y = 0 ; y < fmin(mFrame->mHeight, outBuffer->getHeight()) ; y++) {
+        memcpy(dst, base, fmin(mFrame->mWidth, outBuffer->getWidth()) * mFrame->mBytesPerPixel);
+        dst += mFrame->mRowBytes;
+        base += outBuffer->getStride() * mFrame->mBytesPerPixel;
+    }
+    outBuffer->unlock();
+    return OK;
+}
+
 ////////////////////////////////////////////////////////////////////////
 
 ImageDecoder::ImageDecoder(
@@ -577,8 +729,8 @@
 }
 
 sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions(
-        int64_t frameTimeUs, size_t /*numFrames*/,
-        int /*seekMode*/, MediaSource::ReadOptions *options) {
+        int64_t frameTimeUs, int /*seekMode*/,
+        MediaSource::ReadOptions *options, sp<Surface> * /*window*/) {
     sp<MetaData> overrideMeta;
     if (frameTimeUs < 0) {
         uint32_t type;
@@ -703,9 +855,9 @@
     if (mFrame == NULL) {
         sp<IMemory> frameMem = allocVideoFrame(
                 trackMeta(), mWidth, mHeight, mTileWidth, mTileHeight, dstBpp());
-        mFrame = static_cast<VideoFrame*>(frameMem->pointer());
+        mFrame = static_cast<VideoFrame*>(frameMem->unsecurePointer());
 
-        addFrame(frameMem);
+        setFrame(frameMem);
     }
 
     int32_t srcFormat;
@@ -725,12 +877,6 @@
     }
     converter.setSrcColorSpace(standard, range, transfer);
 
-    int32_t dstLeft, dstTop, dstRight, dstBottom;
-    dstLeft = mTilesDecoded % mGridCols * width;
-    dstTop = mTilesDecoded / mGridCols * height;
-    dstRight = dstLeft + width - 1;
-    dstBottom = dstTop + height - 1;
-
     int32_t crop_left, crop_top, crop_right, crop_bottom;
     if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
         crop_left = crop_top = 0;
@@ -738,15 +884,25 @@
         crop_bottom = height - 1;
     }
 
+    int32_t crop_width, crop_height;
+    crop_width = crop_right - crop_left + 1;
+    crop_height = crop_bottom - crop_top + 1;
+
+    int32_t dstLeft, dstTop, dstRight, dstBottom;
+    dstLeft = mTilesDecoded % mGridCols * crop_width;
+    dstTop = mTilesDecoded / mGridCols * crop_height;
+    dstRight = dstLeft + crop_width - 1;
+    dstBottom = dstTop + crop_height - 1;
+
     // apply crop on bottom-right
     // TODO: need to move this into the color converter itself.
     if (dstRight >= mWidth) {
-        crop_right = mWidth - dstLeft - 1;
-        dstRight = dstLeft + crop_right;
+        crop_right = crop_left + mWidth - dstLeft - 1;
+        dstRight = mWidth - 1;
     }
     if (dstBottom >= mHeight) {
-        crop_bottom = mHeight - dstTop - 1;
-        dstBottom = dstTop + crop_bottom;
+        crop_bottom = crop_top + mHeight - dstTop - 1;
+        dstBottom = mHeight - 1;
     }
 
     *done = (++mTilesDecoded >= mTargetTiles);
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
deleted file mode 100644
index d118e8c..0000000
--- a/media/libstagefright/HTTPBase.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2011 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 "HTTPBase"
-#include <utils/Log.h>
-
-#include "include/HTTPBase.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-
-#include <cutils/properties.h>
-#include <cutils/qtaguid.h>
-
-namespace android {
-
-HTTPBase::HTTPBase()
-    : mNumBandwidthHistoryItems(0),
-      mTotalTransferTimeUs(0),
-      mTotalTransferBytes(0),
-      mMaxBandwidthHistoryItems(100),
-      mPrevBandwidthMeasureTimeUs(0),
-      mPrevEstimatedBandWidthKbps(0),
-      mBandWidthCollectFreqMs(5000) {
-    mName = String8("HTTPBase(<disconnected>)");
-}
-
-void HTTPBase::addBandwidthMeasurement(
-        size_t numBytes, int64_t delayUs) {
-    Mutex::Autolock autoLock(mLock);
-
-    BandwidthEntry entry;
-    entry.mDelayUs = delayUs;
-    entry.mNumBytes = numBytes;
-    mTotalTransferTimeUs += delayUs;
-    mTotalTransferBytes += numBytes;
-
-    mBandwidthHistory.push_back(entry);
-    if (++mNumBandwidthHistoryItems > mMaxBandwidthHistoryItems) {
-        BandwidthEntry *entry = &*mBandwidthHistory.begin();
-        mTotalTransferTimeUs -= entry->mDelayUs;
-        mTotalTransferBytes -= entry->mNumBytes;
-        mBandwidthHistory.erase(mBandwidthHistory.begin());
-        --mNumBandwidthHistoryItems;
-
-        int64_t timeNowUs = ALooper::GetNowUs();
-        if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
-                mBandWidthCollectFreqMs * 1000LL) {
-
-            if (mPrevBandwidthMeasureTimeUs != 0) {
-                mPrevEstimatedBandWidthKbps =
-                    (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
-            }
-            mPrevBandwidthMeasureTimeUs = timeNowUs;
-        }
-    }
-
-}
-
-bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
-    Mutex::Autolock autoLock(mLock);
-
-    // Do not do bandwidth estimation if we don't have enough samples, or
-    // total bytes download are too small (<64K).
-    // Bandwidth estimation from these samples can often shoot up and cause
-    // unwanted bw adaption behaviors.
-    if (mNumBandwidthHistoryItems < 2 || mTotalTransferBytes < 65536) {
-        return false;
-    }
-
-    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
-
-    return true;
-}
-
-status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
-    Mutex::Autolock autoLock(mLock);
-    *kbps = mPrevEstimatedBandWidthKbps;
-    return OK;
-}
-
-status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (freqMs < kMinBandwidthCollectFreqMs
-            || freqMs > kMaxBandwidthCollectFreqMs) {
-
-        ALOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
-        return BAD_VALUE;
-    }
-
-    ALOGI("frequency set to %d ms", freqMs);
-    mBandWidthCollectFreqMs = freqMs;
-    return OK;
-}
-
-void HTTPBase::setBandwidthHistorySize(size_t numHistoryItems) {
-    mMaxBandwidthHistoryItems = numHistoryItems;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index 482a1a7..b347453 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -83,6 +83,7 @@
     }
 
     if (err != OK) {
+        ALOGE("error parsing VPS or SPS or PPS");
         return err;
     }
 
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index a9715c9..34b840e 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -17,7 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MPEG2TSWriter"
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f130c9b..8f7d4bf 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -31,8 +31,9 @@
 #include <utils/Log.h>
 
 #include <functional>
+#include <fcntl.h>
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -64,9 +65,6 @@
 namespace android {
 
 static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
-static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
-                                                         // filesystem file size
-                                                         // used by most SD cards
 static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
 static const uint8_t kNalUnitTypePicParamSet = 0x08;
 static const int64_t kInitialDelayTimeUs     = 700000LL;
@@ -105,8 +103,40 @@
 //#define SHOW_MODEL_BUILD 1
 
 class MPEG4Writer::Track {
+    struct TrackId {
+        TrackId(uint32_t aId)
+            :mId(aId),
+             mTrackIdValid(false) {
+        }
+        bool isValid(bool akKey4BitTrackIds) {
+            // trackId cannot be zero, ISO/IEC 14496-12 8.3.2.3
+            if (mId == 0) {
+                return false;
+            }
+            /* MediaRecorder uses only 4 bit to represent track ids during notifying clients.
+             * MediaMuxer's track ids are restricted by container allowed size only.
+             * MPEG4 Container defines unsigned int (32), ISO/IEC 14496-12 8.3.2.2
+             */
+            if (akKey4BitTrackIds && mId > 15) {
+                return false;
+            }
+            mTrackIdValid = true;
+            return true;
+        }
+        uint32_t getId() const {
+            CHECK(mTrackIdValid);
+            return mId;
+        }
+        TrackId() = delete;
+        DISALLOW_EVIL_CONSTRUCTORS(TrackId);
+    private:
+        // unsigned int (32), ISO/IEC 14496-12 8.3.2.2
+        uint32_t mId;
+        bool mTrackIdValid;
+    };
+
 public:
-    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
+    Track(MPEG4Writer *owner, const sp<MediaSource> &source, uint32_t aTrackId);
 
     ~Track();
 
@@ -118,7 +148,7 @@
     int64_t getDurationUs() const;
     int64_t getEstimatedTrackSizeBytes() const;
     int32_t getMetaSizeIncrease(int32_t angle, int32_t trackCount) const;
-    void writeTrackHeader(bool use32BitOffset = true);
+    void writeTrackHeader();
     int64_t getMinCttsOffsetTimeUs();
     void bufferChunk(int64_t timestampUs);
     bool isAvc() const { return mIsAvc; }
@@ -131,11 +161,12 @@
     void addChunkOffset(off64_t offset);
     void addItemOffsetAndSize(off64_t offset, size_t size, bool isExif);
     void flushItemRefs();
-    int32_t getTrackId() const { return mTrackId; }
+    TrackId& getTrackId() { return mTrackId; }
     status_t dump(int fd, const Vector<String16>& args) const;
     static const char *getFourCCForMime(const char *mime);
     const char *getTrackType() const;
     void resetInternal();
+    int64_t trackMetaDataSize();
 
 private:
     // A helper class to handle faster write box with table entries
@@ -291,24 +322,20 @@
     bool mIsMPEG4;
     bool mGotStartKeyFrame;
     bool mIsMalformed;
-    int32_t mTrackId;
+    TrackId mTrackId;
     int64_t mTrackDurationUs;
     int64_t mMaxChunkDurationUs;
     int64_t mLastDecodingTimeUs;
-
     int64_t mEstimatedTrackSizeBytes;
     int64_t mMdatSizeBytes;
     int32_t mTimeScale;
 
     pthread_t mThread;
 
-
     List<MediaBuffer *> mChunkSamples;
 
-    bool                mSamplesHaveSameSize;
+    bool mSamplesHaveSameSize;
     ListTableEntries<uint32_t, 1> *mStszTableEntries;
-
-    ListTableEntries<uint32_t, 1> *mStcoTableEntries;
     ListTableEntries<off64_t, 1> *mCo64TableEntries;
     ListTableEntries<uint32_t, 3> *mStscTableEntries;
     ListTableEntries<uint32_t, 1> *mStssTableEntries;
@@ -352,6 +379,8 @@
     int64_t mStartTimestampUs;
     int64_t mStartTimeRealUs;
     int64_t mFirstSampleTimeRealUs;
+    // Captures negative start offset of a track(track starttime < 0).
+    int64_t mFirstSampleStartOffsetUs;
     int64_t mPreviousTrackTimeUs;
     int64_t mTrackEveryTimeDurationUs;
 
@@ -361,6 +390,7 @@
     ItemRefs mDimgRefs;
     Vector<uint16_t> mExifList;
     uint16_t mImageItemId;
+    uint16_t mItemIdBase;
     int32_t mIsPrimary;
     int32_t mWidth, mHeight;
     int32_t mTileWidth, mTileHeight;
@@ -410,18 +440,16 @@
     void updateTrackSizeEstimate();
     void addOneStscTableEntry(size_t chunkId, size_t sampleId);
     void addOneStssTableEntry(size_t sampleId);
-
-    // Duration is time scale based
-    void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
-    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+    void addOneSttsTableEntry(size_t sampleCount, int32_t delta /* media time scale based */);
+    void addOneCttsTableEntry(size_t sampleCount, int32_t sampleOffset);
     void addOneElstTableEntry(uint32_t segmentDuration, int32_t mediaTime,
         int16_t mediaRate, int16_t mediaRateFraction);
 
-    bool isTrackMalFormed() const;
+    bool isTrackMalFormed();
     void sendTrackSummary(bool hasMultipleTracks);
 
     // Write the boxes
-    void writeStcoBox(bool use32BitOffset);
+    void writeCo64Box();
     void writeStscBox();
     void writeStszBox();
     void writeStssBox();
@@ -447,7 +475,7 @@
     void writeAudioFourCCBox();
     void writeVideoFourCCBox();
     void writeMetadataFourCCBox();
-    void writeStblBox(bool use32BitOffset);
+    void writeStblBox();
     void writeEdtsBox();
 
     Track(const Track &);
@@ -489,14 +517,17 @@
     mStarted = false;
     mWriterThreadStarted = false;
     mSendNotify = false;
+    mWriteSeekErr = false;
+    mFallocateErr = false;
 
     // Reset following variables for all the sessions and they will be
     // initialized in start(MetaData *param).
     mIsRealTimeRecording = true;
     mUse4ByteNalLength = true;
-    mUse32BitOffset = true;
     mOffset = 0;
+    mPreAllocateFileEndOffset = 0;
     mMdatOffset = 0;
+    mMdatEndOffset = 0;
     mInMemoryCache = NULL;
     mInMemoryCacheOffset = 0;
     mInMemoryCacheSize = 0;
@@ -505,10 +536,14 @@
     mStreamableFile = false;
     mTimeScale = -1;
     mHasFileLevelMeta = false;
+    mFileLevelMetaDataSize = 0;
     mPrimaryItemId = 0;
     mAssociationEntryCount = 0;
     mNumGrids = 0;
+    mNextItemId = kItemIdBase;
     mHasRefs = false;
+    mPreAllocFirstTime = true;
+    mPrevAllTracksTotalMetaDataSizeEstimate = 0;
 
     // Following variables only need to be set for the first recording session.
     // And they will stay the same for all the recording sessions.
@@ -530,6 +565,15 @@
         ALOGE("cannot seek mFd: %s (%d) %lld", strerror(errno), errno, (long long)mFd);
         release();
     }
+
+    if (fallocate64(mFd, FALLOC_FL_KEEP_SIZE, 0, 1) == 0) {
+        ALOGD("PreAllocation enabled");
+        mPreAllocationEnabled = true;
+    } else {
+        ALOGD("PreAllocation disabled. fallocate : %s, %d", strerror(errno), errno);
+        mPreAllocationEnabled = false;
+    }
+
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
         (*it)->resetInternal();
@@ -613,8 +657,9 @@
 
     CHECK(source.get() != NULL);
 
-    const char *mime;
-    source->getFormat()->findCString(kKeyMIMEType, &mime);
+    const char *mime = NULL;
+    sp<MetaData> meta = source->getFormat();
+    meta->findCString(kKeyMIMEType, &mime);
 
     if (Track::getFourCCForMime(mime) == NULL) {
         ALOGE("Unsupported mime '%s'", mime);
@@ -731,14 +776,12 @@
     // where 1MB is the common file size limit for MMS application.
     // The default MAX _MOOV_BOX_SIZE value is based on about 3
     // minute video recording with a bit rate about 3 Mbps, because
-    // statistics also show that most of the video captured are going
-    // to be less than 3 minutes.
+    // statistics show that most captured videos are less than 3 minutes.
 
     // If the estimation is wrong, we will pay the price of wasting
     // some reserved space. This should not happen so often statistically.
-    static const int32_t factor = mUse32BitOffset? 1: 2;
-    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
-    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+    static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;                      // 3 KibiBytes
+    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);  // 395.5 KibiBytes
     int64_t size = MIN_MOOV_BOX_SIZE;
 
     // Max file size limit is set
@@ -781,10 +824,16 @@
          " estimated moov size %" PRId64 " bytes",
          mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
 
-    int64_t estimatedSize = factor * size;
-    CHECK_GE(estimatedSize, 8);
+    return size;
+}
 
-    return estimatedSize;
+status_t MPEG4Writer::validateAllTracksId(bool akKey4BitTrackIds) {
+    for (List<Track *>::iterator it = mTracks.begin(); it != mTracks.end(); ++it) {
+        if (!(*it)->getTrackId().isValid(akKey4BitTrackIds)) {
+            return BAD_VALUE;
+        }
+    }
+    return OK;
 }
 
 status_t MPEG4Writer::start(MetaData *param) {
@@ -794,36 +843,27 @@
     mStartMeta = param;
 
     /*
-     * Check mMaxFileSizeLimitBytes at the beginning
-     * since mMaxFileSizeLimitBytes may be implicitly
-     * changed later for 32-bit file offset even if
-     * user does not ask to set it explicitly.
+     * Check mMaxFileSizeLimitBytes at the beginning since mMaxFileSizeLimitBytes may be implicitly
+     * changed later as per filesizebits of filesystem even if user does not set it explicitly.
      */
     if (mMaxFileSizeLimitBytes != 0) {
         mIsFileSizeLimitExplicitlyRequested = true;
     }
 
-    int32_t use64BitOffset;
-    if (param &&
-        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
-        use64BitOffset) {
-        mUse32BitOffset = false;
-    }
-
-    if (mUse32BitOffset) {
-        // Implicit 32 bit file size limit
-        if (mMaxFileSizeLimitBytes == 0) {
-            mMaxFileSizeLimitBytes = kMax32BitFileSize;
-        }
-
-        // If file size is set to be larger than the 32 bit file
-        // size limit, treat it as an error.
-        if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
-            ALOGW("32-bit file size limit (%" PRId64 " bytes) too big. "
-                 "It is changed to %" PRId64 " bytes",
-                mMaxFileSizeLimitBytes, kMax32BitFileSize);
-            mMaxFileSizeLimitBytes = kMax32BitFileSize;
-        }
+    /* mMaxFileSizeLimitBytes has to be set everytime fd is switched, hence the following code is
+     * appropriate in start() method.
+     */
+    int32_t fileSizeBits = fpathconf(mFd, _PC_FILESIZEBITS);
+    ALOGD("fpathconf _PC_FILESIZEBITS:%" PRId32, fileSizeBits);
+    fileSizeBits = std::min(fileSizeBits, 52 /* cap it below 4 peta bytes */);
+    int64_t maxFileSizeBytes = ((int64_t)1 << fileSizeBits) - 1;
+    if (mMaxFileSizeLimitBytes > maxFileSizeBytes) {
+        mMaxFileSizeLimitBytes = maxFileSizeBytes;
+        ALOGD("File size limit (%" PRId64 " bytes) too big. It is changed to %" PRId64 " bytes",
+              mMaxFileSizeLimitBytes, maxFileSizeBytes);
+    } else if (mMaxFileSizeLimitBytes == 0) {
+        mMaxFileSizeLimitBytes = maxFileSizeBytes;
+        ALOGD("File size limit set to %" PRId64 " bytes implicitly", maxFileSizeBytes);
     }
 
     int32_t use2ByteNalLength;
@@ -850,7 +890,8 @@
 
     if (!param ||
         !param->findInt32(kKeyTimeScale, &mTimeScale)) {
-        mTimeScale = 1000;
+        // Increased by a factor of 10 to improve precision of segment duration in edit list entry.
+        mTimeScale = 10000;
     }
     CHECK_GT(mTimeScale, 0);
     ALOGV("movie time scale: %d", mTimeScale);
@@ -904,10 +945,30 @@
     mInMemoryCache = NULL;
     mInMemoryCacheOffset = 0;
 
+    status_t err = OK;
+    int32_t is4bitTrackId = false;
+    if (param && param->findInt32(kKey4BitTrackIds, &is4bitTrackId) && is4bitTrackId) {
+        err = validateAllTracksId(true);
+    } else {
+        err = validateAllTracksId(false);
+    }
+    if (err != OK) {
+        return err;
+    }
 
     ALOGV("muxer starting: mHasMoovBox %d, mHasFileLevelMeta %d",
             mHasMoovBox, mHasFileLevelMeta);
 
+    err = startWriterThread();
+    if (err != OK) {
+        return err;
+    }
+
+    err = setupAndStartLooper();
+    if (err != OK) {
+        return err;
+    }
+
     writeFtypBox(param);
 
     mFreeBoxOffset = mOffset;
@@ -915,7 +976,8 @@
     if (mInMemoryCacheSize == 0) {
         int32_t bitRate = -1;
         if (mHasFileLevelMeta) {
-            mInMemoryCacheSize += estimateFileLevelMetaSize(param);
+            mFileLevelMetaDataSize = estimateFileLevelMetaSize(param);
+            mInMemoryCacheSize += mFileLevelMetaDataSize;
         }
         if (mHasMoovBox) {
             if (param) {
@@ -926,7 +988,7 @@
     }
     if (mStreamableFile) {
         // Reserve a 'free' box only for streamable file
-        lseek64(mFd, mFreeBoxOffset, SEEK_SET);
+        seekOrPostError(mFd, mFreeBoxOffset, SEEK_SET);
         writeInt32(mInMemoryCacheSize);
         write("free", 4);
         mMdatOffset = mFreeBoxOffset + mInMemoryCacheSize;
@@ -935,16 +997,25 @@
     }
 
     mOffset = mMdatOffset;
-    lseek64(mFd, mMdatOffset, SEEK_SET);
-    if (mUse32BitOffset) {
-        write("????mdat", 8);
-    } else {
-        write("\x00\x00\x00\x01mdat????????", 16);
-    }
+    seekOrPostError(mFd, mMdatOffset, SEEK_SET);
+    write("\x00\x00\x00\x01mdat????????", 16);
 
-    status_t err = startWriterThread();
-    if (err != OK) {
-        return err;
+    /* Confirm whether the writing of the initial file atoms, ftyp and free,
+     * are written to the file properly by posting kWhatNoIOErrorSoFar to the
+     * MP4WtrCtrlHlpLooper that's handling write and seek errors also. If there
+     * was kWhatIOError, the following two scenarios should be handled.
+     * 1) If kWhatIOError was delivered and processed, MP4WtrCtrlHlpLooper
+     * would have stopped all threads gracefully already and posting
+     * kWhatNoIOErrorSoFar would fail.
+     * 2) If kWhatIOError wasn't delivered or getting processed,
+     * kWhatNoIOErrorSoFar should get posted successfully.  Wait for
+     * response from MP4WtrCtrlHlpLooper.
+     */
+    sp<AMessage> msg = new AMessage(kWhatNoIOErrorSoFar, mReflector);
+    sp<AMessage> response;
+    err = msg->postAndAwaitResponse(&response);
+    if (err != OK || !response->findInt32("err", &err) || err != OK) {
+        return ERROR_IO;
     }
 
     err = startTracks(param);
@@ -956,32 +1027,35 @@
     return OK;
 }
 
-bool MPEG4Writer::use32BitFileOffset() const {
-    return mUse32BitOffset;
-}
-
 status_t MPEG4Writer::pause() {
     ALOGW("MPEG4Writer: pause is not supported");
     return ERROR_UNSUPPORTED;
 }
 
-void MPEG4Writer::stopWriterThread() {
-    ALOGD("Stopping writer thread");
+status_t MPEG4Writer::stopWriterThread() {
+    ALOGV("Stopping writer thread");
     if (!mWriterThreadStarted) {
-        return;
+        ALOGD("Writer thread not started");
+        return OK;
     }
-
     {
         Mutex::Autolock autolock(mLock);
-
         mDone = true;
         mChunkReadyCondition.signal();
     }
 
     void *dummy;
-    pthread_join(mThread, &dummy);
+    status_t err = OK;
+    int retVal = pthread_join(mThread, &dummy);
+    if (retVal == 0) {
+        err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
+        ALOGD("WriterThread stopped. Status:%d", err);
+    } else {
+        ALOGE("stopWriterThread pthread_join status:%d", retVal);
+        err = UNKNOWN_ERROR;
+    }
     mWriterThreadStarted = false;
-    ALOGD("Writer thread stopped");
+    return err;
 }
 
 /*
@@ -1036,17 +1110,53 @@
     writeInt32(0x40000000);  // w
 }
 
-void MPEG4Writer::release() {
-    close(mFd);
+void MPEG4Writer::printWriteDurations() {
+    if (mWriteDurationPQ.empty()) {
+        return;
+    }
+    std::string writeDurationsString =
+            "Top " + std::to_string(mWriteDurationPQ.size()) + " write durations(microseconds):";
+    uint8_t i = 0;
+    while (!mWriteDurationPQ.empty()) {
+        writeDurationsString +=
+                " #" + std::to_string(++i) + ":" + std::to_string(mWriteDurationPQ.top().count());
+        mWriteDurationPQ.pop();
+    }
+    ALOGD("%s", writeDurationsString.c_str());
+}
+
+status_t MPEG4Writer::release() {
+    ALOGD("release()");
+    status_t err = OK;
+    if (!truncatePreAllocation()) {
+        if (err == OK) { err = ERROR_IO; }
+    }
+    if (fsync(mFd) != 0) {
+        ALOGW("(ignored)fsync err:%s(%d)", std::strerror(errno), errno);
+        // Don't bubble up fsync error, b/157291505.
+        // if (err == OK) { err = ERROR_IO; }
+    }
+    if (close(mFd) != 0) {
+        ALOGE("close err:%s(%d)", std::strerror(errno), errno);
+        if (err == OK) { err = ERROR_IO; }
+    }
     mFd = -1;
     if (mNextFd != -1) {
-        close(mNextFd);
+        if (close(mNextFd) != 0) {
+            ALOGE("close(mNextFd) error:%s(%d)", std::strerror(errno), errno);
+        }
+        if (err == OK) { err = ERROR_IO; }
         mNextFd = -1;
     }
+    stopAndReleaseLooper();
     mInitCheck = NO_INIT;
     mStarted = false;
     free(mInMemoryCache);
     mInMemoryCache = NULL;
+
+    printWriteDurations();
+
+    return err;
 }
 
 void MPEG4Writer::finishCurrentSession() {
@@ -1061,7 +1171,7 @@
     }
 
     if (mNextFd == -1) {
-        ALOGW("No FileDescripter for next recording");
+        ALOGW("No FileDescriptor for next recording");
         return INVALID_OPERATION;
     }
 
@@ -1073,16 +1183,22 @@
 }
 
 status_t MPEG4Writer::reset(bool stopSource) {
+    ALOGD("reset()");
+    std::lock_guard<std::mutex> l(mResetMutex);
     if (mInitCheck != OK) {
         return OK;
     } else {
         if (!mWriterThreadStarted ||
             !mStarted) {
+            status_t writerErr = OK;
             if (mWriterThreadStarted) {
-                stopWriterThread();
+                writerErr = stopWriterThread();
             }
-            release();
-            return OK;
+            status_t retErr = release();
+            if (writerErr != OK) {
+                retErr = writerErr;
+            }
+            return retErr;
         }
     }
 
@@ -1092,9 +1208,11 @@
     int32_t nonImageTrackCount = 0;
     for (List<Track *>::iterator it = mTracks.begin();
         it != mTracks.end(); ++it) {
-        status_t status = (*it)->stop(stopSource);
-        if (err == OK && status != OK) {
-            err = status;
+        status_t trackErr = (*it)->stop(stopSource);
+        WARN_UNLESS(trackErr == OK, "%s track stopped with an error",
+                    (*it)->getTrackType());
+        if (err == OK && trackErr != OK) {
+            err = trackErr;
         }
 
         // skip image tracks
@@ -1115,26 +1233,28 @@
             minDurationUs, maxDurationUs);
     }
 
-    stopWriterThread();
+    status_t writerErr = stopWriterThread();
 
-    // Do not write out movie header on error.
-    if (err != OK) {
+    // Propagating writer error
+    if (err == OK && writerErr != OK) {
+        err = writerErr;
+    }
+
+    // Do not write out movie header on error except malformed track.
+    // TODO: Remove samples of malformed tracks added in mdat.
+    if (err != OK && err != ERROR_MALFORMED) {
+        // Ignoring release() return value as there was an "err" already.
         release();
         return err;
     }
 
     // Fix up the size of the 'mdat' chunk.
-    if (mUse32BitOffset) {
-        lseek64(mFd, mMdatOffset, SEEK_SET);
-        uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset));
-        ::write(mFd, &size, 4);
-    } else {
-        lseek64(mFd, mMdatOffset + 8, SEEK_SET);
-        uint64_t size = mOffset - mMdatOffset;
-        size = hton64(size);
-        ::write(mFd, &size, 8);
-    }
-    lseek64(mFd, mOffset, SEEK_SET);
+    seekOrPostError(mFd, mMdatOffset + 8, SEEK_SET);
+    uint64_t size = mOffset - mMdatOffset;
+    size = hton64(size);
+    writeOrPostError(mFd, &size, 8);
+    seekOrPostError(mFd, mOffset, SEEK_SET);
+    mMdatEndOffset = mOffset;
 
     // Construct file-level meta and moov box now
     mInMemoryCacheOffset = 0;
@@ -1165,6 +1285,7 @@
         } else {
             ALOGI("The mp4 file will not be streamable.");
         }
+        ALOGI("MOOV atom was written to the file");
     }
     mWriteBoxToMemory = false;
 
@@ -1177,7 +1298,11 @@
 
     CHECK(mBoxes.empty());
 
-    release();
+    status_t errRelease = release();
+    // Prioritize the error that occurred before release().
+    if (err == OK) {
+        err = errRelease;
+    }
     return err;
 }
 
@@ -1198,12 +1323,12 @@
     CHECK_LE(mInMemoryCacheOffset + 8, mInMemoryCacheSize);
 
     // Cached box
-    lseek64(mFd, mFreeBoxOffset, SEEK_SET);
+    seekOrPostError(mFd, mFreeBoxOffset, SEEK_SET);
     mOffset = mFreeBoxOffset;
     write(mInMemoryCache, 1, mInMemoryCacheOffset);
 
     // Free box
-    lseek64(mFd, mOffset, SEEK_SET);
+    seekOrPostError(mFd, mOffset, SEEK_SET);
     mFreeBoxOffset = mOffset;
     writeInt32(mInMemoryCacheSize - mInMemoryCacheOffset);
     write("free", 4);
@@ -1272,20 +1397,19 @@
                 std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs());
         }
     }
-    ALOGI("Ajust the moov start time from %lld us -> %lld us",
-            (long long)mStartTimestampUs,
-            (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
-    // Adjust the global start time.
+    ALOGI("Adjust the moov start time from %lld us -> %lld us", (long long)mStartTimestampUs,
+          (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
+    // Adjust movie start time.
     mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
 
-    // Add mStartTimeOffsetBFramesUs(-ve or zero) to the duration of first entry in STTS.
+    // Add mStartTimeOffsetBFramesUs(-ve or zero) to the start offset of tracks.
     mStartTimeOffsetBFramesUs = minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
     ALOGV("mStartTimeOffsetBFramesUs :%" PRId32, mStartTimeOffsetBFramesUs);
 
     for (List<Track *>::iterator it = mTracks.begin();
         it != mTracks.end(); ++it) {
         if (!(*it)->isHeic()) {
-            (*it)->writeTrackHeader(mUse32BitOffset);
+            (*it)->writeTrackHeader();
         }
     }
     endBox();  // moov
@@ -1346,7 +1470,7 @@
 
     for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
          it != mChunkInfos.end(); ++it) {
-        int trackNum = it->mTrack->getTrackId() << 28;
+        uint32_t trackNum = (it->mTrack->getTrackId().getId() << 28);
         notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
                 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
                 it->mMaxInterChunkDurUs);
@@ -1376,17 +1500,15 @@
     } else {
         if (tiffHdrOffset > 0) {
             tiffHdrOffset = htonl(tiffHdrOffset);
-            ::write(mFd, &tiffHdrOffset, 4); // exif_tiff_header_offset field
+            writeOrPostError(mFd, &tiffHdrOffset, 4);  // exif_tiff_header_offset field
             mOffset += 4;
         }
 
-        ::write(mFd,
-              (const uint8_t *)buffer->data() + buffer->range_offset(),
-              buffer->range_length());
+        writeOrPostError(mFd, (const uint8_t*)buffer->data() + buffer->range_offset(),
+                         buffer->range_length());
 
         mOffset += buffer->range_length();
     }
-
     *bytesWritten = mOffset - old_offset;
     return old_offset;
 }
@@ -1431,30 +1553,23 @@
 
 void MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
     size_t length = buffer->range_length();
-
     if (mUse4ByteNalLength) {
-        uint8_t x = length >> 24;
-        ::write(mFd, &x, 1);
-        x = (length >> 16) & 0xff;
-        ::write(mFd, &x, 1);
-        x = (length >> 8) & 0xff;
-        ::write(mFd, &x, 1);
-        x = length & 0xff;
-        ::write(mFd, &x, 1);
-
-        ::write(mFd,
-              (const uint8_t *)buffer->data() + buffer->range_offset(),
-              length);
-
+        uint8_t x[4];
+        x[0] = length >> 24;
+        x[1] = (length >> 16) & 0xff;
+        x[2] = (length >> 8) & 0xff;
+        x[3] = length & 0xff;
+        writeOrPostError(mFd, &x, 4);
+        writeOrPostError(mFd, (const uint8_t*)buffer->data() + buffer->range_offset(), length);
         mOffset += length + 4;
     } else {
         CHECK_LT(length, 65536u);
 
-        uint8_t x = length >> 8;
-        ::write(mFd, &x, 1);
-        x = length & 0xff;
-        ::write(mFd, &x, 1);
-        ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
+        uint8_t x[2];
+        x[0] = length >> 8;
+        x[1] = length & 0xff;
+        writeOrPostError(mFd, &x, 2);
+        writeOrPostError(mFd, (const uint8_t*)buffer->data() + buffer->range_offset(), length);
         mOffset += length + 2;
     }
 }
@@ -1476,9 +1591,9 @@
                  it != mBoxes.end(); ++it) {
                 (*it) += mOffset;
             }
-            lseek64(mFd, mOffset, SEEK_SET);
-            ::write(mFd, mInMemoryCache, mInMemoryCacheOffset);
-            ::write(mFd, ptr, bytes);
+            seekOrPostError(mFd, mOffset, SEEK_SET);
+            writeOrPostError(mFd, mInMemoryCache, mInMemoryCacheOffset);
+            writeOrPostError(mFd, ptr, bytes);
             mOffset += (bytes + mInMemoryCacheOffset);
 
             // All subsequent boxes will be written to the end of the file.
@@ -1488,13 +1603,64 @@
             mInMemoryCacheOffset += bytes;
         }
     } else {
-        ::write(mFd, ptr, size * nmemb);
+        writeOrPostError(mFd, ptr, bytes);
         mOffset += bytes;
     }
     return bytes;
 }
 
+void MPEG4Writer::writeOrPostError(int fd, const void* buf, size_t count) {
+    if (mWriteSeekErr == true)
+        return;
+
+    auto beforeTP = std::chrono::high_resolution_clock::now();
+    ssize_t bytesWritten = ::write(fd, buf, count);
+    auto afterTP = std::chrono::high_resolution_clock::now();
+    auto writeDuration =
+            std::chrono::duration_cast<std::chrono::microseconds>(afterTP - beforeTP).count();
+    mWriteDurationPQ.emplace(writeDuration);
+    if (mWriteDurationPQ.size() > kWriteDurationsCount) {
+        mWriteDurationPQ.pop();
+    }
+
+    /* Write as much as possible during stop() execution when there was an error
+     * (mWriteSeekErr == true) in the previous call to write() or lseek64().
+     */
+    if (bytesWritten == count)
+        return;
+    mWriteSeekErr = true;
+    // Note that errno is not changed even when bytesWritten < count.
+    ALOGE("writeOrPostError bytesWritten:%zd, count:%zu, error:%s(%d)", bytesWritten, count,
+          std::strerror(errno), errno);
+
+    // Can't guarantee that file is usable or write would succeed anymore, hence signal to stop.
+    sp<AMessage> msg = new AMessage(kWhatIOError, mReflector);
+    msg->setInt32("err", ERROR_IO);
+    WARN_UNLESS(msg->post() == OK, "writeOrPostError:error posting ERROR_IO");
+}
+
+void MPEG4Writer::seekOrPostError(int fd, off64_t offset, int whence) {
+    if (mWriteSeekErr == true)
+        return;
+    off64_t resOffset = lseek64(fd, offset, whence);
+    /* Allow to seek during stop() execution even when there was an error
+     * (mWriteSeekErr == true) in the previous call to write() or lseek64().
+     */
+    if (resOffset == offset)
+        return;
+    mWriteSeekErr = true;
+    ALOGE("seekOrPostError resOffset:%" PRIu64 ", offset:%" PRIu64 ", error:%s(%d)", resOffset,
+          offset, std::strerror(errno), errno);
+
+    // Can't guarantee that file is usable or seek would succeed anymore, hence signal to stop.
+    sp<AMessage> msg = new AMessage(kWhatIOError, mReflector);
+    msg->setInt32("err", ERROR_IO);
+    WARN_UNLESS(msg->post() == OK, "seekOrPostError:error posting ERROR_IO");
+}
+
 void MPEG4Writer::beginBox(uint32_t id) {
+    ALOGV("beginBox:%" PRIu32, id);
+
     mBoxes.push_back(mWriteBoxToMemory?
             mInMemoryCacheOffset: mOffset);
 
@@ -1503,6 +1669,7 @@
 }
 
 void MPEG4Writer::beginBox(const char *fourcc) {
+    ALOGV("beginBox:%s", fourcc);
     CHECK_EQ(strlen(fourcc), 4u);
 
     mBoxes.push_back(mWriteBoxToMemory?
@@ -1522,10 +1689,11 @@
         int32_t x = htonl(mInMemoryCacheOffset - offset);
         memcpy(mInMemoryCache + offset, &x, 4);
     } else {
-        lseek64(mFd, offset, SEEK_SET);
+        seekOrPostError(mFd, offset, SEEK_SET);
         writeInt32(mOffset - offset);
+        ALOGV("box size:%" PRIu64, mOffset - offset);
         mOffset -= 4;
-        lseek64(mFd, mOffset, SEEK_SET);
+        seekOrPostError(mFd, mOffset, SEEK_SET);
     }
 }
 
@@ -1679,6 +1847,87 @@
     return mStreamableFile;
 }
 
+bool MPEG4Writer::preAllocate(uint64_t wantSize) {
+    if (!mPreAllocationEnabled)
+        return true;
+
+    std::lock_guard<std::mutex> l(mFallocMutex);
+
+    if (mFallocateErr == true)
+        return false;
+
+    // approxMOOVHeadersSize has to be changed whenever its needed in the future.
+    uint64_t approxMOOVHeadersSize = 500;
+    // approxTrackHeadersSize has to be changed whenever its needed in the future.
+    const uint64_t approxTrackHeadersSize = 800;
+
+    uint64_t approxMOOVBoxSize = 0;
+    if (mPreAllocFirstTime) {
+        mPreAllocFirstTime = false;
+        approxMOOVBoxSize = approxMOOVHeadersSize + mFileLevelMetaDataSize + mMoovExtraSize +
+                            (approxTrackHeadersSize * numTracks());
+        ALOGV("firstTimeAllocation approxMOOVBoxSize:%" PRIu64, approxMOOVBoxSize);
+    }
+
+    uint64_t allTracksTotalMetaDataSizeEstimate = 0;
+    for (List<Track *>::iterator it = mTracks.begin(); it != mTracks.end(); ++it) {
+        allTracksTotalMetaDataSizeEstimate += ((*it)->trackMetaDataSize());
+    }
+    ALOGV(" allTracksTotalMetaDataSizeEstimate:%" PRIu64, allTracksTotalMetaDataSizeEstimate);
+
+    /* MOOVBoxSize will increase whenever a sample gets written to the file.  Enough to allocate
+     * the delta increase for each sample after the very first allocation.
+     */
+    uint64_t approxMetaDataSizeIncrease =
+            allTracksTotalMetaDataSizeEstimate - mPrevAllTracksTotalMetaDataSizeEstimate;
+    ALOGV("approxMetaDataSizeIncrease:%" PRIu64  " wantSize:%" PRIu64, approxMetaDataSizeIncrease,
+          wantSize);
+    mPrevAllTracksTotalMetaDataSizeEstimate = allTracksTotalMetaDataSizeEstimate;
+    ALOGV("mPreAllocateFileEndOffset:%" PRIu64 " mOffset:%" PRIu64, mPreAllocateFileEndOffset,
+          mOffset);
+    off64_t lastFileEndOffset = std::max(mPreAllocateFileEndOffset, mOffset);
+    uint64_t preAllocateSize = wantSize + approxMOOVBoxSize + approxMetaDataSizeIncrease;
+    ALOGV("preAllocateSize :%" PRIu64 " lastFileEndOffset:%" PRIu64, preAllocateSize,
+          lastFileEndOffset);
+
+    int res = fallocate64(mFd, FALLOC_FL_KEEP_SIZE, lastFileEndOffset, preAllocateSize);
+    if (res == -1) {
+        ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
+        sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector);
+        msg->setInt32("err", ERROR_IO);
+        status_t err = msg->post();
+        mFallocateErr = true;
+        ALOGD("preAllocation post:%d", err);
+    } else {
+        mPreAllocateFileEndOffset = lastFileEndOffset + preAllocateSize;
+        ALOGV("mPreAllocateFileEndOffset:%" PRIu64, mPreAllocateFileEndOffset);
+    }
+    return (res == -1) ? false : true;
+}
+
+bool MPEG4Writer::truncatePreAllocation() {
+    if (!mPreAllocationEnabled)
+        return true;
+
+    bool status = true;
+    off64_t endOffset = std::max(mMdatEndOffset, mOffset);
+    /* if mPreAllocateFileEndOffset >= endOffset, then preallocation logic works good. (diff >= 0).
+     *  Otherwise, the logic needs to be modified.
+     */
+    ALOGD("ftruncate mPreAllocateFileEndOffset:%" PRId64 " mOffset:%" PRIu64
+          " mMdatEndOffset:%" PRIu64 " diff:%" PRId64, mPreAllocateFileEndOffset, mOffset,
+          mMdatEndOffset, mPreAllocateFileEndOffset - endOffset);
+    if (ftruncate64(mFd, endOffset) == -1) {
+        ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
+        status = false;
+        /* No need to post and handle(stop & notify client) error like it's done in preAllocate(),
+         * because ftruncate() is called during release() only and the error here would be
+         * reported from there as this function is returning false on any error in ftruncate().
+         */
+    }
+    return status;
+}
+
 bool MPEG4Writer::exceedsFileSizeLimit() {
     // No limit
     if (mMaxFileSizeLimitBytes == 0) {
@@ -1764,6 +2013,9 @@
     return mStartTimestampUs;
 }
 
+/* Returns negative when reordering is needed because of BFrames or zero otherwise.
+ * CTTS values for tracks with BFrames offsets this negative value.
+ */
 int32_t MPEG4Writer::getStartTimeOffsetBFramesUs() {
     Mutex::Autolock autoLock(mLock);
     return mStartTimeOffsetBFramesUs;
@@ -1777,7 +2029,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
-        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
+        MPEG4Writer *owner, const sp<MediaSource> &source, uint32_t aTrackId)
     : mOwner(owner),
       mMeta(source->getFormat()),
       mSource(source),
@@ -1787,12 +2039,11 @@
       mStarted(false),
       mGotStartKeyFrame(false),
       mIsMalformed(false),
-      mTrackId(trackId),
+      mTrackId(aTrackId),
       mTrackDurationUs(0),
       mEstimatedTrackSizeBytes(0),
       mSamplesHaveSameSize(true),
       mStszTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
-      mStcoTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
       mCo64TableEntries(new ListTableEntries<off64_t, 1>(1000)),
       mStscTableEntries(new ListTableEntries<uint32_t, 3>(1000)),
       mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
@@ -1807,9 +2058,12 @@
       mGotAllCodecSpecificData(false),
       mReachedEOS(false),
       mStartTimestampUs(-1),
+      mFirstSampleTimeRealUs(0),
+      mFirstSampleStartOffsetUs(0),
       mRotation(0),
       mDimgRefs("dimg"),
       mImageItemId(0),
+      mItemIdBase(0),
       mIsPrimary(0),
       mWidth(0),
       mHeight(0),
@@ -1872,15 +2126,11 @@
     mIsMalformed = false;
     mTrackDurationUs = 0;
     mEstimatedTrackSizeBytes = 0;
-    mSamplesHaveSameSize = 0;
+    mSamplesHaveSameSize = false;
     if (mStszTableEntries != NULL) {
         delete mStszTableEntries;
         mStszTableEntries = new ListTableEntries<uint32_t, 1>(1000);
     }
-    if (mStcoTableEntries != NULL) {
-        delete mStcoTableEntries;
-        mStcoTableEntries = new ListTableEntries<uint32_t, 1>(1000);
-    }
     if (mCo64TableEntries != NULL) {
         delete mCo64TableEntries;
         mCo64TableEntries = new ListTableEntries<off64_t, 1>(1000);
@@ -1908,25 +2158,24 @@
     mReachedEOS = false;
 }
 
+int64_t MPEG4Writer::Track::trackMetaDataSize() {
+    int64_t co64BoxSizeBytes = mCo64TableEntries->count() * 8;
+    int64_t stszBoxSizeBytes = mStszTableEntries->count() * 4;
+    int64_t trackMetaDataSize = mStscTableEntries->count() * 12 +  // stsc box size
+                                mStssTableEntries->count() * 4 +   // stss box size
+                                mSttsTableEntries->count() * 8 +   // stts box size
+                                mCttsTableEntries->count() * 8 +   // ctts box size
+                                mElstTableEntries->count() * 12 +  // elst box size
+                                co64BoxSizeBytes +                 // stco box size
+                                stszBoxSizeBytes;                  // stsz box size
+    return trackMetaDataSize;
+}
+
+
 void MPEG4Writer::Track::updateTrackSizeEstimate() {
     mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
-
     if (!isHeic() && !mOwner->isFileStreamable()) {
-        uint32_t stcoBoxCount = (mOwner->use32BitFileOffset()
-                                ? mStcoTableEntries->count()
-                                : mCo64TableEntries->count());
-        int64_t stcoBoxSizeBytes = stcoBoxCount * 4;
-        int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mStszTableEntries->count() * 4);
-
-        // Reserved free space is not large enough to hold
-        // all meta data and thus wasted.
-        mEstimatedTrackSizeBytes += mStscTableEntries->count() * 12 +  // stsc box size
-                                    mStssTableEntries->count() * 4 +   // stss box size
-                                    mSttsTableEntries->count() * 8 +   // stts box size
-                                    mCttsTableEntries->count() * 8 +   // ctts box size
-                                    mElstTableEntries->count() * 12 +   // elst box size
-                                    stcoBoxSizeBytes +           // stco box size
-                                    stszBoxSizeBytes;            // stsz box size
+        mEstimatedTrackSizeBytes += trackMetaDataSize();
     }
 }
 
@@ -1941,24 +2190,20 @@
     mStssTableEntries->add(htonl(sampleId));
 }
 
-void MPEG4Writer::Track::addOneSttsTableEntry(
-        size_t sampleCount, int32_t duration) {
-
-    if (duration == 0) {
+void MPEG4Writer::Track::addOneSttsTableEntry(size_t sampleCount, int32_t delta) {
+    if (delta == 0) {
         ALOGW("0-duration samples found: %zu", sampleCount);
     }
     mSttsTableEntries->add(htonl(sampleCount));
-    mSttsTableEntries->add(htonl(duration));
+    mSttsTableEntries->add(htonl(delta));
 }
 
-void MPEG4Writer::Track::addOneCttsTableEntry(
-        size_t sampleCount, int32_t duration) {
-
+void MPEG4Writer::Track::addOneCttsTableEntry(size_t sampleCount, int32_t sampleOffset) {
     if (!mIsVideo) {
         return;
     }
     mCttsTableEntries->add(htonl(sampleCount));
-    mCttsTableEntries->add(htonl(duration));
+    mCttsTableEntries->add(htonl(sampleOffset));
 }
 
 void MPEG4Writer::Track::addOneElstTableEntry(
@@ -1971,16 +2216,33 @@
     mElstTableEntries->add(htonl((((uint32_t)mediaRate) << 16) | (uint32_t)mediaRateFraction));
 }
 
-status_t MPEG4Writer::setNextFd(int fd) {
-    ALOGV("addNextFd");
-    Mutex::Autolock l(mLock);
-    if (mLooper == NULL) {
-        mReflector = new AHandlerReflector<MPEG4Writer>(this);
+status_t MPEG4Writer::setupAndStartLooper() {
+    status_t err = OK;
+    if (mLooper == nullptr) {
         mLooper = new ALooper;
+        mLooper->setName("MP4WtrCtrlHlpLooper");
+        err = mLooper->start();
+        mReflector = new AHandlerReflector<MPEG4Writer>(this);
         mLooper->registerHandler(mReflector);
-        mLooper->start();
     }
+    ALOGD("MP4WtrCtrlHlpLooper Started");
+    return err;
+}
 
+void MPEG4Writer::stopAndReleaseLooper() {
+    if (mLooper != nullptr) {
+        if (mReflector != nullptr) {
+            mLooper->unregisterHandler(mReflector->id());
+            mReflector.clear();
+        }
+        mLooper->stop();
+        mLooper.clear();
+        ALOGD("MP4WtrCtrlHlpLooper stopped");
+    }
+}
+
+status_t MPEG4Writer::setNextFd(int fd) {
+    Mutex::Autolock l(mLock);
     if (mNextFd != -1) {
         // No need to set a new FD yet.
         return INVALID_OPERATION;
@@ -2021,12 +2283,7 @@
 
 void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
     CHECK(!mIsHeic);
-    if (mOwner->use32BitFileOffset()) {
-        uint32_t value = offset;
-        mStcoTableEntries->add(htonl(value));
-    } else {
-        mCo64TableEntries->add(hton64(offset));
-    }
+    mCo64TableEntries->add(hton64(offset));
 }
 
 void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size, bool isExif) {
@@ -2042,8 +2299,14 @@
     }
 
     if (isExif) {
-         mExifList.push_back(mOwner->addItem_l({
+        uint16_t exifItemId;
+        if (mOwner->reserveItemId_l(1, &exifItemId) != OK) {
+            return;
+        }
+
+        mExifList.push_back(mOwner->addItem_l({
             .itemType = "Exif",
+            .itemId = exifItemId,
             .isPrimary = false,
             .isHidden = false,
             .offset = (uint32_t)offset,
@@ -2092,6 +2355,7 @@
     if (hasGrid) {
         mDimgRefs.value.push_back(mOwner->addItem_l({
             .itemType = "hvc1",
+            .itemId = mItemIdBase++,
             .isPrimary = false,
             .isHidden = true,
             .offset = (uint32_t)offset,
@@ -2114,6 +2378,7 @@
             }
             mImageItemId = mOwner->addItem_l({
                 .itemType = "grid",
+                .itemId = mItemIdBase++,
                 .isPrimary = (mIsPrimary != 0),
                 .isHidden = false,
                 .rows = (uint32_t)mGridRows,
@@ -2126,6 +2391,7 @@
     } else {
         mImageItemId = mOwner->addItem_l({
             .itemType = "hvc1",
+            .itemId = mItemIdBase++,
             .isPrimary = (mIsPrimary != 0),
             .isHidden = false,
             .offset = (uint32_t)offset,
@@ -2195,6 +2461,39 @@
             notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED, 0);
             break;
         }
+        // ::write() or lseek64() wasn't a success, file could be malformed
+        case kWhatIOError: {
+            ALOGE("kWhatIOError");
+            int32_t err;
+            CHECK(msg->findInt32("err", &err));
+            // Stop tracks' threads and main writer thread.
+            stop();
+            notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err);
+            break;
+        }
+        // fallocate() failed, hence stop() and notify app.
+        case kWhatFallocateError: {
+            ALOGE("kWhatFallocateError");
+            int32_t err;
+            CHECK(msg->findInt32("err", &err));
+            // Stop tracks' threads and main writer thread.
+            stop();
+            //TODO: introduce a suitable MEDIA_RECORDER_ERROR_* instead MEDIA_RECORDER_ERROR_UNKNOWN?
+            notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_RECORDER_ERROR_UNKNOWN, err);
+            break;
+        }
+        /* Response to kWhatNoIOErrorSoFar would be OK always as of now.
+         * Responding with other options could be added later if required.
+         */
+        case kWhatNoIOErrorSoFar: {
+            ALOGD("kWhatNoIOErrorSoFar");
+            sp<AMessage> response = new AMessage;
+            response->setInt32("err", OK);
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+            response->postReply(replyID);
+            break;
+        }
         default:
         TRESPASS();
     }
@@ -2213,8 +2512,10 @@
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC) ||
                !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
         mMeta->findData(kKeyHVCC, &type, &data, &size);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
-            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+        mMeta->findData(kKeyDVCC, &type, &data, &size);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
         if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
             ESDS esds(data, size);
             if (esds.getCodecSpecificInfo(&data, &size) == OK &&
@@ -2234,7 +2535,6 @@
     stop();
 
     delete mStszTableEntries;
-    delete mStcoTableEntries;
     delete mCo64TableEntries;
     delete mStscTableEntries;
     delete mSttsTableEntries;
@@ -2243,7 +2543,6 @@
     delete mElstTableEntries;
 
     mStszTableEntries = NULL;
-    mStcoTableEntries = NULL;
     mCo64TableEntries = NULL;
     mStscTableEntries = NULL;
     mSttsTableEntries = NULL;
@@ -2383,7 +2682,6 @@
             if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
                 it->mMaxInterChunkDurUs = interChunkTimeUs;
             }
-
             return true;
         }
     }
@@ -2466,6 +2764,22 @@
             params->findInt32(kKeyRotation, &rotationDegrees)) {
         mRotation = rotationDegrees;
     }
+    if (mIsHeic) {
+        // Reserve the item ids, so that the item ids are ordered in the same
+        // order that the image tracks are added.
+        // If we leave the item ids to be assigned when the sample is written out,
+        // the original track order may not be preserved, if two image tracks
+        // have data around the same time. (This could happen especially when
+        // we're encoding with single tile.) The reordering may be undesirable,
+        // even if the file is well-formed and the primary picture is correct.
+
+        // Reserve item ids for samples + grid
+        size_t numItemsToReserve = mNumTiles + (mNumTiles > 1);
+        status_t err = mOwner->reserveItemId_l(numItemsToReserve, &mItemIdBase);
+        if (err != OK) {
+            return err;
+        }
+    }
 
     initTrackingProgressStatus(params);
 
@@ -2523,7 +2837,7 @@
 status_t MPEG4Writer::Track::stop(bool stopSource) {
     ALOGD("%s track stopping. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
     if (!mStarted) {
-        ALOGE("Stop() called but track is not started");
+        ALOGE("Stop() called but track is not started or stopped");
         return ERROR_END_OF_STREAM;
     }
 
@@ -2542,10 +2856,17 @@
     mDone = true;
 
     void *dummy;
-    pthread_join(mThread, &dummy);
-    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
-
-    ALOGD("%s track stopped. %s source", getTrackType(), stopSource ? "Stop" : "Not Stop");
+    status_t err = OK;
+    int retVal = pthread_join(mThread, &dummy);
+    if (retVal == 0) {
+        err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
+        ALOGD("%s track stopped. Status:%d. %s source",
+            getTrackType(), err, stopSource ? "Stop" : "Not Stop");
+    } else {
+        ALOGE("track::stop: pthread_join retVal:%d", retVal);
+        err = UNKNOWN_ERROR;
+    }
+    mStarted = false;
     return err;
 }
 
@@ -2683,6 +3004,7 @@
         }
 
         if (nextStartCode == NULL) {
+            ALOGE("nextStartCode is null");
             return ERROR_MALFORMED;
         }
 
@@ -2943,6 +3265,7 @@
     int32_t nActualFrames = 0;        // frames containing non-CSD data (non-0 length)
     int32_t nZeroLengthFrames = 0;
     int64_t lastTimestampUs = 0;      // Previous sample time stamp
+    int64_t previousSampleTimestampWithoutFudgeUs = 0; // Timestamp received/without fudge for STTS
     int64_t lastDurationUs = 0;       // Between the previous two samples
     int64_t currDurationTicks = 0;    // Timescale based ticks
     int64_t lastDurationTicks = 0;    // Timescale based ticks
@@ -2955,13 +3278,15 @@
     int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
     int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
     uint32_t lastSamplesPerChunk = 0;
+    int64_t lastSampleDurationUs = -1;      // Duration calculated from EOS buffer and its timestamp
+    int64_t lastSampleDurationTicks = -1;   // Timescale based ticks
 
     if (mIsAudio) {
-        prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
+        prctl(PR_SET_NAME, (unsigned long)"MP4WtrAudTrkThread", 0, 0, 0);
     } else if (mIsVideo) {
-        prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
+        prctl(PR_SET_NAME, (unsigned long)"MP4WtrVidTrkThread", 0, 0, 0);
     } else {
-        prctl(PR_SET_NAME, (unsigned long)"MetadataTrackEncoding", 0, 0, 0);
+        prctl(PR_SET_NAME, (unsigned long)"MP4WtrMetaTrkThread", 0, 0, 0);
     }
 
     if (mOwner->isRealTimeRecording()) {
@@ -2974,11 +3299,32 @@
     MediaBufferBase *buffer;
     const char *trackName = getTrackType();
     while (!mDone && (err = mSource->read(&buffer)) == OK) {
+        int32_t isEOS = false;
         if (buffer->range_length() == 0) {
-            buffer->release();
-            buffer = NULL;
-            ++nZeroLengthFrames;
-            continue;
+            if (buffer->meta_data().findInt32(kKeyIsEndOfStream, &isEOS) && isEOS) {
+                int64_t eosSampleTimestampUs = -1;
+                CHECK(buffer->meta_data().findInt64(kKeyTime, &eosSampleTimestampUs));
+                if (eosSampleTimestampUs > 0) {
+                    lastSampleDurationUs = eosSampleTimestampUs -
+                                           previousSampleTimestampWithoutFudgeUs -
+                                           previousPausedDurationUs;
+                    if (lastSampleDurationUs >= 0) {
+                        lastSampleDurationTicks = (lastSampleDurationUs * mTimeScale + 500000LL) /
+                                                  1000000LL;
+                    } else {
+                        ALOGW("lastSampleDurationUs %" PRId64 " is negative", lastSampleDurationUs);
+                    }
+                }
+                buffer->release();
+                buffer = nullptr;
+                mSource->stop();
+                break;
+            } else {
+                buffer->release();
+                buffer = nullptr;
+                ++nZeroLengthFrames;
+                continue;
+            }
         }
 
         // If the codec specific data has not been received yet, delay pause.
@@ -3015,7 +3361,7 @@
                                 + buffer->range_offset(),
                             buffer->range_length());
                 } else if (mIsMPEG4) {
-                    copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
+                    err = copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
                             buffer->range_length());
                 }
             }
@@ -3024,8 +3370,10 @@
             buffer = NULL;
             if (OK != err) {
                 mSource->stop();
+                mIsMalformed = true;
+                uint32_t trackNum = (mTrackId.getId() << 28);
                 mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
-                       mTrackId | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
+                       trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL, err);
                 break;
             }
 
@@ -3058,6 +3406,18 @@
             }
         }
 
+        /*
+         * Reserve space in the file for the current sample + to be written MOOV box. If reservation
+         * for a new sample fails, preAllocate(...) stops muxing session completely. Stop() could
+         * write MOOV box successfully as space for the same was reserved in the prior call.
+         * Release the current buffer/sample here.
+         */
+        if (!mOwner->preAllocate(buffer->range_length())) {
+            buffer->release();
+            buffer = nullptr;
+            break;
+        }
+
         ++nActualFrames;
 
         // Make a deep copy of the MediaBuffer and Metadata and release
@@ -3069,7 +3429,6 @@
         meta_data = new MetaData(buffer->meta_data());
         buffer->release();
         buffer = NULL;
-
         if (isExif) {
             copy->meta_data().setInt32(kKeyExifTiffOffset, tiffHdrOffset);
         }
@@ -3091,6 +3450,7 @@
         updateTrackSizeEstimate();
 
         if (mOwner->exceedsFileSizeLimit()) {
+            copy->release();
             if (mOwner->switchFd() != OK) {
                 ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
                         mOwner->mMaxFileSizeLimitBytes);
@@ -3101,26 +3461,25 @@
                 ALOGV("%s Current recorded file size exceeds limit %" PRId64 "bytes. Switching output",
                         getTrackType(), mOwner->mMaxFileSizeLimitBytes);
             }
-            copy->release();
             break;
         }
 
         if (mOwner->exceedsFileDurationLimit()) {
             ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
                     mOwner->mMaxFileDurationLimitUs);
-            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
             copy->release();
             mSource->stop();
+            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
             break;
         }
 
         if (mOwner->approachingFileSizeLimit()) {
             mOwner->notifyApproachingLimit();
         }
-
         int32_t isSync = false;
         meta_data->findInt32(kKeyIsSyncFrame, &isSync);
         CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+        timestampUs += mFirstSampleStartOffsetUs;
 
         // For video, skip the first several non-key frames until getting the first key frame.
         if (mIsVideo && !mGotStartKeyFrame && !isSync) {
@@ -3132,10 +3491,13 @@
             mGotStartKeyFrame = true;
         }
 ////////////////////////////////////////////////////////////////////////////////
-
         if (!mIsHeic) {
             if (mStszTableEntries->count() == 0) {
                 mFirstSampleTimeRealUs = systemTime() / 1000;
+                if (timestampUs < 0 && mFirstSampleStartOffsetUs == 0) {
+                    mFirstSampleStartOffsetUs = -timestampUs;
+                    timestampUs = 0;
+                }
                 mOwner->setStartTimestampUs(timestampUs);
                 mStartTimestampUs = timestampUs;
                 previousPausedDurationUs = mStartTimestampUs;
@@ -3291,6 +3653,8 @@
                 break;
             }
 
+            previousSampleTimestampWithoutFudgeUs = timestampUs;
+
             // if the duration is different for this sample, see if it is close enough to the previous
             // duration that we can fudge it and use the same value, to avoid filling the stts table
             // with lots of near-identical entries.
@@ -3307,17 +3671,17 @@
                 }
             }
             mStszTableEntries->add(htonl(sampleSize));
+
             if (mStszTableEntries->count() > 2) {
 
                 // Force the first sample to have its own stts entry so that
                 // we can adjust its value later to maintain the A/V sync.
-                if (mStszTableEntries->count() == 3 || currDurationTicks != lastDurationTicks) {
+                if (lastDurationTicks && currDurationTicks != lastDurationTicks) {
                     addOneSttsTableEntry(sampleCount, lastDurationTicks);
                     sampleCount = 1;
                 } else {
                     ++sampleCount;
                 }
-
             }
             if (mSamplesHaveSameSize) {
                 if (mStszTableEntries->count() >= 2 && previousSampleSize != sampleSize) {
@@ -3350,11 +3714,7 @@
             if (mIsHeic) {
                 addItemOffsetAndSize(offset, bytesWritten, isExif);
             } else {
-                uint32_t count = (mOwner->use32BitFileOffset()
-                            ? mStcoTableEntries->count()
-                            : mCo64TableEntries->count());
-
-                if (count == 0) {
+                if (mCo64TableEntries->count() == 0) {
                     addChunkOffset(offset);
                 }
             }
@@ -3390,7 +3750,6 @@
                 }
             }
         }
-
     }
 
     if (isTrackMalFormed()) {
@@ -3398,50 +3757,56 @@
         err = ERROR_MALFORMED;
     }
 
-    mOwner->trackProgressStatus(mTrackId, -1, err);
+    mOwner->trackProgressStatus(mTrackId.getId(), -1, err);
 
-    if (mIsHeic) {
-        if (!mChunkSamples.empty()) {
-            bufferChunk(0);
-            ++nChunks;
-        }
-    } else {
-        // Last chunk
-        if (!hasMultipleTracks) {
-            addOneStscTableEntry(1, mStszTableEntries->count());
-        } else if (!mChunkSamples.empty()) {
-            addOneStscTableEntry(++nChunks, mChunkSamples.size());
-            bufferChunk(timestampUs);
-        }
-
-        // We don't really know how long the last frame lasts, since
-        // there is no frame time after it, just repeat the previous
-        // frame's duration.
-        if (mStszTableEntries->count() == 1) {
-            lastDurationUs = 0;  // A single sample's duration
-            lastDurationTicks = 0;
-        } else {
-            ++sampleCount;  // Count for the last sample
-        }
-
-        if (mStszTableEntries->count() <= 2) {
-            addOneSttsTableEntry(1, lastDurationTicks);
-            if (sampleCount - 1 > 0) {
-                addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
+    // Add final entries only for non-empty tracks.
+    if (mStszTableEntries->count() > 0) {
+        if (mIsHeic) {
+            if (!mChunkSamples.empty()) {
+                bufferChunk(0);
+                ++nChunks;
             }
         } else {
-            addOneSttsTableEntry(sampleCount, lastDurationTicks);
-        }
+            // Last chunk
+            if (!hasMultipleTracks) {
+                addOneStscTableEntry(1, mStszTableEntries->count());
+            } else if (!mChunkSamples.empty()) {
+                addOneStscTableEntry(++nChunks, mChunkSamples.size());
+                bufferChunk(timestampUs);
+            }
 
-        // The last ctts box may not have been written yet, and this
-        // is to make sure that we write out the last ctts box.
-        if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
-            if (cttsSampleCount > 0) {
-                addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+            // We don't really know how long the last frame lasts, since
+            // there is no frame time after it, just repeat the previous
+            // frame's duration.
+            if (mStszTableEntries->count() == 1) {
+                if (lastSampleDurationUs >= 0) {
+                    addOneSttsTableEntry(sampleCount, lastSampleDurationTicks);
+                } else {
+                    lastDurationUs = 0;  // A single sample's duration
+                    lastDurationTicks = 0;
+                    addOneSttsTableEntry(sampleCount, lastDurationTicks);
+                }
+            } else if (lastSampleDurationUs >= 0) {
+                addOneSttsTableEntry(sampleCount, lastDurationTicks);
+                addOneSttsTableEntry(1, lastSampleDurationTicks);
+            } else {
+                ++sampleCount;  // Count for the last sample
+                addOneSttsTableEntry(sampleCount, lastDurationTicks);
+            }
+
+            // The last ctts box entry may not have been written yet, and this
+            // is to make sure that we write out the last ctts box entry.
+            if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
+                if (cttsSampleCount > 0) {
+                    addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+                }
+            }
+            if (lastSampleDurationUs >= 0) {
+                mTrackDurationUs += lastSampleDurationUs;
+            } else {
+                mTrackDurationUs += lastDurationUs;
             }
         }
-
-        mTrackDurationUs += lastDurationUs;
     }
     mReachedEOS = true;
 
@@ -3459,22 +3824,38 @@
     return err;
 }
 
-bool MPEG4Writer::Track::isTrackMalFormed() const {
+bool MPEG4Writer::Track::isTrackMalFormed() {
     if (mIsMalformed) {
         return true;
     }
 
-    if (!mIsHeic && mStszTableEntries->count() == 0) {  // no samples written
-        ALOGE("The number of recorded samples is 0");
-        return true;
+    int32_t emptyTrackMalformed = false;
+    if (mOwner->mStartMeta &&
+        mOwner->mStartMeta->findInt32(kKeyEmptyTrackMalFormed, &emptyTrackMalformed) &&
+        emptyTrackMalformed) {
+        // MediaRecorder(sets kKeyEmptyTrackMalFormed by default) report empty tracks as malformed.
+        if (!mIsHeic && mStszTableEntries->count() == 0) {  // no samples written
+            ALOGE("The number of recorded samples is 0");
+            mIsMalformed = true;
+            return true;
+        }
+        if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
+            ALOGE("There are no sync frames for video track");
+            mIsMalformed = true;
+            return true;
+        }
+    } else {
+        // Through MediaMuxer, empty tracks can be added. No sync frames for video.
+        if (mIsVideo && mStszTableEntries->count() > 0 && mStssTableEntries->count() == 0) {
+            ALOGE("There are no sync frames for video track");
+            mIsMalformed = true;
+            return true;
+        }
     }
-
-    if (mIsVideo && mStssTableEntries->count() == 0) {  // no sync frames for video
-        ALOGE("There are no sync frames for video track");
-        return true;
-    }
-
-    if (OK != checkCodecSpecificData()) {         // no codec specific data
+    // Don't check for CodecSpecificData when track is empty.
+    if (mStszTableEntries->count() > 0 && OK != checkCodecSpecificData()) {
+        // No codec specific data.
+        mIsMalformed = true;
         return true;
     }
 
@@ -3488,7 +3869,7 @@
         return;
     }
 
-    int trackNum = (mTrackId << 28);
+    uint32_t trackNum = (mTrackId.getId() << 28);
 
     mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
                     trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
@@ -3542,15 +3923,15 @@
     if (mTrackEveryTimeDurationUs > 0 &&
         timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
         ALOGV("Fire time tracking progress status at %" PRId64 " us", timeUs);
-        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
+        mOwner->trackProgressStatus(mTrackId.getId(), timeUs - mPreviousTrackTimeUs, err);
         mPreviousTrackTimeUs = timeUs;
     }
 }
 
 void MPEG4Writer::trackProgressStatus(
-        size_t trackId, int64_t timeUs, status_t err) {
+        uint32_t trackId, int64_t timeUs, status_t err) {
     Mutex::Autolock lock(mLock);
-    int32_t trackNum = (trackId << 28);
+    uint32_t trackNum = (trackId << 28);
 
     // Error notification
     // Do not consider ERROR_END_OF_STREAM an error
@@ -3685,7 +4066,7 @@
                       "Metadata";
 }
 
-void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
+void MPEG4Writer::Track::writeTrackHeader() {
     uint32_t now = getMpeg4Time();
     mOwner->beginBox("trak");
         writeTkhdBox(now);
@@ -3702,7 +4083,7 @@
                     writeNmhdBox();
                 }
                 writeDinfBox();
-                writeStblBox(use32BitOffset);
+                writeStblBox();
             mOwner->endBox();  // minf
         mOwner->endBox();  // mdia
     mOwner->endBox();  // trak
@@ -3718,27 +4099,30 @@
     return mMinCttsOffsetTimeUs;
 }
 
-void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
+void MPEG4Writer::Track::writeStblBox() {
     mOwner->beginBox("stbl");
-    mOwner->beginBox("stsd");
-    mOwner->writeInt32(0);               // version=0, flags=0
-    mOwner->writeInt32(1);               // entry count
-    if (mIsAudio) {
-        writeAudioFourCCBox();
-    } else if (mIsVideo) {
-        writeVideoFourCCBox();
-    } else {
-        writeMetadataFourCCBox();
+    // Add subboxes for only non-empty and well-formed tracks.
+    if (mStszTableEntries->count() > 0 && !isTrackMalFormed()) {
+        mOwner->beginBox("stsd");
+        mOwner->writeInt32(0);               // version=0, flags=0
+        mOwner->writeInt32(1);               // entry count
+        if (mIsAudio) {
+            writeAudioFourCCBox();
+        } else if (mIsVideo) {
+            writeVideoFourCCBox();
+        } else {
+            writeMetadataFourCCBox();
+        }
+        mOwner->endBox();  // stsd
+        writeSttsBox();
+        if (mIsVideo) {
+            writeCttsBox();
+            writeStssBox();
+        }
+        writeStszBox();
+        writeStscBox();
+        writeCo64Box();
     }
-    mOwner->endBox();  // stsd
-    writeSttsBox();
-    if (mIsVideo) {
-        writeCttsBox();
-        writeStssBox();
-    }
-    writeStszBox();
-    writeStscBox();
-    writeStcoBox(use32BitOffset);
     mOwner->endBox();  // stbl
 }
 
@@ -4023,7 +4407,7 @@
     mOwner->writeInt32(0x07);          // version=0, flags=7
     mOwner->writeInt32(now);           // creation time
     mOwner->writeInt32(now);           // modification time
-    mOwner->writeInt32(mTrackId);      // track id starts with 1
+    mOwner->writeInt32(mTrackId.getId()); // track id starts with 1
     mOwner->writeInt32(0);             // reserved
     int64_t trakDurationUs = getDurationUs();
     int32_t mvhdTimeScale = mOwner->getTimeScale();
@@ -4097,19 +4481,122 @@
     mOwner->endBox();
 }
 
-void MPEG4Writer::Track::writeEdtsBox(){
+void MPEG4Writer::Track::writeEdtsBox() {
     ALOGV("%s : getStartTimeOffsetTimeUs of track:%" PRId64 " us", getTrackType(),
         getStartTimeOffsetTimeUs());
 
-    // Prepone video playback.
-    if (mMinCttsOffsetTicks != mMaxCttsOffsetTicks) {
-        int32_t mvhdTimeScale = mOwner->getTimeScale();
-        uint32_t tkhdDuration = (getDurationUs() * mvhdTimeScale + 5E5) / 1E6;
-        int64_t mediaTime = ((kMaxCttsOffsetTimeUs - getMinCttsOffsetTimeUs())
-            * mTimeScale + 5E5) / 1E6;
-        if (tkhdDuration > 0 && mediaTime > 0) {
-            addOneElstTableEntry(tkhdDuration, mediaTime, 1, 0);
+    int32_t mvhdTimeScale = mOwner->getTimeScale();
+    ALOGV("mvhdTimeScale:%" PRId32, mvhdTimeScale);
+    /* trackStartOffsetUs of this track is the sum of longest offset needed by a track among all
+     * tracks with B frames in this movie and the start offset of this track.
+     */
+    int64_t trackStartOffsetUs = getStartTimeOffsetTimeUs();
+    ALOGV("trackStartOffsetUs:%" PRIu64, trackStartOffsetUs);
+
+    // Longest offset needed by a track among all tracks with B frames.
+    int32_t movieStartOffsetBFramesUs = mOwner->getStartTimeOffsetBFramesUs();
+    ALOGV("movieStartOffsetBFramesUs:%" PRId32, movieStartOffsetBFramesUs);
+
+    // This media/track's real duration (sum of duration of all samples in this track).
+    uint32_t tkhdDurationTicks = (mTrackDurationUs * mvhdTimeScale + 5E5) / 1E6;
+    ALOGV("mTrackDurationUs:%" PRId64 "us", mTrackDurationUs);
+
+    int64_t movieStartTimeUs = mOwner->getStartTimestampUs();
+    ALOGV("movieStartTimeUs:%" PRId64, movieStartTimeUs);
+
+    int64_t trackStartTimeUs = movieStartTimeUs + trackStartOffsetUs;
+    ALOGV("trackStartTimeUs:%" PRId64, trackStartTimeUs);
+
+    if (movieStartOffsetBFramesUs == 0) {
+        // No B frames in any tracks.
+        if (trackStartOffsetUs > 0) {
+            // Track with positive start offset.
+            uint32_t segDuration = (trackStartOffsetUs * mvhdTimeScale + 5E5) / 1E6;
+            ALOGV("segDuration:%" PRIu64 "us", trackStartOffsetUs);
+            /* The first entry is an empty edit (indicated by media_time equal to -1), and its
+             * duration (segment_duration) is equal to the difference of the presentation times of
+             * the earliest media sample among all tracks and the earliest media sample of the track.
+             */
+            ALOGV("Empty edit list entry");
+            addOneElstTableEntry(segDuration, -1, 1, 0);
+            addOneElstTableEntry(tkhdDurationTicks, 0, 1, 0);
+        } else if (mFirstSampleStartOffsetUs > 0) {
+            // Track with start time < 0 / negative start offset.
+            ALOGV("Normal edit list entry");
+            int32_t mediaTime = (mFirstSampleStartOffsetUs * mTimeScale + 5E5) / 1E6;
+            int32_t firstSampleOffsetTicks =
+                    (mFirstSampleStartOffsetUs * mvhdTimeScale + 5E5) / 1E6;
+            // samples before 0 don't count in for duration, hence subtract firstSampleOffsetTicks.
+            addOneElstTableEntry(tkhdDurationTicks - firstSampleOffsetTicks, mediaTime, 1, 0);
+        } else {
+            // Track starting at zero.
+            ALOGV("No edit list entry required for this track");
         }
+    } else if (movieStartOffsetBFramesUs < 0) {
+        // B frames present in at least one of the tracks.
+        ALOGV("writeEdtsBox - Reordered frames(B frames) present");
+        if (trackStartOffsetUs == std::abs(movieStartOffsetBFramesUs)) {
+            // Track starting at 0, no start offset.
+            // TODO : need to take care of mFirstSampleStartOffsetUs > 0 and trackStartOffsetUs > 0
+            // separately
+            if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
+                // Video with no B frame or non-video track.
+                if (mFirstSampleStartOffsetUs > 0) {
+                    // Track with start time < 0 / negative start offset.
+                    ALOGV("Normal edit list entry");
+                    ALOGV("mFirstSampleStartOffsetUs:%" PRId64 "us", mFirstSampleStartOffsetUs);
+                    int32_t mediaTimeTicks = (mFirstSampleStartOffsetUs * mTimeScale + 5E5) / 1E6;
+                    int32_t firstSampleOffsetTicks =
+                            (mFirstSampleStartOffsetUs * mvhdTimeScale + 5E5) / 1E6;
+                    // Samples before 0 don't count for duration, subtract firstSampleOffsetTicks.
+                    addOneElstTableEntry(tkhdDurationTicks - firstSampleOffsetTicks, mediaTimeTicks,
+                                         1, 0);
+                }
+            } else {
+                // Track with B Frames.
+                int32_t mediaTimeTicks = (trackStartOffsetUs * mTimeScale + 5E5) / 1E6;
+                ALOGV("mediaTime:%" PRId64 "us", trackStartOffsetUs);
+                ALOGV("Normal edit list entry to negate start offset by B Frames in others tracks");
+                addOneElstTableEntry(tkhdDurationTicks, mediaTimeTicks, 1, 0);
+            }
+        } else if (trackStartOffsetUs > std::abs(movieStartOffsetBFramesUs)) {
+            // Track with start offset.
+            ALOGV("Tracks starting > 0");
+            int32_t editDurationTicks = 0;
+            if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
+                // Video with no B frame or non-video track.
+                editDurationTicks =
+                        ((trackStartOffsetUs + movieStartOffsetBFramesUs) * mvhdTimeScale + 5E5) /
+                        1E6;
+                ALOGV("editDuration:%" PRId64 "us", (trackStartOffsetUs + movieStartOffsetBFramesUs));
+            } else {
+                // Track with B frame.
+                int32_t trackStartOffsetBFramesUs = getMinCttsOffsetTimeUs() - kMaxCttsOffsetTimeUs;
+                ALOGV("trackStartOffsetBFramesUs:%" PRId32, trackStartOffsetBFramesUs);
+                editDurationTicks =
+                        ((trackStartOffsetUs + movieStartOffsetBFramesUs +
+                          trackStartOffsetBFramesUs) * mvhdTimeScale + 5E5) / 1E6;
+                ALOGV("editDuration:%" PRId64 "us", (trackStartOffsetUs + movieStartOffsetBFramesUs + trackStartOffsetBFramesUs));
+            }
+            ALOGV("editDurationTicks:%" PRIu32, editDurationTicks);
+            if (editDurationTicks > 0) {
+                ALOGV("Empty edit list entry");
+                addOneElstTableEntry(editDurationTicks, -1, 1, 0);
+                addOneElstTableEntry(tkhdDurationTicks, 0, 1, 0);
+            } else if (editDurationTicks < 0) {
+                // Only video tracks with B Frames would hit this case.
+                ALOGV("Edit list entry to negate start offset by B frames in other tracks");
+                addOneElstTableEntry(tkhdDurationTicks, std::abs(editDurationTicks), 1, 0);
+            } else {
+                ALOGV("No edit list entry needed for this track");
+            }
+        } else {
+            // Not expecting this case as we adjust negative start timestamps to zero.
+            ALOGW("trackStartOffsetUs < std::abs(movieStartOffsetBFramesUs)");
+        }
+    } else {
+        // Neither B frames present nor absent! or any other case?.
+        ALOGW("movieStartOffsetBFramesUs > 0");
     }
 
     if (mElstTableEntries->count() == 0) {
@@ -4251,19 +4738,6 @@
 void MPEG4Writer::Track::writeSttsBox() {
     mOwner->beginBox("stts");
     mOwner->writeInt32(0);  // version=0, flags=0
-    if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
-        // For non-vdeio tracks or video tracks without ctts table,
-        // adjust duration of first sample for tracks to account for
-        // first sample not starting at the media start time.
-        // TODO: consider signaling this using some offset
-        // as this is not quite correct.
-        uint32_t duration;
-        CHECK(mSttsTableEntries->get(duration, 1));
-        duration = htonl(duration);  // Back to host byte order
-        int32_t startTimeOffsetScaled = (((getStartTimeOffsetTimeUs() +
-            mOwner->getStartTimeOffsetBFramesUs()) * mTimeScale) + 500000LL) / 1000000LL;
-        mSttsTableEntries->set(htonl((int32_t)duration + startTimeOffsetScaled), 1);
-    }
     mSttsTableEntries->write(mOwner);
     mOwner->endBox();  // stts
 }
@@ -4284,7 +4758,9 @@
 
     mOwner->beginBox("ctts");
     mOwner->writeInt32(0);  // version=0, flags=0
-    int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs();
+    // Adjust ctts entries to have only offset needed for reordering frames.
+    int64_t deltaTimeUs = mMinCttsOffsetTimeUs;
+    ALOGV("ctts deltaTimeUs:%" PRId64, deltaTimeUs);
     int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL;
     mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
         // entries are <count, ctts> pairs; adjust only ctts
@@ -4325,14 +4801,10 @@
     mOwner->endBox();  // stsc
 }
 
-void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
-    mOwner->beginBox(use32BitOffset? "stco": "co64");
+void MPEG4Writer::Track::writeCo64Box() {
+    mOwner->beginBox("co64");
     mOwner->writeInt32(0);  // version=0, flags=0
-    if (use32BitOffset) {
-        mStcoTableEntries->write(mOwner);
-    } else {
-        mCo64TableEntries->write(mOwner);
-    }
+    mCo64TableEntries->write(mOwner);
     mOwner->endBox();  // stco or co64
 }
 
@@ -4455,9 +4927,11 @@
     }
     writeInt16((uint16_t)itemCount);
 
-    for (size_t i = 0; i < itemCount; i++) {
-        writeInt16(mItems[i].itemId);
-        bool isGrid = mItems[i].isGrid();
+    for (auto it = mItems.begin(); it != mItems.end(); it++) {
+        ItemInfo &item = it->second;
+
+        writeInt16(item.itemId);
+        bool isGrid = item.isGrid();
 
         writeInt16(isGrid ? 1 : 0); // construction_method
         writeInt16(0); // data_reference_index = 0
@@ -4468,8 +4942,8 @@
             writeInt32(mNumGrids++ * 8);
             writeInt32(8);
         } else {
-            writeInt32(mItems[i].offset);
-            writeInt32(mItems[i].size);
+            writeInt32(item.offset);
+            writeInt32(item.size);
         }
     }
     endBox();
@@ -4498,9 +4972,11 @@
     }
 
     writeInt16((uint16_t)itemCount);
-    for (size_t i = 0; i < itemCount; i++) {
-        writeInfeBox(mItems[i].itemId, mItems[i].itemType,
-                (mItems[i].isImage() && mItems[i].isHidden) ? 1 : 0);
+    for (auto it = mItems.begin(); it != mItems.end(); it++) {
+        ItemInfo &item = it->second;
+
+        writeInfeBox(item.itemId, item.itemType,
+                (item.isImage() && item.isHidden) ? 1 : 0);
     }
 
     endBox();
@@ -4509,20 +4985,22 @@
 void MPEG4Writer::writeIdatBox() {
     beginBox("idat");
 
-    for (size_t i = 0; i < mItems.size(); i++) {
-        if (mItems[i].isGrid()) {
+    for (auto it = mItems.begin(); it != mItems.end(); it++) {
+        ItemInfo &item = it->second;
+
+        if (item.isGrid()) {
             writeInt8(0); // version
             // flags == 1 means 32-bit width,height
-            int8_t flags = (mItems[i].width > 65535 || mItems[i].height > 65535);
+            int8_t flags = (item.width > 65535 || item.height > 65535);
             writeInt8(flags);
-            writeInt8(mItems[i].rows - 1);
-            writeInt8(mItems[i].cols - 1);
+            writeInt8(item.rows - 1);
+            writeInt8(item.cols - 1);
             if (flags) {
-                writeInt32(mItems[i].width);
-                writeInt32(mItems[i].height);
+                writeInt32(item.width);
+                writeInt32(item.height);
             } else {
-                writeInt16((uint16_t)mItems[i].width);
-                writeInt16((uint16_t)mItems[i].height);
+                writeInt16((uint16_t)item.width);
+                writeInt16((uint16_t)item.height);
             }
         }
     }
@@ -4534,11 +5012,13 @@
     beginBox("iref");
     writeInt32(0);          // Version = 0, Flags = 0
     {
-        for (size_t i = 0; i < mItems.size(); i++) {
-            for (size_t r = 0; r < mItems[i].refsList.size(); r++) {
-                const ItemRefs &refs = mItems[i].refsList[r];
+        for (auto it = mItems.begin(); it != mItems.end(); it++) {
+            ItemInfo &item = it->second;
+
+            for (size_t r = 0; r < item.refsList.size(); r++) {
+                const ItemRefs &refs = item.refsList[r];
                 beginBox(refs.key);
-                writeInt16(mItems[i].itemId);
+                writeInt16(item.itemId);
                 size_t refCount = refs.value.size();
                 if (refCount > 65535) {
                     ALOGW("too many entries in %s", refs.key);
@@ -4613,12 +5093,14 @@
     writeInt32(flags); // Version = 0
 
     writeInt32(mAssociationEntryCount);
-    for (size_t itemIndex = 0; itemIndex < mItems.size(); itemIndex++) {
-        const Vector<uint16_t> &properties = mItems[itemIndex].properties;
+    for (auto it = mItems.begin(); it != mItems.end(); it++) {
+        ItemInfo &item = it->second;
+
+        const Vector<uint16_t> &properties = item.properties;
         if (properties.empty()) {
             continue;
         }
-        writeInt16(mItems[itemIndex].itemId);
+        writeInt16(item.itemId);
 
         size_t entryCount = properties.size();
         if (entryCount > 255) {
@@ -4648,19 +5130,21 @@
     // patch up the mPrimaryItemId and count items with prop associations
     uint16_t firstVisibleItemId = 0;
     uint16_t firstImageItemId = 0;
-    for (size_t index = 0; index < mItems.size(); index++) {
-        if (!mItems[index].isImage()) continue;
+    for (auto it = mItems.begin(); it != mItems.end(); it++) {
+        ItemInfo &item = it->second;
 
-        if (mItems[index].isPrimary) {
-            mPrimaryItemId = mItems[index].itemId;
+        if (!item.isImage()) continue;
+
+        if (item.isPrimary) {
+            mPrimaryItemId = item.itemId;
         }
         if (!firstImageItemId) {
-            firstImageItemId = mItems[index].itemId;
+            firstImageItemId = item.itemId;
         }
-        if (!firstVisibleItemId && !mItems[index].isHidden) {
-            firstVisibleItemId = mItems[index].itemId;
+        if (!firstVisibleItemId && !item.isHidden) {
+            firstVisibleItemId = item.itemId;
         }
-        if (!mItems[index].properties.empty()) {
+        if (!item.properties.empty()) {
             mAssociationEntryCount++;
         }
     }
@@ -4714,15 +5198,25 @@
     return mProperties.size();
 }
 
+status_t MPEG4Writer::reserveItemId_l(size_t numItems, uint16_t *itemIdBase) {
+    if (numItems > UINT16_MAX - mNextItemId) {
+        ALOGE("couldn't reserve item ids for %zu items", numItems);
+        return ERROR_OUT_OF_RANGE;
+    }
+    *itemIdBase = mNextItemId;
+    mNextItemId += numItems;
+    return OK;
+}
+
 uint16_t MPEG4Writer::addItem_l(const ItemInfo &info) {
     ALOGV("addItem_l: type %s, offset %u, size %u",
             info.itemType, info.offset, info.size);
 
-    size_t index = mItems.size();
-    mItems.push_back(info);
+    if (info.itemId < kItemIdBase || info.itemId >= mNextItemId) {
+        ALOGW("Item id %u is used without reservation!", info.itemId);
+    }
 
-    // make the item id start at kItemIdBase
-    mItems.editItemAt(index).itemId = index + kItemIdBase;
+    mItems[info.itemId] = info;
 
 #if (LOG_NDEBUG==0)
     if (!info.properties.empty()) {
@@ -4733,24 +5227,28 @@
             }
             str.append(info.properties[i]);
         }
-        ALOGV("addItem_l: id %d, properties: %s", mItems[index].itemId, str.c_str());
+        ALOGV("addItem_l: id %d, properties: %s", info.itemId, str.c_str());
     }
 #endif // (LOG_NDEBUG==0)
 
-    return mItems[index].itemId;
+    return info.itemId;
 }
 
 void MPEG4Writer::addRefs_l(uint16_t itemId, const ItemRefs &refs) {
     if (refs.value.empty()) {
         return;
     }
-    if (itemId < kItemIdBase) {
-        ALOGW("itemId shouldn't be smaller than kItemIdBase");
+    if (itemId < kItemIdBase || itemId >= mNextItemId) {
+        ALOGW("itemId %u for ref is invalid!", itemId);
         return;
     }
 
-    size_t index = itemId - kItemIdBase;
-    mItems.editItemAt(index).refsList.push_back(refs);
+    auto it = mItems.find(itemId);
+    if (it == mItems.end()) {
+        ALOGW("itemId %u was not added yet", itemId);
+        return;
+    }
+    it->second.refsList.push_back(refs);
     mHasRefs = true;
 }
 
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 4f9bc6d..24608a7 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -281,7 +281,7 @@
             it = mTimers.erase(it);
         } else {
             if (mPlaybackRate != 0.0
-                && (double)diffMediaUs < INT64_MAX * (double)mPlaybackRate) {
+                && (double)diffMediaUs < (double)INT64_MAX * (double)mPlaybackRate) {
                 int64_t targetRealUs = diffMediaUs / (double)mPlaybackRate;
                 if (targetRealUs < nextLapseRealUs) {
                     nextLapseRealUs = targetRealUs;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index eceb84e..94c0b84 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -15,31 +15,36 @@
  */
 
 //#define LOG_NDEBUG 0
+#include "hidl/HidlSupport.h"
 #define LOG_TAG "MediaCodec"
 #include <utils/Log.h>
 
 #include <inttypes.h>
 #include <stdlib.h>
 
-#include "include/SecureBuffer.h"
-#include "include/SharedMemoryBuffer.h"
+#include <C2Buffer.h>
+
 #include "include/SoftwareRenderer.h"
-#include "StagefrightPluginLoader.h"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
 #include <binder/IMemory.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
 #include <binder/MemoryDealer.h>
 #include <cutils/properties.h>
 #include <gui/BufferQueue.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IOMX.h>
-#include <media/IResourceManagerService.h>
 #include <media/MediaCodecBuffer.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaCodecInfo.h>
+#include <media/MediaMetricsItem.h>
+#include <media/MediaResource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -50,7 +55,9 @@
 #include <media/stagefright/ACodec.h>
 #include <media/stagefright/BatteryChecker.h>
 #include <media/stagefright/BufferProducerWrapper.h>
+#include <media/stagefright/CCodec.h>
 #include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -63,6 +70,11 @@
 
 namespace android {
 
+using Status = ::ndk::ScopedAStatus;
+using aidl::android::media::BnResourceManagerClient;
+using aidl::android::media::IResourceManagerClient;
+using aidl::android::media::IResourceManagerService;
+
 // key for media statistics
 static const char *kCodecKeyName = "codec";
 // attrs for media statistics
@@ -84,9 +96,12 @@
 static const char *kCodecCrypto = "android.media.mediacodec.crypto";   /* 0,1 */
 static const char *kCodecProfile = "android.media.mediacodec.profile";  /* 0..n */
 static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
+static const char *kCodecBitrateMode = "android.media.mediacodec.bitrate_mode";  /* CQ/VBR/CBR */
+static const char *kCodecBitrate = "android.media.mediacodec.bitrate";  /* 0..n */
 static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
 static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
 static const char *kCodecError = "android.media.mediacodec.errcode";
+static const char *kCodecLifetimeMs = "android.media.mediacodec.lifetimeMs";   /* 0..n ms*/
 static const char *kCodecErrorState = "android.media.mediacodec.errstate";
 static const char *kCodecLatencyMax = "android.media.mediacodec.latency.max";   /* in us */
 static const char *kCodecLatencyMin = "android.media.mediacodec.latency.min";   /* in us */
@@ -94,6 +109,12 @@
 static const char *kCodecLatencyCount = "android.media.mediacodec.latency.n";
 static const char *kCodecLatencyHist = "android.media.mediacodec.latency.hist"; /* in us */
 static const char *kCodecLatencyUnknown = "android.media.mediacodec.latency.unknown";
+static const char *kCodecQueueSecureInputBufferError = "android.media.mediacodec.queueSecureInputBufferError";
+static const char *kCodecQueueInputBufferError = "android.media.mediacodec.queueInputBufferError";
+
+static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on";  /* 0..n */
+static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off";  /* 0..n */
+static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame";  /* 0..n */
 
 // the kCodecRecent* fields appear only in getMetrics() results
 static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max";      /* in us */
@@ -106,7 +127,7 @@
 static bool kEmitHistogram = false;
 
 
-static int64_t getId(const sp<IResourceManagerClient> &client) {
+static int64_t getId(const std::shared_ptr<IResourceManagerClient> &client) {
     return (int64_t) client.get();
 }
 
@@ -118,16 +139,20 @@
 static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
 static const int kNumBuffersAlign = 16;
 
+static const C2MemoryUsage kDefaultReadWriteUsage{
+    C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
 ////////////////////////////////////////////////////////////////////////////////
 
 struct ResourceManagerClient : public BnResourceManagerClient {
     explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
 
-    virtual bool reclaimResource() {
+    Status reclaimResource(bool* _aidl_return) override {
         sp<MediaCodec> codec = mMediaCodec.promote();
         if (codec == NULL) {
             // codec is already gone.
-            return true;
+            *_aidl_return = true;
+            return Status::ok();
         }
         status_t err = codec->reclaim();
         if (err == WOULD_BLOCK) {
@@ -139,25 +164,25 @@
         if (err != OK) {
             ALOGW("ResourceManagerClient failed to release codec with err %d", err);
         }
-        return (err == OK);
+        *_aidl_return = (err == OK);
+        return Status::ok();
     }
 
-    virtual String8 getName() {
-        String8 ret;
+    Status getName(::std::string* _aidl_return) override {
+        _aidl_return->clear();
         sp<MediaCodec> codec = mMediaCodec.promote();
         if (codec == NULL) {
             // codec is already gone.
-            return ret;
+            return Status::ok();
         }
 
         AString name;
         if (codec->getName(&name) == OK) {
-            ret.setTo(name.c_str());
+            *_aidl_return = name.c_str();
         }
-        return ret;
+        return Status::ok();
     }
 
-protected:
     virtual ~ResourceManagerClient() {}
 
 private:
@@ -166,73 +191,119 @@
     DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
 };
 
+struct MediaCodec::ResourceManagerServiceProxy : public RefBase {
+    ResourceManagerServiceProxy(pid_t pid, uid_t uid,
+            const std::shared_ptr<IResourceManagerClient> &client);
+    virtual ~ResourceManagerServiceProxy();
+
+    void init();
+
+    // implements DeathRecipient
+    static void BinderDiedCallback(void* cookie);
+    void binderDied();
+
+    void addResource(const MediaResourceParcel &resource);
+    void removeResource(const MediaResourceParcel &resource);
+    void removeClient();
+    void markClientForPendingRemoval();
+    bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
+
+private:
+    Mutex mLock;
+    pid_t mPid;
+    uid_t mUid;
+    std::shared_ptr<IResourceManagerService> mService;
+    std::shared_ptr<IResourceManagerClient> mClient;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+
 MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(
-        pid_t pid, uid_t uid)
-        : mPid(pid), mUid(uid) {
+        pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client)
+        : mPid(pid), mUid(uid), mClient(client),
+          mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
     if (mPid == MediaCodec::kNoPid) {
-        mPid = IPCThreadState::self()->getCallingPid();
+        mPid = AIBinder_getCallingPid();
     }
 }
 
 MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
-    if (mService != NULL) {
-        IInterface::asBinder(mService)->unlinkToDeath(this);
+    if (mService != nullptr) {
+        AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
     }
 }
 
 void MediaCodec::ResourceManagerServiceProxy::init() {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
-    mService = interface_cast<IResourceManagerService>(binder);
-    if (mService == NULL) {
+    ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+    mService = IResourceManagerService::fromBinder(binder);
+    if (mService == nullptr) {
         ALOGE("Failed to get ResourceManagerService");
         return;
     }
-    IInterface::asBinder(mService)->linkToDeath(this);
+
+    AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
 }
 
-void MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) {
+//static
+void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
+    auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
+    thiz->binderDied();
+}
+
+void MediaCodec::ResourceManagerServiceProxy::binderDied() {
     ALOGW("ResourceManagerService died.");
     Mutex::Autolock _l(mLock);
-    mService.clear();
+    mService = nullptr;
 }
 
 void MediaCodec::ResourceManagerServiceProxy::addResource(
-        int64_t clientId,
-        const sp<IResourceManagerClient> &client,
-        const Vector<MediaResource> &resources) {
+        const MediaResourceParcel &resource) {
+    std::vector<MediaResourceParcel> resources;
+    resources.push_back(resource);
+
     Mutex::Autolock _l(mLock);
-    if (mService == NULL) {
+    if (mService == nullptr) {
         return;
     }
-    mService->addResource(mPid, mUid, clientId, client, resources);
+    mService->addResource(mPid, mUid, getId(mClient), mClient, resources);
 }
 
 void MediaCodec::ResourceManagerServiceProxy::removeResource(
-        int64_t clientId,
-        const Vector<MediaResource> &resources) {
+        const MediaResourceParcel &resource) {
+    std::vector<MediaResourceParcel> resources;
+    resources.push_back(resource);
+
     Mutex::Autolock _l(mLock);
-    if (mService == NULL) {
+    if (mService == nullptr) {
         return;
     }
-    mService->removeResource(mPid, clientId, resources);
+    mService->removeResource(mPid, getId(mClient), resources);
 }
 
-void MediaCodec::ResourceManagerServiceProxy::removeClient(int64_t clientId) {
+void MediaCodec::ResourceManagerServiceProxy::removeClient() {
     Mutex::Autolock _l(mLock);
-    if (mService == NULL) {
+    if (mService == nullptr) {
         return;
     }
-    mService->removeClient(mPid, clientId);
+    mService->removeClient(mPid, getId(mClient));
+}
+
+void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
+    Mutex::Autolock _l(mLock);
+    if (mService == nullptr) {
+        return;
+    }
+    mService->markClientForPendingRemoval(mPid, getId(mClient));
 }
 
 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
-        const Vector<MediaResource> &resources) {
+        const std::vector<MediaResourceParcel> &resources) {
     Mutex::Autolock _l(mLock);
     if (mService == NULL) {
         return false;
     }
-    return mService->reclaimResource(mPid, resources);
+    bool success;
+    Status status = mService->reclaimResource(mPid, resources, &success);
+    return status.isOk() && success;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -241,6 +312,34 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+class MediaCodec::ReleaseSurface {
+public:
+    explicit ReleaseSurface(uint64_t usage) {
+        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+        mSurface = new Surface(mProducer, false /* controlledByApp */);
+        struct ConsumerListener : public BnConsumerListener {
+            void onFrameAvailable(const BufferItem&) override {}
+            void onBuffersReleased() override {}
+            void onSidebandStreamChanged() override {}
+        };
+        sp<ConsumerListener> listener{new ConsumerListener};
+        mConsumer->consumerConnect(listener, false);
+        mConsumer->setConsumerName(String8{"MediaCodec.release"});
+        mConsumer->setConsumerUsageBits(usage);
+    }
+
+    const sp<Surface> &getSurface() {
+        return mSurface;
+    }
+
+private:
+    sp<IGraphicBufferProducer> mProducer;
+    sp<IGraphicBufferConsumer> mConsumer;
+    sp<Surface> mSurface;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
 namespace {
 
 enum {
@@ -490,9 +589,7 @@
 
 // static
 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
-    // allow plugin to create surface
-    sp<PersistentSurface> pluginSurface =
-        StagefrightPluginLoader::GetCCodecInstance()->createInputSurface();
+    sp<PersistentSurface> pluginSurface = CCodec::CreateInputSurface();
     if (pluginSurface != nullptr) {
         return pluginSurface;
     }
@@ -506,7 +603,7 @@
     sp<IOMX> omx = client.interface();
 
     sp<IGraphicBufferProducer> bufferProducer;
-    sp<IGraphicBufferSource> bufferSource;
+    sp<hardware::media::omx::V1_0::IGraphicBufferSource> bufferSource;
 
     status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
 
@@ -527,7 +624,6 @@
       mFlags(0),
       mStickyError(OK),
       mSoftRenderer(NULL),
-      mAnalyticsItem(NULL),
       mIsVideo(false),
       mVideoWidth(0),
       mVideoHeight(0),
@@ -539,28 +635,33 @@
       mHaveInputSurface(false),
       mHavePendingInputBuffers(false),
       mCpuBoostRequested(false),
-      mLatencyUnknown(0) {
+      mLatencyUnknown(0),
+      mNumLowLatencyEnables(0),
+      mNumLowLatencyDisables(0),
+      mIsLowLatencyModeOn(false),
+      mIndexOfFirstFrameWhenLowLatencyOn(-1),
+      mInputBufferCounter(0) {
     if (uid == kNoUid) {
-        mUid = IPCThreadState::self()->getCallingUid();
+        mUid = AIBinder_getCallingUid();
     } else {
         mUid = uid;
     }
-    mResourceManagerClient = new ResourceManagerClient(this);
-    mResourceManagerService = new ResourceManagerServiceProxy(pid, mUid);
+    mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
+            ::ndk::SharedRefBase::make<ResourceManagerClient>(this));
 
-    initAnalyticsItem();
+    initMediametrics();
 }
 
 MediaCodec::~MediaCodec() {
     CHECK_EQ(mState, UNINITIALIZED);
-    mResourceManagerService->removeClient(getId(mResourceManagerClient));
+    mResourceManagerProxy->removeClient();
 
-    flushAnalyticsItem();
+    flushMediametrics();
 }
 
-void MediaCodec::initAnalyticsItem() {
-    if (mAnalyticsItem == NULL) {
-        mAnalyticsItem = MediaAnalyticsItem::create(kCodecKeyName);
+void MediaCodec::initMediametrics() {
+    if (mMetricsHandle == 0) {
+        mMetricsHandle = mediametrics_create(kCodecKeyName);
     }
 
     mLatencyHist.setup(kLatencyHistBuckets, kLatencyHistWidth, kLatencyHistFloor);
@@ -572,40 +673,64 @@
         }
         mRecentHead = 0;
     }
+
+    {
+        Mutex::Autolock al(mLatencyLock);
+        mBuffersInFlight.clear();
+        mNumLowLatencyEnables = 0;
+        mNumLowLatencyDisables = 0;
+        mIsLowLatencyModeOn = false;
+        mIndexOfFirstFrameWhenLowLatencyOn = -1;
+        mInputBufferCounter = 0;
+    }
+
+    mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
 }
 
-void MediaCodec::updateAnalyticsItem() {
-    ALOGV("MediaCodec::updateAnalyticsItem");
-    if (mAnalyticsItem == NULL) {
+void MediaCodec::updateMediametrics() {
+    ALOGV("MediaCodec::updateMediametrics");
+    if (mMetricsHandle == 0) {
         return;
     }
 
     if (mLatencyHist.getCount() != 0 ) {
-        mAnalyticsItem->setInt64(kCodecLatencyMax, mLatencyHist.getMax());
-        mAnalyticsItem->setInt64(kCodecLatencyMin, mLatencyHist.getMin());
-        mAnalyticsItem->setInt64(kCodecLatencyAvg, mLatencyHist.getAvg());
-        mAnalyticsItem->setInt64(kCodecLatencyCount, mLatencyHist.getCount());
+        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
+        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
+        mediametrics_setInt64(mMetricsHandle, kCodecLatencyAvg, mLatencyHist.getAvg());
+        mediametrics_setInt64(mMetricsHandle, kCodecLatencyCount, mLatencyHist.getCount());
 
         if (kEmitHistogram) {
             // and the histogram itself
             std::string hist = mLatencyHist.emit();
-            mAnalyticsItem->setCString(kCodecLatencyHist, hist.c_str());
+            mediametrics_setCString(mMetricsHandle, kCodecLatencyHist, hist.c_str());
         }
     }
     if (mLatencyUnknown > 0) {
-        mAnalyticsItem->setInt64(kCodecLatencyUnknown, mLatencyUnknown);
+        mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
+    }
+    if (mLifetimeStartNs > 0) {
+        nsecs_t lifetime = systemTime(SYSTEM_TIME_MONOTONIC) - mLifetimeStartNs;
+        lifetime = lifetime / (1000 * 1000);    // emitted in ms, truncated not rounded
+        mediametrics_setInt64(mMetricsHandle, kCodecLifetimeMs, lifetime);
     }
 
+    {
+        Mutex::Autolock al(mLatencyLock);
+        mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables);
+        mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOff, mNumLowLatencyDisables);
+        mediametrics_setInt64(mMetricsHandle, kCodecFirstFrameIndexLowLatencyModeOn,
+                              mIndexOfFirstFrameWhenLowLatencyOn);
+    }
 #if 0
     // enable for short term, only while debugging
-    updateEphemeralAnalytics(mAnalyticsItem);
+    updateEphemeralMediametrics(mMetricsHandle);
 #endif
 }
 
-void MediaCodec::updateEphemeralAnalytics(MediaAnalyticsItem *item) {
-    ALOGD("MediaCodec::updateEphemeralAnalytics()");
+void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
+    ALOGD("MediaCodec::updateEphemeralMediametrics()");
 
-    if (item == NULL) {
+    if (item == 0) {
         return;
     }
 
@@ -625,31 +750,45 @@
         }
     }
 
-
     // spit the data (if any) into the supplied analytics record
     if (recentHist.getCount()!= 0 ) {
-        item->setInt64(kCodecRecentLatencyMax, recentHist.getMax());
-        item->setInt64(kCodecRecentLatencyMin, recentHist.getMin());
-        item->setInt64(kCodecRecentLatencyAvg, recentHist.getAvg());
-        item->setInt64(kCodecRecentLatencyCount, recentHist.getCount());
+        mediametrics_setInt64(item, kCodecRecentLatencyMax, recentHist.getMax());
+        mediametrics_setInt64(item, kCodecRecentLatencyMin, recentHist.getMin());
+        mediametrics_setInt64(item, kCodecRecentLatencyAvg, recentHist.getAvg());
+        mediametrics_setInt64(item, kCodecRecentLatencyCount, recentHist.getCount());
 
         if (kEmitHistogram) {
             // and the histogram itself
             std::string hist = recentHist.emit();
-            item->setCString(kCodecRecentLatencyHist, hist.c_str());
+            mediametrics_setCString(item, kCodecRecentLatencyHist, hist.c_str());
         }
     }
 }
 
-void MediaCodec::flushAnalyticsItem() {
-    updateAnalyticsItem();
-    if (mAnalyticsItem != NULL) {
-        // don't log empty records
-        if (mAnalyticsItem->count() > 0) {
-            mAnalyticsItem->selfrecord();
+void MediaCodec::flushMediametrics() {
+    updateMediametrics();
+    if (mMetricsHandle != 0) {
+        if (mediametrics_count(mMetricsHandle) > 0) {
+            mediametrics_selfRecord(mMetricsHandle);
         }
-        delete mAnalyticsItem;
-        mAnalyticsItem = NULL;
+        mediametrics_delete(mMetricsHandle);
+        mMetricsHandle = 0;
+    }
+}
+
+void MediaCodec::updateLowLatency(const sp<AMessage> &msg) {
+    int32_t lowLatency = 0;
+    if (msg->findInt32("low-latency", &lowLatency)) {
+        Mutex::Autolock al(mLatencyLock);
+        if (lowLatency > 0) {
+            ++mNumLowLatencyEnables;
+            // This is just an estimate since low latency mode change happens ONLY at key frame
+            mIsLowLatencyModeOn = true;
+        } else if (lowLatency == 0) {
+            ++mNumLowLatencyDisables;
+            // This is just an estimate since low latency mode change happens ONLY at key frame
+            mIsLowLatencyModeOn = false;
+        }
     }
 }
 
@@ -754,7 +893,7 @@
 
     if (mBatteryChecker != nullptr) {
         mBatteryChecker->onCodecActivity([this] () {
-            addResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1);
+            mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource());
         });
     }
 
@@ -769,6 +908,11 @@
         // XXX: we *could* make sure that the time is later than the end of queue
         // as part of a consistency check...
         mBuffersInFlight.push_back(startdata);
+
+        if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
+            mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
+        }
+        ++mInputBufferCounter;
     }
 }
 
@@ -794,7 +938,7 @@
 
     if (mBatteryChecker != nullptr) {
         mBatteryChecker->onCodecActivity([this] () {
-            addResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1);
+            mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource());
         });
     }
 
@@ -878,7 +1022,7 @@
 }
 
 static CodecBase *CreateCCodec() {
-    return StagefrightPluginLoader::GetCCodecInstance()->createCodec();
+    return new CCodec;
 }
 
 //static
@@ -903,8 +1047,30 @@
     }
 }
 
+struct CodecListCache {
+    CodecListCache()
+        : mCodecInfoMap{[] {
+              const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+              size_t count = mcl->countCodecs();
+              std::map<std::string, sp<MediaCodecInfo>> codecInfoMap;
+              for (size_t i = 0; i < count; ++i) {
+                  sp<MediaCodecInfo> info = mcl->getCodecInfo(i);
+                  codecInfoMap.emplace(info->getCodecName(), info);
+              }
+              return codecInfoMap;
+          }()} {
+    }
+
+    const std::map<std::string, sp<MediaCodecInfo>> mCodecInfoMap;
+};
+
+static const CodecListCache &GetCodecListCache() {
+    static CodecListCache sCache{};
+    return sCache;
+}
+
 status_t MediaCodec::init(const AString &name) {
-    mResourceManagerService->init();
+    mResourceManagerProxy->init();
 
     // save init parameters for reset
     mInitName = name;
@@ -917,37 +1083,41 @@
     mCodecInfo.clear();
 
     bool secureCodec = false;
-    AString tmp = name;
-    if (tmp.endsWith(".secure")) {
-        secureCodec = true;
-        tmp.erase(tmp.size() - 7, 7);
-    }
-    const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
-    if (mcl == NULL) {
-        mCodec = NULL;  // remove the codec.
-        return NO_INIT; // if called from Java should raise IOException
-    }
-    for (const AString &codecName : { name, tmp }) {
-        ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
-        if (codecIdx < 0) {
-            continue;
+    const char *owner = "";
+    if (!name.startsWith("android.filter.")) {
+        AString tmp = name;
+        if (tmp.endsWith(".secure")) {
+            secureCodec = true;
+            tmp.erase(tmp.size() - 7, 7);
         }
-        mCodecInfo = mcl->getCodecInfo(codecIdx);
-        Vector<AString> mediaTypes;
-        mCodecInfo->getSupportedMediaTypes(&mediaTypes);
-        for (size_t i = 0; i < mediaTypes.size(); i++) {
-            if (mediaTypes[i].startsWith("video/")) {
-                mIsVideo = true;
-                break;
+        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+        if (mcl == NULL) {
+            mCodec = NULL;  // remove the codec.
+            return NO_INIT; // if called from Java should raise IOException
+        }
+        for (const AString &codecName : { name, tmp }) {
+            ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
+            if (codecIdx < 0) {
+                continue;
             }
+            mCodecInfo = mcl->getCodecInfo(codecIdx);
+            Vector<AString> mediaTypes;
+            mCodecInfo->getSupportedMediaTypes(&mediaTypes);
+            for (size_t i = 0; i < mediaTypes.size(); i++) {
+                if (mediaTypes[i].startsWith("video/")) {
+                    mIsVideo = true;
+                    break;
+                }
+            }
+            break;
         }
-        break;
-    }
-    if (mCodecInfo == nullptr) {
-        return NAME_NOT_FOUND;
+        if (mCodecInfo == nullptr) {
+            return NAME_NOT_FOUND;
+        }
+        owner = mCodecInfo->getOwnerName();
     }
 
-    mCodec = GetCodecBase(name, mCodecInfo->getOwnerName());
+    mCodec = GetCodecBase(name, owner);
     if (mCodec == NULL) {
         return NAME_NOT_FOUND;
     }
@@ -976,14 +1146,17 @@
                     new BufferCallback(new AMessage(kWhatCodecNotify, this))));
 
     sp<AMessage> msg = new AMessage(kWhatInit, this);
-    msg->setObject("codecInfo", mCodecInfo);
-    // name may be different from mCodecInfo->getCodecName() if we stripped
-    // ".secure"
+    if (mCodecInfo) {
+        msg->setObject("codecInfo", mCodecInfo);
+        // name may be different from mCodecInfo->getCodecName() if we stripped
+        // ".secure"
+    }
     msg->setString("name", name);
 
-    if (mAnalyticsItem != NULL) {
-        mAnalyticsItem->setCString(kCodecCodec, name.c_str());
-        mAnalyticsItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio);
+    if (mMetricsHandle != 0) {
+        mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
+        mediametrics_setCString(mMetricsHandle, kCodecMode,
+                                mIsVideo ? kCodecModeVideo : kCodecModeAudio);
     }
 
     if (mIsVideo) {
@@ -991,16 +1164,12 @@
     }
 
     status_t err;
-    Vector<MediaResource> resources;
-    MediaResource::Type type =
-            secureCodec ? MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
-    MediaResource::SubType subtype =
-            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
-    resources.push_back(MediaResource(type, subtype, 1));
+    std::vector<MediaResourceParcel> resources;
+    resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo));
     for (int i = 0; i <= kMaxRetry; ++i) {
         if (i > 0) {
             // Don't try to reclaim resource for the first time.
-            if (!mResourceManagerService->reclaimResource(resources)) {
+            if (!mResourceManagerProxy->reclaimResource(resources)) {
                 break;
             }
         }
@@ -1044,16 +1213,17 @@
         uint32_t flags) {
     sp<AMessage> msg = new AMessage(kWhatConfigure, this);
 
-    if (mAnalyticsItem != NULL) {
+    if (mMetricsHandle != 0) {
         int32_t profile = 0;
         if (format->findInt32("profile", &profile)) {
-            mAnalyticsItem->setInt32(kCodecProfile, profile);
+            mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
         }
         int32_t level = 0;
         if (format->findInt32("level", &level)) {
-            mAnalyticsItem->setInt32(kCodecLevel, level);
+            mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
         }
-        mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
+        mediametrics_setInt32(mMetricsHandle, kCodecEncoder,
+                              (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
     }
 
     if (mIsVideo) {
@@ -1063,17 +1233,17 @@
             mRotationDegrees = 0;
         }
 
-        if (mAnalyticsItem != NULL) {
-            mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth);
-            mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight);
-            mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees);
+        if (mMetricsHandle != 0) {
+            mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth);
+            mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight);
+            mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
             int32_t maxWidth = 0;
             if (format->findInt32("max-width", &maxWidth)) {
-                mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth);
+                mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth);
             }
             int32_t maxHeight = 0;
             if (format->findInt32("max-height", &maxHeight)) {
-                mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight);
+                mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
             }
         }
 
@@ -1085,6 +1255,8 @@
         }
     }
 
+    updateLowLatency(format);
+
     msg->setMessage("format", format);
     msg->setInt32("flags", flags);
     msg->setObject("surface", surface);
@@ -1095,8 +1267,8 @@
         } else {
             msg->setPointer("descrambler", descrambler.get());
         }
-        if (mAnalyticsItem != NULL) {
-            mAnalyticsItem->setInt32(kCodecCrypto, 1);
+        if (mMetricsHandle != 0) {
+            mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1);
         }
     } else if (mFlags & kFlagIsSecure) {
         ALOGW("Crypto or descrambler should be given for secure codec");
@@ -1106,19 +1278,15 @@
     mConfigureMsg = msg;
 
     status_t err;
-    Vector<MediaResource> resources;
-    MediaResource::Type type = (mFlags & kFlagIsSecure) ?
-            MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
-    MediaResource::SubType subtype =
-            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
-    resources.push_back(MediaResource(type, subtype, 1));
+    std::vector<MediaResourceParcel> resources;
+    resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
     // Don't know the buffer size at this point, but it's fine to use 1 because
     // the reclaimResource call doesn't consider the requester's buffer size for now.
-    resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
+    resources.push_back(MediaResource::GraphicMemoryResource(1));
     for (int i = 0; i <= kMaxRetry; ++i) {
         if (i > 0) {
             // Don't try to reclaim resource for the first time.
-            if (!mResourceManagerService->reclaimResource(resources)) {
+            if (!mResourceManagerProxy->reclaimResource(resources)) {
                 break;
             }
         }
@@ -1239,38 +1407,19 @@
     return size;
 }
 
-void MediaCodec::addResource(
-        MediaResource::Type type, MediaResource::SubType subtype, uint64_t value) {
-    Vector<MediaResource> resources;
-    resources.push_back(MediaResource(type, subtype, value));
-    mResourceManagerService->addResource(
-            getId(mResourceManagerClient), mResourceManagerClient, resources);
-}
-
-void MediaCodec::removeResource(
-        MediaResource::Type type, MediaResource::SubType subtype, uint64_t value) {
-    Vector<MediaResource> resources;
-    resources.push_back(MediaResource(type, subtype, value));
-    mResourceManagerService->removeResource(getId(mResourceManagerClient), resources);
-}
-
 status_t MediaCodec::start() {
     sp<AMessage> msg = new AMessage(kWhatStart, this);
 
     status_t err;
-    Vector<MediaResource> resources;
-    MediaResource::Type type = (mFlags & kFlagIsSecure) ?
-            MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
-    MediaResource::SubType subtype =
-            mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
-    resources.push_back(MediaResource(type, subtype, 1));
+    std::vector<MediaResourceParcel> resources;
+    resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
     // Don't know the buffer size at this point, but it's fine to use 1 because
     // the reclaimResource call doesn't consider the requester's buffer size for now.
-    resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
+    resources.push_back(MediaResource::GraphicMemoryResource(1));
     for (int i = 0; i <= kMaxRetry; ++i) {
         if (i > 0) {
             // Don't try to reclaim resource for the first time.
-            if (!mResourceManagerService->reclaimResource(resources)) {
+            if (!mResourceManagerProxy->reclaimResource(resources)) {
                 break;
             }
             // Recover codec from previous error before retry start.
@@ -1330,7 +1479,13 @@
 
 status_t MediaCodec::release() {
     sp<AMessage> msg = new AMessage(kWhatRelease, this);
+    sp<AMessage> response;
+    return PostAndAwaitResponse(msg, &response);
+}
 
+status_t MediaCodec::releaseAsync(const sp<AMessage> &notify) {
+    sp<AMessage> msg = new AMessage(kWhatRelease, this);
+    msg->setMessage("async", notify);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
@@ -1429,6 +1584,75 @@
     return err;
 }
 
+status_t MediaCodec::queueBuffer(
+        size_t index,
+        const std::shared_ptr<C2Buffer> &buffer,
+        int64_t presentationTimeUs,
+        uint32_t flags,
+        const sp<AMessage> &tunings,
+        AString *errorDetailMsg) {
+    if (errorDetailMsg != NULL) {
+        errorDetailMsg->clear();
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
+    msg->setSize("index", index);
+    sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
+        new WrapperObject<std::shared_ptr<C2Buffer>>{buffer}};
+    msg->setObject("c2buffer", obj);
+    msg->setInt64("timeUs", presentationTimeUs);
+    msg->setInt32("flags", flags);
+    msg->setMessage("tunings", tunings);
+    msg->setPointer("errorDetailMsg", errorDetailMsg);
+
+    sp<AMessage> response;
+    status_t err = PostAndAwaitResponse(msg, &response);
+
+    return err;
+}
+
+status_t MediaCodec::queueEncryptedBuffer(
+        size_t index,
+        const sp<hardware::HidlMemory> &buffer,
+        size_t offset,
+        const CryptoPlugin::SubSample *subSamples,
+        size_t numSubSamples,
+        const uint8_t key[16],
+        const uint8_t iv[16],
+        CryptoPlugin::Mode mode,
+        const CryptoPlugin::Pattern &pattern,
+        int64_t presentationTimeUs,
+        uint32_t flags,
+        const sp<AMessage> &tunings,
+        AString *errorDetailMsg) {
+    if (errorDetailMsg != NULL) {
+        errorDetailMsg->clear();
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
+    msg->setSize("index", index);
+    sp<WrapperObject<sp<hardware::HidlMemory>>> memory{
+        new WrapperObject<sp<hardware::HidlMemory>>{buffer}};
+    msg->setObject("memory", memory);
+    msg->setSize("offset", offset);
+    msg->setPointer("subSamples", (void *)subSamples);
+    msg->setSize("numSubSamples", numSubSamples);
+    msg->setPointer("key", (void *)key);
+    msg->setPointer("iv", (void *)iv);
+    msg->setInt32("mode", mode);
+    msg->setInt32("encryptBlocks", pattern.mEncryptBlocks);
+    msg->setInt32("skipBlocks", pattern.mSkipBlocks);
+    msg->setInt64("timeUs", presentationTimeUs);
+    msg->setInt32("flags", flags);
+    msg->setMessage("tunings", tunings);
+    msg->setPointer("errorDetailMsg", errorDetailMsg);
+
+    sp<AMessage> response;
+    status_t err = PostAndAwaitResponse(msg, &response);
+
+    return err;
+}
+
 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
     sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
     msg->setInt64("timeoutUs", timeoutUs);
@@ -1561,22 +1785,22 @@
     return OK;
 }
 
-status_t MediaCodec::getMetrics(MediaAnalyticsItem * &reply) {
+status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) {
 
-    reply = NULL;
+    reply = 0;
 
     // shouldn't happen, but be safe
-    if (mAnalyticsItem == NULL) {
+    if (mMetricsHandle == 0) {
         return UNKNOWN_ERROR;
     }
 
     // update any in-flight data that's not carried within the record
-    updateAnalyticsItem();
+    updateMediametrics();
 
     // send it back to the caller.
-    reply = mAnalyticsItem->dup();
+    reply = mediametrics_dup(mMetricsHandle);
 
-    updateEphemeralAnalytics(reply);
+    updateEphemeralMediametrics(reply);
 
     return OK;
 }
@@ -1708,8 +1932,7 @@
             totalPixel = width * height;
         }
         if (totalPixel >= 1920 * 1080) {
-            addResource(MediaResource::kCpuBoost,
-                    MediaResource::kUnspecifiedSubType, 1);
+            mResourceManagerProxy->addResource(MediaResource::CpuBoostResource());
             mCpuBoostRequested = true;
         }
     }
@@ -1890,10 +2113,11 @@
                         case CONFIGURING:
                         {
                             if (actionCode == ACTION_CODE_FATAL) {
-                                mAnalyticsItem->setInt32(kCodecError, err);
-                                mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
-                                flushAnalyticsItem();
-                                initAnalyticsItem();
+                                mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+                                mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+                                                        stateString(mState).c_str());
+                                flushMediametrics();
+                                initMediametrics();
                             }
                             setState(actionCode == ACTION_CODE_FATAL ?
                                     UNINITIALIZED : INITIALIZED);
@@ -1903,10 +2127,11 @@
                         case STARTING:
                         {
                             if (actionCode == ACTION_CODE_FATAL) {
-                                mAnalyticsItem->setInt32(kCodecError, err);
-                                mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
-                                flushAnalyticsItem();
-                                initAnalyticsItem();
+                                mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+                                mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+                                                        stateString(mState).c_str());
+                                flushMediametrics();
+                                initMediametrics();
                             }
                             setState(actionCode == ACTION_CODE_FATAL ?
                                     UNINITIALIZED : CONFIGURED);
@@ -1944,10 +2169,11 @@
                         case FLUSHING:
                         {
                             if (actionCode == ACTION_CODE_FATAL) {
-                                mAnalyticsItem->setInt32(kCodecError, err);
-                                mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
-                                flushAnalyticsItem();
-                                initAnalyticsItem();
+                                mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+                                mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+                                                        stateString(mState).c_str());
+                                flushMediametrics();
+                                initMediametrics();
 
                                 setState(UNINITIALIZED);
                             } else {
@@ -1977,10 +2203,11 @@
                                 setState(INITIALIZED);
                                 break;
                             default:
-                                mAnalyticsItem->setInt32(kCodecError, err);
-                                mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
-                                flushAnalyticsItem();
-                                initAnalyticsItem();
+                                mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+                                mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+                                                        stateString(mState).c_str());
+                                flushMediametrics();
+                                initMediametrics();
                                 setState(UNINITIALIZED);
                                 break;
                             }
@@ -2037,32 +2264,31 @@
                     CHECK(msg->findString("componentName", &mComponentName));
 
                     if (mComponentName.c_str()) {
-                        mAnalyticsItem->setCString(kCodecCodec, mComponentName.c_str());
+                        mediametrics_setCString(mMetricsHandle, kCodecCodec,
+                                                mComponentName.c_str());
                     }
 
-                    const char *owner = mCodecInfo->getOwnerName();
+                    const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
                     if (mComponentName.startsWith("OMX.google.")
-                            && (owner == nullptr || strncmp(owner, "default", 8) == 0)) {
+                            && strncmp(owner, "default", 8) == 0) {
                         mFlags |= kFlagUsesSoftwareRenderer;
                     } else {
                         mFlags &= ~kFlagUsesSoftwareRenderer;
                     }
                     mOwnerName = owner;
 
-                    MediaResource::Type resourceType;
                     if (mComponentName.endsWith(".secure")) {
                         mFlags |= kFlagIsSecure;
-                        resourceType = MediaResource::kSecureCodec;
-                        mAnalyticsItem->setInt32(kCodecSecure, 1);
+                        mediametrics_setInt32(mMetricsHandle, kCodecSecure, 1);
                     } else {
                         mFlags &= ~kFlagIsSecure;
-                        resourceType = MediaResource::kNonSecureCodec;
-                        mAnalyticsItem->setInt32(kCodecSecure, 0);
+                        mediametrics_setInt32(mMetricsHandle, kCodecSecure, 0);
                     }
 
                     if (mIsVideo) {
                         // audio codec is currently ignored.
-                        addResource(resourceType, MediaResource::kVideoCodec, 1);
+                        mResourceManagerProxy->addResource(
+                                MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
                     }
 
                     (new AMessage)->postReply(mReplyID);
@@ -2092,6 +2318,8 @@
                         // meaningful and confusing for an encoder in a transcoder scenario
                         mInputFormat->setInt32("allow-frame-drop", mAllowFrameDroppingBySurface);
                     }
+                    sp<AMessage> interestingFormat =
+                            (mFlags & kFlagIsEncoder) ? mOutputFormat : mInputFormat;
                     ALOGV("[%s] configured as input format: %s, output format: %s",
                             mComponentName.c_str(),
                             mInputFormat->debugString(4).c_str(),
@@ -2105,16 +2333,42 @@
                     (new AMessage)->postReply(mReplyID);
 
                     // augment our media metrics info, now that we know more things
-                    if (mAnalyticsItem != NULL) {
+                    // such as what the codec extracted from any CSD passed in.
+                    if (mMetricsHandle != 0) {
                         sp<AMessage> format;
                         if (mConfigureMsg != NULL &&
                             mConfigureMsg->findMessage("format", &format)) {
                                 // format includes: mime
                                 AString mime;
                                 if (format->findString("mime", &mime)) {
-                                    mAnalyticsItem->setCString(kCodecMime, mime.c_str());
+                                    mediametrics_setCString(mMetricsHandle, kCodecMime,
+                                                            mime.c_str());
                                 }
                             }
+                        // perhaps video only?
+                        int32_t profile = 0;
+                        if (interestingFormat->findInt32("profile", &profile)) {
+                            mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
+                        }
+                        int32_t level = 0;
+                        if (interestingFormat->findInt32("level", &level)) {
+                            mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
+                        }
+                        // bitrate and bitrate mode, encoder only
+                        if (mFlags & kFlagIsEncoder) {
+                            // encoder specific values
+                            int32_t bitrate_mode = -1;
+                            if (mOutputFormat->findInt32(KEY_BITRATE_MODE, &bitrate_mode)) {
+                                    mediametrics_setCString(mMetricsHandle, kCodecBitrateMode,
+                                          asString_BitrateMode(bitrate_mode));
+                            }
+                            int32_t bitrate = -1;
+                            if (mOutputFormat->findInt32(KEY_BIT_RATE, &bitrate)) {
+                                    mediametrics_setInt32(mMetricsHandle, kCodecBitrate, bitrate);
+                            }
+                        } else {
+                            // decoder specific values
+                        }
                     }
                     break;
                 }
@@ -2182,10 +2436,8 @@
 
                     CHECK_EQ(mState, STARTING);
                     if (mIsVideo) {
-                        addResource(
-                                MediaResource::kGraphicMemory,
-                                MediaResource::kUnspecifiedSubType,
-                                getGraphicBufferSize());
+                        mResourceManagerProxy->addResource(
+                                MediaResource::GraphicMemoryResource(getGraphicBufferSize()));
                     }
                     setState(STARTED);
                     (new AMessage)->postReply(mReplyID);
@@ -2245,6 +2497,18 @@
                         }
                         break;
                     }
+                    if (!mLeftover.empty()) {
+                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
+                        CHECK_GE(index, 0);
+
+                        status_t err = handleLeftover(index);
+                        if (err != OK) {
+                            setStickyError(err);
+                            postActivityNotificationIfPossible();
+                            cancelPendingDequeueOperations();
+                        }
+                        break;
+                    }
 
                     if (mFlags & kFlagIsAsync) {
                         if (!mHaveInputSurface) {
@@ -2282,6 +2546,23 @@
                     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
 
                     if (mOutputFormat != buffer->format()) {
+                        if (mFlags & kFlagUseBlockModel) {
+                            sp<AMessage> diff1 = mOutputFormat->changesFrom(buffer->format());
+                            sp<AMessage> diff2 = buffer->format()->changesFrom(mOutputFormat);
+                            std::set<std::string> keys;
+                            size_t numEntries = diff1->countEntries();
+                            AMessage::Type type;
+                            for (size_t i = 0; i < numEntries; ++i) {
+                                keys.emplace(diff1->getEntryNameAt(i, &type));
+                            }
+                            numEntries = diff2->countEntries();
+                            for (size_t i = 0; i < numEntries; ++i) {
+                                keys.emplace(diff2->getEntryNameAt(i, &type));
+                            }
+                            sp<WrapperObject<std::set<std::string>>> changedKeys{
+                                new WrapperObject<std::set<std::string>>{std::move(keys)}};
+                            buffer->meta()->setObject("changedKeys", changedKeys);
+                        }
                         mOutputFormat = buffer->format();
                         ALOGV("[%s] output format changed to: %s",
                                 mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
@@ -2331,7 +2612,7 @@
                             // format as necessary.
                             int32_t flags = 0;
                             (void) buffer->meta()->findInt32("flags", &flags);
-                            if (flags & BUFFER_FLAG_CODECCONFIG) {
+                            if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)) {
                                 status_t err =
                                     amendOutputFormatWithCodecSpecificData(buffer);
 
@@ -2409,9 +2690,17 @@
                         mBatteryChecker->onClientRemoved();
                     }
 
-                    mResourceManagerService->removeClient(getId(mResourceManagerClient));
+                    mResourceManagerProxy->removeClient();
+                    mReleaseSurface.reset();
 
-                    (new AMessage)->postReply(mReplyID);
+                    if (mReplyID != nullptr) {
+                        (new AMessage)->postReply(mReplyID);
+                    }
+                    if (mAsyncReleaseCompleteNotification != nullptr) {
+                        flushMediametrics();
+                        mAsyncReleaseCompleteNotification->post();
+                        mAsyncReleaseCompleteNotification.clear();
+                    }
                     break;
                 }
 
@@ -2454,12 +2743,14 @@
             setState(INITIALIZING);
 
             sp<RefBase> codecInfo;
-            CHECK(msg->findObject("codecInfo", &codecInfo));
+            (void)msg->findObject("codecInfo", &codecInfo);
             AString name;
             CHECK(msg->findString("name", &name));
 
             sp<AMessage> format = new AMessage;
-            format->setObject("codecInfo", codecInfo);
+            if (codecInfo) {
+                format->setObject("codecInfo", codecInfo);
+            }
             format->setString("componentName", name);
 
             mCodec->initiateAllocateComponent(format);
@@ -2547,6 +2838,15 @@
                 handleSetSurface(NULL);
             }
 
+            uint32_t flags;
+            CHECK(msg->findInt32("flags", (int32_t *)&flags));
+            if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
+                if (!(mFlags & kFlagIsAsync)) {
+                    PostReplyWithError(replyID, INVALID_OPERATION);
+                    break;
+                }
+                mFlags |= kFlagUseBlockModel;
+            }
             mReplyID = replyID;
             setState(CONFIGURING);
 
@@ -2572,9 +2872,7 @@
             mDescrambler = static_cast<IDescrambler *>(descrambler);
             mBufferChannel->setDescrambler(mDescrambler);
 
-            uint32_t flags;
-            CHECK(msg->findInt32("flags", (int32_t *)&flags));
-
+            format->setInt32("flags", flags);
             if (flags & CONFIGURE_FLAG_ENCODE) {
                 format->setInt32("encoder", true);
                 mFlags |= kFlagIsEncoder;
@@ -2789,6 +3087,31 @@
                 break;
             }
 
+            sp<AMessage> asyncNotify;
+            if (msg->findMessage("async", &asyncNotify) && asyncNotify != nullptr) {
+                if (mSurface != NULL) {
+                    if (!mReleaseSurface) {
+                        uint64_t usage = 0;
+                        if (mSurface->getConsumerUsage(&usage) != OK) {
+                            usage = 0;
+                        }
+                        mReleaseSurface.reset(new ReleaseSurface(usage));
+                    }
+                    if (mSurface != mReleaseSurface->getSurface()) {
+                        status_t err = connectToSurface(mReleaseSurface->getSurface());
+                        ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
+                        if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
+                            err = mCodec->setSurface(mReleaseSurface->getSurface());
+                            ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
+                        }
+                        if (err == OK) {
+                            (void)disconnectFromSurface();
+                            mSurface = mReleaseSurface->getSurface();
+                        }
+                    }
+                }
+            }
+
             mReplyID = replyID;
             setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
 
@@ -2801,6 +3124,13 @@
                 pushBlankBuffersToNativeWindow(mSurface.get());
             }
 
+            if (asyncNotify != nullptr) {
+                mResourceManagerProxy->markClientForPendingRemoval();
+                (new AMessage)->postReply(mReplyID);
+                mReplyID = 0;
+                mAsyncReleaseCompleteNotification = asyncNotify;
+            }
+
             break;
         }
 
@@ -2878,7 +3208,15 @@
                 break;
             }
 
-            status_t err = onQueueInputBuffer(msg);
+            status_t err = UNKNOWN_ERROR;
+            if (!mLeftover.empty()) {
+                mLeftover.push_back(msg);
+                size_t index;
+                msg->findSize("index", &index);
+                err = handleLeftover(index);
+            } else {
+                err = onQueueInputBuffer(msg);
+            }
 
             PostReplyWithError(replyID, err);
             break;
@@ -3124,7 +3462,8 @@
         {
             if (mBatteryChecker != nullptr) {
                 mBatteryChecker->onCheckBatteryTimer(msg, [this] () {
-                    removeResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1);
+                    mResourceManagerProxy->removeResource(
+                            MediaResource::VideoBatteryResource());
                 });
             }
             break;
@@ -3158,22 +3497,59 @@
 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
     CHECK(!mCSD.empty());
 
-    const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex];
-
     sp<ABuffer> csd = *mCSD.begin();
     mCSD.erase(mCSD.begin());
+    std::shared_ptr<C2Buffer> c2Buffer;
+    sp<hardware::HidlMemory> memory;
+    size_t offset = 0;
 
-    const sp<MediaCodecBuffer> &codecInputData = info.mData;
+    if (mFlags & kFlagUseBlockModel) {
+        if (hasCryptoOrDescrambler()) {
+            constexpr size_t kInitialDealerCapacity = 1048576;  // 1MB
+            thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
+                    kInitialDealerCapacity, "CSD(1MB)");
+            sp<IMemory> mem = sDealer->allocate(csd->size());
+            if (mem == nullptr) {
+                size_t newDealerCapacity = sDealer->getMemoryHeap()->getSize() * 2;
+                while (csd->size() * 2 > newDealerCapacity) {
+                    newDealerCapacity *= 2;
+                }
+                sDealer = new MemoryDealer(
+                        newDealerCapacity,
+                        AStringPrintf("CSD(%dMB)", newDealerCapacity / 1048576).c_str());
+                mem = sDealer->allocate(csd->size());
+            }
+            memcpy(mem->unsecurePointer(), csd->data(), csd->size());
+            ssize_t heapOffset;
+            memory = hardware::fromHeap(mem->getMemory(&heapOffset, nullptr));
+            offset += heapOffset;
+        } else {
+            std::shared_ptr<C2LinearBlock> block =
+                FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
+            C2WriteView view{block->map().get()};
+            if (view.error() != C2_OK) {
+                return -EINVAL;
+            }
+            if (csd->size() > view.capacity()) {
+                return -EINVAL;
+            }
+            memcpy(view.base(), csd->data(), csd->size());
+            c2Buffer = C2Buffer::CreateLinearBuffer(block->share(0, csd->size(), C2Fence{}));
+        }
+    } else {
+        const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex];
+        const sp<MediaCodecBuffer> &codecInputData = info.mData;
 
-    if (csd->size() > codecInputData->capacity()) {
-        return -EINVAL;
+        if (csd->size() > codecInputData->capacity()) {
+            return -EINVAL;
+        }
+        if (codecInputData->data() == NULL) {
+            ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
+            return -EINVAL;
+        }
+
+        memcpy(codecInputData->data(), csd->data(), csd->size());
     }
-    if (codecInputData->data() == NULL) {
-        ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
-        return -EINVAL;
-    }
-
-    memcpy(codecInputData->data(), csd->data(), csd->size());
 
     AString errorDetailMsg;
 
@@ -3184,6 +3560,17 @@
     msg->setInt64("timeUs", 0LL);
     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
     msg->setPointer("errorDetailMsg", &errorDetailMsg);
+    if (c2Buffer) {
+        sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
+            new WrapperObject<std::shared_ptr<C2Buffer>>{c2Buffer}};
+        msg->setObject("c2buffer", obj);
+        msg->setMessage("tunings", new AMessage);
+    } else if (memory) {
+        sp<WrapperObject<sp<hardware::HidlMemory>>> obj{
+            new WrapperObject<sp<hardware::HidlMemory>>{memory}};
+        msg->setObject("memory", obj);
+        msg->setMessage("tunings", new AMessage);
+    }
 
     return onQueueInputBuffer(msg);
 }
@@ -3242,6 +3629,9 @@
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
     Mutex::Autolock al(mBufferLock);
 
+    if (portIndex == kPortIndexInput) {
+        mLeftover.clear();
+    }
     for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {
         BufferInfo *info = &mPortBuffers[portIndex][i];
 
@@ -3289,10 +3679,21 @@
     int64_t timeUs;
     uint32_t flags;
     CHECK(msg->findSize("index", &index));
-    CHECK(msg->findSize("offset", &offset));
     CHECK(msg->findInt64("timeUs", &timeUs));
     CHECK(msg->findInt32("flags", (int32_t *)&flags));
-
+    std::shared_ptr<C2Buffer> c2Buffer;
+    sp<hardware::HidlMemory> memory;
+    sp<RefBase> obj;
+    if (msg->findObject("c2buffer", &obj)) {
+        CHECK(obj);
+        c2Buffer = static_cast<WrapperObject<std::shared_ptr<C2Buffer>> *>(obj.get())->value;
+    } else if (msg->findObject("memory", &obj)) {
+        CHECK(obj);
+        memory = static_cast<WrapperObject<sp<hardware::HidlMemory>> *>(obj.get())->value;
+        CHECK(msg->findSize("offset", &offset));
+    } else {
+        CHECK(msg->findSize("offset", &offset));
+    }
     const CryptoPlugin::SubSample *subSamples;
     size_t numSubSamples;
     const uint8_t *key;
@@ -3316,7 +3717,7 @@
             pattern.mEncryptBlocks = 0;
             pattern.mSkipBlocks = 0;
         }
-    } else {
+    } else if (!c2Buffer) {
         if (!hasCryptoOrDescrambler()) {
             ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
                     mComponentName.c_str());
@@ -3347,28 +3748,67 @@
     }
 
     BufferInfo *info = &mPortBuffers[kPortIndexInput][index];
+    sp<MediaCodecBuffer> buffer = info->mData;
 
-    if (info->mData == nullptr || !info->mOwnedByClient) {
+    if (c2Buffer || memory) {
+        sp<AMessage> tunings;
+        CHECK(msg->findMessage("tunings", &tunings));
+        onSetParameters(tunings);
+
+        status_t err = OK;
+        if (c2Buffer) {
+            err = mBufferChannel->attachBuffer(c2Buffer, buffer);
+        } else if (memory) {
+            err = mBufferChannel->attachEncryptedBuffer(
+                    memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
+                    offset, subSamples, numSubSamples, buffer);
+        } else {
+            err = UNKNOWN_ERROR;
+        }
+
+        if (err == OK && !buffer->asC2Buffer()
+                && c2Buffer && c2Buffer->data().type() == C2BufferData::LINEAR) {
+            C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
+            if (block.size() > buffer->size()) {
+                C2ConstLinearBlock leftover = block.subBlock(
+                        block.offset() + buffer->size(), block.size() - buffer->size());
+                sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
+                    new WrapperObject<std::shared_ptr<C2Buffer>>{
+                        C2Buffer::CreateLinearBuffer(leftover)}};
+                msg->setObject("c2buffer", obj);
+                mLeftover.push_front(msg);
+                // Not sending EOS if we have leftovers
+                flags &= ~BUFFER_FLAG_EOS;
+            }
+        }
+
+        offset = buffer->offset();
+        size = buffer->size();
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    if (buffer == nullptr || !info->mOwnedByClient) {
         return -EACCES;
     }
 
-    if (offset + size > info->mData->capacity()) {
+    if (offset + size > buffer->capacity()) {
         return -EINVAL;
     }
 
-    info->mData->setRange(offset, size);
-    info->mData->meta()->setInt64("timeUs", timeUs);
+    buffer->setRange(offset, size);
+    buffer->meta()->setInt64("timeUs", timeUs);
     if (flags & BUFFER_FLAG_EOS) {
-        info->mData->meta()->setInt32("eos", true);
+        buffer->meta()->setInt32("eos", true);
     }
 
     if (flags & BUFFER_FLAG_CODECCONFIG) {
-        info->mData->meta()->setInt32("csd", true);
+        buffer->meta()->setInt32("csd", true);
     }
 
-    sp<MediaCodecBuffer> buffer = info->mData;
     status_t err = OK;
-    if (hasCryptoOrDescrambler()) {
+    if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
         AString *errorDetailMsg;
         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
 
@@ -3382,8 +3822,16 @@
                 subSamples,
                 numSubSamples,
                 errorDetailMsg);
+        if (err != OK) {
+            mediametrics_setInt32(mMetricsHandle, kCodecQueueSecureInputBufferError, err);
+            ALOGW("Log queueSecureInputBuffer error: %d", err);
+        }
     } else {
         err = mBufferChannel->queueInputBuffer(buffer);
+        if (err != OK) {
+            mediametrics_setInt32(mMetricsHandle, kCodecQueueInputBufferError, err);
+            ALOGW("Log queueInputBuffer error: %d", err);
+        }
     }
 
     if (err == OK) {
@@ -3398,6 +3846,16 @@
     return err;
 }
 
+status_t MediaCodec::handleLeftover(size_t index) {
+    if (mLeftover.empty()) {
+        return OK;
+    }
+    sp<AMessage> msg = mLeftover.front();
+    mLeftover.pop_front();
+    msg->setSize("index", index);
+    return onQueueInputBuffer(msg);
+}
+
 //static
 size_t MediaCodec::CreateFramesRenderedMessage(
         const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
@@ -3685,6 +4143,7 @@
 }
 
 status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
+    updateLowLatency(params);
     mCodec->signalSetParameters(params);
 
     return OK;
@@ -3758,4 +4217,70 @@
     return rval;
 }
 
+// static
+status_t MediaCodec::CanFetchLinearBlock(
+        const std::vector<std::string> &names, bool *isCompatible) {
+    *isCompatible = false;
+    if (names.size() == 0) {
+        *isCompatible = true;
+        return OK;
+    }
+    const CodecListCache &cache = GetCodecListCache();
+    for (const std::string &name : names) {
+        auto it = cache.mCodecInfoMap.find(name);
+        if (it == cache.mCodecInfoMap.end()) {
+            return NAME_NOT_FOUND;
+        }
+        const char *owner = it->second->getOwnerName();
+        if (owner == nullptr || strncmp(owner, "default", 8) == 0) {
+            *isCompatible = false;
+            return OK;
+        } else if (strncmp(owner, "codec2::", 8) != 0) {
+            return NAME_NOT_FOUND;
+        }
+    }
+    return CCodec::CanFetchLinearBlock(names, kDefaultReadWriteUsage, isCompatible);
+}
+
+// static
+std::shared_ptr<C2LinearBlock> MediaCodec::FetchLinearBlock(
+        size_t capacity, const std::vector<std::string> &names) {
+    return CCodec::FetchLinearBlock(capacity, kDefaultReadWriteUsage, names);
+}
+
+// static
+status_t MediaCodec::CanFetchGraphicBlock(
+        const std::vector<std::string> &names, bool *isCompatible) {
+    *isCompatible = false;
+    if (names.size() == 0) {
+        *isCompatible = true;
+        return OK;
+    }
+    const CodecListCache &cache = GetCodecListCache();
+    for (const std::string &name : names) {
+        auto it = cache.mCodecInfoMap.find(name);
+        if (it == cache.mCodecInfoMap.end()) {
+            return NAME_NOT_FOUND;
+        }
+        const char *owner = it->second->getOwnerName();
+        if (owner == nullptr || strncmp(owner, "default", 8) == 0) {
+            *isCompatible = false;
+            return OK;
+        } else if (strncmp(owner, "codec2.", 7) != 0) {
+            return NAME_NOT_FOUND;
+        }
+    }
+    return CCodec::CanFetchGraphicBlock(names, isCompatible);
+}
+
+// static
+std::shared_ptr<C2GraphicBlock> MediaCodec::FetchGraphicBlock(
+        int32_t width,
+        int32_t height,
+        int32_t format,
+        uint64_t usage,
+        const std::vector<std::string> &names) {
+    return CCodec::FetchGraphicBlock(width, height, format, usage, names);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 3d58d4b..ac54fa1 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -19,7 +19,6 @@
 #include <utils/Log.h>
 
 #include "MediaCodecListOverrides.h"
-#include "StagefrightPluginLoader.h"
 
 #include <binder/IServiceManager.h>
 
@@ -30,11 +29,14 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include <media/stagefright/CCodec.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/OmxInfoBuilder.h>
-#include <media/stagefright/omx/OMXUtils.h>
-#include <xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include <media/stagefright/PersistentSurface.h>
 
 #include <sys/stat.h>
 #include <utils/threads.h>
@@ -86,8 +88,7 @@
 MediaCodecListBuilderBase *GetCodec2InfoBuilder() {
     Mutex::Autolock _l(sCodec2InfoBuilderMutex);
     if (!sCodec2InfoBuilder) {
-        sCodec2InfoBuilder.reset(
-                StagefrightPluginLoader::GetCCodecInstance()->createBuilder());
+        sCodec2InfoBuilder.reset(new Codec2InfoBuilder);
     }
     return sCodec2InfoBuilder.get();
 }
@@ -96,8 +97,7 @@
     std::vector<MediaCodecListBuilderBase *> builders;
     // if plugin provides the input surface, we cannot use OMX video encoders.
     // In this case, rely on plugin to provide list of OMX codecs that are usable.
-    sp<PersistentSurface> surfaceTest =
-        StagefrightPluginLoader::GetCCodecInstance()->createInputSurface();
+    sp<PersistentSurface> surfaceTest = CCodec::CreateInputSurface();
     if (surfaceTest == nullptr) {
         ALOGD("Allowing all OMX codecs");
         builders.push_back(&sOmxInfoBuilder);
@@ -170,6 +170,7 @@
 sp<IMediaCodecList> MediaCodecList::sRemoteList;
 
 sp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
+sp<IBinder> MediaCodecList::sMediaPlayer;  // kept since linked to death
 
 void MediaCodecList::BinderDeathObserver::binderDied(const wp<IBinder> &who __unused) {
     Mutex::Autolock _l(sRemoteInitMutex);
@@ -181,15 +182,14 @@
 sp<IMediaCodecList> MediaCodecList::getInstance() {
     Mutex::Autolock _l(sRemoteInitMutex);
     if (sRemoteList == nullptr) {
-        sp<IBinder> binder =
-            defaultServiceManager()->getService(String16("media.player"));
+        sMediaPlayer = defaultServiceManager()->getService(String16("media.player"));
         sp<IMediaPlayerService> service =
-            interface_cast<IMediaPlayerService>(binder);
+            interface_cast<IMediaPlayerService>(sMediaPlayer);
         if (service.get() != nullptr) {
             sRemoteList = service->getCodecList();
             if (sRemoteList != nullptr) {
                 sBinderDeathObserver = new BinderDeathObserver();
-                binder->linkToDeath(sBinderDeathObserver.get());
+                sMediaPlayer->linkToDeath(sBinderDeathObserver.get());
             }
         }
         if (sRemoteList == nullptr) {
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index dd7c3e6..4a167d1 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -22,7 +22,7 @@
 
 #include <cutils/properties.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IMediaCodecList.h>
 #include <media/MediaCodecInfo.h>
 #include <media/MediaResourcePolicy.h>
@@ -264,7 +264,9 @@
             }
         }
     }
-    global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
+    global_results->add(
+            MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs(),
+            supportMultipleSecureCodecs);
 }
 
 static AString globalResultsToXml(const CodecSettings &results) {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 50e454c..1395c27 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -22,10 +22,10 @@
 
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaBufferHolder.h>
 #include <media/MediaCodecBuffer.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -221,6 +221,7 @@
 
 void MediaCodecSource::Puller::resume() {
     Mutexed<Queue>::Locked queue(mQueue);
+    queue->flush();
     queue->mPaused = false;
 }
 
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 4c8be1f..c6e753d 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -27,8 +27,8 @@
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaExtractorFactory.h>
-#include <media/IMediaExtractor.h>
-#include <media/IMediaExtractorService.h>
+#include <android/IMediaExtractor.h>
+#include <android/IMediaExtractorService.h>
 #include <nativeloader/dlext_namespaces.h>
 #include <private/android_filesystem_config.h>
 #include <cutils/properties.h>
@@ -54,9 +54,13 @@
         sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
 
         if (binder != 0) {
-            sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
-            sp<IMediaExtractor> ex = mediaExService->makeExtractor(
-                    CreateIDataSourceFromDataSource(source), mime);
+            sp<IMediaExtractorService> mediaExService(
+                    interface_cast<IMediaExtractorService>(binder));
+            sp<IMediaExtractor> ex;
+            mediaExService->makeExtractor(
+                    CreateIDataSourceFromDataSource(source),
+                    mime ? std::make_unique<std::string>(mime) : nullptr,
+                    &ex);
             return ex;
         } else {
             ALOGE("extractor service not running");
@@ -71,9 +75,6 @@
 
     ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
 
-    // initialize source decryption if needed
-    source->DrmInitialization(nullptr /* mime */);
-
     void *meta = nullptr;
     void *creator = NULL;
     FreeMetaFunc freeMeta = nullptr;
@@ -265,7 +266,7 @@
     return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
 }
 
-static std::unordered_set<std::string> gSupportedExtensions;
+static std::vector<std::string> gSupportedExtensions;
 
 // static
 void MediaExtractorFactory::LoadExtractors() {
@@ -279,7 +280,7 @@
 
     std::shared_ptr<std::list<sp<ExtractorPlugin>>> newList(new std::list<sp<ExtractorPlugin>>());
 
-    android_namespace_t *mediaNs = android_get_exported_namespace("media");
+    android_namespace_t *mediaNs = android_get_exported_namespace("com_android_media");
     if (mediaNs != NULL) {
         const android_dlextinfo dlextinfo = {
             .flags = ANDROID_DLEXT_USE_NAMESPACE,
@@ -301,6 +302,12 @@
 #endif
             "/extractors", NULL, *newList);
 
+    RegisterExtractors("/system_ext/lib"
+#ifdef __LP64__
+            "64"
+#endif
+            "/extractors", NULL, *newList);
+
     newList->sort(compareFunc);
     gPlugins = newList;
 
@@ -311,7 +318,7 @@
                 if (ext == nullptr) {
                     break;
                 }
-                gSupportedExtensions.insert(std::string(ext));
+                gSupportedExtensions.push_back(std::string(ext));
             }
         }
     }
@@ -320,7 +327,7 @@
 }
 
 // static
-std::unordered_set<std::string> MediaExtractorFactory::getSupportedTypes() {
+std::vector<std::string> MediaExtractorFactory::getSupportedTypes() {
     if (getuid() == AID_MEDIA_EX) {
         return gSupportedExtensions;
     }
@@ -329,9 +336,11 @@
 
     if (binder != 0) {
         sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
-        return mediaExService->getSupportedTypes();
+        std::vector<std::string> supportedTypes;
+        mediaExService->getSupportedTypes(&supportedTypes);
+        return supportedTypes;
     }
-    return std::unordered_set<std::string>();
+    return std::vector<std::string>();
 }
 
 status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index 7ebdb1a..cab4ebd 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -24,7 +24,7 @@
 #include <media/stagefright/MediaMuxer.h>
 
 #include <media/mediarecorder.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -155,7 +155,6 @@
 
 status_t MediaMuxer::stop() {
     Mutex::Autolock autoLock(mMuxerLock);
-
     if (mState == STARTED) {
         mState = STOPPED;
         for (size_t i = 0; i < mTrackList.size(); i++) {
@@ -163,7 +162,11 @@
                 return INVALID_OPERATION;
             }
         }
-        return mWriter->stop();
+        status_t err = mWriter->stop();
+        if (err != OK) {
+            ALOGE("stop() err: %d", err);
+        }
+        return err;
     } else {
         ALOGE("stop() is called in invalid state %d", mState);
         return INVALID_OPERATION;
@@ -207,6 +210,11 @@
         sampleMetaData.setInt32(kKeyIsMuxerData, 1);
     }
 
+    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
+        sampleMetaData.setInt32(kKeyIsEndOfStream, 1);
+        ALOGV("BUFFER_FLAG_EOS");
+    }
+
     sp<MediaAdapter> currentTrack = mTrackList[trackIndex];
     // This pushBuffer will wait until the mediaBuffer is consumed.
     return currentTrack->pushBuffer(mediaBuffer);
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index 5bbd3d8..ee0031f 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/IMediaSource.h>
 
 namespace android {
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 89c9b25..24ba38a 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -183,6 +183,11 @@
             meta.setData(kKeyAudioPresentationInfo,
                     MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
         }
+        if (format->mFormat->findBuffer("csd-0", &valbuf)) {
+            meta.setData(kKeyOpaqueCSD0,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
+
     } else {
         *buffer = nullptr;
     }
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp
index 3f0bc7d..db60f04 100644
--- a/media/libstagefright/MetaDataUtils.cpp
+++ b/media/libstagefright/MetaDataUtils.cpp
@@ -25,7 +25,6 @@
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaDataUtils.h>
-#include <media/stagefright/Utils.h>
 #include <media/NdkMediaFormat.h>
 
 namespace android {
diff --git a/media/libstagefright/NdkUtils.cpp b/media/libstagefright/NdkUtils.cpp
deleted file mode 100644
index 904fe72..0000000
--- a/media/libstagefright/NdkUtils.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 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
-
-#include <media/stagefright/NdkUtils.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-namespace android {
-
-sp<MetaData> convertMediaFormatWrapperToMetaData(const sp<AMediaFormatWrapper> &fmt) {
-    sp<AMessage> msg = fmt->toAMessage();
-    sp<MetaData> meta = new MetaData;
-    convertMessageToMetaData(msg, meta);
-    return meta;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
deleted file mode 100644
index 522c81d..0000000
--- a/media/libstagefright/NuCachedSource2.cpp
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Copyright (C) 2010 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 <inttypes.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "NuCachedSource2"
-#include <utils/Log.h>
-
-#include "include/NuCachedSource2.h"
-#include "include/HTTPBase.h"
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-struct PageCache {
-    explicit PageCache(size_t pageSize);
-    ~PageCache();
-
-    struct Page {
-        void *mData;
-        size_t mSize;
-    };
-
-    Page *acquirePage();
-    void releasePage(Page *page);
-
-    void appendPage(Page *page);
-    size_t releaseFromStart(size_t maxBytes);
-
-    size_t totalSize() const {
-        return mTotalSize;
-    }
-
-    void copy(size_t from, void *data, size_t size);
-
-private:
-    size_t mPageSize;
-    size_t mTotalSize;
-
-    List<Page *> mActivePages;
-    List<Page *> mFreePages;
-
-    void freePages(List<Page *> *list);
-
-    DISALLOW_EVIL_CONSTRUCTORS(PageCache);
-};
-
-PageCache::PageCache(size_t pageSize)
-    : mPageSize(pageSize),
-      mTotalSize(0) {
-}
-
-PageCache::~PageCache() {
-    freePages(&mActivePages);
-    freePages(&mFreePages);
-}
-
-void PageCache::freePages(List<Page *> *list) {
-    List<Page *>::iterator it = list->begin();
-    while (it != list->end()) {
-        Page *page = *it;
-
-        free(page->mData);
-        delete page;
-        page = NULL;
-
-        ++it;
-    }
-}
-
-PageCache::Page *PageCache::acquirePage() {
-    if (!mFreePages.empty()) {
-        List<Page *>::iterator it = mFreePages.begin();
-        Page *page = *it;
-        mFreePages.erase(it);
-
-        return page;
-    }
-
-    Page *page = new Page;
-    page->mData = malloc(mPageSize);
-    page->mSize = 0;
-
-    return page;
-}
-
-void PageCache::releasePage(Page *page) {
-    page->mSize = 0;
-    mFreePages.push_back(page);
-}
-
-void PageCache::appendPage(Page *page) {
-    mTotalSize += page->mSize;
-    mActivePages.push_back(page);
-}
-
-size_t PageCache::releaseFromStart(size_t maxBytes) {
-    size_t bytesReleased = 0;
-
-    while (maxBytes > 0 && !mActivePages.empty()) {
-        List<Page *>::iterator it = mActivePages.begin();
-
-        Page *page = *it;
-
-        if (maxBytes < page->mSize) {
-            break;
-        }
-
-        mActivePages.erase(it);
-
-        maxBytes -= page->mSize;
-        bytesReleased += page->mSize;
-
-        releasePage(page);
-    }
-
-    mTotalSize -= bytesReleased;
-    return bytesReleased;
-}
-
-void PageCache::copy(size_t from, void *data, size_t size) {
-    ALOGV("copy from %zu size %zu", from, size);
-
-    if (size == 0) {
-        return;
-    }
-
-    CHECK_LE(from + size, mTotalSize);
-
-    size_t offset = 0;
-    List<Page *>::iterator it = mActivePages.begin();
-    while (from >= offset + (*it)->mSize) {
-        offset += (*it)->mSize;
-        ++it;
-    }
-
-    size_t delta = from - offset;
-    size_t avail = (*it)->mSize - delta;
-
-    if (avail >= size) {
-        memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
-        return;
-    }
-
-    memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
-    ++it;
-    data = (uint8_t *)data + avail;
-    size -= avail;
-
-    while (size > 0) {
-        size_t copy = (*it)->mSize;
-        if (copy > size) {
-            copy = size;
-        }
-        memcpy(data, (*it)->mData, copy);
-        data = (uint8_t *)data + copy;
-        size -= copy;
-        ++it;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-NuCachedSource2::NuCachedSource2(
-        const sp<DataSource> &source,
-        const char *cacheConfig,
-        bool disconnectAtHighwatermark)
-    : mSource(source),
-      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
-      mLooper(new ALooper),
-      mCache(new PageCache(kPageSize)),
-      mCacheOffset(0),
-      mFinalStatus(OK),
-      mLastAccessPos(0),
-      mFetching(true),
-      mDisconnecting(false),
-      mLastFetchTimeUs(-1),
-      mNumRetriesLeft(kMaxNumRetries),
-      mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
-      mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
-      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
-      mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
-    // We are NOT going to support disconnect-at-highwatermark indefinitely
-    // and we are not guaranteeing support for client-specified cache
-    // parameters. Both of these are temporary measures to solve a specific
-    // problem that will be solved in a better way going forward.
-
-    updateCacheParamsFromSystemProperty();
-
-    if (cacheConfig != NULL) {
-        updateCacheParamsFromString(cacheConfig);
-    }
-
-    if (mDisconnectAtHighwatermark) {
-        // Makes no sense to disconnect and do keep-alives...
-        mKeepAliveIntervalUs = 0;
-    }
-
-    mLooper->setName("NuCachedSource2");
-    mLooper->registerHandler(mReflector);
-
-    // Since it may not be obvious why our looper thread needs to be
-    // able to call into java since it doesn't appear to do so at all...
-    // IMediaHTTPConnection may be (and most likely is) implemented in JAVA
-    // and a local JAVA IBinder will call directly into JNI methods.
-    // So whenever we call DataSource::readAt it may end up in a call to
-    // IMediaHTTPConnection::readAt and therefore call back into JAVA.
-    mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
-
-    mName = String8::format("NuCachedSource2(%s)", mSource->toString().string());
-}
-
-NuCachedSource2::~NuCachedSource2() {
-    mLooper->stop();
-    mLooper->unregisterHandler(mReflector->id());
-
-    delete mCache;
-    mCache = NULL;
-}
-
-// static
-sp<NuCachedSource2> NuCachedSource2::Create(
-        const sp<DataSource> &source,
-        const char *cacheConfig,
-        bool disconnectAtHighwatermark) {
-    sp<NuCachedSource2> instance = new NuCachedSource2(
-            source, cacheConfig, disconnectAtHighwatermark);
-    Mutex::Autolock autoLock(instance->mLock);
-    (new AMessage(kWhatFetchMore, instance->mReflector))->post();
-    return instance;
-}
-
-status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
-    if (mSource->flags() & kIsHTTPBasedSource) {
-        HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
-        return source->getEstimatedBandwidthKbps(kbps);
-    }
-    return ERROR_UNSUPPORTED;
-}
-
-void NuCachedSource2::close() {
-    disconnect();
-}
-
-void NuCachedSource2::disconnect() {
-    if (mSource->flags() & kIsHTTPBasedSource) {
-        ALOGV("disconnecting HTTPBasedSource");
-
-        {
-            Mutex::Autolock autoLock(mLock);
-            // set mDisconnecting to true, if a fetch returns after
-            // this, the source will be marked as EOS.
-            mDisconnecting = true;
-
-            // explicitly signal mCondition so that the pending readAt()
-            // will immediately return
-            mCondition.signal();
-        }
-
-        // explicitly disconnect from the source, to allow any
-        // pending reads to return more promptly
-        static_cast<HTTPBase *>(mSource.get())->disconnect();
-    }
-}
-
-status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
-    if (mSource->flags() & kIsHTTPBasedSource) {
-        HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
-        return source->setBandwidthStatCollectFreq(freqMs);
-    }
-    return ERROR_UNSUPPORTED;
-}
-
-status_t NuCachedSource2::initCheck() const {
-    return mSource->initCheck();
-}
-
-status_t NuCachedSource2::getSize(off64_t *size) {
-    return mSource->getSize(size);
-}
-
-uint32_t NuCachedSource2::flags() {
-    // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
-    uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
-    return (flags | kIsCachingDataSource);
-}
-
-void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatFetchMore:
-        {
-            onFetch();
-            break;
-        }
-
-        case kWhatRead:
-        {
-            onRead(msg);
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-}
-
-void NuCachedSource2::fetchInternal() {
-    ALOGV("fetchInternal");
-
-    bool reconnect = false;
-
-    {
-        Mutex::Autolock autoLock(mLock);
-        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
-
-        if (mFinalStatus != OK) {
-            --mNumRetriesLeft;
-
-            reconnect = true;
-        }
-    }
-
-    if (reconnect) {
-        status_t err =
-            mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
-
-        Mutex::Autolock autoLock(mLock);
-
-        if (mDisconnecting) {
-            mNumRetriesLeft = 0;
-            mFinalStatus = ERROR_END_OF_STREAM;
-            return;
-        } else if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
-            // These are errors that are not likely to go away even if we
-            // retry, i.e. the server doesn't support range requests or similar.
-            mNumRetriesLeft = 0;
-            return;
-        } else if (err != OK) {
-            ALOGI("The attempt to reconnect failed, %d retries remaining",
-                 mNumRetriesLeft);
-
-            return;
-        }
-    }
-
-    PageCache::Page *page = mCache->acquirePage();
-
-    ssize_t n = mSource->readAt(
-            mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (n == 0 || mDisconnecting) {
-        ALOGI("caching reached eos.");
-
-        mNumRetriesLeft = 0;
-        mFinalStatus = ERROR_END_OF_STREAM;
-
-        mCache->releasePage(page);
-    } else if (n < 0) {
-        mFinalStatus = n;
-        if (n == ERROR_UNSUPPORTED || n == -EPIPE) {
-            // These are errors that are not likely to go away even if we
-            // retry, i.e. the server doesn't support range requests or similar.
-            mNumRetriesLeft = 0;
-        }
-
-        ALOGE("source returned error %zd, %d retries left", n, mNumRetriesLeft);
-        mCache->releasePage(page);
-    } else {
-        if (mFinalStatus != OK) {
-            ALOGI("retrying a previously failed read succeeded.");
-        }
-        mNumRetriesLeft = kMaxNumRetries;
-        mFinalStatus = OK;
-
-        page->mSize = n;
-        mCache->appendPage(page);
-    }
-}
-
-void NuCachedSource2::onFetch() {
-    ALOGV("onFetch");
-
-    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
-        ALOGV("EOS reached, done prefetching for now");
-        mFetching = false;
-    }
-
-    bool keepAlive =
-        !mFetching
-            && mFinalStatus == OK
-            && mKeepAliveIntervalUs > 0
-            && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs;
-
-    if (mFetching || keepAlive) {
-        if (keepAlive) {
-            ALOGI("Keep alive");
-        }
-
-        fetchInternal();
-
-        mLastFetchTimeUs = ALooper::GetNowUs();
-
-        if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
-            ALOGI("Cache full, done prefetching for now");
-            mFetching = false;
-
-            if (mDisconnectAtHighwatermark
-                    && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
-                ALOGV("Disconnecting at high watermark");
-                static_cast<HTTPBase *>(mSource.get())->disconnect();
-                mFinalStatus = -EAGAIN;
-            }
-        }
-    } else {
-        Mutex::Autolock autoLock(mLock);
-        restartPrefetcherIfNecessary_l();
-    }
-
-    int64_t delayUs;
-    if (mFetching) {
-        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
-            // We failed this time and will try again in 3 seconds.
-            delayUs = 3000000LL;
-        } else {
-            delayUs = 0;
-        }
-    } else {
-        delayUs = 100000LL;
-    }
-
-    (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
-}
-
-void NuCachedSource2::onRead(const sp<AMessage> &msg) {
-    ALOGV("onRead");
-
-    int64_t offset;
-    CHECK(msg->findInt64("offset", &offset));
-
-    void *data;
-    CHECK(msg->findPointer("data", &data));
-
-    size_t size;
-    CHECK(msg->findSize("size", &size));
-
-    ssize_t result = readInternal(offset, data, size);
-
-    if (result == -EAGAIN) {
-        msg->post(50000);
-        return;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (mDisconnecting) {
-        mCondition.signal();
-        return;
-    }
-
-    CHECK(mAsyncResult == NULL);
-
-    mAsyncResult = new AMessage;
-    mAsyncResult->setInt32("result", result);
-
-    mCondition.signal();
-}
-
-void NuCachedSource2::restartPrefetcherIfNecessary_l(
-        bool ignoreLowWaterThreshold, bool force) {
-    static const size_t kGrayArea = 1024 * 1024;
-
-    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
-        return;
-    }
-
-    if (!ignoreLowWaterThreshold && !force
-            && mCacheOffset + mCache->totalSize() - mLastAccessPos
-                >= mLowwaterThresholdBytes) {
-        return;
-    }
-
-    size_t maxBytes = mLastAccessPos - mCacheOffset;
-
-    if (!force) {
-        if (maxBytes < kGrayArea) {
-            return;
-        }
-
-        maxBytes -= kGrayArea;
-    }
-
-    size_t actualBytes = mCache->releaseFromStart(maxBytes);
-    mCacheOffset += actualBytes;
-
-    ALOGI("restarting prefetcher, totalSize = %zu", mCache->totalSize());
-    mFetching = true;
-}
-
-ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
-    Mutex::Autolock autoSerializer(mSerializer);
-
-    ALOGV("readAt offset %lld, size %zu", (long long)offset, size);
-
-    Mutex::Autolock autoLock(mLock);
-    if (mDisconnecting) {
-        return ERROR_END_OF_STREAM;
-    }
-
-    // If the request can be completely satisfied from the cache, do so.
-
-    if (offset >= mCacheOffset
-            && offset + size <= mCacheOffset + mCache->totalSize()) {
-        size_t delta = offset - mCacheOffset;
-        mCache->copy(delta, data, size);
-
-        mLastAccessPos = offset + size;
-
-        return size;
-    }
-
-    sp<AMessage> msg = new AMessage(kWhatRead, mReflector);
-    msg->setInt64("offset", offset);
-    msg->setPointer("data", data);
-    msg->setSize("size", size);
-
-    CHECK(mAsyncResult == NULL);
-    msg->post();
-
-    while (mAsyncResult == NULL && !mDisconnecting) {
-        mCondition.wait(mLock);
-    }
-
-    if (mDisconnecting) {
-        mAsyncResult.clear();
-        return ERROR_END_OF_STREAM;
-    }
-
-    int32_t result;
-    CHECK(mAsyncResult->findInt32("result", &result));
-
-    mAsyncResult.clear();
-
-    if (result > 0) {
-        mLastAccessPos = offset + result;
-    }
-
-    return (ssize_t)result;
-}
-
-size_t NuCachedSource2::cachedSize() {
-    Mutex::Autolock autoLock(mLock);
-    return mCacheOffset + mCache->totalSize();
-}
-
-status_t NuCachedSource2::getAvailableSize(off64_t offset, off64_t *size) {
-    Mutex::Autolock autoLock(mLock);
-    status_t finalStatus = UNKNOWN_ERROR;
-    *size = approxDataRemaining_l(offset, &finalStatus);
-    return finalStatus;
-}
-
-size_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) const {
-    Mutex::Autolock autoLock(mLock);
-    return approxDataRemaining_l(mLastAccessPos, finalStatus);
-}
-
-size_t NuCachedSource2::approxDataRemaining_l(off64_t offset, status_t *finalStatus) const {
-    *finalStatus = mFinalStatus;
-
-    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
-        // Pretend that everything is fine until we're out of retries.
-        *finalStatus = OK;
-    }
-
-    offset = offset >= 0 ? offset : mLastAccessPos;
-    off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
-    if (offset < lastBytePosCached) {
-        return lastBytePosCached - offset;
-    }
-    return 0;
-}
-
-ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
-    CHECK_LE(size, (size_t)mHighwaterThresholdBytes);
-
-    ALOGV("readInternal offset %lld size %zu", (long long)offset, size);
-
-    Mutex::Autolock autoLock(mLock);
-
-    // If we're disconnecting, return EOS and don't access *data pointer.
-    // data could be on the stack of the caller to NuCachedSource2::readAt(),
-    // which may have exited already.
-    if (mDisconnecting) {
-        return ERROR_END_OF_STREAM;
-    }
-
-    if (!mFetching) {
-        mLastAccessPos = offset;
-        restartPrefetcherIfNecessary_l(
-                false, // ignoreLowWaterThreshold
-                true); // force
-    }
-
-    if (offset < mCacheOffset
-            || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
-        static const off64_t kPadding = 256 * 1024;
-
-        // In the presence of multiple decoded streams, once of them will
-        // trigger this seek request, the other one will request data "nearby"
-        // soon, adjust the seek position so that that subsequent request
-        // does not trigger another seek.
-        off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
-
-        seekInternal_l(seekOffset);
-    }
-
-    size_t delta = offset - mCacheOffset;
-
-    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
-        if (delta >= mCache->totalSize()) {
-            return mFinalStatus;
-        }
-
-        size_t avail = mCache->totalSize() - delta;
-
-        if (avail > size) {
-            avail = size;
-        }
-
-        mCache->copy(delta, data, avail);
-
-        return avail;
-    }
-
-    if (offset + size <= mCacheOffset + mCache->totalSize()) {
-        mCache->copy(delta, data, size);
-
-        return size;
-    }
-
-    ALOGV("deferring read");
-
-    return -EAGAIN;
-}
-
-status_t NuCachedSource2::seekInternal_l(off64_t offset) {
-    mLastAccessPos = offset;
-
-    if (offset >= mCacheOffset
-            && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) {
-        return OK;
-    }
-
-    ALOGI("new range: offset= %lld", (long long)offset);
-
-    mCacheOffset = offset;
-
-    size_t totalSize = mCache->totalSize();
-    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
-
-    mNumRetriesLeft = kMaxNumRetries;
-    mFetching = true;
-
-    return OK;
-}
-
-void NuCachedSource2::resumeFetchingIfNecessary() {
-    Mutex::Autolock autoLock(mLock);
-
-    restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
-}
-
-sp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) {
-    return mSource->DrmInitialization(mime);
-}
-
-String8 NuCachedSource2::getUri() {
-    return mSource->getUri();
-}
-
-String8 NuCachedSource2::getMIMEType() const {
-    return mSource->getMIMEType();
-}
-
-void NuCachedSource2::updateCacheParamsFromSystemProperty() {
-    char value[PROPERTY_VALUE_MAX];
-    if (!property_get("media.stagefright.cache-params", value, NULL)) {
-        return;
-    }
-
-    updateCacheParamsFromString(value);
-}
-
-void NuCachedSource2::updateCacheParamsFromString(const char *s) {
-    ssize_t lowwaterMarkKb, highwaterMarkKb;
-    int keepAliveSecs;
-
-    if (sscanf(s, "%zd/%zd/%d",
-               &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) {
-        ALOGE("Failed to parse cache parameters from '%s'.", s);
-        return;
-    }
-
-    if (lowwaterMarkKb >= 0) {
-        mLowwaterThresholdBytes = lowwaterMarkKb * 1024;
-    } else {
-        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
-    }
-
-    if (highwaterMarkKb >= 0) {
-        mHighwaterThresholdBytes = highwaterMarkKb * 1024;
-    } else {
-        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
-    }
-
-    if (mLowwaterThresholdBytes >= mHighwaterThresholdBytes) {
-        ALOGE("Illegal low/highwater marks specified, reverting to defaults.");
-
-        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
-        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
-    }
-
-    if (keepAliveSecs >= 0) {
-        mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
-    } else {
-        mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
-    }
-
-    ALOGV("lowwater = %zu bytes, highwater = %zu bytes, keepalive = %lld us",
-         mLowwaterThresholdBytes,
-         mHighwaterThresholdBytes,
-         (long long)mKeepAliveIntervalUs);
-}
-
-// static
-void NuCachedSource2::RemoveCacheSpecificHeaders(
-        KeyedVector<String8, String8> *headers,
-        String8 *cacheConfig,
-        bool *disconnectAtHighwatermark) {
-    *cacheConfig = String8();
-    *disconnectAtHighwatermark = false;
-
-    if (headers == NULL) {
-        return;
-    }
-
-    ssize_t index;
-    if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
-        *cacheConfig = headers->valueAt(index);
-
-        headers->removeItemsAt(index);
-
-        ALOGV("Using special cache config '%s'", cacheConfig->string());
-    }
-
-    if ((index = headers->indexOfKey(
-                    String8("x-disconnect-at-highwatermark"))) >= 0) {
-        *disconnectAtHighwatermark = true;
-        headers->removeItemsAt(index);
-
-        ALOGV("Client requested disconnection at highwater mark");
-    }
-}
-
-}  // namespace android
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 680d426..050d7c2 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -22,13 +22,13 @@
 
 #include "include/ESDS.h"
 
+#include <datasource/DataSourceFactory.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -36,6 +36,7 @@
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 namespace android {
 
@@ -81,7 +82,7 @@
     }
 
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(httpService, path, headers);
+        DataSourceFactory::getInstance()->CreateFromURI(httpService, path, headers);
 
     if (dataSource == NULL) {
         return -ENOENT;
@@ -93,11 +94,16 @@
         return ERROR_UNSUPPORTED;
     }
 
+    status_t err = OK;
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
-    status_t err = updateDurationAndBitrate();
+    err = updateDurationAndBitrate();
     if (err == OK) {
         mDataSource = dataSource;
     }
@@ -130,7 +136,11 @@
     }
 
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
     err = updateDurationAndBitrate();
@@ -160,7 +170,11 @@
     }
 
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
     err = updateDurationAndBitrate();
@@ -194,8 +208,12 @@
     mCasToken = casToken;
 
     if (mImpl != NULL) {
-        mImpl->setMediaCas(casToken);
-        status_t err = updateDurationAndBitrate();
+        status_t err = mImpl->setMediaCas(casToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
+        err = updateDurationAndBitrate();
         if (err != OK) {
             return err;
         }
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index b738fef..0bc5976 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -22,7 +22,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/mediarecorder.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 29c3a35..25e43c2 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -20,8 +20,8 @@
 
 #include <binder/IPCThreadState.h>
 #include <media/stagefright/InterfaceUtils.h>
-#include <media/MediaAnalyticsItem.h>
-#include <media/MediaSource.h>
+#include <media/MediaMetricsItem.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/RemoteMediaExtractor.h>
 
 // still doing some on/off toggling here.
@@ -48,20 +48,20 @@
      mSource(source),
      mExtractorPlugin(plugin) {
 
-    mAnalyticsItem = nullptr;
+    mMetricsItem = nullptr;
     if (MEDIA_LOG) {
-        mAnalyticsItem = MediaAnalyticsItem::create(kKeyExtractor);
+        mMetricsItem = mediametrics::Item::create(kKeyExtractor);
 
         // we're in the extractor service, we want to attribute to the app
         // that invoked us.
         int uid = IPCThreadState::self()->getCallingUid();
-        mAnalyticsItem->setUid(uid);
+        mMetricsItem->setUid(uid);
 
         // track the container format (mpeg, aac, wvm, etc)
         size_t ntracks = extractor->countTracks();
-        mAnalyticsItem->setCString(kExtractorFormat, extractor->name());
+        mMetricsItem->setCString(kExtractorFormat, extractor->name());
         // tracks (size_t)
-        mAnalyticsItem->setInt32(kExtractorTracks, ntracks);
+        mMetricsItem->setInt32(kExtractorTracks, ntracks);
         // metadata
         MetaDataBase pMetaData;
         if (extractor->getMetaData(pMetaData) == OK) {
@@ -70,7 +70,7 @@
             // 'mime'
             const char *mime = nullptr;
             if (pMetaData.findCString(kKeyMIMEType, &mime)) {
-                mAnalyticsItem->setCString(kExtractorMime,  mime);
+                mMetricsItem->setCString(kExtractorMime,  mime);
             }
             // what else is interesting and not already available?
         }
@@ -84,15 +84,15 @@
     mExtractorPlugin = nullptr;
     // log the current record, provided it has some information worth recording
     if (MEDIA_LOG) {
-        if (mAnalyticsItem != nullptr) {
-            if (mAnalyticsItem->count() > 0) {
-                mAnalyticsItem->selfrecord();
+        if (mMetricsItem != nullptr) {
+            if (mMetricsItem->count() > 0) {
+                mMetricsItem->selfrecord();
             }
         }
     }
-    if (mAnalyticsItem != nullptr) {
-        delete mAnalyticsItem;
-        mAnalyticsItem = nullptr;
+    if (mMetricsItem != nullptr) {
+        delete mMetricsItem;
+        mMetricsItem = nullptr;
     }
 }
 
@@ -123,11 +123,11 @@
 }
 
 status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
-    if (mAnalyticsItem == nullptr || reply == nullptr) {
+    if (mMetricsItem == nullptr || reply == nullptr) {
         return UNKNOWN_ERROR;
     }
 
-    mAnalyticsItem->writeToParcel(reply);
+    mMetricsItem->writeToParcel(reply);
     return OK;
 }
 
@@ -139,8 +139,8 @@
     return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
 }
 
-const char * RemoteMediaExtractor::name() {
-    return mExtractor->name();
+String8 RemoteMediaExtractor::name() {
+    return String8(mExtractor->name());
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index babdc7a..771dfea 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -20,7 +20,7 @@
 
 #include <gui/Surface.h>
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -36,7 +36,7 @@
 using namespace android;
 
 const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
-const int64_t kTimeoutWaitForInputUs = 5000; // 5 milliseconds
+const int64_t kTimeoutWaitForInputUs = 0; // don't wait
 const int kTimeoutMaxRetries = 20;
 
 //static
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index cf4edae..6fd0805 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -35,7 +35,7 @@
 
 StagefrightMediaScanner::~StagefrightMediaScanner() {}
 
-static std::unordered_set<std::string> gSupportedExtensions;
+static std::vector<std::string> gSupportedExtensions;
 
 static bool FileHasAcceptableExtension(const char *extension) {
 
@@ -44,7 +44,12 @@
         gSupportedExtensions = MediaExtractorFactory::getSupportedTypes();
     }
 
-    return  gSupportedExtensions.count(std::string(extension + 1)) != 0;
+    for (auto ext: gSupportedExtensions) {
+        if (ext == (extension + 1)) {
+            return true;
+        }
+    }
+    return false;
 }
 
 MediaScanResult StagefrightMediaScanner::processFile(
@@ -158,7 +163,11 @@
     if (mRetriever->setDataSource(fd, 0, size) == OK) {
         sp<IMemory> mem = mRetriever->extractAlbumArt();
         if (mem != NULL) {
-            MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->pointer());
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
+            MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->unsecurePointer());
             return art->clone();
         }
     }
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
deleted file mode 100644
index fa3d372..0000000
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (C) 2009 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 "StagefrightMetadataRetriever"
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-#include "include/FrameDecoder.h"
-#include "include/StagefrightMetadataRetriever.h"
-
-#include <media/IMediaHTTPService.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/MediaCodecList.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaExtractor.h>
-#include <media/stagefright/MediaExtractorFactory.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-#include <media/CharacterEncodingDetector.h>
-
-namespace android {
-
-StagefrightMetadataRetriever::StagefrightMetadataRetriever()
-    : mParsedMetaData(false),
-      mAlbumArt(NULL),
-      mLastImageIndex(-1) {
-    ALOGV("StagefrightMetadataRetriever()");
-}
-
-StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
-    ALOGV("~StagefrightMetadataRetriever()");
-    clearMetadata();
-    if (mSource != NULL) {
-        mSource->close();
-    }
-}
-
-status_t StagefrightMetadataRetriever::setDataSource(
-        const sp<IMediaHTTPService> &httpService,
-        const char *uri,
-        const KeyedVector<String8, String8> *headers) {
-    ALOGV("setDataSource(%s)", uri);
-
-    clearMetadata();
-    mSource = DataSourceFactory::CreateFromURI(httpService, uri, headers);
-
-    if (mSource == NULL) {
-        ALOGE("Unable to create data source for '%s'.", uri);
-        return UNKNOWN_ERROR;
-    }
-
-    mExtractor = MediaExtractorFactory::Create(mSource);
-
-    if (mExtractor == NULL) {
-        ALOGE("Unable to instantiate an extractor for '%s'.", uri);
-
-        mSource.clear();
-
-        return UNKNOWN_ERROR;
-    }
-
-    return OK;
-}
-
-// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
-status_t StagefrightMetadataRetriever::setDataSource(
-        int fd, int64_t offset, int64_t length) {
-    fd = dup(fd);
-
-    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
-
-    clearMetadata();
-    mSource = new FileSource(fd, offset, length);
-
-    status_t err;
-    if ((err = mSource->initCheck()) != OK) {
-        mSource.clear();
-
-        return err;
-    }
-
-    mExtractor = MediaExtractorFactory::Create(mSource);
-
-    if (mExtractor == NULL) {
-        mSource.clear();
-
-        return UNKNOWN_ERROR;
-    }
-
-    return OK;
-}
-
-status_t StagefrightMetadataRetriever::setDataSource(
-        const sp<DataSource>& source, const char *mime) {
-    ALOGV("setDataSource(DataSource)");
-
-    clearMetadata();
-    mSource = source;
-    mExtractor = MediaExtractorFactory::Create(mSource, mime);
-
-    if (mExtractor == NULL) {
-        ALOGE("Failed to instantiate a MediaExtractor.");
-        mSource.clear();
-        return UNKNOWN_ERROR;
-    }
-
-    return OK;
-}
-
-sp<IMemory> StagefrightMetadataRetriever::getImageAtIndex(
-        int index, int colorFormat, bool metaOnly, bool thumbnail) {
-    ALOGV("getImageAtIndex: index(%d) colorFormat(%d) metaOnly(%d) thumbnail(%d)",
-            index, colorFormat, metaOnly, thumbnail);
-
-    return getImageInternal(index, colorFormat, metaOnly, thumbnail, NULL);
-}
-
-sp<IMemory> StagefrightMetadataRetriever::getImageRectAtIndex(
-        int index, int colorFormat, int left, int top, int right, int bottom) {
-    ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d) rect {%d, %d, %d, %d}",
-            index, colorFormat, left, top, right, bottom);
-
-    FrameRect rect = {left, top, right, bottom};
-
-    if (mImageDecoder != NULL && index == mLastImageIndex) {
-        return mImageDecoder->extractFrame(&rect);
-    }
-
-    return getImageInternal(
-            index, colorFormat, false /*metaOnly*/, false /*thumbnail*/, &rect);
-}
-
-sp<IMemory> StagefrightMetadataRetriever::getImageInternal(
-        int index, int colorFormat, bool metaOnly, bool thumbnail, FrameRect* rect) {
-
-    if (mExtractor.get() == NULL) {
-        ALOGE("no extractor.");
-        return NULL;
-    }
-
-    size_t n = mExtractor->countTracks();
-    size_t i;
-    int imageCount = 0;
-
-    for (i = 0; i < n; ++i) {
-        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
-        if (!meta) {
-            continue;
-        }
-        ALOGV("getting track %zu of %zu, meta=%s", i, n, meta->toString().c_str());
-
-        const char *mime;
-        CHECK(meta->findCString(kKeyMIMEType, &mime));
-
-        if (!strncasecmp(mime, "image/", 6)) {
-            int32_t isPrimary;
-            if ((index < 0 && meta->findInt32(
-                    kKeyTrackIsDefault, &isPrimary) && isPrimary)
-                    || (index == imageCount++)) {
-                break;
-            }
-        }
-    }
-
-    if (i == n) {
-        ALOGE("image track not found.");
-        return NULL;
-    }
-
-    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
-    if (!trackMeta) {
-        return NULL;
-    }
-
-    if (metaOnly) {
-        return FrameDecoder::getMetadataOnly(trackMeta, colorFormat, thumbnail);
-    }
-
-    sp<IMediaSource> source = mExtractor->getTrack(i);
-
-    if (source.get() == NULL) {
-        ALOGE("unable to instantiate image track.");
-        return NULL;
-    }
-
-    const char *mime;
-    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
-    ALOGV("extracting from %s track", mime);
-    if (!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
-        mime = MEDIA_MIMETYPE_VIDEO_HEVC;
-        trackMeta = new MetaData(*trackMeta);
-        trackMeta->setCString(kKeyMIMEType, mime);
-    }
-
-    bool preferhw = property_get_bool(
-            "media.stagefright.thumbnail.prefer_hw_codecs", false);
-    uint32_t flags = preferhw ? 0 : MediaCodecList::kPreferSoftwareCodecs;
-    Vector<AString> matchingCodecs;
-    MediaCodecList::findMatchingCodecs(
-            mime,
-            false, /* encoder */
-            flags,
-            &matchingCodecs);
-
-    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
-        const AString &componentName = matchingCodecs[i];
-        sp<ImageDecoder> decoder = new ImageDecoder(componentName, trackMeta, source);
-        int64_t frameTimeUs = thumbnail ? -1 : 0;
-        if (decoder->init(frameTimeUs, 1 /*numFrames*/, 0 /*option*/, colorFormat) == OK) {
-            sp<IMemory> frame = decoder->extractFrame(rect);
-
-            if (frame != NULL) {
-                if (rect != NULL) {
-                    // keep the decoder if slice decoding
-                    mImageDecoder = decoder;
-                    mLastImageIndex = index;
-                }
-                return frame;
-            }
-        }
-        ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str());
-    }
-
-    return NULL;
-}
-
-sp<IMemory> StagefrightMetadataRetriever::getFrameAtTime(
-        int64_t timeUs, int option, int colorFormat, bool metaOnly) {
-    ALOGV("getFrameAtTime: %" PRId64 " us option: %d colorFormat: %d, metaOnly: %d",
-            timeUs, option, colorFormat, metaOnly);
-
-    sp<IMemory> frame;
-    status_t err = getFrameInternal(
-            timeUs, 1, option, colorFormat, metaOnly, &frame, NULL /*outFrames*/);
-    return (err == OK) ? frame : NULL;
-}
-
-status_t StagefrightMetadataRetriever::getFrameAtIndex(
-        std::vector<sp<IMemory> >* frames,
-        int frameIndex, int numFrames, int colorFormat, bool metaOnly) {
-    ALOGV("getFrameAtIndex: frameIndex %d, numFrames %d, colorFormat: %d, metaOnly: %d",
-            frameIndex, numFrames, colorFormat, metaOnly);
-
-    return getFrameInternal(
-            frameIndex, numFrames, MediaSource::ReadOptions::SEEK_FRAME_INDEX,
-            colorFormat, metaOnly, NULL /*outFrame*/, frames);
-}
-
-status_t StagefrightMetadataRetriever::getFrameInternal(
-        int64_t timeUs, int numFrames, int option, int colorFormat, bool metaOnly,
-        sp<IMemory>* outFrame, std::vector<sp<IMemory> >* outFrames) {
-    if (mExtractor.get() == NULL) {
-        ALOGE("no extractor.");
-        return NO_INIT;
-    }
-
-    sp<MetaData> fileMeta = mExtractor->getMetaData();
-
-    if (fileMeta == NULL) {
-        ALOGE("extractor doesn't publish metadata, failed to initialize?");
-        return NO_INIT;
-    }
-
-    size_t n = mExtractor->countTracks();
-    size_t i;
-    for (i = 0; i < n; ++i) {
-        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
-        if (!meta) {
-            continue;
-        }
-
-        const char *mime;
-        CHECK(meta->findCString(kKeyMIMEType, &mime));
-
-        if (!strncasecmp(mime, "video/", 6)) {
-            break;
-        }
-    }
-
-    if (i == n) {
-        ALOGE("no video track found.");
-        return INVALID_OPERATION;
-    }
-
-    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
-            i, MediaExtractor::kIncludeExtensiveMetaData);
-    if (!trackMeta) {
-        return UNKNOWN_ERROR;
-    }
-
-    if (metaOnly) {
-        if (outFrame != NULL) {
-            *outFrame = FrameDecoder::getMetadataOnly(trackMeta, colorFormat);
-            if (*outFrame != NULL) {
-                return OK;
-            }
-        }
-        return UNKNOWN_ERROR;
-    }
-
-    sp<IMediaSource> source = mExtractor->getTrack(i);
-
-    if (source.get() == NULL) {
-        ALOGV("unable to instantiate video track.");
-        return UNKNOWN_ERROR;
-    }
-
-    const void *data;
-    uint32_t type;
-    size_t dataSize;
-    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
-            && mAlbumArt == NULL) {
-        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
-    }
-
-    const char *mime;
-    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
-
-    bool preferhw = property_get_bool(
-            "media.stagefright.thumbnail.prefer_hw_codecs", false);
-    uint32_t flags = preferhw ? 0 : MediaCodecList::kPreferSoftwareCodecs;
-    Vector<AString> matchingCodecs;
-    MediaCodecList::findMatchingCodecs(
-            mime,
-            false, /* encoder */
-            flags,
-            &matchingCodecs);
-
-    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
-        const AString &componentName = matchingCodecs[i];
-        sp<VideoFrameDecoder> decoder = new VideoFrameDecoder(componentName, trackMeta, source);
-        if (decoder->init(timeUs, numFrames, option, colorFormat) == OK) {
-            if (outFrame != NULL) {
-                *outFrame = decoder->extractFrame();
-                if (*outFrame != NULL) {
-                    return OK;
-                }
-            } else if (outFrames != NULL) {
-                status_t err = decoder->extractFrames(outFrames);
-                if (err == OK) {
-                    return OK;
-                }
-            }
-        }
-        ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str());
-    }
-
-    ALOGE("all codecs failed to extract frame.");
-    return UNKNOWN_ERROR;
-}
-
-MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
-    ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
-
-    if (mExtractor == NULL) {
-        return NULL;
-    }
-
-    if (!mParsedMetaData) {
-        parseMetaData();
-
-        mParsedMetaData = true;
-    }
-
-    if (mAlbumArt) {
-        return mAlbumArt->clone();
-    }
-
-    return NULL;
-}
-
-const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
-    if (mExtractor == NULL) {
-        return NULL;
-    }
-
-    if (!mParsedMetaData) {
-        parseMetaData();
-
-        mParsedMetaData = true;
-    }
-
-    ssize_t index = mMetaData.indexOfKey(keyCode);
-
-    if (index < 0) {
-        return NULL;
-    }
-
-    return mMetaData.valueAt(index).string();
-}
-
-void StagefrightMetadataRetriever::parseColorAspects(const sp<MetaData>& meta) {
-    sp<AMessage> format = new AMessage();
-    if (convertMetaDataToMessage(meta, &format) != OK) {
-        return;
-    }
-
-    int32_t standard, transfer, range;
-    if (format->findInt32("color-standard", &standard)
-            && format->findInt32("color-transfer", &transfer)
-            && format->findInt32("color-range", &range)) {
-        ALOGV("found color aspects : standard=%d, transfer=%d, range=%d",
-                standard, transfer, range);
-
-        mMetaData.add(METADATA_KEY_COLOR_STANDARD, String8::format("%d", standard));
-        mMetaData.add(METADATA_KEY_COLOR_TRANSFER, String8::format("%d", transfer));
-        mMetaData.add(METADATA_KEY_COLOR_RANGE, String8::format("%d", range));
-    }
-}
-
-void StagefrightMetadataRetriever::parseMetaData() {
-    sp<MetaData> meta = mExtractor->getMetaData();
-
-    if (meta == NULL) {
-        ALOGV("extractor doesn't publish metadata, failed to initialize?");
-        return;
-    }
-
-    struct Map {
-        int from;
-        int to;
-        const char *name;
-    };
-    static const Map kMap[] = {
-        { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL },
-        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" },
-        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" },
-        { kKeyAlbum, METADATA_KEY_ALBUM, "album" },
-        { kKeyArtist, METADATA_KEY_ARTIST, "artist" },
-        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" },
-        { kKeyAuthor, METADATA_KEY_AUTHOR, NULL },
-        { kKeyComposer, METADATA_KEY_COMPOSER, "composer" },
-        { kKeyDate, METADATA_KEY_DATE, NULL },
-        { kKeyGenre, METADATA_KEY_GENRE, "genre" },
-        { kKeyTitle, METADATA_KEY_TITLE, "title" },
-        { kKeyYear, METADATA_KEY_YEAR, "year" },
-        { kKeyWriter, METADATA_KEY_WRITER, "writer" },
-        { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" },
-        { kKeyLocation, METADATA_KEY_LOCATION, NULL },
-    };
-
-    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
-
-    CharacterEncodingDetector *detector = new CharacterEncodingDetector();
-
-    for (size_t i = 0; i < kNumMapEntries; ++i) {
-        const char *value;
-        if (meta->findCString(kMap[i].from, &value)) {
-            if (kMap[i].name) {
-                // add to charset detector
-                detector->addTag(kMap[i].name, value);
-            } else {
-                // directly add to output list
-                mMetaData.add(kMap[i].to, String8(value));
-            }
-        }
-    }
-
-    detector->detectAndConvert();
-    int size = detector->size();
-    if (size) {
-        for (int i = 0; i < size; i++) {
-            const char *name;
-            const char *value;
-            detector->getTag(i, &name, &value);
-            for (size_t j = 0; j < kNumMapEntries; ++j) {
-                if (kMap[j].name && !strcmp(kMap[j].name, name)) {
-                    mMetaData.add(kMap[j].to, String8(value));
-                }
-            }
-        }
-    }
-    delete detector;
-
-    const void *data;
-    uint32_t type;
-    size_t dataSize;
-    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
-            && mAlbumArt == NULL) {
-        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
-    }
-
-    size_t numTracks = mExtractor->countTracks();
-
-    char tmp[32];
-    sprintf(tmp, "%zu", numTracks);
-
-    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
-
-    float captureFps;
-    if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) {
-        sprintf(tmp, "%f", captureFps);
-        mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp));
-    }
-
-    int64_t exifOffset, exifSize;
-    if (meta->findInt64(kKeyExifOffset, &exifOffset)
-     && meta->findInt64(kKeyExifSize, &exifSize)) {
-        sprintf(tmp, "%lld", (long long)exifOffset);
-        mMetaData.add(METADATA_KEY_EXIF_OFFSET, String8(tmp));
-        sprintf(tmp, "%lld", (long long)exifSize);
-        mMetaData.add(METADATA_KEY_EXIF_LENGTH, String8(tmp));
-    }
-
-    bool hasAudio = false;
-    bool hasVideo = false;
-    int32_t videoWidth = -1;
-    int32_t videoHeight = -1;
-    int32_t videoFrameCount = 0;
-    int32_t audioBitrate = -1;
-    int32_t rotationAngle = -1;
-    int32_t imageCount = 0;
-    int32_t imagePrimary = 0;
-    int32_t imageWidth = -1;
-    int32_t imageHeight = -1;
-    int32_t imageRotation = -1;
-
-    // The overall duration is the duration of the longest track.
-    int64_t maxDurationUs = 0;
-    String8 timedTextLang;
-    for (size_t i = 0; i < numTracks; ++i) {
-        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
-        if (!trackMeta) {
-            continue;
-        }
-
-        int64_t durationUs;
-        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
-            if (durationUs > maxDurationUs) {
-                maxDurationUs = durationUs;
-            }
-        }
-
-        const char *mime;
-        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
-            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
-                hasAudio = true;
-
-                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
-                    audioBitrate = -1;
-                }
-
-                int32_t bitsPerSample = -1;
-                int32_t sampleRate = -1;
-                trackMeta->findInt32(kKeyBitsPerSample, &bitsPerSample);
-                trackMeta->findInt32(kKeySampleRate, &sampleRate);
-                if (bitsPerSample >= 0) {
-                    sprintf(tmp, "%d", bitsPerSample);
-                    mMetaData.add(METADATA_KEY_BITS_PER_SAMPLE, String8(tmp));
-                }
-                if (sampleRate >= 0) {
-                    sprintf(tmp, "%d", sampleRate);
-                    mMetaData.add(METADATA_KEY_SAMPLERATE, String8(tmp));
-                }
-            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
-                hasVideo = true;
-
-                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
-                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
-                if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
-                    rotationAngle = 0;
-                }
-                if (!trackMeta->findInt32(kKeyFrameCount, &videoFrameCount)) {
-                    videoFrameCount = 0;
-                }
-
-                parseColorAspects(trackMeta);
-            } else if (!strncasecmp("image/", mime, 6)) {
-                int32_t isPrimary;
-                if (trackMeta->findInt32(
-                        kKeyTrackIsDefault, &isPrimary) && isPrimary) {
-                    imagePrimary = imageCount;
-                    CHECK(trackMeta->findInt32(kKeyWidth, &imageWidth));
-                    CHECK(trackMeta->findInt32(kKeyHeight, &imageHeight));
-                    if (!trackMeta->findInt32(kKeyRotation, &imageRotation)) {
-                        imageRotation = 0;
-                    }
-                }
-                imageCount++;
-            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
-                const char *lang;
-                if (trackMeta->findCString(kKeyMediaLanguage, &lang)) {
-                    timedTextLang.append(String8(lang));
-                    timedTextLang.append(String8(":"));
-                } else {
-                    ALOGE("No language found for timed text");
-                }
-            }
-        }
-    }
-
-    // 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()) {
-        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
-    }
-
-    // The duration value is a string representing the duration in ms.
-    sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000);
-    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
-
-    if (hasAudio) {
-        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
-    }
-
-    if (hasVideo) {
-        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
-
-        sprintf(tmp, "%d", videoWidth);
-        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
-
-        sprintf(tmp, "%d", videoHeight);
-        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
-
-        sprintf(tmp, "%d", rotationAngle);
-        mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp));
-
-        if (videoFrameCount > 0) {
-            sprintf(tmp, "%d", videoFrameCount);
-            mMetaData.add(METADATA_KEY_VIDEO_FRAME_COUNT, String8(tmp));
-        }
-    }
-
-    if (imageCount > 0) {
-        mMetaData.add(METADATA_KEY_HAS_IMAGE, String8("yes"));
-
-        sprintf(tmp, "%d", imageCount);
-        mMetaData.add(METADATA_KEY_IMAGE_COUNT, String8(tmp));
-
-        sprintf(tmp, "%d", imagePrimary);
-        mMetaData.add(METADATA_KEY_IMAGE_PRIMARY, String8(tmp));
-
-        sprintf(tmp, "%d", imageWidth);
-        mMetaData.add(METADATA_KEY_IMAGE_WIDTH, String8(tmp));
-
-        sprintf(tmp, "%d", imageHeight);
-        mMetaData.add(METADATA_KEY_IMAGE_HEIGHT, String8(tmp));
-
-        sprintf(tmp, "%d", imageRotation);
-        mMetaData.add(METADATA_KEY_IMAGE_ROTATION, String8(tmp));
-    }
-
-    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
-        sprintf(tmp, "%d", audioBitrate);
-        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
-    } else {
-        off64_t sourceSize;
-        if (mSource != NULL && mSource->getSize(&sourceSize) == OK) {
-            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
-
-            sprintf(tmp, "%" PRId64, avgBitRate);
-            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
-        }
-    }
-
-    if (numTracks == 1) {
-        const char *fileMIME;
-
-        if (meta->findCString(kKeyMIMEType, &fileMIME) &&
-                !strcasecmp(fileMIME, "video/x-matroska")) {
-            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
-            const char *trackMIME;
-            if (trackMeta != nullptr) {
-                CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
-            }
-            if (!strncasecmp("audio/", trackMIME, 6)) {
-                // The matroska file only contains a single audio track,
-                // rewrite its mime type.
-                mMetaData.add(
-                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
-            }
-        }
-    }
-}
-
-void StagefrightMetadataRetriever::clearMetadata() {
-    mParsedMetaData = false;
-    mMetaData.clear();
-    delete mAlbumArt;
-    mAlbumArt = NULL;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.cpp b/media/libstagefright/StagefrightPluginLoader.cpp
deleted file mode 100644
index fb03c5e..0000000
--- a/media/libstagefright/StagefrightPluginLoader.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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 "StagefrightPluginLoader"
-#include <utils/Log.h>
-
-#include <android-base/properties.h>
-#include <dlfcn.h>
-
-#include "StagefrightPluginLoader.h"
-
-namespace android {
-
-/* static */ Mutex StagefrightPluginLoader::sMutex;
-/* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
-
-namespace /* unnamed */ {
-
-constexpr const char kCCodecPluginPath[] = "libsfplugin_ccodec.so";
-
-}  // unnamed namespace
-
-StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath) {
-    if (android::base::GetIntProperty("debug.stagefright.ccodec", 1) == 0) {
-        ALOGD("CCodec is disabled.");
-        return;
-    }
-    mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
-    if (mLibHandle == nullptr) {
-        ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
-        return;
-    }
-    mCreateCodec = (CodecBase::CreateCodecFunc)dlsym(mLibHandle, "CreateCodec");
-    if (mCreateCodec == nullptr) {
-        ALOGD("Failed to find symbol: CreateCodec (%s)", dlerror());
-    }
-    mCreateBuilder = (MediaCodecListBuilderBase::CreateBuilderFunc)dlsym(
-            mLibHandle, "CreateBuilder");
-    if (mCreateBuilder == nullptr) {
-        ALOGD("Failed to find symbol: CreateBuilder (%s)", dlerror());
-    }
-    mCreateInputSurface = (CodecBase::CreateInputSurfaceFunc)dlsym(
-            mLibHandle, "CreateInputSurface");
-    if (mCreateInputSurface == nullptr) {
-        ALOGD("Failed to find symbol: CreateInputSurface (%s)", dlerror());
-    }
-}
-
-StagefrightPluginLoader::~StagefrightPluginLoader() {
-    if (mLibHandle != nullptr) {
-        ALOGV("Closing handle");
-        dlclose(mLibHandle);
-    }
-}
-
-CodecBase *StagefrightPluginLoader::createCodec() {
-    if (mLibHandle == nullptr || mCreateCodec == nullptr) {
-        ALOGD("Handle or CreateCodec symbol is null");
-        return nullptr;
-    }
-    return mCreateCodec();
-}
-
-MediaCodecListBuilderBase *StagefrightPluginLoader::createBuilder() {
-    if (mLibHandle == nullptr || mCreateBuilder == nullptr) {
-        ALOGD("Handle or CreateBuilder symbol is null");
-        return nullptr;
-    }
-    return mCreateBuilder();
-}
-
-PersistentSurface *StagefrightPluginLoader::createInputSurface() {
-    if (mLibHandle == nullptr || mCreateInputSurface == nullptr) {
-        ALOGD("Handle or CreateInputSurface symbol is null");
-        return nullptr;
-    }
-    return mCreateInputSurface();
-}
-
-//static
-const std::unique_ptr<StagefrightPluginLoader> &StagefrightPluginLoader::GetCCodecInstance() {
-    Mutex::Autolock _l(sMutex);
-    if (!sInstance) {
-        ALOGV("Loading library");
-        sInstance.reset(new StagefrightPluginLoader(kCCodecPluginPath));
-    }
-    return sInstance;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.h b/media/libstagefright/StagefrightPluginLoader.h
deleted file mode 100644
index 78effbf..0000000
--- a/media/libstagefright/StagefrightPluginLoader.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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 STAGEFRIGHT_PLUGIN_LOADER_H_
-
-#define STAGEFRIGHT_PLUGIN_LOADER_H_
-
-#include <media/stagefright/CodecBase.h>
-#include <media/stagefright/MediaCodecListWriter.h>
-#include <media/stagefright/PersistentSurface.h>
-#include <utils/Mutex.h>
-
-namespace android {
-
-class StagefrightPluginLoader {
-public:
-    static const std::unique_ptr<StagefrightPluginLoader> &GetCCodecInstance();
-    ~StagefrightPluginLoader();
-
-    CodecBase *createCodec();
-    MediaCodecListBuilderBase *createBuilder();
-    PersistentSurface *createInputSurface();
-
-private:
-    explicit StagefrightPluginLoader(const char *libPath);
-
-    static Mutex sMutex;
-    static std::unique_ptr<StagefrightPluginLoader> sInstance;
-
-    void *mLibHandle{nullptr};
-    CodecBase::CreateCodecFunc mCreateCodec{nullptr};
-    MediaCodecListBuilderBase::CreateBuilderFunc mCreateBuilder{nullptr};
-    CodecBase::CreateInputSurfaceFunc mCreateInputSurface{nullptr};
-};
-
-}  // namespace android
-
-#endif  // STAGEFRIGHT_PLUGIN_LOADER_H_
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index c1b270c..8b36ea5 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -1,13 +1,25 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "CtsMediaTestCases",
       "options": [
         {
-          "include-annotation": "android.platform.test.annotations.RequiresDevice"
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+        },
+        // TODO: b/149314419
+        {
+          "exclude-filter": "android.media.cts.AudioPlaybackCaptureTest"
+        },
+        {
+          "exclude-filter": "android.media.cts.AudioRecordTest"
         }
       ]
-    },
+    }
+  ],
+  "postsubmit": [
     {
        "name": "BatteryChecker_test"
     }
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 135151f..a1e4d43 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -227,6 +227,68 @@
     }
 }
 
+static void parseDolbyVisionProfileLevelFromDvcc(const uint8_t *ptr, size_t size, sp<AMessage> &format) {
+    // dv_major.dv_minor Should be 1.0 or 2.1
+    if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+        ALOGV("Size %zu, dv_major %d, dv_minor %d", size, ptr[0], ptr[1]);
+        return;
+    }
+
+    const uint8_t profile = ptr[2] >> 1;
+    const uint8_t level = ((ptr[2] & 0x1) << 5) | ((ptr[3] >> 3) & 0x1f);
+    const uint8_t rpu_present_flag = (ptr[3] >> 2) & 0x01;
+    const uint8_t el_present_flag = (ptr[3] >> 1) & 0x01;
+    const uint8_t bl_present_flag = (ptr[3] & 0x01);
+    const int32_t bl_compatibility_id = (int32_t)(ptr[4] >> 4);
+
+    ALOGV("profile-level-compatibility value in dv(c|v)c box %d-%d-%d",
+          profile, level, bl_compatibility_id);
+
+    // All Dolby Profiles will have profile and level info in MediaFormat
+    // Profile 8 and 9 will have bl_compatibility_id too.
+    const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONPROFILETYPE> profiles{
+        {1, OMX_VIDEO_DolbyVisionProfileDvavPen},
+        {3, OMX_VIDEO_DolbyVisionProfileDvheDen},
+        {4, OMX_VIDEO_DolbyVisionProfileDvheDtr},
+        {5, OMX_VIDEO_DolbyVisionProfileDvheStn},
+        {6, OMX_VIDEO_DolbyVisionProfileDvheDth},
+        {7, OMX_VIDEO_DolbyVisionProfileDvheDtb},
+        {8, OMX_VIDEO_DolbyVisionProfileDvheSt},
+        {9, OMX_VIDEO_DolbyVisionProfileDvavSe},
+        {10, OMX_VIDEO_DolbyVisionProfileDvav110},
+    };
+
+    const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONLEVELTYPE> levels{
+        {0, OMX_VIDEO_DolbyVisionLevelUnknown},
+        {1, OMX_VIDEO_DolbyVisionLevelHd24},
+        {2, OMX_VIDEO_DolbyVisionLevelHd30},
+        {3, OMX_VIDEO_DolbyVisionLevelFhd24},
+        {4, OMX_VIDEO_DolbyVisionLevelFhd30},
+        {5, OMX_VIDEO_DolbyVisionLevelFhd60},
+        {6, OMX_VIDEO_DolbyVisionLevelUhd24},
+        {7, OMX_VIDEO_DolbyVisionLevelUhd30},
+        {8, OMX_VIDEO_DolbyVisionLevelUhd48},
+        {9, OMX_VIDEO_DolbyVisionLevelUhd60},
+    };
+    // set rpuAssoc
+    if (rpu_present_flag && el_present_flag && !bl_present_flag) {
+        format->setInt32("rpuAssoc", 1);
+    }
+    // set profile & level if they are recognized
+    OMX_VIDEO_DOLBYVISIONPROFILETYPE codecProfile;
+    OMX_VIDEO_DOLBYVISIONLEVELTYPE codecLevel;
+    if (profiles.map(profile, &codecProfile)) {
+        format->setInt32("profile", codecProfile);
+        if (codecProfile == OMX_VIDEO_DolbyVisionProfileDvheSt ||
+            codecProfile == OMX_VIDEO_DolbyVisionProfileDvavSe) {
+            format->setInt32("bl_compatibility_id", bl_compatibility_id);
+        }
+        if (levels.map(level, &codecLevel)) {
+            format->setInt32("level", codecLevel);
+        }
+    }
+}
+
 static void parseH263ProfileLevelFromD263(const uint8_t *ptr, size_t size, sp<AMessage> &format) {
     if (size < 7) {
         return;
@@ -689,6 +751,7 @@
         { "temporal-layer-id", kKeyTemporalLayerId },
         { "thumbnail-width", kKeyThumbnailWidth },
         { "thumbnail-height", kKeyThumbnailHeight },
+        { "track-id", kKeyTrackID },
         { "valid-samples", kKeyValidSamples },
     }
 };
@@ -896,12 +959,6 @@
         msg->setInt32("is-sync-frame", 1);
     }
 
-    // this only needs to be translated from meta to message as it is an extractor key
-    int32_t trackID;
-    if (meta->findInt32(kKeyTrackID, &trackID)) {
-        msg->setInt32("track-id", trackID);
-    }
-
     const char *lang;
     if (meta->findCString(kKeyMediaLanguage, &lang)) {
         msg->setString("language", lang);
@@ -1411,6 +1468,12 @@
         msg->setBuffer("csd-0", buffer);
     }
 
+    if (meta->findData(kKeyDVCC, &type, &data, &size)) {
+        const uint8_t *ptr = (const uint8_t *)data;
+        ALOGV("DV: calling parseDolbyVisionProfileLevelFromDvcc with data size %zu", size);
+        parseDolbyVisionProfileLevelFromDvcc(ptr, size, msg);
+    }
+
     *format = msg;
 
     return OK;
@@ -1806,7 +1869,7 @@
     if (msg->findInt32("frame-rate", &fps) && fps > 0) {
         meta->setInt32(kKeyFrameRate, fps);
     } else if (msg->findFloat("frame-rate", &fpsFloat)
-            && fpsFloat >= 1 && fpsFloat <= INT32_MAX) {
+            && fpsFloat >= 1 && fpsFloat <= (float)INT32_MAX) {
         // truncate values to distinguish between e.g. 24 vs 23.976 fps
         meta->setInt32(kKeyFrameRate, (int32_t)fpsFloat);
     }
@@ -1839,6 +1902,31 @@
             meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
         } else if (mime == MEDIA_MIMETYPE_VIDEO_AV1) {
             meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
+        } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION) {
+            if (msg->findBuffer("csd-2", &csd2)) {
+                //dvcc should be 24
+                if (csd2->size() == 24) {
+                    meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
+                    uint8_t *dvcc = csd2->data();
+                    const uint8_t profile = dvcc[2] >> 1;
+                    if (profile > 1 && profile < 9) {
+                        std::vector<uint8_t> hvcc(csd0size + 1024);
+                        size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
+                        meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
+                    } else if (DolbyVisionProfileDvav110 == profile) {
+                        meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
+                    } else {
+                        sp<ABuffer> csd1;
+                        if (msg->findBuffer("csd-1", &csd1)) {
+                            std::vector<char> avcc(csd0size + csd1->size() + 1024);
+                            size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
+                            meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+                        }
+                    }
+                }
+            } else {
+                ALOGW("We need csd-2!!. %s", msg->debugString().c_str());
+            }
         } else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
             meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
         } else if (mime == MEDIA_MIMETYPE_AUDIO_OPUS) {
@@ -1885,8 +1973,18 @@
         meta->setData(kKeyStreamHeader, 'mdat', csd0->data(), csd0->size());
     } else if (msg->findBuffer("d263", &csd0)) {
         meta->setData(kKeyD263, kTypeD263, csd0->data(), csd0->size());
-    }
+    } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION && msg->findBuffer("csd-2", &csd2)) {
+        meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
 
+        // Remove CSD-2 from the data here to avoid duplicate data in meta
+        meta->remove(kKeyOpaqueCSD2);
+
+        if (msg->findBuffer("csd-avc", &csd0)) {
+            meta->setData(kKeyAVCC, kTypeAVCC, csd0->data(), csd0->size());
+        } else if (msg->findBuffer("csd-hevc", &csd0)) {
+            meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
+        }
+    }
     // XXX TODO add whatever other keys there are
 
 #if 0
@@ -1895,22 +1993,6 @@
 #endif
 }
 
-AString MakeUserAgent() {
-    AString ua;
-    ua.append("stagefright/1.2 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.build.version.release", value, "Unknown");
-    ua.append(value);
-    ua.append(")");
-
-    return ua;
-}
-
 status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink,
                            const sp<MetaData>& meta)
 {
@@ -2099,39 +2181,6 @@
     return AudioSystem::isOffloadSupported(info);
 }
 
-AString uriDebugString(const AString &uri, bool incognito) {
-    if (incognito) {
-        return AString("<URI suppressed>");
-    }
-
-    if (property_get_bool("media.stagefright.log-uri", false)) {
-        return uri;
-    }
-
-    // find scheme
-    AString scheme;
-    const char *chars = uri.c_str();
-    for (size_t i = 0; i < uri.size(); i++) {
-        const char c = chars[i];
-        if (!isascii(c)) {
-            break;
-        } else if (isalpha(c)) {
-            continue;
-        } else if (i == 0) {
-            // first character must be a letter
-            break;
-        } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
-            continue;
-        } else if (c != ':') {
-            break;
-        }
-        scheme = AString(uri, 0, i);
-        scheme.append("://<suppressed>");
-        return scheme;
-    }
-    return AString("<no-scheme URI suppressed>");
-}
-
 HLSTime::HLSTime(const sp<AMessage>& meta) :
     mSeq(-1),
     mTimeUs(-1LL),
@@ -2230,36 +2279,4 @@
     }
 }
 
-AString nameForFd(int fd) {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    AString result;
-    snprintf(buffer, SIZE, "/proc/%d/fd/%d", getpid(), fd);
-    struct stat s;
-    if (lstat(buffer, &s) == 0) {
-        if ((s.st_mode & S_IFMT) == S_IFLNK) {
-            char linkto[256];
-            int len = readlink(buffer, linkto, sizeof(linkto));
-            if(len > 0) {
-                if(len > 255) {
-                    linkto[252] = '.';
-                    linkto[253] = '.';
-                    linkto[254] = '.';
-                    linkto[255] = 0;
-                } else {
-                    linkto[len] = 0;
-                }
-                result.append(linkto);
-            }
-        } else {
-            result.append("unexpected type for ");
-            result.append(buffer);
-        }
-    } else {
-        result.append("couldn't open ");
-        result.append(buffer);
-    }
-    return result;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
deleted file mode 100644
index 23671f2..0000000
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 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 "VideoFrameScheduler2"
-#include <utils/Log.h>
-#define ATRACE_TAG ATRACE_TAG_VIDEO
-#include <utils/Mutex.h>
-#include <utils/Thread.h>
-#include <utils/Trace.h>
-
-#include <algorithm>
-#include <jni.h>
-#include <math.h>
-
-#include <android/choreographer.h>
-#include <android/looper.h>
-#include <media/stagefright/VideoFrameScheduler2.h>
-#include <mediaplayer2/JavaVMHelper.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AUtils.h>
-
-namespace android {
-
-static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
-
-/* ======================================================================= */
-/*                               VsyncTracker                              */
-/* ======================================================================= */
-
-class VsyncTracker : public RefBase{
-public:
-    VsyncTracker();
-    ~VsyncTracker() {}
-    nsecs_t getVsyncPeriod();
-    nsecs_t getVsyncTime(nsecs_t periodOffset);
-    void addSample(nsecs_t timestamp);
-
-private:
-    static const int kMaxSamples = 32;
-    static const int kMinSamplesForUpdate = 6;
-    int mNumSamples;
-    int mFirstSample;
-    nsecs_t mReferenceTime;
-    nsecs_t mPhase;
-    nsecs_t mPeriod;
-    nsecs_t mTimestampSamples[kMaxSamples];
-    Mutex mLock;
-
-    void updateModelLocked();
-};
-
-VsyncTracker::VsyncTracker()
-    : mNumSamples(0),
-      mFirstSample(0),
-      mReferenceTime(0),
-      mPhase(0),
-      mPeriod(0) {
-    for (int i = 0; i < kMaxSamples; i++) {
-        mTimestampSamples[i] = 0;
-    }
-}
-
-nsecs_t VsyncTracker::getVsyncPeriod() {
-    Mutex::Autolock dataLock(mLock);
-    return mPeriod;
-}
-
-nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
-    Mutex::Autolock dataLock(mLock);
-    const nsecs_t now = systemTime();
-    nsecs_t phase = mReferenceTime + mPhase;
-
-    // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
-    // prevent overflow
-    nsecs_t result = (now - phase) / mPeriod;
-    if (result > LONG_LONG_MAX - periodOffset - 1) {
-        return LONG_LONG_MAX;
-    } else {
-        result += periodOffset + 1;
-    }
-    if (result > LONG_LONG_MAX / mPeriod) {
-        return LONG_LONG_MAX;
-    } else {
-        result *= mPeriod;
-    }
-    if (result > LONG_LONG_MAX - phase) {
-        return LONG_LONG_MAX;
-    } else {
-        result += phase;
-    }
-
-    return result;
-}
-
-void VsyncTracker::addSample(nsecs_t timestamp) {
-    Mutex::Autolock dataLock(mLock);
-    if (mNumSamples == 0) {
-        mPhase = 0;
-        mReferenceTime = timestamp;
-    }
-    int idx = (mFirstSample + mNumSamples) % kMaxSamples;
-    mTimestampSamples[idx] = timestamp;
-    if (mNumSamples < kMaxSamples) {
-        mNumSamples++;
-    } else {
-        mFirstSample = (mFirstSample + 1) % kMaxSamples;
-    }
-    updateModelLocked();
-}
-
-void VsyncTracker::updateModelLocked() {
-    if (mNumSamples < kMinSamplesForUpdate) {
-        return;
-    }
-    nsecs_t durationSum = 0;
-    nsecs_t minDuration = LONG_MAX;
-    nsecs_t maxDuration = 0;
-
-    for (int i = 1; i < mNumSamples; i++) {
-        int idx = (mFirstSample + i) % kMaxSamples;
-        int prev = (idx + kMaxSamples - 1) % kMaxSamples;
-        long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
-        durationSum += duration;
-        if (minDuration > duration) { minDuration = duration; }
-        if (maxDuration < duration) { maxDuration = duration; }
-    }
-
-    durationSum -= (minDuration + maxDuration);
-    mPeriod = durationSum / (mNumSamples - 3);
-
-    double sampleAvgX = 0.0;
-    double sampleAvgY = 0.0;
-    double scale = 2.0 * M_PI / (double) mPeriod;
-
-    for (int i = 1; i < mNumSamples; i++) {
-        int idx = (mFirstSample + i) % kMaxSamples;
-        long sample = mTimestampSamples[idx] - mReferenceTime;
-        double samplePhase = (double) (sample % mPeriod) * scale;
-        sampleAvgX += cos(samplePhase);
-        sampleAvgY += sin(samplePhase);
-    }
-
-    sampleAvgX /= (double) mNumSamples - 1.0;
-    sampleAvgY /= (double) mNumSamples - 1.0;
-    mPhase = (long) (atan2(sampleAvgY, sampleAvgX) / scale);
-}
-
-static void frameCallback(int64_t frameTimeNanos, void* data) {
-    if (data == NULL) {
-        return;
-    }
-    sp<VsyncTracker> vsyncTracker(static_cast<VsyncTracker*>(data));
-    vsyncTracker->addSample(frameTimeNanos);
-    AChoreographer_postFrameCallback64(AChoreographer_getInstance(),
-            frameCallback, static_cast<void*>(vsyncTracker.get()));
-}
-
-/* ======================================================================= */
-/*                                   JNI                                   */
-/* ======================================================================= */
-
-static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
-    static const nsecs_t kOneMillisecInNanosec = 1000000;
-    static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
-
-    JNIEnv *env = JavaVMHelper::getJNIEnv();
-    jclass jDisplayManagerGlobalCls = env->FindClass(
-            "android/hardware/display/DisplayManagerGlobal");
-    jclass jDisplayCls = env->FindClass("android/view/Display");
-
-    jmethodID jGetInstance = env->GetStaticMethodID(jDisplayManagerGlobalCls,
-            "getInstance", "()Landroid/hardware/display/DisplayManagerGlobal;");
-    jobject javaDisplayManagerGlobalObj = env->CallStaticObjectMethod(
-            jDisplayManagerGlobalCls, jGetInstance);
-
-    jfieldID jDEFAULT_DISPLAY = env->GetStaticFieldID(jDisplayCls, "DEFAULT_DISPLAY", "I");
-    jint DEFAULT_DISPLAY = env->GetStaticIntField(jDisplayCls, jDEFAULT_DISPLAY);
-
-    jmethodID jgetRealDisplay = env->GetMethodID(jDisplayManagerGlobalCls,
-            "getRealDisplay", "(I)Landroid/view/Display;");
-    jobject javaDisplayObj = env->CallObjectMethod(
-            javaDisplayManagerGlobalObj, jgetRealDisplay, DEFAULT_DISPLAY);
-
-    jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
-    jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
-    nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
-
-    jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
-            jDisplayCls, "getAppVsyncOffsetNanos", "()J");
-    jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
-    *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
-
-    jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
-            jDisplayCls, "getPresentationDeadlineNanos", "()J");
-    jlong javaPresentationDeadline = env->CallLongMethod(
-            javaDisplayObj, jGetPresentationDeadlineNanos);
-
-    *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
-}
-
-/* ======================================================================= */
-/*                          Choreographer Thread                           */
-/* ======================================================================= */
-
-struct ChoreographerThread : public Thread {
-    ChoreographerThread(bool canCallJava);
-    status_t init(void* data);
-    virtual status_t readyToRun() override;
-    virtual bool threadLoop() override;
-
-protected:
-    virtual ~ChoreographerThread() {}
-
-private:
-    DISALLOW_EVIL_CONSTRUCTORS(ChoreographerThread);
-    void* mData;
-};
-
-ChoreographerThread::ChoreographerThread(bool canCallJava) : Thread(canCallJava) {
-}
-
-status_t ChoreographerThread::init(void* data) {
-    if (data == NULL) {
-        return NO_INIT;
-    }
-    mData = data;
-    return OK;
-}
-
-status_t ChoreographerThread::readyToRun() {
-    ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
-    if (AChoreographer_getInstance() == NULL) {
-        return NO_INIT;
-    }
-    AChoreographer_postFrameCallback64(AChoreographer_getInstance(), frameCallback, mData);
-    return OK;
-}
-
-bool ChoreographerThread::threadLoop() {
-    ALooper_pollOnce(-1, nullptr, nullptr, nullptr);
-    return true;
-}
-
-/* ======================================================================= */
-/*                             Frame Scheduler                             */
-/* ======================================================================= */
-
-VideoFrameScheduler2::VideoFrameScheduler2() : VideoFrameSchedulerBase() {
-
-    getVsyncOffset(&mAppVsyncOffset, &mSfVsyncOffset);
-
-    Mutex::Autolock threadLock(mLock);
-    mChoreographerThread = new ChoreographerThread(true);
-
-    mVsyncTracker = new VsyncTracker();
-    if (mChoreographerThread->init(static_cast<void*>(mVsyncTracker.get())) != OK) {
-        mChoreographerThread.clear();
-    }
-    if (mChoreographerThread != NULL && mChoreographerThread->run("Choreographer") != OK) {
-        mChoreographerThread.clear();
-    }
-}
-
-void VideoFrameScheduler2::updateVsync() {
-    mVsyncTime = 0;
-    mVsyncPeriod = 0;
-
-    if (mVsyncTracker != NULL) {
-        mVsyncPeriod = mVsyncTracker->getVsyncPeriod();
-        mVsyncTime = mVsyncTracker->getVsyncTime(mSfVsyncOffset - mAppVsyncOffset);
-    }
-    mVsyncRefreshAt = systemTime(SYSTEM_TIME_MONOTONIC) + kVsyncRefreshPeriod;
-}
-
-void VideoFrameScheduler2::release() {
-    // Do not change order
-    {
-        Mutex::Autolock threadLock(mLock);
-        mChoreographerThread->requestExitAndWait();
-        mChoreographerThread.clear();
-    }
-
-    mVsyncTracker.clear();
-}
-
-VideoFrameScheduler2::~VideoFrameScheduler2() {
-    release();
-}
-
-} // namespace android
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index db67034..8698d33 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -1,10 +1,7 @@
-cc_library_shared {
-    name: "libstagefright_bufferqueue_helper",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
+cc_defaults {
+    name: "libstagefright_bufferqueue-defaults",
     double_loadable: true,
+
     srcs: [
         "FrameDropper.cpp",
         "GraphicBufferSource.cpp",
@@ -23,29 +20,17 @@
     ],
 
     shared_libs: [
-        "libbinder",
+        "libbase",
         "libcutils",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
         "liblog",
         "libstagefright_foundation",
         "libui",
         "libutils",
 
         "android.hardware.graphics.bufferqueue@1.0",
-        // Following libs are from libgui_bufferqueue_static
         "android.hardware.graphics.bufferqueue@2.0",
-        "android.hidl.token@1.0-utils",
-        "libbase",
-        "libEGL",
-        "libhwbinder",
-        "libnativewindow",
-        "libvndksupport",
-    ],
-    
-    static_libs: [
-        "libgui_bufferqueue_static"
     ],
 
     export_shared_lib_headers: [
@@ -70,3 +55,62 @@
         cfi: true,
     },
 }
+
+cc_library_shared {
+    name: "libstagefright_bufferqueue_helper",
+    defaults: ["libstagefright_bufferqueue-defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    min_sdk_version: "29",
+
+    shared_libs: [ "libgui" ],
+    target: {
+        vendor: {
+            exclude_shared_libs: [
+                "libgui",
+            ],
+            static_libs: [
+                "libgui_bufferqueue_static",
+            ],
+            shared_libs: [
+                "android.hidl.token@1.0-utils",
+                "libEGL",
+                "libnativewindow",
+                "libvndksupport",
+            ],
+            cflags: [
+                "-DNO_BINDER",
+            ],
+        },
+    },
+}
+
+// This lib is needed on devices that doesn't use vndk,
+// on these devices we still don't want libgui to be pulled
+// in onto the apex build. It should only be used by
+// libcodec2_hidl@1.x, etc. from service side. It could
+// be removed if all builds are using vndk.
+cc_library_shared {
+    name: "libstagefright_bufferqueue_helper_novndk",
+    defaults: ["libstagefright_bufferqueue-defaults"],
+    apex_available: [
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
+        "//apex_available:platform",
+    ],
+    vendor_available: false,
+    static_libs: [
+        "libgui_bufferqueue_static",
+    ],
+    shared_libs: [
+        "android.hidl.token@1.0-utils",
+        "libEGL",
+        "libnativewindow",
+        "libvndksupport",
+    ],
+    cflags: [
+        "-DNO_BINDER",
+    ],
+}
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 59317e7..cff14ac 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/foundation/ColorUtils.h>
 #include <media/stagefright/foundation/FileDescriptor.h>
 
+#include <android-base/properties.h>
 #include <media/hardware/MetadataBufferType.h>
 #include <ui/GraphicBuffer.h>
 #include <gui/BufferItem.h>
@@ -411,7 +412,7 @@
                     B2HGraphicBufferProducer(getIGraphicBufferProducer());
 }
 
-Status GraphicBufferSource::start() {
+status_t GraphicBufferSource::start() {
     Mutex::Autolock autoLock(mMutex);
     ALOGV("--> start; available=%zu, submittable=%zd",
             mAvailableBuffers.size(), mFreeCodecBuffers.size());
@@ -458,10 +459,10 @@
         }
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::stop() {
+status_t GraphicBufferSource::stop() {
     ALOGV("stop");
 
     Mutex::Autolock autoLock(mMutex);
@@ -471,10 +472,10 @@
         // not loaded->idle.
         mExecuting = false;
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::release(){
+status_t GraphicBufferSource::release(){
     sp<ALooper> looper;
     {
         Mutex::Autolock autoLock(mMutex);
@@ -500,26 +501,26 @@
     if (looper != NULL) {
         looper->stop();
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
+status_t GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting) {
         // This should never happen -- buffers can only be allocated when
         // transitioning from "loaded" to "idle".
         ALOGE("addCodecBuffer: buffer added while executing");
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     ALOGV("addCodecBuffer: bufferId=%u", bufferId);
 
     mFreeCodecBuffers.push_back(bufferId);
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
+status_t GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
     Mutex::Autolock autoLock(mMutex);
     FileDescriptor::Autoclose fence(fenceFd);
 
@@ -527,7 +528,7 @@
     if (cbi < 0) {
         // This should never happen.
         ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
     std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);
@@ -547,13 +548,13 @@
             ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
         }
         // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
     if (!mExecuting) {
         // this is fine since this could happen when going from Idle to Loaded
         ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
-        return Status::fromServiceSpecificError(OK);
+        return OK;
     }
 
     ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
@@ -583,7 +584,7 @@
     }
 
     // releaseReleasableBuffers_l();
-    return Status::ok();
+    return OK;
 }
 
 void GraphicBufferSource::onDataspaceChanged_l(
@@ -800,6 +801,9 @@
     }
 }
 
+#ifdef __clang__
+__attribute__((no_sanitize("integer")))
+#endif
 bool GraphicBufferSource::calculateCodecTimestamp_l(
         nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
     int64_t timeUs = bufferTimeNs / 1000;
@@ -816,14 +820,15 @@
             mPrevFrameUs = mBaseFrameUs =
                     std::llround((timeUs * mCaptureFps) / mFps);
             mFrameCount = 0;
-        } else {
-            // snap to nearest capture point
+        } else if (mSnapTimestamps) {
             double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000;
             if (nFrames < 0.5 - kTimestampFluctuation) {
                 // skip this frame as it's too close to previous capture
-                ALOGD("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
+                ALOGD("skipping frame, timeUs %lld",
+                      static_cast<long long>(timeUs));
                 return false;
             }
+            // snap to nearest capture point
             if (nFrames <= 1.0) {
                 nFrames = 1.0;
             }
@@ -832,6 +837,22 @@
                     mFrameCount * 1000000 / mCaptureFps);
             mPrevFrameUs = mBaseFrameUs + std::llround(
                     mFrameCount * 1000000 / mFps);
+        } else {
+            if (timeUs <= mPrevCaptureUs) {
+                if (mFrameDropper != NULL && mFrameDropper->disabled()) {
+                    // Warn only, client has disabled frame drop logic possibly for image
+                    // encoding cases where camera's ZSL mode could send out of order frames.
+                    ALOGW("Received frame that's going backward in time");
+                } else {
+                    // Drop the frame if it's going backward in time. Bad timestamp
+                    // could disrupt encoder's rate control completely.
+                    ALOGW("Dropping frame that's going backward in time");
+                    return false;
+                }
+            }
+            mPrevCaptureUs = timeUs;
+            mPrevFrameUs = mBaseFrameUs + std::llround(
+                    (timeUs - mBaseCaptureUs) * (mCaptureFps / mFps));
         }
 
         ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
@@ -1359,6 +1380,12 @@
 
     mFps = fps;
     mCaptureFps = captureFps;
+    if (captureFps > fps) {
+        mSnapTimestamps = 1 == base::GetIntProperty(
+                "debug.stagefright.snap_timestamps", int64_t(0));
+    } else {
+        mSnapTimestamps = false;
+    }
 
     return OK;
 }
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
index b4c4d4a..fe6bcce 100644
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
+++ b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
@@ -31,8 +31,6 @@
 
 namespace android {
 
-using ::android::binder::Status;
-
 struct FrameDropper;
 class BufferItem;
 class IGraphicBufferProducer;
@@ -99,26 +97,26 @@
     // This is called when component transitions to running state, which means
     // we can start handing it buffers.  If we already have buffers of data
     // sitting in the BufferQueue, this will send them to the codec.
-    Status start();
+    status_t start();
 
     // This is called when component transitions to stopped, indicating that
     // the codec is meant to return all buffers back to the client for them
     // to be freed. Do NOT submit any more buffers to the component.
-    Status stop();
+    status_t stop();
 
     // This is called when component transitions to released, indicating that
     // we are shutting down.
-    Status release();
+    status_t release();
 
     // A "codec buffer", i.e. a buffer that can be used to pass data into
     // the encoder, has been allocated.  (This call does not call back into
     // component.)
-    Status onInputBufferAdded(int32_t bufferId);
+    status_t onInputBufferAdded(int32_t bufferId);
 
     // Called when encoder is no longer using the buffer.  If we have a BQ
     // buffer available, fill it with a new frame of data; otherwise, just mark
     // it as available.
-    Status onInputBufferEmptied(int32_t bufferId, int fenceFd);
+    status_t onInputBufferEmptied(int32_t bufferId, int fenceFd);
 
     // IGraphicBufferSource interface
     // ------------------------------
@@ -461,12 +459,33 @@
     // Slow motion mode is enabled if both encoding and capture frame rates are
     // defined and the encoding frame rate is less than half the capture frame
     // rate. In this mode, the source is expected to produce frames with an even
-    // timestamp interval (after rounding) with the configured capture fps. The
-    // first source timestamp is used as the source base time. Afterwards, the
-    // timestamp of each source frame is snapped to the nearest expected capture
-    // timestamp and scaled to match the configured encoding frame rate.
+    // timestamp interval (after rounding) with the configured capture fps.
+    //
+    // These modes must be configured by calling setTimeLapseConfig() before
+    // using this source.
+    //
+    // Timestamp snapping for slow motion recording
+    // ============================================
+    //
+    // When the slow motion mode is configured with setTimeLapseConfig(), the
+    // property "debug.stagefright.snap_timestamps" will be checked. If the
+    // value of the property is set to any value other than 1, mSnapTimestamps
+    // will be set to false. Otherwise, mSnapTimestamps will be set to true.
+    // (mSnapTimestamps will be false for time lapse recording regardless of the
+    // value of the property.)
+    //
+    // If mSnapTimestamps is true, i.e., timestamp snapping is enabled, the
+    // first source timestamp will be used as the source base time; afterwards,
+    // the timestamp of each source frame will be snapped to the nearest
+    // expected capture timestamp and scaled to match the configured encoding
+    // frame rate.
+    //
+    // If timestamp snapping is disabled, the timestamp of source frames will
+    // be scaled to match the ratio between the configured encoding frame rate
+    // and the configured capture frame rate.
 
-    // These modes must be enabled before using this source.
+    // whether timestamps will be snapped
+    bool mSnapTimestamps{true};
 
     // adjusted capture timestamp of the base frame
     int64_t mBaseCaptureUs;
diff --git a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
index 95d3724..168d140 100644
--- a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
+++ b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
     mEncoderTarget = -1;
 
     /* Values from last time. */
-    /* Initialized to the same values as the desired values */
-    mLastTarget = -1;
-    mLastAttFactor = 0;
-    mLastBoostFactor = 0;
+    mLastTarget = -2;
+    mLastAttFactor = -1;
+    mLastBoostFactor = -1;
     mLastHeavy = 0;
 }
 
@@ -163,7 +162,7 @@
 
     if (mDataUpdate) {
         // sanity check
-        if (mDesTarget < MAX_TARGET_LEVEL){
+        if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
             mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
             newTarget = MAX_TARGET_LEVEL;
         }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 41bc16c..2aeddd7 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -37,6 +37,7 @@
 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1   /* switch for heavy compression for mobile conf */
 #define DRC_DEFAULT_MOBILE_DRC_EFFECT 3  /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0  /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
 #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
 #define MAX_CHANNEL_COUNT            8  /* maximum number of audio channels that can be decoded */
 // names of properties that can be used to override the default DRC settings
@@ -219,6 +220,11 @@
     ALOGV("AAC decoder using MPEG-D DRC effect type %d (default=%d)",
             effectType, DRC_DEFAULT_MOBILE_DRC_EFFECT);
     aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+    // AAC_UNIDRC_ALBUM_MODE
+    int32_t albumMode = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+    ALOGV("AAC decoder using MPEG-D Album mode value %d (default=%d)", albumMode,
+            DRC_DEFAULT_MOBILE_DRC_ALBUM);
+    aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
 
     // By default, the decoder creates a 5.1 channel downmix signal.
     // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
@@ -459,6 +465,11 @@
                 ALOGV("set nDrcEffectType=%d", aacPresParams->nDrcEffectType);
                 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, aacPresParams->nDrcEffectType);
             }
+            if (aacPresParams->nDrcAlbumMode >= -1) {
+                ALOGV("set nDrcAlbumMode=%d", aacPresParams->nDrcAlbumMode);
+                aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE,
+                        aacPresParams->nDrcAlbumMode);
+            }
             bool updateDrcWrapper = false;
             if (aacPresParams->nDrcBoost >= 0) {
                 ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost);
@@ -477,7 +488,7 @@
                         aacPresParams->nHeavyCompression);
                 updateDrcWrapper = true;
             }
-            if (aacPresParams->nTargetReferenceLevel >= 0) {
+            if (aacPresParams->nTargetReferenceLevel >= -1) {
                 ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
                 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
                         aacPresParams->nTargetReferenceLevel);
diff --git a/media/libstagefright/codecs/amrnb/common/Android.bp b/media/libstagefright/codecs/amrnb/common/Android.bp
index 772ebf9..59a791d 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.bp
+++ b/media/libstagefright/codecs/amrnb/common/Android.bp
@@ -1,6 +1,8 @@
-cc_library_shared {
+cc_library {
     name: "libstagefright_amrnb_common",
     vendor_available: true,
+    host_supported: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/add.cpp",
@@ -73,6 +75,12 @@
         "-Werror",
     ],
 
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
     //addressing b/25409744
     //sanitize: {
     //    misc_undefined: [
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index e18117e..b8e00b3 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -1,6 +1,8 @@
 cc_library_static {
     name: "libstagefright_amrnbdec",
     vendor_available: true,
+    host_supported: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/a_refl.cpp",
@@ -61,6 +63,12 @@
         "libstagefright_amrnb_common",
         "liblog",
     ],
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
@@ -100,6 +108,7 @@
 cc_test {
     name: "libstagefright_amrnbdec_test",
     gtest: false,
+    host_supported: true,
 
     srcs: ["test/amrnbdec_test.cpp"],
 
@@ -118,6 +127,12 @@
         "liblog",
     ],
 
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
     //sanitize: {
     //    misc_undefined: [
     //        "signed-integer-overflow",
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index 34dd011..cdfc03a 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -20,9 +20,6 @@
 
 #include "SoftAMR.h"
 
-#include "gsmamr_dec.h"
-#include "pvamrwbdecoder.h"
-
 #include <media/stagefright/foundation/ADebug.h>
 
 namespace android {
@@ -470,11 +467,10 @@
                 memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
             } else if (mode < 9) {
                 int16 frameType;
-                RX_State_wb rx_state;
                 mime_unsorting(
                         const_cast<uint8_t *>(&inputPtr[1]),
                         mInputSampleBuffer,
-                        &frameType, &mode, 1, &rx_state);
+                        &frameType, &mode, 1, &mRxState);
 
                 int16_t numSamplesOutput;
                 pvDecoder_AmrWb(
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
index 869b81d..d5aaed3 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
@@ -19,6 +19,8 @@
 #define SOFT_AMR_H_
 
 #include <media/stagefright/omx/SimpleSoftOMXComponent.h>
+#include "gsmamr_dec.h"
+#include "pvamrwbdecoder.h"
 
 namespace android {
 
@@ -60,6 +62,7 @@
     void *mState;
     void *mDecoderBuf;
     int16_t *mDecoderCookie;
+    RX_State_wb mRxState{};
 
     size_t mInputBufferCount;
     int64_t mAnchorTimeUs;
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h b/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
new file mode 100644
index 0000000..0344ac5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __AMRNBDEC_TEST_ENVIRONMENT_H__
+#define __AMRNBDEC_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class AmrnbDecTestEnvironment : public ::testing::Environment {
+  public:
+    AmrnbDecTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int AmrnbDecTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __AMRNBDEC_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp b/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
new file mode 100644
index 0000000..af62074
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2019 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 "AmrnbDecoderTest"
+#define OUTPUT_FILE "/data/local/tmp/amrnbDecode.out"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "gsmamr_dec.h"
+
+#include "AmrnbDecTestEnvironment.h"
+
+// Constants for AMR-NB
+constexpr int32_t kInputBufferSize = 64;
+constexpr int32_t kSamplesPerFrame = L_FRAME;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kSampleRate = 8000;
+constexpr int32_t kChannels = 1;
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+const int32_t kFrameSizes[] = {12, 13, 15, 17, 19, 20, 26, 31, -1, -1, -1, -1, -1, -1, -1, -1};
+
+constexpr int32_t kNumFrameReset = 150;
+
+static AmrnbDecTestEnvironment *gEnv = nullptr;
+
+class AmrnbDecoderTest : public ::testing::TestWithParam<string> {
+  public:
+    AmrnbDecoderTest() : mFpInput(nullptr) {}
+
+    ~AmrnbDecoderTest() {
+        if (mFpInput) {
+            fclose(mFpInput);
+            mFpInput = nullptr;
+        }
+    }
+
+    FILE *mFpInput;
+    SNDFILE *openOutputFile(SF_INFO *sfInfo);
+    int32_t DecodeFrames(void *amrHandle, SNDFILE *outFileHandle, int32_t frameCount = INT32_MAX);
+};
+
+SNDFILE *AmrnbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
+    memset(sfInfo, 0, sizeof(SF_INFO));
+    sfInfo->channels = kChannels;
+    sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo->samplerate = kSampleRate;
+    SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
+    return outFileHandle;
+}
+
+int32_t AmrnbDecoderTest::DecodeFrames(void *amrHandle, SNDFILE *outFileHandle,
+                                       int32_t frameCount) {
+    uint8_t inputBuf[kInputBufferSize];
+    int16_t outputBuf[kOutputBufferSize];
+
+    while (frameCount > 0) {
+        uint8_t mode;
+        int32_t bytesRead = fread(&mode, 1, 1, mFpInput);
+        if (bytesRead != 1) break;
+
+        // Find frame type
+        Frame_Type_3GPP frameType = (Frame_Type_3GPP)((mode >> 3) & 0x0f);
+        int32_t frameSize = kFrameSizes[frameType];
+        if (frameSize < 0) {
+            ALOGE("Illegal frame type");
+            return -1;
+        }
+        bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
+        if (bytesRead != frameSize) break;
+
+        int32_t bytesDecoded = AMRDecode(amrHandle, frameType, inputBuf, outputBuf, MIME_IETF);
+        if (bytesDecoded == -1) {
+            ALOGE("Failed to decode the input file");
+            return -1;
+        }
+
+        sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame);
+        frameCount--;
+    }
+    return 0;
+}
+
+TEST_F(AmrnbDecoderTest, CreateAmrnbDecoderTest) {
+    void *amrHandle;
+    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
+    GSMDecodeFrameExit(&amrHandle);
+    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
+}
+
+TEST_P(AmrnbDecoderTest, DecodeTest) {
+    string inputFile = gEnv->getRes() + GetParam();
+    mFpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    void *amrHandle;
+    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
+
+    // Decode
+    int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    sf_close(outFileHandle);
+    GSMDecodeFrameExit(&amrHandle);
+    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
+}
+
+TEST_P(AmrnbDecoderTest, ResetDecodeTest) {
+    string inputFile = gEnv->getRes() + GetParam();
+    mFpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    void *amrHandle;
+    int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB decoder";
+
+    // Decode kNumFrameReset first
+    int32_t decoderErr = DecodeFrames(amrHandle, outFileHandle, kNumFrameReset);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    status = Speech_Decode_Frame_reset(amrHandle);
+    ASSERT_EQ(status, 0) << "Error resting AMR-NB decoder";
+
+    // Start decoding again
+    decoderErr = DecodeFrames(amrHandle, outFileHandle);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    sf_close(outFileHandle);
+    GSMDecodeFrameExit(&amrHandle);
+    ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
+}
+
+INSTANTIATE_TEST_SUITE_P(AmrnbDecoderTestAll, AmrnbDecoderTest,
+                         ::testing::Values(("bbb_8000hz_1ch_8kbps_amrnb_30sec.amrnb"),
+                                           ("sine_amrnb_1ch_12kbps_8000hz.amrnb")));
+
+int main(int argc, char **argv) {
+    gEnv = new AmrnbDecTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/test/Android.bp b/media/libstagefright/codecs/amrnb/dec/test/Android.bp
new file mode 100644
index 0000000..7a95cfa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "AmrnbDecoderTest",
+    gtest: true,
+
+    srcs: [
+        "AmrnbDecoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_amrnb_common",
+        "libstagefright_amrnbdec",
+        "libaudioutils",
+        "libsndfile",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/test/README.md b/media/libstagefright/codecs/amrnb/dec/test/README.md
new file mode 100644
index 0000000..62e13ae
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/test/README.md
@@ -0,0 +1,34 @@
+## Media Testing ##
+---
+#### AMR-NB Decoder :
+The Amr-Nb Decoder Test Suite validates the amrnb decoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m AmrnbDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b). Push these files into device for testing.
+Download amr-nb folder and push all the files in this folder to /data/local/tmp/ on the device.
+```
+adb push amr-nb/. /data/local/tmp/
+```
+
+usage: AmrnbDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/
+```
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index 438ed04..73a1d4b 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_amrnbenc",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/amrencode.cpp",
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
new file mode 100644
index 0000000..5a2fcd1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __AMRNBENC_TEST_ENVIRONMENT_H__
+#define __AMRNBENC_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class AmrnbEncTestEnvironment : public ::testing::Environment {
+  public:
+    AmrnbEncTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int AmrnbEncTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __AMRNBENC_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
new file mode 100644
index 0000000..fb72998
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 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 "AmrnbEncoderTest"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "gsmamr_enc.h"
+
+#include "AmrnbEncTestEnvironment.h"
+
+#define OUTPUT_FILE "/data/local/tmp/amrnbEncode.out"
+
+constexpr int32_t kInputBufferSize = L_FRAME * 2;  // 160 samples * 16-bit per sample.
+constexpr int32_t kOutputBufferSize = 1024;
+constexpr int32_t kNumFrameReset = 200;
+constexpr int32_t kMaxCount = 10;
+struct AmrNbEncState {
+    void *encCtx;
+    void *pidSyncCtx;
+};
+
+static AmrnbEncTestEnvironment *gEnv = nullptr;
+
+class AmrnbEncoderTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+  public:
+    AmrnbEncoderTest() : mAmrEncHandle(nullptr) {}
+
+    ~AmrnbEncoderTest() {
+        if (mAmrEncHandle) {
+            free(mAmrEncHandle);
+            mAmrEncHandle = nullptr;
+        }
+    }
+
+    AmrNbEncState *mAmrEncHandle;
+    int32_t EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
+                         int32_t frameCount = INT32_MAX);
+};
+
+int32_t AmrnbEncoderTest::EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
+                                       int32_t frameCount) {
+    int32_t frameNum = 0;
+    uint16_t inputBuf[kInputBufferSize];
+    uint8_t outputBuf[kOutputBufferSize];
+    while (frameNum < frameCount) {
+        int32_t bytesRead = fread(inputBuf, 1, kInputBufferSize, fpInput);
+        if (bytesRead != kInputBufferSize && !feof(fpInput)) {
+            ALOGE("Unable to read data from input file");
+            return -1;
+        } else if (feof(fpInput) && bytesRead == 0) {
+            break;
+        }
+        Frame_Type_3GPP frame_type = (Frame_Type_3GPP)mode;
+        int32_t bytesGenerated =
+                AMREncode(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx, (Mode)mode,
+                          (Word16 *)inputBuf, outputBuf, &frame_type, AMR_TX_WMF);
+        frameNum++;
+        if (bytesGenerated < 0) {
+            ALOGE("Error in encoging the file: Invalid output format");
+            return -1;
+        }
+
+        // Convert from WMF to RFC 3267 format.
+        if (bytesGenerated > 0) {
+            outputBuf[0] = ((outputBuf[0] << 3) | 4) & 0x7c;
+        }
+        fwrite(outputBuf, 1, bytesGenerated, mFpOutput);
+    }
+    return 0;
+}
+
+TEST_F(AmrnbEncoderTest, CreateAmrnbEncoderTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    for (int count = 0; count < kMaxCount; count++) {
+        int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+        ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+        ALOGV("Successfully created encoder");
+    }
+    if (mAmrEncHandle) {
+        AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+        ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+        ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+        free(mAmrEncHandle);
+        mAmrEncHandle = nullptr;
+        ALOGV("Successfully deleted encoder");
+    }
+}
+
+TEST_P(AmrnbEncoderTest, EncodeTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *fpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
+
+    FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
+    ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
+
+    // Write file header.
+    fwrite("#!AMR\n", 1, 6, fpOutput);
+
+    int32_t mode = GetParam().second;
+    int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    fclose(fpOutput);
+    fclose(fpInput);
+
+    AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+    ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+    free(mAmrEncHandle);
+    mAmrEncHandle = nullptr;
+    ALOGV("Successfully deleted encoder");
+}
+
+TEST_P(AmrnbEncoderTest, ResetEncoderTest) {
+    mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
+    ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
+    int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
+    ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
+
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *fpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
+
+    FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
+    ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
+
+    // Write file header.
+    fwrite("#!AMR\n", 1, 6, fpOutput);
+
+    int32_t mode = GetParam().second;
+    // Encode kNumFrameReset first
+    int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput, kNumFrameReset);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    status = AMREncodeReset(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(status, 0) << "Error resting AMR-NB encoder";
+
+    // Start encoding again
+    encodeErr = EncodeFrames(mode, fpInput, fpOutput);
+    ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
+
+    fclose(fpOutput);
+    fclose(fpInput);
+
+    AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
+    ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
+    ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
+    free(mAmrEncHandle);
+    mAmrEncHandle = nullptr;
+    ALOGV("Successfully deleted encoder");
+}
+
+// TODO: Add more test vectors
+INSTANTIATE_TEST_SUITE_P(AmrnbEncoderTestAll, AmrnbEncoderTest,
+                         ::testing::Values(make_pair("bbb_raw_1ch_8khz_s16le.raw", MR475),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR515),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR59),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR67),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR74),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR795),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR102),
+                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR122),
+                                           make_pair("sinesweepraw.raw", MR475),
+                                           make_pair("sinesweepraw.raw", MR515),
+                                           make_pair("sinesweepraw.raw", MR59),
+                                           make_pair("sinesweepraw.raw", MR67),
+                                           make_pair("sinesweepraw.raw", MR74),
+                                           make_pair("sinesweepraw.raw", MR795),
+                                           make_pair("sinesweepraw.raw", MR102),
+                                           make_pair("sinesweepraw.raw", MR122)));
+
+int main(int argc, char **argv) {
+    gEnv = new AmrnbEncTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/test/Android.bp b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
new file mode 100644
index 0000000..e8982fe
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "AmrnbEncoderTest",
+    gtest: true,
+
+    srcs: [
+        "AmrnbEncoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_amrnb_common",
+        "libstagefright_amrnbenc",
+        "libaudioutils",
+        "libsndfile",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/test/AndroidTest.xml b/media/libstagefright/codecs/amrnb/enc/test/AndroidTest.xml
new file mode 100644
index 0000000..9fe61b1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Amr-nb Encoder unit test">
+    <option name="test-suite-tag" value="AmrnbEncoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="AmrnbEncoderTest->/data/local/tmp/AmrnbEncoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true"
+            value="/data/local/tmp/AmrnbEncoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="AmrnbEncoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/AmrnbEncoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/amrnb/enc/test/README.md b/media/libstagefright/codecs/amrnb/enc/test/README.md
new file mode 100644
index 0000000..e9d2c95
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### AMR-NB Encoder :
+The Amr-Nb Encoder Test Suite validates the amrnb encoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m AmrnbEncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/AmrnbEncoderTest/AmrnbEncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/AmrnbEncoderTest/AmrnbEncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push AmrnbEncoderTestRes/. /data/local/tmp/
+```
+
+usage: AmrnbEncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/AmrnbEncoderTest -P /data/local/tmp/AmrnbEncoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest AmrnbEncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp b/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
new file mode 100644
index 0000000..54de1cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "amrnb_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "amrnb_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_amrnbdec",
+        "libstagefright_amrnb_common",
+        "liblog",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/README.md b/media/libstagefright/codecs/amrnb/fuzzer/README.md
new file mode 100644
index 0000000..7791b83
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/README.md
@@ -0,0 +1,62 @@
+# Fuzzer for libstagefright_amrnbdec decoder
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR-NB is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+AMR-NB supports the following parameters:
+1. Stream format (parameter name: `input_format`)
+2. 3GPP frame type (parameter name: `frame_type`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `input_format` | 0. `MIME_IETF` 1. `IF2` | Bit 0 (LSB) of 1st byte of data. |
+| `frame_type`   | 0. `AMR_475` 1. `AMR_515` 2. `AMR_59` 3. `AMR_67`  4. `AMR_74` 5. `AMR_795` 6. `AMR_102` 7. `AMR_122`  | Bits 3, 4 and 5 of 1st byte of data. |
+
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+If the decode operation was successful, the input is advanced by the frame size
+which is based on `input_format` and `frame_type` selected.
+If the decode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build amrnb_dec_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) amrnb_dec_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some amrnb files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/amrnb_dec_fuzzer/amrnb_dec_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/amrnb_dec_fuzzer/amrnb_dec_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp b/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
new file mode 100644
index 0000000..d4e7e5c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
@@ -0,0 +1,94 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <string.h>
+#include <algorithm>
+#include "gsmamr_dec.h"
+
+// Constants for AMR-NB
+constexpr int32_t kSamplesPerFrame = L_FRAME;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+const bitstream_format kBitStreamFormats[2] = {MIME_IETF, IF2};
+const int32_t kLocalWmfDecBytesPerFrame[8] = {12, 13, 15, 17, 19, 20, 26, 31};
+const int32_t kLocalIf2DecBytesPerFrame[8] = {13, 14, 16, 18, 19, 21, 26, 31};
+
+class Codec {
+ public:
+  Codec() = default;
+  ~Codec() { deInitDecoder(); }
+  int16_t initDecoder();
+  void deInitDecoder();
+  void decodeFrames(const uint8_t *data, size_t size);
+
+ private:
+  void *mAmrHandle = nullptr;
+};
+
+int16_t Codec::initDecoder() { return GSMInitDecode(&mAmrHandle, (Word8 *)"AMRNBDecoder"); }
+
+void Codec::deInitDecoder() { GSMDecodeFrameExit(&mAmrHandle); }
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  while (size > 0) {
+    uint8_t mode = *data;
+    bool bit = mode & 0x01;
+    bitstream_format bitsreamFormat = kBitStreamFormats[bit];
+    int32_t frameSize = 0;
+    /* Find frame type */
+    Frame_Type_3GPP frameType = static_cast<Frame_Type_3GPP>((mode >> 3) & 0x07);
+    ++data;
+    --size;
+    if (bit) {
+      frameSize = kLocalIf2DecBytesPerFrame[frameType];
+    } else {
+      frameSize = kLocalWmfDecBytesPerFrame[frameType];
+    }
+    int16_t outputBuf[kOutputBufferSize];
+    uint8_t *inputBuf = new uint8_t[frameSize];
+    if (!inputBuf) {
+      return;
+    }
+    int32_t minSize = std::min((int32_t)size, frameSize);
+    memcpy(inputBuf, data, minSize);
+    AMRDecode(mAmrHandle, frameType, inputBuf, outputBuf, bitsreamFormat);
+    /* AMRDecode() decodes minSize number of bytes if decode is successful.
+     * AMRDecode() returns -1 if decode fails.
+     * Even if no bytes are decoded, increment by minSize to ensure fuzzer proceeds
+     * to feed next data */
+    data += minSize;
+    size -= minSize;
+    delete[] inputBuf;
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 2) {
+    return 0;
+  }
+  Codec *codec = new Codec();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder() == 0) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/libstagefright/codecs/amrwb/Android.bp
index 88cf7f2..204cbe3 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/libstagefright/codecs/amrwb/Android.bp
@@ -1,6 +1,8 @@
 cc_library_static {
     name: "libstagefright_amrwbdec",
     vendor_available: true,
+    host_supported: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/agc2_amr_wb.cpp",
@@ -44,8 +46,6 @@
         "src/weight_amrwb_lpc.cpp",
     ],
 
-    header_libs: ["libstagefright_headers"],
-
     export_include_dirs: [
         "src",
         "include",
@@ -63,12 +63,19 @@
             "signed-integer-overflow",
         ],
     },
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
 cc_test {
     name: "libstagefright_amrwbdec_test",
     gtest: false,
+    host_supported: true,
 
     srcs: ["test/amrwbdec_test.cpp"],
 
@@ -88,4 +95,10 @@
             "signed-integer-overflow",
         ],
     },
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/Android.bp b/media/libstagefright/codecs/amrwb/fuzzer/Android.bp
new file mode 100644
index 0000000..46f77e3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/Android.bp
@@ -0,0 +1,35 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "amrwb_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "amrwb_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_amrwbdec",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/README.md b/media/libstagefright/codecs/amrwb/fuzzer/README.md
new file mode 100644
index 0000000..de45784
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/README.md
@@ -0,0 +1,61 @@
+# Fuzzer for libstagefright_amrwbdec decoder
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR-WB is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+AMR-WB supports the following parameters:
+1. Quality (parameter name: `quality`)
+2. Mode (parameter name: `mode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `quality` | 0. `Bad Quality` 1. `Good quality` | Bit 0 (LSB) of 1st byte of data. |
+| `mode`   | 0. `MODE_7k` 1. `MODE_9k` 2. `MODE_12k` 3. `MODE_14k`  4. `MODE_16k ` 5. `MODE_18k` 6. `MODE_20k` 7. `MODE_23k` 8. `MODE_24k` 9. `MRDTX`  | Bits 3, 4, 5 and 6 of 1st byte of data. |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+If the decode operation was successful, the input is advanced by the frame size
+which is based on `mode` and `quality` selected.
+If the decode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build amrwb_dec_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) amrwb_dec_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some amrwb files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/amrwb_dec_fuzzer/amrwb_dec_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
new file mode 100644
index 0000000..592a6ec
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/fuzzer/amrwb_dec_fuzzer.cpp
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <malloc.h>
+#include <string.h>
+#include <algorithm>
+#include "pvamrwbdecoder.h"
+#include "pvamrwbdecoder_api.h"
+
+// Constants for AMR-WB.
+constexpr int32_t kSamplesPerFrame = 320;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+constexpr int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58,
+                                     60, 17, 23, 32, 36, 40, 46, 50};
+
+class Codec {
+ public:
+  Codec() = default;
+  ~Codec() { deInitDecoder(); }
+  bool initDecoder();
+  void decodeFrames(const uint8_t *data, size_t size);
+  void deInitDecoder();
+
+ private:
+  void *mAmrHandle = nullptr;
+  int16_t *mDecoderCookie = nullptr;
+  void *mDecoderBuffer = nullptr;
+};
+
+bool Codec::initDecoder() {
+  mDecoderBuffer = malloc(pvDecoder_AmrWbMemRequirements());
+  if (mDecoderBuffer) {
+    pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuffer, &mDecoderCookie);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void Codec::deInitDecoder() {
+  if (mDecoderBuffer) {
+    free(mDecoderBuffer);
+    mDecoderBuffer = nullptr;
+  }
+  mAmrHandle = nullptr;
+  mDecoderCookie = nullptr;
+}
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  RX_State_wb rx_state{};
+  while (size > 0) {
+    uint8_t modeByte = *data;
+    bool quality = modeByte & 0x01;
+    int16 mode = ((modeByte >> 3) & 0x0f);
+    ++data;
+    --size;
+    int32_t frameSize = kFrameSizes[mode];
+    int16_t inputSampleBuf[kMaxSourceDataUnitSize];
+    uint8_t *inputBuf = new uint8_t[frameSize];
+    if (!inputBuf) {
+      return;
+    }
+    int32_t minSize = std::min((int32_t)size, frameSize);
+    memcpy(inputBuf, data, minSize);
+    int16 frameMode = mode;
+    int16 frameType;
+    mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
+
+    int16_t numSamplesOutput;
+    int16_t outputBuf[kOutputBufferSize];
+    pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, mDecoderBuffer,
+                    frameType, mDecoderCookie);
+    data += minSize;
+    size -= minSize;
+    delete[] inputBuf;
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 2) {
+    return 0;
+  }
+  Codec *codec = new Codec();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder()) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
index ddc818e..c9c1cd4 100644
--- a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
@@ -337,7 +337,10 @@
     st = (Decoder_State *) spd_state;
 
     /* mode verification */
-
+    if (mode < 0 || mode >= NUM_OF_MODES)
+    {
+        return (-1);
+    }
     nb_bits = AMR_WB_COMPRESSED[mode];
 
     *frame_length = AMR_WB_PCM_FRAME;
diff --git a/media/libstagefright/codecs/amrwb/test/AmrwbDecTestEnvironment.h b/media/libstagefright/codecs/amrwb/test/AmrwbDecTestEnvironment.h
new file mode 100644
index 0000000..84d337d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/AmrwbDecTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __AMRWBDEC_TEST_ENVIRONMENT_H__
+#define __AMRWBDEC_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class AmrwbDecTestEnvironment : public ::testing::Environment {
+  public:
+    AmrwbDecTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int AmrwbDecTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __AMRWBDEC_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp b/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
new file mode 100644
index 0000000..7221b92
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2019 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 "AmrwbDecoderTest"
+#define OUTPUT_FILE "/data/local/tmp/amrwbDecode.out"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "pvamrwbdecoder.h"
+#include "pvamrwbdecoder_api.h"
+
+#include "AmrwbDecTestEnvironment.h"
+
+// Constants for AMR-WB.
+constexpr int32_t kInputBufferSize = 64;
+constexpr int32_t kSamplesPerFrame = 320;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kSampleRate = 16000;
+constexpr int32_t kChannels = 1;
+constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+const int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58, 60, -1, -1, -1, -1, -1, -1, -1};
+constexpr int32_t kNumFrameReset = 150;
+
+constexpr int32_t kMaxCount = 10;
+
+static AmrwbDecTestEnvironment *gEnv = nullptr;
+
+class AmrwbDecoderTest : public ::testing::TestWithParam<string> {
+  public:
+    AmrwbDecoderTest() : mFpInput(nullptr) {}
+
+    ~AmrwbDecoderTest() {
+        if (mFpInput) {
+            fclose(mFpInput);
+            mFpInput = nullptr;
+        }
+    }
+
+    FILE *mFpInput;
+    int32_t DecodeFrames(int16_t *decoderCookie, void *decoderBuf, SNDFILE *outFileHandle,
+                         int32_t frameCount = INT32_MAX);
+    SNDFILE *openOutputFile(SF_INFO *sfInfo);
+};
+
+SNDFILE *AmrwbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
+    memset(sfInfo, 0, sizeof(SF_INFO));
+    sfInfo->channels = kChannels;
+    sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo->samplerate = kSampleRate;
+    SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
+    return outFileHandle;
+}
+
+int32_t AmrwbDecoderTest::DecodeFrames(int16_t *decoderCookie, void *decoderBuf,
+                                       SNDFILE *outFileHandle, int32_t frameCount) {
+    uint8_t inputBuf[kInputBufferSize];
+    int16_t inputSampleBuf[kMaxSourceDataUnitSize];
+    int16_t outputBuf[kOutputBufferSize];
+    RX_State_wb rx_state{};
+
+    while (frameCount > 0) {
+        uint8_t modeByte;
+        int32_t bytesRead = fread(&modeByte, 1, 1, mFpInput);
+        if (bytesRead != 1) break;
+
+        int16 mode = ((modeByte >> 3) & 0x0f);
+        if (mode >= 9) {
+            // Produce silence for comfort noise, speech lost and no data.
+            int32_t outputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+            memset(outputBuf, 0, outputBufferSize);
+        } else {
+            // Read rest of the frame.
+            int32_t frameSize = kFrameSizes[mode];
+            // AMR-WB file format cannot have mode 10, 11, 12 and 13.
+            if (frameSize < 0) {
+                ALOGE("Illegal frame mode");
+                return -1;
+            }
+            bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
+            if (bytesRead != frameSize) break;
+
+            int16 frameMode = mode;
+            int16 frameType;
+            mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, 1, &rx_state);
+
+            int16_t numSamplesOutput;
+            pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, decoderBuf,
+                            frameType, decoderCookie);
+            if (numSamplesOutput != kSamplesPerFrame) {
+                ALOGE("Failed to decode the input file");
+                return -1;
+            }
+            for (int count = 0; count < kSamplesPerFrame; ++count) {
+                /* Delete the 2 LSBs (14-bit output) */
+                outputBuf[count] &= 0xfffc;
+            }
+        }
+        sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame / kChannels);
+        frameCount--;
+    }
+    return 0;
+}
+
+TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
+    uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    // Create AMR-WB decoder instance.
+    void *amrHandle = nullptr;
+    int16_t *decoderCookie;
+    for (int count = 0; count < kMaxCount; count++) {
+        pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+        ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
+        ALOGV("Decoder created successfully");
+    }
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(AmrwbDecoderTest, DecodeTest) {
+    uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    void *amrHandle = nullptr;
+    int16_t *decoderCookie;
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
+
+    string inputFile = gEnv->getRes() + GetParam();
+    mFpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
+    uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    void *amrHandle = nullptr;
+    int16_t *decoderCookie;
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
+
+    string inputFile = gEnv->getRes() + GetParam();
+    mFpInput = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    // Decode 150 frames first
+    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    // Reset Decoder
+    pvDecoder_AmrWb_Reset(decoderBuf, 1);
+
+    // Start decoding again
+    decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
+
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
+                         ::testing::Values(("bbb_amrwb_1ch_14kbps_16000hz.amrwb"),
+                                           ("bbb_16000hz_1ch_9kbps_amrwb_30sec.amrwb")));
+
+int main(int argc, char **argv) {
+    gEnv = new AmrwbDecTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/amrwb/test/Android.bp b/media/libstagefright/codecs/amrwb/test/Android.bp
new file mode 100644
index 0000000..968215a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/Android.bp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "AmrwbDecoderTest",
+    gtest: true,
+
+    srcs: [
+        "AmrwbDecoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_amrwbdec",
+        "libsndfile",
+        "libaudioutils",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/amrwb/test/AndroidTest.xml b/media/libstagefright/codecs/amrwb/test/AndroidTest.xml
new file mode 100644
index 0000000..e211a1f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Amr-wb Decoder unit test">
+    <option name="test-suite-tag" value="AmrwbDecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="AmrwbDecoderTest->/data/local/tmp/AmrwbDecoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true"
+            value="/data/local/tmp/AmrwbDecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="AmrwbDecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/AmrwbDecoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/amrwb/test/README.md b/media/libstagefright/codecs/amrwb/test/README.md
new file mode 100644
index 0000000..a9d5c06
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### AMR-WB Decoder :
+The Amr-Wb Decoder Test Suite validates the amrwb decoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m AmrwbDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/AmrwbDecoderTest/AmrwbDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/AmrwbDecoderTest/AmrwbDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push AmrwbDecoderTestRes/. /data/local/tmp/
+```
+
+usage: AmrwbDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/AmrwbDecoderTest -P /data/local/tmp/AmrwbDecoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest AmrwbDecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
index b04bafd..1bc90e8 100644
--- a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
+++ b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
@@ -110,6 +110,7 @@
 
     // Decode loop.
     int retVal = EXIT_SUCCESS;
+    RX_State_wb rx_state{};
     while (1) {
         // Read mode.
         uint8_t modeByte;
@@ -134,7 +135,6 @@
             if (bytesRead != frameSize) break;
 
             int16 frameType, frameMode;
-            RX_State_wb rx_state;
             frameMode = mode;
             mime_unsorting(
                     (uint8_t *)inputBuf,
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index 084be0a..64f302c 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_amrwbenc",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/autocorr.c",
diff --git a/media/libstagefright/codecs/amrwbenc/test/AmrwbEncTestEnvironment.h b/media/libstagefright/codecs/amrwbenc/test/AmrwbEncTestEnvironment.h
new file mode 100644
index 0000000..08ada66
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/AmrwbEncTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __AMRWBENC_TEST_ENVIRONMENT_H__
+#define __AMRWBENC_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class AmrwbEncTestEnvironment : public ::testing::Environment {
+  public:
+    AmrwbEncTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int AmrwbEncTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __AMRWBENC_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.cpp b/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.cpp
new file mode 100644
index 0000000..1a6ee27
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2019 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 "AmrwbEncoderTest"
+
+#include <utils/Log.h>
+
+#include <stdio.h>
+
+#include "cmnMemory.h"
+#include "voAMRWB.h"
+
+#include "AmrwbEncTestEnvironment.h"
+
+#define OUTPUT_FILE "/data/local/tmp/amrwbEncode.out"
+#define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n"
+
+constexpr int32_t kInputBufferSize = 640;
+constexpr int32_t kOutputBufferSize = 1024;
+
+static AmrwbEncTestEnvironment *gEnv = nullptr;
+
+class AmrwbEncoderTest : public ::testing::TestWithParam<tuple<string, int32_t, VOAMRWBFRAMETYPE>> {
+  public:
+    AmrwbEncoderTest() : mEncoderHandle(nullptr) {
+        tuple<string, int32_t, VOAMRWBFRAMETYPE> params = GetParam();
+        mInputFile = gEnv->getRes() + get<0>(params);
+        mMode = get<1>(params);
+        mFrameType = get<2>(params);
+        mMemOperator.Alloc = cmnMemAlloc;
+        mMemOperator.Copy = cmnMemCopy;
+        mMemOperator.Free = cmnMemFree;
+        mMemOperator.Set = cmnMemSet;
+        mMemOperator.Check = cmnMemCheck;
+
+        mUserData.memflag = VO_IMF_USERMEMOPERATOR;
+        mUserData.memData = (VO_PTR)(&mMemOperator);
+    }
+
+    ~AmrwbEncoderTest() {
+        if (mEncoderHandle) {
+            mEncoderHandle = nullptr;
+        }
+    }
+
+    string mInputFile;
+    unsigned char mOutputBuf[kOutputBufferSize];
+    unsigned char mInputBuf[kInputBufferSize];
+    VOAMRWBFRAMETYPE mFrameType;
+    VO_AUDIO_CODECAPI mApiHandle;
+    VO_MEM_OPERATOR mMemOperator;
+    VO_CODEC_INIT_USERDATA mUserData;
+    VO_HANDLE mEncoderHandle;
+    int32_t mMode;
+};
+
+TEST_P(AmrwbEncoderTest, CreateAmrwbEncoderTest) {
+    int32_t status = voGetAMRWBEncAPI(&mApiHandle);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to get api handle";
+
+    status = mApiHandle.Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &mUserData);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to init AMRWB encoder";
+
+    status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &mFrameType);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder frame type to " << mFrameType;
+
+    status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mMode);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder mode to %d" << mMode;
+    ALOGV("AMR-WB encoder created successfully");
+
+    status = mApiHandle.Uninit(mEncoderHandle);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to delete AMRWB encoder";
+    ALOGV("AMR-WB encoder deleted successfully");
+}
+
+TEST_P(AmrwbEncoderTest, AmrwbEncodeTest) {
+    VO_CODECBUFFER inData;
+    VO_CODECBUFFER outData;
+    VO_AUDIO_OUTPUTINFO outFormat;
+
+    FILE *fpInput = fopen(mInputFile.c_str(), "rb");
+    ASSERT_NE(fpInput, nullptr) << "Error opening input file " << mInputFile;
+
+    FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
+    ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
+
+    uint32_t status = voGetAMRWBEncAPI(&mApiHandle);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to get api handle";
+
+    status = mApiHandle.Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &mUserData);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to init AMRWB encoder";
+
+    status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &mFrameType);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder frame type to " << mFrameType;
+
+    status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mMode);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder mode to " << mMode;
+
+    if (mFrameType == VOAMRWB_RFC3267) {
+        /* write RFC3267 Header info to indicate single channel AMR file storage format */
+        int32_t size = strlen(VOAMRWB_RFC3267_HEADER_INFO);
+        memcpy(mOutputBuf, VOAMRWB_RFC3267_HEADER_INFO, size);
+        fwrite(mOutputBuf, 1, size, fpOutput);
+    }
+
+    int32_t frameNum = 0;
+    while (1) {
+        int32_t buffLength =
+                (int32_t)fread(mInputBuf, sizeof(signed char), kInputBufferSize, fpInput);
+
+        if (buffLength == 0 || feof(fpInput)) break;
+        ASSERT_EQ(buffLength, kInputBufferSize) << "Error in reading input file";
+
+        inData.Buffer = (unsigned char *)mInputBuf;
+        inData.Length = buffLength;
+        outData.Buffer = mOutputBuf;
+        status = mApiHandle.SetInputData(mEncoderHandle, &inData);
+        ASSERT_EQ(status, VO_ERR_NONE) << "Failed to setup Input data";
+
+        do {
+            status = mApiHandle.GetOutputData(mEncoderHandle, &outData, &outFormat);
+            ASSERT_NE(status, VO_ERR_LICENSE_ERROR) << "Failed to encode the file";
+            if (status == 0) {
+                frameNum++;
+                fwrite(outData.Buffer, 1, outData.Length, fpOutput);
+                fflush(fpOutput);
+            }
+        } while (status != VO_ERR_INPUT_BUFFER_SMALL);
+    }
+
+    ALOGV("Number of frames processed: %d", frameNum);
+    status = mApiHandle.Uninit(mEncoderHandle);
+    ASSERT_EQ(status, VO_ERR_NONE) << "Failed to delete AMRWB encoder";
+
+    if (fpInput) {
+        fclose(fpInput);
+    }
+    if (fpOutput) {
+        fclose(fpOutput);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        AmrwbEncoderTestAll, AmrwbEncoderTest,
+        ::testing::Values(
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_DEFAULT),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_ITU),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_RFC3267),
+                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_RFC3267)));
+
+int main(int argc, char **argv) {
+    gEnv = new AmrwbEncTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/amrwbenc/test/Android.bp b/media/libstagefright/codecs/amrwbenc/test/Android.bp
new file mode 100644
index 0000000..7042bc5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "AmrwbEncoderTest",
+    gtest: true,
+
+    srcs: [
+        "AmrwbEncoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_enc_common",
+        "libstagefright_amrwbenc",
+        "libaudioutils",
+        "libsndfile",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml b/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml
new file mode 100644
index 0000000..46f147c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Amr-wb Encoder unit test">
+    <option name="test-suite-tag" value="AmrwbEncoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="AmrwbEncoderTest->/data/local/tmp/AmrwbEncoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true"
+            value="/data/local/tmp/AmrwbEncoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="AmrwbEncoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/AmrwbEncoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/amrwbenc/test/README.md b/media/libstagefright/codecs/amrwbenc/test/README.md
new file mode 100644
index 0000000..78762cb
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### AMR-WB Encoder :
+The Amr-Wb Encoder Test Suite validates the amrwb encoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m AmrwbEncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/AmrwbEncoderTest/AmrwbEncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/AmrwbEncoderTest/AmrwbEncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push AmrwbEncoderTestRes/. /data/local/tmp/
+```
+
+usage: AmrwbEncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/AmrwbEncoderTest -P /data/local/tmp/AmrwbEncoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest AmrwbEncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/libstagefright/codecs/common/Android.bp
index c5a076a..260a60a 100644
--- a/media/libstagefright/codecs/common/Android.bp
+++ b/media/libstagefright/codecs/common/Android.bp
@@ -1,6 +1,7 @@
 cc_library {
     name: "libstagefright_enc_common",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: ["cmnMemory.c"],
 
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index d7d871a..f35bce1 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -15,8 +15,10 @@
     },
 
     header_libs: ["libbase_headers"],
-    static_libs: [
+    shared_libs: [
         "libaudioutils",
+    ],
+    static_libs: [
         "libFLAC",
     ],
 }
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 3add006..078c8e3 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -399,29 +399,31 @@
             mEncoderWriteData = true;
             mEncoderReturnedEncodedData = false;
             mEncoderReturnedNbBytes = 0;
-            mCurrentInputTimeStamp = inHeader->nTimeStamp;
+            if (inHeader->nFilledLen) {
+                mCurrentInputTimeStamp = inHeader->nTimeStamp;
 
-            const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
-            const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
+                const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
+                const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
 
-            if (inputFloat) {
-                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
-                const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
-                 memcpy_to_q8_23_from_float_with_clamp(
-                         mInputBufferPcm32, pcmFloat, nbInputSamples);
-            } else {
-                // note nbInputSamples may be 2x as large for pcm16 data.
-                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
-                const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
-                for (unsigned i = 0; i < nbInputSamples; ++i) {
-                    mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+                if (inputFloat) {
+                    CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
+                    const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
+                     memcpy_to_q8_23_from_float_with_clamp(
+                             mInputBufferPcm32, pcmFloat, nbInputSamples);
+                } else {
+                    // note nbInputSamples may be 2x as large for pcm16 data.
+                    CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
+                    const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
+                    for (unsigned i = 0; i < nbInputSamples; ++i) {
+                        mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+                    }
                 }
+                ALOGV(" about to encode %u samples per channel", nbInputFrames);
+                ok = FLAC__stream_encoder_process_interleaved(
+                                mFlacStreamEncoder,
+                                mInputBufferPcm32,
+                                nbInputFrames /*samples per channel*/ );
             }
-            ALOGV(" about to encode %u samples per channel", nbInputFrames);
-            ok = FLAC__stream_encoder_process_interleaved(
-                            mFlacStreamEncoder,
-                            mInputBufferPcm32,
-                            nbInputFrames /*samples per channel*/ );
 
             inInfo->mOwnedByUs = false;
             inQueue.erase(inQueue.begin());
@@ -434,7 +436,15 @@
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 
         if (ok) {
-            if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) {
+            ALOGV("encoded %d, bytes %lld, eos %d", mEncoderReturnedEncodedData,
+                  (long long )mEncoderReturnedNbBytes, mSawInputEOS);
+            if (mSawInputEOS && !mEncoderReturnedEncodedData) {
+                ALOGV("finishing encoder");
+                mSentOutputEOS = true;
+                FLAC__stream_encoder_finish(mFlacStreamEncoder);
+                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+            }
+            if (mSawInputEOS || mEncoderReturnedEncodedData) {
                 ALOGV(" dequeueing buffer on output port after writing data");
                 outInfo->mOwnedByUs = false;
                 outQueue.erase(outQueue.begin());
@@ -442,23 +452,6 @@
                 notifyFillBufferDone(outHeader);
                 outHeader = NULL;
                 mEncoderReturnedEncodedData = false;
-            } else {
-                ALOGV(" encoder process_interleaved returned without data to write");
-                if (mSawInputEOS) {
-                    ALOGV("finishing encoder");
-                    mSentOutputEOS = true;
-                    FLAC__stream_encoder_finish(mFlacStreamEncoder);
-                    if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) {
-                        ALOGV(" dequeueing residual buffer on output port after writing data");
-                        outInfo->mOwnedByUs = false;
-                        outQueue.erase(outQueue.begin());
-                        outInfo = NULL;
-                        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
-                        notifyFillBufferDone(outHeader);
-                        outHeader = NULL;
-                        mEncoderReturnedEncodedData = false;
-                    }
-                }
             }
         } else {
             ALOGE(" error encountered during encoding");
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index 6b45ea2..4303565 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -1,6 +1,11 @@
 cc_library_static {
     name: "libstagefright_m4vh263dec",
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
     shared_libs: ["liblog"],
 
     srcs: [
@@ -47,9 +52,6 @@
     export_include_dirs: ["include"],
 
     cflags: [
-        "-DOSCL_EXPORT_REF=",
-        "-DOSCL_IMPORT_REF=",
-
         "-Werror",
     ],
 
@@ -74,8 +76,6 @@
     local_include_dirs: ["src"],
 
     cflags: [
-        "-DOSCL_EXPORT_REF=",
-        "-DOSCL_IMPORT_REF=",
     ],
 
     static_libs: ["libstagefright_m4vh263dec"],
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h b/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
index 6d4868c..1f404ce 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
@@ -35,6 +35,13 @@
 #define PV_TRUE  1
 #define PV_FALSE 0
 
+#ifndef OSCL_IMPORT_REF
+#define OSCL_IMPORT_REF /* empty */
+#endif
+#ifndef OSCL_EXPORT_REF
+#define OSCL_EXPORT_REF /* empty */
+#endif
+
 /* flag for post-processing  4/25/00 */
 
 #ifdef DEC_NOPOSTPROC
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
new file mode 100644
index 0000000..655491a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "Mpeg4H263DecoderTest",
+    gtest: true,
+
+    srcs: [
+        "Mpeg4H263DecoderTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_m4vh263dec",
+        "libstagefright_foundation",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml
new file mode 100755
index 0000000..47e10ca
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Mpeg4H263 Decoder unit tests">
+    <option name="test-suite-tag" value="Mpeg4H263DecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="Mpeg4H263DecoderTest->/data/local/tmp/Mpeg4H263DecoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder.zip?unzip=true"
+            value="/data/local/tmp/Mpeg4H263DecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="Mpeg4H263DecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263DecoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp b/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
new file mode 100644
index 0000000..967c1ea
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Mpeg4H263DecoderTest"
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <utils/String8.h>
+#include <fstream>
+
+#include <media/stagefright/foundation/AUtils.h>
+#include "mp4dec_api.h"
+
+#include "Mpeg4H263DecoderTestEnvironment.h"
+
+using namespace android;
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/Output.yuv"
+#define CODEC_CONFIG_FLAG 32
+#define SYNC_FRAME 1
+#define MPEG4_MAX_WIDTH 1920
+#define MPEG4_MAX_HEIGHT 1080
+#define H263_MAX_WIDTH 352
+#define H263_MAX_HEIGHT 288
+
+constexpr uint32_t kNumOutputBuffers = 2;
+
+struct FrameInfo {
+    int32_t bytesCount;
+    uint32_t flags;
+    int64_t timestamp;
+};
+
+struct tagvideoDecControls;
+
+static Mpeg4H263DecoderTestEnvironment *gEnv = nullptr;
+
+class Mpeg4H263DecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {
+  public:
+    Mpeg4H263DecoderTest()
+        : mDecHandle(nullptr),
+          mInputBuffer(nullptr),
+          mInitialized(false),
+          mFramesConfigured(false),
+          mNumSamplesOutput(0),
+          mWidth(352),
+          mHeight(288) {
+        memset(mOutputBuffer, 0x0, sizeof(mOutputBuffer));
+    }
+
+    ~Mpeg4H263DecoderTest() {
+        if (mEleStream.is_open()) mEleStream.close();
+        if (mDecHandle) {
+            delete mDecHandle;
+            mDecHandle = nullptr;
+        }
+        if (mInputBuffer) {
+            free(mInputBuffer);
+            mInputBuffer = nullptr;
+        }
+        freeOutputBuffer();
+    }
+
+    status_t initDecoder();
+    void allocOutputBuffer(size_t outputBufferSize);
+    void dumpOutput(ofstream &ostrm);
+    void freeOutputBuffer();
+    void processMpeg4H263Decoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+                                 ifstream &mEleStream, ofstream &ostrm, MP4DecodingMode inputMode);
+    void deInitDecoder();
+
+    ifstream mEleStream;
+    tagvideoDecControls *mDecHandle;
+    char *mInputBuffer;
+    uint8_t *mOutputBuffer[kNumOutputBuffers];
+    bool mInitialized;
+    bool mFramesConfigured;
+    uint32_t mNumSamplesOutput;
+    uint32_t mWidth;
+    uint32_t mHeight;
+};
+
+status_t Mpeg4H263DecoderTest::initDecoder() {
+    if (!mDecHandle) {
+        mDecHandle = new tagvideoDecControls;
+    }
+    if (!mDecHandle) {
+        return NO_MEMORY;
+    }
+    memset(mDecHandle, 0, sizeof(tagvideoDecControls));
+
+    return OK;
+}
+
+void Mpeg4H263DecoderTest::allocOutputBuffer(size_t outputBufferSize) {
+    for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
+        if (!mOutputBuffer[i]) {
+            mOutputBuffer[i] = (uint8_t *)malloc(outputBufferSize);
+            ASSERT_NE(mOutputBuffer[i], nullptr) << "Output buffer allocation failed";
+        }
+    }
+}
+
+void Mpeg4H263DecoderTest::dumpOutput(ofstream &ostrm) {
+    uint8_t *src = mOutputBuffer[mNumSamplesOutput & 1];
+    size_t vStride = align(mHeight, 16);
+    size_t srcYStride = align(mWidth, 16);
+    size_t srcUVStride = srcYStride / 2;
+    uint8_t *srcStart = src;
+
+    /* Y buffer */
+    for (size_t i = 0; i < mHeight; ++i) {
+        ostrm.write(reinterpret_cast<char *>(src), mWidth);
+        src += srcYStride;
+    }
+    /* U buffer */
+    src = srcStart + vStride * srcYStride;
+    for (size_t i = 0; i < mHeight / 2; ++i) {
+        ostrm.write(reinterpret_cast<char *>(src), mWidth / 2);
+        src += srcUVStride;
+    }
+    /* V buffer */
+    src = srcStart + vStride * srcYStride * 5 / 4;
+    for (size_t i = 0; i < mHeight / 2; ++i) {
+        ostrm.write(reinterpret_cast<char *>(src), mWidth / 2);
+        src += srcUVStride;
+    }
+}
+
+void Mpeg4H263DecoderTest::freeOutputBuffer() {
+    for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
+        if (mOutputBuffer[i]) {
+            free(mOutputBuffer[i]);
+            mOutputBuffer[i] = nullptr;
+        }
+    }
+}
+
+void Mpeg4H263DecoderTest::processMpeg4H263Decoder(vector<FrameInfo> Info, int32_t offset,
+                                                   int32_t range, ifstream &mEleStream,
+                                                   ofstream &ostrm, MP4DecodingMode inputMode) {
+    size_t maxWidth = (inputMode == MPEG4_MODE) ? MPEG4_MAX_WIDTH : H263_MAX_WIDTH;
+    size_t maxHeight = (inputMode == MPEG4_MODE) ? MPEG4_MAX_HEIGHT : H263_MAX_HEIGHT;
+    size_t outputBufferSize = align(maxWidth, 16) * align(maxHeight, 16) * 3 / 2;
+    uint32_t frameIndex = offset;
+    bool status = true;
+    ASSERT_GE(range, 0) << "Invalid range";
+    ASSERT_TRUE(offset >= 0 && offset <= Info.size() - 1) << "Invalid offset";
+    ASSERT_LE(range + offset, Info.size()) << "range+offset can't be greater than the no of frames";
+
+    while (1) {
+        if (frameIndex == Info.size() || frameIndex == (offset + range)) break;
+
+        int32_t bytesCount = Info[frameIndex].bytesCount;
+        ASSERT_GT(bytesCount, 0) << "Size for the memory allocation is negative";
+        mInputBuffer = (char *)malloc(bytesCount);
+        ASSERT_NE(mInputBuffer, nullptr) << "Insufficient memory to read frame";
+        mEleStream.read(mInputBuffer, bytesCount);
+        ASSERT_EQ(mEleStream.gcount(), bytesCount) << "mEleStream.gcount() != bytesCount";
+        static const uint8_t volInfo[] = {0x00, 0x00, 0x01, 0xB0};
+        bool volHeader = memcmp(mInputBuffer, volInfo, 4) == 0;
+        if (volHeader) {
+            PVCleanUpVideoDecoder(mDecHandle);
+            mInitialized = false;
+        }
+
+        if (!mInitialized) {
+            uint8_t *volData[1]{};
+            int32_t volSize = 0;
+
+            uint32_t flags = Info[frameIndex].flags;
+            bool codecConfig = flags == CODEC_CONFIG_FLAG;
+            if (codecConfig || volHeader) {
+                volData[0] = reinterpret_cast<uint8_t *>(mInputBuffer);
+                volSize = bytesCount;
+            }
+
+            status = PVInitVideoDecoder(mDecHandle, volData, &volSize, 1, maxWidth, maxHeight,
+                                        inputMode);
+            ASSERT_TRUE(status) << "PVInitVideoDecoder failed. Unsupported content";
+
+            mInitialized = true;
+            MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle);
+            ASSERT_EQ(inputMode, actualMode)
+                    << "Decoded mode not same as actual mode of the decoder";
+
+            PVSetPostProcType(mDecHandle, 0);
+
+            int32_t dispWidth, dispHeight;
+            PVGetVideoDimensions(mDecHandle, &dispWidth, &dispHeight);
+
+            int32_t bufWidth, bufHeight;
+            PVGetBufferDimensions(mDecHandle, &bufWidth, &bufHeight);
+
+            ASSERT_LE(dispWidth, bufWidth) << "Display width is greater than buffer width";
+            ASSERT_LE(dispHeight, bufHeight) << "Display height is greater than buffer height";
+
+            if (dispWidth != mWidth || dispHeight != mHeight) {
+                mWidth = dispWidth;
+                mHeight = dispHeight;
+                freeOutputBuffer();
+                if (inputMode == H263_MODE) {
+                    PVCleanUpVideoDecoder(mDecHandle);
+
+                    uint8_t *volData[1]{};
+                    int32_t volSize = 0;
+
+                    status = PVInitVideoDecoder(mDecHandle, volData, &volSize, 1, maxWidth,
+                                                maxHeight, H263_MODE);
+                    ASSERT_TRUE(status) << "PVInitVideoDecoder failed for H263";
+                }
+                mFramesConfigured = false;
+            }
+
+            if (codecConfig) {
+                frameIndex++;
+                continue;
+            }
+        }
+
+        uint32_t yFrameSize = sizeof(uint8) * mDecHandle->size;
+        ASSERT_GE(outputBufferSize, yFrameSize * 3 / 2)
+                << "Too small output buffer: " << outputBufferSize << " bytes";
+        ASSERT_NO_FATAL_FAILURE(allocOutputBuffer(outputBufferSize));
+
+        if (!mFramesConfigured) {
+            PVSetReferenceYUV(mDecHandle, mOutputBuffer[1]);
+            mFramesConfigured = true;
+        }
+
+        // Need to check if header contains new info, e.g., width/height, etc.
+        VopHeaderInfo headerInfo;
+        uint32_t useExtTimestamp = 1;
+        int32_t inputSize = (Info)[frameIndex].bytesCount;
+        uint32_t timestamp = frameIndex;
+
+        uint8_t *bitstreamTmp = reinterpret_cast<uint8_t *>(mInputBuffer);
+
+        status = PVDecodeVopHeader(mDecHandle, &bitstreamTmp, &timestamp, &inputSize, &headerInfo,
+                                   &useExtTimestamp, mOutputBuffer[mNumSamplesOutput & 1]);
+        ASSERT_EQ(status, PV_TRUE) << "failed to decode vop header";
+
+        // H263 doesn't have VOL header, the frame size information is in short header, i.e. the
+        // decoder may detect size change after PVDecodeVopHeader.
+        int32_t dispWidth, dispHeight;
+        PVGetVideoDimensions(mDecHandle, &dispWidth, &dispHeight);
+
+        int32_t bufWidth, bufHeight;
+        PVGetBufferDimensions(mDecHandle, &bufWidth, &bufHeight);
+
+        ASSERT_LE(dispWidth, bufWidth) << "Display width is greater than buffer width";
+        ASSERT_LE(dispHeight, bufHeight) << "Display height is greater than buffer height";
+        if (dispWidth != mWidth || dispHeight != mHeight) {
+            mWidth = dispWidth;
+            mHeight = dispHeight;
+        }
+
+        status = PVDecodeVopBody(mDecHandle, &inputSize);
+        ASSERT_EQ(status, PV_TRUE) << "failed to decode video frame No = %d" << frameIndex;
+
+        dumpOutput(ostrm);
+
+        ++mNumSamplesOutput;
+        ++frameIndex;
+    }
+    freeOutputBuffer();
+}
+
+void Mpeg4H263DecoderTest::deInitDecoder() {
+    if (mInitialized) {
+        if (mDecHandle) {
+            PVCleanUpVideoDecoder(mDecHandle);
+            delete mDecHandle;
+            mDecHandle = nullptr;
+        }
+        mInitialized = false;
+    }
+    freeOutputBuffer();
+}
+
+void getInfo(string infoFileName, vector<FrameInfo> &Info) {
+    ifstream eleInfo;
+    eleInfo.open(infoFileName);
+    ASSERT_EQ(eleInfo.is_open(), true) << "Failed to open " << infoFileName;
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) {
+            break;
+        }
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        Info.push_back({bytesCount, flags, timestamp});
+    }
+    if (eleInfo.is_open()) eleInfo.close();
+}
+
+TEST_P(Mpeg4H263DecoderTest, DecodeTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* mode */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open " << get<0>(params);
+
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    vector<FrameInfo> Info;
+    ASSERT_NO_FATAL_FAILURE(getInfo(infoFileName, Info));
+    ASSERT_NE(Info.empty(), true) << "Invalid Info file";
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true) << "Failed to open output stream for " << get<0>(params);
+
+    status_t err = initDecoder();
+    ASSERT_EQ(err, OK) << "initDecoder: failed to create decoder " << err;
+
+    bool isMpeg4 = get<2>(params);
+    MP4DecodingMode inputMode = isMpeg4 ? MPEG4_MODE : H263_MODE;
+    ASSERT_NO_FATAL_FAILURE(
+            processMpeg4H263Decoder(Info, 0, Info.size(), mEleStream, ostrm, inputMode));
+    deInitDecoder();
+    ostrm.close();
+    Info.clear();
+}
+
+TEST_P(Mpeg4H263DecoderTest, FlushTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* mode */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true) << "Failed to open " << get<0>(params);
+
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    vector<FrameInfo> Info;
+    ASSERT_NO_FATAL_FAILURE(getInfo(infoFileName, Info));
+    ASSERT_NE(Info.empty(), true) << "Invalid Info file";
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true) << "Failed to open output stream for " << get<0>(params);
+
+    status_t err = initDecoder();
+    ASSERT_EQ(err, OK) << "initDecoder: failed to create decoder " << err;
+
+    bool isMpeg4 = get<2>(params);
+    MP4DecodingMode inputMode = isMpeg4 ? MPEG4_MODE : H263_MODE;
+    // Number of frames to be decoded before flush
+    int32_t numFrames = Info.size() / 3;
+    ASSERT_NO_FATAL_FAILURE(
+            processMpeg4H263Decoder(Info, 0, numFrames, mEleStream, ostrm, inputMode));
+
+    if (mInitialized) {
+        int32_t status = PVResetVideoDecoder(mDecHandle);
+        ASSERT_EQ(status, PV_TRUE);
+    }
+
+    // Seek to next key frame and start decoding till the end
+    int32_t index = numFrames;
+    bool keyFrame = false;
+    uint32_t flags = 0;
+    while (index < (int32_t)Info.size()) {
+        if (Info[index].flags) flags = 1u << (Info[index].flags - 1);
+        if ((flags & SYNC_FRAME) == SYNC_FRAME) {
+            keyFrame = true;
+            break;
+        }
+        flags = 0;
+        mEleStream.ignore(Info[index].bytesCount);
+        index++;
+    }
+    ALOGV("Index= %d", index);
+    if (keyFrame) {
+        mNumSamplesOutput = 0;
+        ASSERT_NO_FATAL_FAILURE(processMpeg4H263Decoder(Info, index, (int32_t)Info.size() - index,
+                                                        mEleStream, ostrm, inputMode));
+    }
+    deInitDecoder();
+    ostrm.close();
+    Info.clear();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        Mpeg4H263DecoderTestAll, Mpeg4H263DecoderTest,
+        ::testing::Values(make_tuple("swirl_128x96_h263.h263", "swirl_128x96_h263.info", false),
+                          make_tuple("swirl_176x144_h263.h263", "swirl_176x144_h263.info", false),
+                          make_tuple("swirl_352x288_h263.h263", "swirl_352x288_h263.info", false),
+                          make_tuple("bbb_352x288_h263.h263", "bbb_352x288_h263.info", false),
+                          make_tuple("bbb_352x288_mpeg4.m4v", "bbb_352x288_mpeg4.info", true),
+                          make_tuple("swirl_128x128_mpeg4.m4v", "swirl_128x128_mpeg4.info", true),
+                          make_tuple("swirl_130x132_mpeg4.m4v", "swirl_130x132_mpeg4.info", true),
+                          make_tuple("swirl_132x130_mpeg4.m4v", "swirl_132x130_mpeg4.info", true),
+                          make_tuple("swirl_136x144_mpeg4.m4v", "swirl_136x144_mpeg4.info", true),
+                          make_tuple("swirl_144x136_mpeg4.m4v", "swirl_144x136_mpeg4.info", true)));
+
+int main(int argc, char **argv) {
+    gEnv = new Mpeg4H263DecoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD("Decoder Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h b/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
new file mode 100644
index 0000000..f085845
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPEG4_H263_DECODER_TEST_ENVIRONMENT_H__
+#define __MPEG4_H263_DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg4H263DecoderTestEnvironment : public ::testing::Environment {
+  public:
+    Mpeg4H263DecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int Mpeg4H263DecoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __MPEG4_H263_DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/README.md b/media/libstagefright/codecs/m4v_h263/dec/test/README.md
new file mode 100644
index 0000000..7e4aea1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### Mpeg4H263Decoder :
+The Mpeg4H263Decoder Test Suite validates the Mpeg4 and H263 decoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m Mpeg4H263DecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mpeg4H263DecoderTest/Mpeg4H263DecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mpeg4H263DecoderTest/Mpeg4H263DecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg4H263Decoder /data/local/tmp/
+```
+
+usage: Mpeg4H263DecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg4H263DecoderTest -P /data/local/tmp/Mpeg4H263Decoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263DecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index 2738187..b8bc24e 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -1,6 +1,11 @@
 cc_library_static {
     name: "libstagefright_m4vh263enc",
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
 
     srcs: [
         "src/bitstream_io.cpp",
@@ -23,10 +28,6 @@
 
     cflags: [
         "-DBX_RC",
-        "-DOSCL_IMPORT_REF=",
-        "-DOSCL_UNUSED_ARG(x)=(void)(x)",
-        "-DOSCL_EXPORT_REF=",
-
         "-Werror",
     ],
 
@@ -55,9 +56,6 @@
 
     cflags: [
         "-DBX_RC",
-        "-DOSCL_IMPORT_REF=",
-        "-DOSCL_UNUSED_ARG(x)=(void)(x)",
-        "-DOSCL_EXPORT_REF=",
     ],
 
     static_libs: ["libstagefright_m4vh263enc"],
@@ -81,8 +79,6 @@
     local_include_dirs: ["src"],
 
     cflags: [
-        "-DOSCL_EXPORT_REF=",
-        "-DOSCL_IMPORT_REF=",
         "-DBX_RC",
         "-Wall",
         "-Werror",
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
index d5a3ff1..9f824b1 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
@@ -39,6 +39,16 @@
 #define PV_TRUE  1
 #define PV_FALSE 0
 
+#ifndef OSCL_IMPORT_REF
+#define OSCL_IMPORT_REF /* empty */
+#endif
+#ifndef OSCL_EXPORT_REF
+#define OSCL_EXPORT_REF /* empty */
+#endif
+#ifndef OSCL_UNUSED_ARG
+#define OSCL_UNUSED_ARG(x) ((void)(x))
+#endif
+
 typedef enum
 {
     SHORT_HEADER,
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
new file mode 100644
index 0000000..b9a8117
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "Mpeg4H263EncoderTest",
+    gtest: true,
+
+    srcs : [ "Mpeg4H263EncoderTest.cpp" ],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_m4vh263enc",
+    ],
+
+    cflags: [
+        "-DOSCL_IMPORT_REF=",
+        "-Wall",
+        "-Werror",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+            "unsigned-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
new file mode 100644
index 0000000..5218932
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for MPEG4H263 encoder unit tests">
+    <option name="test-suite-tag" value="Mpeg4H263EncoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
+            value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="Mpeg4H263EncoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
new file mode 100644
index 0000000..78c705a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Mpeg4H263EncoderTest"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "mp4enc_api.h"
+
+#include "Mpeg4H263EncoderTestEnvironment.h"
+
+#define ENCODED_FILE "/data/local/tmp/Mpeg4H263Output"
+
+// assuming a worst case compression of 2X
+constexpr int16_t kCompressionRatio = 2;
+constexpr int8_t kIDRFrameRefreshIntervalInSec = 1;
+
+static Mpeg4H263EncoderTestEnvironment *gEnv = nullptr;
+
+class Mpeg4H263EncoderTest
+    : public ::testing::TestWithParam<tuple<string, bool, int32_t, int32_t, float, int32_t>> {
+  private:
+    void initEncoderParams();
+
+  public:
+    Mpeg4H263EncoderTest()
+        : mInputBuffer(nullptr),
+          mOutputBuffer(nullptr),
+          mFpInput(nullptr),
+          mFpOutput(nullptr),
+          mEncodeHandle(nullptr),
+          mEncodeControl(nullptr) {}
+
+    ~Mpeg4H263EncoderTest() {
+        if(mFpInput) {
+            fclose(mFpInput);
+        }
+        if(mFpOutput) {
+            fclose(mFpOutput);
+        }
+        if(mInputBuffer) free(mInputBuffer);
+        if(mOutputBuffer) free(mOutputBuffer);
+        if(mEncodeHandle) free(mEncodeHandle);
+        if(mEncodeControl) free(mEncodeControl);
+    }
+
+    void SetUp() override {
+        tuple<string /* fileName */, bool /* isMpeg4 */, int32_t /* frameWidth */,
+          int32_t /* frameHeight */, float /* frameRate */, int32_t /* bitRate */>
+            params = GetParam();
+        mFileName = gEnv->getRes() + get<0>(params);
+        mIsMpeg4 = get<1>(params);
+        mFrameWidth = get<2>(params);
+        mFrameHeight = get<3>(params);
+        mFrameRate = get<4>(params);
+        mBitRate = get<5>(params);
+
+        ASSERT_TRUE(mFrameWidth % 16 == 0) << "Frame Width should be multiple of 16";
+        ASSERT_TRUE(mFrameHeight % 16 == 0) << "Frame Height should be multiple of 16";
+        ASSERT_LE(mFrameWidth, (mIsMpeg4 ? 720 : 352))
+                << "Frame Width <= 720 for Mpeg4 and <= 352 for H263";
+        ASSERT_LE(mFrameHeight, (mIsMpeg4 ? 480 : 288))
+                << "Frame Height <= 480 for Mpeg4 and <= 288 for H263";
+        ASSERT_LE(mFrameRate, 30) << "Frame rate less than or equal to 30";
+        ASSERT_LE(mBitRate, 2048) << "Bit rate less than or equal to 2048 kbps";
+
+        mOutputBufferSize = ( mFrameWidth * mFrameHeight * 3/2 ) / kCompressionRatio;
+        mEncodeHandle = new VideoEncOptions;
+        ASSERT_NE(mEncodeHandle, nullptr) << "Failed to get Video Encoding options object";
+        memset(mEncodeHandle, 0, sizeof(VideoEncOptions));
+        mEncodeControl = new VideoEncControls;
+        ASSERT_NE(mEncodeControl, nullptr) << "Failed to get Video Encoding control object";
+        memset(mEncodeControl, 0, sizeof(VideoEncControls));
+        ASSERT_NO_FATAL_FAILURE(initEncoderParams())
+                << "Failed to get the default Encoding parameters!";
+    }
+
+    int64_t getTotalFrames();
+    void processEncoder(int32_t);
+    bool mIsMpeg4;
+    int32_t mFrameWidth, mFrameHeight, mBitRate;
+    int64_t mOutputBufferSize;
+    float mFrameRate;
+    string mFileName;
+    uint8_t *mInputBuffer, *mOutputBuffer;
+    FILE *mFpInput, *mFpOutput;
+    VideoEncOptions *mEncodeHandle;
+    VideoEncControls *mEncodeControl;
+};
+
+void Mpeg4H263EncoderTest::initEncoderParams() {
+    bool status = PVGetDefaultEncOption(mEncodeHandle, 0);
+    ASSERT_TRUE(status);
+
+    mEncodeHandle->rcType = VBR_1;
+    mEncodeHandle->vbvDelay = 5.0f;
+    mEncodeHandle->profile_level = CORE_PROFILE_LEVEL2;
+    mEncodeHandle->packetSize = 32;
+    mEncodeHandle->rvlcEnable = PV_OFF;
+    mEncodeHandle->numLayers = 1;
+    mEncodeHandle->timeIncRes = 1000;
+    mEncodeHandle->iQuant[0] = 15;
+    mEncodeHandle->pQuant[0] = 12;
+    mEncodeHandle->quantType[0] = 0;
+    mEncodeHandle->noFrameSkipped = PV_OFF;
+    mEncodeHandle->numIntraMB = 0;
+    mEncodeHandle->sceneDetect = PV_ON;
+    mEncodeHandle->searchRange = 16;
+    mEncodeHandle->mv8x8Enable = PV_OFF;
+    mEncodeHandle->gobHeaderInterval = 0;
+    mEncodeHandle->useACPred = PV_ON;
+    mEncodeHandle->intraDCVlcTh = 0;
+    if(!mIsMpeg4) {
+        mEncodeHandle->encMode = H263_MODE;
+    } else {
+        mEncodeHandle->encMode = COMBINE_MODE_WITH_ERR_RES;
+    }
+    mEncodeHandle->encWidth[0] = mFrameWidth;
+    mEncodeHandle->encHeight[0] = mFrameHeight;
+    mEncodeHandle->encFrameRate[0] = mFrameRate;
+    mEncodeHandle->bitRate[0] = mBitRate * 1024;
+    mEncodeHandle->tickPerSrc = mEncodeHandle->timeIncRes / mFrameRate;
+    if (kIDRFrameRefreshIntervalInSec == 0) {
+        // All I frames.
+        mEncodeHandle->intraPeriod = 1;
+    } else {
+        mEncodeHandle->intraPeriod = (kIDRFrameRefreshIntervalInSec * mFrameRate);
+    }
+}
+
+int64_t Mpeg4H263EncoderTest::getTotalFrames() {
+    int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+    struct stat buf;
+    stat(mFileName.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int64_t totalFrames = (int64_t)(fileSize/frameSize);
+    return totalFrames;
+}
+
+void Mpeg4H263EncoderTest::processEncoder(int32_t numFramesToEncode) {
+    bool status;
+    int64_t numEncodedFrames = 0;
+    int32_t bytesRead;
+    int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+    while(numFramesToEncode != 0) {
+        bytesRead = fread(mInputBuffer, 1, frameSize, mFpInput);
+        // End of file.
+        if (bytesRead != frameSize) {
+            break;
+        }
+
+        VideoEncFrameIO videoIn, videoOut;
+        videoIn.height = mFrameHeight;
+        videoIn.pitch = mFrameWidth;
+        videoIn.timestamp = (numEncodedFrames * 1000) / mFrameRate;  // in ms.
+        videoIn.yChan = mInputBuffer;
+        videoIn.uChan = videoIn.yChan + videoIn.height * videoIn.pitch;
+        videoIn.vChan = videoIn.uChan + ((videoIn.height * videoIn.pitch) >> 2);
+        uint32_t modTimeMs = 0;
+        int32_t dataLength = mOutputBufferSize;
+        int32_t nLayer = 0;
+        status = PVEncodeVideoFrame(mEncodeControl, &videoIn, &videoOut, &modTimeMs, mOutputBuffer,
+                                    &dataLength, &nLayer);
+        ASSERT_TRUE(status) << "Failed to Encode: " << mFileName;
+
+        MP4HintTrack hintTrack;
+        status = PVGetHintTrack(mEncodeControl, &hintTrack);
+        ASSERT_TRUE(status) << "Failed to get hint track!";
+        UChar *overrunBuffer = PVGetOverrunBuffer(mEncodeControl);
+        ASSERT_EQ(overrunBuffer, nullptr) << "Overrun of buffer!";
+
+        int64_t numBytes = fwrite(mOutputBuffer, 1, dataLength, mFpOutput);
+        ASSERT_EQ(numBytes, dataLength) << "Failed to write to the output file!";
+        numEncodedFrames++;
+        numFramesToEncode--;
+    }
+}
+
+TEST_P(Mpeg4H263EncoderTest, EncodeTest) {
+    mInputBuffer = (uint8_t *)malloc((mFrameWidth * mFrameWidth * 3) / 2);
+    ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate the input buffer!";
+
+    mOutputBuffer = (uint8_t *)malloc(mOutputBufferSize);
+    ASSERT_NE(mOutputBuffer, nullptr) << "Failed to allocate the output buffer!";
+
+    mFpInput = fopen(mFileName.c_str(), "rb");
+    ASSERT_NE(mFpInput, nullptr) << "Failed to open the input file: " << mFileName;
+
+    mFpOutput = fopen(ENCODED_FILE, "wb");
+    ASSERT_NE(mFpOutput, nullptr) << "Failed to open the output file:" << ENCODED_FILE;
+
+    bool status = PVInitVideoEncoder(mEncodeControl, mEncodeHandle);
+    ASSERT_TRUE(status) << "Failed to initialize the encoder!";
+
+    // Get VOL header.
+    int32_t size = mOutputBufferSize;
+    status = PVGetVolHeader(mEncodeControl, mOutputBuffer, &size, 0);
+    ASSERT_TRUE(status) << "Failed to get the VOL header!";
+
+    // Write the VOL header on the first frame.
+    int32_t numBytes = fwrite(mOutputBuffer, 1, size, mFpOutput);
+    ASSERT_EQ(numBytes, size) << "Failed to write the VOL header!";
+
+    int64_t totalFrames = getTotalFrames();
+    ASSERT_NO_FATAL_FAILURE(processEncoder(totalFrames)) << "Failed to Encode: " << mFileName;
+    status = PVCleanUpVideoEncoder(mEncodeControl);
+    ASSERT_TRUE(status) << "Failed to clean up the encoder resources!";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        EncodeTest, Mpeg4H263EncoderTest,
+        ::testing::Values(
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 352, 288, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 352, 288, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 176, 144, 25, 1024),
+                make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 176, 144, 25, 1024),
+                make_tuple("football_qvga.yuv", false, 352, 288, 25, 1024),
+                make_tuple("football_qvga.yuv", true, 352, 288, 25, 1024),
+                make_tuple("football_qvga.yuv", false, 176, 144, 30, 1024),
+                make_tuple("football_qvga.yuv", true, 176, 144, 30, 1024)));
+
+int32_t main(int argc, char **argv) {
+    gEnv = new Mpeg4H263EncoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    uint8_t status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGI("Encoder Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
new file mode 100644
index 0000000..7ee36e0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+#define __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg4H263EncoderTestEnvironment : public::testing::Environment {
+  public:
+    Mpeg4H263EncoderTestEnvironment() : res("/data/local/tmp/Mpeg4H263EncoderTest/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int Mpeg4H263EncoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/README.md b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
new file mode 100644
index 0000000..25de878
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
@@ -0,0 +1,38 @@
+## Media Testing ##
+---
+
+#### Mpeg4H263Encoder :
+The Mpeg4H263Encoder Test Suite validates the Mpeg4 and H263 encoder available in libstagefright.
+Run the following steps to build the test suite:
+```
+m Mpeg4H263EncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip ) Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg4H263Encoder/. /data/local/tmp/
+```
+
+usage: Mpeg4H263EncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg4H263EncoderTest -P /data/local/tmp/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263EncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index b630524..96106f1 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_mp3dec",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: [
         "src/pvmp3_normalize.cpp",
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 80083f7..b5d32ed 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -307,6 +307,20 @@
 
             if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                 mSawInputEos = true;
+                if (mIsFirst && !inHeader->nFilledLen) {
+                     ALOGV("empty first EOS");
+                     outHeader->nFilledLen = 0;
+                     outHeader->nTimeStamp = inHeader->nTimeStamp;
+                     outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+                     mSignalledOutputEos = true;
+                     outInfo->mOwnedByUs = false;
+                     outQueue.erase(outQueue.begin());
+                     notifyFillBufferDone(outHeader);
+                     inInfo->mOwnedByUs = false;
+                     inQueue.erase(inQueue.begin());
+                     notifyEmptyBufferDone(inHeader);
+                     return;
+                }
             }
 
             mConfig->pInputBuffer =
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
index adb0dd4..f9d91b1 100644
--- a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
@@ -44,7 +44,7 @@
 #endif
 
 #include "pvmp3_audio_type_defs.h"
-#define Qfmt_31(a)   (Int32)((float)(a)*0x7FFFFFFF)
+#define Qfmt_31(a)   (Int32)((float)(a)*(float)0x7FFFFFFF)
 
 #define Qfmt15(x)   (Int16)((x)*((Int32)1<<15) + ((x)>=0?0.5F:-0.5F))
 
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
index af738ba..6c8102b 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
@@ -169,7 +169,7 @@
 
     int32 i, j;
 
-    *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)(0x7FFFFFFF / (float)18 - 1.0f)) >> 15;
+    *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)((float)0x7FFFFFFF / (float)18 - 1.0f)) >> 15;
 
 
     if (gr_info->window_switching_flag &&  gr_info->block_type == 2)
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
index bbb247d..9cd0e91 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
@@ -77,7 +77,7 @@
 ; Include all pre-processor statements here. Include conditional
 ; compile variables also.
 ----------------------------------------------------------------------------*/
-#define Qfmt31(a)   (int32)((a)*(0x7FFFFFFF))
+#define Qfmt31(a)   (int32)((a)*((float)0x7FFFFFFF))
 
 #define cos_pi_9    Qfmt31( 0.93969262078591f)
 #define cos_2pi_9   Qfmt31( 0.76604444311898f)
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index df6cd03..a5c7f5e 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -659,20 +659,12 @@
     huffcodetab       *pHuff;
 
     pVars = (tmp3dec_file *)pMem;
-
-    pVars->num_channels = 0;
+    memset(pVars, 0, sizeof(*pVars));
 
     pExt->totalNumberOfBitsUsed = 0;
     pExt->inputBufferCurrentLength = 0;
     pExt->inputBufferUsedLength    = 0;
 
-    pVars->mainDataStream.offset = 0;
-
-    pv_memset((void*)pVars->mainDataBuffer,
-              0,
-              BUFSIZE*sizeof(*pVars->mainDataBuffer));
-
-
     pVars->inputStream.pBuffer = pExt->pInputBuffer;
 
     /*
diff --git a/media/libstagefright/codecs/mp3dec/test/Android.bp b/media/libstagefright/codecs/mp3dec/test/Android.bp
new file mode 100644
index 0000000..0ff8b12
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "Mp3DecoderTest",
+    gtest: true,
+
+    srcs: [
+        "mp3reader.cpp",
+        "Mp3DecoderTest.cpp",
+    ],
+
+    static_libs: [
+        "libstagefright_mp3dec",
+        "libsndfile",
+        "libaudioutils",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
new file mode 100644
index 0000000..7ff9732
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for Mp3 Decoder unit test">
+    <option name="test-suite-tag" value="Mp3DecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest.zip?unzip=true"
+            value="/data/local/tmp/Mp3DecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="Mp3DecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/Mp3DecoderTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
new file mode 100644
index 0000000..99553ec
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2019 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 "Mp3DecoderTest"
+
+#include <utils/Log.h>
+
+#include <audio_utils/sndfile.h>
+#include <stdio.h>
+
+#include "mp3reader.h"
+#include "pvmp3decoder_api.h"
+
+#include "Mp3DecoderTestEnvironment.h"
+
+#define OUTPUT_FILE "/data/local/tmp/mp3Decode.out"
+
+constexpr int32_t kInputBufferSize = 1024 * 10;
+constexpr int32_t kOutputBufferSize = 4608 * 2;
+constexpr int32_t kMaxCount = 10;
+constexpr int32_t kNumFrameReset = 150;
+
+static Mp3DecoderTestEnvironment *gEnv = nullptr;
+
+class Mp3DecoderTest : public ::testing::TestWithParam<string> {
+  public:
+    Mp3DecoderTest() : mConfig(nullptr) {}
+
+    ~Mp3DecoderTest() {
+        if (mConfig) {
+            delete mConfig;
+            mConfig = nullptr;
+        }
+    }
+
+    virtual void SetUp() override {
+        mConfig = new tPVMP3DecoderExternal{};
+        ASSERT_NE(mConfig, nullptr) << "Failed to initialize config. No Memory available";
+        mConfig->equalizerType = flat;
+        mConfig->crcEnabled = false;
+    }
+
+    tPVMP3DecoderExternal *mConfig;
+    Mp3Reader mMp3Reader;
+
+    ERROR_CODE DecodeFrames(void *decoderbuf, SNDFILE *outFileHandle, SF_INFO sfInfo,
+                            int32_t frameCount = INT32_MAX);
+    SNDFILE *openOutputFile(SF_INFO *sfInfo);
+};
+
+ERROR_CODE Mp3DecoderTest::DecodeFrames(void *decoderBuf, SNDFILE *outFileHandle, SF_INFO sfInfo,
+                                        int32_t frameCount) {
+    uint8_t inputBuf[kInputBufferSize];
+    int16_t outputBuf[kOutputBufferSize];
+    uint32_t bytesRead;
+    ERROR_CODE decoderErr;
+    while (frameCount > 0) {
+        bool success = mMp3Reader.getFrame(inputBuf, &bytesRead);
+        if (!success) {
+            break;
+        }
+        mConfig->inputBufferCurrentLength = bytesRead;
+        mConfig->inputBufferMaxLength = 0;
+        mConfig->inputBufferUsedLength = 0;
+        mConfig->pInputBuffer = inputBuf;
+        mConfig->pOutputBuffer = outputBuf;
+        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+        decoderErr = pvmp3_framedecoder(mConfig, decoderBuf);
+        if (decoderErr != NO_DECODING_ERROR) break;
+        sf_writef_short(outFileHandle, outputBuf, mConfig->outputFrameSize / sfInfo.channels);
+        frameCount--;
+    }
+    return decoderErr;
+}
+
+SNDFILE *Mp3DecoderTest::openOutputFile(SF_INFO *sfInfo) {
+    memset(sfInfo, 0, sizeof(SF_INFO));
+    sfInfo->channels = mMp3Reader.getNumChannels();
+    sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo->samplerate = mMp3Reader.getSampleRate();
+    SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
+    return outFileHandle;
+}
+
+TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+    for (int count = 0; count < kMaxCount; count++) {
+        pvmp3_InitDecoder(mConfig, decoderBuf);
+        ALOGV("Decoder created successfully");
+    }
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(Mp3DecoderTest, DecodeTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    pvmp3_InitDecoder(mConfig, decoderBuf);
+    ALOGV("Decoder created successfully");
+    string inputFile = gEnv->getRes() + GetParam();
+    bool status = mMp3Reader.init(inputFile.c_str());
+    ASSERT_TRUE(status) << "Unable to initialize the mp3Reader";
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    mMp3Reader.close();
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+TEST_P(Mp3DecoderTest, ResetDecoderTest) {
+    size_t memRequirements = pvmp3_decoderMemRequirements();
+    ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
+    void *decoderBuf = malloc(memRequirements);
+    ASSERT_NE(decoderBuf, nullptr)
+            << "Failed to allocate decoder memory of size " << memRequirements;
+
+    pvmp3_InitDecoder(mConfig, decoderBuf);
+    ALOGV("Decoder created successfully.");
+    string inputFile = gEnv->getRes() + GetParam();
+    bool status = mMp3Reader.init(inputFile.c_str());
+    ASSERT_TRUE(status) << "Unable to initialize the mp3Reader";
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    SNDFILE *outFileHandle = openOutputFile(&sfInfo);
+    ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
+
+    ERROR_CODE decoderErr;
+    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    pvmp3_resetDecoder(decoderBuf);
+    // Decode the same file.
+    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
+    ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
+    ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
+
+    mMp3Reader.close();
+    sf_close(outFileHandle);
+    if (decoderBuf) {
+        free(decoderBuf);
+        decoderBuf = nullptr;
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
+                         ::testing::Values(("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3"),
+                                           ("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3"),
+                                           ("bbb_mp3_stereo_192kbps_48000hz.mp3")));
+
+int main(int argc, char **argv) {
+    gEnv = new Mp3DecoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
new file mode 100644
index 0000000..a54b34c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __MP3DECODER_TEST_ENVIRONMENT_H__
+#define __MP3DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mp3DecoderTestEnvironment : public ::testing::Environment {
+  public:
+    Mp3DecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int Mp3DecoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __MP3DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/mp3dec/test/README.md b/media/libstagefright/codecs/mp3dec/test/README.md
new file mode 100644
index 0000000..f59fec7
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/README.md
@@ -0,0 +1,39 @@
+## Media Testing ##
+---
+#### Mp3Decoder :
+The Mp3Decoder Test Suite validates the mp3decoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m Mp3DecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mp3DecoderTest/Mp3DecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mp3DecoderTest/Mp3DecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest.zip). Download, unzip and push these files into device for testing.
+
+```
+adb push Mp3DecoderTestRes/. /data/local/tmp/
+```
+
+usage: Mp3DecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mp3DecoderTest -P /data/local/tmp/Mp3DecoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mp3DecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index cd69e0d..705e554 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -21,4 +21,5 @@
     },
 
     shared_libs: ["libvpx"],
+    header_libs: ["libbase_headers"],
 }
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 1293a74..08e20cc 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -572,16 +572,17 @@
 }
 
 void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
-    if (portIndex == 0 && mState != NULL) {
-        // Make sure that the next buffer output does not still
-        // depend on fragments from the last one decoded.
-
+    if (portIndex == 0) {
         mInputBufferCount = 0;
         mNumFramesOutput = 0;
         mSawInputEos = false;
         mSignalledOutputEos = false;
         mNumFramesLeftOnPage = -1;
-        vorbis_dsp_restart(mState);
+        if (mState != NULL) {
+            // Make sure that the next buffer output does not still
+            // depend on fragments from the last one decoded.
+            vorbis_dsp_restart(mState);
+        }
     }
 }
 
@@ -603,6 +604,7 @@
     mSawInputEos = false;
     mSignalledOutputEos = false;
     mSignalledError = false;
+    mNumFramesLeftOnPage = -1;
     mOutputPortSettingsChange = NONE;
 }
 
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index da86758..87e8fd4 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -1426,75 +1426,90 @@
     RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
 
     UWORD32 ui_exec_done;
+    WORD32 i_num_preroll = 0;
     /* Checking for end of processing */
     err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DONE_QUERY,
                                 &ui_exec_done);
     RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DONE_QUERY");
 
-#ifdef ENABLE_MPEG_D_DRC
+    err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
+                              IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES,
+                              &i_num_preroll);
+
+    RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GET_NUM_PRE_ROLL_FRAMES");
     {
-        if (ui_exec_done != 1) {
-            VOID* p_array;        // ITTIAM:buffer to handle gain payload
-            WORD32 buf_size = 0;  // ITTIAM:gain payload length
-            WORD32 bit_str_fmt = 1;
-            WORD32 gain_stream_flag = 1;
+        int32_t pi_preroll_frame_offset = 0;
+        do {
+#ifdef ENABLE_MPEG_D_DRC
+            if (ui_exec_done != 1) {
+                VOID* p_array;        // ITTIAM:buffer to handle gain payload
+                WORD32 buf_size = 0;  // ITTIAM:gain payload length
+                WORD32 bit_str_fmt = 1;
+                WORD32 gain_stream_flag = 1;
 
-            err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
-                                        IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size);
-            RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN");
+                err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
+                                            IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size);
+                RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN");
 
-            err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
-                                        IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array);
-            RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF");
+                err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
+                                            IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array);
+                RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF");
 
-            if (buf_size > 0) {
-                /*Set bitstream_split_format */
-                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
-                                          IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
-                RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+                if (buf_size > 0) {
+                    /*Set bitstream_split_format */
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
+                                              IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
 
-                memcpy(mDrcInBuf, p_array, buf_size);
-                /* Set number of bytes to be processed */
-                err_code =
-                    ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size);
-                RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+                    memcpy(mDrcInBuf, p_array, buf_size);
+                    /* Set number of bytes to be processed */
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS,
+                                              0, &buf_size);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
 
-                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
-                                          IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag);
-                RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM,
+                                              IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG,
+                                              &gain_stream_flag);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
 
-                /* Execute process */
-                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
-                                          IA_CMD_TYPE_INIT_CPY_BSF_BUFF, NULL);
-                RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
+                    /* Execute process */
+                    err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
+                                              IA_CMD_TYPE_INIT_CPY_BSF_BUFF, NULL);
+                    RETURN_IF_FATAL(err_code, "IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT");
 
-                mMpegDDRCPresent = 1;
+                    mMpegDDRCPresent = 1;
+                }
             }
-        }
-    }
 #endif
-    /* How much buffer is used in input buffers */
-    err_code =
-        ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, bytesConsumed);
-    RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF");
+            /* How much buffer is used in input buffers */
+            err_code =
+                ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF,
+                                 0, bytesConsumed);
+            RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_CURIDX_INPUT_BUF");
 
-    /* Get the output bytes */
-    err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_OUTPUT_BYTES, 0, outBytes);
-    RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_OUTPUT_BYTES");
+            /* Get the output bytes */
+            err_code = ixheaacd_dec_api(mXheaacCodecHandle,
+                                        IA_API_CMD_GET_OUTPUT_BYTES, 0, outBytes);
+            RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_OUTPUT_BYTES");
 #ifdef ENABLE_MPEG_D_DRC
 
-    if (mMpegDDRCPresent == 1) {
-        memcpy(mDrcInBuf, mOutputBuffer, *outBytes);
-        err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes);
-        RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
+            if (mMpegDDRCPresent == 1) {
+                memcpy(mDrcInBuf, mOutputBuffer + pi_preroll_frame_offset, *outBytes);
+                pi_preroll_frame_offset += *outBytes;
+                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES,
+                                          0, outBytes);
+                RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_INPUT_BYTES");
 
-        err_code =
-            ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, NULL);
-        RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
+                err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE,
+                                          IA_CMD_TYPE_DO_EXECUTE, NULL);
+                RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_DO_EXECUTE");
 
-        memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
-    }
+                memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
+            }
 #endif
+            i_num_preroll--;
+        } while (i_num_preroll > 0);
+    }
     return IA_NO_ERROR;
 }
 
diff --git a/media/libstagefright/colorconversion/Android.bp b/media/libstagefright/colorconversion/Android.bp
index ba57497..6b08b08 100644
--- a/media/libstagefright/colorconversion/Android.bp
+++ b/media/libstagefright/colorconversion/Android.bp
@@ -15,6 +15,11 @@
         "libnativewindow",
     ],
 
+    header_libs: [
+        "libstagefright_headers",
+        "libstagefright_foundation_headers",
+    ],
+
     static_libs: ["libyuv_static"],
 
     cflags: ["-Werror"],
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index d685321..c7dc415 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -324,8 +324,8 @@
 }
 
 #define DECLARE_YUV2RGBFUNC(func, rgb) int (*func)(     \
-        const uint8*, int, const uint8*, int,           \
-        const uint8*, int, uint8*, int, int, int)       \
+        const uint8_t*, int, const uint8_t*, int,           \
+        const uint8_t*, int, uint8_t*, int, int, int)       \
         = mSrcColorSpace.isBt709() ? libyuv::H420To##rgb \
         : mSrcColorSpace.isJpeg() ? libyuv::J420To##rgb  \
         : libyuv::I420To##rgb
@@ -350,7 +350,7 @@
     {
         DECLARE_YUV2RGBFUNC(func, RGB565);
         (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
-                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
+                (uint8_t *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
     }
 
@@ -358,7 +358,7 @@
     {
         DECLARE_YUV2RGBFUNC(func, ABGR);
         (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
-                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
+                (uint8_t *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
     }
 
@@ -366,7 +366,7 @@
     {
         DECLARE_YUV2RGBFUNC(func, ARGB);
         (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
-                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
+                (uint8_t *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
     }
 
@@ -391,17 +391,17 @@
 
     switch (mDstFormat) {
     case OMX_COLOR_Format16bitRGB565:
-        libyuv::NV12ToRGB565(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+        libyuv::NV12ToRGB565(src_y, src.mStride, src_u, src.mStride, (uint8_t *)dst_ptr,
                 dst.mStride, src.cropWidth(), src.cropHeight());
         break;
 
     case OMX_COLOR_Format32bitBGRA8888:
-        libyuv::NV12ToARGB(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+        libyuv::NV12ToARGB(src_y, src.mStride, src_u, src.mStride, (uint8_t *)dst_ptr,
                 dst.mStride, src.cropWidth(), src.cropHeight());
         break;
 
     case OMX_COLOR_Format32BitRGBA8888:
-        libyuv::NV12ToABGR(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+        libyuv::NV12ToABGR(src_y, src.mStride, src_u, src.mStride, (uint8_t *)dst_ptr,
                 dst.mStride, src.cropWidth(), src.cropHeight());
         break;
 
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 359df3d..4711315 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -31,9 +31,14 @@
 
 namespace android {
 
-static int ALIGN(int x, int y) {
-    // y must be a power of 2.
-    return (x + y - 1) & ~(y - 1);
+inline void initDstYUV(
+        const android_ycbcr &ycbcr, int32_t cropTop, int32_t cropLeft,
+        uint8_t **dst_y, uint8_t **dst_u, uint8_t **dst_v) {
+    *dst_y = (uint8_t *)ycbcr.y + cropTop * ycbcr.ystride + cropLeft;
+
+    int32_t c_offset = (cropTop / 2) * ycbcr.cstride + cropLeft / 2;
+    *dst_v = (uint8_t *)ycbcr.cr + c_offset;
+    *dst_u = (uint8_t *)ycbcr.cb + c_offset;
 }
 
 SoftwareRenderer::SoftwareRenderer(
@@ -269,10 +274,21 @@
 
     Rect bounds(mCropWidth, mCropHeight);
 
-    void *dst;
-    CHECK_EQ(0, mapper.lock(buf->handle,
-            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
-            bounds, &dst));
+    void *dst = NULL;
+    struct android_ycbcr ycbcr;
+    if ( !mConverter &&
+         (mColorFormat == OMX_COLOR_FormatYUV420Planar ||
+         mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+         mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar ||
+         mColorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+        CHECK_EQ(0, mapper.lockYCbCr(buf->handle,
+                GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
+                bounds, &ycbcr));
+    } else {
+        CHECK_EQ(0, mapper.lock(buf->handle,
+                GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
+                bounds, &dst));
+    }
 
     // TODO move the other conversions also into ColorConverter, and
     // fix cropping issues (when mCropLeft/Top != 0 or mWidth != mCropWidth)
@@ -289,22 +305,14 @@
         const uint8_t *src_u = (const uint8_t *)data + mStride * mHeight + mCropTop * mStride / 4;
         const uint8_t *src_v = (const uint8_t *)src_u + mStride * mHeight / 4;
 
-        uint8_t *dst_y = (uint8_t *)dst;
-        size_t dst_y_size = buf->stride * buf->height;
-        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
-        size_t dst_c_size = dst_c_stride * buf->height / 2;
-        uint8_t *dst_v = dst_y + dst_y_size;
-        uint8_t *dst_u = dst_v + dst_c_size;
-
-        dst_y += mCropTop * buf->stride + mCropLeft;
-        dst_v += (mCropTop/2) * dst_c_stride + mCropLeft/2;
-        dst_u += (mCropTop/2) * dst_c_stride + mCropLeft/2;
+        uint8_t *dst_y, *dst_u, *dst_v;
+        initDstYUV(ycbcr, mCropTop, mCropLeft, &dst_y, &dst_u, &dst_v);
 
         for (int y = 0; y < mCropHeight; ++y) {
             memcpy(dst_y, src_y, mCropWidth);
 
             src_y += mStride;
-            dst_y += buf->stride;
+            dst_y += ycbcr.ystride;
         }
 
         for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
@@ -313,24 +321,16 @@
 
             src_u += mStride / 2;
             src_v += mStride / 2;
-            dst_u += dst_c_stride;
-            dst_v += dst_c_stride;
+            dst_u += ycbcr.cstride;
+            dst_v += ycbcr.cstride;
         }
     } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
         const uint8_t *src_y = (const uint8_t *)data + mCropTop * mStride + mCropLeft * 2;
         const uint8_t *src_u = (const uint8_t *)data + mStride * mHeight + mCropTop * mStride / 4;
         const uint8_t *src_v = (const uint8_t *)src_u + mStride * mHeight / 4;
 
-        uint8_t *dst_y = (uint8_t *)dst;
-        size_t dst_y_size = buf->stride * buf->height;
-        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
-        size_t dst_c_size = dst_c_stride * buf->height / 2;
-        uint8_t *dst_v = dst_y + dst_y_size;
-        uint8_t *dst_u = dst_v + dst_c_size;
-
-        dst_y += mCropTop * buf->stride + mCropLeft;
-        dst_v += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
-        dst_u += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
+        uint8_t *dst_y, *dst_u, *dst_v;
+        initDstYUV(ycbcr, mCropTop, mCropLeft, &dst_y, &dst_u, &dst_v);
 
         for (int y = 0; y < mCropHeight; ++y) {
             for (int x = 0; x < mCropWidth; ++x) {
@@ -338,7 +338,7 @@
             }
 
             src_y += mStride;
-            dst_y += buf->stride;
+            dst_y += ycbcr.ystride;
         }
 
         for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
@@ -349,8 +349,8 @@
 
             src_u += mStride / 2;
             src_v += mStride / 2;
-            dst_u += dst_c_stride;
-            dst_v += dst_c_stride;
+            dst_u += ycbcr.cstride;
+            dst_v += ycbcr.cstride;
         }
     } else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
             || mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
@@ -361,23 +361,14 @@
         src_y += mCropLeft + mCropTop * mWidth;
         src_uv += (mCropLeft + mCropTop * mWidth) / 2;
 
-        uint8_t *dst_y = (uint8_t *)dst;
-
-        size_t dst_y_size = buf->stride * buf->height;
-        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
-        size_t dst_c_size = dst_c_stride * buf->height / 2;
-        uint8_t *dst_v = dst_y + dst_y_size;
-        uint8_t *dst_u = dst_v + dst_c_size;
-
-        dst_y += mCropTop * buf->stride + mCropLeft;
-        dst_v += (mCropTop/2) * dst_c_stride + mCropLeft/2;
-        dst_u += (mCropTop/2) * dst_c_stride + mCropLeft/2;
+        uint8_t *dst_y, *dst_u, *dst_v;
+        initDstYUV(ycbcr, mCropTop, mCropLeft, &dst_y, &dst_u, &dst_v);
 
         for (int y = 0; y < mCropHeight; ++y) {
             memcpy(dst_y, src_y, mCropWidth);
 
             src_y += mWidth;
-            dst_y += buf->stride;
+            dst_y += ycbcr.ystride;
         }
 
         for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
@@ -388,8 +379,8 @@
             }
 
             src_uv += mWidth;
-            dst_u += dst_c_stride;
-            dst_v += dst_c_stride;
+            dst_u += ycbcr.cstride;
+            dst_v += ycbcr.cstride;
         }
     } else if (mColorFormat == OMX_COLOR_Format24bitRGB888) {
         uint8_t* srcPtr = (uint8_t*)data + mWidth * mCropTop * 3 + mCropLeft * 3;
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 67d3f1a..6571162 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -48,13 +48,13 @@
         </MediaCodec>
         <MediaCodec name="c2.android.g711.alaw.decoder" type="audio/g711-alaw">
             <Alias name="OMX.google.g711.alaw.decoder" />
-            <Limit name="channel-count" max="1" />
+            <Limit name="channel-count" max="6" />
             <Limit name="sample-rate" ranges="8000-48000" />
             <Limit name="bitrate" range="64000" />
         </MediaCodec>
         <MediaCodec name="c2.android.g711.mlaw.decoder" type="audio/g711-mlaw">
             <Alias name="OMX.google.g711.mlaw.decoder" />
-            <Limit name="channel-count" max="1" />
+            <Limit name="channel-count" max="6" />
             <Limit name="sample-rate" ranges="8000-48000" />
             <Limit name="bitrate" range="64000" />
         </MediaCodec>
@@ -67,7 +67,7 @@
         <MediaCodec name="c2.android.opus.decoder" type="audio/opus">
             <Alias name="OMX.google.opus.decoder" />
             <Limit name="channel-count" max="8" />
-            <Limit name="sample-rate" ranges="48000" />
+            <Limit name="sample-rate" ranges="8000,12000,16000,24000,48000" />
             <Limit name="bitrate" range="6000-510000" />
         </MediaCodec>
         <MediaCodec name="c2.android.raw.decoder" type="audio/raw">
@@ -295,12 +295,12 @@
             <Feature name="bitrate-modes" value="VBR,CBR" />
         </MediaCodec>
         <MediaCodec name="c2.android.hevc.encoder" type="video/hevc" variant="!slow-cpu">
-            <!-- profiles and levels:  ProfileMain : MainTierLevel51 -->
-            <Limit name="size" min="2x2" max="512x512" />
+            <!-- profiles and levels:  ProfileMain : MainTierLevel3 -->
+            <Limit name="size" min="2x2" max="960x544" />
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="8x8" />
-            <Limit name="block-count" range="1-4096" /> <!-- max 512x512 -->
-            <Limit name="blocks-per-second" range="1-122880" />
+            <Limit name="block-count" range="1-8160" /> <!-- max 960x544 -->
+            <Limit name="blocks-per-second" range="1-244880" />
             <Limit name="frame-rate" range="1-120" />
             <Limit name="bitrate" range="1-10000000" />
             <Limit name="complexity" range="0-10"  default="0" />
diff --git a/media/libstagefright/exports.lds b/media/libstagefright/exports.lds
index aabc233..f5ddf1e 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -395,7 +395,6 @@
         ScaleFilterCols_NEON*;
         ScaleFilterReduce;
         ScaleFilterRows_NEON*;
-        ScaleOffset;
         ScalePlane;
         ScalePlane_16;
         ScalePlaneBilinearDown;
@@ -505,4 +504,8 @@
         YUY2ToYRow_Any_NEON*;
         YUY2ToYRow_C;
         YUY2ToYRow_NEON*;
+        ogg_packet_*;
+        ogg_page_*;
+        ogg_stream_*;
+        ogg_sync_*;
 };
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index 7a67e55..88f30c4 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -8,7 +8,7 @@
         "MediaFilter.cpp",
         "RSFilter.cpp",
         "SaturationFilter.cpp",
-        "saturationARGB.rs",
+        "saturationARGB.rscript",
         "SimpleFilter.cpp",
         "ZeroFilter.cpp",
     ],
@@ -23,6 +23,10 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+    ],
+
     shared_libs: [
         "libgui",
         "libmedia",
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index 777ab5b..c7baa73 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -20,13 +20,12 @@
 #include <inttypes.h>
 #include <utils/Trace.h>
 
-#include <binder/MemoryDealer.h>
-
-#include <media/stagefright/BufferProducerWrapper.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
+#include <media/stagefright/BufferProducerWrapper.h>
+#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaFilter.h>
@@ -42,11 +41,121 @@
 #include "SaturationFilter.h"
 #include "ZeroFilter.h"
 
-#include "../include/ACodecBufferChannel.h"
-#include "../include/SharedMemoryBuffer.h"
-
 namespace android {
 
+class MediaFilter::BufferChannel : public BufferChannelBase {
+public:
+    BufferChannel(const sp<AMessage> &in, const sp<AMessage> &out)
+        : mInputBufferFilled(in), mOutputBufferDrained(out) {
+    }
+
+    ~BufferChannel() override = default;
+
+    // BufferChannelBase
+
+    status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override {
+        sp<AMessage> msg = mInputBufferFilled->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    status_t queueSecureInputBuffer(
+            const sp<MediaCodecBuffer> &,
+            bool,
+            const uint8_t *,
+            const uint8_t *,
+            CryptoPlugin::Mode,
+            CryptoPlugin::Pattern,
+            const CryptoPlugin::SubSample *,
+            size_t,
+            AString *) override {
+        return INVALID_OPERATION;
+    }
+
+    status_t renderOutputBuffer(
+            const sp<MediaCodecBuffer> &buffer, int64_t /* timestampNs */) override {
+        sp<AMessage> msg = mOutputBufferDrained->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override {
+        if (FindBufferIndex(&mInputBuffers, buffer) >= 0) {
+            sp<AMessage> msg = mInputBufferFilled->dup();
+            msg->setObject("buffer", buffer);
+            msg->post();
+            return OK;
+        }
+        sp<AMessage> msg = mOutputBufferDrained->dup();
+        msg->setObject("buffer", buffer);
+        msg->post();
+        return OK;
+    }
+
+    void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+        if (!array) {
+            return;
+        }
+        array->clear();
+        array->appendVector(mInputBuffers);
+    }
+
+    void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+        if (!array) {
+            return;
+        }
+        array->clear();
+        array->appendVector(mOutputBuffers);
+    }
+
+    // For MediaFilter
+
+    void fillThisBuffer(const sp<MediaCodecBuffer> &buffer) {
+        ssize_t index = FindBufferIndex(&mInputBuffers, buffer);
+        mCallback->onInputBufferAvailable(index, buffer);
+    }
+
+    void drainThisBuffer(const sp<MediaCodecBuffer> &buffer, int flags) {
+        ssize_t index = FindBufferIndex(&mOutputBuffers, buffer);
+        buffer->meta()->setInt32("flags", flags);
+        mCallback->onOutputBufferAvailable(index, buffer);
+    }
+
+    template <class T>
+    void setInputBuffers(T begin, T end) {
+        mInputBuffers.clear();
+        for (T it = begin; it != end; ++it) {
+            mInputBuffers.push_back(it->mData);
+        }
+    }
+
+    template <class T>
+    void setOutputBuffers(T begin, T end) {
+        mOutputBuffers.clear();
+        for (T it = begin; it != end; ++it) {
+            mOutputBuffers.push_back(it->mData);
+        }
+    }
+
+private:
+    sp<AMessage> mInputBufferFilled;
+    sp<AMessage> mOutputBufferDrained;
+    Vector<sp<MediaCodecBuffer>> mInputBuffers;
+    Vector<sp<MediaCodecBuffer>> mOutputBuffers;
+
+    static ssize_t FindBufferIndex(
+            Vector<sp<MediaCodecBuffer>> *array, const sp<MediaCodecBuffer> &buffer) {
+        for (size_t i = 0; i < array->size(); ++i) {
+            if (array->itemAt(i) == buffer) {
+                return i;
+            }
+        }
+        return -1;
+    }
+};
+
 // parameter: number of input and output buffers
 static const size_t kBufferCountActual = 4;
 
@@ -54,9 +163,6 @@
     : mState(UNINITIALIZED),
       mGeneration(0),
       mGraphicBufferListener(NULL) {
-    mBufferChannel = std::make_shared<ACodecBufferChannel>(
-            new AMessage(kWhatInputBufferFilled, this),
-            new AMessage(kWhatOutputBufferDrained, this));
 }
 
 MediaFilter::~MediaFilter() {
@@ -65,6 +171,11 @@
 //////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
 
 std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
+    if (!mBufferChannel) {
+        mBufferChannel = std::make_shared<BufferChannel>(
+                new AMessage(kWhatInputBufferFilled, this),
+                new AMessage(kWhatOutputBufferDrained, this));
+    }
     return mBufferChannel;
 }
 
@@ -212,28 +323,23 @@
     const bool isInput = portIndex == kPortIndexInput;
     const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
 
-    CHECK(mDealer[portIndex] == NULL);
     CHECK(mBuffers[portIndex].isEmpty());
 
     ALOGV("Allocating %zu buffers of size %zu on %s port",
             kBufferCountActual, bufferSize,
             isInput ? "input" : "output");
 
-    size_t totalSize = kBufferCountActual * bufferSize;
-
-    mDealer[portIndex] = new MemoryDealer(totalSize, "MediaFilter");
-
+    // trigger output format change
+    sp<AMessage> outputFormat = mOutputFormat->dup();
     for (size_t i = 0; i < kBufferCountActual; ++i) {
-        sp<IMemory> mem = mDealer[portIndex]->allocate(bufferSize);
-        CHECK(mem.get() != NULL);
-
         BufferInfo info;
         info.mStatus = BufferInfo::OWNED_BY_US;
         info.mBufferID = i;
         info.mGeneration = mGeneration;
         info.mOutputFlags = 0;
-        info.mData = new SharedMemoryBuffer(
-                isInput ? mInputFormat : mOutputFormat, mem);
+        info.mData = new MediaCodecBuffer(
+                isInput ? mInputFormat : outputFormat,
+                new ABuffer(bufferSize));
         info.mData->meta()->setInt64("timeUs", 0);
 
         mBuffers[portIndex].push_back(info);
@@ -243,27 +349,24 @@
                     &mBuffers[portIndex].editItemAt(i));
         }
     }
-
-    std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
-    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
-    }
-    if (portIndex == kPortIndexInput) {
-        mBufferChannel->setInputBufferArray(array);
+    if (isInput) {
+        mBufferChannel->setInputBuffers(
+                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
     } else {
-        mBufferChannel->setOutputBufferArray(array);
+        mBufferChannel->setOutputBuffers(
+                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
     }
 
     return OK;
 }
 
-MediaFilter::BufferInfo* MediaFilter::findBufferByID(
-        uint32_t portIndex, IOMX::buffer_id bufferID,
+MediaFilter::BufferInfo* MediaFilter::findBuffer(
+        uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
         ssize_t *index) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
 
-        if (info->mBufferID == bufferID) {
+        if (info->mData == buffer) {
             if (index != NULL) {
                 *index = i;
             }
@@ -293,7 +396,7 @@
 
     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
 
-    mBufferChannel->fillThisBuffer(info->mBufferID);
+    mBufferChannel->fillThisBuffer(info->mData);
 }
 
 void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
@@ -304,7 +407,7 @@
     sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
     reply->setInt32("buffer-id", info->mBufferID);
 
-    mBufferChannel->drainThisBuffer(info->mBufferID, info->mOutputFlags);
+    mBufferChannel->drainThisBuffer(info->mData, info->mOutputFlags);
 
     info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
 }
@@ -359,7 +462,7 @@
     outputInfo->mOutputFlags = 0;
     int32_t eos = 0;
     if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
-        outputInfo->mOutputFlags |= OMX_BUFFERFLAG_EOS;
+        outputInfo->mOutputFlags |= BUFFER_FLAG_END_OF_STREAM;
         mPortEOS[kPortIndexOutput] = true;
         outputInfo->mData->meta()->setInt32("eos", eos);
         postEOS();
@@ -400,8 +503,7 @@
         return;
     }
 
-    // HACK - need "OMX.google" to use MediaCodec's software renderer
-    mCallback->onComponentAllocated("OMX.google.MediaFilter");
+    mCallback->onComponentAllocated(mComponentName.c_str());
     mState = INITIALIZED;
     ALOGV("Handled kWhatAllocateComponent.");
 }
@@ -477,6 +579,7 @@
     mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
     mOutputFormat->setInt32("width", mWidth);
     mOutputFormat->setInt32("height", mHeight);
+    mOutputFormat->setInt32("using-sw-renderer", 1);
 
     mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
     mState = CONFIGURED;
@@ -509,9 +612,11 @@
 }
 
 void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
-    IOMX::buffer_id bufferID;
-    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
-    BufferInfo *info = findBufferByID(kPortIndexInput, bufferID);
+    sp<RefBase> obj;
+    CHECK(msg->findObject("buffer", &obj));
+    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    ssize_t index = -1;
+    BufferInfo *info = findBuffer(kPortIndexInput, buffer, &index);
 
     if (mState != STARTED) {
         // we're not running, so we'll just keep that buffer...
@@ -520,7 +625,7 @@
     }
 
     if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale input buffer [ID %d]", bufferID);
+        ALOGV("Caught a stale input buffer [index %zd]", index);
         // buffer is stale (taken before a flush/shutdown) - repost it
         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
         postFillThisBuffer(info);
@@ -530,30 +635,9 @@
     CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
     info->mStatus = BufferInfo::OWNED_BY_US;
 
-    sp<MediaCodecBuffer> buffer;
     int32_t err = OK;
     bool eos = false;
 
-    sp<RefBase> obj;
-    if (!msg->findObject("buffer", &obj)) {
-        // these are unfilled buffers returned by client
-        CHECK(msg->findInt32("err", &err));
-
-        if (err == OK) {
-            // buffers with no errors are returned on MediaCodec.flush
-            ALOGV("saw unfilled buffer (MediaCodec.flush)");
-            postFillThisBuffer(info);
-            return;
-        } else {
-            ALOGV("saw error %d instead of an input buffer", err);
-            eos = true;
-        }
-
-        buffer.clear();
-    } else {
-        buffer = static_cast<MediaCodecBuffer *>(obj.get());
-    }
-
     int32_t isCSD;
     if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
             && isCSD != 0) {
@@ -577,13 +661,15 @@
         mInputEOSResult = err;
     }
 
-    ALOGV("Handled kWhatInputBufferFilled. [ID %u]", bufferID);
+    ALOGV("Handled kWhatInputBufferFilled. [index %zd]", index);
 }
 
 void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
-    IOMX::buffer_id bufferID;
-    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
-    BufferInfo *info = findBufferByID(kPortIndexOutput, bufferID);
+    sp<RefBase> obj;
+    CHECK(msg->findObject("buffer", &obj));
+    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+    ssize_t index = -1;
+    BufferInfo *info = findBuffer(kPortIndexOutput, buffer, &index);
 
     if (mState != STARTED) {
         // we're not running, so we'll just keep that buffer...
@@ -592,7 +678,7 @@
     }
 
     if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale output buffer [ID %d]", bufferID);
+        ALOGV("Caught a stale output buffer [index %zd]", index);
         // buffer is stale (taken before a flush/shutdown) - keep it
         CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
         return;
@@ -605,8 +691,7 @@
 
     processBuffers();
 
-    ALOGV("Handled kWhatOutputBufferDrained. [ID %u]",
-            bufferID);
+    ALOGV("Handled kWhatOutputBufferDrained. [index %zd]", index);
 }
 
 void MediaFilter::onShutdown(const sp<AMessage> &msg) {
@@ -739,7 +824,7 @@
             return;
         }
 
-        eosBuf->mOutputFlags = OMX_BUFFERFLAG_EOS;
+        eosBuf->mOutputFlags = BUFFER_FLAG_END_OF_STREAM;
         eosBuf->mGeneration = mGeneration;
         eosBuf->mData->setRange(0, 0);
         postDrainThisBuffer(eosBuf);
diff --git a/media/libstagefright/filters/saturation.rs b/media/libstagefright/filters/saturation.rscript
similarity index 100%
rename from media/libstagefright/filters/saturation.rs
rename to media/libstagefright/filters/saturation.rscript
diff --git a/media/libstagefright/filters/saturationARGB.rs b/media/libstagefright/filters/saturationARGB.rscript
similarity index 100%
rename from media/libstagefright/filters/saturationARGB.rs
rename to media/libstagefright/filters/saturationARGB.rscript
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index b494e16..32b2075 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -1,6 +1,7 @@
 cc_library {
     name: "libstagefright_flacdec",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: [
         "FLACDecoder.cpp",
@@ -18,29 +19,20 @@
         cfi: true,
     },
 
-    static: {
-        whole_static_libs: [
-            "libFLAC",
-            "libaudioutils",
-        ],
-    },
-
-    shared: {
-        static_libs: [
-            "libFLAC",
-            "libaudioutils",
-        ],
-        export_static_lib_headers: [
-            "libFLAC",
-        ],
-    },
-
     shared_libs: [
+        "libaudioutils",
         "liblog",
     ],
 
+    static_libs: [
+        "libFLAC",
+    ],
+
+    export_static_lib_headers: [
+        "libFLAC",
+    ],
+
     header_libs: [
         "libmedia_headers",
-        "libFLAC-headers",
     ],
 }
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/libstagefright/flac/dec/test/Android.bp
new file mode 100644
index 0000000..70ca80a
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "FlacDecoderTest",
+    gtest: true,
+
+    srcs: [
+        "FlacDecoderTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    static_libs: [
+        "libstagefright_flacdec",
+        "libFLAC",
+    ],
+
+    header_libs: [
+        "libstagefright_foundation_headers",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/libstagefright/flac/dec/test/AndroidTest.xml
new file mode 100644
index 0000000..bebba8e
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for flac decoder unit tests">
+    <option name="test-suite-tag" value="FlacDecoderTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
+            value="/data/local/tmp/FlacDecoderTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="FlacDecoderTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
new file mode 100644
index 0000000..34f12db
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2019 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 "FlacDecoderTest"
+
+#include <utils/Log.h>
+#include <fstream>
+
+#include "FLACDecoder.h"
+
+#include "FlacDecoderTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/FlacDecoderOutput.raw"
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCount = 10;
+constexpr int32_t kMaxBlockSize = 4096;
+
+using namespace android;
+
+struct FrameInfo {
+    int32_t bytesCount;
+    uint32_t flags;
+    int64_t timestamp;
+};
+
+static FlacDecoderTestEnvironment *gEnv = nullptr;
+
+class FLACDecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {
+  public:
+    FLACDecoderTest() : mFLACDecoder(nullptr), mHasStreamInfo(false), mInputBufferCount(0) {}
+
+    ~FLACDecoderTest() {
+        if (mEleStream.is_open()) mEleStream.close();
+        if (mFLACDecoder) delete mFLACDecoder;
+        mFLACDecoder = nullptr;
+    }
+
+    virtual void SetUp() override {
+        mFLACDecoder = FLACDecoder::Create();
+        ASSERT_NE(mFLACDecoder, nullptr) << "initDecoder: failed to create FLACDecoder";
+    }
+
+    int32_t processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+                               bool outputFloat, ofstream &ostrm);
+
+    FLACDecoder *mFLACDecoder;
+    FLAC__StreamMetadata_StreamInfo mStreamInfo;
+
+    bool mHasStreamInfo;
+    int32_t mInputBufferCount;
+    ifstream mEleStream;
+};
+
+void getInfo(string infoFileName, vector<FrameInfo> &Info) {
+    ifstream eleInfo;
+    eleInfo.open(infoFileName);
+    ASSERT_EQ(eleInfo.is_open(), true);
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) break;
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        Info.push_back({bytesCount, flags, timestamp});
+    }
+    if (eleInfo.is_open()) eleInfo.close();
+}
+
+int32_t FLACDecoderTest::processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+                                            bool outputFloat, ofstream &ostrm) {
+    memset(&mStreamInfo, 0, sizeof(mStreamInfo));
+
+    int32_t frameID = offset;
+    if (range + offset > Info.size() || range < 0 || offset > Info.size() - 1 || offset < 0) {
+        ALOGE("Invalid offset or range or both passed for decoding");
+        ALOGE("offset = %d \t range = %d  \t Info.size() = %zu", offset, range, Info.size());
+        return -1;
+    }
+
+    while (1) {
+        if (frameID == Info.size() || frameID == (offset + range)) break;
+        int64_t flags = (Info)[frameID].flags;
+        int32_t size = (Info)[frameID].bytesCount;
+        if (size < 0) {
+            ALOGE("Size for the memory allocation is negative");
+            return -1;
+        }
+        char *data = (char *)malloc(size);
+        if (!data) {
+            ALOGE("Insufficient memory to read frame");
+            return -1;
+        }
+
+        mEleStream.read(data, size);
+        if (mEleStream.gcount() != size) {
+            if (data) {
+                free(data);
+                data = nullptr;
+            }
+            ALOGE("Invalid size read, requested: %d and read: %zu", size, mEleStream.gcount());
+            return -1;
+        }
+
+        if (flags == CODEC_CONFIG_FLAG && mInputBufferCount == 0) {
+            status_t decoderErr = mFLACDecoder->parseMetadata((uint8_t *)data, size);
+            if (decoderErr == WOULD_BLOCK) {
+                ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
+            } else if (decoderErr == OK) {
+                mStreamInfo = mFLACDecoder->getStreamInfo();
+                if (mStreamInfo.sample_rate && mStreamInfo.max_blocksize && mStreamInfo.channels) {
+                    mHasStreamInfo = true;
+                }
+                ALOGV("decoder configuration : %d Hz, %d channels, %d samples,"
+                      " %d block size",
+                      mStreamInfo.sample_rate, mStreamInfo.channels,
+                      (int32_t)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
+            } else {
+                ALOGE("FLACDecoder parseMetaData returns error %d", decoderErr);
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                return decoderErr;
+            }
+        } else {
+            const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+            size_t outSize = mHasStreamInfo
+                                     ? mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+                                     : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
+
+            void *out_buf = malloc(outSize);
+            if (!out_buf) {
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                ALOGE("Output buffer allocation failed");
+                return -1;
+            }
+            status_t decoderErr = mFLACDecoder->decodeOneFrame((uint8_t *)data, size, out_buf,
+                                                               &outSize, outputFloat);
+            if (decoderErr != OK) {
+                ALOGE("decodeOneFrame returns error %d", decoderErr);
+                if (data) {
+                    free(data);
+                    data = nullptr;
+                }
+                if (out_buf) {
+                    free(out_buf);
+                    out_buf = nullptr;
+                }
+                return decoderErr;
+            }
+            ostrm.write(reinterpret_cast<char *>(out_buf), outSize);
+            free(out_buf);
+            out_buf = nullptr;
+        }
+        mInputBufferCount++;
+        frameID++;
+        free(data);
+        data = nullptr;
+    }
+    ALOGV("frameID=%d", frameID);
+    return 0;
+}
+
+TEST_F(FLACDecoderTest, CreateDeleteTest) {
+    if (mFLACDecoder) delete mFLACDecoder;
+    mFLACDecoder = nullptr;
+
+    for (int32_t i = 0; i < kMaxCount; i++) {
+        mFLACDecoder = FLACDecoder::Create();
+        ASSERT_NE(mFLACDecoder, nullptr) << "FLACDecoder Creation Failed";
+        if (mFLACDecoder) delete mFLACDecoder;
+        mFLACDecoder = nullptr;
+    }
+}
+
+TEST_P(FLACDecoderTest, FlushTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    bool outputFloat = get<2>(params);
+
+    vector<FrameInfo> Info;
+    getInfo(infoFileName, Info);
+
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true);
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true);
+
+    int32_t status = processFlacDecoder(Info, 0, Info.size() / 3, outputFloat, ostrm);
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+    mFLACDecoder->flush();
+    mHasStreamInfo = false;
+    status = processFlacDecoder(Info, (Info.size() / 3), Info.size() - (Info.size() / 3),
+                                outputFloat, ostrm);
+    ostrm.close();
+    Info.clear();
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+TEST_P(FLACDecoderTest, DecodeTest) {
+    tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+            GetParam();
+
+    string inputFileName = gEnv->getRes() + get<0>(params);
+    string infoFileName = gEnv->getRes() + get<1>(params);
+    bool outputFloat = get<2>(params);
+
+    vector<FrameInfo> Info;
+    getInfo(infoFileName, Info);
+
+    mEleStream.open(inputFileName, ifstream::binary);
+    ASSERT_EQ(mEleStream.is_open(), true);
+
+    ofstream ostrm;
+    ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+    ASSERT_EQ(ostrm.is_open(), true);
+
+    int32_t status = processFlacDecoder(Info, 0, Info.size(), outputFloat, ostrm);
+    ostrm.close();
+    Info.clear();
+    ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+// TODO: Add remaining tests
+INSTANTIATE_TEST_SUITE_P(
+        FLACDecoderTestAll, FLACDecoderTest,
+        ::testing::Values(make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+                                     "bbb_flac_stereo_680kbps_48000hz.info", true),
+                          make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+                                     "bbb_flac_stereo_680kbps_48000hz.info", false),
+                          make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+                                     "bbb_flac_stereo_600kbps_44100hz.info", true),
+                          make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+                                     "bbb_flac_stereo_600kbps_44100hz.info", false)));
+
+int main(int argc, char **argv) {
+    gEnv = new FlacDecoderTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Flac Decoder Test Result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
new file mode 100644
index 0000000..1334bba
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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 __FLAC_DECODER_TEST_ENVIRONMENT_H__
+#define __FLAC_DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class FlacDecoderTestEnvironment : public ::testing::Environment {
+  public:
+    FlacDecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int FlacDecoderTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __FLAC_DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/libstagefright/flac/dec/test/README.md
new file mode 100644
index 0000000..4d194cd
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/README.md
@@ -0,0 +1,40 @@
+## Media Testing ##
+---
+#### FlacDecoder :
+The FlacDecoder Test Suite validates the FlacDecoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m FlacDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push FlacDecoder /data/local/tmp/
+```
+
+usage: FlacDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/FlacDecoderTest -P /data/local/tmp/FlacDecoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest FlacDecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index df66ac6..7752bda 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -22,7 +22,6 @@
 
 #include "AMessage.h"
 
-#include <binder/Parcel.h>
 #include <log/log.h>
 
 #include "AAtomizer.h"
@@ -34,6 +33,10 @@
 
 #include <media/stagefright/foundation/hexdump.h>
 
+#ifndef __ANDROID_VNDK__
+#include <binder/Parcel.h>
+#endif
+
 namespace android {
 
 extern ALooperRoster gLooperRoster;
@@ -643,6 +646,7 @@
     return s;
 }
 
+#ifndef __ANDROID_VNDK__
 // static
 sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) {
     int32_t what = parcel.readInt32();
@@ -809,6 +813,7 @@
         }
     }
 }
+#endif  // __ANDROID_VNDK__
 
 sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
     if (other == NULL) {
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index fb51cc5..4bd186c 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -23,11 +23,14 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <binder/Parcel.h>
 #include <utils/String8.h>
 #include "ADebug.h"
 #include "AString.h"
 
+#ifndef __ANDROID_VNDK__
+#include <binder/Parcel.h>
+#endif
+
 namespace android {
 
 // static
@@ -362,11 +365,10 @@
     return !strcasecmp(mData + mSize - suffixLen, suffix);
 }
 
+#ifndef __ANDROID_VNDK__
 // static
 AString AString::FromParcel(const Parcel &parcel) {
     size_t size = static_cast<size_t>(parcel.readInt32());
-    // The static analyzer incorrectly reports a false-positive here in c++17.
-    // https://bugs.llvm.org/show_bug.cgi?id=38176 . NOLINTNEXTLINE
     return AString(static_cast<const char *>(parcel.readInplace(size)), size);
 }
 
@@ -378,6 +380,7 @@
     }
     return err;
 }
+#endif
 
 AString AStringPrintf(const char *format, ...) {
     va_list ap;
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 533cd72..f440e00 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -2,6 +2,8 @@
     name: "libstagefright_foundation_headers",
     export_include_dirs: ["include"],
     vendor_available: true,
+    host_supported: true,
+    min_sdk_version: "29",
 }
 
 cc_defaults {
@@ -34,10 +36,6 @@
         "media_plugin_headers",
     ],
 
-    export_shared_lib_headers: [
-        "libbinder",
-    ],
-
     cflags: [
         "-Wno-multichar",
         "-Werror",
@@ -65,6 +63,7 @@
         "AudioPresentationInfo.cpp",
         "ByteUtils.cpp",
         "ColorUtils.cpp",
+        "FoundationUtils.cpp",
         "MediaBuffer.cpp",
         "MediaBufferBase.cpp",
         "MediaBufferGroup.cpp",
@@ -78,6 +77,17 @@
         "hexdump.cpp",
     ],
 
+    target: {
+        vendor: {
+            exclude_shared_libs: [
+                "libbinder",
+            ],
+            cflags: [
+                "-DNO_IMEMORY",
+            ],
+        },
+    },
+
     clang: true,
 
     sanitize: {
@@ -92,11 +102,13 @@
 cc_library {
     name: "libstagefright_foundation",
     defaults: ["libstagefright_foundation_defaults"],
+    min_sdk_version: "29",
 }
 
 cc_library_static {
     name: "libstagefright_foundation_without_imemory",
     defaults: ["libstagefright_foundation_defaults"],
+    min_sdk_version: "29",
 
     cflags: [
         "-Wno-multichar",
diff --git a/media/libstagefright/foundation/FoundationUtils.cpp b/media/libstagefright/foundation/FoundationUtils.cpp
new file mode 100644
index 0000000..8285e4c
--- /dev/null
+++ b/media/libstagefright/foundation/FoundationUtils.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 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 "FoundationUtils"
+#include <utils/Log.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+AString uriDebugString(const AString &uri, bool incognito) {
+    if (incognito) {
+        return AString("<URI suppressed>");
+    }
+
+    if (property_get_bool("media.stagefright.log-uri", false)) {
+        return uri;
+    }
+
+    // find scheme
+    AString scheme;
+    const char *chars = uri.c_str();
+    for (size_t i = 0; i < uri.size(); i++) {
+        const char c = chars[i];
+        if (!isascii(c)) {
+            break;
+        } else if (isalpha(c)) {
+            continue;
+        } else if (i == 0) {
+            // first character must be a letter
+            break;
+        } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
+            continue;
+        } else if (c != ':') {
+            break;
+        }
+        scheme = AString(uri, 0, i);
+        scheme.append("://<suppressed>");
+        return scheme;
+    }
+    return AString("<no-scheme URI suppressed>");
+}
+
+AString MakeUserAgent() {
+    AString ua;
+    ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    ua.append(value);
+    ua.append(")");
+
+    return ua;
+}
+
+AString nameForFd(int fd) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    AString result;
+    snprintf(buffer, SIZE, "/proc/%d/fd/%d", getpid(), fd);
+    struct stat s;
+    if (lstat(buffer, &s) == 0) {
+        if ((s.st_mode & S_IFMT) == S_IFLNK) {
+            char linkto[256];
+            int len = readlink(buffer, linkto, sizeof(linkto));
+            if(len > 0) {
+                if(len > 255) {
+                    linkto[252] = '.';
+                    linkto[253] = '.';
+                    linkto[254] = '.';
+                    linkto[255] = 0;
+                } else {
+                    linkto[len] = 0;
+                }
+                result.append(linkto);
+            }
+        } else {
+            result.append("unexpected type for ");
+            result.append(buffer);
+        }
+    } else {
+        result.append("couldn't open ");
+        result.append(buffer);
+    }
+    return result;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
index 9beac05..8e245dc 100644
--- a/media/libstagefright/foundation/MediaBuffer.cpp
+++ b/media/libstagefright/foundation/MediaBuffer.cpp
@@ -72,7 +72,7 @@
             }
         } else {
             getSharedControl()->clear();
-            mData = (uint8_t *)mMemory->pointer() + sizeof(SharedControl);
+            mData = (uint8_t *)mMemory->unsecurePointer() + sizeof(SharedControl);
             ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
         }
     }
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
index 84ff9a6..3c25047 100644
--- a/media/libstagefright/foundation/MediaBufferGroup.cpp
+++ b/media/libstagefright/foundation/MediaBufferGroup.cpp
@@ -75,7 +75,7 @@
 
         for (size_t i = 0; i < buffers; ++i) {
             sp<IMemory> mem = memoryDealer->allocate(augmented_size);
-            if (mem.get() == nullptr || mem->pointer() == nullptr) {
+            if (mem.get() == nullptr || mem->unsecurePointer() == nullptr) {
                 ALOGW("Only allocated %zu shared buffers of size %zu", i, buffer_size);
                 break;
             }
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
index 1d0a607..8174597 100644
--- a/media/libstagefright/foundation/MetaData.cpp
+++ b/media/libstagefright/foundation/MetaData.cpp
@@ -17,7 +17,6 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MetaData"
 #include <inttypes.h>
-#include <binder/Parcel.h>
 #include <utils/KeyedVector.h>
 #include <utils/Log.h>
 
@@ -29,6 +28,10 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MetaData.h>
 
+#ifndef __ANDROID_VNDK__
+#include <binder/Parcel.h>
+#endif
+
 namespace android {
 
 
@@ -45,6 +48,7 @@
 MetaData::~MetaData() {
 }
 
+#ifndef __ANDROID_VNDK__
 /* static */
 sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
 
@@ -52,6 +56,7 @@
     meta->updateFromParcel(parcel);
     return meta;
 }
+#endif
 
 }  // namespace android
 
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
index bfea6f1..4b439c6 100644
--- a/media/libstagefright/foundation/MetaDataBase.cpp
+++ b/media/libstagefright/foundation/MetaDataBase.cpp
@@ -17,7 +17,6 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MetaDataBase"
 #include <inttypes.h>
-#include <binder/Parcel.h>
 #include <utils/KeyedVector.h>
 #include <utils/Log.h>
 
@@ -29,6 +28,10 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MetaDataBase.h>
 
+#ifndef __ANDROID_VNDK__
+#include <binder/Parcel.h>
+#endif
+
 namespace android {
 
 struct MetaDataBase::typed_data {
@@ -449,6 +452,7 @@
     }
 }
 
+#ifndef __ANDROID_VNDK__
 status_t MetaDataBase::writeToParcel(Parcel &parcel) {
     status_t ret;
     size_t numItems = mInternalData->mItems.size();
@@ -528,6 +532,7 @@
     ALOGW("no metadata in parcel");
     return UNKNOWN_ERROR;
 }
+#endif
 
 }  // namespace android
 
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index f5687e0..784e802 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -126,12 +126,20 @@
     }
     header->num_streams = data[kOpusHeaderNumStreamsOffset];
     header->num_coupled = data[kOpusHeaderNumCoupledStreamsOffset];
-    if (header->num_streams + header->num_coupled != header->channels) {
-        ALOGV("Inconsistent channel mapping.");
+    if (header->num_coupled > header->num_streams ||
+        header->num_streams + header->num_coupled != header->channels) {
+        ALOGV("Inconsistent channel mapping, streams: %d coupled: %d channels: %d",
+        header->num_streams, header->num_coupled, header->channels);
         return false;
     }
-    for (int i = 0; i < header->channels; ++i)
-        header->stream_map[i] = data[kOpusHeaderStreamMapOffset + i];
+    for (int i = 0; i < header->channels; ++i) {
+        uint8_t value = data[kOpusHeaderStreamMapOffset + i];
+        if (value != 255 && value >= header->channels) {
+            ALOGV("Invalid channel mapping for index %i : %d", i, value);
+            return false;
+        }
+        header->stream_map[i] = value;
+    }
     return true;
 }
 
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/libstagefright/foundation/TEST_MAPPING
new file mode 100644
index 0000000..3301c4b
--- /dev/null
+++ b/media/libstagefright/foundation/TEST_MAPPING
@@ -0,0 +1,5 @@
+{
+  "presubmit": [
+    { "name": "sf_foundation_test" }
+  ]
+}
diff --git a/media/libstagefright/foundation/avc_utils.cpp b/media/libstagefright/foundation/avc_utils.cpp
index e8a6083..f53d2c9 100644
--- a/media/libstagefright/foundation/avc_utils.cpp
+++ b/media/libstagefright/foundation/avc_utils.cpp
@@ -166,10 +166,21 @@
     unsigned pic_height_in_map_units_minus1 = parseUE(&br);
     unsigned frame_mbs_only_flag = br.getBits(1);
 
-    *width = pic_width_in_mbs_minus1 * 16 + 16;
+    //    *width = pic_width_in_mbs_minus1 * 16 + 16;
+    if (__builtin_mul_overflow(pic_width_in_mbs_minus1, 16, &pic_width_in_mbs_minus1) ||
+        __builtin_add_overflow(pic_width_in_mbs_minus1, 16, width)) {
+        *width = 0;
+    }
 
-    *height = (2 - frame_mbs_only_flag)
-        * (pic_height_in_map_units_minus1 * 16 + 16);
+    //    *height = (2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 * 16 + 16);
+    if (__builtin_mul_overflow(
+                pic_height_in_map_units_minus1, 16, &pic_height_in_map_units_minus1) ||
+        __builtin_add_overflow(
+                pic_height_in_map_units_minus1, 16, &pic_height_in_map_units_minus1) ||
+        __builtin_mul_overflow(
+                pic_height_in_map_units_minus1, (2 - frame_mbs_only_flag), height)) {
+        *height = 0;
+    }
 
     if (!frame_mbs_only_flag) {
         br.getBits(1);  // mb_adaptive_frame_field_flag
@@ -202,17 +213,19 @@
 
 
         // *width -= (frame_crop_left_offset + frame_crop_right_offset) * cropUnitX;
-        if(__builtin_add_overflow(frame_crop_left_offset, frame_crop_right_offset, &frame_crop_left_offset) ||
-            __builtin_mul_overflow(frame_crop_left_offset, cropUnitX, &frame_crop_left_offset) ||
-            __builtin_sub_overflow(*width, frame_crop_left_offset, width) ||
+        if(__builtin_add_overflow(
+                   frame_crop_left_offset, frame_crop_right_offset, &frame_crop_left_offset) ||
+           __builtin_mul_overflow(frame_crop_left_offset, cropUnitX, &frame_crop_left_offset) ||
+           __builtin_sub_overflow(*width, frame_crop_left_offset, width) ||
             *width < 0) {
             *width = 0;
         }
 
         //*height -= (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY;
-        if(__builtin_add_overflow(frame_crop_top_offset, frame_crop_bottom_offset, &frame_crop_top_offset) ||
-            __builtin_mul_overflow(frame_crop_top_offset, cropUnitY, &frame_crop_top_offset) ||
-            __builtin_sub_overflow(*height, frame_crop_top_offset, height) ||
+        if(__builtin_add_overflow(
+                   frame_crop_top_offset, frame_crop_bottom_offset, &frame_crop_top_offset) ||
+           __builtin_mul_overflow(frame_crop_top_offset, cropUnitY, &frame_crop_top_offset) ||
+           __builtin_sub_overflow(*height, frame_crop_top_offset, height) ||
             *height < 0) {
             *height = 0;
         }
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
index c6c12ff..87cf58b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
@@ -28,6 +28,10 @@
 #undef HIDE
 #define HIDE __attribute__((visibility("hidden")))
 
+// The internals of AUnion cause problems with CFI
+#undef  NO_CFI
+#define NO_CFI __attribute__((no_sanitize("cfi")))
+
 namespace android {
 
 /**
@@ -93,7 +97,7 @@
      * \param args      arbitrary arguments for constructor
      */
     template<typename T, typename ...Args>
-    inline static void emplace(size_t totalSize, T *addr, Args&&... args) {
+    inline static void NO_CFI emplace(size_t totalSize, T *addr, Args&&... args) {
         new(addr)T(std::forward<Args>(args)...);
         // clear slack space - this is not technically required
         constexpr size_t size = sizeof(T);
@@ -160,7 +164,7 @@
     template<
             typename T, typename ...Args,
             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
-    inline void emplace(Args&&... args) {
+    inline void NO_CFI emplace(Args&&... args) {
         _AUnion_impl::emplace(
                 sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
     }
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
index 742651e..b5d6666 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
@@ -63,6 +63,7 @@
     AMessage();
     AMessage(uint32_t what, const sp<const AHandler> &handler);
 
+#ifndef __ANDROID_VNDK__
     // Construct an AMessage from a parcel.
     // nestingAllowed determines how many levels AMessage can be nested inside
     // AMessage. The default value here is arbitrarily set to 255.
@@ -87,6 +88,7 @@
     // All items in the AMessage must have types that are recognized by
     // FromParcel(); otherwise, TRESPASS error will occur.
     void writeToParcel(Parcel *parcel) const;
+#endif
 
     void setWhat(uint32_t what);
     uint32_t what() const;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
index 0f6299c..deef0d4 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
@@ -89,8 +89,10 @@
 
     void tolower();
 
+#ifndef __ANDROID_VNDK__
     static AString FromParcel(const Parcel &parcel);
     status_t writeToParcel(Parcel *parcel) const;
+#endif
 
 private:
     constexpr static const char *kEmptyString = "";
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
new file mode 100644
index 0000000..f2157c9
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -0,0 +1,27 @@
+cc_test {
+    name: "sf_foundation_test",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    include_dirs: [
+        "frameworks/av/include",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    srcs: [
+        "AData_test.cpp",
+        "Base64_test.cpp",
+        "Flagged_test.cpp",
+        "TypeTraits_test.cpp",
+        "Utils_test.cpp",
+    ],
+}
diff --git a/media/libstagefright/foundation/tests/Android.mk b/media/libstagefright/foundation/tests/Android.mk
deleted file mode 100644
index a9e3c76..0000000
--- a/media/libstagefright/foundation/tests/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := sf_foundation_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-	AData_test.cpp \
-	Base64_test.cpp \
-	Flagged_test.cpp \
-	TypeTraits_test.cpp \
-	Utils_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libstagefright_foundation \
-	libutils \
-
-LOCAL_C_INCLUDES := \
-	frameworks/av/include \
-
-LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
-
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/media/libstagefright/http/ClearMediaHTTP.cpp b/media/libstagefright/http/ClearMediaHTTP.cpp
deleted file mode 100644
index 9557c8a..0000000
--- a/media/libstagefright/http/ClearMediaHTTP.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 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 "ClearMediaHTTP"
-#include <utils/Log.h>
-
-#include <media/stagefright/ClearMediaHTTP.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/Utils.h>
-
-#include <media/MediaHTTPConnection.h>
-
-namespace android {
-
-ClearMediaHTTP::ClearMediaHTTP(const sp<MediaHTTPConnection> &conn)
-    : mInitCheck((conn != NULL) ? OK : NO_INIT),
-      mHTTPConnection(conn),
-      mCachedSizeValid(false),
-      mCachedSize(0ll) {
-}
-
-ClearMediaHTTP::~ClearMediaHTTP() {
-}
-
-status_t ClearMediaHTTP::connect(
-        const char *uri,
-        const KeyedVector<String8, String8> *headers,
-        off64_t /* offset */) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    KeyedVector<String8, String8> extHeaders;
-    if (headers != NULL) {
-        extHeaders = *headers;
-    }
-
-    if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
-        extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
-    }
-
-    mLastURI = uri;
-    // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
-    // as part of the above assignment. Ensure no accidental later use.
-    uri = NULL;
-
-    bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
-
-    mLastHeaders = extHeaders;
-
-    mCachedSizeValid = false;
-
-    if (success) {
-        AString sanitized = uriDebugString(mLastURI);
-        mName = String8::format("ClearMediaHTTP(%s)", sanitized.c_str());
-    }
-
-    return success ? OK : UNKNOWN_ERROR;
-}
-
-void ClearMediaHTTP::close() {
-    disconnect();
-}
-
-void ClearMediaHTTP::disconnect() {
-    mName = String8("ClearMediaHTTP(<disconnected>)");
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    mHTTPConnection->disconnect();
-}
-
-status_t ClearMediaHTTP::initCheck() const {
-    return mInitCheck;
-}
-
-ssize_t ClearMediaHTTP::readAt(off64_t offset, void *data, size_t size) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    int64_t startTimeUs = ALooper::GetNowUs();
-
-    size_t numBytesRead = 0;
-    while (numBytesRead < size) {
-        size_t copy = size - numBytesRead;
-
-        if (copy > 64 * 1024) {
-            // limit the buffer sizes transferred across binder boundaries
-            // to avoid spurious transaction failures.
-            copy = 64 * 1024;
-        }
-
-        ssize_t n = mHTTPConnection->readAt(
-                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
-
-        if (n < 0) {
-            return n;
-        } else if (n == 0) {
-            break;
-        }
-
-        numBytesRead += n;
-    }
-
-    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
-
-    addBandwidthMeasurement(numBytesRead, delayUs);
-
-    return numBytesRead;
-}
-
-status_t ClearMediaHTTP::getSize(off64_t *size) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    // Caching the returned size so that it stays valid even after a
-    // disconnect. NuCachedSource2 relies on this.
-
-    if (!mCachedSizeValid) {
-        mCachedSize = mHTTPConnection->getSize();
-        mCachedSizeValid = true;
-    }
-
-    *size = mCachedSize;
-
-    return *size < 0 ? *size : static_cast<status_t>(OK);
-}
-
-uint32_t ClearMediaHTTP::flags() {
-    return kWantsPrefetching | kIsHTTPBasedSource;
-}
-
-status_t ClearMediaHTTP::reconnectAtOffset(off64_t offset) {
-    return connect(mLastURI.c_str(), &mLastHeaders, offset);
-}
-
-
-String8 ClearMediaHTTP::getUri() {
-    if (mInitCheck != OK) {
-        return String8::empty();
-    }
-
-    String8 uri;
-    if (OK == mHTTPConnection->getUri(&uri)) {
-        return uri;
-    }
-    return String8(mLastURI.c_str());
-}
-
-String8 ClearMediaHTTP::getMIMEType() const {
-    if (mInitCheck != OK) {
-        return String8("application/octet-stream");
-    }
-
-    String8 mimeType;
-    status_t err = mHTTPConnection->getMIMEType(&mimeType);
-
-    if (err != OK) {
-        return String8("application/octet-stream");
-    }
-
-    return mimeType;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/http/MediaHTTP.cpp b/media/libstagefright/http/MediaHTTP.cpp
deleted file mode 100644
index 0fba3dc..0000000
--- a/media/libstagefright/http/MediaHTTP.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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 "MediaHTTP"
-#include <utils/Log.h>
-
-#include <media/stagefright/MediaHTTP.h>
-
-#include <binder/IServiceManager.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/Utils.h>
-
-#include <media/MediaHTTPConnection.h>
-
-namespace android {
-
-MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
-    : ClearMediaHTTP(conn),
-      mDrmManagerClient(NULL) {
-}
-
-MediaHTTP::~MediaHTTP() {
-    clearDRMState_l();
-}
-
-// DRM...
-
-sp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
-    if (mDrmManagerClient == NULL) {
-        mDrmManagerClient = new DrmManagerClient();
-    }
-
-    if (mDrmManagerClient == NULL) {
-        return NULL;
-    }
-
-    if (mDecryptHandle == NULL) {
-        mDecryptHandle = mDrmManagerClient->openDecryptSession(
-                String8(mLastURI.c_str()), mime);
-    }
-
-    if (mDecryptHandle == NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-
-    return mDecryptHandle;
-}
-
-void MediaHTTP::clearDRMState_l() {
-    if (mDecryptHandle != NULL) {
-        // To release mDecryptHandle
-        CHECK(mDrmManagerClient);
-        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
-        mDecryptHandle = NULL;
-    }
-}
-
-}  // namespace android
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index c0ee14e..12e7ca6 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -31,6 +31,7 @@
         "liblog",
         "libcrypto",
         "libcutils",
+        "libdatasource",
         "libmedia",
         "libmediandk",
         "libstagefright",
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index c7e92cd..68f1de9 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -21,13 +21,13 @@
 #include "HTTPDownloader.h"
 #include "M3UParser.h"
 
+#include <datasource/MediaHTTP.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ClearMediaHTTP.h>
-#include <media/stagefright/ClearFileSource.h>
 #include <openssl/aes.h>
 #include <openssl/md5.h>
 #include <utils/Mutex.h>
@@ -38,7 +38,7 @@
 HTTPDownloader::HTTPDownloader(
         const sp<MediaHTTPService> &httpService,
         const KeyedVector<String8, String8> &headers) :
-    mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())),
+    mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())),
     mExtraHeaders(headers),
     mDisconnecting(false) {
 }
@@ -91,7 +91,7 @@
 
     if (reconnect) {
         if (!strncasecmp(url, "file://", 7)) {
-            mDataSource = new ClearFileSource(url + 7);
+            mDataSource = new FileSource(url + 7);
         } else if (strncasecmp(url, "http://", 7)
                 && strncasecmp(url, "https://", 8)) {
             return ERROR_UNSUPPORTED;
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 9cf97c7..3bad015 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -34,6 +34,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <utils/Mutex.h>
 
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index cb97a3c..4324c45 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -27,6 +27,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 #include <media/mediaplayer.h>
 
 namespace android {
@@ -614,7 +615,7 @@
                 if (mIsVariantPlaylist) {
                     return ERROR_MALFORMED;
                 }
-                err = parseCipherInfo(line, &itemMeta, mBaseURI);
+                err = parseCipherInfo(line, &itemMeta);
             } else if (line.startsWith("#EXT-X-ENDLIST")) {
                 mIsComplete = true;
             } else if (line.startsWith("#EXT-X-PLAYLIST-TYPE:EVENT")) {
@@ -935,7 +936,7 @@
 
 // static
 status_t M3UParser::parseCipherInfo(
-        const AString &line, sp<AMessage> *meta, const AString &baseURI) {
+        const AString &line, sp<AMessage> *meta) {
     ssize_t colonPos = line.find(":");
 
     if (colonPos < 0) {
@@ -984,13 +985,9 @@
                     val = tmp;
                 }
 
-                AString absURI;
-                if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) {
-                    val = absURI;
-                } else {
-                    ALOGE("failed to make absolute url for %s.",
-                            uriDebugString(baseURI).c_str());
-                }
+                // To save space, we only store the partial Uri here
+                // The full Uri will be constructed from this plus
+                // the base Uri as needed by PlaylistFetcher
             }
 
             key.insert(AString("cipher-"), 0);
@@ -1002,6 +999,14 @@
     return OK;
 }
 
+AString M3UParser::getFullCipherUri(const AString &partial) {
+    AString full;
+    if (MakeURL(mBaseURI.c_str(), partial.c_str(), &full)) {
+        return full;
+    }
+    return AString("");
+}
+
 // static
 status_t M3UParser::parseByteRange(
         const AString &line, uint64_t curOffset,
diff --git a/media/libstagefright/httplive/M3UParser.h b/media/libstagefright/httplive/M3UParser.h
index c85335a..9f7a66a 100644
--- a/media/libstagefright/httplive/M3UParser.h
+++ b/media/libstagefright/httplive/M3UParser.h
@@ -55,6 +55,8 @@
     bool getTypeURI(size_t index, const char *key, AString *uri) const;
     bool hasType(size_t index, const char *key) const;
 
+    AString getFullCipherUri(const AString &partial);
+
 protected:
     virtual ~M3UParser();
 
@@ -99,7 +101,7 @@
             const AString &line, sp<AMessage> *meta) const;
 
     static status_t parseCipherInfo(
-            const AString &line, sp<AMessage> *meta, const AString &baseURI);
+            const AString &line, sp<AMessage> *meta);
 
     static status_t parseByteRange(
             const AString &line, uint64_t curOffset,
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 635ecfe..b23aa8a 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -28,17 +28,18 @@
 #include "mpeg2ts/AnotherPacketSource.h"
 #include "mpeg2ts/HlsSampleDecryptor.h"
 
+#include <datasource/DataURISource.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/foundation/MediaKeys.h>
 #include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/DataURISource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MetaDataUtils.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <ctype.h>
 #include <inttypes.h>
@@ -344,6 +345,7 @@
         ALOGE("Missing key uri");
         return ERROR_MALFORMED;
     }
+    keyURI = mPlaylist->getFullCipherUri(keyURI);
 
     ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
 
@@ -2160,7 +2162,9 @@
             return ERROR_MALFORMED;
         }
 
-        CHECK_LE(offset + aac_frame_length, buffer->size());
+        if (aac_frame_length > buffer->size() - offset) {
+            return ERROR_MALFORMED;
+        }
 
         int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
         offset += aac_frame_length;
diff --git a/media/libstagefright/id3/Android.bp b/media/libstagefright/id3/Android.bp
index 7151d07..db37fe9 100644
--- a/media/libstagefright/id3/Android.bp
+++ b/media/libstagefright/id3/Android.bp
@@ -1,9 +1,11 @@
 cc_library_static {
     name: "libstagefright_id3",
+    min_sdk_version: "29",
 
     srcs: ["ID3.cpp"],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 
@@ -33,6 +35,7 @@
     ],
 
     shared_libs: [
+        "libdatasource",
         "libstagefright",
         "libutils",
         "liblog",
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 792a68a..e97f6eb 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -32,7 +32,7 @@
 
 static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
 
-struct MemorySource : public DataSourceBase {
+struct ID3::MemorySource : public DataSourceBase {
     MemorySource(const uint8_t *data, size_t size)
         : mData(data),
           mSize(size) {
@@ -58,7 +58,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
 };
 
-class DataSourceUnwrapper : public DataSourceBase {
+class ID3::DataSourceUnwrapper : public DataSourceBase {
 
 public:
     explicit DataSourceUnwrapper(DataSourceHelper *sourcehelper) {
@@ -107,20 +107,6 @@
     }
 }
 
-ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
-    : mIsValid(false),
-      mData(NULL),
-      mSize(0),
-      mFirstFrameOffset(0),
-      mVersion(ID3_UNKNOWN),
-      mRawSize(0) {
-    mIsValid = parseV2(source, offset);
-
-    if (!mIsValid && !ignoreV1) {
-        mIsValid = parseV1(source);
-    }
-}
-
 ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
     : mIsValid(false),
       mData(NULL),
@@ -247,44 +233,14 @@
         return false;
     }
 
-    if (header.version_major == 4) {
-        void *copy = malloc(size);
-        if (copy == NULL) {
-            free(mData);
-            mData = NULL;
-            ALOGE("b/24623447, no more memory");
-            return false;
-        }
-
-        memcpy(copy, mData, size);
-
-        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
-        if (!success) {
-            memcpy(mData, copy, size);
-            mSize = size;
-
-            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
-
-            if (success) {
-                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
-            }
-        }
-
-        free(copy);
-        copy = NULL;
-
-        if (!success) {
-            free(mData);
-            mData = NULL;
-
-            return false;
-        }
-    } else if (header.flags & 0x80) {
+    // first handle global unsynchronization
+    if (header.flags & 0x80) {
         ALOGV("removing unsynchronization");
 
         removeUnsynchronization();
     }
 
+    // handle extended header, if present
     mFirstFrameOffset = 0;
     if (header.version_major == 3 && (header.flags & 0x40)) {
         // Version 2.3 has an optional extended header.
@@ -296,6 +252,7 @@
             return false;
         }
 
+        // v2.3 does not have syncsafe integers
         size_t extendedHeaderSize = U32_AT(&mData[0]);
         if (extendedHeaderSize > SIZE_MAX - 4) {
             free(mData);
@@ -367,6 +324,48 @@
         mFirstFrameOffset = ext_size;
     }
 
+    // Handle any v2.4 per-frame unsynchronization
+    // The id3 spec isn't clear about what should happen if the global
+    // unsynchronization flag is combined with per-frame unsynchronization,
+    // or whether that's even allowed, so this code assumes id3 writing
+    // tools do the right thing and not apply double-unsynchronization,
+    // but will honor the flags if they are set.
+    if (header.version_major == 4) {
+        void *copy = malloc(size);
+        if (copy == NULL) {
+            free(mData);
+            mData = NULL;
+            ALOGE("b/24623447, no more memory");
+            return false;
+        }
+
+        memcpy(copy, mData, size);
+
+        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
+        if (!success) {
+            memcpy(mData, copy, size);
+            mSize = size;
+
+            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
+
+            if (success) {
+                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
+            }
+        }
+
+        free(copy);
+        copy = NULL;
+
+        if (!success) {
+            free(mData);
+            mData = NULL;
+
+            return false;
+        }
+    }
+
+
+
     if (header.version_major == 2) {
         mVersion = ID3_V2_2;
     } else if (header.version_major == 3) {
@@ -411,7 +410,7 @@
 bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
     size_t oldSize = mSize;
 
-    size_t offset = 0;
+    size_t offset = mFirstFrameOffset;
     while (mSize >= 10 && offset <= mSize - 10) {
         if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
             break;
@@ -445,7 +444,7 @@
         }
 
         if ((flags & 2) && (dataSize >= 2)) {
-            // This file has "unsynchronization", so we have to replace occurrences
+            // This frame has "unsynchronization", so we have to replace occurrences
             // of 0xff 0x00 with just 0xff in order to get the real data.
 
             size_t readOffset = offset + 11;
diff --git a/media/libstagefright/id3/test/Android.bp b/media/libstagefright/id3/test/Android.bp
new file mode 100644
index 0000000..9d26eec
--- /dev/null
+++ b/media/libstagefright/id3/test/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "ID3Test",
+    gtest: true,
+
+    srcs: ["ID3Test.cpp"],
+
+    static_libs: [
+        "libdatasource",
+        "libstagefright_id3",
+        "libstagefright",
+        "libstagefright_foundation",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+        "libbinder",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/id3/test/AndroidTest.xml b/media/libstagefright/id3/test/AndroidTest.xml
new file mode 100644
index 0000000..6c6697d
--- /dev/null
+++ b/media/libstagefright/id3/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for ID3 unit tests">
+    <option name="test-suite-tag" value="ID3Test" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test.zip?unzip=true"
+            value="/data/local/tmp/ID3TestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="ID3Test" />
+        <option name="native-test-flag" value="-P /data/local/tmp/ID3TestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/libstagefright/id3/test/ID3Test.cpp
new file mode 100644
index 0000000..cd5cd9e
--- /dev/null
+++ b/media/libstagefright/id3/test/ID3Test.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2019 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 "ID3Test"
+#include <utils/Log.h>
+
+#include <ctype.h>
+#include <string>
+#include <sys/stat.h>
+#include <datasource/FileSource.h>
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/MediaExtractorPluginHelper.h>
+#include <ID3.h>
+
+#include "ID3TestEnvironment.h"
+
+using namespace android;
+
+static ID3TestEnvironment *gEnv = nullptr;
+
+class ID3tagTest : public ::testing::TestWithParam<string> {};
+class ID3versionTest : public ::testing::TestWithParam<pair<string, int>> {};
+class ID3textTagTest : public ::testing::TestWithParam<pair<string, int>> {};
+class ID3albumArtTest : public ::testing::TestWithParam<pair<string, bool>> {};
+class ID3multiAlbumArtTest : public ::testing::TestWithParam<pair<string, int>> {};
+
+TEST_P(ID3tagTest, TagTest) {
+    string path = gEnv->getRes() + GetParam();
+    sp<FileSource> file = new FileSource(path.c_str());
+    ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
+    ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
+
+    ID3::Iterator it(tag, nullptr);
+    while (!it.done()) {
+        String8 id;
+        it.getID(&id);
+        ASSERT_GT(id.length(), 0) << "No ID tag found! \n";
+        ALOGV("Found ID tag: %s\n", String8(id).c_str());
+        it.next();
+    }
+}
+
+TEST_P(ID3versionTest, VersionTest) {
+    int versionNumber = GetParam().second;
+    string path = gEnv->getRes() + GetParam().first;
+    sp<android::FileSource> file = new FileSource(path.c_str());
+    ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
+
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
+    ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
+    ASSERT_TRUE(tag.version() >= versionNumber)
+            << "Expected version: " << tag.version() << " Found version: " << versionNumber;
+}
+
+TEST_P(ID3textTagTest, TextTagTest) {
+    int numTextFrames = GetParam().second;
+    string path = gEnv->getRes() + GetParam().first;
+    sp<android::FileSource> file = new FileSource(path.c_str());
+    ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
+
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
+    ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
+    int countTextFrames = 0;
+    ID3::Iterator it(tag, nullptr);
+    while (!it.done()) {
+        String8 id;
+        it.getID(&id);
+        ASSERT_GT(id.length(), 0);
+        if (id[0] == 'T') {
+            String8 text;
+            countTextFrames++;
+            it.getString(&text);
+            ALOGV("Found text frame %s : %s \n", id.string(), text.string());
+        }
+        it.next();
+    }
+    ASSERT_EQ(countTextFrames, numTextFrames)
+            << "Expected " << numTextFrames << " text frames, found " << countTextFrames;
+}
+
+TEST_P(ID3albumArtTest, AlbumArtTest) {
+    bool albumArtPresent = GetParam().second;
+    string path = gEnv->getRes() + GetParam().first;
+    sp<android::FileSource> file = new FileSource(path.c_str());
+    ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
+
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
+    ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
+    size_t dataSize;
+    String8 mime;
+    const void *data = tag.getAlbumArt(&dataSize, &mime);
+
+    if (albumArtPresent) {
+        if (data) {
+            ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+        }
+        ASSERT_NE(data, nullptr) << "Expected album art, found none!" << path;
+    } else {
+        ASSERT_EQ(data, nullptr) << "Found album art when expected none!";
+    }
+#if (LOG_NDEBUG == 0)
+    hexdump(data, dataSize > 128 ? 128 : dataSize);
+#endif
+}
+
+TEST_P(ID3multiAlbumArtTest, MultiAlbumArtTest) {
+    int numAlbumArt = GetParam().second;
+    string path = gEnv->getRes() + GetParam().first;
+    sp<android::FileSource> file = new FileSource(path.c_str());
+    ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
+
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
+    ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
+    int count = 0;
+    ID3::Iterator it(tag, nullptr);
+    while (!it.done()) {
+        String8 id;
+        it.getID(&id);
+        ASSERT_GT(id.length(), 0);
+        // Check if the tag is an "APIC/PIC" tag.
+        if (String8(id) == "APIC" || String8(id) == "PIC") {
+            count++;
+            size_t dataSize;
+            String8 mime;
+            const void *data = tag.getAlbumArt(&dataSize, &mime);
+            if (data) {
+                ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+#if (LOG_NDEBUG == 0)
+                hexdump(data, dataSize > 128 ? 128 : dataSize);
+#endif
+            }
+            ASSERT_NE(data, nullptr) << "Expected album art, found none!" << path;
+        }
+        it.next();
+    }
+    ASSERT_EQ(count, numAlbumArt) << "Found " << count << " album arts, expected " << numAlbumArt
+                                  << " album arts! \n";
+}
+
+INSTANTIATE_TEST_SUITE_P(id3TestAll, ID3tagTest,
+                         ::testing::Values("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_5mins.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3",
+                                           "bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3"));
+
+INSTANTIATE_TEST_SUITE_P(
+        id3TestAll, ID3versionTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 4),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3", 4)));
+
+INSTANTIATE_TEST_SUITE_P(
+        id3TestAll, ID3textTagTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_moreTextFrames.mp3", 5)));
+
+INSTANTIATE_TEST_SUITE_P(
+        id3TestAll, ID3albumArtTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", false),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", true),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", true),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", false),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", true),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", true),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", true)));
+
+INSTANTIATE_TEST_SUITE_P(
+        id3TestAll, ID3multiAlbumArtTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", 0),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_1_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_1_image.mp3", 1),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec_2_image.mp3", 2),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_2_image.mp3", 2),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins_largeSize.mp3", 3)));
+
+int main(int argc, char **argv) {
+    gEnv = new ID3TestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGI("ID3 Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/id3/test/ID3TestEnvironment.h b/media/libstagefright/id3/test/ID3TestEnvironment.h
new file mode 100644
index 0000000..2229718
--- /dev/null
+++ b/media/libstagefright/id3/test/ID3TestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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 __ID3_TEST_ENVIRONMENT_H__
+#define __ID3_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class ID3TestEnvironment : public::testing::Environment {
+  public:
+    ID3TestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int ID3TestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __ID3_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/id3/test/README.md b/media/libstagefright/id3/test/README.md
new file mode 100644
index 0000000..7fd8901
--- /dev/null
+++ b/media/libstagefright/id3/test/README.md
@@ -0,0 +1,40 @@
+## Media Testing ##
+---
+#### ID3 Test :
+The ID3 Test Suite validates the ID3 parser available in libstagefright.
+
+Run the following command in the id3 folder to build the test suite:
+```
+m ID3Test
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/ID3Test/ID3Test /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/ID3Test/ID3Test /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test.zip ).
+Download, unzip and push these files into device for testing.
+
+```
+adb push ID3Test /data/local/tmp/
+```
+
+usage: ID3Test -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/ID3Test -P /data/local/tmp/ID3/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ID3Test -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index 86e6adf..5cd51cf 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -22,8 +22,9 @@
 #include <dirent.h>
 
 #include <binder/ProcessState.h>
-#include <media/stagefright/FileSource.h>
+#include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/MediaExtractorPluginHelper.h>
 
 #define MAXPATHLEN 256
 
@@ -72,7 +73,8 @@
     sp<FileSource> file = new FileSource(path);
     CHECK_EQ(file->initCheck(), (status_t)OK);
 
-    ID3 tag(file.get());
+    DataSourceHelper helper(file->wrap());
+    ID3 tag(&helper);
     if (!tag.isValid()) {
         printf("FAIL %s\n", path);
     } else {
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 7c01e45..da962d1 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -25,7 +25,7 @@
 
 #include <media/openmax/OMX_Types.h>
 #include <media/stagefright/CodecBase.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/IOMX.h>
 
 namespace android {
@@ -67,6 +67,9 @@
     virtual ~ACodecBufferChannel();
 
     // BufferChannelBase interface
+    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(
             const sp<MediaCodecBuffer> &buffer,
@@ -78,6 +81,20 @@
             const CryptoPlugin::SubSample *subSamples,
             size_t numSubSamples,
             AString *errorDetailMsg) override;
+    virtual status_t attachBuffer(
+            const std::shared_ptr<C2Buffer> &c2Buffer,
+            const sp<MediaCodecBuffer> &buffer) override;
+    virtual status_t attachEncryptedBuffer(
+            const sp<hardware::HidlMemory> &memory,
+            bool secure,
+            const uint8_t *key,
+            const uint8_t *iv,
+            CryptoPlugin::Mode mode,
+            CryptoPlugin::Pattern pattern,
+            size_t offset,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
     virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -115,12 +132,15 @@
     void drainThisBuffer(IOMX::buffer_id bufferID, OMX_U32 omxFlags);
 
 private:
+    int32_t getHeapSeqNum(const sp<HidlMemory> &memory);
+
     const sp<AMessage> mInputBufferFilled;
     const sp<AMessage> mOutputBufferDrained;
 
     sp<MemoryDealer> mDealer;
     sp<IMemory> mDecryptDestination;
     int32_t mHeapSeqNum;
+    std::map<wp<HidlMemory>, int32_t> mHeapSeqNumMap;
     sp<HidlMemory> mHidlMemory;
 
     // These should only be accessed via std::atomic_* functions.
@@ -135,6 +155,9 @@
 
     sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
 
+    sp<ICrypto> mCrypto;
+    sp<IDescrambler> mDescrambler;
+
     bool hasCryptoOrDescrambler() {
         return mCrypto != NULL || mDescrambler != NULL;
     }
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..e428494 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -41,7 +41,6 @@
     virtual String8 toString() {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
     virtual sp<IDataSource> getIDataSource() const;
 
 private:
@@ -70,7 +69,6 @@
     virtual String8 toString() {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
     virtual sp<IDataSource> getIDataSource() const;
 
 private:
diff --git a/media/libstagefright/include/FrameCaptureLayer.h b/media/libstagefright/include/FrameCaptureLayer.h
new file mode 100644
index 0000000..23fd5e5
--- /dev/null
+++ b/media/libstagefright/include/FrameCaptureLayer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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 FRAME_CAPTURE_LAYER_H_
+#define FRAME_CAPTURE_LAYER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <gui/IConsumerListener.h>
+#include <ui/GraphicTypes.h>
+#include <utils/Mutex.h>
+#include <utils/Condition.h>
+
+namespace android {
+
+class GraphicBuffer;
+class IGraphicBufferConsumer;
+class Rect;
+class Surface;
+
+/*
+ * This class is a simple BufferQueue consumer implementation to
+ * obtain a decoded buffer output from MediaCodec. The output
+ * buffer is then sent to FrameCaptureProcessor to be converted
+ * to sRGB properly.
+ */
+struct FrameCaptureLayer : public ConsumerListener {
+    FrameCaptureLayer();
+    ~FrameCaptureLayer() = default;
+
+    // ConsumerListener
+    void onFrameAvailable(const BufferItem& /*item*/) override;
+    void onBuffersReleased() override;
+    void onSidebandStreamChanged() override;
+
+    status_t init();
+
+    sp<Surface> getSurface() { return mSurface; }
+
+    status_t capture(const ui::PixelFormat reqPixelFormat,
+            const Rect &sourceCrop, sp<GraphicBuffer> *outBuffer);
+
+private:
+    struct BufferLayer;
+    // Note: do not hold any sp ref to GraphicBufferSource
+    // GraphicBufferSource is holding an sp to us, holding any sp ref
+    // to GraphicBufferSource will cause circular dependency and both
+    // object will not be released.
+    sp<IGraphicBufferConsumer> mConsumer;
+    sp<Surface> mSurface;
+    std::map<int32_t, sp<GraphicBuffer> > mSlotToBufferMap;
+
+    Mutex mLock;
+    Condition mCondition;
+    bool mFrameAvailable GUARDED_BY(mLock);
+
+    status_t acquireBuffer(BufferItem *bi);
+    status_t releaseBuffer(const BufferItem &bi);
+
+    DISALLOW_EVIL_CONSTRUCTORS(FrameCaptureLayer);
+};
+
+}  // namespace android
+
+#endif  // FRAME_CAPTURE_LAYER_H_
diff --git a/media/libstagefright/include/FrameDecoder.h b/media/libstagefright/include/FrameDecoder.h
index dc58c15..19ae0e3 100644
--- a/media/libstagefright/include/FrameDecoder.h
+++ b/media/libstagefright/include/FrameDecoder.h
@@ -22,17 +22,18 @@
 
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/ABase.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/openmax/OMX_Video.h>
-#include <system/graphics-base.h>
+#include <ui/GraphicTypes.h>
 
 namespace android {
 
 struct AMessage;
-class MediaCodecBuffer;
-class IMediaSource;
-class VideoFrame;
 struct MediaCodec;
+class IMediaSource;
+class MediaCodecBuffer;
+class Surface;
+class VideoFrame;
 
 struct FrameRect {
     int32_t left, top, right, bottom;
@@ -44,13 +45,10 @@
             const sp<MetaData> &trackMeta,
             const sp<IMediaSource> &source);
 
-    status_t init(
-            int64_t frameTimeUs, size_t numFrames, int option, int colorFormat);
+    status_t init(int64_t frameTimeUs, int option, int colorFormat);
 
     sp<IMemory> extractFrame(FrameRect *rect = NULL);
 
-    status_t extractFrames(std::vector<sp<IMemory> >* frames);
-
     static sp<IMemory> getMetadataOnly(
             const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false);
 
@@ -59,9 +57,9 @@
 
     virtual sp<AMessage> onGetFormatAndSeekOptions(
             int64_t frameTimeUs,
-            size_t numFrames,
             int seekMode,
-            MediaSource::ReadOptions *options) = 0;
+            MediaSource::ReadOptions *options,
+            sp<Surface> *window) = 0;
 
     virtual status_t onExtractRect(FrameRect *rect) = 0;
 
@@ -79,29 +77,30 @@
 
     sp<MetaData> trackMeta()     const      { return mTrackMeta; }
     OMX_COLOR_FORMATTYPE dstFormat() const  { return mDstFormat; }
+    ui::PixelFormat captureFormat() const   { return mCaptureFormat; }
     int32_t dstBpp()             const      { return mDstBpp; }
-
-    void addFrame(const sp<IMemory> &frame) {
-        mFrames.push_back(frame);
-    }
+    void setFrame(const sp<IMemory> &frameMem) { mFrameMemory = frameMem; }
 
 private:
     AString mComponentName;
     sp<MetaData> mTrackMeta;
     sp<IMediaSource> mSource;
     OMX_COLOR_FORMATTYPE mDstFormat;
+    ui::PixelFormat mCaptureFormat;
     int32_t mDstBpp;
-    std::vector<sp<IMemory> > mFrames;
+    sp<IMemory> mFrameMemory;
     MediaSource::ReadOptions mReadOptions;
     sp<MediaCodec> mDecoder;
     sp<AMessage> mOutputFormat;
     bool mHaveMoreInputs;
     bool mFirstSample;
+    sp<Surface> mSurface;
 
     status_t extractInternal();
 
     DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder);
 };
+struct FrameCaptureLayer;
 
 struct VideoFrameDecoder : public FrameDecoder {
     VideoFrameDecoder(
@@ -112,9 +111,9 @@
 protected:
     virtual sp<AMessage> onGetFormatAndSeekOptions(
             int64_t frameTimeUs,
-            size_t numFrames,
             int seekMode,
-            MediaSource::ReadOptions *options) override;
+            MediaSource::ReadOptions *options,
+            sp<Surface> *window) override;
 
     virtual status_t onExtractRect(FrameRect *rect) override {
         // Rect extraction for sequences is not supported for now.
@@ -134,11 +133,16 @@
             bool *done) override;
 
 private:
+    sp<FrameCaptureLayer> mCaptureLayer;
+    VideoFrame *mFrame;
     bool mIsAvcOrHevc;
     MediaSource::ReadOptions::SeekMode mSeekMode;
     int64_t mTargetTimeUs;
-    size_t mNumFrames;
-    size_t mNumFramesDecoded;
+    List<int64_t> mSampleDurations;
+    int64_t mDefaultSampleDurationUs;
+
+    sp<Surface> initSurface();
+    status_t captureSurface();
 };
 
 struct ImageDecoder : public FrameDecoder {
@@ -150,9 +154,9 @@
 protected:
     virtual sp<AMessage> onGetFormatAndSeekOptions(
             int64_t frameTimeUs,
-            size_t numFrames,
             int seekMode,
-            MediaSource::ReadOptions *options) override;
+            MediaSource::ReadOptions *options,
+            sp<Surface> *window) override;
 
     virtual status_t onExtractRect(FrameRect *rect) override;
 
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
deleted file mode 100644
index 8b20187..0000000
--- a/media/libstagefright/include/HTTPBase.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 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 HTTP_BASE_H_
-
-#define HTTP_BASE_H_
-
-#include <media/DataSource.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/List.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct HTTPBase : public DataSource {
-    enum Flags {
-        // Don't log any URLs.
-        kFlagIncognito = 1
-    };
-
-    HTTPBase();
-
-    virtual status_t connect(
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL,
-            off64_t offset = 0) = 0;
-
-    virtual void disconnect() = 0;
-
-    // Returns true if bandwidth could successfully be estimated,
-    // false otherwise.
-    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
-
-    virtual status_t getEstimatedBandwidthKbps(int32_t *kbps);
-
-    virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
-
-    virtual void setBandwidthHistorySize(size_t numHistoryItems);
-
-    virtual String8 toString() {
-        return mName;
-    }
-
-protected:
-    virtual void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
-    String8 mName;
-
-private:
-    struct BandwidthEntry {
-        int64_t mDelayUs;
-        size_t mNumBytes;
-    };
-
-    Mutex mLock;
-
-    List<BandwidthEntry> mBandwidthHistory;
-    size_t mNumBandwidthHistoryItems;
-    int64_t mTotalTransferTimeUs;
-    size_t mTotalTransferBytes;
-    size_t mMaxBandwidthHistoryItems;
-
-    enum {
-        kMinBandwidthCollectFreqMs = 1000,   // 1 second
-        kMaxBandwidthCollectFreqMs = 60000,  // one minute
-    };
-
-    int64_t mPrevBandwidthMeasureTimeUs;
-    int32_t mPrevEstimatedBandWidthKbps;
-    int32_t mBandWidthCollectFreqMs;
-
-    DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
-};
-
-}  // namespace android
-
-#endif  // HTTP_BASE_H_
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 5e433ea..0be5896 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -37,7 +37,6 @@
     };
 
     explicit ID3(DataSourceHelper *source, bool ignoreV1 = false, off64_t offset = 0);
-    explicit ID3(DataSourceBase *source, bool ignoreV1 = false, off64_t offset = 0);
     ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
     ~ID3();
 
@@ -77,6 +76,8 @@
     size_t rawSize() const { return mRawSize; }
 
 private:
+    class DataSourceUnwrapper;
+    struct MemorySource;
     bool mIsValid;
     uint8_t *mData;
     size_t mSize;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
deleted file mode 100644
index 596efb8..0000000
--- a/media/libstagefright/include/NuCachedSource2.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2010 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 NU_CACHED_SOURCE_2_H_
-
-#define NU_CACHED_SOURCE_2_H_
-
-#include <media/DataSource.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/AHandlerReflector.h>
-
-namespace android {
-
-struct ALooper;
-struct PageCache;
-
-struct NuCachedSource2 : public DataSource {
-    static sp<NuCachedSource2> Create(
-            const sp<DataSource> &source,
-            const char *cacheConfig = NULL,
-            bool disconnectAtHighwatermark = false);
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
-    virtual void close();
-
-    virtual void disconnect();
-
-    virtual status_t getSize(off64_t *size);
-    virtual uint32_t flags();
-
-    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
-    virtual String8 getUri();
-
-    virtual String8 getMIMEType() const;
-
-    virtual String8 toString() {
-        return mName;
-    }
-
-    status_t getAvailableSize(off64_t offset, off64_t *size);
-
-    ////////////////////////////////////////////////////////////////////////////
-
-    size_t cachedSize();
-    size_t approxDataRemaining(status_t *finalStatus) const;
-
-    void resumeFetchingIfNecessary();
-
-    // The following methods are supported only if the
-    // data source is HTTP-based; otherwise, ERROR_UNSUPPORTED
-    // is returned.
-    status_t getEstimatedBandwidthKbps(int32_t *kbps);
-    status_t setCacheStatCollectFreq(int32_t freqMs);
-
-    static void RemoveCacheSpecificHeaders(
-            KeyedVector<String8, String8> *headers,
-            String8 *cacheConfig,
-            bool *disconnectAtHighwatermark);
-
-protected:
-    virtual ~NuCachedSource2();
-
-private:
-    friend struct AHandlerReflector<NuCachedSource2>;
-
-    NuCachedSource2(
-            const sp<DataSource> &source,
-            const char *cacheConfig,
-            bool disconnectAtHighwatermark);
-
-    enum {
-        kPageSize                       = 65536,
-        kDefaultHighWaterThreshold      = 20 * 1024 * 1024,
-        kDefaultLowWaterThreshold       = 4 * 1024 * 1024,
-
-        // Read data after a 15 sec timeout whether we're actively
-        // fetching or not.
-        kDefaultKeepAliveIntervalUs     = 15000000,
-    };
-
-    enum {
-        kWhatFetchMore  = 'fetc',
-        kWhatRead       = 'read',
-    };
-
-    enum {
-        kMaxNumRetries = 10,
-    };
-
-    sp<DataSource> mSource;
-    sp<AHandlerReflector<NuCachedSource2> > mReflector;
-    sp<ALooper> mLooper;
-    String8 mName;
-
-    Mutex mSerializer;
-    mutable Mutex mLock;
-    Condition mCondition;
-
-    PageCache *mCache;
-    off64_t mCacheOffset;
-    status_t mFinalStatus;
-    off64_t mLastAccessPos;
-    sp<AMessage> mAsyncResult;
-    bool mFetching;
-    bool mDisconnecting;
-    int64_t mLastFetchTimeUs;
-
-    int32_t mNumRetriesLeft;
-
-    size_t mHighwaterThresholdBytes;
-    size_t mLowwaterThresholdBytes;
-
-    // If the keep-alive interval is 0, keep-alives are disabled.
-    int64_t mKeepAliveIntervalUs;
-
-    bool mDisconnectAtHighwatermark;
-
-    void onMessageReceived(const sp<AMessage> &msg);
-    void onFetch();
-    void onRead(const sp<AMessage> &msg);
-
-    void fetchInternal();
-    ssize_t readInternal(off64_t offset, void *data, size_t size);
-    status_t seekInternal_l(off64_t offset);
-
-    size_t approxDataRemaining_l(off64_t offset, status_t *finalStatus) const;
-
-    void restartPrefetcherIfNecessary_l(
-            bool ignoreLowWaterThreshold = false, bool force = false);
-
-    void updateCacheParamsFromSystemProperty();
-    void updateCacheParamsFromString(const char *s);
-
-    DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
-};
-
-}  // namespace android
-
-#endif  // NU_CACHED_SOURCE_2_H_
diff --git a/media/libstagefright/include/SecureBuffer.h b/media/libstagefright/include/SecureBuffer.h
index cf7933a..c45e0e5 100644
--- a/media/libstagefright/include/SecureBuffer.h
+++ b/media/libstagefright/include/SecureBuffer.h
@@ -18,7 +18,7 @@
 
 #define SECURE_BUFFER_H_
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 
 namespace android {
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
deleted file mode 100644
index c50677a..0000000
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 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 STAGEFRIGHT_METADATA_RETRIEVER_H_
-
-#define STAGEFRIGHT_METADATA_RETRIEVER_H_
-
-#include <media/IMediaExtractor.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include <utils/KeyedVector.h>
-
-namespace android {
-
-class DataSource;
-struct ImageDecoder;
-struct FrameRect;
-
-struct StagefrightMetadataRetriever : public MediaMetadataRetrieverBase {
-    StagefrightMetadataRetriever();
-    virtual ~StagefrightMetadataRetriever();
-
-    virtual status_t setDataSource(
-            const sp<IMediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t setDataSource(const sp<DataSource>& source, const char *mime);
-
-    virtual sp<IMemory> getFrameAtTime(
-            int64_t timeUs, int option, int colorFormat, bool metaOnly);
-    virtual sp<IMemory> getImageAtIndex(
-            int index, int colorFormat, bool metaOnly, bool thumbnail);
-    virtual sp<IMemory> getImageRectAtIndex(
-            int index, int colorFormat, int left, int top, int right, int bottom);
-    virtual status_t getFrameAtIndex(
-            std::vector<sp<IMemory> >* frames,
-            int frameIndex, int numFrames, int colorFormat, bool metaOnly);
-
-    virtual MediaAlbumArt *extractAlbumArt();
-    virtual const char *extractMetadata(int keyCode);
-
-private:
-    sp<DataSource> mSource;
-    sp<IMediaExtractor> mExtractor;
-
-    bool mParsedMetaData;
-    KeyedVector<int, String8> mMetaData;
-    MediaAlbumArt *mAlbumArt;
-
-    sp<ImageDecoder> mImageDecoder;
-    int mLastImageIndex;
-    void parseMetaData();
-    void parseColorAspects(const sp<MetaData>& meta);
-    // Delete album art and clear metadata.
-    void clearMetadata();
-
-    status_t getFrameInternal(
-            int64_t timeUs, int numFrames, int option, int colorFormat, bool metaOnly,
-            sp<IMemory>* outFrame, std::vector<sp<IMemory> >* outFrames);
-    virtual sp<IMemory> getImageInternal(
-            int index, int colorFormat, bool metaOnly, bool thumbnail, FrameRect* rect);
-
-    StagefrightMetadataRetriever(const StagefrightMetadataRetriever &);
-
-    StagefrightMetadataRetriever &operator=(
-            const StagefrightMetadataRetriever &);
-};
-
-}  // namespace android
-
-#endif  // STAGEFRIGHT_METADATA_RETRIEVER_H_
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
index 71e62f7..5ae0653 100644
--- a/media/libstagefright/include/ThrottledSource.h
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -54,10 +54,6 @@
         return mSource->reconnectAtOffset(offset);
     }
 
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL) {
-        return mSource->DrmInitialization(mime);
-    }
-
     virtual String8 getMIMEType() const {
         return mSource->getMIMEType();
     }
diff --git a/media/libstagefright/include/media/stagefright/AACWriter.h b/media/libstagefright/include/media/stagefright/AACWriter.h
index 7c63ddd..2671138 100644
--- a/media/libstagefright/include/media/stagefright/AACWriter.h
+++ b/media/libstagefright/include/media/stagefright/AACWriter.h
@@ -17,7 +17,7 @@
 #ifndef AAC_WRITER_H_
 #define AAC_WRITER_H_
 
-#include "foundation/ABase.h"
+#include "media/stagefright/foundation/ABase.h"
 #include <media/stagefright/MediaWriter.h>
 #include <utils/threads.h>
 
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 784fd36..83e92b9 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -37,6 +37,15 @@
 #define TRACK_BUFFER_TIMING     0
 
 namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+struct IGraphicBufferSource;
+}  // namespace V1_0
+}  // namespace omx
+}  // namespace media
+}  // namespace hardware
 
 struct ABuffer;
 class ACodecBufferChannel;
@@ -149,6 +158,7 @@
         kFlagIsSecure                                 = 1,
         kFlagPushBlankBuffersToNativeWindowOnShutdown = 2,
         kFlagIsGrallocUsageProtected                  = 4,
+        kFlagPreregisterMetadataBuffers               = 8,
     };
 
     enum {
@@ -279,7 +289,7 @@
     size_t mNumUndequeuedBuffers;
     sp<DataConverter> mConverter[2];
 
-    sp<IGraphicBufferSource> mGraphicBufferSource;
+    sp<hardware::media::omx::V1_0::IGraphicBufferSource> mGraphicBufferSource;
     int64_t mRepeatFrameDelayUs;
     int64_t mMaxPtsGapUs;
     float mMaxFps;
@@ -466,6 +476,8 @@
         int32_t targetRefLevel;
         int32_t encodedTargetLevel;
         int32_t effectType;
+        int32_t albumMode;
+        int32_t outputLoudness;
     } drcParams_t;
 
     status_t setupAACCodec(
@@ -496,6 +508,7 @@
             AudioEncoding encoding = kAudioEncodingPcm16bit);
 
     status_t setPriority(int32_t priority);
+    status_t setLowLatency(int32_t lowLatency);
     status_t setLatency(uint32_t latency);
     status_t getLatency(uint32_t *latency);
     status_t setAudioPresentation(int32_t presentationId, int32_t programId);
diff --git a/media/libstagefright/include/media/stagefright/AudioPlayer.h b/media/libstagefright/include/media/stagefright/AudioPlayer.h
deleted file mode 100644
index 7c2c36f..0000000
--- a/media/libstagefright/include/media/stagefright/AudioPlayer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2009 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 AUDIO_PLAYER_H_
-
-#define AUDIO_PLAYER_H_
-
-#include <media/MediaSource.h>
-#include <media/MediaPlayerInterface.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct AudioPlaybackRate;
-class AudioTrack;
-struct AwesomePlayer;
-
-class AudioPlayer {
-public:
-    enum {
-        REACHED_EOS,
-        SEEK_COMPLETE
-    };
-
-    enum {
-        ALLOW_DEEP_BUFFERING = 0x01,
-        USE_OFFLOAD = 0x02,
-        HAS_VIDEO   = 0x1000,
-        IS_STREAMING = 0x2000
-
-    };
-
-    AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
-                uint32_t flags = 0);
-
-    virtual ~AudioPlayer();
-
-    // Caller retains ownership of "source".
-    void setSource(const sp<MediaSource> &source);
-
-    status_t start(bool sourceAlreadyStarted = false);
-
-    void pause(bool playPendingSamples = false);
-    status_t resume();
-
-    status_t seekTo(int64_t time_us);
-
-    bool isSeeking();
-    bool reachedEOS(status_t *finalStatus);
-
-    status_t setPlaybackRate(const AudioPlaybackRate &rate);
-    status_t getPlaybackRate(AudioPlaybackRate *rate /* nonnull */);
-
-private:
-    sp<MediaSource> mSource;
-    sp<AudioTrack> mAudioTrack;
-
-    MediaBufferBase *mInputBuffer;
-
-    int mSampleRate;
-    int64_t mLatencyUs;
-    size_t mFrameSize;
-
-    Mutex mLock;
-    int64_t mNumFramesPlayed;
-    int64_t mNumFramesPlayedSysTimeUs;
-
-    int64_t mPositionTimeMediaUs;
-    int64_t mPositionTimeRealUs;
-
-    bool mSeeking;
-    bool mReachedEOS;
-    status_t mFinalStatus;
-    int64_t mSeekTimeUs;
-
-    bool mStarted;
-
-    bool mIsFirstBuffer;
-    status_t mFirstBufferResult;
-    MediaBufferBase *mFirstBuffer;
-
-    sp<MediaPlayerBase::AudioSink> mAudioSink;
-
-    bool mPlaying;
-    int64_t mStartPosUs;
-    const uint32_t mCreateFlags;
-
-    static void AudioCallback(int event, void *user, void *info);
-    void AudioCallback(int event, void *info);
-
-    static size_t AudioSinkCallback(
-            MediaPlayerBase::AudioSink *audioSink,
-            void *data, size_t size, void *me,
-            MediaPlayerBase::AudioSink::cb_event_t event);
-
-    size_t fillBuffer(void *data, size_t size);
-
-    void reset();
-
-    int64_t getOutputPlayPositionUs_l();
-
-    bool allowDeepBuffering() const { return (mCreateFlags & ALLOW_DEEP_BUFFERING) != 0; }
-    bool useOffload() const { return (mCreateFlags & USE_OFFLOAD) != 0; }
-
-    AudioPlayer(const AudioPlayer &);
-    AudioPlayer &operator=(const AudioPlayer &);
-};
-
-}  // namespace android
-
-#endif  // AUDIO_PLAYER_H_
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index af04dad..451aa57 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -20,7 +20,7 @@
 
 #include <media/AudioRecord.h>
 #include <media/AudioSystem.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/MicrophoneInfo.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <utils/List.h>
@@ -37,7 +37,7 @@
     // Note that the "channels" parameter _is_ the number of channels,
     // _not_ a bitmask of audio_channels_t constants.
     AudioSource(
-            audio_source_t inputSource,
+            const audio_attributes_t *attr,
             const String16 &opPackageName,
             uint32_t sampleRate,
             uint32_t channels,
diff --git a/media/libstagefright/include/media/stagefright/CallbackMediaSource.h b/media/libstagefright/include/media/stagefright/CallbackMediaSource.h
index 33453fa..d2adbb9 100644
--- a/media/libstagefright/include/media/stagefright/CallbackMediaSource.h
+++ b/media/libstagefright/include/media/stagefright/CallbackMediaSource.h
@@ -17,7 +17,7 @@
 #ifndef CALLBACK_MEDIA_SOURCE_H_
 #define CALLBACK_MEDIA_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 
 namespace android {
diff --git a/media/libstagefright/include/media/stagefright/CameraSource.h b/media/libstagefright/include/media/stagefright/CameraSource.h
index 3037b72..6f0d3b5 100644
--- a/media/libstagefright/include/media/stagefright/CameraSource.h
+++ b/media/libstagefright/include/media/stagefright/CameraSource.h
@@ -19,7 +19,7 @@
 #define CAMERA_SOURCE_H_
 
 #include <deque>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <camera/android/hardware/ICamera.h>
 #include <camera/ICameraRecordingProxy.h>
diff --git a/media/libstagefright/include/media/stagefright/ClearFileSource.h b/media/libstagefright/include/media/stagefright/ClearFileSource.h
deleted file mode 100644
index be83748..0000000
--- a/media/libstagefright/include/media/stagefright/ClearFileSource.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 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 CLEAR_FILE_SOURCE_H_
-
-#define CLEAR_FILE_SOURCE_H_
-
-#include <stdio.h>
-
-#include <media/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class ClearFileSource : public DataSource {
-public:
-    ClearFileSource(const char *filename);
-    // ClearFileSource takes ownership and will close the fd
-    ClearFileSource(int fd, int64_t offset, int64_t length);
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
-    virtual status_t getSize(off64_t *size);
-
-    virtual uint32_t flags() {
-        return kIsLocalFileSource;
-    }
-
-    virtual String8 toString() {
-        return mName;
-    }
-
-protected:
-    virtual ~ClearFileSource();
-    virtual ssize_t readAt_l(off64_t offset, void *data, size_t size);
-
-    int mFd;
-    int64_t mOffset;
-    int64_t mLength;
-    Mutex mLock;
-
-private:
-    String8 mName;
-
-    ClearFileSource(const ClearFileSource &);
-    ClearFileSource &operator=(const ClearFileSource &);
-};
-
-}  // namespace android
-
-#endif  // CLEAR_FILE_SOURCE_H_
-
diff --git a/media/libstagefright/include/media/stagefright/ClearMediaHTTP.h b/media/libstagefright/include/media/stagefright/ClearMediaHTTP.h
deleted file mode 100644
index 72907a9..0000000
--- a/media/libstagefright/include/media/stagefright/ClearMediaHTTP.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 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 CLEAR_MEDIA_HTTP_H_
-
-#define CLEAR_MEDIA_HTTP_H_
-
-#include <media/stagefright/foundation/AString.h>
-
-#include "include/HTTPBase.h"
-
-namespace android {
-
-struct MediaHTTPConnection;
-
-struct ClearMediaHTTP : public HTTPBase {
-    ClearMediaHTTP(const sp<MediaHTTPConnection> &conn);
-
-    virtual status_t connect(
-            const char *uri,
-            const KeyedVector<String8, String8> *headers,
-            off64_t offset);
-
-    virtual void close();
-
-    virtual void disconnect();
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
-    virtual status_t getSize(off64_t *size);
-
-    virtual uint32_t flags();
-
-    virtual status_t reconnectAtOffset(off64_t offset);
-
-protected:
-    virtual ~ClearMediaHTTP();
-
-    virtual String8 getUri();
-    virtual String8 getMIMEType() const;
-
-    AString mLastURI;
-
-private:
-    status_t mInitCheck;
-    sp<MediaHTTPConnection> mHTTPConnection;
-
-    KeyedVector<String8, String8> mLastHeaders;
-
-    bool mCachedSizeValid;
-    off64_t mCachedSize;
-
-    DISALLOW_EVIL_CONSTRUCTORS(ClearMediaHTTP);
-};
-
-}  // namespace android
-
-#endif  // CLEAR_MEDIA_HTTP_H_
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index ad60f46..dd6df90 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -34,6 +34,8 @@
 #include <system/graphics.h>
 #include <utils/NativeHandle.h>
 
+class C2Buffer;
+
 namespace android {
 class BufferChannelBase;
 struct BufferProducerWrapper;
@@ -42,12 +44,21 @@
 struct RenderedFrameInfo;
 class Surface;
 struct ICrypto;
+class IMemory;
+
 namespace hardware {
+class HidlMemory;
 namespace cas {
 namespace native {
 namespace V1_0 {
 struct IDescrambler;
-}}}}
+}}}
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+}}
+}
+
 using hardware::cas::native::V1_0::IDescrambler;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
@@ -249,15 +260,15 @@
  */
 class BufferChannelBase {
 public:
+    BufferChannelBase() = default;
     virtual ~BufferChannelBase() = default;
 
     inline void setCallback(std::unique_ptr<CodecBase::BufferCallback> &&callback) {
         mCallback = std::move(callback);
     }
 
-    void setCrypto(const sp<ICrypto> &crypto);
-
-    void setDescrambler(const sp<IDescrambler> &descrambler);
+    virtual void setCrypto(const sp<ICrypto> &) {}
+    virtual void setDescrambler(const sp<IDescrambler> &) {}
 
     /**
      * Queue an input buffer into the buffer channel.
@@ -287,6 +298,50 @@
             size_t numSubSamples,
             AString *errorDetailMsg) = 0;
     /**
+     * Attach a Codec 2.0 buffer to MediaCodecBuffer.
+     *
+     * @return    OK if successful;
+     *            -ENOENT if index is not recognized
+     *            -ENOSYS if attaching buffer is not possible or not supported
+     */
+    virtual status_t attachBuffer(
+            const std::shared_ptr<C2Buffer> &c2Buffer,
+            const sp<MediaCodecBuffer> &buffer) {
+        (void)c2Buffer;
+        (void)buffer;
+        return -ENOSYS;
+    }
+    /**
+     * Attach an encrypted HidlMemory buffer to an index
+     *
+     * @return    OK if successful;
+     *            -ENOENT if index is not recognized
+     *            -ENOSYS if attaching buffer is not possible or not supported
+     */
+    virtual status_t attachEncryptedBuffer(
+            const sp<hardware::HidlMemory> &memory,
+            bool secure,
+            const uint8_t *key,
+            const uint8_t *iv,
+            CryptoPlugin::Mode mode,
+            CryptoPlugin::Pattern pattern,
+            size_t offset,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const sp<MediaCodecBuffer> &buffer) {
+        (void)memory;
+        (void)secure;
+        (void)key;
+        (void)iv;
+        (void)mode;
+        (void)pattern;
+        (void)offset;
+        (void)subSamples;
+        (void)numSubSamples;
+        (void)buffer;
+        return -ENOSYS;
+    }
+    /**
      * Request buffer rendering at specified time.
      *
      * @param     timestampNs   nanosecond timestamp for rendering time.
@@ -314,10 +369,20 @@
      */
     virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
 
+    /**
+     * Convert binder IMemory to drm SharedBuffer
+     *
+     * \param   memory      IMemory object to store encrypted content.
+     * \param   heapSeqNum  Heap sequence number from ICrypto; -1 if N/A
+     * \param   buf         SharedBuffer structure to fill.
+     */
+    static void IMemoryToSharedBuffer(
+            const sp<IMemory> &memory,
+            int32_t heapSeqNum,
+            hardware::drm::V1_0::SharedBuffer *buf);
+
 protected:
     std::unique_ptr<CodecBase::BufferCallback> mCallback;
-    sp<ICrypto> mCrypto;
-    sp<IDescrambler> mDescrambler;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
deleted file mode 100644
index 1f7a473..0000000
--- a/media/libstagefright/include/media/stagefright/DataSource.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2009 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 DATA_SOURCE_H_
-
-#define DATA_SOURCE_H_
-
-#include <sys/types.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/DataSourceBase.h>
-#include <media/IDataSource.h>
-#include <media/MediaExtractorPluginApi.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include <drm/DrmManagerClient.h>
-
-
-namespace android {
-
-class String8;
-
-class DataSource : public DataSourceBase, public virtual RefBase {
-public:
-    DataSource() : mWrapper(NULL) {}
-
-    // returns a pointer to IDataSource if it is wrapped.
-    virtual sp<IDataSource> getIDataSource() const {
-        return nullptr;
-    }
-
-    virtual String8 toString() {
-        return String8("<unspecified>");
-    }
-
-    virtual status_t reconnectAtOffset(off64_t /*offset*/) {
-        return ERROR_UNSUPPORTED;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-
-    // for DRM
-    virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
-        return NULL;
-    }
-
-    virtual String8 getUri() {
-        return String8();
-    }
-
-    virtual bool getUri(char *uriString, size_t bufferSize) final {
-        int ret = snprintf(uriString, bufferSize, "%s", getUri().c_str());
-        return ret >= 0 && static_cast<size_t>(ret) < bufferSize;
-    }
-
-    virtual String8 getMIMEType() const {
-        return String8("application/octet-stream");
-    }
-
-    CDataSource *wrap() {
-        if (mWrapper) {
-            return mWrapper;
-        }
-        mWrapper = new CDataSource();
-        mWrapper->handle = this;
-
-        mWrapper->readAt = [](void *handle, off64_t offset, void *data, size_t size) -> ssize_t {
-            return ((DataSource*)handle)->readAt(offset, data, size);
-        };
-        mWrapper->getSize = [](void *handle, off64_t *size) -> status_t {
-            return ((DataSource*)handle)->getSize(size);
-        };
-        mWrapper->flags = [](void *handle) -> uint32_t {
-            return ((DataSource*)handle)->flags();
-        };
-        mWrapper->getUri = [](void *handle, char *uriString, size_t bufferSize) -> bool {
-            return ((DataSource*)handle)->getUri(uriString, bufferSize);
-        };
-        return mWrapper;
-    }
-
-protected:
-    virtual ~DataSource() {
-        delete mWrapper;
-    }
-
-private:
-    CDataSource *mWrapper;
-    DataSource(const DataSource &);
-    DataSource &operator=(const DataSource &);
-};
-
-}  // namespace android
-
-#endif  // DATA_SOURCE_H_
diff --git a/media/libstagefright/include/media/stagefright/DataSourceFactory.h b/media/libstagefright/include/media/stagefright/DataSourceFactory.h
deleted file mode 100644
index 2a1d491..0000000
--- a/media/libstagefright/include/media/stagefright/DataSourceFactory.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 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 DATA_SOURCE_FACTORY_H_
-
-#define DATA_SOURCE_FACTORY_H_
-
-#include <sys/types.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct MediaHTTPService;
-class String8;
-struct HTTPBase;
-
-class DataSourceFactory {
-public:
-    static sp<DataSource> CreateFromURI(
-            const sp<MediaHTTPService> &httpService,
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL,
-            String8 *contentType = NULL,
-            HTTPBase *httpSource = NULL);
-
-    static sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
-    static sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
-};
-
-}  // namespace android
-
-#endif  // DATA_SOURCE_FACTORY_H_
diff --git a/media/libstagefright/include/media/stagefright/FileSource.h b/media/libstagefright/include/media/stagefright/FileSource.h
deleted file mode 100644
index b610eef..0000000
--- a/media/libstagefright/include/media/stagefright/FileSource.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 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 FILE_SOURCE_H_
-
-#define FILE_SOURCE_H_
-
-#include <stdio.h>
-
-#include <media/stagefright/ClearFileSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-#include <drm/DrmManagerClient.h>
-
-namespace android {
-
-class FileSource : public ClearFileSource {
-public:
-    FileSource(const char *filename);
-    // FileSource takes ownership and will close the fd
-    FileSource(int fd, int64_t offset, int64_t length);
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime);
-
-    static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
-
-protected:
-    virtual ~FileSource();
-
-private:
-    /*for DRM*/
-    sp<DecryptHandle> mDecryptHandle;
-    DrmManagerClient *mDrmManagerClient;
-    int64_t mDrmBufOffset;
-    ssize_t mDrmBufSize;
-    unsigned char *mDrmBuf;
-
-    ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
-
-    FileSource(const FileSource &);
-    FileSource &operator=(const FileSource &);
-};
-
-}  // namespace android
-
-#endif  // FILE_SOURCE_H_
-
diff --git a/media/libstagefright/include/media/stagefright/FoundationUtils.h b/media/libstagefright/include/media/stagefright/FoundationUtils.h
new file mode 100644
index 0000000..1548981
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/FoundationUtils.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 FOUNDATION_UTILS_H_
+
+#define FOUNDATION_UTILS_H_
+
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+AString MakeUserAgent();
+
+AString uriDebugString(const AString &uri, bool incognito = false);
+
+AString nameForFd(int fd);
+}  // namespace android
+
+#endif  // FOUNDATION_UTILS_H_
diff --git a/media/libstagefright/include/media/stagefright/FrameCaptureProcessor.h b/media/libstagefright/include/media/stagefright/FrameCaptureProcessor.h
new file mode 100644
index 0000000..66e5daa
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/FrameCaptureProcessor.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 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 FRAME_CAPTURE_PROCESSOR_H_
+#define FRAME_CAPTURE_PROCESSOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+struct AMessage;
+class GraphicBuffer;
+class Rect;
+
+namespace renderengine {
+class RenderEngine;
+struct LayerSettings;
+}
+
+/*
+ * Process a decoded graphic buffer through RenderEngine to
+ * convert it to sRGB.
+ *
+ * This class is a singleton that holds one instance of RenderEngine
+ * and its event queue (on which the GL context runs). The RenderEngine
+ * is created upon the first getInstance().
+ */
+class FrameCaptureProcessor : public AHandler {
+
+public:
+
+    struct Layer : public RefBase {
+        virtual void getLayerSettings(
+                const Rect &sourceCrop, uint32_t textureName,
+                renderengine::LayerSettings *layerSettings) = 0;
+    };
+
+    static sp<FrameCaptureProcessor> getInstance();
+
+    status_t capture(
+            const sp<Layer> &layer,
+            const Rect &sourceCrop, const sp<GraphicBuffer> &outBuffer);
+
+protected:
+    virtual ~FrameCaptureProcessor();
+    void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+    FrameCaptureProcessor();
+
+    enum {
+        kWhatCreate,
+        kWhatCapture,
+    };
+
+    static Mutex sLock;
+    static sp<FrameCaptureProcessor> sInstance GUARDED_BY(sLock);
+
+    constexpr static float sDefaultMaxLumiance = 500.0f;
+
+    status_t mInitStatus;
+    sp<ALooper> mLooper;
+    std::unique_ptr<renderengine::RenderEngine> mRE;
+    uint32_t mTextureName;
+
+    static status_t PostAndAwaitResponse(
+            const sp<AMessage> &msg, sp<AMessage> *response);
+    static void PostReplyWithError(
+            const sp<AReplyToken> &replyID, status_t err);
+
+    status_t initCheck() { return mInitStatus; }
+    void createRenderEngine();
+
+    // message handlers
+    status_t onCreate();
+    status_t onCapture(const sp<Layer> &layer,
+            const Rect &sourceCrop, const sp<GraphicBuffer> &outBuffer);
+
+    DISALLOW_EVIL_CONSTRUCTORS(FrameCaptureProcessor);
+};
+
+}  // namespace android
+
+#endif  // FRAME_CAPTURE_PROCESSOR_H_
diff --git a/media/libstagefright/include/media/stagefright/InterfaceUtils.h b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
index b83a958..92ef543 100644
--- a/media/libstagefright/include/media/stagefright/InterfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
@@ -19,8 +19,8 @@
 
 #include <utils/RefBase.h>
 #include <media/stagefright/RemoteMediaExtractor.h>
-#include <media/MediaSource.h>
-#include <media/IMediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <android/IMediaExtractor.h>
 #include <media/IMediaSource.h>
 
 namespace android {
diff --git a/media/libstagefright/include/media/stagefright/JPEGSource.h b/media/libstagefright/include/media/stagefright/JPEGSource.h
index 8ab3d11..53cb344 100644
--- a/media/libstagefright/include/media/stagefright/JPEGSource.h
+++ b/media/libstagefright/include/media/stagefright/JPEGSource.h
@@ -18,7 +18,7 @@
 
 #define JPEG_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 
 namespace android {
 
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index 6f19023..501cf2c 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -23,8 +23,11 @@
 #include <media/stagefright/MediaWriter.h>
 #include <utils/List.h>
 #include <utils/threads.h>
+#include <map>
 #include <media/stagefright/foundation/AHandlerReflector.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <mutex>
+#include <queue>
 
 namespace android {
 
@@ -58,6 +61,10 @@
     void writeFourcc(const char *fourcc);
     void write(const void *data, size_t size);
     inline size_t write(const void *ptr, size_t size, size_t nmemb);
+    // Write to file system by calling ::write() or post error message to looper on failure.
+    void writeOrPostError(int fd, const void *buf, size_t count);
+    // Seek in the file by calling ::lseek64() or post error message to looper on failure.
+    void seekOrPostError(int fd, off64_t offset, int whence);
     void endBox();
     uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
     status_t setInterleaveDuration(uint32_t duration);
@@ -79,7 +86,10 @@
     friend struct AHandlerReflector<MPEG4Writer>;
 
     enum {
-        kWhatSwitch                          = 'swch',
+        kWhatSwitch                  = 'swch',
+        kWhatIOError                 = 'ioer',
+        kWhatFallocateError          = 'faer',
+        kWhatNoIOErrorSoFar          = 'noie'
     };
 
     int  mFd;
@@ -88,14 +98,15 @@
     status_t mInitCheck;
     bool mIsRealTimeRecording;
     bool mUse4ByteNalLength;
-    bool mUse32BitOffset;
     bool mIsFileSizeLimitExplicitlyRequested;
     bool mPaused;
     bool mStarted;  // Writer thread + track threads started successfully
     bool mWriterThreadStarted;  // Only writer thread started successfully
     bool mSendNotify;
     off64_t mOffset;
-    off_t mMdatOffset;
+    off64_t mPreAllocateFileEndOffset;  //End of file offset during preallocation.
+    off64_t mMdatOffset;
+    off64_t mMdatEndOffset;  // End offset of mdat atom.
     uint8_t *mInMemoryCache;
     off64_t mInMemoryCacheOffset;
     off64_t mInMemoryCacheSize;
@@ -106,17 +117,28 @@
     uint32_t mInterleaveDurationUs;
     int32_t mTimeScale;
     int64_t mStartTimestampUs;
-    int32_t mStartTimeOffsetBFramesUs; // Start time offset when B Frames are present
+    int32_t mStartTimeOffsetBFramesUs;  // Longest offset needed for reordering tracks with B Frames
     int mLatitudex10000;
     int mLongitudex10000;
     bool mAreGeoTagsAvailable;
     int32_t mStartTimeOffsetMs;
     bool mSwitchPending;
+    bool mWriteSeekErr;
+    bool mFallocateErr;
+    bool mPreAllocationEnabled;
+    // Queue to hold top long write durations
+    std::priority_queue<std::chrono::microseconds, std::vector<std::chrono::microseconds>,
+                        std::greater<std::chrono::microseconds>> mWriteDurationPQ;
+    const uint8_t kWriteDurationsCount = 5;
 
     sp<ALooper> mLooper;
     sp<AHandlerReflector<MPEG4Writer> > mReflector;
 
     Mutex mLock;
+    std::mutex mResetMutex;
+    std::mutex mFallocMutex;
+    bool mPreAllocFirstTime; // Pre-allocate space for file and track headers only once per file.
+    uint64_t mPrevAllTracksTotalMetaDataSizeEstimate;
 
     List<Track *> mTracks;
 
@@ -132,6 +154,7 @@
     int64_t estimateMoovBoxSize(int32_t bitRate);
     int64_t estimateFileLevelMetaSize(MetaData *params);
     void writeCachedBoxToFile(const char *type);
+    void printWriteDurations();
 
     struct Chunk {
         Track               *mTrack;        // Owner
@@ -200,19 +223,23 @@
     } ItemProperty;
 
     bool mHasFileLevelMeta;
+    uint64_t mFileLevelMetaDataSize;
     bool mHasMoovBox;
     uint32_t mPrimaryItemId;
     uint32_t mAssociationEntryCount;
     uint32_t mNumGrids;
+    uint16_t mNextItemId;
     bool mHasRefs;
-    Vector<ItemInfo> mItems;
+    std::map<uint32_t, ItemInfo> mItems;
     Vector<ItemProperty> mProperties;
 
     // Writer thread handling
     status_t startWriterThread();
-    void stopWriterThread();
+    status_t stopWriterThread();
     static void *ThreadWrapper(void *me);
     void threadFunc();
+    status_t setupAndStartLooper();
+    void stopAndReleaseLooper();
 
     // Buffer a single chunk to be written out later.
     void bufferChunk(const Chunk& chunk);
@@ -259,15 +286,16 @@
     void addLengthPrefixedSample_l(MediaBuffer *buffer);
     void addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer);
     uint16_t addProperty_l(const ItemProperty &);
+    status_t reserveItemId_l(size_t numItems, uint16_t *itemIdBase);
     uint16_t addItem_l(const ItemInfo &);
     void addRefs_l(uint16_t itemId, const ItemRefs &);
 
     bool exceedsFileSizeLimit();
-    bool use32BitFileOffset() const;
     bool exceedsFileDurationLimit();
     bool approachingFileSizeLimit();
     bool isFileStreamable() const;
-    void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
+    void trackProgressStatus(uint32_t trackId, int64_t timeUs, status_t err = OK);
+    status_t validateAllTracksId(bool akKey4BitTrackIds);
     void writeCompositionMatrix(int32_t degrees);
     void writeMvhdBox(int64_t durationUs);
     void writeMoovBox(int64_t durationUs);
@@ -284,6 +312,16 @@
     void writeIlst();
     void writeMoovLevelMetaBox();
 
+    /*
+     * Allocate space needed for MOOV atom in advance and maintain just enough before write
+     * of any data.  Stop writing and save MOOV atom if there was any error.
+     */
+    bool preAllocate(uint64_t wantSize);
+    /*
+     * Truncate file as per the size used for metadata and actual data in a session.
+     */
+    bool truncatePreAllocation();
+
     // HEIF writing
     void writeIlocBox();
     void writeInfeBox(uint16_t itemId, const char *type, uint32_t flags);
@@ -297,7 +335,7 @@
     void writeFileLevelMetaBox();
 
     void sendSessionSummary();
-    void release();
+    status_t release();
     status_t switchFd();
     status_t reset(bool stopSource = true);
 
diff --git a/media/libstagefright/include/media/stagefright/MediaAdapter.h b/media/libstagefright/include/media/stagefright/MediaAdapter.h
index 589c827..177a9e9 100644
--- a/media/libstagefright/include/media/stagefright/MediaAdapter.h
+++ b/media/libstagefright/include/media/stagefright/MediaAdapter.h
@@ -17,7 +17,7 @@
 #ifndef MEDIA_ADAPTER_H
 #define MEDIA_ADAPTER_H
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
index ace63ae..9145b63 100644
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ b/media/libstagefright/include/media/stagefright/MediaBuffer.h
@@ -48,7 +48,11 @@
     explicit MediaBuffer(const sp<ABuffer> &buffer);
 #ifndef NO_IMEMORY
     MediaBuffer(const sp<IMemory> &mem) :
-        MediaBuffer((uint8_t *)mem->pointer() + sizeof(SharedControl), mem->size()) {
+         // TODO: Using unsecurePointer() has some associated security pitfalls
+         //       (see declaration for details).
+         //       Either document why it is safe in this case or address the
+         //       issue (e.g. by copying).
+        MediaBuffer((uint8_t *)mem->unsecurePointer() + sizeof(SharedControl), mem->size()) {
         // delegate and override mMemory
         mMemory = mem;
     }
@@ -94,9 +98,13 @@
 
     virtual int remoteRefcount() const {
 #ifndef NO_IMEMORY
-        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
+         // TODO: Using unsecurePointer() has some associated security pitfalls
+         //       (see declaration for details).
+         //       Either document why it is safe in this case or address the
+         //       issue (e.g. by copying).
+        if (mMemory.get() == nullptr || mMemory->unsecurePointer() == nullptr) return 0;
         int32_t remoteRefcount =
-                reinterpret_cast<SharedControl *>(mMemory->pointer())->getRemoteRefcount();
+                reinterpret_cast<SharedControl *>(mMemory->unsecurePointer())->getRemoteRefcount();
         // Sanity check so that remoteRefCount() is non-negative.
         return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
 #else
@@ -107,8 +115,12 @@
     // returns old value
     int addRemoteRefcount(int32_t value) {
 #ifndef NO_IMEMORY
-        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
-        return reinterpret_cast<SharedControl *>(mMemory->pointer())->addRemoteRefcount(value);
+          // TODO: Using unsecurePointer() has some associated security pitfalls
+         //       (see declaration for details).
+         //       Either document why it is safe in this case or address the
+         //       issue (e.g. by copying).
+       if (mMemory.get() == nullptr || mMemory->unsecurePointer() == nullptr) return 0;
+        return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer())->addRemoteRefcount(value);
 #else
         (void) value;
         return 0;
@@ -121,8 +133,12 @@
 
     static bool isDeadObject(const sp<IMemory> &memory) {
 #ifndef NO_IMEMORY
-        if (memory.get() == nullptr || memory->pointer() == nullptr) return false;
-        return reinterpret_cast<SharedControl *>(memory->pointer())->isDeadObject();
+         // TODO: Using unsecurePointer() has some associated security pitfalls
+         //       (see declaration for details).
+         //       Either document why it is safe in this case or address the
+         //       issue (e.g. by copying).
+        if (memory.get() == nullptr || memory->unsecurePointer() == nullptr) return false;
+        return reinterpret_cast<SharedControl *>(memory->unsecurePointer())->isDeadObject();
 #else
         (void) memory;
         return false;
@@ -220,7 +236,11 @@
 
     inline SharedControl *getSharedControl() const {
 #ifndef NO_IMEMORY
-         return reinterpret_cast<SharedControl *>(mMemory->pointer());
+         // TODO: Using unsecurePointer() has some associated security pitfalls
+         //       (see declaration for details).
+         //       Either document why it is safe in this case or address the
+         //       issue (e.g. by copying).
+         return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer());
 #else
          return nullptr;
 #endif
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index cd30347..f7e6c27 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -24,12 +24,23 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/MediaCodecInfo.h>
-#include <media/MediaResource.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
 #include <media/stagefright/foundation/AHandler.h>
 #include <media/stagefright/FrameRenderTracker.h>
 #include <utils/Vector.h>
 
+class C2Buffer;
+class C2GraphicBlock;
+class C2LinearBlock;
+
+namespace aidl {
+namespace android {
+namespace media {
+class MediaResourceParcel;
+} // media
+} // android
+} // aidl
+
 namespace android {
 
 struct ABuffer;
@@ -43,8 +54,6 @@
 struct ICrypto;
 class MediaCodecBuffer;
 class IMemory;
-class IResourceManagerClient;
-class IResourceManagerService;
 struct PersistentSurface;
 class SoftwareRenderer;
 class Surface;
@@ -54,11 +63,14 @@
 namespace V1_0 {
 struct IDescrambler;
 }}}}
+
 using hardware::cas::native::V1_0::IDescrambler;
+using aidl::android::media::MediaResourceParcel;
 
 struct MediaCodec : public AHandler {
     enum ConfigureFlags {
-        CONFIGURE_FLAG_ENCODE   = 1,
+        CONFIGURE_FLAG_ENCODE           = 1,
+        CONFIGURE_FLAG_USE_BLOCK_MODEL  = 2,
     };
 
     enum BufferFlags {
@@ -127,6 +139,8 @@
     // object.
     status_t release();
 
+    status_t releaseAsync(const sp<AMessage> &notify);
+
     status_t flush();
 
     status_t queueInputBuffer(
@@ -150,6 +164,38 @@
             uint32_t flags,
             AString *errorDetailMsg = NULL);
 
+    status_t queueBuffer(
+            size_t index,
+            const std::shared_ptr<C2Buffer> &buffer,
+            int64_t presentationTimeUs,
+            uint32_t flags,
+            const sp<AMessage> &tunings,
+            AString *errorDetailMsg = NULL);
+
+    status_t queueEncryptedBuffer(
+            size_t index,
+            const sp<hardware::HidlMemory> &memory,
+            size_t offset,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const uint8_t key[16],
+            const uint8_t iv[16],
+            CryptoPlugin::Mode mode,
+            const CryptoPlugin::Pattern &pattern,
+            int64_t presentationTimeUs,
+            uint32_t flags,
+            const sp<AMessage> &tunings,
+            AString *errorDetailMsg = NULL);
+
+    std::shared_ptr<C2Buffer> decrypt(
+            const std::shared_ptr<C2Buffer> &buffer,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const uint8_t key[16],
+            const uint8_t iv[16],
+            CryptoPlugin::Mode mode,
+            const CryptoPlugin::Pattern &pattern);
+
     status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);
 
     status_t dequeueOutputBuffer(
@@ -189,7 +235,7 @@
 
     status_t getCodecInfo(sp<MediaCodecInfo> *codecInfo) const;
 
-    status_t getMetrics(MediaAnalyticsItem * &reply);
+    status_t getMetrics(mediametrics_handle_t &reply);
 
     status_t setParameters(const sp<AMessage> &params);
 
@@ -199,6 +245,29 @@
     static size_t CreateFramesRenderedMessage(
             const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg);
 
+    static status_t CanFetchLinearBlock(
+            const std::vector<std::string> &names, bool *isCompatible);
+
+    static std::shared_ptr<C2LinearBlock> FetchLinearBlock(
+            size_t capacity, const std::vector<std::string> &names);
+
+    static status_t CanFetchGraphicBlock(
+            const std::vector<std::string> &names, bool *isCompatible);
+
+    static std::shared_ptr<C2GraphicBlock> FetchGraphicBlock(
+            int32_t width,
+            int32_t height,
+            int32_t format,
+            uint64_t usage,
+            const std::vector<std::string> &names);
+
+    template <typename T>
+    struct WrapperObject : public RefBase {
+        WrapperObject(const T& v) : value(v) {}
+        WrapperObject(T&& v) : value(std::move(v)) {}
+        T value;
+    };
+
 protected:
     virtual ~MediaCodec();
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -275,6 +344,7 @@
         kFlagIsAsync                    = 1024,
         kFlagIsComponentAllocated       = 2048,
         kFlagPushBlankBuffersOnShutdown = 4096,
+        kFlagUseBlockModel              = 8192,
     };
 
     struct BufferInfo {
@@ -284,34 +354,7 @@
         bool mOwnedByClient;
     };
 
-    struct ResourceManagerServiceProxy : public IBinder::DeathRecipient {
-        ResourceManagerServiceProxy(pid_t pid, uid_t uid);
-        ~ResourceManagerServiceProxy();
-
-        void init();
-
-        // implements DeathRecipient
-        virtual void binderDied(const wp<IBinder>& /*who*/);
-
-        void addResource(
-                int64_t clientId,
-                const sp<IResourceManagerClient> &client,
-                const Vector<MediaResource> &resources);
-
-        void removeResource(
-                int64_t clientId,
-                const Vector<MediaResource> &resources);
-
-        void removeClient(int64_t clientId);
-
-        bool reclaimResource(const Vector<MediaResource> &resources);
-
-    private:
-        Mutex mLock;
-        sp<IResourceManagerService> mService;
-        pid_t mPid;
-        uid_t mUid;
-    };
+    struct ResourceManagerServiceProxy;
 
     State mState;
     uid_t mUid;
@@ -328,19 +371,21 @@
     sp<Surface> mSurface;
     SoftwareRenderer *mSoftRenderer;
 
-    MediaAnalyticsItem *mAnalyticsItem;
-    void initAnalyticsItem();
-    void updateAnalyticsItem();
-    void flushAnalyticsItem();
-    void updateEphemeralAnalytics(MediaAnalyticsItem *item);
+    mediametrics_handle_t mMetricsHandle = 0;
+    nsecs_t mLifetimeStartNs = 0;
+    void initMediametrics();
+    void updateMediametrics();
+    void flushMediametrics();
+    void updateEphemeralMediametrics(mediametrics_handle_t item);
+    void updateLowLatency(const sp<AMessage> &msg);
 
     sp<AMessage> mOutputFormat;
     sp<AMessage> mInputFormat;
     sp<AMessage> mCallback;
     sp<AMessage> mOnFrameRenderedNotification;
+    sp<AMessage> mAsyncReleaseCompleteNotification;
 
-    sp<IResourceManagerClient> mResourceManagerClient;
-    sp<ResourceManagerServiceProxy> mResourceManagerService;
+    sp<ResourceManagerServiceProxy> mResourceManagerProxy;
 
     bool mIsVideo;
     int32_t mVideoWidth;
@@ -434,8 +479,6 @@
     bool isExecuting() const;
 
     uint64_t getGraphicBufferSize();
-    void addResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
-    void removeResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
     void requestCpuBoostIfNeeded();
 
     bool hasPendingBuffer(int portIndex);
@@ -463,6 +506,18 @@
     std::deque<BufferFlightTiming_t> mBuffersInFlight;
     Mutex mLatencyLock;
     int64_t mLatencyUnknown;    // buffers for which we couldn't calculate latency
+    int64_t mNumLowLatencyEnables;  // how many times low latency mode is enabled
+    int64_t mNumLowLatencyDisables;  // how many times low latency mode is disabled
+    bool mIsLowLatencyModeOn;  // is low latency mode on currently
+    int64_t mIndexOfFirstFrameWhenLowLatencyOn;  // index of the first frame queued
+                                                 // when low latency is on
+    int64_t mInputBufferCounter;  // number of input buffers queued since last reset/flush
+
+    class ReleaseSurface;
+    std::unique_ptr<ReleaseSurface> mReleaseSurface;
+
+    std::list<sp<AMessage>> mLeftover;
+    status_t handleLeftover(size_t index);
 
     sp<BatteryChecker> mBatteryChecker;
 
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 50d7724..178d334 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -510,22 +510,24 @@
 constexpr int32_t DolbyVisionProfileDvheStn = 0x20;
 constexpr int32_t DolbyVisionProfileDvheDth = 0x40;
 constexpr int32_t DolbyVisionProfileDvheDtb = 0x80;
-constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
-constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
+constexpr int32_t DolbyVisionProfileDvheSt  = 0x100;
+constexpr int32_t DolbyVisionProfileDvavSe  = 0x200;
+constexpr int32_t DolbyVisionProfileDvav110 = 0x400;
 
 inline static const char *asString_DolbyVisionProfile(int32_t i, const char *def = "??") {
     switch (i) {
-        case DolbyVisionProfileDvavPer: return "DvavPer";
-        case DolbyVisionProfileDvavPen: return "DvavPen";
-        case DolbyVisionProfileDvheDer: return "DvheDer";
-        case DolbyVisionProfileDvheDen: return "DvheDen";
-        case DolbyVisionProfileDvheDtr: return "DvheDtr";
-        case DolbyVisionProfileDvheStn: return "DvheStn";
-        case DolbyVisionProfileDvheDth: return "DvheDth";
-        case DolbyVisionProfileDvheDtb: return "DvheDtb";
-        case DolbyVisionProfileDvheSt:  return "DvheSt";
-        case DolbyVisionProfileDvavSe:  return "DvavSe";
-        default:                        return def;
+        case DolbyVisionProfileDvavPer:  return "DvavPer";
+        case DolbyVisionProfileDvavPen:  return "DvavPen";
+        case DolbyVisionProfileDvheDer:  return "DvheDer";
+        case DolbyVisionProfileDvheDen:  return "DvheDen";
+        case DolbyVisionProfileDvheDtr:  return "DvheDtr";
+        case DolbyVisionProfileDvheStn:  return "DvheStn";
+        case DolbyVisionProfileDvheDth:  return "DvheDth";
+        case DolbyVisionProfileDvheDtb:  return "DvheDtb";
+        case DolbyVisionProfileDvheSt:   return "DvheSt";
+        case DolbyVisionProfileDvavSe:   return "DvavSe";
+        case DolbyVisionProfileDvav110:  return "Dav110";
+        default:                         return def;
     }
 }
 
@@ -731,10 +733,12 @@
 constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
 constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
 
+constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
 constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
 constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
 constexpr char KEY_AAC_DRC_EFFECT_TYPE[] = "aac-drc-effect-type";
 constexpr char KEY_AAC_DRC_HEAVY_COMPRESSION[] = "aac-drc-heavy-compression";
+constexpr char KEY_AAC_DRC_OUTPUT_LOUDNESS[] = "aac-drc-output-loudness";
 constexpr char KEY_AAC_DRC_TARGET_REFERENCE_LEVEL[] = "aac-target-ref-level";
 constexpr char KEY_AAC_ENCODED_TARGET_LEVEL[] = "aac-encoded-target-level";
 constexpr char KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT[] = "aac-max-output-channel_count";
@@ -774,6 +778,7 @@
 constexpr char KEY_LANGUAGE[] = "language";
 constexpr char KEY_LATENCY[] = "latency";
 constexpr char KEY_LEVEL[] = "level";
+constexpr char KEY_LOW_LATENCY[] = "low-latency";
 constexpr char KEY_MAX_B_FRAMES[] = "max-bframes";
 constexpr char KEY_MAX_BIT_RATE[] = "max-bitrate";
 constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder";
@@ -785,6 +790,8 @@
 constexpr char KEY_OPERATING_RATE[] = "operating-rate";
 constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth";
 constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
+constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height";
+constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width";
 constexpr char KEY_PREPEND_HEADERS_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
 constexpr char KEY_PRIORITY[] = "priority";
 constexpr char KEY_PROFILE[] = "profile";
@@ -827,6 +834,7 @@
 constexpr int32_t BUFFER_FLAG_PARTIAL_FRAME = 8;
 constexpr int32_t BUFFER_FLAG_SYNC_FRAME = 1;
 constexpr int32_t CONFIGURE_FLAG_ENCODE = 1;
+constexpr int32_t CONFIGURE_FLAG_USE_BLOCK_MODEL = 2;
 constexpr int32_t CRYPTO_MODE_AES_CBC     = 2;
 constexpr int32_t CRYPTO_MODE_AES_CTR     = 1;
 constexpr int32_t CRYPTO_MODE_UNENCRYPTED = 0;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index e44b0a4..e681d25 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -83,6 +83,7 @@
     };
 
     static sp<BinderDeathObserver> sBinderDeathObserver;
+    static sp<IBinder> sMediaPlayer;
 
     static sp<IMediaCodecList> sCodecList;
     static sp<IMediaCodecList> sRemoteList;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecSource.h b/media/libstagefright/include/media/stagefright/MediaCodecSource.h
index a68cc19..2f98af1 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecSource.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecSource.h
@@ -17,7 +17,7 @@
 #ifndef MediaCodecSource_H_
 #define MediaCodecSource_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AHandlerReflector.h>
 #include <media/stagefright/foundation/Mutexed.h>
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 09639e2..5418f10 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -99,7 +99,14 @@
     ERROR_CAS_DEVICE_REVOKED                 = CAS_ERROR_BASE - 9,
     ERROR_CAS_RESOURCE_BUSY                  = CAS_ERROR_BASE - 10,
     ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = CAS_ERROR_BASE - 11,
-    ERROR_CAS_LAST_USED_ERRORCODE            = CAS_ERROR_BASE - 11,
+    ERROR_CAS_NEED_ACTIVATION                = CAS_ERROR_BASE - 12,
+    ERROR_CAS_NEED_PAIRING                   = CAS_ERROR_BASE - 13,
+    ERROR_CAS_NO_CARD                        = CAS_ERROR_BASE - 14,
+    ERROR_CAS_CARD_MUTE                      = CAS_ERROR_BASE - 15,
+    ERROR_CAS_CARD_INVALID                   = CAS_ERROR_BASE - 16,
+    ERROR_CAS_BLACKOUT                       = CAS_ERROR_BASE - 17,
+    ERROR_CAS_REBOOTING                      = CAS_ERROR_BASE - 18,
+    ERROR_CAS_LAST_USED_ERRORCODE            = CAS_ERROR_BASE - 18,
 
     ERROR_CAS_VENDOR_MAX                     = CAS_ERROR_BASE - 500,
     ERROR_CAS_VENDOR_MIN                     = CAS_ERROR_BASE - 999,
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 2ab98e1..745e342 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -22,7 +22,7 @@
 #include <unordered_set>
 
 #include <android/dlext.h>
-#include <media/IMediaExtractor.h>
+#include <android/IMediaExtractor.h>
 
 namespace android {
 
@@ -36,7 +36,7 @@
     static sp<IMediaExtractor> CreateFromService(
             const sp<DataSource> &source, const char *mime = NULL);
     static status_t dump(int fd, const Vector<String16>& args);
-    static std::unordered_set<std::string> getSupportedTypes();
+    static std::vector<std::string> getSupportedTypes();
     static void LoadExtractors();
 
 private:
diff --git a/media/libstagefright/include/media/stagefright/MediaFilter.h b/media/libstagefright/include/media/stagefright/MediaFilter.h
index a28c49d..1255e0f 100644
--- a/media/libstagefright/include/media/stagefright/MediaFilter.h
+++ b/media/libstagefright/include/media/stagefright/MediaFilter.h
@@ -21,9 +21,7 @@
 
 namespace android {
 
-class ACodecBufferChannel;
 struct GraphicBufferListener;
-class MemoryDealer;
 struct SimpleFilter;
 
 struct MediaFilter : public CodecBase {
@@ -65,6 +63,8 @@
         sp<MediaCodecBuffer> mData;
     };
 
+    class BufferChannel;
+
     enum State {
       UNINITIALIZED,
       INITIALIZED,
@@ -104,7 +104,6 @@
     sp<AMessage> mInputFormat;
     sp<AMessage> mOutputFormat;
 
-    sp<MemoryDealer> mDealer[2];
     Vector<BufferInfo> mBuffers[2];
     Vector<BufferInfo*> mAvailableInputBuffers;
     Vector<BufferInfo*> mAvailableOutputBuffers;
@@ -113,15 +112,15 @@
     sp<SimpleFilter> mFilter;
     sp<GraphicBufferListener> mGraphicBufferListener;
 
-    std::shared_ptr<ACodecBufferChannel> mBufferChannel;
+    std::shared_ptr<BufferChannel> mBufferChannel;
 
     // helper functions
     void signalProcessBuffers();
     void signalError(status_t error);
 
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
-    BufferInfo *findBufferByID(
-            uint32_t portIndex, uint32_t bufferID,
+    BufferInfo *findBuffer(
+            uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
             ssize_t *index = NULL);
     void postFillThisBuffer(BufferInfo *info);
     void postDrainThisBuffer(BufferInfo *info);
diff --git a/media/libstagefright/include/media/stagefright/MediaHTTP.h b/media/libstagefright/include/media/stagefright/MediaHTTP.h
deleted file mode 100644
index acaa6c4..0000000
--- a/media/libstagefright/include/media/stagefright/MediaHTTP.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 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 MEDIA_HTTP_H_
-
-#define MEDIA_HTTP_H_
-
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/ClearMediaHTTP.h>
-
-namespace android {
-
-struct MediaHTTPConnection;
-
-struct MediaHTTP : public ClearMediaHTTP {
-    MediaHTTP(const sp<MediaHTTPConnection> &conn);
-
-protected:
-    virtual ~MediaHTTP();
-
-    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
-
-private:
-    sp<DecryptHandle> mDecryptHandle;
-    DrmManagerClient *mDrmManagerClient;
-
-    void clearDRMState_l();
-
-    DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
-};
-
-}  // namespace android
-
-#endif  // MEDIA_HTTP_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaMuxer.h b/media/libstagefright/include/media/stagefright/MediaMuxer.h
index 69d6cde..a1b9465 100644
--- a/media/libstagefright/include/media/stagefright/MediaMuxer.h
+++ b/media/libstagefright/include/media/stagefright/MediaMuxer.h
@@ -22,7 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/threads.h>
 
-#include "foundation/ABase.h"
+#include "media/stagefright/foundation/ABase.h"
 
 namespace android {
 
@@ -122,7 +122,6 @@
     sp<MediaWriter> mWriter;
     Vector< sp<MediaAdapter> > mTrackList;  // Each track has its MediaAdapter.
     sp<MetaData> mFileMeta;  // Metadata for the whole file.
-
     Mutex mMuxerLock;
 
     enum State {
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 972ae1d..1f4fbcb 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -19,8 +19,9 @@
 #define MEDIA_WRITER_H_
 
 #include <utils/RefBase.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/IMediaRecorderClient.h>
+#include <media/mediarecorder.h>
 
 namespace android {
 
@@ -36,7 +37,7 @@
     virtual status_t stop() = 0;
     virtual status_t pause() = 0;
     virtual status_t setCaptureRate(float /* captureFps */) {
-        ALOGW("setCaptureRate unsupported");
+        ALOG(LOG_WARN, "MediaWriter", "setCaptureRate unsupported");
         return ERROR_UNSUPPORTED;
     }
 
@@ -61,7 +62,16 @@
     sp<IMediaRecorderClient> mListener;
 
     void notify(int msg, int ext1, int ext2) {
-        if (mListener != NULL) {
+        if (msg == MEDIA_RECORDER_TRACK_EVENT_INFO || msg == MEDIA_RECORDER_TRACK_EVENT_ERROR) {
+            uint32_t trackId = (ext1 >> 28) & 0xf;
+            int type = ext1 & 0xfffffff;
+            ALOG(LOG_VERBOSE, "MediaWriter", "Track event err/info msg:%d, trackId:%u, type:%d,"
+                                             "val:%d", msg, trackId, type, ext2);
+        } else {
+            ALOG(LOG_VERBOSE, "MediaWriter", "Recorder event msg:%d, ext1:%d, ext2:%d",
+                                              msg, ext1, ext2);
+        }
+        if (mListener != nullptr) {
             mListener->notify(msg, ext1, ext2);
         }
     }
diff --git a/media/libstagefright/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
index f625358..68adf346 100644
--- a/media/libstagefright/include/media/stagefright/MetaData.h
+++ b/media/libstagefright/include/media/stagefright/MetaData.h
@@ -41,7 +41,9 @@
     friend class BnMediaSource;
     friend class BpMediaSource;
     friend class BpMediaExtractor;
+#ifndef __ANDROID_VNDK__
     static sp<MetaData> createFromParcel(const Parcel &parcel);
+#endif
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 8dc2dd5..64eb8b4 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -59,6 +59,7 @@
     kKeyAACProfile        = 'aacp',  // int32_t
     kKeyAVCC              = 'avcc',  // raw data
     kKeyHVCC              = 'hvcc',  // raw data
+    kKeyDVCC              = 'dvcc',  // raw data
     kKeyAV1C              = 'av1c',  // raw data
     kKeyThumbnailHVCC     = 'thvc',  // raw data
     kKeyD263              = 'd263',  // raw data
@@ -69,6 +70,7 @@
     kKeyIsSyncFrame       = 'sync',  // int32_t (bool)
     kKeyIsCodecConfig     = 'conf',  // int32_t (bool)
     kKeyIsMuxerData       = 'muxd',  // int32_t (bool)
+    kKeyIsEndOfStream     = 'feos',  // int32_t (bool)
     kKeyTime              = 'time',  // int64_t (usecs)
     kKeyDecodingTime      = 'decT',  // int64_t (decoding timestamp in usecs)
     kKeyNTPTime           = 'ntpT',  // uint64_t (ntp-timestamp)
@@ -112,8 +114,6 @@
     kKeyVideoProfile      = 'vprf',  // int32_t
     kKeyVideoLevel        = 'vlev',  // int32_t
 
-    // Set this key to enable authoring files in 64-bit offset
-    kKey64BitFileOffset   = 'fobt',  // int32_t (bool)
     kKey2ByteNalLength    = '2NAL',  // int32_t (bool)
 
     // Identify the file output format for authoring
@@ -238,6 +238,15 @@
     kKeyOpaqueCSD2       = 'csd2',
 
     kKeyHapticChannelCount = 'hapC',
+
+    /* MediaRecorder.h, error notifications can represent track ids with 4 bits only.
+     * | track id | reserved |     error or info type     |
+     * 31         28         16                           0
+     */
+    kKey4BitTrackIds = '4bid',
+
+    // Treat empty track as malformed for MediaRecorder.
+    kKeyEmptyTrackMalFormed = 'nemt', // bool (int32_t)
 };
 
 enum {
@@ -245,6 +254,7 @@
     kTypeAVCC        = 'avcc',
     kTypeHVCC        = 'hvcc',
     kTypeAV1C        = 'av1c',
+    kTypeDVCC        = 'dvcc',
     kTypeD263        = 'd263',
 };
 
@@ -319,8 +329,10 @@
     struct Rect;
     struct MetaDataInternal;
     MetaDataInternal *mInternalData;
+#ifndef __ANDROID_VNDK__
     status_t writeToParcel(Parcel &parcel);
     status_t updateFromParcel(const Parcel &parcel);
+#endif
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/NdkUtils.h b/media/libstagefright/include/media/stagefright/NdkUtils.h
deleted file mode 100644
index a68884a..0000000
--- a/media/libstagefright/include/media/stagefright/NdkUtils.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 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 NDK_UTILS_H_
-
-#define NDK_UTILS_H_
-
-#include <media/stagefright/MetaData.h>
-#include <media/NdkWrapper.h>
-
-namespace android {
-
-sp<MetaData> convertMediaFormatWrapperToMetaData(
-        const sp<AMediaFormatWrapper> &fmt);
-
-}  // namespace android
-
-#endif  // NDK_UTILS_H_
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 4307110..227cead 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -21,8 +21,8 @@
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AudioPresentationInfo.h>
-#include <media/IMediaExtractor.h>
-#include <media/MediaSource.h>
+#include <android/IMediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
diff --git a/media/libstagefright/include/media/stagefright/PersistentSurface.h b/media/libstagefright/include/media/stagefright/PersistentSurface.h
index 49b36c9..f4943c3 100644
--- a/media/libstagefright/include/media/stagefright/PersistentSurface.h
+++ b/media/libstagefright/include/media/stagefright/PersistentSurface.h
@@ -18,31 +18,21 @@
 
 #define PERSISTENT_SURFACE_H_
 
-#include <android/IGraphicBufferSource.h>
 #include <binder/Parcel.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HybridInterface.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <media/stagefright/foundation/ABase.h>
 
-using android::hidl::base::V1_0::IBase;
-
 namespace android {
 
 struct PersistentSurface : public RefBase {
     PersistentSurface() {}
 
-    // create an OMX persistent surface
+    // create a persistent surface
     PersistentSurface(
             const sp<IGraphicBufferProducer>& bufferProducer,
-            const sp<IGraphicBufferSource>& bufferSource) :
-        mBufferProducer(bufferProducer),
-        mBufferSource(bufferSource) { }
-
-    // create a HIDL persistent surface
-    PersistentSurface(
-            const sp<IGraphicBufferProducer>& bufferProducer,
-            const sp<IBase>& hidlTarget) :
+            const sp<hidl::base::V1_0::IBase>& hidlTarget) :
         mBufferProducer(bufferProducer),
         mHidlTarget(hidlTarget) { }
 
@@ -50,18 +40,12 @@
         return mBufferProducer;
     }
 
-    sp<IGraphicBufferSource> getBufferSource() const {
-        return mBufferSource;
-    }
-
-    sp<IBase> getHidlTarget() const {
+    sp<hidl::base::V1_0::IBase> getHidlTarget() const {
         return mHidlTarget;
     }
 
     status_t writeToParcel(Parcel *parcel) const {
         parcel->writeStrongBinder(IInterface::asBinder(mBufferProducer));
-        // this can handle null
-        parcel->writeStrongBinder(IInterface::asBinder(mBufferSource));
         // write hidl target
         if (mHidlTarget != nullptr) {
             HalToken token;
@@ -79,8 +63,6 @@
     status_t readFromParcel(const Parcel *parcel) {
         mBufferProducer = interface_cast<IGraphicBufferProducer>(
                 parcel->readStrongBinder());
-        mBufferSource = interface_cast<IGraphicBufferSource>(
-                parcel->readStrongBinder());
         // read hidl target
         bool haveHidlTarget = parcel->readBool();
         if (haveHidlTarget) {
@@ -97,8 +79,7 @@
 
 private:
     sp<IGraphicBufferProducer> mBufferProducer;
-    sp<IGraphicBufferSource> mBufferSource;
-    sp<IBase> mHidlTarget;
+    sp<hidl::base::V1_0::IBase> mHidlTarget;
 
     DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface);
 };
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index e191e6a..d82be8a 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -17,10 +17,10 @@
 #ifndef REMOTE_DATA_SOURCE_H_
 #define REMOTE_DATA_SOURCE_H_
 
+#include <android/IDataSource.h>
 #include <binder/IMemory.h>
 #include <binder/MemoryDealer.h>
 #include <media/DataSource.h>
-#include <media/IDataSource.h>
 
 namespace android {
 
@@ -48,7 +48,7 @@
         if (size > kBufferSize) {
             size = kBufferSize;
         }
-        return mSource->readAt(offset, mMemory->pointer(), size);
+        return mSource->readAt(offset, mMemory->unsecurePointer(), size);
     }
     virtual status_t getSize(off64_t *size) {
         return mSource->getSize(size);
@@ -66,9 +66,6 @@
     virtual String8 toString()  {
         return mName;
     }
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
-        return mSource->DrmInitialization(mime);
-    }
 
 private:
     enum {
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index 9925114..2ce7bc7 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -17,13 +17,13 @@
 #ifndef REMOTE_MEDIA_EXTRACTOR_H_
 #define REMOTE_MEDIA_EXTRACTOR_H_
 
-#include <media/IMediaExtractor.h>
+#include <android/IMediaExtractor.h>
+#include <media/MediaMetricsItem.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/foundation/ABase.h>
 
 namespace android {
 
-class MediaAnalyticsItem;
 
 // IMediaExtractor wrapper to the MediaExtractor.
 class RemoteMediaExtractor : public BnMediaExtractor {
@@ -41,14 +41,14 @@
     virtual status_t getMetrics(Parcel *reply);
     virtual uint32_t flags() const;
     virtual status_t setMediaCas(const HInterfaceToken &casToken);
-    virtual const char * name();
+    virtual String8 name();
 
 private:
     MediaExtractor *mExtractor;
     sp<DataSource> mSource;
     sp<RefBase> mExtractorPlugin;
 
-    MediaAnalyticsItem *mAnalyticsItem;
+    mediametrics::Item *mMetricsItem;
 
     explicit RemoteMediaExtractor(
             MediaExtractor *extractor,
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
index 03d3869..2cd23f0 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
@@ -18,7 +18,7 @@
 #define REMOTE_MEDIA_SOURCE_H_
 
 #include <media/IMediaSource.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 
 namespace android {
diff --git a/media/libstagefright/include/media/stagefright/SimpleDecodingSource.h b/media/libstagefright/include/media/stagefright/SimpleDecodingSource.h
index 23defb4..a97ae23 100644
--- a/media/libstagefright/include/media/stagefright/SimpleDecodingSource.h
+++ b/media/libstagefright/include/media/stagefright/SimpleDecodingSource.h
@@ -17,7 +17,7 @@
 #ifndef SIMPLE_DECODING_SOURCE_H_
 #define SIMPLE_DECODING_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/Mutexed.h>
 
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index e8e0a11..2b9b759 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -41,8 +41,6 @@
 // TODO: combine this with avc_utils::getNextNALUnit
 const uint8_t *findNextNalStartCode(const uint8_t *data, size_t length);
 
-AString MakeUserAgent();
-
 // Convert a MIME type to a AudioSystem::audio_format
 status_t mapMimeToAudioFormat(audio_format_t& format, const char* mime);
 
@@ -60,8 +58,6 @@
 bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo,
                       bool isStreaming, audio_stream_type_t streamType);
 
-AString uriDebugString(const AString &uri, bool incognito = false);
-
 struct HLSTime {
     int32_t mSeq;
     int64_t mTimeUs;
@@ -85,7 +81,6 @@
 void writeToAMessage(const sp<AMessage> &msg, const BufferingSettings &buffering);
 void readFromAMessage(const sp<AMessage> &msg, BufferingSettings *buffering /* nonnull */);
 
-AString nameForFd(int fd);
 }  // namespace android
 
 #endif  // UTILS_H_
diff --git a/media/libstagefright/include/media/stagefright/foundation b/media/libstagefright/include/media/stagefright/foundation
deleted file mode 120000
index b9fd3b3..0000000
--- a/media/libstagefright/include/media/stagefright/foundation
+++ /dev/null
@@ -1 +0,0 @@
-../../../foundation/include/media/stagefright/foundation/
\ No newline at end of file
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 0ff2d7e..49578d3 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -20,7 +20,7 @@
 
 #include <sys/types.h>
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AudioPresentationInfo.h>
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index a507b91..fbb2d0c 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -29,7 +29,6 @@
 
     shared_libs: [
         "libcrypto",
-        "libmedia",
         "libhidlmemory",
         "android.hardware.cas.native@1.0",
         "android.hidl.memory@1.0",
@@ -37,10 +36,16 @@
     ],
 
     header_libs: [
+        "libmedia_headers",
+        "libaudioclient_headers",
         "media_ndk_headers",
     ],
 
+    export_include_dirs: ["."],
+
     whole_static_libs: [
         "libstagefright_metadatautils",
     ],
+
+    min_sdk_version: "29",
 }
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index f4a6acb..44fe2c8 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -18,7 +18,7 @@
 
 #define ANOTHER_PACKET_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/threads.h>
 #include <utils/List.h>
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index e89d3e3..ea5d2de 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -36,6 +36,10 @@
 #include <inttypes.h>
 #include <netinet/in.h>
 
+#ifndef __ANDROID_APEX__
+#include "HlsSampleDecryptor.h"
+#endif
+
 namespace android {
 
 ElementaryStreamQueue::ElementaryStreamQueue(Mode mode, uint32_t flags)
@@ -50,7 +54,13 @@
 
     // Create the decryptor anyway since we don't know the use-case unless key is provided
     // Won't decrypt if key info not available (e.g., scanner/extractor just parsing ts files)
-    mSampleDecryptor = isSampleEncrypted() ? new HlsSampleDecryptor : NULL;
+    mSampleDecryptor = isSampleEncrypted() ?
+#ifdef __ANDROID_APEX__
+        new SampleDecryptor
+#else
+        new HlsSampleDecryptor
+#endif
+        : NULL;
 }
 
 sp<MetaData> ElementaryStreamQueue::getFormat() {
@@ -1143,7 +1153,7 @@
     }
 
     const RangeInfo &info = *mRangeInfos.begin();
-    if (mBuffer->size() < info.mLength) {
+    if (info.mLength == 0 || mBuffer->size() < info.mLength) {
         return NULL;
     }
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 3227f47..a06bd6a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -25,7 +25,7 @@
 #include <utils/RefBase.h>
 #include <vector>
 
-#include "HlsSampleDecryptor.h"
+#include "SampleDecryptor.h"
 
 namespace android {
 
@@ -109,7 +109,7 @@
 
     sp<MetaData> mFormat;
 
-    sp<HlsSampleDecryptor> mSampleDecryptor;
+    sp<SampleDecryptor> mSampleDecryptor;
     int mAUIndex;
 
     bool isSampleEncrypted() const {
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
index 2c76620..63b4d7b 100644
--- a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
+++ b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef SAMPLE_AES_PROCESSOR_H_
+#ifndef HLS_SAMPLE_AES_PROCESSOR_H_
 
-#define SAMPLE_AES_PROCESSOR_H_
+#define HLS_SAMPLE_AES_PROCESSOR_H_
 
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AString.h>
@@ -28,18 +28,20 @@
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 
+#include "SampleDecryptor.h"
+
 namespace android {
 
-struct HlsSampleDecryptor : RefBase {
+struct HlsSampleDecryptor : SampleDecryptor {
 
     HlsSampleDecryptor();
     explicit HlsSampleDecryptor(const sp<AMessage> &sampleAesKeyItem);
 
-    void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
+    virtual void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
 
-    size_t processNal(uint8_t *nalData, size_t nalSize);
-    void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
-    void processAC3(uint8_t *data, size_t size);
+    virtual size_t processNal(uint8_t *nalData, size_t nalSize);
+    virtual void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
+    virtual void processAC3(uint8_t *data, size_t size);
 
     static AString aesBlockToStr(uint8_t block[AES_BLOCK_SIZE]);
 
@@ -60,4 +62,4 @@
 
 }  // namespace android
 
-#endif // SAMPLE_AES_PROCESSOR_H_
+#endif // HLS_SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/mpeg2ts/SampleDecryptor.h b/media/libstagefright/mpeg2ts/SampleDecryptor.h
new file mode 100644
index 0000000..6bc4ac8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/SampleDecryptor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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 SAMPLE_AES_PROCESSOR_H_
+
+#define SAMPLE_AES_PROCESSOR_H_
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Base class of HlsSampleDecryptor which has dummy default implementation.
+struct SampleDecryptor : RefBase {
+
+    SampleDecryptor() { };
+
+    virtual void signalNewSampleAesKey(const sp<AMessage> &) { };
+
+    virtual size_t processNal(uint8_t *, size_t) { return -1; };
+    virtual void processAAC(size_t, uint8_t *, size_t) { };
+    virtual void processAC3(uint8_t *, size_t) { };
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(SampleDecryptor);
+};
+
+}  // namespace android
+
+#endif // SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp b/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
index ed272bb..7d217eb 100644
--- a/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/1.0/WGraphicBufferSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "TWGraphicBufferSource"
 
@@ -21,6 +25,7 @@
 #include <media/stagefright/omx/1.0/WOmxNode.h>
 #include <media/stagefright/omx/1.0/Conversion.h>
 #include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/omx/OmxGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <media/openmax/OMX_Component.h>
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 7d03d98..78b4f19 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -4,6 +4,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     srcs: [
         "OMXMaster.cpp",
@@ -45,7 +46,6 @@
         "libdl",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
         "libvndksupport",
         "android.hardware.media.omx@1.0",
         "android.hardware.graphics.bufferqueue@1.0",
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 8c5ca6e..094b1f5 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "OMXMaster"
+#include <android-base/properties.h>
 #include <utils/Log.h>
 
 #include <media/stagefright/omx/OMXMaster.h>
@@ -67,6 +68,10 @@
 }
 
 void OMXMaster::addPlugin(const char *libname) {
+    if (::android::base::GetIntProperty("vendor.media.omx", int64_t(1)) == 0) {
+        return;
+    }
+
     void *libHandle = android_load_sphal_library(libname, RTLD_NOW);
 
     if (libHandle == NULL) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ddb4ba0..ac42373 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -47,6 +47,8 @@
 
 #include <hidlmemory/mapping.h>
 
+#include <vector>
+
 static const OMX_U32 kPortIndexInput = 0;
 static const OMX_U32 kPortIndexOutput = 1;
 
@@ -128,7 +130,7 @@
     }
 
     OMX_U8 *getPointer() {
-        return mMem.get() ? static_cast<OMX_U8*>(mMem->pointer()) :
+        return mMem.get() ? static_cast<OMX_U8*>(mMem->unsecurePointer()) :
                 mHidlMemory.get() ? static_cast<OMX_U8*>(
                 static_cast<void*>(mHidlMemory->getPointer())) : nullptr;
     }
@@ -212,6 +214,80 @@
     }
 }
 
+template <typename T>
+inline static T *asSetting(void *setting /* nonnull */, size_t size) {
+    // no need to check internally stored size as that is outside of sanitizing
+    // the underlying buffer's size is the one passed into this method.
+    if (size < sizeof(T)) {
+        return nullptr;
+    }
+
+    return (T *)setting;
+}
+
+inline static void sanitize(OMX_CONFIG_CONTAINERNODEIDTYPE *s) {
+    s->cNodeName = 0;
+}
+
+inline static void sanitize(OMX_CONFIG_METADATAITEMTYPE *s) {
+    s->sLanguageCountry = 0;
+}
+
+inline static void sanitize(OMX_PARAM_PORTDEFINITIONTYPE *s) {
+    switch (s->eDomain) {
+    case OMX_PortDomainAudio:
+        s->format.audio.cMIMEType = 0;
+        break;
+    case OMX_PortDomainVideo:
+        s->format.video.cMIMEType = 0;
+        break;
+    case OMX_PortDomainImage:
+        s->format.image.cMIMEType = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+template <typename T>
+static bool sanitizeAs(void *setting, size_t size) {
+    T *s = asSetting<T>(setting, size);
+    if (s) {
+        sanitize(s);
+        return true;
+    }
+    return false;
+}
+
+static void sanitizeSetting(OMX_INDEXTYPE index, void *setting, size_t size) {
+    if (size < 8 || setting == nullptr) {
+        return;
+    }
+
+    bool ok = true;
+
+    // there are 3 standard OMX settings that contain pointer members
+    switch ((OMX_U32)index) {
+    case OMX_IndexConfigCounterNodeID:
+        ok = sanitizeAs<OMX_CONFIG_CONTAINERNODEIDTYPE>(setting, size);
+        break;
+    case OMX_IndexConfigMetadataItem:
+        ok = sanitizeAs<OMX_CONFIG_METADATAITEMTYPE>(setting, size);
+        break;
+    case OMX_IndexParamPortDefinition:
+        ok = sanitizeAs<OMX_PARAM_PORTDEFINITIONTYPE>(setting, size);
+        break;
+    }
+
+    if (!ok) {
+        // cannot effectively sanitize - we should not be here as IOMX.cpp
+        // should guard against size being too small. Nonetheless, log and
+        // clear result.
+        android_errorWriteLog(0x534e4554, "120781925");
+        memset(setting, 0, size);
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // This provides the underlying Thread used by CallbackDispatcher.
@@ -492,6 +568,10 @@
         }
 
         case OMX_StateLoaded:
+        {
+            freeActiveBuffers();
+            FALLTHROUGH_INTENDED;
+        }
         case OMX_StateInvalid:
             break;
 
@@ -602,7 +682,7 @@
 }
 
 status_t OMXNodeInstance::getParameter(
-        OMX_INDEXTYPE index, void *params, size_t /* size */) {
+        OMX_INDEXTYPE index, void *params, size_t size) {
     Mutex::Autolock autoLock(mLock);
     if (mHandle == NULL) {
         return DEAD_OBJECT;
@@ -619,6 +699,7 @@
     if (err != OMX_ErrorNoMore) {
         CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
     }
+    sanitizeSetting(index, params, size);
     return StatusFromOMXError(err);
 }
 
@@ -644,11 +725,12 @@
     OMX_ERRORTYPE err = OMX_SetParameter(
             mHandle, index, const_cast<void *>(params));
     CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
+    sanitizeSetting(index, const_cast<void *>(params), size);
     return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::getConfig(
-        OMX_INDEXTYPE index, void *params, size_t /* size */) {
+        OMX_INDEXTYPE index, void *params, size_t size) {
     Mutex::Autolock autoLock(mLock);
     if (mHandle == NULL) {
         return DEAD_OBJECT;
@@ -665,6 +747,8 @@
     if (err != OMX_ErrorNoMore) {
         CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
     }
+
+    sanitizeSetting(index, params, size);
     return StatusFromOMXError(err);
 }
 
@@ -686,6 +770,7 @@
     OMX_ERRORTYPE err = OMX_SetConfig(
             mHandle, index, const_cast<void *>(params));
     CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
+    sanitizeSetting(index, const_cast<void *>(params), size);
     return StatusFromOMXError(err);
 }
 
@@ -1173,7 +1258,11 @@
         return BAD_VALUE;
     }
     if (params != NULL) {
-        paramsPointer = params->pointer();
+        // TODO: Using unsecurePointer() has some associated security pitfalls
+        //       (see declaration for details).
+        //       Either document why it is safe in this case or address the
+        //       issue (e.g. by copying).
+        paramsPointer = params->unsecurePointer();
         paramsSize = params->size();
     } else if (hParams != NULL) {
         paramsPointer = hParams->getPointer();
@@ -2420,11 +2509,19 @@
 }
 
 void OMXNodeInstance::freeActiveBuffers() {
-    // Make sure to count down here, as freeBuffer will in turn remove
-    // the active buffer from the vector...
-    for (size_t i = mActiveBuffers.size(); i > 0;) {
-        i--;
-        freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
+    std::vector<OMX_U32> portIndices;
+    std::vector<IOMX::buffer_id> bufferIds;
+    {
+        // Access to mActiveBuffers must be protected by mLock.
+        Mutex::Autolock _l(mLock);
+        for (const ActiveBuffer& activeBuffer : mActiveBuffers) {
+            portIndices.emplace_back(activeBuffer.mPortIndex);
+            bufferIds.emplace_back(activeBuffer.mID);
+        }
+    }
+    for (size_t i = bufferIds.size(); i > 0; ) {
+        --i;
+        freeBuffer(portIndices[i], bufferIds[i]);
     }
 }
 
diff --git a/media/libstagefright/omx/OmxGraphicBufferSource.cpp b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
index 8de1f4f..9484046 100644
--- a/media/libstagefright/omx/OmxGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
@@ -14,12 +14,18 @@
  * limitations under the License.
  */
 
+#ifdef __LP64__
+#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+#endif
+
 #include <inttypes.h>
 
 #define LOG_TAG "OmxGraphicBufferSource"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <media/openmax/OMX_Core.h>
+
 #include <media/stagefright/bqhelper/ComponentWrapper.h>
 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
 #include <media/stagefright/omx/OmxGraphicBufferSource.h>
@@ -59,15 +65,18 @@
 }  // namespace
 
 Status OmxGraphicBufferSource::onOmxExecuting() {
-    return start();
+    status_t err = start();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 Status OmxGraphicBufferSource::onOmxIdle() {
-    return stop();
+    status_t err = stop();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 Status OmxGraphicBufferSource::onOmxLoaded(){
-    return release();
+    status_t err = release();
+    return (OK == err) ? Status::ok() : Status::fromServiceSpecificError(err);
 }
 
 status_t OmxGraphicBufferSource::configure(
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index a720bc9..8c186c9 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -34,12 +34,7 @@
     const char *mRole;
 
 } kComponents[] = {
-    // two choices for aac decoding.
-    // configurable in media/libstagefright/data/media_codecs_google_audio.xml
-    // default implementation
     { "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
-    // alternate implementation
-    { "OMX.google.xaac.decoder", "xaacdec", "audio_decoder.aac" },
     { "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },
     { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
     { "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },
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 9669677..264c01d 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
@@ -48,7 +48,6 @@
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
 
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
 namespace android {
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
index 4e56c98..02d4b7b 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferSource.h
@@ -26,18 +26,16 @@
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 
-#include <android/BnGraphicBufferSource.h>
-
-#include <media/stagefright/omx/OmxGraphicBufferSource.h>
-
 namespace android {
+
+class OmxGraphicBufferSource;
+
 namespace hardware {
 namespace media {
 namespace omx {
 namespace V1_0 {
 namespace implementation {
 
-using ::android::OmxGraphicBufferSource;
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::media::omx::V1_0::ColorAspects;
 using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
@@ -52,8 +50,6 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
-using ::android::IOMXNode;
-
 /**
  * Wrapper classes for conversion
  * ==============================
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
index 518e0cb..e576d75 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
@@ -21,7 +21,6 @@
 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
 #include <media/stagefright/foundation/ABase.h>
 
-#include <android/BnGraphicBufferSource.h>
 #include <android/BnOMXBufferSource.h>
 
 #include "IOmxNodeWrapper.h"
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index 569fa88..fefb3bb 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -7,6 +7,7 @@
     shared_libs: [
         "libstagefright",
         "libbinder",
+        "libdatasource",
         "libmedia",
         "libmedia_omx",
         "libutils",
@@ -22,6 +23,7 @@
 
     header_libs: [
         "libbase_headers",
+        "libmediametrics_headers",
         "media_ndk_headers",
     ],
 
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index cc8c234..039991c 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -27,13 +27,13 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
 #include <media/IMediaHTTPService.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/OMXBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
@@ -211,6 +211,17 @@
     status_t err = getPortDefinition(portIndex, &def);
     EXPECT_SUCCESS(err, "getPortDefinition");
 
+    switch (def.eDomain) {
+        case OMX_PortDomainVideo:
+            EXPECT(def.format.video.cMIMEType == 0, "portDefinition video MIME");
+            break;
+        case OMX_PortDomainAudio:
+            EXPECT(def.format.audio.cMIMEType == 0, "portDefinition audio MIME");
+            break;
+        default:
+            break;
+    }
+
     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
         Buffer buffer;
         buffer.mFlags = 0;
@@ -278,7 +289,7 @@
 
 static sp<IMediaExtractor> CreateExtractorFromURI(const char *uri) {
     sp<DataSource> source =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, uri);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri);
 
     if (source == NULL) {
         return NULL;
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 9df3508..7bd33c1 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -203,6 +203,14 @@
     unsigned mSerial;
 };
 
+bool AMPEG4ElementaryAssembler::initCheck() {
+    if(mSizeLength == 0 || mIndexLength == 0 || mIndexDeltaLength == 0) {
+        android_errorWriteLog(0x534e4554, "124777537");
+        return false;
+    }
+    return true;
+}
+
 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
         const sp<ARTPSource> &source) {
     List<sp<ABuffer> > *queue = source->queue();
@@ -250,12 +258,16 @@
     } else {
         // hexdump(buffer->data(), buffer->size());
         if (buffer->size() < 2) {
+            android_errorWriteLog(0x534e4554, "124783982");
+            queue->erase(queue->begin());
             return MALFORMED_PACKET;
         }
 
         unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
 
         if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
+            android_errorWriteLog(0x534e4554, "124783982");
+            queue->erase(queue->begin());
             return MALFORMED_PACKET;
         }
 
@@ -359,6 +371,8 @@
                 return MALFORMED_PACKET;
             }
             if (buffer->size() < offset + header.mSize) {
+                android_errorWriteLog(0x534e4554, "124783982");
+                queue->erase(queue->begin());
                 return MALFORMED_PACKET;
             }
 
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
index 693fca5..57b7d71 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
@@ -36,6 +36,7 @@
     AMPEG4ElementaryAssembler(
             const sp<AMessage> &notify, const AString &desc,
             const AString &params);
+    virtual bool initCheck();
 
 protected:
     virtual ~AMPEG4ElementaryAssembler();
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 1aa8a20..574bd7a 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -112,7 +112,9 @@
     sp<ABuffer> profileLevelID = NULL;
     if (GetAttribute(params, "profile-level-id", &val)) {
         profileLevelID = decodeHex(val);
-        CHECK_EQ(profileLevelID->size(), 3u);
+        if (profileLevelID != NULL && profileLevelID->size() != 3u) {
+            profileLevelID = NULL;
+        }
     }
 
     Vector<sp<ABuffer> > paramSets;
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
index 7c147be..4082d4c 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.h
+++ b/media/libstagefright/rtsp/ARTPAssembler.h
@@ -39,6 +39,7 @@
 
     void onPacketReceived(const sp<ARTPSource> &source);
     virtual void onByeReceived() = 0;
+    virtual bool initCheck() { return true; }
 
 protected:
     virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source) = 0;
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4afa6f4..f5f8128 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -82,6 +82,10 @@
     } else {
         TRESPASS();
     }
+
+    if (mAssembler != NULL && !mAssembler->initCheck()) {
+        mAssembler.clear();
+    }
 }
 
 static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) {
@@ -89,7 +93,7 @@
 }
 
 void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
-    if (queuePacket(buffer) && mAssembler != NULL) {
+    if (mAssembler != NULL && queuePacket(buffer)) {
         mAssembler->onPacketReceived(this);
     }
 }
@@ -171,7 +175,9 @@
 }
 
 void ARTPSource::byeReceived() {
-    mAssembler->onByeReceived();
+    if (mAssembler != NULL) {
+        mAssembler->onByeReceived();
+    }
 }
 
 void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 4f86773..58d6086 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -22,7 +22,7 @@
 
 #include <fcntl.h>
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 789e62a..bb66f4c 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -21,12 +21,14 @@
 #include "ARTSPConnection.h"
 #include "NetworkUtils.h"
 
+#include <datasource/HTTPBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <arpa/inet.h>
 #include <fcntl.h>
@@ -34,7 +36,6 @@
 #include <openssl/md5.h>
 #include <sys/socket.h>
 
-#include "include/HTTPBase.h"
 
 namespace android {
 
@@ -953,7 +954,7 @@
     CHECK_GE(space2, 0);
 
     method->setTo(request, 0, space1);
-    url->setTo(request, space1 + 1, space2 - space1);
+    url->setTo(request, space1 + 1, space2 - space1 - 1);
 }
 
 void ARTSPConnection::addAuthentication(AString *request) {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 8df2676..56b604d 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -46,6 +46,8 @@
             const char *url, AString *host, unsigned *port, AString *path,
             AString *user, AString *pass);
 
+    int getSocket() { return mSocket; }
+
 protected:
     virtual ~ARTSPConnection();
     virtual void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 9263565..2b42040 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -141,6 +141,12 @@
                 AString key, value;
 
                 ssize_t equalPos = line.find("=");
+                /* The condition 'if (line.size() < 2 || line.c_str()[1] != '=')' a few lines above
+                 * ensures '=' is at position 1.  However for robustness we do the following check.
+                 */
+                if (equalPos < 0) {
+                    return false;
+                }
 
                 key = AString(line, 0, equalPos + 1);
                 value = AString(line, equalPos + 1, line.size() - equalPos - 1);
diff --git a/media/libstagefright/rtsp/Android.bp b/media/libstagefright/rtsp/Android.bp
index 9bc9c89..a5a895e 100644
--- a/media/libstagefright/rtsp/Android.bp
+++ b/media/libstagefright/rtsp/Android.bp
@@ -21,6 +21,7 @@
 
     shared_libs: [
         "libcrypto",
+        "libdatasource",
         "libmedia",
     ],
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 48bc8ce..7f025a5 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -36,18 +36,19 @@
 #include <ctype.h>
 #include <cutils/properties.h>
 
+#include <datasource/HTTPBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <netdb.h>
 
-#include "HTTPBase.h"
 
 #if LOG_NDEBUG
 #define UNUSED_UNLESS_VERBOSE(x) (void)(x)
@@ -257,6 +258,10 @@
         msg->post();
     }
 
+    sp<ARTSPConnection> getARTSPConnection() {
+      return mConn;
+    }
+
     static void addRR(const sp<ABuffer> &buf) {
         uint8_t *ptr = buf->data() + buf->size();
         ptr[0] = 0x80 | 0;
diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp
index 665d51a..e236267 100644
--- a/media/libstagefright/rtsp/SDPLoader.cpp
+++ b/media/libstagefright/rtsp/SDPLoader.cpp
@@ -22,12 +22,13 @@
 
 #include "ASessionDescription.h"
 
+#include <datasource/MediaHTTP.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
-#include <media/stagefright/ClearMediaHTTP.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/FoundationUtils.h>
 
 #define DEFAULT_SDP_SIZE 100000
 
@@ -41,7 +42,7 @@
       mFlags(flags),
       mNetLooper(new ALooper),
       mCancelled(false),
-      mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())) {
+      mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())) {
     mNetLooper->setName("sdp net");
     mNetLooper->start(false /* runOnCallingThread */,
                       false /* canCallJava */,
diff --git a/media/libstagefright/rtsp/VideoSource.h b/media/libstagefright/rtsp/VideoSource.h
index 4be9bf6..f29db57 100644
--- a/media/libstagefright/rtsp/VideoSource.h
+++ b/media/libstagefright/rtsp/VideoSource.h
@@ -18,7 +18,7 @@
 
 #define VIDEO_SOURCE_H_
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
new file mode 100644
index 0000000..e3e61d7
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "ExtractorFactoryTest",
+    gtest: true,
+
+    srcs: [
+        "ExtractorFactoryTest.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libbase",
+        "libutils",
+        "libmedia",
+        "libbinder",
+        "libcutils",
+        "libdl_android",
+        "libdatasource",
+        "libmediametrics",
+    ],
+
+    static_libs: [
+        "libstagefright",
+        "libstagefright_foundation",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright",
+    ],
+
+    // TODO: (b/150181583)
+    compile_multilib: "first",
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/tests/extractorFactory/AndroidTest.xml b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
new file mode 100644
index 0000000..3aa6392
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Test module config for extractor factory unit tests">
+    <option name="test-suite-tag" value="ExtractorFactoryTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
+            value="/data/local/tmp/ExtractorFactoryTestRes/" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="ExtractorFactoryTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp
new file mode 100644
index 0000000..d155caa
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ExtractorFactoryTest"
+#include <utils/Log.h>
+
+#include <binder/ProcessState.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include "ExtractorFactoryTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/exFactoryLogs"
+
+using namespace android;
+
+static ExtractorFactoryTestEnvironment *gEnv = nullptr;
+
+class ExtractorFactoryTest : public ::testing::TestWithParam<pair<string, string>> {
+  public:
+    ExtractorFactoryTest() : mDataSource(nullptr), mExtractor(nullptr) {}
+
+    ~ExtractorFactoryTest() {
+        if (mDataSource) {
+            mDataSource.clear();
+            mDataSource = nullptr;
+        }
+        if (mExtractor) {
+            mExtractor.clear();
+            mExtractor = nullptr;
+        }
+    }
+
+    int32_t createDataSource(string inputFileName);
+    int32_t createExtractor(bool createFromService, string inputMime);
+
+    sp<DataSource> mDataSource;
+    sp<IMediaExtractor> mExtractor;
+};
+
+int32_t ExtractorFactoryTest::createDataSource(string inputFileName) {
+    FILE *mInputFp = fopen(inputFileName.c_str(), "rb");
+    if (!mInputFp) {
+        ALOGE("Unable to open input file : %s for reading", inputFileName.c_str());
+        return -1;
+    }
+    struct stat buf;
+    int32_t status = stat(inputFileName.c_str(), &buf);
+    if (status != 0) {
+        ALOGE("Failed to read file properties for input file : %s", inputFileName.c_str());
+        return -1;
+    }
+    int32_t fd = fileno(mInputFp);
+    if (fd < 0) {
+        ALOGE("Invalid file descriptor for input file : %s", inputFileName.c_str());
+        return -1;
+    }
+    mDataSource = new FileSource(dup(fd), 0, buf.st_size);
+    if (!mDataSource) return -1;
+    return 0;
+}
+
+int32_t ExtractorFactoryTest::createExtractor(bool createFromService, string inputMime) {
+    ALOGV("Creating extractor for mime : %s", inputMime.c_str());
+    if (createFromService) {
+        mExtractor = MediaExtractorFactory::CreateFromService(mDataSource, inputMime.c_str());
+    } else {
+        mExtractor = MediaExtractorFactory::Create(mDataSource);
+    }
+    if (mExtractor == nullptr) return -1;
+    return 0;
+}
+
+TEST_F(ExtractorFactoryTest, ListExtractorsTest) {
+    MediaExtractorFactory::LoadExtractors();
+    vector<std::string> supportedTypes = MediaExtractorFactory::getSupportedTypes();
+    ASSERT_GT(supportedTypes.size(), 0) << " MediaExtractorFactory doesn't suuport any extractor";
+
+    FILE *outputLog = fopen(OUTPUT_FILE_NAME, "wb");
+    ASSERT_NE(outputLog, nullptr) << "Unable to open output file - " << OUTPUT_FILE_NAME
+                                  << " for writing";
+
+    int32_t fd = fileno(outputLog);
+    ASSERT_GE(fd, 0);
+
+    Vector<String16> args;
+    int32_t status = MediaExtractorFactory::dump(fd, args);
+    ASSERT_EQ(status, OK) << "MediaExtractorFactory dump failed";
+    fclose(outputLog);
+}
+
+TEST_P(ExtractorFactoryTest, ExtractorFactoryApiTest) {
+    string inputMime = GetParam().second;
+    string inputFileName = gEnv->getRes() + GetParam().first;
+
+    MediaExtractorFactory::LoadExtractors();
+    bool createMode[] = {true, false};
+    for (bool createFromService : createMode) {
+        int32_t status = createDataSource(inputFileName);
+        ASSERT_EQ(status, 0) << "create data source failed";
+
+        status = createExtractor(createFromService, inputMime);
+        ASSERT_EQ(status, 0) << "Extractor creation failed for input: " << inputFileName;
+
+        int32_t numTracks = mExtractor->countTracks();
+        ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+        sp<MetaData> meta = mExtractor->getMetaData();
+        ASSERT_NE(meta, nullptr) << "getMetaData returned null";
+
+        const char *mime;
+        bool valueFound = meta->findCString(kKeyMIMEType, &mime);
+        ASSERT_TRUE(valueFound) << "Extractor did not provide MIME type";
+        ASSERT_EQ(mime, inputMime) << "Extractor factory returned invalid mime type";
+        mExtractor.clear();
+        mDataSource.clear();
+    }
+}
+
+// TODO: (b/150111966)
+// Replace mime strings with appropriate definitions
+INSTANTIATE_TEST_SUITE_P(
+        ExtractorFactoryTestAll, ExtractorFactoryTest,
+        ::testing::Values(make_pair("loudsoftaac.aac", MEDIA_MIMETYPE_AUDIO_AAC_ADTS),
+                          make_pair("testamr.amr", "audio/amr"),
+                          make_pair("amrwb.wav", MEDIA_MIMETYPE_AUDIO_AMR_WB),
+                          make_pair("john_cage.ogg", MEDIA_MIMETYPE_CONTAINER_OGG),
+                          make_pair("monotestgsm.wav", MEDIA_MIMETYPE_CONTAINER_WAV),
+                          make_pair("segment000001.ts", MEDIA_MIMETYPE_CONTAINER_MPEG2TS),
+                          make_pair("sinesweepflac.flac", MEDIA_MIMETYPE_AUDIO_FLAC),
+                          make_pair("testopus.opus", MEDIA_MIMETYPE_CONTAINER_OGG),
+                          make_pair("midi_a.mid", MEDIA_MIMETYPE_AUDIO_MIDI),
+                          make_pair("sinesweepvorbis.mkv", MEDIA_MIMETYPE_CONTAINER_MATROSKA),
+                          make_pair("sinesweepoggmp4.mp4", "audio/mp4"),
+                          make_pair("sinesweepmp3lame.mp3", MEDIA_MIMETYPE_AUDIO_MPEG),
+                          make_pair("swirl_144x136_vp9.webm", "video/webm"),
+                          make_pair("swirl_144x136_vp8.webm", "video/webm"),
+                          make_pair("swirl_132x130_mpeg4.mp4", MEDIA_MIMETYPE_CONTAINER_MPEG4)));
+
+int main(int argc, char **argv) {
+    ProcessState::self()->startThreadPool();
+    gEnv = new ExtractorFactoryTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h
new file mode 100644
index 0000000..0fad4d3
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
+#define __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class ExtractorFactoryTestEnvironment : public ::testing::Environment {
+  public:
+    ExtractorFactoryTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int ExtractorFactoryTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/tests/extractorFactory/README.md b/media/libstagefright/tests/extractorFactory/README.md
new file mode 100644
index 0000000..aaa71aa
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/README.md
@@ -0,0 +1,37 @@
+## Media Testing ##
+---
+#### Writer :
+The Writer Test Suite validates the writers available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/tests/writer/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push extractor /data/local/tmp/
+```
+
+usage: ExtractorFactoryTest -P \<path_to_res_folder\>
+```
+adb shell /data/local/tmp/ExtractorFactoryTest -P /data/local/tmp/extractor/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ExtractorFactoryTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
new file mode 100644
index 0000000..7e169cb
--- /dev/null
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "writerTest",
+    gtest: true,
+
+    srcs: [
+        "WriterUtility.cpp",
+        "WriterTest.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libstagefright_webm",
+        "libdatasource",
+        "libstagefright",
+        "libstagefright_foundation",
+        "libstagefright_esds",
+        "libogg",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/tests/writer/AndroidTest.xml b/media/libstagefright/tests/writer/AndroidTest.xml
new file mode 100644
index 0000000..d831555
--- /dev/null
+++ b/media/libstagefright/tests/writer/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Test module config for writer tests">
+    <option name="test-suite-tag" value="writerTest" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="writerTest->/data/local/tmp/writerTest" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/Writer.zip?unzip=true"
+            value="/data/local/tmp/writerTestRes/" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="writerTest" />
+        <option name="native-test-flag" value="-P /data/local/tmp/writerTestRes/" />
+    </test>
+</configuration>
diff --git a/media/libstagefright/tests/writer/README.md b/media/libstagefright/tests/writer/README.md
new file mode 100644
index 0000000..ae07917
--- /dev/null
+++ b/media/libstagefright/tests/writer/README.md
@@ -0,0 +1,31 @@
+## Media Testing ##
+---
+#### Writer :
+The Writer Test Suite validates the writers available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/tests/writer/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/writerTest/writerTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/writerTest/writerTest /data/local/tmp/
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/writerTestRes.zip).
+Download and extract the folder. Push all the files in this folder to /data/local/tmp/ on the device.
+```
+adb push writerTestRes /data/local/tmp/
+```
+
+usage: writerTest -P \<path_to_res_folder\>
+```
+adb shell /data/local/tmp/writerTest -P /data/local/tmp/
+```
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
new file mode 100644
index 0000000..ff063e3
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2019 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 "WriterTest"
+#include <utils/Log.h>
+
+#include <fstream>
+#include <iostream>
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/mediarecorder.h>
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OggWriter.h>
+#include <webm/WebmWriter.h>
+
+#include "WriterTestEnvironment.h"
+#include "WriterUtility.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/writer.out"
+
+static WriterTestEnvironment *gEnv = nullptr;
+
+struct configFormat {
+    char mime[128];
+    int32_t width;
+    int32_t height;
+    int32_t sampleRate;
+    int32_t channelCount;
+};
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+    const char *mime;
+    string inputFile;
+    string info;
+    int32_t firstParam;
+    int32_t secondParam;
+    bool isAudio;
+} kInputData[] = {
+        {MEDIA_MIMETYPE_AUDIO_OPUS, "bbb_opus_stereo_128kbps_48000hz.opus",
+         "bbb_opus_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AAC, "bbb_aac_stereo_128kbps_48000hz.aac",
+         "bbb_aac_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AAC_ADTS, "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.adts",
+         "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_AMR_NB, "sine_amrnb_1ch_12kbps_8000hz.amrnb",
+         "sine_amrnb_1ch_12kbps_8000hz.info", 8000, 1, true},
+        {MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+         "bbb_amrwb_1ch_14kbps_16000hz.info", 16000, 1, true},
+        {MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
+         "bbb_vorbis_stereo_128kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_AUDIO_FLAC, "bbb_flac_stereo_680kbps_48000hz.flac",
+         "bbb_flac_stereo_680kbps_48000hz.info", 48000, 2, true},
+        {MEDIA_MIMETYPE_VIDEO_VP9, "bbb_vp9_176x144_285kbps_60fps.vp9",
+         "bbb_vp9_176x144_285kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_VP8, "bbb_vp8_176x144_240kbps_60fps.vp8",
+         "bbb_vp8_176x144_240kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_AVC, "bbb_avc_176x144_300kbps_60fps.h264",
+         "bbb_avc_176x144_300kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_HEVC, "bbb_hevc_176x144_176kbps_60fps.hevc",
+         "bbb_hevc_176x144_176kbps_60fps.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_AV1, "bbb_av1_176_144.av1", "bbb_av1_176_144.info", 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_H263, "bbb_h263_352x288_300kbps_12fps.h263",
+         "bbb_h263_352x288_300kbps_12fps.info", 352, 288, false},
+        {MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_mpeg4_352x288_512kbps_30fps.m4v",
+         "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false},
+};
+
+class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+  public:
+    WriterTest() : mWriter(nullptr), mFileMeta(nullptr), mCurrentTrack(nullptr) {}
+
+    ~WriterTest() {
+        if (mWriter) {
+            mWriter.clear();
+            mWriter = nullptr;
+        }
+        if (mFileMeta) {
+            mFileMeta.clear();
+            mFileMeta = nullptr;
+        }
+        if (mCurrentTrack) {
+            mCurrentTrack.clear();
+            mCurrentTrack = nullptr;
+        }
+    }
+
+    virtual void SetUp() override {
+        mNumCsds = 0;
+        mInputFrameId = 0;
+        mWriterName = unknown_comp;
+        mDisableTest = false;
+
+        static const std::map<std::string, standardWriters> mapWriter = {
+                {"ogg", OGG},     {"aac", AAC},      {"aac_adts", AAC_ADTS}, {"webm", WEBM},
+                {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB},      {"mpeg2Ts", MPEG2TS}};
+        // Find the component type
+        string writerFormat = GetParam().first;
+        if (mapWriter.find(writerFormat) != mapWriter.end()) {
+            mWriterName = mapWriter.at(writerFormat);
+        }
+        if (mWriterName == standardWriters::unknown_comp) {
+            cout << "[   WARN   ] Test Skipped. No specific writer mentioned\n";
+            mDisableTest = true;
+        }
+    }
+
+    virtual void TearDown() override {
+        mBufferInfo.clear();
+        if (mInputStream.is_open()) mInputStream.close();
+    }
+
+    void getInputBufferInfo(string inputFileName, string inputInfo);
+
+    int32_t createWriter(int32_t fd);
+
+    int32_t addWriterSource(bool isAudio, configFormat params);
+
+    enum standardWriters {
+        OGG,
+        AAC,
+        AAC_ADTS,
+        WEBM,
+        MPEG4,
+        AMR_NB,
+        AMR_WB,
+        MPEG2TS,
+        unknown_comp,
+    };
+
+    standardWriters mWriterName;
+    sp<MediaWriter> mWriter;
+    sp<MetaData> mFileMeta;
+    sp<MediaAdapter> mCurrentTrack;
+
+    bool mDisableTest;
+    int32_t mNumCsds;
+    int32_t mInputFrameId;
+    ifstream mInputStream;
+    vector<BufferInfo> mBufferInfo;
+};
+
+void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo) {
+    std::ifstream eleInfo;
+    eleInfo.open(inputInfo.c_str());
+    ASSERT_EQ(eleInfo.is_open(), true);
+    int32_t bytesCount = 0;
+    uint32_t flags = 0;
+    int64_t timestamp = 0;
+    while (1) {
+        if (!(eleInfo >> bytesCount)) break;
+        eleInfo >> flags;
+        eleInfo >> timestamp;
+        mBufferInfo.push_back({bytesCount, flags, timestamp});
+        if (flags == CODEC_CONFIG_FLAG) mNumCsds++;
+    }
+    eleInfo.close();
+    mInputStream.open(inputFileName.c_str(), std::ifstream::binary);
+    ASSERT_EQ(mInputStream.is_open(), true);
+}
+
+int32_t WriterTest::createWriter(int32_t fd) {
+    mFileMeta = new MetaData;
+    switch (mWriterName) {
+        case OGG:
+            mWriter = new OggWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+            break;
+        case AAC:
+            mWriter = new AACWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+            break;
+        case AAC_ADTS:
+            mWriter = new AACWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+            break;
+        case WEBM:
+            mWriter = new WebmWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+            break;
+        case MPEG4:
+            mWriter = new MPEG4Writer(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+            break;
+        case AMR_NB:
+            mWriter = new AMRWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+            break;
+        case AMR_WB:
+            mWriter = new AMRWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+            break;
+        case MPEG2TS:
+            mWriter = new MPEG2TSWriter(fd);
+            mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+            break;
+        default:
+            return -1;
+    }
+    if (mWriter == nullptr) return -1;
+    mFileMeta->setInt32(kKeyRealTimeRecording, false);
+    return 0;
+}
+
+int32_t WriterTest::addWriterSource(bool isAudio, configFormat params) {
+    if (mInputFrameId) return -1;
+    sp<AMessage> format = new AMessage;
+    if (mInputStream.is_open()) {
+        format->setString("mime", params.mime);
+        if (isAudio) {
+            format->setInt32("channel-count", params.channelCount);
+            format->setInt32("sample-rate", params.sampleRate);
+        } else {
+            format->setInt32("width", params.width);
+            format->setInt32("height", params.height);
+        }
+
+        int32_t status =
+                writeHeaderBuffers(mInputStream, mBufferInfo, mInputFrameId, format, mNumCsds);
+        if (status != 0) return -1;
+    }
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
+    mCurrentTrack = new MediaAdapter(trackMeta);
+    if (mCurrentTrack == nullptr) {
+        ALOGE("MediaAdapter returned nullptr");
+        return -1;
+    }
+    status_t result = mWriter->addSource(mCurrentTrack);
+    return result;
+}
+
+void getFileDetails(string &inputFilePath, string &info, configFormat &params, bool &isAudio,
+                    int32_t streamIndex = 0) {
+    if (streamIndex >= sizeof(kInputData) / sizeof(kInputData[0])) {
+        return;
+    }
+    inputFilePath += kInputData[streamIndex].inputFile;
+    info += kInputData[streamIndex].info;
+    strcpy(params.mime, kInputData[streamIndex].mime);
+    isAudio = kInputData[streamIndex].isAudio;
+    if (isAudio) {
+        params.sampleRate = kInputData[streamIndex].firstParam;
+        params.channelCount = kInputData[streamIndex].secondParam;
+    } else {
+        params.width = kInputData[streamIndex].firstParam;
+        params.height = kInputData[streamIndex].secondParam;
+    }
+    return;
+}
+
+TEST_P(WriterTest, CreateWriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Tests the creation of writers");
+
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
+
+    // Creating writer within a test scope. Destructor should be called when the test ends
+    ASSERT_EQ((status_t)OK, createWriter(fd))
+            << "Failed to create writer for output format:" << GetParam().first;
+}
+
+TEST_P(WriterTest, WriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Checks if for a given input, a valid muxed file has been created or not");
+
+    string writerFormat = GetParam().first;
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
+
+    int32_t status = createWriter(fd);
+    ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat;
+
+    string inputFile = gEnv->getRes();
+    string inputInfo = gEnv->getRes();
+    configFormat param;
+    bool isAudio;
+    int32_t inputFileIdx = GetParam().second;
+    getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+    ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
+
+    ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
+    status = addWriterSource(isAudio, param);
+    ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
+
+    status = mWriter->start(mFileMeta.get());
+    ASSERT_EQ((status_t)OK, status);
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+                                 mBufferInfo.size());
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+    mCurrentTrack->stop();
+
+    status = mWriter->stop();
+    ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
+    close(fd);
+}
+
+TEST_P(WriterTest, PauseWriterTest) {
+    if (mDisableTest) return;
+    ALOGV("Validates the pause() api of writers");
+
+    string writerFormat = GetParam().first;
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
+
+    int32_t status = createWriter(fd);
+    ASSERT_EQ((status_t)OK, status) << "Failed to create writer for output format:" << writerFormat;
+
+    string inputFile = gEnv->getRes();
+    string inputInfo = gEnv->getRes();
+    configFormat param;
+    bool isAudio;
+    int32_t inputFileIdx = GetParam().second;
+    getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+    ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
+
+    ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
+    status = addWriterSource(isAudio, param);
+    ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
+
+    status = mWriter->start(mFileMeta.get());
+    ASSERT_EQ((status_t)OK, status);
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+                                 mBufferInfo.size() / 4);
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+
+    bool isPaused = false;
+    if ((mWriterName != standardWriters::MPEG2TS) && (mWriterName != standardWriters::MPEG4)) {
+        status = mWriter->pause();
+        ASSERT_EQ((status_t)OK, status);
+        isPaused = true;
+    }
+    // In the pause state, writers shouldn't write anything. Testing the writers for the same
+    int32_t numFramesPaused = mBufferInfo.size() / 4;
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                                  mInputFrameId, numFramesPaused, isPaused);
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+
+    if (isPaused) {
+        status = mWriter->start(mFileMeta.get());
+        ASSERT_EQ((status_t)OK, status);
+    }
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                                  mInputFrameId, mBufferInfo.size());
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+    mCurrentTrack->stop();
+
+    status = mWriter->stop();
+    ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
+    close(fd);
+}
+
+TEST_P(WriterTest, MultiStartStopPauseTest) {
+    // TODO: (b/144821804)
+    // Enable the test for MPE2TS writer
+    if (mDisableTest || mWriterName == standardWriters::MPEG2TS) return;
+    ALOGV("Test writers for multiple start, stop and pause calls");
+
+    string outputFile = OUTPUT_FILE_NAME;
+    int32_t fd =
+            open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    ASSERT_GE(fd, 0) << "Failed to open output file to dump writer's data";
+
+    string writerFormat = GetParam().first;
+    int32_t status = createWriter(fd);
+    ASSERT_EQ(status, (status_t)OK) << "Failed to create writer for output format:" << writerFormat;
+
+    string inputFile = gEnv->getRes();
+    string inputInfo = gEnv->getRes();
+    configFormat param;
+    bool isAudio;
+    int32_t inputFileIdx = GetParam().second;
+    getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+    ASSERT_NE(inputFile.compare(gEnv->getRes()), 0) << "No input file specified";
+
+    ASSERT_NO_FATAL_FAILURE(getInputBufferInfo(inputFile, inputInfo));
+    status = addWriterSource(isAudio, param);
+    ASSERT_EQ((status_t)OK, status) << "Failed to add source for " << writerFormat << "Writer";
+
+    // first start should succeed.
+    status = mWriter->start(mFileMeta.get());
+    ASSERT_EQ((status_t)OK, status) << "Could not start the writer";
+
+    // Multiple start() may/may not succeed.
+    // Writers are expected to not crash on multiple start() calls.
+    for (int32_t count = 0; count < kMaxCount; count++) {
+        mWriter->start(mFileMeta.get());
+    }
+
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+                              mBufferInfo.size() / 4);
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+
+    for (int32_t count = 0; count < kMaxCount; count++) {
+        mWriter->pause();
+        mWriter->start(mFileMeta.get());
+    }
+
+    mWriter->pause();
+    int32_t numFramesPaused = mBufferInfo.size() / 4;
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                              mInputFrameId, numFramesPaused, true);
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+
+    for (int32_t count = 0; count < kMaxCount; count++) {
+        mWriter->start(mFileMeta.get());
+    }
+
+    status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+                              mInputFrameId, mBufferInfo.size());
+    ASSERT_EQ((status_t)OK, status) << writerFormat << " writer failed";
+
+    mCurrentTrack->stop();
+
+    // first stop should succeed.
+    status = mWriter->stop();
+    ASSERT_EQ((status_t)OK, status) << "Failed to stop the writer";
+    // Multiple stop() may/may not succeed.
+    // Writers are expected to not crash on multiple stop() calls.
+    for (int32_t count = 0; count < kMaxCount; count++) {
+        mWriter->stop();
+    }
+    close(fd);
+}
+
+// TODO: (b/144476164)
+// Add AAC_ADTS, FLAC, AV1 input
+INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriterTest,
+                         ::testing::Values(make_pair("ogg", 0), make_pair("webm", 0),
+                                           make_pair("aac", 1), make_pair("mpeg4", 1),
+                                           make_pair("amrnb", 3), make_pair("amrwb", 4),
+                                           make_pair("webm", 5), make_pair("webm", 7),
+                                           make_pair("webm", 8), make_pair("mpeg4", 9),
+                                           make_pair("mpeg4", 10), make_pair("mpeg4", 12),
+                                           make_pair("mpeg4", 13), make_pair("mpeg2Ts", 1),
+                                           make_pair("mpeg2Ts", 9)));
+
+int main(int argc, char **argv) {
+    gEnv = new WriterTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/libstagefright/tests/writer/WriterTestEnvironment.h b/media/libstagefright/tests/writer/WriterTestEnvironment.h
new file mode 100644
index 0000000..99e686f
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 __WRITER_TEST_ENVIRONMENT_H__
+#define __WRITER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class WriterTestEnvironment : public ::testing::Environment {
+  public:
+    WriterTestEnvironment() : res("/data/local/tmp/") {}
+
+    // Parses the command line arguments
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int WriterTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P':
+                setRes(optarg);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __WRITER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/tests/writer/WriterUtility.cpp b/media/libstagefright/tests/writer/WriterUtility.cpp
new file mode 100644
index 0000000..f24ccb6
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 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 "WriterUtility"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaBuffer.h>
+
+#include "WriterUtility.h"
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                            int32_t &inputFrameId, sp<MediaAdapter> &currentTrack, int32_t offset,
+                            int32_t range, bool isPaused) {
+    while (1) {
+        if (inputFrameId >= (int)bufferInfo.size() || inputFrameId >= (offset + range)) break;
+        int32_t size = bufferInfo[inputFrameId].size;
+        char *data = (char *)malloc(size);
+        if (!data) {
+            ALOGE("Insufficient memeory to read input");
+            return -1;
+        }
+
+        inputStream.read(data, size);
+        CHECK_EQ(inputStream.gcount(), size);
+
+        sp<ABuffer> buffer = new ABuffer((void *)data, size);
+        if (buffer.get() == nullptr) {
+            ALOGE("sendBuffersToWriter() got a nullptr buffer.");
+            return -1;
+        }
+        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[inputFrameId].timeUs);
+        // Just set the kKeyDecodingTime as the presentation time for now.
+        sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[inputFrameId].timeUs);
+
+        if (bufferInfo[inputFrameId].flags == 1) {
+            sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+        }
+
+        // This pushBuffer will wait until the mediaBuffer is consumed.
+        int status = currentTrack->pushBuffer(mediaBuffer);
+        free(data);
+        inputFrameId++;
+
+        if (OK != status) {
+            if (!isPaused) return status;
+            else {
+                ALOGD("Writer is in paused state. Input buffers won't get consumed");
+                return 0;
+            }
+        }
+    }
+    return 0;
+}
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                           int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds) {
+    char csdName[kMaxCSDStrlen];
+    for (int csdId = 0; csdId < numCsds; csdId++) {
+        int32_t flags = bufferInfo[inputFrameId].flags;
+        if (flags == CODEC_CONFIG_FLAG) {
+            int32_t size = bufferInfo[inputFrameId].size;
+            char *data = (char *)malloc(size);
+            if (!data) {
+                ALOGE("Insufficient memeory to read input");
+                return -1;
+            }
+            inputStream.read(data, size);
+            CHECK_EQ(inputStream.gcount(), size);
+
+            sp<ABuffer> csdBuffer = ABuffer::CreateAsCopy((void *)data, size);
+            if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+                return -1;
+            }
+            snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+            format->setBuffer(csdName, csdBuffer);
+            inputFrameId++;
+            free(data);
+        }
+    }
+    return 0;
+}
diff --git a/media/libstagefright/tests/writer/WriterUtility.h b/media/libstagefright/tests/writer/WriterUtility.h
new file mode 100644
index 0000000..cdd6246
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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 WRITER_UTILITY_H_
+#define WRITER_UTILITY_H_
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <media/stagefright/MediaAdapter.h>
+
+using namespace android;
+using namespace std;
+
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kMaxCount = 20;
+
+struct BufferInfo {
+    int32_t size;
+    uint32_t flags;
+    int64_t timeUs;
+};
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                            int32_t &inputFrameId, sp<MediaAdapter> &currentTrack, int32_t offset,
+                            int32_t range, bool isPaused = false);
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+                           int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds);
+
+#endif  // WRITER_UTILITY_H_
diff --git a/media/libstagefright/timedtext/Android.bp b/media/libstagefright/timedtext/Android.bp
index 6935655..4f4ceb1 100644
--- a/media/libstagefright/timedtext/Android.bp
+++ b/media/libstagefright/timedtext/Android.bp
@@ -23,32 +23,4 @@
     shared_libs: ["libmedia"],
 }
 
-cc_library_static {
-    name: "libstagefright_timedtext2",
 
-    srcs: ["TextDescriptions2.cpp"],
-
-    static_libs: [
-        "libmediaplayer2-protos",
-        "libprotobuf-cpp-lite",
-    ],
-
-    cflags: [
-        "-Wno-multichar",
-        "-Werror",
-        "-Wall",
-    ],
-
-    sanitize: {
-        misc_undefined: [
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-
-    include_dirs: [
-        "frameworks/av/media/libstagefright",
-    ],
-
-    shared_libs: ["libmedia"],
-}
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
index 0dc7722..2c2d11d 100644
--- a/media/libstagefright/timedtext/TextDescriptions.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -445,51 +445,75 @@
                     | *(tmpData + 10) << 8 | *(tmpData + 11);
                 parcel->writeInt32(rgba);
 
+                // tx3g box contains class FontTableBox() which extends ftab box
+                // This information is part of the 3gpp Timed Text Format
+                // Specification#: 26.245 / Section: 5.16(Sample Description Format)
+                // https://www.3gpp.org/ftp/Specs/archive/26_series/26.245/
+
                 tmpData += 12;
                 remaining -= 12;
 
-                if (remaining < 2) {
+                if (remaining < 8) {
                     return OK;
                 }
 
-                size_t dataPos = parcel->dataPosition();
-
-                parcel->writeInt32(KEY_STRUCT_FONT_LIST);
-                uint16_t count = U16_AT(tmpData);
-                parcel->writeInt32(count);
-
-                tmpData += 2;
-                remaining -= 2;
-
-                for (int i = 0; i < count; i++) {
-                    if (remaining < 3) {
-                        // roll back
-                        parcel->setDataPosition(dataPos);
-                        return OK;
-                    }
-                    // font ID
-                    parcel->writeInt32(U16_AT(tmpData));
-
-                    // font name length
-                    parcel->writeInt32(*(tmpData + 2));
-
-                    size_t len = *(tmpData + 2);
-
-                    tmpData += 3;
-                    remaining -= 3;
-
-                    if (remaining < len) {
-                        // roll back
-                        parcel->setDataPosition(dataPos);
-                        return OK;
-                    }
-
-                    parcel->write(tmpData, len);
-                    tmpData += len;
-                    remaining -= len;
+                size_t subChunkSize = U32_AT(tmpData);
+                if(remaining < subChunkSize) {
+                    return OK;
                 }
 
-                // there is a "DisparityBox" after this according to the spec, but we ignore it
+                uint32_t subChunkType = U32_AT(tmpData + 4);
+
+                if (subChunkType == FOURCC('f', 't', 'a', 'b'))
+                {
+                    tmpData += 8;
+                    size_t subChunkRemaining = subChunkSize - 8;
+
+                    if(subChunkRemaining < 2) {
+                        return OK;
+                    }
+                    size_t dataPos = parcel->dataPosition();
+
+                    parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+                    uint16_t count = U16_AT(tmpData);
+                    parcel->writeInt32(count);
+
+                    tmpData += 2;
+                    subChunkRemaining -= 2;
+
+                    for (int i = 0; i < count; i++) {
+                        if (subChunkRemaining < 3) {
+                            // roll back
+                            parcel->setDataPosition(dataPos);
+                            return OK;
+                        }
+                        // font ID
+                        parcel->writeInt32(U16_AT(tmpData));
+
+                        // font name length
+                        size_t len = *(tmpData + 2);
+
+                        parcel->writeInt32(len);
+
+                        tmpData += 3;
+                        subChunkRemaining -=3;
+
+                        if (subChunkRemaining < len) {
+                            // roll back
+                            parcel->setDataPosition(dataPos);
+                            return OK;
+                        }
+
+                        parcel->writeByteArray(len, tmpData);
+                        tmpData += len;
+                        subChunkRemaining -= len;
+                    }
+                    tmpData += subChunkRemaining;
+                    remaining -= subChunkSize;
+                } else {
+                    tmpData += subChunkSize;
+                    remaining -= subChunkSize;
+                }
                 break;
             }
             default:
diff --git a/media/libstagefright/timedtext/TextDescriptions2.cpp b/media/libstagefright/timedtext/TextDescriptions2.cpp
deleted file mode 100644
index f48eacc..0000000
--- a/media/libstagefright/timedtext/TextDescriptions2.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include "TextDescriptions2.h"
-#include <media/stagefright/foundation/ByteUtils.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-TextDescriptions2::TextDescriptions2() {
-}
-
-status_t TextDescriptions2::getPlayerMessageOfDescriptions(
-        const uint8_t *data, ssize_t size,
-        uint32_t flags, int timeMs, PlayerMessage *playerMsg) {
-    if (flags & IN_BAND_TEXT_3GPP) {
-        if (flags & GLOBAL_DESCRIPTIONS) {
-            return extract3GPPGlobalDescriptions(data, size, playerMsg);
-        } else if (flags & LOCAL_DESCRIPTIONS) {
-            return extract3GPPLocalDescriptions(data, size, timeMs, playerMsg);
-        }
-    } else if (flags & OUT_OF_BAND_TEXT_SRT) {
-        if (flags & LOCAL_DESCRIPTIONS) {
-            return extractSRTLocalDescriptions(data, size, timeMs, playerMsg);
-        }
-    }
-
-    return ERROR_UNSUPPORTED;
-}
-
-// Parse the SRT text sample, and store the timing and text sample in a PlayerMessage.
-// The PlayerMessage will be sent to MediaPlayer2.java through event, and will be
-// parsed in TimedText.java.
-status_t TextDescriptions2::extractSRTLocalDescriptions(
-        const uint8_t *data, ssize_t size, int timeMs, PlayerMessage *playerMsg) {
-    playerMsg->add_values()->set_int32_value(KEY_LOCAL_SETTING);
-    playerMsg->add_values()->set_int32_value(KEY_START_TIME);
-    playerMsg->add_values()->set_int32_value(timeMs);
-
-    playerMsg->add_values()->set_int32_value(KEY_STRUCT_TEXT);
-    playerMsg->add_values()->set_bytes_value(data, size);
-
-    return OK;
-}
-
-// Extract the local 3GPP display descriptions. 3GPP local descriptions
-// are appended to the text sample if any.
-status_t TextDescriptions2::extract3GPPLocalDescriptions(
-        const uint8_t *data, ssize_t size,
-        int timeMs, PlayerMessage *playerMsg) {
-
-    playerMsg->add_values()->set_int32_value(KEY_LOCAL_SETTING);
-
-    // write start time to display this text sample
-    playerMsg->add_values()->set_int32_value(KEY_START_TIME);
-    playerMsg->add_values()->set_int32_value(timeMs);
-
-    if (size < 2) {
-        return OK;
-    }
-    ssize_t textLen = (*data) << 8 | (*(data + 1));
-
-    if (size < textLen + 2) {
-        return OK;
-    }
-
-    // write text sample length and text sample itself
-    playerMsg->add_values()->set_int32_value(KEY_STRUCT_TEXT);
-    playerMsg->add_values()->set_bytes_value(data + 2, textLen);
-
-    if (size > textLen + 2) {
-        data += (textLen + 2);
-        size -= (textLen + 2);
-    } else {
-        return OK;
-    }
-
-    while (size >= 8) {
-        const uint8_t *tmpData = data;
-        ssize_t chunkSize = U32_AT(tmpData);      // size includes size and type
-        uint32_t chunkType = U32_AT(tmpData + 4);
-
-        if (chunkSize <= 8 || chunkSize > size) {
-            return OK;
-        }
-
-        size_t remaining = chunkSize - 8;
-
-        tmpData += 8;
-
-        switch(chunkType) {
-            // 'tbox' box to indicate the position of the text with values
-            // of top, left, bottom and right
-            case FOURCC('t', 'b', 'o', 'x'):
-            {
-                if (remaining < 8) {
-                    return OK;
-                }
-                playerMsg->add_values()->set_int32_value(KEY_STRUCT_TEXT_POS);
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 2));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 4));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 6));
-
-                tmpData += 8;
-                remaining -= 8;
-                break;
-            }
-            default:
-            {
-                break;
-            }
-        }
-
-        data += chunkSize;
-        size -= chunkSize;
-    }
-
-    return OK;
-}
-
-// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a PlayerMessage
-status_t TextDescriptions2::extract3GPPGlobalDescriptions(
-        const uint8_t *data, ssize_t size, PlayerMessage *playerMsg) {
-
-    playerMsg->add_values()->set_int32_value(KEY_GLOBAL_SETTING);
-
-    while (size >= 8) {
-        ssize_t chunkSize = U32_AT(data);
-        uint32_t chunkType = U32_AT(data + 4);
-        const uint8_t *tmpData = data;
-        tmpData += 8;
-        size_t remaining = size - 8;
-
-        if (size < chunkSize) {
-            return OK;
-        }
-        switch(chunkType) {
-            case FOURCC('t', 'x', '3', 'g'):
-            {
-                if (remaining < 18) {
-                    return OK;
-                }
-                // Skip DISPLAY_FLAGS, STRUCT_JUSTIFICATION, and BACKGROUND_COLOR_RGBA
-                tmpData += 18;
-                remaining -= 18;
-
-                if (remaining < 8) {
-                    return OK;
-                }
-                playerMsg->add_values()->set_int32_value(KEY_STRUCT_TEXT_POS);
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 2));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 4));
-                playerMsg->add_values()->set_int32_value(U16_AT(tmpData + 6));
-
-                tmpData += 8;
-                remaining -= 18;
-                // Ignore remaining data.
-                break;
-            }
-            default:
-            {
-                break;
-            }
-        }
-
-        data += chunkSize;
-        size -= chunkSize;
-    }
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/timedtext/TextDescriptions2.h b/media/libstagefright/timedtext/TextDescriptions2.h
deleted file mode 100644
index 7c7d2d0..0000000
--- a/media/libstagefright/timedtext/TextDescriptions2.h
+++ /dev/null
@@ -1,88 +0,0 @@
- /*
- * Copyright (C) 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 TEXT_DESCRIPTIONS2_H_
-
-#define TEXT_DESCRIPTIONS2_H_
-
-#include <binder/Parcel.h>
-#include <media/stagefright/foundation/ABase.h>
-
-#include "mediaplayer2.pb.h"
-
-using android::media::MediaPlayer2Proto::PlayerMessage;
-
-namespace android {
-
-class TextDescriptions2 {
-public:
-    enum {
-        IN_BAND_TEXT_3GPP             = 0x01,
-        OUT_OF_BAND_TEXT_SRT          = 0x02,
-
-        GLOBAL_DESCRIPTIONS           = 0x100,
-        LOCAL_DESCRIPTIONS            = 0x200,
-    };
-
-    static status_t getPlayerMessageOfDescriptions(
-            const uint8_t *data, ssize_t size,
-            uint32_t flags, int timeMs, PlayerMessage *playerMsg);
-private:
-    TextDescriptions2();
-
-    enum {
-        // These keys must be in sync with the keys in TimedText.java
-        KEY_DISPLAY_FLAGS                 = 1, // int
-        KEY_STYLE_FLAGS                   = 2, // int
-        KEY_BACKGROUND_COLOR_RGBA         = 3, // int
-        KEY_HIGHLIGHT_COLOR_RGBA          = 4, // int
-        KEY_SCROLL_DELAY                  = 5, // int
-        KEY_WRAP_TEXT                     = 6, // int
-        KEY_START_TIME                    = 7, // int
-        KEY_STRUCT_BLINKING_TEXT_LIST     = 8, // List<CharPos>
-        KEY_STRUCT_FONT_LIST              = 9, // List<Font>
-        KEY_STRUCT_HIGHLIGHT_LIST         = 10, // List<CharPos>
-        KEY_STRUCT_HYPER_TEXT_LIST        = 11, // List<HyperText>
-        KEY_STRUCT_KARAOKE_LIST           = 12, // List<Karaoke>
-        KEY_STRUCT_STYLE_LIST             = 13, // List<Style>
-        KEY_STRUCT_TEXT_POS               = 14, // TextPos
-        KEY_STRUCT_JUSTIFICATION          = 15, // Justification
-        KEY_STRUCT_TEXT                   = 16, // Text
-
-        KEY_GLOBAL_SETTING                = 101,
-        KEY_LOCAL_SETTING                 = 102,
-        KEY_START_CHAR                    = 103,
-        KEY_END_CHAR                      = 104,
-        KEY_FONT_ID                       = 105,
-        KEY_FONT_SIZE                     = 106,
-        KEY_TEXT_COLOR_RGBA               = 107,
-    };
-
-    static status_t extractSRTLocalDescriptions(
-            const uint8_t *data, ssize_t size,
-            int timeMs, PlayerMessage *playerMsg);
-    static status_t extract3GPPGlobalDescriptions(
-            const uint8_t *data, ssize_t size,
-            PlayerMessage *playerMsg);
-    static status_t extract3GPPLocalDescriptions(
-            const uint8_t *data, ssize_t size,
-            int timeMs, PlayerMessage *playerMsg);
-
-    DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions2);
-};
-
-}  // namespace android
-#endif  // TEXT_DESCRIPTIONS2_H_
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 64ecc2d..2cebe8f 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -27,12 +27,14 @@
     include_dirs: ["frameworks/av/include"],
 
     shared_libs: [
+        "libdatasource",
         "libstagefright_foundation",
         "libutils",
         "liblog",
     ],
 
     header_libs: [
+        "libmedia_headers",
         "media_ndk_headers",
     ],
 }
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 631a2ab..59ce8db 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -321,6 +321,7 @@
 status_t WebmFrameMediaSourceThread::pause() {
     if (mStarted) {
         mPaused = true;
+        mResumed = false;
     }
     return OK;
 }
diff --git a/media/libstagefright/webm/WebmFrameThread.h b/media/libstagefright/webm/WebmFrameThread.h
index 1ddaf9a..5aa6feb 100644
--- a/media/libstagefright/webm/WebmFrameThread.h
+++ b/media/libstagefright/webm/WebmFrameThread.h
@@ -20,8 +20,8 @@
 #include "WebmFrame.h"
 #include "LinkedBlockingQueue.h"
 
-#include <media/MediaSource.h>
-#include <media/stagefright/FileSource.h>
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaSource.h>
 
 #include <utils/List.h>
 #include <utils/Errors.h>
diff --git a/media/libstagefright/webm/WebmWriter.h b/media/libstagefright/webm/WebmWriter.h
index ffe4c79..ed5bc4c 100644
--- a/media/libstagefright/webm/WebmWriter.h
+++ b/media/libstagefright/webm/WebmWriter.h
@@ -21,7 +21,7 @@
 #include "WebmFrameThread.h"
 #include "LinkedBlockingQueue.h"
 
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaWriter.h>
 
 #include <utils/Errors.h>
diff --git a/media/libstagefright/webm/tests/Android.bp b/media/libstagefright/webm/tests/Android.bp
new file mode 100644
index 0000000..5183a49
--- /dev/null
+++ b/media/libstagefright/webm/tests/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "WebmFrameThreadUnitTest",
+    gtest: true,
+
+    srcs: [
+        "WebmFrameThreadUnitTest.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libstagefright",
+    ],
+
+    static_libs: [
+        "libdatasource",
+        "libstagefright",
+        "libstagefright_webm",
+        "libstagefright_foundation",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libstagefright/webm/tests/README.md b/media/libstagefright/webm/tests/README.md
new file mode 100644
index 0000000..2e74f34
--- /dev/null
+++ b/media/libstagefright/webm/tests/README.md
@@ -0,0 +1,26 @@
+## Media Testing ##
+---
+#### Webm Writer Utility Tests :
+The Webm Writer Utility Test Suite validates the APIs being used by the WebmWriter.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/webm/tests/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+#### WebmFrameThread
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+```
+adb shell /data/local/tmp/WebmFrameThreadUnitTest
+```
diff --git a/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
new file mode 100644
index 0000000..89cd2ca
--- /dev/null
+++ b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WebmFrameThreadUnitTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/OpusHeader.h>
+
+#include "webm/EbmlUtil.h"
+#include "webm/WebmConstants.h"
+#include "webm/WebmFrameThread.h"
+
+using namespace android;
+using namespace webm;
+
+static constexpr int32_t kVideoIdx = 0;
+static constexpr int32_t kAudioIdx = 1;
+static constexpr int32_t kMaxStreamCount = 2;
+
+static constexpr int32_t kCsdSize = 32;
+static constexpr int32_t kFrameSize = 128;
+
+static constexpr int32_t kMaxLoopCount = 20;
+static constexpr int32_t kNumFramesToWrite = 32;
+static constexpr int32_t kSyncFrameInterval = 10;
+static constexpr uint64_t kDefaultTimeCodeScaleUs = 1000000; /* 1sec */
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/webmFrameThreadOutput.webm"
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+    const char *mime;
+    int32_t firstParam;
+    int32_t secondParam;
+    bool isAudio;
+} kInputData[] = {
+        {MEDIA_MIMETYPE_AUDIO_OPUS, 48000, 6, true},
+        {MEDIA_MIMETYPE_AUDIO_VORBIS, 44100, 1, true},
+        {MEDIA_MIMETYPE_VIDEO_VP9, 176, 144, false},
+        {MEDIA_MIMETYPE_VIDEO_VP8, 1920, 1080, false},
+};
+
+class WebmFrameThreadUnitTest : public ::testing::TestWithParam<std::pair<int32_t, int32_t>> {
+  public:
+    WebmFrameThreadUnitTest()
+        : mSinkThread(nullptr), mAudioThread(nullptr), mVideoThread(nullptr), mSource{} {}
+
+    ~WebmFrameThreadUnitTest() {
+        if (mSinkThread) mSinkThread.clear();
+        if (mAudioThread) mAudioThread.clear();
+        if (mVideoThread) mVideoThread.clear();
+    }
+
+    virtual void SetUp() override {
+        mSegmentDataStart = 0;
+        mFd = open(OUTPUT_FILE_NAME, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+        ASSERT_GE(mFd, 0) << "Failed to open output file " << OUTPUT_FILE_NAME;
+    }
+
+    virtual void TearDown() override {
+        if (mFd >= 0) close(mFd);
+        for (int32_t idx = 0; idx < kMaxStreamCount; idx++) {
+            if (mSource[idx] != nullptr) {
+                mSource[idx].clear();
+            }
+        }
+        mVSink.clear();
+        mASink.clear();
+        mCuePoints.clear();
+    }
+
+    void addTrack(bool isAudio, int32_t index);
+    void writeFileData(int32_t inputFrameId, int32_t range);
+
+    void createWebmThreads(std::initializer_list<int32_t> indexList);
+    void startWebmFrameThreads();
+    void stopWebmFrameThreads();
+
+    int32_t mFd;
+    uint64_t mSegmentDataStart;
+
+    sp<WebmFrameSinkThread> mSinkThread;
+    sp<WebmFrameSourceThread> mAudioThread;
+    sp<WebmFrameSourceThread> mVideoThread;
+
+    List<sp<WebmElement>> mCuePoints;
+    sp<MediaAdapter> mSource[kMaxStreamCount];
+    LinkedBlockingQueue<const sp<WebmFrame>> mVSink;
+    LinkedBlockingQueue<const sp<WebmFrame>> mASink;
+};
+
+void writeAudioHeaderData(const sp<AMessage> &format, const char *mimeType) {
+    if (strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_OPUS, strlen(MEDIA_MIMETYPE_AUDIO_OPUS) + 1) &&
+        strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_VORBIS,
+                    strlen(MEDIA_MIMETYPE_AUDIO_VORBIS) + 1)) {
+        ASSERT_TRUE(false) << "Unsupported mime type";
+    }
+
+    // Dummy CSD buffers for Opus and Vorbis
+    char csdBuffer[kCsdSize];
+    memset(csdBuffer, 0xFF, sizeof(csdBuffer));
+
+    sp<ABuffer> csdBuffer0 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer0.get(), nullptr) << "Unable to allocate buffer for CSD0 data";
+    ASSERT_NE(csdBuffer0->base(), nullptr) << "ABuffer base is null for CSD0";
+
+    sp<ABuffer> csdBuffer1 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer1.get(), nullptr) << "Unable to allocate buffer for CSD1 data";
+    ASSERT_NE(csdBuffer1->base(), nullptr) << "ABuffer base is null for CSD1";
+
+    sp<ABuffer> csdBuffer2 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+    ASSERT_NE(csdBuffer2.get(), nullptr) << "Unable to allocate buffer for CSD2 data";
+    ASSERT_NE(csdBuffer2->base(), nullptr) << "ABuffer base is null for CSD2";
+
+    format->setBuffer("csd-0", csdBuffer0);
+    format->setBuffer("csd-1", csdBuffer1);
+    format->setBuffer("csd-2", csdBuffer2);
+}
+
+void WebmFrameThreadUnitTest::addTrack(bool isAudio, int32_t index) {
+    ASSERT_LT(index, sizeof(kInputData) / sizeof(kInputData[0]))
+            << "Invalid index for loopup table";
+
+    sp<AMessage> format = new AMessage;
+    format->setString("mime", kInputData[index].mime);
+    if (!isAudio) {
+        format->setInt32("width", kInputData[index].firstParam);
+        format->setInt32("height", kInputData[index].secondParam);
+    } else {
+        format->setInt32("sample-rate", kInputData[index].firstParam);
+        format->setInt32("channel-count", kInputData[index].secondParam);
+        ASSERT_NO_FATAL_FAILURE(writeAudioHeaderData(format, kInputData[index].mime));
+    }
+
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
+
+    if (!isAudio) {
+        mSource[kVideoIdx] = new MediaAdapter(trackMeta);
+        ASSERT_NE(mSource[kVideoIdx], nullptr) << "Unable to create source";
+    } else {
+        mSource[kAudioIdx] = new MediaAdapter(trackMeta);
+        ASSERT_NE(mSource[kAudioIdx], nullptr) << "Unable to create source";
+    }
+}
+
+void WebmFrameThreadUnitTest::createWebmThreads(std::initializer_list<int32_t> indexList) {
+    mSinkThread = new WebmFrameSinkThread(mFd, mSegmentDataStart, mVSink, mASink, mCuePoints);
+    ASSERT_NE(mSinkThread, nullptr) << "Failed to create Sink Thread";
+
+    bool isAudio;
+    // MultiTrack input
+    for (int32_t index : indexList) {
+        isAudio = kInputData[index].isAudio;
+        ASSERT_NO_FATAL_FAILURE(addTrack(isAudio, index));
+        if (!isAudio) {
+            mVideoThread = new WebmFrameMediaSourceThread(mSource[kVideoIdx], kVideoType, mVSink,
+                                                          kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+        } else {
+            mAudioThread = new WebmFrameMediaSourceThread(mSource[kAudioIdx], kAudioType, mASink,
+                                                          kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+        }
+    }
+    // To handle single track file
+    if (!mVideoThread) {
+        mVideoThread = new WebmFrameEmptySourceThread(kVideoType, mVSink);
+    } else if (!mAudioThread) {
+        mAudioThread = new WebmFrameEmptySourceThread(kAudioType, mASink);
+    }
+    ASSERT_NE(mVideoThread, nullptr) << "Failed to create Video Thread";
+    ASSERT_NE(mAudioThread, nullptr) << "Failed to create Audio Thread";
+}
+
+void WebmFrameThreadUnitTest::startWebmFrameThreads() {
+    status_t status = mAudioThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Audio Thread";
+    status = mVideoThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Video Thread";
+    status = mSinkThread->start();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Sink Thread";
+}
+
+void WebmFrameThreadUnitTest::stopWebmFrameThreads() {
+    status_t status = mAudioThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Audio Thread";
+    status = mVideoThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Video Thread";
+    status = mSinkThread->stop();
+    ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Sink Thread";
+}
+
+// Write dummy data to a file
+void WebmFrameThreadUnitTest::writeFileData(int32_t inputFrameId, int32_t range) {
+    char data[kFrameSize];
+    memset(data, 0xFF, sizeof(data));
+    int32_t status = OK;
+    do {
+        // Queue frames for both A/V tracks
+        for (int32_t idx = kVideoIdx; idx < kMaxStreamCount; idx++) {
+            sp<ABuffer> buffer = new ABuffer((void *)data, kFrameSize);
+            ASSERT_NE(buffer.get(), nullptr) << "ABuffer returned nullptr";
+
+            // Released in MediaAdapter::signalBufferReturned().
+            MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+            ASSERT_NE(mediaBuffer, nullptr) << "MediaBuffer returned nullptr";
+
+            mediaBuffer->add_ref();
+            mediaBuffer->set_range(buffer->offset(), buffer->size());
+
+            MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+            sampleMetaData.setInt64(kKeyTime, inputFrameId * kDefaultTimeCodeScaleUs);
+
+            // For audio codecs, treat all frame as sync frame
+            if ((idx == kAudioIdx) || (inputFrameId % kSyncFrameInterval == 0)) {
+                sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+            }
+
+            // This pushBuffer will wait until the mediaBuffer is consumed.
+            if (mSource[idx] != nullptr) {
+                status = mSource[idx]->pushBuffer(mediaBuffer);
+            }
+            ASSERT_EQ(status, OK);
+        }
+        inputFrameId++;
+    } while (inputFrameId < range);
+}
+
+TEST_P(WebmFrameThreadUnitTest, WriteTest) {
+    int32_t index1 = GetParam().first;
+    int32_t index2 = GetParam().second;
+    ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+    ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+    ASSERT_NO_FATAL_FAILURE(writeFileData(0, kNumFramesToWrite));
+
+    if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+    if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+
+    ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+TEST_P(WebmFrameThreadUnitTest, PauseTest) {
+    int32_t index1 = GetParam().first;
+    int32_t index2 = GetParam().second;
+    ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+    ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+    int32_t offset = 0;
+    ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+    offset += kNumFramesToWrite;
+
+    for (int idx = 0; idx < kMaxLoopCount; idx++) {
+        // pause the threads
+        status_t status = mAudioThread->pause();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Audio Thread";
+        status = mVideoThread->pause();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Video Thread";
+
+        // Under pause state, no write should happen
+        ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+        offset += kNumFramesToWrite;
+
+        status = mAudioThread->resume();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Audio Thread";
+        status = mVideoThread->resume();
+        ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Video Thread";
+
+        ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+        offset += kNumFramesToWrite;
+    }
+
+    if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+    if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+    ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+INSTANTIATE_TEST_SUITE_P(WebmFrameThreadUnitTestAll, WebmFrameThreadUnitTest,
+                         ::testing::Values(std::make_pair(0, 1), std::make_pair(0, 2),
+                                           std::make_pair(0, 3), std::make_pair(1, 0),
+                                           std::make_pair(1, 2), std::make_pair(1, 3),
+                                           std::make_pair(2, 3)));
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGV("Test result = %d\n", status);
+    return status;
+}
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index 38de831..7ed0e88 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -10,6 +10,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
 
     srcs: [
         "MediaCodecsXmlParser.cpp",
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 9783e9b..a232150 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -21,6 +21,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/properties.h>
 #include <utils/Log.h>
 
 #include <media/stagefright/MediaErrors.h>
@@ -38,8 +39,6 @@
 
 namespace android {
 
-using MCXP = MediaCodecsXmlParser;
-
 namespace {
 
 bool fileExists(const std::string &path) {
@@ -118,8 +117,8 @@
     }
 }
 
-MCXP::StringSet parseCommaSeparatedStringSet(const char *s) {
-    MCXP::StringSet result;
+MediaCodecsXmlParser::StringSet parseCommaSeparatedStringSet(const char *s) {
+    MediaCodecsXmlParser::StringSet result;
     for (const char *ptr = s ? : ""; *ptr; ) {
         const char *end = strchrnul(ptr, ',');
         if (ptr != end) { // skip empty values
@@ -136,6 +135,23 @@
 
 }  // unnamed namespace
 
+std::vector<std::string> MediaCodecsXmlParser::getDefaultXmlNames() {
+    static constexpr char const* prefixes[] = {
+            "media_codecs",
+            "media_codecs_performance"
+        };
+    static std::vector<std::string> variants = {
+            android::base::GetProperty("ro.media.xml_variant.codecs", ""),
+            android::base::GetProperty("ro.media.xml_variant.codecs_performance", "")
+        };
+    static std::vector<std::string> names = {
+            prefixes[0] + variants[0] + ".xml",
+            prefixes[1] + variants[1] + ".xml"
+        };
+    return names;
+}
+
+
 struct MediaCodecsXmlParser::Impl {
     // status + error message
     struct Result {
@@ -1269,7 +1285,7 @@
 void MediaCodecsXmlParser::Impl::State::addDetail(
         const std::string &key, const std::string &value) {
     CHECK(inType());
-    ALOGI("limit: %s = %s", key.c_str(), value.c_str());
+    ALOGV("limit: %s = %s", key.c_str(), value.c_str());
     const StringSet &variants = mVariantsStack.back();
     if (variants.empty()) {
         type()[key] = value;
diff --git a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
index b666de4..e224452 100644
--- a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
+++ b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
@@ -33,13 +33,17 @@
 class MediaCodecsXmlParser {
 public:
 
-    // Treblized media codec list will be located in /odm/etc or /vendor/etc.
+    // Treblized media codec list will be located in /product/etc, /odm/etc or
+    // /vendor/etc.
     static std::vector<std::string> getDefaultSearchDirs() {
-            return { "/odm/etc", "/vendor/etc", "/etc" };
+        return { "/product/etc",
+                 "/odm/etc",
+                 "/vendor/etc",
+                 "/system/etc" };
     }
-    static std::vector<std::string> getDefaultXmlNames() {
-            return { "media_codecs.xml", "media_codecs_performance.xml" };
-    }
+
+    static std::vector<std::string> getDefaultXmlNames();
+
     static constexpr char const* defaultProfilingResultsXmlPath =
             "/data/misc/media/media_codecs_profiling_results.xml";
 
diff --git a/media/libstagefright/xmlparser/vts/Android.bp b/media/libstagefright/xmlparser/vts/Android.bp
index 3f93e9e..132ce82 100644
--- a/media/libstagefright/xmlparser/vts/Android.bp
+++ b/media/libstagefright/xmlparser/vts/Android.bp
@@ -30,4 +30,12 @@
         "-Wall",
         "-Werror",
     ],
+    data: [
+        ":media_codecs",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts"
+    ],
+    test_config: "vts_mediaCodecs_validate_test.xml",
 }
diff --git a/media/libstagefright/xmlparser/vts/vts_mediaCodecs_validate_test.xml b/media/libstagefright/xmlparser/vts/vts_mediaCodecs_validate_test.xml
new file mode 100644
index 0000000..fbb7cc6
--- /dev/null
+++ b/media/libstagefright/xmlparser/vts/vts_mediaCodecs_validate_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs vts_mediaCodecs_validate_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="media_codecs.xsd->/data/local/tmp/media_codecs.xsd" />
+        <option name="push" value="vts_mediaCodecs_validate_test->/data/local/tmp/vts_mediaCodecs_validate_test" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_mediaCodecs_validate_test" />
+    </test>
+</configuration>
diff --git a/media/libwatchdog/Android.bp b/media/libwatchdog/Android.bp
index 2bdf172..1a87824 100644
--- a/media/libwatchdog/Android.bp
+++ b/media/libwatchdog/Android.bp
@@ -19,10 +19,8 @@
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "liblog",
-    ],
-    static_libs: [
         "libbase",
+        "liblog",
     ],
     target: {
         windows: {
@@ -32,4 +30,6 @@
             enabled: false,
         },
     },
+    apex_available: ["com.android.media"],
+    min_sdk_version: "29",
 }
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index a968890..afca7c4 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -15,13 +15,14 @@
     srcs: ["main_mediaserver.cpp"],
 
     shared_libs: [
-        "libresourcemanagerservice",
+        "android.hardware.media.omx@1.0",
+        "libandroidicu",
+        "libbinder",
+        "libhidlbase",
         "liblog",
         "libmediaplayerservice",
+        "libresourcemanagerservice",
         "libutils",
-        "libbinder",
-        "libandroidicu",
-        "android.hardware.media.omx@1.0",
     ],
 
     static_libs: [
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 7b22b05..316732b 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -22,6 +22,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
 #include <utils/Log.h>
 #include "RegisterExtensions.h"
 
@@ -42,6 +43,8 @@
     MediaPlayerService::instantiate();
     ResourceManagerService::instantiate();
     registerExtensions();
+    ::android::hardware::configureRpcThreadpool(16, false);
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
+    ::android::hardware::joinRpcThreadpool();
 }
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software.xml
index 5196336..f23ed44 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -2,7 +2,7 @@
     <hal>
         <name>android.hardware.media.c2</name>
         <transport>hwbinder</transport>
-        <version>1.0</version>
+        <version>1.1</version>
         <interface>
             <name>IComponentStore</name>
             <instance>software</instance>
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index f6c325c..05373c9 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -1,6 +1,9 @@
+on property:init.svc.media=*
+    setprop init.svc.mediadrm ${init.svc.media}
+
 service media /system/bin/mediaserver
     class main
     user media
     group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mtp/IMtpHandle.h b/media/mtp/IMtpHandle.h
index fd14b18..0435e82 100644
--- a/media/mtp/IMtpHandle.h
+++ b/media/mtp/IMtpHandle.h
@@ -16,7 +16,7 @@
 #ifndef _IMTP_HANDLE_H
 #define _IMTP_HANDLE_H
 
-#include <linux/usb/f_mtp.h>
+#include "f_mtp.h"
 
 namespace android {
 
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index dd69496..8677b90 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -42,6 +42,7 @@
 #include "MtpServer.h"
 #include "MtpStorage.h"
 #include "MtpStringBuffer.h"
+#include "android-base/strings.h"
 
 namespace android {
 static const int SN_EVENT_LOG_ID = 0x534e4554;
@@ -83,8 +84,8 @@
 //    MTP_OPERATION_SET_OBJECT_PROP_LIST,
 //    MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
 //    MTP_OPERATION_SEND_OBJECT_PROP_LIST,
-    MTP_OPERATION_GET_OBJECT_REFERENCES,
-    MTP_OPERATION_SET_OBJECT_REFERENCES,
+//    MTP_OPERATION_GET_OBJECT_REFERENCES,
+//    MTP_OPERATION_SET_OBJECT_REFERENCES,
 //    MTP_OPERATION_SKIP,
     // Android extension for direct file IO
     MTP_OPERATION_GET_PARTIAL_OBJECT_64,
@@ -956,6 +957,11 @@
     if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER;     // date modified
     // keywords follow
 
+    int type = storage->getType();
+    if (type == MTP_STORAGE_REMOVABLE_RAM) {
+        std::string str = android::base::Trim((const char*)name);
+        name.set(str.c_str());
+    }
     ALOGV("name: %s format: 0x%04X (%s)\n", (const char*)name, format,
           MtpDebug::getFormatCodeName(format));
     time_t modifiedTime;
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 1f8799f..8cc9a9a 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -34,8 +34,11 @@
 
 class IMtpDatabase;
 class MtpStorage;
+class MtpMockServer;
 
 class MtpServer {
+    // libFuzzer testing
+    friend class MtpMockServer;
 
 private:
     IMtpDatabase*       mDatabase;
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
index cd379bf..d8d425b 100644
--- a/media/mtp/MtpStringBuffer.cpp
+++ b/media/mtp/MtpStringBuffer.cpp
@@ -26,14 +26,31 @@
 
 namespace {
 
-std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> gConvert;
+const char * utf16_cerror = "__CONVERSION_ERROR__";
+const char16_t * utf8_cerror = u"__CONVERSION_ERROR__";
+
+std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> gConvert(utf16_cerror, utf8_cerror);
 
 static std::string utf16ToUtf8(std::u16string input_str) {
-    return gConvert.to_bytes(input_str);
+    std::string conversion = gConvert.to_bytes(input_str);
+
+    if (conversion == utf16_cerror) {
+        ALOGE("Unable to convert UTF-16 string to UTF-8");
+        return "";
+    } else {
+        return conversion;
+    }
 }
 
 static std::u16string utf8ToUtf16(std::string input_str) {
-    return gConvert.from_bytes(input_str);
+    std::u16string conversion = gConvert.from_bytes(input_str);
+
+    if (conversion == utf8_cerror) {
+        ALOGE("Unable to convert UTF-8 string to UTF-16");
+        return u"";
+    } else {
+        return conversion;
+    }
 }
 
 } // namespace
diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp
index 8564576..84a20d3 100644
--- a/media/mtp/MtpUtils.cpp
+++ b/media/mtp/MtpUtils.cpp
@@ -150,6 +150,7 @@
             ret += copyFile(oldFile.c_str(), newFile.c_str());
         }
     }
+    closedir(dir);
     return ret;
 }
 
diff --git a/media/mtp/PosixAsyncIO.cpp b/media/mtp/PosixAsyncIO.cpp
index 72c07cc..8205e3b 100644
--- a/media/mtp/PosixAsyncIO.cpp
+++ b/media/mtp/PosixAsyncIO.cpp
@@ -47,10 +47,10 @@
         CHECK(aiocbp->queued);
         int ret;
         if (aiocbp->read) {
-            ret = TEMP_FAILURE_RETRY(pread(aiocbp->aio_fildes,
+            ret = TEMP_FAILURE_RETRY(pread64(aiocbp->aio_fildes,
                     aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset));
         } else {
-            ret = TEMP_FAILURE_RETRY(pwrite(aiocbp->aio_fildes,
+            ret = TEMP_FAILURE_RETRY(pwrite64(aiocbp->aio_fildes,
                aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset));
         }
         {
@@ -139,7 +139,7 @@
     return 0;
 }
 
-void aio_prepare(struct aiocb *aiocbp, void* buf, size_t count, off_t offset) {
+void aio_prepare(struct aiocb *aiocbp, void* buf, size_t count, off64_t offset) {
     aiocbp->aio_buf = buf;
     aiocbp->aio_offset = offset;
     aiocbp->aio_nbytes = count;
diff --git a/media/mtp/PosixAsyncIO.h b/media/mtp/PosixAsyncIO.h
index 2bb5735..2bcae4c 100644
--- a/media/mtp/PosixAsyncIO.h
+++ b/media/mtp/PosixAsyncIO.h
@@ -32,7 +32,7 @@
     int aio_fildes;
     void *aio_buf;
 
-    off_t aio_offset;
+    off64_t aio_offset;
     size_t aio_nbytes;
 
     // Used internally
@@ -61,7 +61,7 @@
 ssize_t aio_return(struct aiocb *);
 
 // Helper method for setting aiocb members
-void aio_prepare(struct aiocb *, void*, size_t, off_t);
+void aio_prepare(struct aiocb *, void*, size_t, off64_t);
 
 #endif // POSIXASYNCIO_H
 
diff --git a/media/mtp/f_mtp.h b/media/mtp/f_mtp.h
new file mode 100644
index 0000000..22ec771
--- /dev/null
+++ b/media/mtp/f_mtp.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_USB_F_MTP_H
+#define _UAPI_LINUX_USB_F_MTP_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct mtp_file_range {
+  int fd;
+  loff_t offset;
+  int64_t length;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+  uint16_t command;
+  uint32_t transaction_id;
+};
+struct mtp_event {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+  size_t length;
+  void * data;
+};
+#define MTP_SEND_FILE _IOW('M', 0, struct mtp_file_range)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define MTP_RECEIVE_FILE _IOW('M', 1, struct mtp_file_range)
+#define MTP_SEND_EVENT _IOW('M', 3, struct mtp_event)
+#define MTP_SEND_FILE_WITH_HEADER _IOW('M', 4, struct mtp_file_range)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 9c7a630..43989bb 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -35,6 +35,14 @@
 cc_library_headers {
     name: "media_ndk_headers",
     vendor_available: true,
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
     export_include_dirs: ["include"]
 }
 
@@ -42,6 +50,7 @@
     name: "libmediandk",
 
     srcs: [
+        "NdkJavaVMHelper.cpp",
         "NdkMediaCodec.cpp",
         "NdkMediaCrypto.cpp",
         "NdkMediaDataSource.cpp",
@@ -54,7 +63,6 @@
     ],
 
     include_dirs: [
-        "bionic/libc/private",
         "frameworks/base/core/jni",
         "frameworks/native/include/media/openmax",
         "system/media/camera/include",
@@ -70,28 +78,32 @@
         "libgrallocusage",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+        "libmediametrics_headers",
+    ],
+
     shared_libs: [
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hidl.token@1.0-utils",
         "libandroid_runtime_lazy",
         "libbase",
-        "libbinder",
+        "libdatasource",
         "libmedia",
+        "libmediadrm",
         "libmedia_omx",
         "libmedia_jni_utils",
-        "libmediadrm",
         "libstagefright",
         "libstagefright_foundation",
         "liblog",
         "libutils",
         "libcutils",
         "libnativewindow",
-        "libbinder",
         "libhidlbase",
         "libgui",
         "libui",
-        "libmedia2_jni_core",
         "libmediandk_utils",
+        "libnativehelper",
     ],
 
     export_include_dirs: ["include"],
@@ -142,6 +154,10 @@
         "-Wall",
     ],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
     ],
 
@@ -168,6 +184,10 @@
         "libcutils",
         "android.hardware.graphics.bufferqueue@1.0",
     ],
+    header_libs: [
+        "libstagefright_foundation_headers",
+    ],
+
     cflags: [
         "-D__ANDROID_VNDK__",
     ],
diff --git a/media/ndk/NdkJavaVMHelper.cpp b/media/ndk/NdkJavaVMHelper.cpp
new file mode 100644
index 0000000..a77016c
--- /dev/null
+++ b/media/ndk/NdkJavaVMHelper.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 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_TAG "NdkJavaVMHelper"
+
+#include "NdkJavaVMHelperPriv.h"
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+JNIEnv *NdkJavaVMHelper::getJNIEnv() {
+    JNIEnv *env;
+    jsize nVMs;
+    JavaVM *vm;
+
+    int status = JNI_GetCreatedJavaVMs(&vm, 1, &nVMs);
+    if (status != JNI_OK || nVMs == 0 || vm == NULL) {
+        ALOGE("Failed to get JVM instance");
+        return NULL;
+    } else if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("Failed to get JNIEnv for JavaVM: %p", vm);
+        return NULL;
+    }
+
+    return env;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/media/ndk/NdkJavaVMHelperPriv.h b/media/ndk/NdkJavaVMHelperPriv.h
new file mode 100644
index 0000000..49f087e
--- /dev/null
+++ b/media/ndk/NdkJavaVMHelperPriv.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 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 NDK_JAVA_VM_HELPER_PRIV_H_
+
+#define NDK_JAVA_VM_HELPER_PRIV_H_
+
+#include "jni.h"
+
+namespace android {
+
+struct NdkJavaVMHelper {
+    static JNIEnv *getJNIEnv();
+};
+
+}  // namespace android
+
+#endif  // NDK_JAVA_VM_HELPER_PRIV_H_
\ No newline at end of file
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index e041533..af21a99 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -250,8 +250,8 @@
                          ALOGE("CB_ERROR: err is expected.");
                          break;
                      }
-                     if (!msg->findInt32("action", &actionCode)) {
-                         ALOGE("CB_ERROR: action is expected.");
+                     if (!msg->findInt32("actionCode", &actionCode)) {
+                         ALOGE("CB_ERROR: actionCode is expected.");
                          break;
                      }
                      msg->findString("detail", &detail);
diff --git a/media/ndk/NdkMediaCrypto.cpp b/media/ndk/NdkMediaCrypto.cpp
index ce2c660..741e58b 100644
--- a/media/ndk/NdkMediaCrypto.cpp
+++ b/media/ndk/NdkMediaCrypto.cpp
@@ -26,9 +26,8 @@
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
-#include <binder/IServiceManager.h>
-#include <media/ICrypto.h>
-#include <media/IMediaDrmService.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/ICrypto.h>
 #include <android_util_Binder.h>
 
 #include <jni.h>
@@ -36,19 +35,7 @@
 using namespace android;
 
 static sp<ICrypto> makeCrypto() {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.drm"));
-
-    sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
-    if (service == NULL) {
-        return NULL;
-    }
-
-    sp<ICrypto> crypto = service->makeCrypto();
-    if (crypto == NULL || (crypto->initCheck() != OK && crypto->initCheck() != NO_INIT)) {
-        return NULL;
-    }
-    return crypto;
+    return DrmUtils::MakeCrypto();
 }
 
 struct AMediaCrypto {
diff --git a/media/ndk/NdkMediaCryptoPriv.h b/media/ndk/NdkMediaCryptoPriv.h
index 14ea928..8664d95 100644
--- a/media/ndk/NdkMediaCryptoPriv.h
+++ b/media/ndk/NdkMediaCryptoPriv.h
@@ -30,7 +30,7 @@
 
 #include <sys/types.h>
 #include <utils/StrongPointer.h>
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 
 using namespace android;
 
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 7979c2f..3e6d7d6 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "NdkMediaDataSource"
 
+#include "NdkJavaVMHelperPriv.h"
 #include "NdkMediaDataSourcePriv.h"
 
 #include <inttypes.h>
@@ -26,18 +27,16 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_util_Binder.h>
 #include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/StrongPointer.h>
+#include <datasource/DataSourceFactory.h>
+#include <datasource/HTTPBase.h>
+#include <datasource/NuCachedSource2.h>
 #include <media/IMediaHTTPService.h>
 #include <media/NdkMediaError.h>
 #include <media/NdkMediaDataSource.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
-#include <mediaplayer2/JavaVMHelper.h>
-#include <mediaplayer2/JMedia2HTTPService.h>
+#include <utils/Log.h>
+#include <utils/StrongPointer.h>
 
-#include "../../libstagefright/include/HTTPBase.h"
-#include "../../libstagefright/include/NuCachedSource2.h"
 #include "NdkMediaDataSourceCallbacksPriv.h"
 
 
@@ -120,18 +119,11 @@
     return size >= 0 ? OK : UNKNOWN_ERROR;
 }
 
-static sp<MediaHTTPService> createMediaHttpServiceFromJavaObj(JNIEnv *env, jobject obj, int version) {
+static sp<MediaHTTPService> createMediaHttpServiceFromJavaObj(JNIEnv *env, jobject obj) {
     if (obj == NULL) {
         return NULL;
     }
-    switch (version) {
-        case 1:
-            return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
-        case 2:
-            return new JMedia2HTTPService(env, obj);
-        default:
-            return NULL;
-    }
+    return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
 }
 
 static sp<MediaHTTPService> createMediaHttpServiceTemplate(
@@ -139,8 +131,7 @@
         const char *uri,
         const char *clazz,
         const char *method,
-        const char *signature,
-        int version) {
+        const char *signature) {
     jobject service = NULL;
     if (env == NULL) {
         ALOGE("http service must be created from Java thread");
@@ -167,34 +158,23 @@
     env->DeleteLocalRef(juri);
 
     env->ExceptionClear();
-    sp<MediaHTTPService> httpService = createMediaHttpServiceFromJavaObj(env, service, version);
+    sp<MediaHTTPService> httpService = createMediaHttpServiceFromJavaObj(env, service);
     return httpService;
 
 }
 
-sp<MediaHTTPService> createMediaHttpService(const char *uri, int version) {
+sp<MediaHTTPService> createMediaHttpService(const char *uri) {
 
     JNIEnv *env;
     const char *clazz, *method, *signature;
 
-    switch (version) {
-        case 1:
-            env = AndroidRuntime::getJNIEnv();
-            clazz = "android/media/MediaHTTPService";
-            method = "createHttpServiceBinderIfNecessary";
-            signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
-            break;
-        case 2:
-            env = JavaVMHelper::getJNIEnv();
-            clazz = "android/media/Media2HTTPService";
-            method = "createHTTPService";
-            signature = "(Ljava/lang/String;)Landroid/media/Media2HTTPService;";
-            break;
-        default:
-            return NULL;
-    }
+    env = NdkJavaVMHelper::getJNIEnv();
 
-    return createMediaHttpServiceTemplate(env, uri, clazz, method, signature, version);
+    clazz = "android/media/MediaHTTPService";
+    method = "createHttpServiceBinderIfNecessary";
+    signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
+
+    return createMediaHttpServiceTemplate(env, uri, clazz, method, signature);
 
 }
 
@@ -216,7 +196,7 @@
         int numheaders,
         const char * const *key_values) {
 
-    sp<MediaHTTPService> service = createMediaHttpService(uri, /* version = */ 1);
+    sp<MediaHTTPService> service = createMediaHttpService(uri);
     KeyedVector<String8, String8> headers;
     for (int i = 0; i < numheaders; ++i) {
         String8 key8(key_values[i * 2]);
@@ -224,7 +204,7 @@
         headers.add(key8, value8);
     }
 
-    sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers);
     if (source == NULL) {
         ALOGE("AMediaDataSource_newUri source is null");
         return NULL;
diff --git a/media/ndk/NdkMediaDataSourcePriv.h b/media/ndk/NdkMediaDataSourcePriv.h
index 16ff974..ddcd7da 100644
--- a/media/ndk/NdkMediaDataSourcePriv.h
+++ b/media/ndk/NdkMediaDataSourcePriv.h
@@ -62,7 +62,7 @@
 
 };
 
-sp<MediaHTTPService> createMediaHttpService(const char *uri, int version);
+sp<MediaHTTPService> createMediaHttpService(const char *uri);
 
 #endif // _NDK_MEDIA_DATASOURCE_PRIV_H
 
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index cd5a23a..3af9771 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -20,6 +20,10 @@
 #include <inttypes.h>
 #include <unistd.h>
 
+#include <iostream>
+#include <fstream>
+#include <string>
+
 #include <media/NdkMediaDrm.h>
 
 #include <cutils/properties.h>
@@ -28,12 +32,10 @@
 #include <gui/Surface.h>
 
 #include <android-base/properties.h>
-#include <binder/PermissionController.h>
-#include <media/IDrm.h>
-#include <media/IDrmClient.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
 #include <media/stagefright/MediaErrors.h>
-#include <binder/IServiceManager.h>
-#include <media/IMediaDrmService.h>
 #include <media/NdkMediaCrypto.h>
 
 
@@ -41,7 +43,7 @@
 
 typedef Vector<uint8_t> idvec_t;
 
-struct DrmListener: virtual public BnDrmClient
+struct DrmListener: virtual public IDrmClient
 {
 private:
     AMediaDrm *mObj;
@@ -71,12 +73,27 @@
         mKeysChangeListener = listener;
     }
 
-    void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
+    void sendEvent(
+            DrmPlugin::EventType eventType,
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            const hardware::hidl_vec<uint8_t> &data) override;
+
+    void sendExpirationUpdate(
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            int64_t expiryTimeInMS) override;
+
+    void sendKeysChange(
+            const hardware::hidl_vec<uint8_t> &sessionId,
+            const std::vector<DrmKeyStatus> &keyStatusList,
+            bool hasNewUsableKey) override;
+
+    void sendSessionLostState(
+            const hardware::hidl_vec<uint8_t> &) override {}
+
 };
 
 struct AMediaDrm {
     sp<IDrm> mDrm;
-    sp<IDrmClient> mDrmClient;
     List<idvec_t> mIds;
     KeyedVector<String8, String8> mQueryResults;
     Vector<uint8_t> mKeyRequest;
@@ -88,71 +105,52 @@
     sp<DrmListener> mListener;
 };
 
-void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
-    if (!mEventListener || !mExpirationUpdateListener || !mKeysChangeListener) {
-        ALOGE("No listeners are specified");
+void DrmListener::sendExpirationUpdate(
+        const hardware::hidl_vec<uint8_t> &sessionId,
+        int64_t expiryTimeInMS) {
+    if (!mExpirationUpdateListener) {
+        ALOGE("No ExpirationUpdateListener specified");
         return;
     }
 
-    obj->setDataPosition(0);
+    if (expiryTimeInMS >= 0) {
+        AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+        (*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
+    } else {
+        ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
+    }
+}
 
-    AMediaDrmSessionId sessionId = {NULL, 0};
-    int32_t sessionIdSize = obj->readInt32();
-    if (sessionIdSize <= 0) {
-        ALOGE("Invalid session id size");
+void DrmListener::sendKeysChange(
+        const hardware::hidl_vec<uint8_t> &sessionId,
+        const std::vector<DrmKeyStatus> &keyStatusList,
+        bool hasNewUsableKey) {
+    if (!mKeysChangeListener) {
+        ALOGE("No KeysChangeListener specified");
         return;
     }
 
-    std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
-    sessionId.ptr = sessionIdData.get();
-    sessionId.length = sessionIdSize;
-    status_t err = obj->read(sessionIdData.get(), sessionId.length);
-    if (err != OK) {
-        ALOGE("Failed to read session id, error=%d", err);
-        return;
-    }
-
-    if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
-        int64_t expiryTimeInMS = obj->readInt64();
-        if (expiryTimeInMS >= 0) {
-            (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
-        } else {
-            ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
-        }
-        return;
-    } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
-        int32_t numKeys = 0;
-        err = obj->readInt32(&numKeys);
-        if (err != OK) {
-            ALOGE("Failed to read number of keys status, error=%d", err);
-            return;
-        }
-
-        Vector<AMediaDrmKeyStatus> keysStatus;
-        std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
+    Vector<AMediaDrmKeyStatus> keysStatus;
+    for (const auto &drmKeyStatus : keyStatusList) {
         AMediaDrmKeyStatus keyStatus;
+        keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
+        keyStatus.keyId.length = drmKeyStatus.keyId.size();
+        keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
+        keysStatus.push(keyStatus);
+    }
 
-        for (size_t i = 0; i < numKeys; ++i) {
-            keyStatus.keyId.ptr = nullptr;
-            keyStatus.keyId.length = 0;
-            int32_t idSize = obj->readInt32();
-            if (idSize > 0) {
-                std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
-                err = obj->read(data.get(), idSize);
-                if (err != OK) {
-                    ALOGE("Failed to read key data, error=%d", err);
-                    return;
-                }
-                keyStatus.keyId.ptr = data.get();
-                keyStatus.keyId.length = idSize;
-                dataPointers.push_back(std::move(data));
-            }
-            keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
-            keysStatus.push(keyStatus);
-        }
+    AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+    int32_t numKeys = keyStatusList.size();
+    (*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
+    return;
+}
 
-        bool hasNewUsableKey = obj->readInt32();
-        (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
+void DrmListener::sendEvent(
+        DrmPlugin::EventType eventType,
+        const hardware::hidl_vec<uint8_t> &sessionId,
+        const hardware::hidl_vec<uint8_t> &data) {
+    if (!mEventListener) {
+        ALOGE("No EventListener specified");
         return;
     }
 
@@ -176,23 +174,17 @@
             ndkEventType = EVENT_SESSION_RECLAIMED;
             break;
         default:
-            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
+            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
             return;
     }
 
-    int32_t dataSize = obj->readInt32();
-    uint8_t *data = NULL;
+    AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+    int32_t dataSize = data.size();
+    const uint8_t *dataPtr = data.data();
     if (dataSize > 0) {
-        data = new uint8_t[dataSize];
-        err = obj->read(data, dataSize);
-        if (err == OK) {
-            (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
-        } else {
-            ALOGE("Failed to read event data, error=%d", err);
-        }
-        delete [] data;
+        (*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
     } else {
-        ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
+        ALOGE("invalid event data size=%d", dataSize);
     }
 }
 
@@ -246,41 +238,20 @@
 }
 
 static status_t GetAppPackageName(String8 *packageName) {
-    sp<IServiceManager> serviceManager = defaultServiceManager();
-    sp<IBinder> binder = serviceManager->getService(String16("permission"));
-
-    sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
-    if (permissionContol == NULL) {
-        ALOGE("Failed to get permission service");
+    // todo(robertshih): use refactored/renamed libneuralnetworks_packageinfo which is stable
+    std::string appName;
+    std::ifstream cmdline("/proc/self/cmdline");
+    std::getline(cmdline, appName);
+    cmdline.close();
+    if (appName.empty()) {
         return UNKNOWN_ERROR;
     }
-
-    Vector<String16> packages;
-    permissionContol->getPackagesForUid(getuid(), packages);
-
-    if (packages.isEmpty()) {
-        ALOGE("Unable to get package name for current UID");
-        return UNKNOWN_ERROR;
-    }
-
-    *packageName = String8(packages[0]);
+    *packageName = String8(appName.c_str());
     return OK;
 }
 
 static sp<IDrm> CreateDrm() {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.drm"));
-
-    sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
-    if (service == NULL) {
-        return NULL;
-    }
-
-    sp<IDrm> drm = service->makeDrm();
-    if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
-        return NULL;
-    }
-    return drm;
+    return DrmUtils::MakeDrm();
 }
 
 
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index c83b255..0da0740 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -89,7 +89,7 @@
 
     ALOGV("setDataSource(%s)", uri);
 
-    sp<MediaHTTPService> httpService = createMediaHttpService(uri, /* version = */ 1);
+    sp<MediaHTTPService> httpService = createMediaHttpService(uri);
     if (httpService == NULL) {
         ALOGE("can't create http service");
         return AMEDIA_ERROR_UNSUPPORTED;
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 51138c8..ab0cb63 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -341,6 +341,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level";
 EXPORT const char* AMEDIAFORMAT_KEY_LOCATION = "location";
 EXPORT const char* AMEDIAFORMAT_KEY_LOOP = "loop";
+EXPORT const char* AMEDIAFORMAT_KEY_LOW_LATENCY = "low-latency";
 EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist";
 EXPORT const char* AMEDIAFORMAT_KEY_MANUFACTURER = "manufacturer";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE = "max-bitrate";
diff --git a/media/ndk/include/media/NdkImage.h b/media/ndk/include/media/NdkImage.h
index 3e60de0..62b8624 100644
--- a/media/ndk/include/media/NdkImage.h
+++ b/media/ndk/include/media/NdkImage.h
@@ -570,6 +570,8 @@
  * return {@link AMEDIA_ERROR_INVALID_OBJECT}. Application still needs to call this method on those
  * {@link AImage} objects to fully delete the {@link AImage} object from memory.</p>
  *
+ * Available since API level 24.
+ *
  * @param image The {@link AImage} to be deleted.
  */
 void AImage_delete(AImage* image) __INTRODUCED_IN(24);
@@ -577,6 +579,8 @@
 /**
  * Query the width of the input {@link AImage}.
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param width the width of the image will be filled here if the method call succeeeds.
  *
@@ -591,6 +595,8 @@
 /**
  * Query the height of the input {@link AImage}.
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param height the height of the image will be filled here if the method call succeeeds.
  *
@@ -607,6 +613,8 @@
  *
  * <p>The format value will be one of AIMAGE_FORMAT_* enum value.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param format the format of the image will be filled here if the method call succeeeds.
  *
@@ -624,6 +632,8 @@
  * <p>The crop rectangle specifies the region of valid pixels in the image, using coordinates in the
  * largest-resolution plane.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param rect the cropped rectangle of the image will be filled here if the method call succeeeds.
  *
@@ -648,6 +658,8 @@
  * {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted} callback.
  * </p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param timestampNs the timestamp of the image will be filled here if the method call succeeeds.
  *
@@ -665,6 +677,8 @@
  * <p>The number of plane of an {@link AImage} is determined by its format, which can be queried by
  * {@link AImage_getFormat} method.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param numPlanes the number of planes of the image will be filled here if the method call
  *         succeeeds.
@@ -687,6 +701,8 @@
  * being returned.
  * For formats where pixel stride is well defined, the pixel stride is always greater than 0.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
  * @param pixelStride the pixel stride of the image will be filled here if the method call succeeeds.
@@ -714,6 +730,8 @@
  * being returned.
  * For formats where row stride is well defined, the row stride is always greater than 0.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
  * @param rowStride the row stride of the image will be filled here if the method call succeeeds.
@@ -739,6 +757,8 @@
  * pointer from previous AImage_getPlaneData call becomes invalid. Do NOT use it after the
  * {@link AImage} or the parent {@link AImageReader} is deleted.</p>
  *
+ * Available since API level 24.
+ *
  * @param image the {@link AImage} of interest.
  * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
  * @param data the data pointer of the image will be filled here if the method call succeeeds.
@@ -769,6 +789,8 @@
  * signal the release of the hardware buffer back to the {@link AImageReader}'s queue using
  * releaseFenceFd.</p>
  *
+ * Available since API level 26.
+ *
  * @param image The {@link AImage} to be deleted.
  * @param releaseFenceFd A sync fence fd defined in {@link sync.h}, which signals the release of
  *         underlying {@link AHardwareBuffer}.
@@ -794,6 +816,8 @@
  * {@link AImageReader_setBufferRemovedListener} to be notified when the buffer is no longer used
  * by {@link AImageReader}.</p>
  *
+ * Available since API level 26.
+ *
  * @param image the {@link AImage} of interest.
  * @param outBuffer The memory area pointed to by buffer will contain the acquired AHardwareBuffer
  *         handle.
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index e5d863c..600ffc9 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -67,6 +67,8 @@
  * The valid sizes and formats depend on the source of the image data.
  * </p>
  *
+ * Available since API level 24.
+ *
  * @param width The default width in pixels of the Images that this reader will produce.
  * @param height The default height in pixels of the Images that this reader will produce.
  * @param format The format of the Image that this reader will produce. This must be one of the
@@ -101,6 +103,8 @@
  * making any of data pointers obtained from {@link AImage_getPlaneData} invalid. Do NOT access
  * the reader object or any of those data pointers after this method returns.</p>
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader to be deleted.
  */
 void AImageReader_delete(AImageReader* reader) __INTRODUCED_IN(24);
@@ -108,6 +112,8 @@
 /**
  * Get a {@link ANativeWindow} that can be used to produce {@link AImage} for this image reader.
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param window The output {@link ANativeWindow} will be filled here if the method call succeeds.
  *                The {@link ANativeWindow} is managed by this image reader. Do NOT call
@@ -126,6 +132,8 @@
  * {@link ANativeWindow}. If so, the actual width of the images can be found using
  * {@link AImage_getWidth}.</p>
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param width the default width of the reader will be filled here if the method call succeeeds.
  *
@@ -142,6 +150,8 @@
  * {@link ANativeWindow}. If so, the actual height of the images can be found using
  * {@link AImage_getHeight}.</p>
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param height the default height of the reader will be filled here if the method call succeeeds.
  *
@@ -154,6 +164,8 @@
 /**
  * Query the format of the {@link AImage} generated by this reader.
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param format the fromat of the reader will be filled here if the method call succeeeds. The
  *                value will be one of the AIMAGE_FORMAT_* enum value defiend in {@link NdkImage.h}.
@@ -167,6 +179,8 @@
 /**
  * Query the maximum number of concurrently acquired {@link AImage}s of this reader.
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param maxImages the maximum number of concurrently acquired images of the reader will be filled
  *                here if the method call succeeeds.
@@ -197,6 +211,8 @@
  * {@link AImage_delete}.
  * </p>
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param image the acquired {@link AImage} will be filled here if the method call succeeeds.
  *
@@ -214,7 +230,6 @@
 media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) __INTRODUCED_IN(24);
 
 /**
-
  * Acquire the latest {@link AImage} from the image reader's queue, dropping older images.
  *
  * <p>
@@ -241,6 +256,8 @@
  * {@link AImage_delete}.
  * </p>
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param image the acquired {@link AImage} will be filled here if the method call succeeeds.
  *
@@ -290,6 +307,8 @@
  *
  * Calling this method will replace previously registered listeners.
  *
+ * Available since API level 24.
+ *
  * @param reader The image reader of interest.
  * @param listener The {@link AImageReader_ImageListener} to be registered. Set this to NULL if
  *                 the application no longer needs to listen to new images.
@@ -356,6 +375,9 @@
  *   {@link AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE}, or combined</td>
  * </tr>
  * </table>
+ *
+ * Available since API level 26.
+ *
  * @return <ul>
  *         <li>{@link AMEDIA_OK} if the method call succeeds.</li>
  *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL, or one or more of width,
@@ -377,6 +399,8 @@
  * additional parameter for the sync fence. All other parameters and the return values are
  * identical to those passed to {@link AImageReader_acquireNextImage}.</p>
  *
+ * Available since API level 26.
+ *
  * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
  *         buffer is ready to consume. When synchronization fence is not needed, fence will be set
  *         to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
@@ -397,6 +421,8 @@
  * additional parameter for the sync fence. All other parameters and the return values are
  * identical to those passed to {@link AImageReader_acquireLatestImage}.</p>
  *
+ * Available since API level 26.
+ *
  * @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
  *         buffer is ready to consume. When synchronization fence is not needed, fence will be set
  *         to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
@@ -408,6 +434,7 @@
  */
 media_status_t AImageReader_acquireLatestImageAsync(
         AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) __INTRODUCED_IN(26);
+
 /**
  * Signature of the callback which is called when {@link AImageReader} is about to remove a buffer.
  *
@@ -451,6 +478,8 @@
  *
  * <p>Note that calling this method will replace previously registered listeners.</p>
  *
+ * Available since API level 26.
+ *
  * @param reader The image reader of interest.
  * @param listener the {@link AImageReader_BufferRemovedListener} to be registered. Set this to
  * NULL if application no longer needs to listen to buffer removed events.
diff --git a/media/ndk/include/media/NdkMediaCodec.h b/media/ndk/include/media/NdkMediaCodec.h
index b3ee853..8fb6a87 100644
--- a/media/ndk/include/media/NdkMediaCodec.h
+++ b/media/ndk/include/media/NdkMediaCodec.h
@@ -127,27 +127,37 @@
  * Create codec by name. Use this if you know the exact codec you want to use.
  * When configuring, you will need to specify whether to use the codec as an
  * encoder or decoder.
+ *
+ * Available since API level 21.
  */
 AMediaCodec* AMediaCodec_createCodecByName(const char *name) __INTRODUCED_IN(21);
 
 /**
  * Create codec by mime type. Most applications will use this, specifying a
  * mime type obtained from media extractor.
+ *
+ * Available since API level 21.
  */
 AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) __INTRODUCED_IN(21);
 
 /**
  * Create encoder by name.
+ *
+ * Available since API level 21.
  */
 AMediaCodec* AMediaCodec_createEncoderByType(const char *mime_type) __INTRODUCED_IN(21);
 
 /**
- * delete the codec and free its resources
+ * Delete the codec and free its resources.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_delete(AMediaCodec*) __INTRODUCED_IN(21);
 
 /**
  * Configure the codec. For decoding you would typically get the format from an extractor.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_configure(
         AMediaCodec*,
@@ -159,29 +169,39 @@
 /**
  * Start the codec. A codec must be configured before it can be started, and must be started
  * before buffers can be sent to it.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_start(AMediaCodec*) __INTRODUCED_IN(21);
 
 /**
  * Stop the codec.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_stop(AMediaCodec*) __INTRODUCED_IN(21);
 
 /*
  * Flush the codec's input and output. All indices previously returned from calls to
  * AMediaCodec_dequeueInputBuffer and AMediaCodec_dequeueOutputBuffer become invalid.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_flush(AMediaCodec*) __INTRODUCED_IN(21);
 
 /**
  * Get an input buffer. The specified buffer index must have been previously obtained from
  * dequeueInputBuffer, and not yet queued.
+ *
+ * Available since API level 21.
  */
 uint8_t* AMediaCodec_getInputBuffer(AMediaCodec*, size_t idx, size_t *out_size) __INTRODUCED_IN(21);
 
 /**
  * Get an output buffer. The specified buffer index must have been previously obtained from
  * dequeueOutputBuffer, and not yet queued.
+ *
+ * Available since API level 21.
  */
 uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec*, size_t idx, size_t *out_size) __INTRODUCED_IN(21);
 
@@ -189,6 +209,8 @@
  * Get the index of the next available input buffer. An app will typically use this with
  * getInputBuffer() to get a pointer to the buffer, then copy the data to be encoded or decoded
  * into the buffer before passing it to the codec.
+ *
+ * Available since API level 21.
  */
 ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec*, int64_t timeoutUs) __INTRODUCED_IN(21);
 
@@ -218,6 +240,8 @@
 
 /**
  * Send the specified buffer to the codec for processing.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_queueInputBuffer(AMediaCodec*, size_t idx,
                                             _off_t_compat offset, size_t size,
@@ -225,6 +249,8 @@
 
 /**
  * Send the specified buffer to the codec for processing.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_queueSecureInputBuffer(AMediaCodec*, size_t idx,
                                                   _off_t_compat offset,
@@ -235,15 +261,26 @@
 
 /**
  * Get the index of the next available buffer of processed data.
+ *
+ * Available since API level 21.
  */
 ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info,
         int64_t timeoutUs) __INTRODUCED_IN(21);
+
+/**
+ * Returns the format of the codec's output.
+ * The caller must free the returned format.
+ *
+ * Available since API level 21.
+ */
 AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*) __INTRODUCED_IN(21);
 
 /**
  * If you are done with a buffer, use this call to return the buffer to
  * the codec. If you previously specified a surface when configuring this
  * video decoder you can optionally render the buffer.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec*, size_t idx, bool render) __INTRODUCED_IN(21);
 
@@ -256,6 +293,8 @@
  *  to ImageReader (software readable) output.
  *
  * For more details, see the Java documentation for MediaCodec.setOutputSurface.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_setOutputSurface(AMediaCodec*, ANativeWindow* surface) __INTRODUCED_IN(21);
 
@@ -266,6 +305,8 @@
  * this call will simply return the buffer to the codec.
  *
  * For more details, see the Java documentation for MediaCodec.releaseOutputBuffer.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodec_releaseOutputBufferAtTime(
         AMediaCodec *mData, size_t idx, int64_t timestampNs) __INTRODUCED_IN(21);
@@ -282,6 +323,8 @@
  * ANativeWindow_release() when done.
  *
  * For more details, see the Java documentation for MediaCodec.createInputSurface.
+ *
+ * Available since API level 26.
  */
 media_status_t AMediaCodec_createInputSurface(
         AMediaCodec *mData, ANativeWindow **surface) __INTRODUCED_IN(26);
@@ -298,6 +341,8 @@
  * ANativeWindow_release() when done.
  *
  * For more details, see the Java documentation for MediaCodec.createPersistentInputSurface.
+ *
+ * Available since API level 26.
  */
 media_status_t AMediaCodec_createPersistentInputSurface(
         ANativeWindow **surface) __INTRODUCED_IN(26);
@@ -311,6 +356,8 @@
  * AMediaCodec_configure(..); and before AMediaCodec_start() has been called.
  *
  * For more details, see the Java documentation for MediaCodec.setInputSurface.
+ *
+ * Available since API level 26.
  */
 media_status_t AMediaCodec_setInputSurface(
         AMediaCodec *mData, ANativeWindow *surface) __INTRODUCED_IN(26);
@@ -322,6 +369,8 @@
  * after AMediaCodec_start() has been called.
  *
  * NOTE: Some of these parameter changes may silently fail to apply.
+ *
+ * Available since API level 26.
  */
 media_status_t AMediaCodec_setParameters(
         AMediaCodec *mData, const AMediaFormat* params) __INTRODUCED_IN(26);
@@ -339,6 +388,8 @@
  * Returns AMEDIA_OK when completed succesfully.
  *
  * For more details, see the Java documentation for MediaCodec.signalEndOfInputStream.
+ *
+ * Available since API level 26.
  */
 media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) __INTRODUCED_IN(26);
 
@@ -349,6 +400,9 @@
 /**
  * Get format of the buffer. The specified buffer index must have been previously obtained from
  * dequeueOutputBuffer.
+ * The caller must free the returned format.
+ *
+ * Available since API level 28.
  */
 AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec*, size_t index) __INTRODUCED_IN(28);
 
@@ -356,11 +410,15 @@
  * Get the component name. If the codec was created by createDecoderByType
  * or createEncoderByType, what component is chosen is not known beforehand.
  * Caller shall call AMediaCodec_releaseName to free the returned pointer.
+ *
+ * Available since API level 28.
  */
 media_status_t AMediaCodec_getName(AMediaCodec*, char** out_name) __INTRODUCED_IN(28);
 
 /**
  * Free the memory pointed by name which is returned by AMediaCodec_getName.
+ *
+ * Available since API level 28.
  */
 void AMediaCodec_releaseName(AMediaCodec*, char* name) __INTRODUCED_IN(28);
 
@@ -382,6 +440,8 @@
  * All callbacks are fired on one NDK internal thread.
  * AMediaCodec_setAsyncNotifyCallback should not be called on the callback thread.
  * No heavy duty task should be performed on callback thread.
+ *
+ * Available since API level 28.
  */
 media_status_t AMediaCodec_setAsyncNotifyCallback(
         AMediaCodec*,
@@ -390,6 +450,8 @@
 
 /**
  * Release the crypto if applicable.
+ *
+ * Available since API level 28.
  */
 media_status_t AMediaCodec_releaseCrypto(AMediaCodec*) __INTRODUCED_IN(28);
 
@@ -397,12 +459,17 @@
  * Call this after AMediaCodec_configure() returns successfully to get the input
  * format accepted by the codec. Do this to determine what optional configuration
  * parameters were supported by the codec.
+ * The caller must free the returned format.
+ *
+ * Available since API level 28.
  */
 AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec*) __INTRODUCED_IN(28);
 
 /**
  * Returns true if the codec cannot proceed further, but can be recovered by stopping,
  * configuring, and starting again.
+ *
+ * Available since API level 28.
  */
 bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) __INTRODUCED_IN(28);
 
@@ -410,6 +477,8 @@
  * Returns true if the codec error is a transient issue, perhaps due to
  * resource constraints, and that the method (or encoding/decoding) may be
  * retried at a later time.
+ *
+ * Available since API level 28.
  */
 bool AMediaCodecActionCode_isTransient(int32_t actionCode) __INTRODUCED_IN(28);
 
@@ -440,6 +509,8 @@
  * numBytesOfClearData can be null to indicate that all data is encrypted.
  * This information encapsulates per-sample metadata as outlined in
  * ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base media file format files".
+ *
+ * Available since API level 21.
  */
 AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
         int numsubsamples,
@@ -450,13 +521,17 @@
         size_t *encryptedbytes) __INTRODUCED_IN(21);
 
 /**
- * delete an AMediaCodecCryptoInfo created previously with AMediaCodecCryptoInfo_new, or
- * obtained from AMediaExtractor
+ * Delete an AMediaCodecCryptoInfo created previously with AMediaCodecCryptoInfo_new, or
+ * obtained from AMediaExtractor.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo*) __INTRODUCED_IN(21);
 
 /**
- * Set the crypto pattern on an AMediaCryptoInfo object
+ * Set the crypto pattern on an AMediaCryptoInfo object.
+ *
+ * Available since API level 21.
  */
 void AMediaCodecCryptoInfo_setPattern(
         AMediaCodecCryptoInfo *info,
@@ -464,32 +539,44 @@
 
 /**
  * The number of subsamples that make up the buffer's contents.
+ *
+ * Available since API level 21.
  */
 size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo*) __INTRODUCED_IN(21);
 
 /**
- * A 16-byte opaque key
+ * A 16-byte opaque key.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo*, uint8_t *dst) __INTRODUCED_IN(21);
 
 /**
- * A 16-byte initialization vector
+ * A 16-byte initialization vector.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo*, uint8_t *dst) __INTRODUCED_IN(21);
 
 /**
  * The type of encryption that has been applied,
  * one of AMEDIACODECRYPTOINFO_MODE_CLEAR or AMEDIACODECRYPTOINFO_MODE_AES_CTR.
+ *
+ * Available since API level 21.
  */
 cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo*) __INTRODUCED_IN(21);
 
 /**
  * The number of leading unencrypted bytes in each subsample.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo*, size_t *dst) __INTRODUCED_IN(21);
 
 /**
  * The number of trailing encrypted bytes in each subsample.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo*, size_t *dst) __INTRODUCED_IN(21);
 
diff --git a/media/ndk/include/media/NdkMediaCrypto.h b/media/ndk/include/media/NdkMediaCrypto.h
index bcdf9a0..3fa07c7 100644
--- a/media/ndk/include/media/NdkMediaCrypto.h
+++ b/media/ndk/include/media/NdkMediaCrypto.h
@@ -49,12 +49,24 @@
 
 #if __ANDROID_API__ >= 21
 
+/**
+ * Available since API level 21.
+ */
 bool AMediaCrypto_isCryptoSchemeSupported(const AMediaUUID uuid) __INTRODUCED_IN(21);
 
+/**
+ * Available since API level 21.
+ */
 bool AMediaCrypto_requiresSecureDecoderComponent(const char *mime) __INTRODUCED_IN(21);
 
+/**
+ * Available since API level 21.
+ */
 AMediaCrypto* AMediaCrypto_new(const AMediaUUID uuid, const void *initData, size_t initDataSize) __INTRODUCED_IN(21);
 
+/**
+ * Available since API level 21.
+ */
 void AMediaCrypto_delete(AMediaCrypto* crypto) __INTRODUCED_IN(21);
 
 #endif /* __ANDROID_API__ >= 21 */
diff --git a/media/ndk/include/media/NdkMediaDataSource.h b/media/ndk/include/media/NdkMediaDataSource.h
index 16b1eb3..0577df2 100644
--- a/media/ndk/include/media/NdkMediaDataSource.h
+++ b/media/ndk/include/media/NdkMediaDataSource.h
@@ -88,6 +88,8 @@
 /**
  * Create new media data source. Returns NULL if memory allocation
  * for the new data source object fails.
+ *
+ * Available since API level 28.
  */
 AMediaDataSource* AMediaDataSource_new() __INTRODUCED_IN(28);
 
@@ -116,6 +118,7 @@
  * ...
  * key_values[(numheaders - 1) * 2]:key_values[(numheaders - 1) * 2 + 1]
  *
+ * Available since API level 29.
  */
 AMediaDataSource* AMediaDataSource_newUri(const char *uri,
         int numheaders,
@@ -125,12 +128,16 @@
 
 /**
  * Delete a previously created media data source.
+ *
+ * Available since API level 28.
  */
 void AMediaDataSource_delete(AMediaDataSource*) __INTRODUCED_IN(28);
 
 /**
  * Set an user provided opaque handle. This opaque handle is passed as
  * the first argument to the data source callbacks.
+ *
+ * Available since API level 28.
  */
 void AMediaDataSource_setUserdata(
         AMediaDataSource*, void *userdata) __INTRODUCED_IN(28);
@@ -145,6 +152,8 @@
  *
  * Please refer to the definition of AMediaDataSourceReadAt for
  * additional details.
+ *
+ * Available since API level 28.
  */
 void AMediaDataSource_setReadAt(
         AMediaDataSource*,
@@ -156,6 +165,8 @@
  *
  * Please refer to the definition of AMediaDataSourceGetSize for
  * additional details.
+ *
+ * Available since API level 28.
  */
 void AMediaDataSource_setGetSize(
         AMediaDataSource*,
@@ -167,6 +178,8 @@
  *
  * Please refer to the definition of AMediaDataSourceClose for
  * additional details.
+ *
+ * Available since API level 28.
  */
 void AMediaDataSource_setClose(
         AMediaDataSource*,
@@ -181,6 +194,8 @@
  *
  * Please refer to the definition of AMediaDataSourceClose for
  * additional details.
+ *
+ * Available since API level 29.
  */
 void AMediaDataSource_close(AMediaDataSource*) __INTRODUCED_IN(29);
 
@@ -191,6 +206,8 @@
  *
  * Please refer to the definition of AMediaDataSourceGetAvailableSize
  * for additional details.
+ *
+ * Available since API level 29.
  */
 void AMediaDataSource_setGetAvailableSize(
         AMediaDataSource*,
diff --git a/media/ndk/include/media/NdkMediaDrm.h b/media/ndk/include/media/NdkMediaDrm.h
index 2e438d9..31f5c7d 100644
--- a/media/ndk/include/media/NdkMediaDrm.h
+++ b/media/ndk/include/media/NdkMediaDrm.h
@@ -174,41 +174,53 @@
  * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes.
  * mimeType is the MIME type of the media container, e.g. "video/mp4".  If mimeType
  * is not known or required, it can be provided as NULL.
+ *
+ * Available since API level 21.
  */
 bool AMediaDrm_isCryptoSchemeSupported(const uint8_t *uuid,
         const char *mimeType) __INTRODUCED_IN(21);
 
 /**
- * Create a MediaDrm instance from a UUID
+ * Create a MediaDrm instance from a UUID.
  * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes.
+ *
+ * Available since API level 21.
  */
 AMediaDrm* AMediaDrm_createByUUID(const uint8_t *uuid) __INTRODUCED_IN(21);
 
 /**
- * Release a MediaDrm object
+ * Release a MediaDrm object.
+ *
+ * Available since API level 21.
  */
 void AMediaDrm_release(AMediaDrm *) __INTRODUCED_IN(21);
 
 /**
- * Register a callback to be invoked when an event occurs
+ * Register a callback to be invoked when an event occurs.
  *
- * listener is the callback that will be invoked on event
+ * listener is the callback that will be invoked on event.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_setOnEventListener(AMediaDrm *,
         AMediaDrmEventListener listener) __INTRODUCED_IN(21);
 
 /**
- * Register a callback to be invoked when an expiration update event occurs
+ * Register a callback to be invoked when an expiration update event occurs.
  *
- * listener is the callback that will be invoked on event
+ * listener is the callback that will be invoked on event.
+ *
+ * Available since API level 29.
  */
 media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *,
         AMediaDrmExpirationUpdateListener listener) __INTRODUCED_IN(29);
 
 /**
- * Register a callback to be invoked when a key status change event occurs
+ * Register a callback to be invoked when a key status change event occurs.
  *
- * listener is the callback that will be invoked on event
+ * listener is the callback that will be invoked on event.
+ *
+ * Available since API level 29.
  */
 media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *,
         AMediaDrmKeysChangeListener listener) __INTRODUCED_IN(29);
@@ -216,8 +228,10 @@
 /**
  * Open a new session with the MediaDrm object.  A session ID is returned.
  *
- * returns MEDIADRM_NOT_PROVISIONED_ERROR if provisioning is needed
- * returns MEDIADRM_RESOURCE_BUSY_ERROR if required resources are in use
+ * Returns MEDIADRM_NOT_PROVISIONED_ERROR if provisioning is needed.
+ * Returns MEDIADRM_RESOURCE_BUSY_ERROR if required resources are in use.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_openSession(AMediaDrm *,
         AMediaDrmSessionId *sessionId) __INTRODUCED_IN(21);
@@ -225,6 +239,8 @@
 /**
  * Close a session on the MediaDrm object that was previously opened
  * with AMediaDrm_openSession.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_closeSession(AMediaDrm *,
         const AMediaDrmSessionId *sessionId) __INTRODUCED_IN(21);
@@ -272,9 +288,11 @@
  *       MediaDrm object is released.
  *   2. keyRequestSize will be set to the size of the request
  *
- * returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
+ * Returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
  * problem with the device certificate.
-*/
+ *
+ * Available since API level 21.
+ */
 media_status_t AMediaDrm_getKeyRequest(AMediaDrm *, const AMediaDrmScope *scope,
         const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
         const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
@@ -295,8 +313,9 @@
  *
  * response points to the opaque response from the server
  * responseSize should be set to the size of the response in bytes
+ *
+ * Available since API level 21.
  */
-
 media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *, const AMediaDrmScope *scope,
         const uint8_t *response, size_t responseSize,
         AMediaDrmKeySetId *keySetId) __INTRODUCED_IN(21);
@@ -305,8 +324,10 @@
  * Restore persisted offline keys into a new session.  keySetId identifies the
  * keys to load, obtained from a prior call to AMediaDrm_provideKeyResponse.
  *
- * sessionId is the session ID for the DRM session
- * keySetId identifies the saved key set to restore
+ * sessionId is the session ID for the DRM session.
+ * keySetId identifies the saved key set to restore.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_restoreKeys(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         const AMediaDrmKeySetId *keySetId) __INTRODUCED_IN(21);
@@ -314,7 +335,9 @@
 /**
  * Remove the current keys from a session.
  *
- * keySetId identifies keys to remove
+ * keySetId identifies keys to remove.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_removeKeys(AMediaDrm *,
         const AMediaDrmSessionId *keySetId) __INTRODUCED_IN(21);
@@ -331,6 +354,8 @@
  * to the number of entries written to the array.  If the number of {key, value} pairs
  * to be returned is greater than *numPairs, MEDIADRM_SHORT_BUFFER will be returned
  * and numPairs will be set to the number of pairs available.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) __INTRODUCED_IN(21);
@@ -350,6 +375,8 @@
  *    3. serverUrl will reference a NULL terminated string containing the URL
  *       the provisioning request should be sent to.  It will remain accessible until
  *       the next call to getProvisionRequest.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *, const uint8_t **provisionRequest,
         size_t *provisionRequestSize, const char **serverUrl) __INTRODUCED_IN(21);
@@ -363,8 +390,10 @@
  *   DRM engine plugin.
  * responseSize is the length of the provisioning response in bytes.
  *
- * returns MEDIADRM_DEVICE_REVOKED_ERROR if the response indicates that the
+ * Returns MEDIADRM_DEVICE_REVOKED_ERROR if the response indicates that the
  * server rejected the request
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *,
         const uint8_t *response, size_t responseSize) __INTRODUCED_IN(21);
@@ -390,6 +419,8 @@
  * If *numSecureStops is too small for the number of secure stops available,
  * MEDIADRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
  * number required.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_getSecureStops(AMediaDrm *,
         AMediaDrmSecureStop *secureStops, size_t *numSecureStops) __INTRODUCED_IN(21);
@@ -399,6 +430,8 @@
  * the message, remove the SecureStops identified in the response.
  *
  * ssRelease is the server response indicating which secure stops to release
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *,
         const AMediaDrmSecureStop *ssRelease) __INTRODUCED_IN(21);
@@ -432,6 +465,8 @@
  * On return, propertyValue will be set to point to the property value.  The
  * memory that the value resides in is owned by the NDK MediaDrm API and
  * will remain valid until the next call to AMediaDrm_getPropertyString.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_getPropertyString(AMediaDrm *, const char *propertyName,
         const char **propertyValue) __INTRODUCED_IN(21);
@@ -447,18 +482,24 @@
  * On return, *propertyValue will be set to point to the property value.  The
  * memory that the value resides in is owned by the NDK MediaDrm API and
  * will remain valid until the next call to AMediaDrm_getPropertyByteArray.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *, const char *propertyName,
         AMediaDrmByteArray *propertyValue) __INTRODUCED_IN(21);
 
 /**
  * Set a DRM engine plugin String property value.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_setPropertyString(AMediaDrm *, const char *propertyName,
         const char *value) __INTRODUCED_IN(21);
 
 /**
  * Set a DRM engine plugin byte array property value.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *, const char *propertyName,
         const uint8_t *value, size_t valueSize) __INTRODUCED_IN(21);
@@ -487,6 +528,8 @@
  * ensure that the output buffer is large enough to accept dataSize bytes. The key
  * to use is identified by the 16 byte keyId.  The key must have been loaded into
  * the session using provideKeyResponse.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_encrypt(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
@@ -498,6 +541,8 @@
  * ensure that the output buffer is large enough to accept dataSize bytes.  The key
  * to use is identified by the 16 byte keyId.  The key must have been loaded into
  * the session using provideKeyResponse.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_decrypt(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
@@ -511,6 +556,8 @@
  * *signatureSize is set to the buffer size required.  The key to use is identified
  * by the 16 byte keyId.  The key must have been loaded into the session using
  * provideKeyResponse.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_sign(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
@@ -522,6 +569,8 @@
  * if the signature matches, otherwise MEDAIDRM_VERIFY_FAILED is returned. The key to
  * use is identified by the 16 byte keyId.  The key must have been loaded into the
  * session using provideKeyResponse.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaDrm_verify(AMediaDrm *, const AMediaDrmSessionId *sessionId,
         const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
diff --git a/media/ndk/include/media/NdkMediaExtractor.h b/media/ndk/include/media/NdkMediaExtractor.h
index e3d9fe6..14319c4 100644
--- a/media/ndk/include/media/NdkMediaExtractor.h
+++ b/media/ndk/include/media/NdkMediaExtractor.h
@@ -52,23 +52,31 @@
 #if __ANDROID_API__ >= 21
 
 /**
- * Create new media extractor
+ * Create new media extractor.
+ *
+ * Available since API level 21.
  */
 AMediaExtractor* AMediaExtractor_new() __INTRODUCED_IN(21);
 
 /**
- * Delete a previously created media extractor
+ * Delete a previously created media extractor.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_delete(AMediaExtractor*) __INTRODUCED_IN(21);
 
 /**
- *  Set the file descriptor from which the extractor will read.
+ * Set the file descriptor from which the extractor will read.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor*, int fd, off64_t offset,
         off64_t length) __INTRODUCED_IN(21);
 
 /**
  * Set the URI from which the extractor will read.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_setDataSource(AMediaExtractor*,
         const char *location) __INTRODUCED_IN(21);
@@ -77,6 +85,8 @@
 
 /**
  * Set the custom data source implementation from which the extractor will read.
+ *
+ * Available since API level 28.
  */
 media_status_t AMediaExtractor_setDataSourceCustom(AMediaExtractor*,
         AMediaDataSource *src) __INTRODUCED_IN(28);
@@ -85,11 +95,15 @@
 
 /**
  * Return the number of tracks in the previously specified media file
+ *
+ * Available since API level 21.
  */
 size_t AMediaExtractor_getTrackCount(AMediaExtractor*) __INTRODUCED_IN(21);
 
 /**
  * Return the format of the specified track. The caller must free the returned format
+ *
+ * Available since API level 21.
  */
 AMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor*, size_t idx) __INTRODUCED_IN(21);
 
@@ -98,41 +112,55 @@
  * getSampleTime only retrieve information for the subset of tracks selected.
  * Selecting the same track multiple times has no effect, the track is
  * only selected once.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_selectTrack(AMediaExtractor*, size_t idx) __INTRODUCED_IN(21);
 
 /**
  * Unselect the specified track. Subsequent calls to readSampleData, getSampleTrackIndex and
- * getSampleTime only retrieve information for the subset of tracks selected..
+ * getSampleTime only retrieve information for the subset of tracks selected.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_unselectTrack(AMediaExtractor*, size_t idx) __INTRODUCED_IN(21);
 
 /**
  * Read the current sample.
+ *
+ * Available since API level 21.
  */
 ssize_t AMediaExtractor_readSampleData(AMediaExtractor*,
         uint8_t *buffer, size_t capacity) __INTRODUCED_IN(21);
 
 /**
  * Read the current sample's flags.
+ *
+ * Available since API level 21.
  */
 uint32_t AMediaExtractor_getSampleFlags(AMediaExtractor*) __INTRODUCED_IN(21);
 
 /**
  * Returns the track index the current sample originates from (or -1
  * if no more samples are available)
+ *
+ * Available since API level 21.
  */
 int AMediaExtractor_getSampleTrackIndex(AMediaExtractor*) __INTRODUCED_IN(21);
 
 /**
  * Returns the current sample's presentation time in microseconds.
  * or -1 if no more samples are available.
+ *
+ * Available since API level 21.
  */
 int64_t AMediaExtractor_getSampleTime(AMediaExtractor*) __INTRODUCED_IN(21);
 
 /**
  * Advance to the next sample. Returns false if no more sample data
  * is available (end of stream).
+ *
+ * Available since API level 21.
  */
 bool AMediaExtractor_advance(AMediaExtractor*) __INTRODUCED_IN(21);
 
@@ -143,7 +171,7 @@
 } SeekMode;
 
 /**
- *
+ * Available since API level 21.
  */
 media_status_t AMediaExtractor_seekTo(AMediaExtractor*,
         int64_t seekPosUs, SeekMode mode) __INTRODUCED_IN(21);
@@ -167,10 +195,14 @@
 
 /**
  * Get the PSSH info if present.
+ *
+ * Available since API level 21.
  */
 PsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor*) __INTRODUCED_IN(21);
 
-
+/**
+ * Available since API level 21.
+ */
 AMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *) __INTRODUCED_IN(21);
 
 enum {
@@ -186,6 +218,8 @@
  *
  * This function will always return a format; however, the format could be empty
  * (no key-value pairs) if the media container does not provide format information.
+ *
+ * Available since API level 28.
  */
 AMediaFormat* AMediaExtractor_getFileFormat(AMediaExtractor*) __INTRODUCED_IN(28);
 
@@ -198,6 +232,7 @@
  * uint8_t *buf = new uint8_t[sampleSize];
  * AMediaExtractor_readSampleData(ex, buf, sampleSize);
  *
+ * Available since API level 28.
  */
 ssize_t AMediaExtractor_getSampleSize(AMediaExtractor*) __INTRODUCED_IN(28);
 
@@ -211,6 +246,8 @@
  * Returns -1 when the extractor is not reading from a network data source, or when the
  * cached duration cannot be calculated (bitrate, duration, and file size information
  * not available).
+ *
+ * Available since API level 28.
  */
 int64_t AMediaExtractor_getCachedDuration(AMediaExtractor *) __INTRODUCED_IN(28);
 
@@ -222,6 +259,8 @@
  * Returns AMEDIA_OK on success or AMEDIA_ERROR_* to indicate failure reason.
  * Existing key-value pairs in |fmt| would be removed if this API returns AMEDIA_OK.
  * The contents of |fmt| is undefined if this API returns AMEDIA_ERROR_*.
+ *
+ * Available since API level 28.
  */
 media_status_t AMediaExtractor_getSampleFormat(AMediaExtractor *ex,
         AMediaFormat *fmt) __INTRODUCED_IN(28);
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index fd43f36..49d8b4a 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -48,40 +48,78 @@
 
 #if __ANDROID_API__ >= 21
 
+/**
+ * Available since API level 21.
+ */
 AMediaFormat *AMediaFormat_new() __INTRODUCED_IN(21);
+
+/**
+ * Available since API level 21.
+ */
 media_status_t AMediaFormat_delete(AMediaFormat*) __INTRODUCED_IN(21);
 
 /**
  * Human readable representation of the format. The returned string is owned by the format,
  * and remains valid until the next call to toString, or until the format is deleted.
+ *
+ * Available since API level 21.
  */
 const char* AMediaFormat_toString(AMediaFormat*) __INTRODUCED_IN(21);
 
+/**
+ * Available since API level 21.
+ */
 bool AMediaFormat_getInt32(AMediaFormat*, const char *name, int32_t *out) __INTRODUCED_IN(21);
+/**
+ * Available since API level 21.
+ */
 bool AMediaFormat_getInt64(AMediaFormat*, const char *name, int64_t *out) __INTRODUCED_IN(21);
+/**
+ * Available since API level 21.
+ */
 bool AMediaFormat_getFloat(AMediaFormat*, const char *name, float *out) __INTRODUCED_IN(21);
+/**
+ * Available since API level 21.
+ */
 bool AMediaFormat_getSize(AMediaFormat*, const char *name, size_t *out) __INTRODUCED_IN(21);
 /**
  * The returned data is owned by the format and remains valid as long as the named entry
  * is part of the format.
+ *
+ * Available since API level 21.
  */
 bool AMediaFormat_getBuffer(AMediaFormat*, const char *name, void** data, size_t *size) __INTRODUCED_IN(21);
 /**
  * The returned string is owned by the format, and remains valid until the next call to getString,
  * or until the format is deleted.
+ *
+ * Available since API level 21.
  */
 bool AMediaFormat_getString(AMediaFormat*, const char *name, const char **out) __INTRODUCED_IN(21);
 
 
+/**
+ * Available since API level 21.
+ */
 void AMediaFormat_setInt32(AMediaFormat*, const char* name, int32_t value) __INTRODUCED_IN(21);
+/**
+ * Available since API level 21.
+ */
 void AMediaFormat_setInt64(AMediaFormat*, const char* name, int64_t value) __INTRODUCED_IN(21);
+/**
+ * Available since API level 21.
+ */
 void AMediaFormat_setFloat(AMediaFormat*, const char* name, float value) __INTRODUCED_IN(21);
 /**
  * The provided string is copied into the format.
+ *
+ * Available since API level 21.
  */
 void AMediaFormat_setString(AMediaFormat*, const char* name, const char* value) __INTRODUCED_IN(21);
 /**
  * The provided data is copied into the format.
+ *
+ * Available since API level 21.
  */
 void AMediaFormat_setBuffer(AMediaFormat*, const char* name, const void* data, size_t size) __INTRODUCED_IN(21);
 
@@ -155,24 +193,43 @@
 #endif /* __ANDROID_API__ >= 21 */
 
 #if __ANDROID_API__ >= 28
+/**
+ * Available since API level 28.
+ */
 bool AMediaFormat_getDouble(AMediaFormat*, const char *name, double *out) __INTRODUCED_IN(28);
+/**
+ * Available since API level 28.
+ */
 bool AMediaFormat_getRect(AMediaFormat*, const char *name,
         int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) __INTRODUCED_IN(28);
 
+/**
+ * Available since API level 28.
+ */
 void AMediaFormat_setDouble(AMediaFormat*, const char* name, double value) __INTRODUCED_IN(28);
+/**
+ * Available since API level 28.
+ */
 void AMediaFormat_setSize(AMediaFormat*, const char* name, size_t value) __INTRODUCED_IN(28);
+/**
+ * Available since API level 28.
+ */
 void AMediaFormat_setRect(AMediaFormat*, const char* name,
         int32_t left, int32_t top, int32_t right, int32_t bottom) __INTRODUCED_IN(28);
 #endif /* __ANDROID_API__ >= 28 */
 
 #if __ANDROID_API__ >= 29
 /**
- * remove all key/value pairs from the given AMediaFormat
+ * Remove all key/value pairs from the given AMediaFormat.
+ *
+ * Available since API level 29.
  */
 void AMediaFormat_clear(AMediaFormat*) __INTRODUCED_IN(29);
 
 /**
- * copy one AMediaFormat to another
+ * Copy one AMediaFormat to another.
+ *
+ * Available since API level 29.
  */
 media_status_t AMediaFormat_copy(AMediaFormat *to, AMediaFormat *from) __INTRODUCED_IN(29);
 
@@ -237,6 +294,19 @@
 
 #endif /* __ANDROID_API__ >= 29 */
 
+#if __ANDROID_API__ >= 30
+/**
+ * An optional key describing the low latency decoding mode. This is an optional parameter
+ * that applies only to decoders. If enabled, the decoder doesn't hold input and output
+ * data more than required by the codec standards.
+ * The associated value is an integer (0 or 1): 1 when low-latency decoding is enabled,
+ * 0 otherwise. The default value is 0.
+ *
+ * Available since API level 30.
+ */
+extern const char* AMEDIAFORMAT_KEY_LOW_LATENCY __INTRODUCED_IN(30);
+#endif /* __ANDROID_API__ >= 30 */
+
 __END_DECLS
 
 #endif // _NDK_MEDIA_FORMAT_H
diff --git a/media/ndk/include/media/NdkMediaMuxer.h b/media/ndk/include/media/NdkMediaMuxer.h
index 7393867..9de3fbf 100644
--- a/media/ndk/include/media/NdkMediaMuxer.h
+++ b/media/ndk/include/media/NdkMediaMuxer.h
@@ -51,17 +51,22 @@
 typedef enum {
     AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4 = 0,
     AMEDIAMUXER_OUTPUT_FORMAT_WEBM   = 1,
+    AMEDIAMUXER_OUTPUT_FORMAT_THREE_GPP   = 2,
 } OutputFormat;
 
 #if __ANDROID_API__ >= 21
 
 /**
- * Create new media muxer
+ * Create new media muxer.
+ *
+ * Available since API level 21.
  */
 AMediaMuxer* AMediaMuxer_new(int fd, OutputFormat format) __INTRODUCED_IN(21);
 
 /**
- * Delete a previously created media muxer
+ * Delete a previously created media muxer.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_delete(AMediaMuxer*) __INTRODUCED_IN(21);
 
@@ -75,6 +80,8 @@
  * Both values are specified in degrees.
  * Latitude must be in the range [-90, 90].
  * Longitude must be in the range [-180, 180].
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_setLocation(AMediaMuxer*,
         float latitude, float longitude) __INTRODUCED_IN(21);
@@ -90,6 +97,8 @@
  * during playback.
  * The angle is specified in degrees, clockwise.
  * The supported angles are 0, 90, 180, and 270 degrees.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_setOrientationHint(AMediaMuxer*, int degrees) __INTRODUCED_IN(21);
 
@@ -97,18 +106,24 @@
  * Adds a track with the specified format.
  * Returns the index of the new track or a negative value in case of failure,
  * which can be interpreted as a media_status_t.
+ *
+ * Available since API level 21.
  */
 ssize_t AMediaMuxer_addTrack(AMediaMuxer*, const AMediaFormat* format) __INTRODUCED_IN(21);
 
 /**
  * Start the muxer. Should be called after AMediaMuxer_addTrack and
  * before AMediaMuxer_writeSampleData.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_start(AMediaMuxer*) __INTRODUCED_IN(21);
 
 /**
  * Stops the muxer.
  * Once the muxer stops, it can not be restarted.
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_stop(AMediaMuxer*) __INTRODUCED_IN(21);
 
@@ -118,6 +133,8 @@
  * the right tracks. Also, it needs to make sure the samples for each track
  * are written in chronological order (e.g. in the order they are provided
  * by the encoder.)
+ *
+ * Available since API level 21.
  */
 media_status_t AMediaMuxer_writeSampleData(AMediaMuxer *muxer,
         size_t trackIdx, const uint8_t *data,
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index f666ad0..29f1da8 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -4,7 +4,7 @@
     AImageReader_acquireLatestImageAsync; # introduced=26
     AImageReader_acquireNextImage; # introduced=24
     AImageReader_acquireNextImageAsync; # introduced=26
-    AImageReader_getWindowNativeHandle; #vndk
+    AImageReader_getWindowNativeHandle; # llndk
     AImageReader_delete; # introduced=24
     AImageReader_getFormat; # introduced=24
     AImageReader_getHeight; # introduced=24
@@ -105,6 +105,7 @@
     AMEDIAFORMAT_KEY_LEVEL; # var introduced=28
     AMEDIAFORMAT_KEY_LOCATION; # var introduced=29
     AMEDIAFORMAT_KEY_LOOP; # var introduced=29
+    AMEDIAFORMAT_KEY_LOW_LATENCY; # var introduced=30
     AMEDIAFORMAT_KEY_LYRICIST; # var introduced=29
     AMEDIAFORMAT_KEY_MANUFACTURER; # var introduced=29
     AMEDIAFORMAT_KEY_MAX_BIT_RATE; # var introduced=29
diff --git a/media/tests/benchmark/.clang-format b/media/tests/benchmark/.clang-format
new file mode 100644
index 0000000..bf1e355
--- /dev/null
+++ b/media/tests/benchmark/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Right
+TabWidth: 4
+UseTab: Never
diff --git a/media/tests/benchmark/Android.bp b/media/tests/benchmark/Android.bp
new file mode 100644
index 0000000..de408dd
--- /dev/null
+++ b/media/tests/benchmark/Android.bp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+subdirs = [
+    "src",
+    "tests",
+    "MediaBenchmarkTest",
+]
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
new file mode 100644
index 0000000..d80d9a5
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+android_test {
+    name: "MediaBenchmarkTest",
+
+    defaults: [
+        "MediaBenchmark-defaults",
+    ],
+
+    // Include all the test code
+    srcs: ["src/androidTest/**/*.java"],
+
+    resource_dirs: ["res"],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    jni_libs: [
+        "libmediabenchmark_jni",
+    ],
+
+    static_libs: [
+        "libMediaBenchmark",
+        "junit",
+        "androidx.test.runner",
+    ],
+}
+
+android_library {
+    name: "libMediaBenchmark",
+
+    defaults: [
+        "MediaBenchmark-defaults",
+    ],
+
+    // Include all the libraries
+    srcs: ["src/main/**/*.java"],
+
+    static_libs: [
+        "androidx.test.core",
+    ],
+}
+
+java_defaults {
+    name: "MediaBenchmark-defaults",
+
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    target_sdk_version: "29",
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
new file mode 100644
index 0000000..eea9914
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.android.media.benchmark">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
+
+    <application
+        tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon"
+        tools:remove="android:appComponentFactory">
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.media.benchmark"
+            android:label="Benchmark Media Test"/>
+</manifest>
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
new file mode 100644
index 0000000..1890661
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+<configuration description="Runs Media Benchmark Tests">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file"
+            key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
+            value="/data/local/tmp/MediaBenchmark/res/" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="false" />
+        <option name="test-file-name" value="MediaBenchmarkTest.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="MediaBenchmarkTest" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.media.benchmark" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/build.gradle b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
new file mode 100644
index 0000000..b2aee1a
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.0'
+    }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 29
+    defaultConfig {
+        applicationId "com.android.media.benchmark"
+        minSdkVersion 28
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    sourceSets {
+        main {
+            java.srcDirs 'src/main/java'
+            res.srcDirs 'res'
+            manifest.srcFile 'AndroidManifest.xml'
+        }
+        androidTest {
+            java.srcDirs  'src/androidTest/java'
+            res.srcDirs 'res'
+            manifest.srcFile 'AndroidManifest.xml'
+        }
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "src/main/cpp/CMakeLists.txt"
+            version "3.10.2"
+        }
+    }
+}
+
+repositories {
+    google()
+    jcenter()
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test:runner:1.2.0'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
new file mode 100644
index 0000000..24dbccc
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -0,0 +1,4 @@
+<resources>
+    <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+    <string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
+</resources>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
new file mode 100644
index 0000000..afd70a3
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Extractor;
+import com.android.media.benchmark.library.Native;
+import com.android.media.benchmark.library.Stats;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class DecoderTest {
+    private static final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+    private static final String mStatsFile =
+            mContext.getExternalFilesDir(null) + "/Decoder." + System.currentTimeMillis() + ".csv";
+    private static final String TAG = "DecoderTest";
+    private static final long PER_TEST_TIMEOUT_MS = 60000;
+    private static final boolean DEBUG = false;
+    private static final boolean WRITE_OUTPUT = false;
+    private String mInputFile;
+    private boolean mAsyncMode;
+
+    public DecoderTest(String inputFile, boolean asyncMode) {
+        this.mInputFile = inputFile;
+        this.mAsyncMode = asyncMode;
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> input() {
+        return Arrays.asList(new Object[][]{
+                //Audio Sync Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4", false},
+                {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", false},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", false},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", false},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", false},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", false},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", false},
+                // Audio Async Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4", true},
+                {"bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", true},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", true},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", true},
+                {"bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", true},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4", true},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm", true},
+                // Video Sync Test
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", false},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", false},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", false},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", false},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", false},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", false},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", false},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", false},
+                // Video Async Test
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", true},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", true},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", true},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", true},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", true},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", true},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", true},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", true}});
+    }
+
+    @BeforeClass
+    public static void writeStatsHeaderToFile() throws IOException {
+        Stats mStats = new Stats();
+        boolean status = mStats.writeStatsHeader(mStatsFile);
+        assertTrue("Unable to open stats file for writing!", status);
+        Log.d(TAG, "Saving Benchmark results in: " + mStatsFile);
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void testDecoder() throws IOException {
+        File inputFile = new File(mInputFilePath + mInputFile);
+        assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        Extractor extractor = new Extractor();
+        int trackCount = extractor.setUpExtractor(fileDescriptor);
+        assertTrue("Extraction failed. No tracks for file: " + mInputFile, (trackCount > 0));
+        ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+        ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+        for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            extractor.selectExtractorTrack(currentTrack);
+            MediaFormat format = extractor.getFormat(currentTrack);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+            ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+            assertTrue("No suitable codecs found for file: " + mInputFile + " track : " +
+                    currentTrack + " mime: " + mime, (mediaCodecs.size() > 0));
+
+            // Get samples from extractor
+            int sampleSize;
+            do {
+                sampleSize = extractor.getFrameSample();
+                MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+                MediaCodec.BufferInfo info = extractor.getBufferInfo();
+                ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+                dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+                bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+                inputBuffer.add(dataBuffer);
+                frameInfo.add(bufInfo);
+                if (DEBUG) {
+                    Log.d(TAG, "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = " +
+                            bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+                }
+            } while (sampleSize > 0);
+            for (String codecName : mediaCodecs) {
+                FileOutputStream decodeOutputStream = null;
+                if (WRITE_OUTPUT) {
+                    if (!Paths.get(mOutputFilePath).toFile().exists()) {
+                        Files.createDirectories(Paths.get(mOutputFilePath));
+                    }
+                    File outFile = new File(mOutputFilePath + "decoder.out");
+                    if (outFile.exists()) {
+                        assertTrue(" Unable to delete existing file" + outFile.toString(),
+                                outFile.delete());
+                    }
+                    assertTrue("Unable to create file: " + outFile.toString(),
+                            outFile.createNewFile());
+                    decodeOutputStream = new FileOutputStream(outFile);
+                }
+                Decoder decoder = new Decoder();
+                decoder.setupDecoder(decodeOutputStream);
+                int status = decoder.decode(inputBuffer, frameInfo, mAsyncMode, format, codecName);
+                decoder.deInitCodec();
+                assertEquals("Decoder returned error " + status + " for file: " + mInputFile +
+                        " with codec: " + codecName, 0, status);
+                decoder.dumpStatistics(mInputFile, codecName, (mAsyncMode ? "async" : "sync"),
+                        extractor.getClipDuration(), mStatsFile);
+                Log.i(TAG, "Decoding Successful for file: " + mInputFile + " with codec: " +
+                        codecName);
+                decoder.resetDecoder();
+                if (decodeOutputStream != null) {
+                    decodeOutputStream.close();
+                }
+            }
+            extractor.unselectExtractorTrack(currentTrack);
+            inputBuffer.clear();
+            frameInfo.clear();
+        }
+        extractor.deinitExtractor();
+        fileInput.close();
+    }
+
+    @Test
+    public void testNativeDecoder() throws IOException {
+        File inputFile = new File(mInputFilePath + mInputFile);
+        assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        Extractor extractor = new Extractor();
+        int trackCount = extractor.setUpExtractor(fileDescriptor);
+        assertTrue("Extraction failed. No tracks for file: ", trackCount > 0);
+        for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            extractor.selectExtractorTrack(currentTrack);
+            MediaFormat format = extractor.getFormat(currentTrack);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+            ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+            for (String codecName : mediaCodecs) {
+                Log.i("Test: %s\n", mInputFile);
+                Native nativeDecoder = new Native();
+                int status = nativeDecoder.Decode(
+                        mInputFilePath, mInputFile, mStatsFile, codecName, mAsyncMode);
+                assertEquals("Decoder returned error " + status + " for file: " + mInputFile, 0,
+                        status);
+            }
+        }
+        fileInput.close();
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
new file mode 100644
index 0000000..48e1422
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Encoder;
+import com.android.media.benchmark.library.Extractor;
+import com.android.media.benchmark.library.Native;
+import com.android.media.benchmark.library.Stats;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class EncoderTest {
+    private static final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+    private static final String mStatsFile =
+            mContext.getExternalFilesDir(null) + "/Encoder." + System.currentTimeMillis() + ".csv";
+    private static final String TAG = "EncoderTest";
+    private static final long PER_TEST_TIMEOUT_MS = 120000;
+    private static final boolean DEBUG = false;
+    private static final boolean WRITE_OUTPUT = false;
+    private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
+    private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+    private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+    private static final int ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
+    private String mInputFile;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{
+                // Audio Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp"},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4"},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm"},
+                // Video Test
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv"},
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm"},
+                {"crowd_176x144_25fps_6000kbps_mpeg4.mp4"},
+                {"crowd_176x144_25fps_6000kbps_h263.3gp"}});
+    }
+
+    public EncoderTest(String inputFileName) {
+        this.mInputFile = inputFileName;
+    }
+
+    @BeforeClass
+    public static void writeStatsHeaderToFile() throws IOException {
+        Stats mStats = new Stats();
+        boolean status = mStats.writeStatsHeader(mStatsFile);
+        assertTrue("Unable to open stats file for writing!", status);
+        Log.d(TAG, "Saving Benchmark results in: " + mStatsFile);
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void testEncoder() throws Exception {
+        int status;
+        int frameSize;
+        //Parameters for video
+        int width = 0;
+        int height = 0;
+        int profile = 0;
+        int level = 0;
+        int frameRate = 0;
+
+        //Parameters for audio
+        int bitRate = 0;
+        int sampleRate = 0;
+        int numChannels = 0;
+        File inputFile = new File(mInputFilePath + mInputFile);
+        assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        Extractor extractor = new Extractor();
+        int trackCount = extractor.setUpExtractor(fileDescriptor);
+        assertTrue("Extraction failed. No tracks for file: " + mInputFile, (trackCount > 0));
+        ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+        ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+        for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            int colorFormat = COLOR_FormatYUV420Flexible;
+            extractor.selectExtractorTrack(currentTrack);
+            MediaFormat format = extractor.getFormat(currentTrack);
+            // Get samples from extractor
+            int sampleSize;
+            do {
+                sampleSize = extractor.getFrameSample();
+                MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+                MediaCodec.BufferInfo info = extractor.getBufferInfo();
+                ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+                dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+                bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+                inputBuffer.add(dataBuffer);
+                frameInfo.add(bufInfo);
+                if (DEBUG) {
+                    Log.d(TAG, "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = " +
+                            bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+                }
+            } while (sampleSize > 0);
+            int tid = android.os.Process.myTid();
+            File decodedFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+            FileOutputStream decodeOutputStream = new FileOutputStream(decodedFile);
+            Decoder decoder = new Decoder();
+            decoder.setupDecoder(decodeOutputStream);
+            status = decoder.decode(inputBuffer, frameInfo, false, format, "");
+            assertEquals("Decoder returned error " + status + " for file: " + mInputFile, 0,
+                    status);
+            MediaFormat decoderFormat = decoder.getFormat();
+            decoder.deInitCodec();
+            extractor.unselectExtractorTrack(currentTrack);
+            inputBuffer.clear();
+            frameInfo.clear();
+            if (decodeOutputStream != null) {
+                decodeOutputStream.close();
+            }
+            String mime = format.getString(MediaFormat.KEY_MIME);
+            ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
+            assertTrue("No suitable codecs found for file: " + mInputFile + " track : " +
+                    currentTrack + " mime: " + mime, (mediaCodecs.size() > 0));
+            Boolean[] encodeMode = {true, false};
+            /* Encoding the decoder's output */
+            for (Boolean asyncMode : encodeMode) {
+                for (String codecName : mediaCodecs) {
+                    FileOutputStream encodeOutputStream = null;
+                    if (WRITE_OUTPUT) {
+                        File outEncodeFile = new File(mOutputFilePath + "encoder.out");
+                        if (outEncodeFile.exists()) {
+                            assertTrue(" Unable to delete existing file" + outEncodeFile.toString(),
+                                    outEncodeFile.delete());
+                        }
+                        assertTrue("Unable to create file to write encoder output: " +
+                                outEncodeFile.toString(), outEncodeFile.createNewFile());
+                        encodeOutputStream = new FileOutputStream(outEncodeFile);
+                    }
+                    File rawFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+                    assertTrue("Cannot open file to write decoded output", rawFile.exists());
+                    if (DEBUG) {
+                        Log.i(TAG, "Path of decoded input file: " + rawFile.toString());
+                    }
+                    FileInputStream eleStream = new FileInputStream(rawFile);
+                    if (mime.startsWith("video/")) {
+                        width = format.getInteger(MediaFormat.KEY_WIDTH);
+                        height = format.getInteger(MediaFormat.KEY_HEIGHT);
+                        if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+                            frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+                        } else if (frameRate <= 0) {
+                            frameRate = ENCODE_DEFAULT_FRAME_RATE;
+                        }
+                        if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
+                            bitRate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+                        } else if (bitRate <= 0) {
+                            if (mime.contains("video/3gpp") || mime.contains("video/mp4v-es")) {
+                                bitRate = ENCODE_MIN_BIT_RATE;
+                            } else {
+                                bitRate = ENCODE_DEFAULT_BIT_RATE;
+                            }
+                        }
+                        if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                            profile = format.getInteger(MediaFormat.KEY_PROFILE);
+                        }
+                        if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                            level = format.getInteger(MediaFormat.KEY_LEVEL);
+                        }
+                        if (decoderFormat.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
+                            colorFormat = decoderFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+                        }
+                    } else {
+                        sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+                        numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+                        if (decoderFormat.containsKey(MediaFormat.KEY_BIT_RATE)) {
+                            bitRate = decoderFormat.getInteger(MediaFormat.KEY_BIT_RATE);
+                        } else {
+                            bitRate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
+                        }
+                    }
+                    /*Setup Encode Format*/
+                    MediaFormat encodeFormat;
+                    if (mime.startsWith("video/")) {
+                        frameSize = width * height * 3 / 2;
+                        encodeFormat = MediaFormat.createVideoFormat(mime, width, height);
+                        encodeFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+                        encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                        encodeFormat.setInteger(MediaFormat.KEY_PROFILE, profile);
+                        encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
+                        encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
+                        encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+                        encodeFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
+                    } else {
+                        encodeFormat = MediaFormat.createAudioFormat(mime, sampleRate, numChannels);
+                        encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                        frameSize = 4096;
+                    }
+                    Encoder encoder = new Encoder();
+                    encoder.setupEncoder(encodeOutputStream, eleStream);
+                    status = encoder.encode(codecName, encodeFormat, mime, frameRate, sampleRate,
+                            frameSize, asyncMode);
+                    encoder.deInitEncoder();
+                    assertEquals(
+                            codecName + " encoder returned error " + status + " for " + "file:" +
+                                    " " + mInputFile, 0, status);
+                    encoder.dumpStatistics(mInputFile, codecName, (asyncMode ? "async" : "sync"),
+                            extractor.getClipDuration(), mStatsFile);
+                    Log.i(TAG, "Encoding complete for file: " + mInputFile + " with codec: " +
+                            codecName + " for aSyncMode = " + asyncMode);
+                    encoder.resetEncoder();
+                    eleStream.close();
+                    if (encodeOutputStream != null) {
+                        encodeOutputStream.close();
+                    }
+
+                }
+            }
+            //Cleanup temporary input file
+            if (decodedFile.exists()) {
+                assertTrue(" Unable to delete decoded file" + decodedFile.toString(),
+                        decodedFile.delete());
+                Log.i(TAG, "Successfully deleted decoded file");
+            }
+        }
+        extractor.deinitExtractor();
+        fileInput.close();
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void testNativeEncoder() throws Exception {
+        File inputFile = new File(mInputFilePath + mInputFile);
+        assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
+                inputFile.exists());
+        int tid = android.os.Process.myTid();
+        final String mDecodedFile = mContext.getFilesDir() + "/decoder_" + tid + ".out";
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        Extractor extractor = new Extractor();
+        int trackCount = extractor.setUpExtractor(fileDescriptor);
+        assertTrue("Extraction failed. No tracks for file: ", trackCount > 0);
+        for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            extractor.selectExtractorTrack(currentTrack);
+            MediaFormat format = extractor.getFormat(currentTrack);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+            ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
+            // Encoding the decoder's output
+            for (String codecName : mediaCodecs) {
+                Native nativeEncoder = new Native();
+                int status = nativeEncoder
+                        .Encode(mInputFilePath, mInputFile, mDecodedFile, mStatsFile, codecName);
+                assertEquals(
+                        codecName + " encoder returned error " + status + " for " + "file:" + " " +
+                                mInputFile, 0, status);
+            }
+        }
+        File decodedFile = new File(mDecodedFile);
+        // Cleanup temporary input file
+        if (decodedFile.exists()) {
+            assertTrue("Unable to delete - " + mDecodedFile, decodedFile.delete());
+            Log.i(TAG, "Successfully deleted - " + mDecodedFile);
+        }
+        fileInput.close();
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
new file mode 100644
index 0000000..4d026c1
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/ExtractorTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.Extractor;
+import com.android.media.benchmark.library.Native;
+import com.android.media.benchmark.library.Stats;
+
+import android.content.Context;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Parameterized.class)
+public class ExtractorTest {
+    private static Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mStatsFile = mContext.getExternalFilesDir(null) + "/Extractor."
+            + System.currentTimeMillis() + ".csv";
+    private static final String TAG = "ExtractorTest";
+    private String mInputFileName;
+    private int mTrackId;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{/* Parameters: filename, trackId*/
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", 0},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", 0},
+                {"crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", 0},
+                {"crowd_1920x1080_25fps_4000kbps_av1.webm", 0},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", 0},
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", 0},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", 0},
+                {"bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0},
+                {"bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", 0},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", 0}});
+    }
+
+    public ExtractorTest(String filename, int track) {
+        this.mInputFileName = filename;
+        this.mTrackId = track;
+    }
+
+    @BeforeClass
+    public static void writeStatsHeaderToFile() throws IOException {
+        Stats mStats = new Stats();
+        boolean status = mStats.writeStatsHeader(mStatsFile);
+        assertTrue("Unable to open stats file for writing!", status);
+        Log.d(TAG, "Saving Benchmark results in: " + mStatsFile);
+    }
+
+    @Test
+    public void testExtractor() throws IOException {
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        Extractor extractor = new Extractor();
+        extractor.setUpExtractor(fileDescriptor);
+        MediaFormat format = extractor.getFormat(mTrackId);
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        int status = extractor.extractSample(mTrackId);
+        assertEquals("Extraction failed for " + mInputFileName, 0, status);
+        Log.i(TAG, "Extracted " + mInputFileName + " successfully.");
+        extractor.deinitExtractor();
+        extractor.dumpStatistics(mInputFileName, mime, mStatsFile);
+        fileInput.close();
+    }
+
+    @Test
+    public void testNativeExtractor() throws IOException {
+        Native nativeExtractor = new Native();
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        int status = nativeExtractor.Extract(mInputFilePath, mInputFileName, mStatsFile);
+        fileInput.close();
+        assertEquals("Extraction failed for " + mInputFileName, 0, status);
+        Log.i(TAG, "Extracted " + mInputFileName + " successfully.");
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
new file mode 100644
index 0000000..21ba957
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.tests;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.Extractor;
+import com.android.media.benchmark.library.Muxer;
+import com.android.media.benchmark.library.Native;
+import com.android.media.benchmark.library.Stats;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.util.Log;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Parameterized.class)
+public class MuxerTest {
+    private static Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mStatsFile =
+            mContext.getExternalFilesDir(null) + "/Muxer." + System.currentTimeMillis() + ".csv";
+    private static final String TAG = "MuxerTest";
+    private static final Map<String, Integer> mMapFormat = new Hashtable<String, Integer>() {
+        {
+            put("mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+            put("webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
+            put("3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
+            put("ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
+        }
+    };
+    private String mInputFileName;
+    private String mFormat;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{
+                /* Parameters: filename, format */
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm", "webm"},
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm", "webm"},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mp4"},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", "mp4"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", "mp4"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", "mp4"},
+                {"crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "3gpp"},
+                {"crowd_352x288_25fps_6000kbps_h263.3gp", "3gpp"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"},
+                {"bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", "webm"},
+                {"bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "mp4"},
+                {"bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "3gpp"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "3gpp"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp"}});
+    }
+
+    public MuxerTest(String filename, String outputFormat) {
+        this.mInputFileName = filename;
+        this.mFormat = outputFormat;
+    }
+
+    @BeforeClass
+    public static void writeStatsHeaderToFile() throws IOException {
+        Stats mStats = new Stats();
+        boolean status = mStats.writeStatsHeader(mStatsFile);
+        assertTrue("Unable to open stats file for writing!", status);
+        Log.d(TAG, "Saving Benchmark results in: " + mStatsFile);
+    }
+
+    @Test
+    public void testMuxer() throws IOException {
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
+                inputFile.exists());
+        FileInputStream fileInput = new FileInputStream(inputFile);
+        FileDescriptor fileDescriptor = fileInput.getFD();
+        ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+        ArrayList<MediaCodec.BufferInfo> inputBufferInfo = new ArrayList<>();
+        Extractor extractor = new Extractor();
+        int trackCount = extractor.setUpExtractor(fileDescriptor);
+        for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+            extractor.selectExtractorTrack(currentTrack);
+            while (true) {
+                int sampleSize = extractor.getFrameSample();
+                MediaCodec.BufferInfo bufferInfo = extractor.getBufferInfo();
+                MediaCodec.BufferInfo tempBufferInfo = new MediaCodec.BufferInfo();
+                tempBufferInfo
+                        .set(bufferInfo.offset, bufferInfo.size, bufferInfo.presentationTimeUs,
+                                bufferInfo.flags);
+                inputBufferInfo.add(tempBufferInfo);
+                ByteBuffer tempSampleBuffer = ByteBuffer.allocate(tempBufferInfo.size);
+                tempSampleBuffer.put(extractor.getFrameBuffer().array(), 0, bufferInfo.size);
+                inputBuffer.add(tempSampleBuffer);
+                if (sampleSize < 0) {
+                    break;
+                }
+            }
+            MediaFormat format = extractor.getFormat(currentTrack);
+            int outputFormat = mMapFormat.getOrDefault(mFormat, -1);
+            assertNotEquals("Test failed for " + mInputFileName + ". Returned invalid " +
+                    "output format for given " + mFormat + " format.", -1, outputFormat);
+            Muxer muxer = new Muxer();
+            int trackIndex = muxer.setUpMuxer(mContext, outputFormat, format);
+            int status = muxer.mux(trackIndex, inputBuffer, inputBufferInfo);
+            assertEquals("Cannot perform write operation for " + mInputFileName, 0, status);
+            Log.i(TAG, "Muxed " + mInputFileName + " successfully.");
+            muxer.deInitMuxer();
+            muxer.dumpStatistics(mInputFileName, mFormat, extractor.getClipDuration(), mStatsFile);
+            muxer.resetMuxer();
+            extractor.unselectExtractorTrack(currentTrack);
+            inputBufferInfo.clear();
+            inputBuffer.clear();
+
+        }
+        extractor.deinitExtractor();
+        fileInput.close();
+    }
+
+    @Test
+    public void testNativeMuxer() {
+        Native nativeMuxer = new Native();
+        File inputFile = new File(mInputFilePath + mInputFileName);
+        assertTrue("Cannot find " + mInputFileName + " in directory " + mInputFilePath,
+                inputFile.exists());
+        int tid = android.os.Process.myTid();
+        String mMuxOutputFile = (mContext.getFilesDir() + "/mux_" + tid + ".out");
+        int status = nativeMuxer.Mux(
+                mInputFilePath, mInputFileName, mMuxOutputFile, mStatsFile, mFormat);
+        assertEquals("Cannot perform write operation for " + mInputFileName, 0, status);
+        Log.i(TAG, "Muxed " + mInputFileName + " successfully.");
+        File muxedFile = new File(mMuxOutputFile);
+        // Cleanup temporary output file
+        if (muxedFile.exists()) {
+            assertTrue("Unable to delete" + mMuxOutputFile + " file.",
+                    muxedFile.delete());
+        }
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
new file mode 100644
index 0000000..3e5e4c8
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
@@ -0,0 +1,33 @@
+cc_test_library {
+    name: "libmediabenchmark_jni",
+    sdk_version: "current",
+
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: [
+        "NativeExtractor.cpp",
+        "NativeMuxer.cpp",
+        "NativeEncoder.cpp",
+        "NativeDecoder.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+    ],
+
+    static_libs: [
+        "libmediabenchmark_common",
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_muxer",
+        "libmediabenchmark_decoder",
+        "libmediabenchmark_encoder",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/CMakeLists.txt b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000..5823883
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2019 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.
+#
+
+cmake_minimum_required(VERSION 3.4.1)
+
+set(native_source_path "../../../../src/native")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
+
+add_library(
+  mediabenchmark_jni SHARED
+  NativeExtractor.cpp
+  NativeMuxer.cpp
+  NativeDecoder.cpp
+  NativeEncoder.cpp
+  ${native_source_path}/common/BenchmarkCommon.cpp
+  ${native_source_path}/common/Stats.cpp
+  ${native_source_path}/common/utils/Timers.cpp
+  ${native_source_path}/extractor/Extractor.cpp
+  ${native_source_path}/muxer/Muxer.cpp
+  ${native_source_path}/decoder/Decoder.cpp
+  ${native_source_path}/encoder/Encoder.cpp)
+
+include_directories(${native_source_path}/common)
+include_directories(${native_source_path}/extractor)
+include_directories(${native_source_path}/muxer)
+include_directories(${native_source_path}/decoder)
+include_directories(${native_source_path}/encoder)
+
+find_library(log-lib log)
+
+target_link_libraries(mediabenchmark_jni mediandk ${log-lib})
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
new file mode 100644
index 0000000..043bc9e
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 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 "NativeDecoder"
+
+#include <jni.h>
+#include <fstream>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <android/log.h>
+
+#include "Decoder.h"
+
+extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Decode(
+        JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jStatsFile,
+        jstring jCodecName, jboolean asyncMode) {
+    const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
+    const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
+    string sFilePath = string(filePath) + string(fileName);
+    UNUSED(thiz);
+    FILE *inputFp = fopen(sFilePath.c_str(), "rb");
+    env->ReleaseStringUTFChars(jFileName, fileName);
+    env->ReleaseStringUTFChars(jFilePath, filePath);
+    if (!inputFp) {
+        ALOGE("Unable to open input file for reading");
+        return -1;
+    }
+
+    Decoder *decoder = new Decoder();
+    Extractor *extractor = decoder->getExtractor();
+    if (!extractor) {
+        ALOGE("Extractor creation failed");
+        return -1;
+    }
+
+    // Read file properties
+    struct stat buf;
+    stat(sFilePath.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    if (fileSize > kMaxBufferSize) {
+        ALOGE("File size greater than maximum buffer size");
+        return -1;
+    }
+    int32_t fd = fileno(inputFp);
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    if (trackCount <= 0) {
+        ALOGE("initExtractor failed");
+        return -1;
+    }
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        if (status != 0) {
+            ALOGE("Track Format invalid");
+            return -1;
+        }
+
+        uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
+        if (!inputBuffer) {
+            ALOGE("Insufficient memory");
+            return -1;
+        }
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            if (inputBufferOffset + info.size > kMaxBufferSize) {
+                ALOGE("Memory allocated not sufficient");
+                free(inputBuffer);
+                return -1;
+            }
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        const char *codecName = env->GetStringUTFChars(jCodecName, nullptr);
+        string sCodecName = string(codecName);
+        decoder->setupDecoder();
+        status = decoder->decode(inputBuffer, frameInfo, sCodecName, asyncMode);
+        if (status != AMEDIA_OK) {
+            ALOGE("Decode returned error");
+            free(inputBuffer);
+            env->ReleaseStringUTFChars(jCodecName, codecName);
+            return -1;
+        }
+        decoder->deInitCodec();
+        const char *inputReference = env->GetStringUTFChars(jFileName, nullptr);
+        const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
+        string sInputReference = string(inputReference);
+        decoder->dumpStatistics(sInputReference, sCodecName, (asyncMode ? "async" : "sync"),
+                                statsFile);
+        env->ReleaseStringUTFChars(jCodecName, codecName);
+        env->ReleaseStringUTFChars(jStatsFile, statsFile);
+        env->ReleaseStringUTFChars(jFileName, inputReference);
+        if (inputBuffer) {
+            free(inputBuffer);
+            inputBuffer = nullptr;
+        }
+        decoder->resetDecoder();
+    }
+    if (inputFp) {
+        fclose(inputFp);
+        inputFp = nullptr;
+    }
+    extractor->deInitExtractor();
+    delete decoder;
+    return 0;
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
new file mode 100644
index 0000000..1277c8b
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 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 "NativeEncoder"
+
+#include <jni.h>
+#include <sys/stat.h>
+#include <fstream>
+#include <iostream>
+
+#include <android/log.h>
+
+#include "Decoder.h"
+#include "Encoder.h"
+
+#include <stdio.h>
+
+constexpr int32_t ENCODE_DEFAULT_FRAME_RATE = 25;
+constexpr int32_t ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
+constexpr int32_t ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+constexpr int32_t ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
+extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Encode(
+        JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jOutFilePath,
+        jstring jStatsFile, jstring jCodecName) {
+    const char *filePath = env->GetStringUTFChars(jFilePath, nullptr);
+    const char *fileName = env->GetStringUTFChars(jFileName, nullptr);
+    string sFilePath = string(filePath) + string(fileName);
+    UNUSED(thiz);
+    FILE *inputFp = fopen(sFilePath.c_str(), "rb");
+    env->ReleaseStringUTFChars(jFileName, fileName);
+    env->ReleaseStringUTFChars(jFilePath, filePath);
+    if (!inputFp) {
+        ALOGE("Unable to open input file for reading");
+        return -1;
+    }
+
+    Decoder *decoder = new Decoder();
+    Extractor *extractor = decoder->getExtractor();
+    if (!extractor) {
+        ALOGE("Extractor creation failed");
+        return -1;
+    }
+
+    // Read file properties
+    struct stat buf;
+    stat(sFilePath.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    if (fileSize > kMaxBufferSize) {
+        ALOGE("File size greater than maximum buffer size");
+        return -1;
+    }
+    int32_t fd = fileno(inputFp);
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    if (trackCount <= 0) {
+        ALOGE("initExtractor failed");
+        return -1;
+    }
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        if (status != 0) {
+            ALOGE("Track Format invalid");
+            return -1;
+        }
+        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        if (!inputBuffer) {
+            ALOGE("Insufficient memory");
+            return -1;
+        }
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            if (inputBufferOffset + info.size > kMaxBufferSize) {
+                ALOGE("Memory allocated not sufficient");
+                free(inputBuffer);
+                return -1;
+            }
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+        string decName = "";
+        const char *outputFilePath = env->GetStringUTFChars(jOutFilePath, nullptr);
+        FILE *outFp = fopen(outputFilePath, "wb");
+        if (outFp == nullptr) {
+            ALOGE("%s - File failed to open for writing!", outputFilePath);
+            free(inputBuffer);
+            return -1;
+        }
+        decoder->setupDecoder();
+        status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+        if (status != AMEDIA_OK) {
+            ALOGE("Decode returned error");
+            free(inputBuffer);
+            return -1;
+        }
+
+        AMediaFormat *decoderFormat = decoder->getFormat();
+        AMediaFormat *format = extractor->getFormat();
+        if (inputBuffer) {
+            free(inputBuffer);
+            inputBuffer = nullptr;
+        }
+        const char *mime = nullptr;
+        AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+        if (!mime) {
+            ALOGE("Error in AMediaFormat_getString");
+            return -1;
+        }
+        ifstream eleStream;
+        eleStream.open(outputFilePath, ifstream::binary | ifstream::ate);
+        if (!eleStream.is_open()) {
+            ALOGE("%s - File failed to open for reading!", outputFilePath);
+            env->ReleaseStringUTFChars(jOutFilePath, outputFilePath);
+            return -1;
+        }
+        const char *codecName = env->GetStringUTFChars(jCodecName, NULL);
+        const char *inputReference = env->GetStringUTFChars(jFileName, nullptr);
+        string sCodecName = string(codecName);
+        string sInputReference = string(inputReference);
+
+        bool asyncMode[2] = {true, false};
+        for (int i = 0; i < 2; i++) {
+            size_t eleSize = eleStream.tellg();
+            eleStream.seekg(0, ifstream::beg);
+
+            // Get encoder params
+            encParameter encParams;
+            if (!strncmp(mime, "video/", 6)) {
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &encParams.width);
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &encParams.height);
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
+                if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
+                    encParams.frameRate = ENCODE_DEFAULT_FRAME_RATE;
+                    if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
+                        encParams.bitrate = ENCODE_MIN_BIT_RATE /* 600 Kbps */;
+                    } else {
+                        encParams.bitrate = ENCODE_DEFAULT_BIT_RATE /* 8 Mbps */;
+                    }
+                }
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
+                AMediaFormat_getInt32(decoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
+                                      &encParams.colorFormat);
+            } else {
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &encParams.sampleRate);
+                AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
+                                      &encParams.numChannels);
+                encParams.bitrate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
+            }
+            Encoder *encoder = new Encoder();
+            encoder->setupEncoder();
+            status = encoder->encode(sCodecName, eleStream, eleSize, asyncMode[i], encParams,
+                                     (char *)mime);
+            if (status != AMEDIA_OK) {
+                ALOGE("Encoder returned error");
+                return -1;
+            }
+            ALOGV("Encoding complete with codec %s for asyncMode = %d", sCodecName.c_str(),
+                  asyncMode[i]);
+            encoder->deInitCodec();
+            const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
+            encoder->dumpStatistics(sInputReference, extractor->getClipDuration(), sCodecName,
+                                    (asyncMode[i] ? "async" : "sync"), statsFile);
+            env->ReleaseStringUTFChars(jStatsFile, statsFile);
+            encoder->resetEncoder();
+            delete encoder;
+            encoder = nullptr;
+        }
+        eleStream.close();
+        if (outFp) {
+            fclose(outFp);
+            outFp = nullptr;
+        }
+        env->ReleaseStringUTFChars(jFileName, inputReference);
+        env->ReleaseStringUTFChars(jCodecName, codecName);
+        env->ReleaseStringUTFChars(jOutFilePath, outputFilePath);
+        if (format) {
+            AMediaFormat_delete(format);
+            format = nullptr;
+        }
+        if (decoderFormat) {
+            AMediaFormat_delete(decoderFormat);
+            decoderFormat = nullptr;
+        }
+        decoder->deInitCodec();
+        decoder->resetDecoder();
+    }
+    if (inputFp) {
+        fclose(inputFp);
+        inputFp = nullptr;
+    }
+    extractor->deInitExtractor();
+    delete decoder;
+    return 0;
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeExtractor.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeExtractor.cpp
new file mode 100644
index 0000000..a762760
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeExtractor.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 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 "NativeExtractor"
+
+#include <jni.h>
+#include <fstream>
+#include <string>
+#include <sys/stat.h>
+
+#include "Extractor.h"
+
+extern "C" JNIEXPORT int32_t JNICALL Java_com_android_media_benchmark_library_Native_Extract(
+        JNIEnv *env, jobject thiz, jstring jInputFilePath, jstring jInputFileName,
+        jstring jStatsFile) {
+    UNUSED(thiz);
+    const char *inputFilePath = env->GetStringUTFChars(jInputFilePath, nullptr);
+    const char *inputFileName = env->GetStringUTFChars(jInputFileName, nullptr);
+    string sFilePath = string(inputFilePath) + string(inputFileName);
+    FILE *inputFp = fopen(sFilePath.c_str(), "rb");
+
+    // Read file properties
+    struct stat buf;
+    stat(sFilePath.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    Extractor *extractObj = new Extractor();
+    int32_t trackCount = extractObj->initExtractor((long) fd, fileSize);
+    if (trackCount <= 0) {
+        ALOGE("initExtractor failed");
+        return -1;
+    }
+
+    int32_t trackID = 0;
+    const char *mime = nullptr;
+    int32_t status = extractObj->extract(trackID);
+    if (status != AMEDIA_OK) {
+        ALOGE("Extraction failed");
+        return -1;
+    }
+
+    if (inputFp) {
+        fclose(inputFp);
+        inputFp = nullptr;
+    }
+    status = extractObj->setupTrackFormat(trackID);
+    AMediaFormat *format = extractObj->getFormat();
+    if (!format) {
+        ALOGE("format is null!");
+        return -1;
+    }
+    AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+    if (!mime) {
+        ALOGE("mime is null!");
+        return -1;
+    }
+    extractObj->deInitExtractor();
+    const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
+    extractObj->dumpStatistics(string(inputFileName), string(mime), statsFile);
+    env->ReleaseStringUTFChars(jStatsFile, statsFile);
+    env->ReleaseStringUTFChars(jInputFilePath, inputFilePath);
+    env->ReleaseStringUTFChars(jInputFileName, inputFileName);
+
+    delete extractObj;
+    return status;
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
new file mode 100644
index 0000000..a5ef5b8
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2019 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 "NativeMuxer"
+
+#include <jni.h>
+#include <fstream>
+#include <string>
+#include <sys/stat.h>
+
+#include "Muxer.h"
+
+MUXER_OUTPUT_T getMuxerOutFormat(const char *fmt);
+
+extern "C" JNIEXPORT int32_t JNICALL Java_com_android_media_benchmark_library_Native_Mux(
+        JNIEnv *env, jobject thiz, jstring jInputFilePath, jstring jInputFileName,
+        jstring jOutputFilePath, jstring jStatsFile, jstring jFormat) {
+    UNUSED(thiz);
+    ALOGV("Mux the samples given by extractor");
+    const char *inputFilePath = env->GetStringUTFChars(jInputFilePath, nullptr);
+    const char *inputFileName = env->GetStringUTFChars(jInputFileName, nullptr);
+    string sInputFile = string(inputFilePath) + string(inputFileName);
+    FILE *inputFp = fopen(sInputFile.c_str(), "rb");
+    if (!inputFp) {
+        ALOGE("Unable to open input file for reading");
+        return -1;
+    }
+
+    const char *fmt = env->GetStringUTFChars(jFormat, nullptr);
+    MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
+    if (outputFormat == MUXER_OUTPUT_FORMAT_INVALID) {
+        ALOGE("output format is MUXER_OUTPUT_FORMAT_INVALID");
+        return MUXER_OUTPUT_FORMAT_INVALID;
+    }
+
+    Muxer *muxerObj = new Muxer();
+    Extractor *extractor = muxerObj->getExtractor();
+    if (!extractor) {
+        ALOGE("Extractor creation failed");
+        return -1;
+    }
+
+    // Read file properties
+    struct stat buf;
+    stat(sInputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    if (trackCount <= 0) {
+        ALOGE("initExtractor failed");
+        return -1;
+    }
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        if (status != 0) {
+            ALOGE("Track Format invalid");
+            return -1;
+        }
+
+        uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
+        if (!inputBuffer) {
+            ALOGE("Allocation Failed");
+            return -1;
+        }
+        vector<AMediaCodecBufferInfo> frameInfos;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get Frame Data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to muxer
+            if (inputBufferOffset + info.size > fileSize) {
+                ALOGE("Memory allocated not sufficient");
+                if (inputBuffer) {
+                    free(inputBuffer);
+                    inputBuffer = nullptr;
+                }
+                return -1;
+            }
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(),
+                   static_cast<size_t>(info.size));
+            info.offset = inputBufferOffset;
+            frameInfos.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        const char *outputFilePath = env->GetStringUTFChars(jOutputFilePath, nullptr);
+        FILE *outputFp = fopen(((string) outputFilePath).c_str(), "w+b");
+        env->ReleaseStringUTFChars(jOutputFilePath, outputFilePath);
+
+        if (!outputFp) {
+            ALOGE("Unable to open output file for writing");
+            if (inputBuffer) {
+                free(inputBuffer);
+                inputBuffer = nullptr;
+            }
+            return -1;
+        }
+        int32_t outFd = fileno(outputFp);
+
+        status = muxerObj->initMuxer(outFd, (MUXER_OUTPUT_T) outputFormat);
+        if (status != 0) {
+            ALOGE("initMuxer failed");
+            if (inputBuffer) {
+                free(inputBuffer);
+                inputBuffer = nullptr;
+            }
+            return -1;
+        }
+
+        status = muxerObj->mux(inputBuffer, frameInfos);
+        if (status != 0) {
+            ALOGE("Mux failed");
+            if (inputBuffer) {
+                free(inputBuffer);
+                inputBuffer = nullptr;
+            }
+            return -1;
+        }
+        muxerObj->deInitMuxer();
+        const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
+        string muxFormat(fmt);
+        muxerObj->dumpStatistics(string(inputFileName), muxFormat, statsFile);
+        env->ReleaseStringUTFChars(jStatsFile, statsFile);
+        env->ReleaseStringUTFChars(jInputFilePath, inputFilePath);
+        env->ReleaseStringUTFChars(jInputFileName, inputFileName);
+
+        if (inputBuffer) {
+            free(inputBuffer);
+            inputBuffer = nullptr;
+        }
+        if (outputFp) {
+            fclose(outputFp);
+            outputFp = nullptr;
+        }
+        muxerObj->resetMuxer();
+    }
+    if (inputFp) {
+        fclose(inputFp);
+        inputFp = nullptr;
+    }
+    env->ReleaseStringUTFChars(jFormat, fmt);
+    extractor->deInitExtractor();
+    delete muxerObj;
+
+    return 0;
+}
+
+MUXER_OUTPUT_T getMuxerOutFormat(const char *fmt) {
+    static const struct {
+        const char *name;
+        int value;
+    } kFormatMaps[] = {{"mp4",  MUXER_OUTPUT_FORMAT_MPEG_4},
+                       {"webm", MUXER_OUTPUT_FORMAT_WEBM},
+                       {"3gpp", MUXER_OUTPUT_FORMAT_3GPP},
+                       {"ogg",  MUXER_OUTPUT_FORMAT_OGG}};
+
+    int32_t muxOutputFormat = MUXER_OUTPUT_FORMAT_INVALID;
+    for (auto kFormatMap : kFormatMaps) {
+        if (!strcmp(fmt, kFormatMap.name)) {
+            muxOutputFormat = kFormatMap.value;
+            break;
+        }
+    }
+    return (MUXER_OUTPUT_T) muxOutputFormat;
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
new file mode 100644
index 0000000..08035c9
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
@@ -0,0 +1,39 @@
+package com.android.media.benchmark.library;
+
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.os.Build;
+
+import java.util.ArrayList;
+
+public class CodecUtils {
+    private CodecUtils() {}
+
+    /**
+     * Queries the MediaCodecList and returns codec names of supported codecs.
+     *
+     * @param mimeType  Mime type of input
+     * @param isEncoder Specifies encoder or decoder
+     * @return ArrayList of codec names
+     */
+    public static ArrayList<String> selectCodecs(String mimeType, boolean isEncoder) {
+        MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+        ArrayList<String> supportedCodecs = new ArrayList<>();
+        for (MediaCodecInfo codecInfo : codecInfos) {
+            if (isEncoder != codecInfo.isEncoder()) {
+                continue;
+            }
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) {
+                continue;
+            }
+            String[] types = codecInfo.getSupportedTypes();
+            for (String type : types) {
+                if (type.equalsIgnoreCase(mimeType)) {
+                    supportedCodecs.add(codecInfo.getName());
+                }
+            }
+        }
+        return supportedCodecs;
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
new file mode 100644
index 0000000..66fee33
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+public class Decoder {
+    private static final String TAG = "Decoder";
+    private static final boolean DEBUG = false;
+    private static final int kQueueDequeueTimeoutUs = 1000;
+
+    private final Object mLock = new Object();
+    private MediaCodec mCodec;
+    private ArrayList<BufferInfo> mInputBufferInfo;
+    private Stats mStats;
+
+    private boolean mSawInputEOS;
+    private boolean mSawOutputEOS;
+    private boolean mSignalledError;
+
+    private int mNumOutputFrame;
+    private int mIndex;
+
+    private ArrayList<ByteBuffer> mInputBuffer;
+    private FileOutputStream mOutputStream;
+
+    public Decoder() { mStats = new Stats(); }
+
+    /**
+     * Setup of decoder
+     *
+     * @param outputStream Will dump the output in this stream if not null.
+     */
+    public void setupDecoder(FileOutputStream outputStream) {
+        mSignalledError = false;
+        mOutputStream = outputStream;
+    }
+
+    private MediaCodec createCodec(String codecName, MediaFormat format) throws IOException {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        try {
+            MediaCodec codec;
+            if (codecName.isEmpty()) {
+                Log.i(TAG, "File mime type: " + mime);
+                if (mime != null) {
+                    codec = MediaCodec.createDecoderByType(mime);
+                    Log.i(TAG, "Decoder created for mime type " + mime);
+                    return codec;
+                } else {
+                    Log.e(TAG, "Mime type is null, please specify a mime type to create decoder");
+                    return null;
+                }
+            } else {
+                codec = MediaCodec.createByCodecName(codecName);
+                Log.i(TAG, "Decoder created with codec name: " + codecName + " mime: " + mime);
+                return codec;
+            }
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            Log.e(TAG, "Failed to create decoder for " + codecName + " mime:" + mime);
+            return null;
+        }
+    }
+
+    /**
+     * Decodes the given input buffer,
+     * provided valid list of buffer info and format are passed as inputs.
+     *
+     * @param inputBuffer     Decode the provided list of ByteBuffers
+     * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+     * @param asyncMode       Will run on async implementation if true
+     * @param format          For creating the decoder if codec name is empty and configuring it
+     * @param codecName       Will create the decoder with codecName
+     * @return 0 if decode was successful , -1 for fail, -2 for decoder not created
+     * @throws IOException if the codec cannot be created.
+     */
+    public int decode(@NonNull ArrayList<ByteBuffer> inputBuffer,
+            @NonNull ArrayList<BufferInfo> inputBufferInfo, final boolean asyncMode,
+            @NonNull MediaFormat format, String codecName) throws IOException {
+        mInputBuffer = new ArrayList<>(inputBuffer.size());
+        mInputBuffer.addAll(inputBuffer);
+        mInputBufferInfo = new ArrayList<>(inputBufferInfo.size());
+        mInputBufferInfo.addAll(inputBufferInfo);
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mNumOutputFrame = 0;
+        mIndex = 0;
+        long sTime = mStats.getCurTime();
+        mCodec = createCodec(codecName, format);
+        if (mCodec == null) {
+            return -2;
+        }
+        if (asyncMode) {
+            mCodec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(
+                        @NonNull MediaCodec mediaCodec, int inputBufferId) {
+                    try {
+                        mStats.addInputTime();
+                        onInputAvailable(inputBufferId, mediaCodec);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.e(TAG, e.toString());
+                    }
+                }
+
+                @Override
+                public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                        int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+                    mStats.addOutputTime();
+                    onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+                    if (mSawOutputEOS) {
+                        synchronized (mLock) { mLock.notify(); }
+                    }
+                }
+
+                @Override
+                public void onOutputFormatChanged(
+                        @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+                    Log.i(TAG, "Output format changed. Format: " + format.toString());
+                }
+
+                @Override
+                public void onError(
+                        @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+                    mSignalledError = true;
+                    Log.e(TAG, "Codec Error: " + e.toString());
+                    e.printStackTrace();
+                    synchronized (mLock) { mLock.notify(); }
+                }
+            });
+        }
+        int isEncoder = 0;
+        if (DEBUG) {
+            Log.d(TAG, "Media Format : " + format.toString());
+        }
+        mCodec.configure(format, null, null, isEncoder);
+        mCodec.start();
+        Log.i(TAG, "Codec started ");
+        long eTime = mStats.getCurTime();
+        mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+        mStats.setStartTime();
+        if (asyncMode) {
+            try {
+                synchronized (mLock) { mLock.wait(); }
+                if (mSignalledError) {
+                    return -1;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        } else {
+            while (!mSawOutputEOS && !mSignalledError) {
+                /* Queue input data */
+                if (!mSawInputEOS) {
+                    int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+                    if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG,
+                                "MediaCodec.dequeueInputBuffer "
+                                        + " returned invalid index : " + inputBufferId);
+                        return -1;
+                    }
+                    mStats.addInputTime();
+                    onInputAvailable(inputBufferId, mCodec);
+                }
+                /* Dequeue output data */
+                BufferInfo outputBufferInfo = new BufferInfo();
+                int outputBufferId =
+                        mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+                if (outputBufferId < 0) {
+                    if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        MediaFormat outFormat = mCodec.getOutputFormat();
+                        Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+                    } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                        Log.i(TAG, "Ignoring deprecated flag: INFO_OUTPUT_BUFFERS_CHANGED");
+                    } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG,
+                                "MediaCodec.dequeueOutputBuffer"
+                                        + " returned invalid index " + outputBufferId);
+                        return -1;
+                    }
+                } else {
+                    mStats.addOutputTime();
+                    if (DEBUG) {
+                        Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+                    }
+                    onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+                }
+            }
+        }
+        mInputBuffer.clear();
+        mInputBufferInfo.clear();
+        return 0;
+    }
+
+    /**
+     * Stops the codec and releases codec resources.
+     */
+    public void deInitCodec() {
+        long sTime = mStats.getCurTime();
+        if (mCodec != null) {
+            mCodec.stop();
+            mCodec.release();
+            mCodec = null;
+        }
+        long eTime = mStats.getCurTime();
+        mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+    }
+
+    /**
+     * Prints out the statistics in the information log
+     *
+     * @param inputReference The operation being performed, in this case decode
+     * @param componentName  Name of the component/codec
+     * @param mode           The operating mode: Sync/Async
+     * @param durationUs     Duration of the clip in microseconds
+     * @param statsFile      The output file where the stats data is written
+     */
+    public void dumpStatistics(String inputReference, String componentName, String mode,
+            long durationUs, String statsFile) throws IOException {
+        String operation = "decode";
+        mStats.dumpStatistics(
+                inputReference, operation, componentName, mode, durationUs, statsFile);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetDecoder() { mStats.reset(); }
+
+    /**
+     * Returns the format of the output buffers
+     */
+    public MediaFormat getFormat() {
+        return mCodec.getOutputFormat();
+    }
+
+    private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
+        if ((inputBufferId >= 0) && !mSawInputEOS) {
+            ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
+            BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
+            inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+            mIndex++;
+            mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+            if (mSawInputEOS) {
+                Log.i(TAG, "Saw input EOS");
+            }
+            mStats.addFrameSize(bufInfo.size);
+            mediaCodec.queueInputBuffer(inputBufferId, bufInfo.offset, bufInfo.size,
+                    bufInfo.presentationTimeUs, bufInfo.flags);
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Codec Input: "
+                                + "flag = " + bufInfo.flags + " timestamp = "
+                                + bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+            }
+        }
+    }
+
+    private void onOutputAvailable(
+            MediaCodec mediaCodec, int outputBufferId, BufferInfo outputBufferInfo) {
+        if (mSawOutputEOS || outputBufferId < 0) {
+            return;
+        }
+        mNumOutputFrame++;
+        if (DEBUG) {
+            Log.d(TAG,
+                    "In OutputBufferAvailable ,"
+                            + " output frame number = " + mNumOutputFrame);
+        }
+        if (mOutputStream != null) {
+            try {
+                ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+                byte[] bytesOutput = new byte[outputBuffer.remaining()];
+                outputBuffer.get(bytesOutput);
+                mOutputStream.write(bytesOutput);
+            } catch (IOException e) {
+                e.printStackTrace();
+                Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+            }
+        }
+        mediaCodec.releaseOutputBuffer(outputBufferId, false);
+        mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+        if (mSawOutputEOS) {
+            Log.i(TAG, "Saw output EOS");
+        }
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
new file mode 100644
index 0000000..45e5574
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Encoder {
+    // Change in AUDIO_ENCODE_DEFAULT_MAX_INPUT_SIZE should also be taken to
+    // kDefaultAudioEncodeFrameSize present in BenchmarkCommon.h
+    private static final int AUDIO_ENCODE_DEFAULT_MAX_INPUT_SIZE = 4096;
+    private static final String TAG = "Encoder";
+    private static final boolean DEBUG = false;
+    private static final int kQueueDequeueTimeoutUs = 1000;
+
+    private final Object mLock = new Object();
+    private MediaCodec mCodec;
+    private String mMime;
+    private Stats mStats;
+
+    private int mOffset;
+    private int mFrameSize;
+    private int mNumInputFrame;
+    private int mNumFrames;
+    private int mFrameRate;
+    private int mSampleRate;
+    private long mInputBufferSize;
+
+    private boolean mSawInputEOS;
+    private boolean mSawOutputEOS;
+    private boolean mSignalledError;
+
+    private FileInputStream mInputStream;
+    private FileOutputStream mOutputStream;
+
+    public Encoder() {
+        mStats = new Stats();
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+    }
+
+    /**
+     * Setup of encoder
+     *
+     * @param encoderOutputStream Will dump the encoder output in this stream if not null.
+     * @param fileInputStream     Will read the decoded output from this stream
+     */
+    public void setupEncoder(FileOutputStream encoderOutputStream,
+                             FileInputStream fileInputStream) {
+        this.mInputStream = fileInputStream;
+        this.mOutputStream = encoderOutputStream;
+    }
+
+    private MediaCodec createCodec(String codecName, String mime) throws IOException {
+        try {
+            MediaCodec codec;
+            if (codecName.isEmpty()) {
+                Log.i(TAG, "Mime type: " + mime);
+                if (mime != null) {
+                    codec = MediaCodec.createEncoderByType(mime);
+                    Log.i(TAG, "Encoder created for mime type " + mime);
+                    return codec;
+                } else {
+                    Log.e(TAG, "Mime type is null, please specify a mime type to create encoder");
+                    return null;
+                }
+            } else {
+                codec = MediaCodec.createByCodecName(codecName);
+                Log.i(TAG, "Encoder created with codec name: " + codecName + " and mime: " + mime);
+                return codec;
+            }
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            Log.e(TAG, "Failed to create encoder for " + codecName + " mime: " + mime);
+            return null;
+        }
+    }
+
+    /**
+     * Encodes the given raw input file and measures the performance of encode operation,
+     * provided a valid list of parameters are passed as inputs.
+     *
+     * @param codecName    Will create the encoder with codecName
+     * @param mime         For creating encode format
+     * @param encodeFormat Format of the output data
+     * @param frameSize    Size of the frame
+     * @param asyncMode    Will run on async implementation if true
+     * @return 0 if encode was successful , -1 for fail, -2 for encoder not created
+     * @throws IOException If the codec cannot be created.
+     */
+    public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
+                      int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+        mInputBufferSize = mInputStream.getChannel().size();
+        mMime = mime;
+        mOffset = 0;
+        mFrameRate = frameRate;
+        mSampleRate = sampleRate;
+        long sTime = mStats.getCurTime();
+        mCodec = createCodec(codecName, mime);
+        if (mCodec == null) {
+            return -2;
+        }
+        /*Configure Codec*/
+        try {
+            mCodec.configure(encodeFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        } catch (IllegalArgumentException | IllegalStateException | MediaCodec.CryptoException e) {
+            Log.e(TAG, "Failed to configure " + mCodec.getName() + " encoder.");
+            e.printStackTrace();
+            return -2;
+        }
+        if (mMime.startsWith("video/")) {
+            mFrameSize = frameSize;
+        } else {
+            int maxInputSize = AUDIO_ENCODE_DEFAULT_MAX_INPUT_SIZE;
+            MediaFormat format = mCodec.getInputFormat();
+            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+                maxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+            }
+            mFrameSize = frameSize;
+            if (mFrameSize > maxInputSize && maxInputSize > 0) {
+                mFrameSize = maxInputSize;
+            }
+        }
+        mNumFrames = (int) ((mInputBufferSize + mFrameSize - 1) / mFrameSize);
+        if (asyncMode) {
+            mCodec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                   int inputBufferId) {
+                    try {
+                        mStats.addInputTime();
+                        onInputAvailable(mediaCodec, inputBufferId);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.e(TAG, e.toString());
+                    }
+                }
+
+                @Override
+                public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                    int outputBufferId,
+                                                    @NonNull MediaCodec.BufferInfo bufferInfo) {
+                    mStats.addOutputTime();
+                    onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+                    if (mSawOutputEOS) {
+                        Log.i(TAG, "Saw output EOS");
+                        synchronized (mLock) { mLock.notify(); }
+                    }
+                }
+
+                @Override
+                public void onError(@NonNull MediaCodec mediaCodec, @NonNull CodecException e) {
+                    mediaCodec.stop();
+                    mediaCodec.release();
+                    Log.e(TAG, "CodecError: " + e.toString());
+                    e.printStackTrace();
+                }
+
+                @Override
+                public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
+                                                  @NonNull MediaFormat format) {
+                    Log.i(TAG, "Output format changed. Format: " + format.toString());
+                }
+            });
+        }
+        mCodec.start();
+        long eTime = mStats.getCurTime();
+        mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+        mStats.setStartTime();
+        if (asyncMode) {
+            try {
+                synchronized (mLock) { mLock.wait(); }
+                if (mSignalledError) {
+                    return -1;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        } else {
+            while (!mSawOutputEOS && !mSignalledError) {
+                /* Queue input data */
+                if (!mSawInputEOS) {
+                    int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+                    if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueInputBuffer " + "returned invalid index : " +
+                                inputBufferId);
+                        return -1;
+                    }
+                    mStats.addInputTime();
+                    onInputAvailable(mCodec, inputBufferId);
+                }
+                /* Dequeue output data */
+                MediaCodec.BufferInfo outputBufferInfo = new MediaCodec.BufferInfo();
+                int outputBufferId =
+                        mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+                if (outputBufferId < 0) {
+                    if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        MediaFormat outFormat = mCodec.getOutputFormat();
+                        Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+                    } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueOutputBuffer" + " returned invalid index " +
+                                outputBufferId);
+                        return -1;
+                    }
+                } else {
+                    mStats.addOutputTime();
+                    if (DEBUG) {
+                        Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+                    }
+                    onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+                }
+            }
+        }
+        return 0;
+    }
+
+    private void onOutputAvailable(MediaCodec mediaCodec, int outputBufferId,
+                                   MediaCodec.BufferInfo outputBufferInfo) {
+        if (mSawOutputEOS || outputBufferId < 0) {
+            if (mSawOutputEOS) {
+                Log.i(TAG, "Saw output EOS");
+            }
+            return;
+        }
+        ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+        if (mOutputStream != null) {
+            try {
+
+                byte[] bytesOutput = new byte[outputBuffer.remaining()];
+                outputBuffer.get(bytesOutput);
+                mOutputStream.write(bytesOutput);
+            } catch (IOException e) {
+                e.printStackTrace();
+                Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+                return;
+            }
+        }
+        mStats.addFrameSize(outputBuffer.remaining());
+        mediaCodec.releaseOutputBuffer(outputBufferId, false);
+        mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+    }
+
+    private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
+        if (mSawInputEOS || inputBufferId < 0) {
+            if (mSawInputEOS) {
+                Log.i(TAG, "Saw input EOS");
+            }
+            return;
+        }
+        if (mInputBufferSize < mOffset) {
+            Log.e(TAG, "Out of bound access of input buffer");
+            mSignalledError = true;
+            return;
+        }
+        ByteBuffer inputBuffer = mCodec.getInputBuffer(inputBufferId);
+        if (inputBuffer == null) {
+            mSignalledError = true;
+            return;
+        }
+        int bufSize = inputBuffer.capacity();
+        int bytesToRead = mFrameSize;
+        if (mInputBufferSize - mOffset < mFrameSize) {
+            bytesToRead = (int) (mInputBufferSize - mOffset);
+        }
+        //b/148655275 - Update Frame size, as Format value may not be valid
+        if (bufSize < bytesToRead) {
+            if(mNumInputFrame == 0) {
+                mFrameSize = bufSize;
+                bytesToRead = bufSize;
+                mNumFrames = (int) ((mInputBufferSize + mFrameSize - 1) / mFrameSize);
+            } else {
+                mSignalledError = true;
+                return;
+            }
+        }
+
+        byte[] inputArray = new byte[bytesToRead];
+        mInputStream.read(inputArray, 0, bytesToRead);
+        inputBuffer.put(inputArray);
+        int flag = 0;
+        if (mNumInputFrame >= mNumFrames - 1 || bytesToRead == 0) {
+            Log.i(TAG, "Sending EOS on input last frame");
+            mSawInputEOS = true;
+            flag = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+        }
+        int presentationTimeUs;
+        if (mMime.startsWith("video/")) {
+            presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
+        } else {
+            presentationTimeUs = mNumInputFrame * mFrameSize * 1000000 / mSampleRate;
+        }
+        mediaCodec.queueInputBuffer(inputBufferId, 0, bytesToRead, presentationTimeUs, flag);
+        mNumInputFrame++;
+        mOffset += bytesToRead;
+    }
+
+    /**
+     * Stops the codec and releases codec resources.
+     */
+    public void deInitEncoder() {
+        long sTime = mStats.getCurTime();
+        if (mCodec != null) {
+            mCodec.stop();
+            mCodec.release();
+            mCodec = null;
+        }
+        long eTime = mStats.getCurTime();
+        mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+    }
+
+    /**
+     * Prints out the statistics in the information log
+     *
+     * @param inputReference The operation being performed, in this case decode
+     * @param componentName  Name of the component/codec
+     * @param mode           The operating mode: Sync/Async
+     * @param durationUs     Duration of the clip in microseconds
+     * @param statsFile      The output file where the stats data is written
+     */
+    public void dumpStatistics(String inputReference, String componentName, String mode,
+                               long durationUs, String statsFile) throws IOException {
+        String operation = "encode";
+        mStats.dumpStatistics(
+                inputReference, operation, componentName, mode, durationUs, statsFile);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetEncoder() {
+        mOffset = 0;
+        mInputBufferSize = 0;
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+        mStats.reset();
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
new file mode 100644
index 0000000..f3024e7
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Extractor {
+    private static final String TAG = "Extractor";
+    private static final int kMaxBufSize = 1024 * 1024 * 16;
+    private MediaExtractor mExtractor;
+    private ByteBuffer mFrameBuffer;
+    private MediaCodec.BufferInfo mBufferInfo;
+    private Stats mStats;
+    private long mDurationUs;
+
+    public Extractor() {
+        mFrameBuffer = ByteBuffer.allocate(kMaxBufSize);
+        mBufferInfo = new MediaCodec.BufferInfo();
+        mStats = new Stats();
+    }
+
+    /**
+     * Creates a Media Extractor and sets data source(FileDescriptor)to use
+     *
+     * @param fileDescriptor FileDescriptor for the file which is to be extracted
+     * @return TrackCount of the sample
+     * @throws IOException If FileDescriptor is null
+     */
+    public int setUpExtractor(FileDescriptor fileDescriptor) throws IOException {
+        long sTime = mStats.getCurTime();
+        mExtractor = new MediaExtractor();
+        mExtractor.setDataSource(fileDescriptor);
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setInitTime(timeTaken);
+        return mExtractor.getTrackCount();
+    }
+
+    /**
+     * Returns the track format of the specified index
+     *
+     * @param trackID Index of the track
+     * @return Format of the track
+     */
+    public MediaFormat getFormat(int trackID) { return mExtractor.getTrackFormat(trackID); }
+
+    /**
+     * Returns the extracted buffer for the input clip
+     */
+    public ByteBuffer getFrameBuffer() { return this.mFrameBuffer; }
+
+    /**
+     * Returns the information of buffer related to sample
+     */
+    public MediaCodec.BufferInfo getBufferInfo() { return this.mBufferInfo; }
+
+    /**
+     * Returns the duration of the sample
+     */
+    public long getClipDuration() { return this.mDurationUs; }
+
+    /**
+     * Retrieve the current sample and store it in the byte buffer
+     * Also, sets the information related to extracted sample and store it in buffer info
+     *
+     * @return Sample size of the extracted sample
+     */
+    public int getFrameSample() {
+        int sampleSize = mExtractor.readSampleData(mFrameBuffer, 0);
+        if (sampleSize < 0) {
+            mBufferInfo.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+            mBufferInfo.size = 0;
+        } else {
+            mBufferInfo.size = sampleSize;
+            mBufferInfo.offset = 0;
+            mBufferInfo.flags = mExtractor.getSampleFlags();
+            mBufferInfo.presentationTimeUs = mExtractor.getSampleTime();
+            mExtractor.advance();
+        }
+        return sampleSize;
+    }
+
+    /**
+     * Setup the track format and get the duration of the sample
+     * Track is selected here for extraction
+     *
+     * @param trackId Track index to be selected
+     * @return 0 for valid track, otherwise -1
+     */
+    public int selectExtractorTrack(int trackId) {
+        MediaFormat trackFormat = mExtractor.getTrackFormat(trackId);
+        mDurationUs = trackFormat.getLong(MediaFormat.KEY_DURATION);
+        if (mDurationUs < 0) {
+            Log.e(TAG, "Invalid Clip");
+            return -1;
+        }
+        mExtractor.selectTrack(trackId);
+        return 0;
+    }
+
+    /**
+     * Unselect the track
+     *
+     * @param trackId Track Index to be unselected
+     */
+    public void unselectExtractorTrack(int trackId) { mExtractor.unselectTrack(trackId); }
+
+    /**
+     * Free up the resources
+     */
+    public void deinitExtractor() {
+        long sTime = mStats.getCurTime();
+        mExtractor.release();
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setDeInitTime(timeTaken);
+    }
+
+    /**
+     * Performs extract operation
+     *
+     * @param currentTrack Track index to be extracted
+     * @return Status as 0 if extraction is successful, -1 otherwise
+     */
+    public int extractSample(int currentTrack) {
+        int status;
+        status = selectExtractorTrack(currentTrack);
+        if (status == -1) {
+            Log.e(TAG, "Failed to select track");
+            return -1;
+        }
+        mStats.setStartTime();
+        while (true) {
+            int readSampleSize = getFrameSample();
+            if (readSampleSize <= 0) {
+                break;
+            }
+            mStats.addOutputTime();
+            mStats.addFrameSize(readSampleSize);
+        }
+        unselectExtractorTrack(currentTrack);
+        return 0;
+    }
+
+    /**
+     * Write the benchmark logs for the given input file
+     *
+     * @param inputReference Name of the input file
+     * @param mimeType       Mime type of the muxed file
+     * @param statsFile      The output file where the stats data is written
+     */
+    public void dumpStatistics(String inputReference, String mimeType, String statsFile)
+            throws IOException {
+        String operation = "extract";
+        mStats.dumpStatistics(inputReference, operation, mimeType, "", mDurationUs, statsFile);
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
new file mode 100644
index 0000000..340b539
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+public class Muxer {
+    private Stats mStats;
+    private MediaMuxer mMuxer;
+
+    /**
+     * Creates a Media Muxer for the specified path
+     *
+     * @param context      App context to specify the output file path
+     * @param outputFormat Format of the output media file
+     * @param trackFormat  Format of the current track
+     * @return Returns the track index of the newly added track, -1 otherwise
+     */
+    public int setUpMuxer(Context context, int outputFormat, MediaFormat trackFormat) {
+        try {
+            mStats = new Stats();
+            long sTime = mStats.getCurTime();
+            mMuxer = new MediaMuxer(context.getFilesDir().getPath() + "/mux.out.", outputFormat);
+            int trackIndex = mMuxer.addTrack(trackFormat);
+            mMuxer.start();
+            long eTime = mStats.getCurTime();
+            long timeTaken = mStats.getTimeDiff(sTime, eTime);
+            mStats.setInitTime(timeTaken);
+            return trackIndex;
+        } catch (IllegalArgumentException | IOException e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
+    /**
+     * Performs the Mux operation
+     *
+     * @param trackIndex           Track index of the sample
+     * @param inputExtractedBuffer Buffer containing encoded samples
+     * @param inputBufferInfo      Buffer information related to these samples
+     * @return Returns Status as 0 if write operation is successful, -1 otherwise
+     */
+    public int mux(int trackIndex, ArrayList<ByteBuffer> inputExtractedBuffer,
+                   ArrayList<MediaCodec.BufferInfo> inputBufferInfo) {
+        mStats.setStartTime();
+        for (int sampleCount = 0; sampleCount < inputExtractedBuffer.size(); sampleCount++) {
+            try {
+                mMuxer.writeSampleData(trackIndex, inputExtractedBuffer.get(sampleCount),
+                        inputBufferInfo.get(sampleCount));
+                mStats.addOutputTime();
+                mStats.addFrameSize(inputBufferInfo.get(sampleCount).size);
+            } catch (IllegalArgumentException | IllegalStateException e) {
+                e.printStackTrace();
+                return -1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Stops the muxer and free up the resources
+     */
+    public void deInitMuxer() {
+        long sTime = mStats.getCurTime();
+        mMuxer.stop();
+        mMuxer.release();
+        long eTime = mStats.getCurTime();
+        long timeTaken = mStats.getTimeDiff(sTime, eTime);
+        mStats.setDeInitTime(timeTaken);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetMuxer() {
+        mStats.reset();
+    }
+
+    /**
+     * Write the benchmark logs for the given input file
+     *
+     * @param inputReference Name of the input file
+     * @param muxFormat      Format of the muxed output
+     * @param clipDuration   Duration of the given inputReference file
+     * @param statsFile      The output file where the stats data is written
+     */
+    public void dumpStatistics(String inputReference, String muxFormat, long clipDuration,
+                               String statsFile) throws IOException {
+        String operation = "mux";
+        mStats.dumpStatistics(inputReference, operation, muxFormat, "", clipDuration, statsFile);
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Native.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Native.java
new file mode 100644
index 0000000..38b608a
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Native.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+public class Native {
+    static { System.loadLibrary("mediabenchmark_jni"); }
+
+    public native int Extract(String inputFilePath, String inputFileName, String statsFile);
+
+    public native int Mux(String inputFilePath, String inputFileName, String outputFilePath,
+            String statsFile, String format);
+
+    public native int Decode(String inputFilePath, String inputFileName, String statsFile,
+            String codecName, boolean asyncMode);
+
+    public native int Encode(String inputFilePath, String inputFileName, String outputFilePath,
+            String statsFile, String codecName);
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
new file mode 100644
index 0000000..7245a3a
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2019 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 com.android.media.benchmark.library;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Measures Performance.
+ */
+public class Stats {
+    private static final String TAG = "Stats";
+    private long mInitTimeNs;
+    private long mDeInitTimeNs;
+    private long mStartTimeNs;
+    private ArrayList<Integer> mFrameSizes;
+    private ArrayList<Long> mInputTimer;
+    private ArrayList<Long> mOutputTimer;
+
+    public Stats() {
+        mFrameSizes = new ArrayList<>();
+        mInputTimer = new ArrayList<>();
+        mOutputTimer = new ArrayList<>();
+        mInitTimeNs = 0;
+        mDeInitTimeNs = 0;
+    }
+
+    public long getCurTime() { return System.nanoTime(); }
+
+    public void setInitTime(long initTime) { mInitTimeNs = initTime; }
+
+    public void setDeInitTime(long deInitTime) { mDeInitTimeNs = deInitTime; }
+
+    public void setStartTime() { mStartTimeNs = System.nanoTime(); }
+
+    public void addFrameSize(int size) { mFrameSizes.add(size); }
+
+    public void addInputTime() { mInputTimer.add(System.nanoTime()); }
+
+    public void addOutputTime() { mOutputTimer.add(System.nanoTime()); }
+
+    public void reset() {
+        if (mFrameSizes.size() != 0) {
+            mFrameSizes.clear();
+        }
+
+        if (mInputTimer.size() != 0) {
+            mInputTimer.clear();
+        }
+
+        if (mOutputTimer.size() != 0) {
+            mOutputTimer.clear();
+        }
+    }
+
+    public long getInitTime() { return mInitTimeNs; }
+
+    public long getDeInitTime() { return mDeInitTimeNs; }
+
+    public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); }
+
+    private long getTotalTime() {
+        if (mOutputTimer.size() == 0) {
+            return -1;
+        }
+        long lastTime = mOutputTimer.get(mOutputTimer.size() - 1);
+        return lastTime - mStartTimeNs;
+    }
+
+    private long getTotalSize() {
+        long totalSize = 0;
+        for (long size : mFrameSizes) {
+            totalSize += size;
+        }
+        return totalSize;
+    }
+
+    /**
+     * Writes the stats header to a file
+     * <p>
+     * \param statsFile    file where the stats data is to be written
+     **/
+    public boolean writeStatsHeader(String statsFile) throws IOException {
+        File outputFile = new File(statsFile);
+        FileOutputStream out = new FileOutputStream(outputFile, true);
+        if (!outputFile.exists())
+            return false;
+        String statsHeader =
+                "currentTime, fileName, operation, componentName, NDK/SDK, sync/async, setupTime, "
+                        + "destroyTime, minimumTime, maximumTime, "
+                        + "averageTime, timeToProcess1SecContent, totalBytesProcessedPerSec, "
+                        + "timeToFirstFrame, totalSizeInBytes, totalTime\n";
+        out.write(statsHeader.getBytes());
+        out.close();
+        return true;
+    }
+
+    /**
+     * Dumps the stats of the operation for a given input media.
+     * <p>
+     * \param inputReference input media
+     * \param operation      describes the operation performed on the input media
+     * (i.e. extract/mux/decode/encode)
+     * \param componentName  name of the codec/muxFormat/mime
+     * \param mode           the operating mode: sync/async.
+     * \param durationUs     is a duration of the input media in microseconds.
+     * \param statsFile      the file where the stats data is to be written.
+     */
+    public void dumpStatistics(String inputReference, String operation, String componentName,
+            String mode, long durationUs, String statsFile) throws IOException {
+        if (mOutputTimer.size() == 0) {
+            Log.e(TAG, "No output produced");
+            return;
+        }
+        long totalTimeTakenNs = getTotalTime();
+        long timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs;
+        long timeToFirstFrameNs = mOutputTimer.get(0) - mStartTimeNs;
+        long size = getTotalSize();
+        // get min and max output intervals.
+        long intervalNs;
+        long minTimeTakenNs = Long.MAX_VALUE;
+        long maxTimeTakenNs = 0;
+        long prevIntervalNs = mStartTimeNs;
+        for (int idx = 0; idx < mOutputTimer.size() - 1; idx++) {
+            intervalNs = mOutputTimer.get(idx) - prevIntervalNs;
+            prevIntervalNs = mOutputTimer.get(idx);
+            if (minTimeTakenNs > intervalNs) {
+                minTimeTakenNs = intervalNs;
+            } else if (maxTimeTakenNs < intervalNs) {
+                maxTimeTakenNs = intervalNs;
+            }
+        }
+
+        // Write the stats row data to file
+        String rowData = "";
+        rowData += System.nanoTime() + ", ";
+        rowData += inputReference + ", ";
+        rowData += operation + ", ";
+        rowData += componentName + ", ";
+        rowData += "SDK, ";
+        rowData += mode + ", ";
+        rowData += mInitTimeNs + ", ";
+        rowData += mDeInitTimeNs + ", ";
+        rowData += minTimeTakenNs + ", ";
+        rowData += maxTimeTakenNs + ", ";
+        rowData += totalTimeTakenNs / mOutputTimer.size() + ", ";
+        rowData += timeTakenPerSec + ", ";
+        rowData += (size * 1000000000) / totalTimeTakenNs + ", ";
+        rowData += timeToFirstFrameNs + ", ";
+        rowData += size + ", ";
+        rowData += totalTimeTakenNs + "\n";
+
+        File outputFile = new File(statsFile);
+        FileOutputStream out = new FileOutputStream(outputFile, true);
+        assert outputFile.exists() : "Failed to open the stats file for writing!";
+        out.write(rowData.getBytes());
+        out.close();
+    }
+}
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
new file mode 100644
index 0000000..05fbe6f
--- /dev/null
+++ b/media/tests/benchmark/README.md
@@ -0,0 +1,156 @@
+# Benchmark tests
+
+Benchmark app analyses the time taken by MediaCodec, MediaExtractor and MediaMuxer for given set of inputs. It is used to benchmark these modules on android devices.
+Benchmark results are emitted to logcat.
+
+This page describes steps to run the NDK and SDK layer test.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/tests/benchmark/
+```
+
+# NDK
+
+To run the test suite for measuring performance of the native layer, follow the following steps:
+
+The binaries will be created in the following path : $OUT/data/nativetest64/
+
+adb push $OUT/data/nativetest64/* /data/local/tmp/
+
+Eg. adb push $OUT/data/nativetest64/extractorTest/extractorTest /data/local/tmp/
+
+To run the binary, follow the commands mentioned below under each module.
+
+The resource file for the tests is taken from [here](https://drive.google.com/open?id=1ghMr17BBJ7n0pqbm7oREiTN_MNemJUqy)
+
+Download the MediaBenchmark.zip file, unzip and push it to /data/local/tmp/ on the device.
+
+```
+unzip MediaBenchmark.zip
+adb push MediaBenchmark /data/local/tmp
+```
+
+## Extractor
+
+The test extracts elementary stream and benchmarks the extractors available in NDK.
+
+The resource files are assumed to be at /data/local/tmp/MediaBenchmark/res/. You can use a different location, but you have to modify the rest of the instructions to replace /data/local/tmp/MediaBenchmark/res/ with wherever you chose to put the files.
+
+The path to these files on the device is required to be given for the test.
+
+```
+adb shell /data/local/tmp/extractorTest -P /data/local/tmp/MediaBenchmark/res/
+```
+
+## Decoder
+
+The test decodes input stream and benchmarks the decoders available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/decoderTest -P /data/local/tmp/MediaBenchmark/res/
+```
+
+## Muxer
+
+The test muxes elementary stream and benchmarks the muxers available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/muxerTest -P /data/local/tmp/MediaBenchmark/res/
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/encoderTest -P /data/local/tmp/MediaBenchmark/res/
+```
+
+# SDK
+
+To run the test suite for measuring performance of the SDK APIs, follow the following steps:
+
+The apk will be created at the following path:
+$OUT/testcases/MediaBenchmarkTest/arm64/
+
+To get the resorce files for the test follow instructions given in [NDK](#NDK)
+
+For installing the apk, run the command:
+```
+adb install -f -r $OUT/testcases/MediaBenchmarkTest/arm64/MediaBenchmarkTest.apk
+```
+
+For running all the tests, run the command:
+```
+adb shell am instrument -w -r -e package com.android.media.benchmark.tests com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Extractor
+
+The test extracts elementary stream and benchmarks the extractors available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.ExtractorTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Decoder
+
+The test decodes input stream and benchmarks the decoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.DecoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Muxer
+
+The test muxes elementary stream and benchmarks different writers available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.MuxerTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+# Codec2
+To run the test suite for measuring performance of the codec2 layer, follow the following steps:
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+adb push $(OUT)/data/nativetest64/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest64/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+adb push $(OUT)/data/nativetest/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To get the resource files for the test follow instructions given in [NDK](#NDK)
+
+## C2 Decoder
+
+The test decodes input stream and benchmarks the codec2 decoders available in device.
+
+Setup steps are same as [extractor](#extractor).
+
+```
+adb shell /data/local/tmp/C2DecoderTest -P /data/local/tmp/MediaBenchmark/res/
+```
+## C2 Encoder
+
+The test encodes input stream and benchmarks the codec2 encoders available in device.
+
+Setup steps are same as [extractor](#extractor).
+
+```
+adb shell /data/local/tmp/C2EncoderTest -P /data/local/tmp/MediaBenchmark/res/
+```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
new file mode 100644
index 0000000..d4389da
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+    name: "libmediabenchmark_common",
+    defaults: [
+        "libmediabenchmark-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: [
+        "BenchmarkCommon.cpp",
+        "Stats.cpp",
+        "utils/Timers.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
+
+cc_defaults {
+    name: "libmediabenchmark_common-defaults",
+
+    defaults: [
+        "libmediabenchmark-defaults",
+    ],
+
+    static_libs: [
+        "libmediabenchmark_common",
+    ],
+}
+
+cc_defaults {
+    name: "libmediabenchmark-defaults",
+    sdk_version: "current",
+    stl: "c++_shared",
+
+    shared_libs: [
+        "libmediandk",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+cc_library_static {
+    name: "libmediabenchmark_codec2_common",
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: [
+        "BenchmarkC2Common.cpp",
+        "BenchmarkCommon.cpp",
+        "Stats.cpp",
+        "utils/Timers.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
+
+cc_defaults {
+    name: "libmediabenchmark_codec2_common-defaults",
+
+    defaults: [
+        "libcodec2-hidl-client-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/codec2/hidl/client/include",
+    ],
+
+    shared_libs: [
+        "libcodec2_client",
+        "libmediandk",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+// public dependency for native implementation
+// to be used by code under media/benchmark/* only
+cc_defaults {
+    name: "libmediabenchmark_soft_sanitize_all-defaults",
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
new file mode 100644
index 0000000..e09f468
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 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 "BenchmarkC2Common"
+
+#include "BenchmarkC2Common.h"
+
+int32_t BenchmarkC2Common::setupCodec2() {
+    ALOGV("In %s", __func__);
+    mClient = android::Codec2Client::CreateFromService("default");
+    if (!mClient) {
+        mClient = android::Codec2Client::CreateFromService("software");
+    }
+    if (!mClient) return -1;
+
+    std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+    if (!store) return -1;
+
+    c2_status_t status = store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+    if (status != C2_OK) return status;
+
+    mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
+    if (!mLinearPool) return -1;
+
+    status = store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator);
+    if (status != C2_OK) return status;
+
+    mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
+    if (!mGraphicPool) return -1;
+
+    for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
+        mWorkQueue.emplace_back(new C2Work);
+    }
+    if (!mStats) mStats = new Stats();
+
+    return status;
+}
+
+vector<string> BenchmarkC2Common::getSupportedComponentList(bool isEncoder) {
+    // Get List of components from all known services
+    vector<string> codecList;
+    const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
+    if (listTraits.size() == 0)
+        ALOGE("ComponentInfo list empty.");
+    else {
+        for (size_t i = 0; i < listTraits.size(); i++) {
+            if (isEncoder && C2Component::KIND_ENCODER == listTraits[i].kind) {
+                codecList.push_back(listTraits[i].name);
+            } else if (!isEncoder && C2Component::KIND_DECODER == listTraits[i].kind) {
+                codecList.push_back(listTraits[i].name);
+            }
+        }
+    }
+    return codecList;
+}
+
+void BenchmarkC2Common::waitOnInputConsumption() {
+    typedef std::unique_lock<std::mutex> ULock;
+    uint32_t queueSize;
+    uint32_t maxRetry = 0;
+    {
+        ULock l(mQueueLock);
+        queueSize = mWorkQueue.size();
+    }
+    while ((maxRetry < MAX_RETRY) && (queueSize < MAX_INPUT_BUFFERS)) {
+        ULock l(mQueueLock);
+        if (queueSize != mWorkQueue.size()) {
+            queueSize = mWorkQueue.size();
+            maxRetry = 0;
+        } else {
+            mQueueCondition.wait_for(l, TIME_OUT);
+            maxRetry++;
+        }
+    }
+}
+
+void BenchmarkC2Common::handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
+    ALOGV("In %s", __func__);
+    mStats->addOutputTime();
+    for (std::unique_ptr<C2Work> &work : workItems) {
+        if (!work->worklets.empty()) {
+            if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+                mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) !=
+                       0;
+                ALOGV("WorkDone: frameID received %d , mEos : %d",
+                      (int)work->worklets.front()->output.ordinal.frameIndex.peeku(), mEos);
+                work->input.buffers.clear();
+                work->worklets.clear();
+                {
+                    typedef std::unique_lock<std::mutex> ULock;
+                    ULock l(mQueueLock);
+                    mWorkQueue.push_back(std::move(work));
+                    mQueueCondition.notify_all();
+                }
+            }
+        }
+    }
+}
+
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.h b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
new file mode 100644
index 0000000..d67758a
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 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 __BENCHMARK_C2_COMMON_H__
+#define __BENCHMARK_C2_COMMON_H__
+
+#include "codec2/hidl/client.h"
+
+#include <C2Component.h>
+#include <C2Config.h>
+
+#include <hidl/HidlSupport.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+
+#include "BenchmarkCommon.h"
+
+#define MAX_RETRY 20
+#define TIME_OUT 400ms
+#define MAX_INPUT_BUFFERS 8
+
+using android::C2AllocatorIon;
+
+class LinearBuffer : public C2Buffer {
+  public:
+    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
+        : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+    explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block, size_t size)
+        : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+class GraphicBuffer : public C2Buffer {
+  public:
+    explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
+        : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone(), onTripped(),
+ * onError(), onDeath(), onFramesRendered() for C2 Components
+ */
+struct CodecListener : public android::Codec2Client::Listener {
+  public:
+    CodecListener(
+            const std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> fn = nullptr)
+        : callBack(fn) {}
+    virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component> &comp,
+                            std::list<std::unique_ptr<C2Work>> &workItems) override {
+        ALOGV("onWorkDone called");
+        (void)comp;
+        if (callBack) callBack(workItems);
+    }
+
+    virtual void onTripped(
+            const std::weak_ptr<android::Codec2Client::Component> &comp,
+            const std::vector<std::shared_ptr<C2SettingResult>> &settingResults) override {
+        (void)comp;
+        (void)settingResults;
+    }
+
+    virtual void onError(const std::weak_ptr<android::Codec2Client::Component> &comp,
+                         uint32_t errorCode) override {
+        (void)comp;
+        ALOGV("onError called");
+        if (errorCode != 0) ALOGE("Error : %u", errorCode);
+    }
+
+    virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component> &comp) override {
+        (void)comp;
+    }
+
+    virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
+        (void)frameIndex;
+        (void)arrayIndex;
+    }
+
+    virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
+                                 int64_t timestampNs) override {
+        (void)bufferQueueId;
+        (void)slotId;
+        (void)timestampNs;
+    }
+
+    std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> callBack;
+};
+
+class BenchmarkC2Common {
+  public:
+    BenchmarkC2Common()
+        : mEos(false),
+          mStats(nullptr),
+          mClient(nullptr),
+          mBlockPoolId(0),
+          mLinearPool(nullptr),
+          mGraphicPool(nullptr),
+          mLinearAllocator(nullptr),
+          mGraphicAllocator(nullptr) {}
+
+    int32_t setupCodec2();
+
+    vector<string> getSupportedComponentList(bool isEncoder);
+
+    void waitOnInputConsumption();
+
+    // callback function to process onWorkDone received by Listener
+    void handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
+
+    bool mEos;
+  protected:
+    Stats *mStats;
+
+    std::shared_ptr<android::Codec2Client> mClient;
+
+    C2BlockPool::local_id_t mBlockPoolId;
+    std::shared_ptr<C2BlockPool> mLinearPool;
+    std::shared_ptr<C2BlockPool> mGraphicPool;
+    std::shared_ptr<C2Allocator> mLinearAllocator;
+    std::shared_ptr<C2Allocator> mGraphicAllocator;
+
+    std::mutex mQueueLock;
+    std::condition_variable mQueueCondition;
+    std::list<std::unique_ptr<C2Work>> mWorkQueue;
+};
+
+#endif  // __BENCHMARK_C2_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
new file mode 100644
index 0000000..cb49b8e
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 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 "BenchmarkCommon"
+
+#include "BenchmarkCommon.h"
+#include <iostream>
+
+void CallBackHandle::ioThread() {
+    ALOGV("In %s mIsDone : %d, mSawError : %d ", __func__, mIsDone, mSawError);
+    while (!mIsDone && !mSawError) {
+        auto task = mIOQueue.pop();
+        task();
+    }
+}
+
+void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index) {
+    ALOGV("OnInputAvailableCB: index(%d)", index);
+    CallBackHandle *self = (CallBackHandle *)userdata;
+    self->getStats()->addInputTime();
+    self->mIOQueue.push([self, codec, index]() { self->onInputAvailable(codec, index); });
+}
+
+void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
+                         AMediaCodecBufferInfo *bufferInfo) {
+    ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)", index, bufferInfo->offset,
+          bufferInfo->size, (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
+    CallBackHandle *self = (CallBackHandle *)userdata;
+    self->getStats()->addOutputTime();
+    AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
+    self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
+        AMediaCodecBufferInfo bc = bufferInfoCopy;
+        self->onOutputAvailable(codec, index, &bc);
+    });
+}
+
+void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format) {
+    ALOGV("OnFormatChangedCB: format(%s)", AMediaFormat_toString(format));
+    CallBackHandle *self = (CallBackHandle *)userdata;
+    self->mIOQueue.push([self, codec, format]() { self->onFormatChanged(codec, format); });
+}
+
+void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
+               const char *detail) {
+    (void)codec;
+    ALOGE("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
+    CallBackHandle *self = (CallBackHandle *)userdata;
+    self->mSawError = true;
+    self->mIOQueue.push([self, codec, err]() { self->onError(codec, err); });
+}
+
+AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
+                              bool isEncoder) {
+    ALOGV("In %s", __func__);
+    if (!mime) {
+        ALOGE("Please specify a mime type to create codec");
+        return nullptr;
+    }
+
+    AMediaCodec *codec;
+    if (!codecName.empty()) {
+        codec = AMediaCodec_createCodecByName(codecName.c_str());
+        if (!codec) {
+            ALOGE("Unable to create codec by name: %s", codecName.c_str());
+            return nullptr;
+        }
+    } else {
+        if (isEncoder) {
+            codec = AMediaCodec_createEncoderByType(mime);
+        } else {
+            codec = AMediaCodec_createDecoderByType(mime);
+        }
+        if (!codec) {
+            ALOGE("Unable to create codec by mime: %s", mime);
+            return nullptr;
+        }
+    }
+
+    /* Configure codec with the given format*/
+    const char *s = AMediaFormat_toString(format);
+    ALOGI("Input format: %s\n", s);
+
+    media_status_t status = AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder);
+    if (status != AMEDIA_OK) {
+        ALOGE("AMediaCodec_configure failed %d", status);
+        return nullptr;
+    }
+    return codec;
+}
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
new file mode 100644
index 0000000..40a8c9e
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 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 __BENCHMARK_COMMON_H__
+#define __BENCHMARK_COMMON_H__
+
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <iostream>
+
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaError.h>
+
+#include "Stats.h"
+#define UNUSED(x) (void)(x)
+
+using namespace std;
+
+constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;
+// Change in kDefaultAudioEncodeFrameSize should also be taken to
+// AUDIO_ENCODE_DEFAULT_MAX_INPUT_SIZE present in Encoder.java
+constexpr uint32_t kDefaultAudioEncodeFrameSize = 4096;
+
+template <typename T>
+class CallBackQueue {
+  public:
+    CallBackQueue() {}
+    ~CallBackQueue() {}
+
+    void push(T elem) {
+        bool needsNotify = false;
+        {
+            lock_guard<mutex> lock(mMutex);
+            needsNotify = mQueue.empty();
+            mQueue.push(move(elem));
+        }
+        if (needsNotify) mQueueNotEmptyCondition.notify_one();
+    }
+
+    T pop() {
+        unique_lock<mutex> lock(mMutex);
+        if (mQueue.empty()) {
+            mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
+        }
+        auto result = mQueue.front();
+        mQueue.pop();
+        return result;
+    }
+
+  private:
+    mutex mMutex;
+    queue<T> mQueue;
+    condition_variable mQueueNotEmptyCondition;
+};
+
+class CallBackHandle {
+  public:
+    CallBackHandle() : mSawError(false), mIsDone(false), mStats(nullptr) {
+        mStats = new Stats();
+    }
+
+    virtual ~CallBackHandle() {
+        if (mIOThread.joinable()) mIOThread.join();
+        if (mStats) delete mStats;
+    }
+
+    void ioThread();
+
+    // Implementation in child class (Decoder/Encoder)
+    virtual void onInputAvailable(AMediaCodec *codec, int32_t index) {
+        (void)codec;
+        (void)index;
+    }
+    virtual void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) {
+        (void)codec;
+        (void)format;
+    }
+    virtual void onError(AMediaCodec *codec, media_status_t err) {
+        (void)codec;
+        (void)err;
+    }
+    virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
+                                   AMediaCodecBufferInfo *bufferInfo) {
+        (void)codec;
+        (void)index;
+        (void)bufferInfo;
+    }
+
+    Stats *getStats() { return mStats; }
+
+    // Keep a queue of all function callbacks.
+    typedef function<void()> IOTask;
+    CallBackQueue<IOTask> mIOQueue;
+    thread mIOThread;
+    bool mSawError;
+    bool mIsDone;
+
+  protected:
+    Stats *mStats;
+};
+
+// Async API's callback
+void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index);
+
+void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
+                         AMediaCodecBufferInfo *bufferInfo);
+
+void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format);
+
+void OnErrorCB(AMediaCodec *codec, void * /* userdata */, media_status_t err, int32_t actionCode,
+               const char *detail);
+
+// Utility to create and configure AMediaCodec
+AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
+                              bool isEncoder);
+
+#endif  // __BENCHMARK_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/Stats.cpp b/media/tests/benchmark/src/native/common/Stats.cpp
new file mode 100644
index 0000000..bfde125
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Stats.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 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 "Stats"
+
+#include <ctime>
+#include <iostream>
+#include <stdint.h>
+#include <fstream>
+
+#include "Stats.h"
+
+/**
+ * Dumps the stats of the operation for a given input media.
+ *
+ * \param operation      describes the operation performed on the input media
+ *                       (i.e. extract/mux/decode/encode)
+ * \param inputReference input media
+ * \param durationUs     is a duration of the input media in microseconds.
+ * \param componentName  describes the codecName/muxFormat/mimeType.
+ * \param mode           the operating mode: sync/async.
+ * \param statsFile      the file where the stats data is to be written.
+ */
+void Stats::dumpStatistics(string operation, string inputReference, int64_t durationUs,
+                           string componentName, string mode, string statsFile) {
+    ALOGV("In %s", __func__);
+    if (!mOutputTimer.size()) {
+        ALOGE("No output produced");
+        return;
+    }
+    nsecs_t totalTimeTakenNs = getTotalTime();
+    nsecs_t timeTakenPerSec = (totalTimeTakenNs * 1000000) / durationUs;
+    nsecs_t timeToFirstFrameNs = *mOutputTimer.begin() - mStartTimeNs;
+    int32_t size = std::accumulate(mFrameSizes.begin(), mFrameSizes.end(), 0);
+    // get min and max output intervals.
+    nsecs_t intervalNs;
+    nsecs_t minTimeTakenNs = INT64_MAX;
+    nsecs_t maxTimeTakenNs = 0;
+    nsecs_t prevIntervalNs = mStartTimeNs;
+    for (int32_t idx = 0; idx < mOutputTimer.size() - 1; idx++) {
+        intervalNs = mOutputTimer.at(idx) - prevIntervalNs;
+        prevIntervalNs = mOutputTimer.at(idx);
+        if (minTimeTakenNs > intervalNs) minTimeTakenNs = intervalNs;
+        else if (maxTimeTakenNs < intervalNs) maxTimeTakenNs = intervalNs;
+    }
+
+    // Write the stats data to file.
+    int64_t dataSize = size;
+    int64_t bytesPerSec = ((int64_t)dataSize * 1000000000) / totalTimeTakenNs;
+    string rowData = "";
+    rowData.append(to_string(systemTime(CLOCK_MONOTONIC)) + ", ");
+    rowData.append(inputReference + ", ");
+    rowData.append(operation + ", ");
+    rowData.append(componentName + ", ");
+    rowData.append("NDK, ");
+    rowData.append(mode + ", ");
+    rowData.append(to_string(mInitTimeNs) + ", ");
+    rowData.append(to_string(mDeInitTimeNs) + ", ");
+    rowData.append(to_string(minTimeTakenNs) + ", ");
+    rowData.append(to_string(maxTimeTakenNs) + ", ");
+    rowData.append(to_string(totalTimeTakenNs / mOutputTimer.size()) + ", ");
+    rowData.append(to_string(timeTakenPerSec) + ", ");
+    rowData.append(to_string(bytesPerSec) + ", ");
+    rowData.append(to_string(timeToFirstFrameNs) + ", ");
+    rowData.append(to_string(size) + ",");
+    rowData.append(to_string(totalTimeTakenNs) + ",\n");
+
+    ofstream out(statsFile, ios::out | ios::app);
+    if(out.bad()) {
+        ALOGE("Failed to open stats file for writing!");
+        return;
+    }
+    out << rowData;
+    out.close();
+}
diff --git a/media/tests/benchmark/src/native/common/Stats.h b/media/tests/benchmark/src/native/common/Stats.h
new file mode 100644
index 0000000..18e4b06
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Stats.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 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 __STATS_H__
+#define __STATS_H__
+
+#include <android/log.h>
+#include <inttypes.h>
+
+#ifndef ALOG
+#define ALOG(priority, tag, ...) ((void)__android_log_print(ANDROID_##priority, tag, __VA_ARGS__))
+
+#define ALOGI(...) ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define ALOGW(...) ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)
+
+#ifndef LOG_NDEBUG
+#define LOG_NDEBUG 1
+#endif
+
+#if LOG_NDEBUG
+#define ALOGV(cond, ...)   ((void)0)
+#else
+#define ALOGV(...) ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#endif
+#endif  // ALOG
+
+#include <sys/time.h>
+#include <algorithm>
+#include <numeric>
+#include <vector>
+
+// Include local copy of Timers taken from system/core/libutils
+#include "utils/Timers.h"
+
+using namespace std;
+
+class Stats {
+  public:
+    Stats() {
+        mInitTimeNs = 0;
+        mDeInitTimeNs = 0;
+    }
+
+    ~Stats() {
+        reset();
+    }
+
+  private:
+    nsecs_t mInitTimeNs;
+    nsecs_t mDeInitTimeNs;
+    nsecs_t mStartTimeNs;
+    std::vector<int32_t> mFrameSizes;
+    std::vector<nsecs_t> mInputTimer;
+    std::vector<nsecs_t> mOutputTimer;
+
+  public:
+    nsecs_t getCurTime() { return systemTime(CLOCK_MONOTONIC); }
+
+    void setInitTime(nsecs_t initTime) { mInitTimeNs = initTime; }
+
+    void setDeInitTime(nsecs_t deInitTime) { mDeInitTimeNs = deInitTime; }
+
+    void setStartTime() { mStartTimeNs = systemTime(CLOCK_MONOTONIC); }
+
+    void addFrameSize(int32_t size) { mFrameSizes.push_back(size); }
+
+    void addInputTime() { mInputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+    void addOutputTime() { mOutputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+    void reset() {
+        if (!mFrameSizes.empty()) mFrameSizes.clear();
+        if (!mInputTimer.empty()) mInputTimer.clear();
+        if (!mOutputTimer.empty()) mOutputTimer.clear();
+    }
+
+    std::vector<nsecs_t> getOutputTimer() { return mOutputTimer; }
+
+    nsecs_t getInitTime() { return mInitTimeNs; }
+
+    nsecs_t getDeInitTime() { return mDeInitTimeNs; }
+
+    nsecs_t getTimeDiff(nsecs_t sTime, nsecs_t eTime) { return (eTime - sTime); }
+
+    nsecs_t getTotalTime() {
+        if (mOutputTimer.empty()) return -1;
+        return (*(mOutputTimer.end() - 1) - mStartTimeNs);
+    }
+
+    void dumpStatistics(string operation, string inputReference, int64_t duarationUs,
+                        string codecName = "", string mode = "", string statsFile = "");
+};
+
+#endif  // __STATS_H__
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.cpp b/media/tests/benchmark/src/native/common/utils/Timers.cpp
new file mode 100644
index 0000000..1acbdb3
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#define LOG_TAG "Timers"
+
+#include <limits.h>
+#include <time.h>
+
+#include "Timers.h"
+
+#if defined(__ANDROID__)
+nsecs_t systemTime(int clock) {
+    static const clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
+                                       CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME};
+    struct timespec t;
+    t.tv_sec = t.tv_nsec = 0;
+    clock_gettime(clocks[clock], &t);
+    return nsecs_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+#else
+nsecs_t systemTime(int /*clock*/) {
+    // Clock support varies widely across hosts. Mac OS doesn't support
+    // posix clocks, older glibcs don't support CLOCK_BOOTTIME and Windows
+    // is windows.
+    struct timeval t;
+    t.tv_sec = t.tv_usec = 0;
+    gettimeofday(&t, NULL);
+    return nsecs_t(t.tv_sec) * 1000000000LL + nsecs_t(t.tv_usec) * 1000LL;
+}
+#endif
+
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) {
+    nsecs_t timeoutDelayMillis;
+    if (timeoutTime > referenceTime) {
+        uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
+        if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
+            timeoutDelayMillis = -1;
+        } else {
+            timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
+        }
+    } else {
+        timeoutDelayMillis = 0;
+    }
+    return (int)timeoutDelayMillis;
+}
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.h b/media/tests/benchmark/src/native/common/utils/Timers.h
new file mode 100644
index 0000000..d643dcd
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t;  // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs) {
+    return secs * 1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs) {
+    return secs / 1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs) {
+    return secs / 1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs) {
+    return secs / 1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v) {
+    return seconds_to_nanoseconds(v);
+}
+static inline nsecs_t ms2ns(nsecs_t v) {
+    return milliseconds_to_nanoseconds(v);
+}
+static inline nsecs_t us2ns(nsecs_t v) {
+    return microseconds_to_nanoseconds(v);
+}
+static inline nsecs_t ns2s(nsecs_t v) {
+    return nanoseconds_to_seconds(v);
+}
+static inline nsecs_t ns2ms(nsecs_t v) {
+    return nanoseconds_to_milliseconds(v);
+}
+static inline nsecs_t ns2us(nsecs_t v) {
+    return nanoseconds_to_microseconds(v);
+}
+
+static inline nsecs_t seconds(nsecs_t v) {
+    return s2ns(v);
+}
+static inline nsecs_t milliseconds(nsecs_t v) {
+    return ms2ns(v);
+}
+static inline nsecs_t microseconds(nsecs_t v) {
+    return us2ns(v);
+}
+
+enum {
+    SYSTEM_TIME_REALTIME = 0,   // system-wide realtime clock
+    SYSTEM_TIME_MONOTONIC = 1,  // monotonic time since unspecified starting point
+    SYSTEM_TIME_PROCESS = 2,    // high-resolution per-process clock
+    SYSTEM_TIME_THREAD = 3,     // high-resolution per-thread clock
+    SYSTEM_TIME_BOOTTIME = 4    // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif  // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // _LIBS_UTILS_TIMERS_H
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
new file mode 100644
index 0000000..9791c11
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+    name: "libmediabenchmark_decoder",
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["Decoder.cpp"],
+
+    static_libs: ["libmediabenchmark_extractor"],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
+
+cc_library_static {
+    name: "libmediabenchmark_codec2_decoder",
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: [
+        "C2Decoder.cpp",
+        "Decoder.cpp",
+    ],
+
+    static_libs: [
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_codec2_extractor",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
new file mode 100644
index 0000000..20a1468
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 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 "C2Decoder"
+#include <log/log.h>
+
+#include "C2Decoder.h"
+#include <iostream>
+
+int32_t C2Decoder::createCodec2Component(string compName, AMediaFormat *format) {
+    ALOGV("In %s", __func__);
+    mListener.reset(new CodecListener(
+            [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
+    if (!mListener) return -1;
+
+    const char *mime = nullptr;
+    AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+    if (!mime) {
+        ALOGE("Error in AMediaFormat_getString");
+        return -1;
+    }
+    // Configure the plugin with Input properties
+    std::vector<C2Param *> configParam;
+    if (!strncmp(mime, "audio/", 6)) {
+        int32_t sampleRate, numChannels;
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels);
+        C2StreamSampleRateInfo::output sampleRateInfo(0u, sampleRate);
+        C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
+        configParam.push_back(&sampleRateInfo);
+        configParam.push_back(&channelCountInfo);
+
+    } else {
+        int32_t width, height;
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
+        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
+        C2StreamPictureSizeInfo::input inputSize(0u, width, height);
+        configParam.push_back(&inputSize);
+    }
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
+    if (mComponent == nullptr) {
+        ALOGE("Create component failed for %s", compName.c_str());
+        return -1;
+    }
+    std::vector<std::unique_ptr<C2SettingResult>> failures;
+    int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+    if (failures.size() != 0) {
+        ALOGE("Invalid Configuration");
+        return -1;
+    }
+
+    status |= mComponent->start();
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+    return status;
+}
+
+int32_t C2Decoder::decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo) {
+    ALOGV("In %s", __func__);
+    typedef std::unique_lock<std::mutex> ULock;
+    c2_status_t status = C2_OK;
+    mStats->setStartTime();
+    while (1) {
+        if (mNumInputFrame == frameInfo.size()) break;
+        std::unique_ptr<C2Work> work;
+        // Prepare C2Work
+        {
+            ULock l(mQueueLock);
+            if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
+            if (!mWorkQueue.empty()) {
+                mStats->addInputTime();
+                work.swap(mWorkQueue.front());
+                mWorkQueue.pop_front();
+            } else {
+                std::cout << "Wait for generating C2Work exceeded timeout" << std::endl;
+                return -1;
+            }
+        }
+
+        uint32_t flags = frameInfo[mNumInputFrame].flags;
+        if (flags == AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
+            flags = C2FrameData::FLAG_CODEC_CONFIG;
+        }
+        if (mNumInputFrame == (frameInfo.size() - 1)) {
+            flags |= C2FrameData::FLAG_END_OF_STREAM;
+        }
+        work->input.flags = (C2FrameData::flags_t)flags;
+        work->input.ordinal.timestamp = frameInfo[mNumInputFrame].presentationTimeUs;
+        work->input.ordinal.frameIndex = mNumInputFrame;
+        work->input.buffers.clear();
+        int size = frameInfo[mNumInputFrame].size;
+        int alignedSize = ALIGN(size, PAGE_SIZE);
+        if (size) {
+            std::shared_ptr<C2LinearBlock> block;
+            status = mLinearPool->fetchLinearBlock(
+                    alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+            if (status != C2_OK || block == nullptr) {
+                std::cout << "C2LinearBlock::map() failed : " << status << std::endl;
+                return status;
+            }
+
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                std::cout << "C2LinearBlock::map() failed : " << view.error() << std::endl;
+                return view.error();
+            }
+            memcpy(view.base(), inputBuffer + mOffset, size);
+            work->input.buffers.emplace_back(new LinearBuffer(block, size));
+            mStats->addFrameSize(size);
+        }
+        work->worklets.clear();
+        work->worklets.emplace_back(new C2Worklet);
+
+        std::list<std::unique_ptr<C2Work>> items;
+        items.push_back(std::move(work));
+        // queue() invokes process() function of C2 Plugin.
+        status = mComponent->queue(&items);
+        if (status != C2_OK) {
+            ALOGE("queue failed");
+            return status;
+        }
+        ALOGV("Frame #%d size = %d queued", mNumInputFrame, size);
+        mNumInputFrame++;
+        mOffset += size;
+    }
+    return status;
+}
+
+void C2Decoder::deInitCodec() {
+    ALOGV("In %s", __func__);
+    if (!mComponent) return;
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent->stop();
+    mComponent->release();
+    mComponent = nullptr;
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs) {
+    string operation = "c2decode";
+    mStats->dumpStatistics(operation, inputReference, durationUs);
+}
+
+void C2Decoder::resetDecoder() {
+    mOffset = 0;
+    mNumInputFrame = 0;
+    if (mStats) mStats->reset();
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.h b/media/tests/benchmark/src/native/decoder/C2Decoder.h
new file mode 100644
index 0000000..4a3eb96
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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 __C2_DECODER_H__
+#define __C2_DECODER_H__
+
+#include "BenchmarkC2Common.h"
+
+#define ALIGN(_sz, _align) (((_sz) + ((_align) - 1)) & ~((_align) - 1))
+
+class C2Decoder : public BenchmarkC2Common {
+  public:
+    C2Decoder() : mOffset(0), mNumInputFrame(0), mComponent(nullptr) {}
+
+    int32_t createCodec2Component(string codecName, AMediaFormat *format);
+
+    int32_t decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo);
+
+    void deInitCodec();
+
+    void dumpStatistics(string inputReference, int64_t durationUs);
+
+    void resetDecoder();
+
+  private:
+    int32_t mOffset;
+    int32_t mNumInputFrame;
+    vector<AMediaCodecBufferInfo> mFrameMetaData;
+
+    std::shared_ptr<android::Codec2Client::Listener> mListener;
+    std::shared_ptr<android::Codec2Client::Component> mComponent;
+};
+
+#endif  // __C2_DECODER_H__
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
new file mode 100644
index 0000000..090f3e1
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2019 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 "decoder"
+
+#include <iostream>
+
+#include "Decoder.h"
+
+tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
+                                                 vector<AMediaCodecBufferInfo> &frameInfo,
+                                                 uint8_t *buf, int32_t frameID, size_t bufSize) {
+    ALOGV("In %s", __func__);
+    if (frameID == (int32_t)frameInfo.size()) {
+        return make_tuple(0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM, 0);
+    }
+    uint32_t flags = frameInfo[frameID].flags;
+    int64_t timestamp = frameInfo[frameID].presentationTimeUs;
+    ssize_t bytesCount = frameInfo[frameID].size;
+    if (bufSize < bytesCount) {
+        ALOGE("Error : Buffer size is insufficient to read sample");
+        return make_tuple(0, AMEDIA_ERROR_MALFORMED, 0);
+    }
+
+    memcpy(buf, inputBuffer + offset, bytesCount);
+    offset += bytesCount;
+    return make_tuple(bytesCount, flags, timestamp);
+}
+
+void Decoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        if (mSawInputEOS || bufIdx < 0) return;
+        if (mSignalledError) {
+            CallBackHandle::mSawError = true;
+            mDecoderDoneCondition.notify_one();
+            return;
+        }
+
+        size_t bufSize;
+        uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
+        if (!buf) {
+            mErrorCode = AMEDIA_ERROR_IO;
+            mSignalledError = true;
+            mDecoderDoneCondition.notify_one();
+            return;
+        }
+
+        ssize_t bytesRead = 0;
+        uint32_t flag = 0;
+        int64_t presentationTimeUs = 0;
+        tie(bytesRead, flag, presentationTimeUs) =
+                readSampleData(mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
+        if (flag == AMEDIA_ERROR_MALFORMED) {
+            mErrorCode = (media_status_t)flag;
+            mSignalledError = true;
+            mDecoderDoneCondition.notify_one();
+            return;
+        }
+
+        if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
+        ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
+              bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
+
+        media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+                                                             bytesRead, presentationTimeUs, flag);
+        if (AMEDIA_OK != status) {
+            mErrorCode = status;
+            mSignalledError = true;
+            mDecoderDoneCondition.notify_one();
+            return;
+        }
+        mStats->addFrameSize(bytesRead);
+        mNumInputFrame++;
+    }
+}
+
+void Decoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
+                                AMediaCodecBufferInfo *bufferInfo) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        if (mSawOutputEOS || bufIdx < 0) return;
+        if (mSignalledError) {
+            CallBackHandle::mSawError = true;
+            mDecoderDoneCondition.notify_one();
+            return;
+        }
+
+        if (mOutFp != nullptr) {
+            size_t bufSize;
+            uint8_t *buf = AMediaCodec_getOutputBuffer(mCodec, bufIdx, &bufSize);
+            if (buf) {
+                fwrite(buf, sizeof(char), bufferInfo->size, mOutFp);
+                ALOGV("bytes written into file  %d\n", bufferInfo->size);
+            }
+        }
+
+        AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
+        mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+        mNumOutputFrame++;
+        ALOGV("%s index : %d  mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
+              mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
+
+        if (mSawOutputEOS) {
+            CallBackHandle::mIsDone = true;
+            mDecoderDoneCondition.notify_one();
+        }
+    }
+}
+
+void Decoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
+        mFormat = format;
+    }
+}
+
+void Decoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGE("Received Error %d", err);
+        mErrorCode = err;
+        mSignalledError = true;
+        mDecoderDoneCondition.notify_one();
+    }
+}
+
+void Decoder::setupDecoder() {
+    if (!mFormat) mFormat = mExtractor->getFormat();
+}
+
+AMediaFormat *Decoder::getFormat() {
+    ALOGV("In %s", __func__);
+    return AMediaCodec_getOutputFormat(mCodec);
+}
+
+int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
+                        string &codecName, bool asyncMode, FILE *outFp) {
+    ALOGV("In %s", __func__);
+    mInputBuffer = inputBuffer;
+    mFrameMetaData = frameInfo;
+    mOffset = 0;
+    mOutFp = outFp;
+
+    const char *mime = nullptr;
+    AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+    if (!mime) return AMEDIA_ERROR_INVALID_OBJECT;
+
+    int64_t sTime = mStats->getCurTime();
+    mCodec = createMediaCodec(mFormat, mime, codecName, false /*isEncoder*/);
+    if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
+
+    if (asyncMode) {
+        AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
+                                                OnFormatChangedCB, OnErrorCB};
+        AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
+
+        mIOThread = thread(&CallBackHandle::ioThread, this);
+    }
+
+    AMediaCodec_start(mCodec);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+
+    mStats->setStartTime();
+    if (!asyncMode) {
+        while (!mSawOutputEOS && !mSignalledError) {
+            /* Queue input data */
+            if (!mSawInputEOS) {
+                ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
+                if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+                    ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
+                    mErrorCode = (media_status_t)inIdx;
+                    return mErrorCode;
+                } else if (inIdx >= 0) {
+                    mStats->addInputTime();
+                    onInputAvailable(mCodec, inIdx);
+                }
+            }
+
+            /* Dequeue output data */
+            AMediaCodecBufferInfo info;
+            ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
+            if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+                mFormat = AMediaCodec_getOutputFormat(mCodec);
+                const char *s = AMediaFormat_toString(mFormat);
+                ALOGI("Output format: %s\n", s);
+            } else if (outIdx >= 0) {
+                mStats->addOutputTime();
+                onOutputAvailable(mCodec, outIdx, &info);
+            } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
+                         outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
+                ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
+                mErrorCode = (media_status_t)outIdx;
+                return mErrorCode;
+            }
+        }
+    } else {
+        unique_lock<mutex> lock(mMutex);
+        mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
+    }
+    if (mSignalledError) {
+        ALOGE("Received Error while Decoding");
+        return mErrorCode;
+    }
+
+    if (codecName.empty()) {
+        char *decName;
+        AMediaCodec_getName(mCodec, &decName);
+        codecName.assign(decName);
+        AMediaCodec_releaseName(mCodec, decName);
+    }
+    return AMEDIA_OK;
+}
+
+void Decoder::deInitCodec() {
+    if (mFormat) {
+        AMediaFormat_delete(mFormat);
+        mFormat = nullptr;
+    }
+    if (!mCodec) return;
+    int64_t sTime = mStats->getCurTime();
+    AMediaCodec_stop(mCodec);
+    AMediaCodec_delete(mCodec);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void Decoder::dumpStatistics(string inputReference, string componentName, string mode,
+                             string statsFile) {
+    int64_t durationUs = mExtractor->getClipDuration();
+    string operation = "decode";
+    mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
+}
+
+void Decoder::resetDecoder() {
+    if (mStats) mStats->reset();
+    if (mInputBuffer) mInputBuffer = nullptr;
+    if (!mFrameMetaData.empty()) mFrameMetaData.clear();
+}
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
new file mode 100644
index 0000000..e619cb4
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 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 __DECODER_H__
+#define __DECODER_H__
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include "BenchmarkCommon.h"
+#include "Extractor.h"
+#include "Stats.h"
+
+class Decoder : public CallBackHandle {
+  public:
+    Decoder()
+        : mCodec(nullptr),
+          mFormat(nullptr),
+          mExtractor(nullptr),
+          mNumInputFrame(0),
+          mNumOutputFrame(0),
+          mSawInputEOS(false),
+          mSawOutputEOS(false),
+          mSignalledError(false),
+          mErrorCode(AMEDIA_OK),
+          mInputBuffer(nullptr),
+          mOutFp(nullptr) {
+        mExtractor = new Extractor();
+    }
+
+    virtual ~Decoder() {
+        if (mExtractor) delete mExtractor;
+    }
+
+    Extractor *getExtractor() { return mExtractor; }
+
+    // Decoder related utilities
+    void setupDecoder();
+
+    void deInitCodec();
+
+    void resetDecoder();
+
+    AMediaFormat *getFormat();
+
+    // Async callback APIs
+    void onInputAvailable(AMediaCodec *codec, int32_t index) override;
+
+    void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+
+    void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
+    void onOutputAvailable(AMediaCodec *codec, int32_t index,
+                           AMediaCodecBufferInfo *bufferInfo) override;
+
+    // Process the frames and give decoded output
+    int32_t decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
+                   string &codecName, bool asyncMode, FILE *outFp = nullptr);
+
+    void dumpStatistics(string inputReference, string componentName = "", string mode = "",
+                        string statsFile = "");
+
+  private:
+    AMediaCodec *mCodec;
+    AMediaFormat *mFormat;
+
+    Extractor *mExtractor;
+
+    int32_t mNumInputFrame;
+    int32_t mNumOutputFrame;
+
+    bool mSawInputEOS;
+    bool mSawOutputEOS;
+    bool mSignalledError;
+    media_status_t mErrorCode;
+
+    int32_t mOffset;
+    uint8_t *mInputBuffer;
+    vector<AMediaCodecBufferInfo> mFrameMetaData;
+    FILE *mOutFp;
+
+    /* Asynchronous locks */
+    mutex mMutex;
+    condition_variable mDecoderDoneCondition;
+};
+
+// Read input samples
+tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
+                                                 vector<AMediaCodecBufferInfo> &frameSizes,
+                                                 uint8_t *buf, int32_t frameID, size_t bufSize);
+
+#endif  // __DECODER_H__
diff --git a/media/tests/benchmark/src/native/encoder/Android.bp b/media/tests/benchmark/src/native/encoder/Android.bp
new file mode 100644
index 0000000..8de7823
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Android.bp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+    name: "libmediabenchmark_encoder",
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["Encoder.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_decoder",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
+
+cc_library_static {
+    name: "libmediabenchmark_codec2_encoder",
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: ["C2Encoder.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_codec2_extractor",
+        "libmediabenchmark_codec2_decoder",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"],
+}
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
new file mode 100644
index 0000000..33429ef
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2019 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 "C2Encoder"
+
+#include "C2Encoder.h"
+
+int32_t C2Encoder::createCodec2Component(string compName, AMediaFormat *format) {
+    ALOGV("In %s", __func__);
+    mListener.reset(new CodecListener(
+            [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
+    if (!mListener) return -1;
+
+    const char *mime = nullptr;
+    AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+    if (!mime) {
+        ALOGE("Error in AMediaFormat_getString");
+        return -1;
+    }
+    // Configure the plugin with Input properties
+    std::vector<C2Param *> configParam;
+    if (!strncmp(mime, "audio/", 6)) {
+        mIsAudioEncoder = true;
+        int32_t numChannels;
+        if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate)) {
+            ALOGE("AMEDIAFORMAT_KEY_SAMPLE_RATE not set");
+            return -1;
+        }
+        if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels)) {
+            ALOGE("AMEDIAFORMAT_KEY_CHANNEL_COUNT not set");
+            return -1;
+        }
+        C2StreamSampleRateInfo::input sampleRateInfo(0u, mSampleRate);
+        C2StreamChannelCountInfo::input channelCountInfo(0u, numChannels);
+        configParam.push_back(&sampleRateInfo);
+        configParam.push_back(&channelCountInfo);
+    } else {
+        mIsAudioEncoder = false;
+        if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &mWidth)) {
+            ALOGE("AMEDIAFORMAT_KEY_WIDTH not set");
+            return -1;
+        }
+        if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &mHeight)) {
+            ALOGE("AMEDIAFORMAT_KEY_HEIGHT not set");
+            return -1;
+        }
+        C2StreamPictureSizeInfo::input inputSize(0u, mWidth, mHeight);
+        configParam.push_back(&inputSize);
+
+        if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &mFrameRate) ||
+            (mFrameRate <= 0)) {
+            mFrameRate = KDefaultFrameRate;
+        }
+    }
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
+    if (mComponent == nullptr) {
+        ALOGE("Create component failed for %s", compName.c_str());
+        return -1;
+    }
+    std::vector<std::unique_ptr<C2SettingResult>> failures;
+    int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+    if (failures.size() != 0) {
+        ALOGE("Invalid Configuration");
+        return -1;
+    }
+
+    status |= mComponent->start();
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+    return status;
+}
+
+// In encoder components, fetch the size of input buffer allocated
+int32_t C2Encoder::getInputMaxBufSize() {
+    int32_t bitStreamInfo[1] = {0};
+    std::vector<std::unique_ptr<C2Param>> inParams;
+    c2_status_t status = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
+                                           C2_DONT_BLOCK, &inParams);
+    if (status != C2_OK && inParams.size() == 0) {
+        ALOGE("Query MaxBufferSizeInfo failed => %d", status);
+        return status;
+    } else {
+        size_t offset = sizeof(C2Param);
+        for (size_t i = 0; i < inParams.size(); ++i) {
+            C2Param *param = inParams[i].get();
+            bitStreamInfo[i] = *(int32_t *)((uint8_t *)param + offset);
+        }
+    }
+    mInputMaxBufSize = bitStreamInfo[0];
+    if (mInputMaxBufSize < 0) {
+        ALOGE("Invalid mInputMaxBufSize %d\n", mInputMaxBufSize);
+        return -1;
+    }
+    return status;
+}
+
+int32_t C2Encoder::encodeFrames(ifstream &eleStream, size_t inputBufferSize) {
+    ALOGV("In %s", __func__);
+    int32_t frameSize = 0;
+    if (!mIsAudioEncoder) {
+        frameSize = mWidth * mHeight * 3 / 2;
+    } else {
+        frameSize = DEFAULT_AUDIO_FRAME_SIZE;
+        if (getInputMaxBufSize() != 0) return -1;
+        if (frameSize > mInputMaxBufSize) {
+            frameSize = mInputMaxBufSize;
+        }
+    }
+    int32_t numFrames = (inputBufferSize + frameSize - 1) / frameSize;
+    // Temporary buffer to read data from the input file
+    char *data = (char *)malloc(frameSize);
+    if (!data) {
+        ALOGE("Insufficient memory to read from input file");
+        return -1;
+    }
+
+    typedef std::unique_lock<std::mutex> ULock;
+    uint64_t presentationTimeUs = 0;
+    size_t offset = 0;
+    c2_status_t status = C2_OK;
+
+    mStats->setStartTime();
+    while (numFrames > 0) {
+        std::unique_ptr<C2Work> work;
+        // Prepare C2Work
+        {
+            ULock l(mQueueLock);
+            if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
+            if (!mWorkQueue.empty()) {
+                mStats->addInputTime();
+                work.swap(mWorkQueue.front());
+                mWorkQueue.pop_front();
+            } else {
+                cout << "Wait for generating C2Work exceeded timeout" << endl;
+                return -1;
+            }
+        }
+
+        if (mIsAudioEncoder) {
+            presentationTimeUs = mNumInputFrame * frameSize * (1000000 / mSampleRate);
+        } else {
+            presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
+        }
+        uint32_t flags = 0;
+        if (numFrames == 1) flags |= C2FrameData::FLAG_END_OF_STREAM;
+
+        work->input.flags = (C2FrameData::flags_t)flags;
+        work->input.ordinal.timestamp = presentationTimeUs;
+        work->input.ordinal.frameIndex = mNumInputFrame;
+        work->input.buffers.clear();
+
+        if (inputBufferSize - offset < frameSize) {
+            frameSize = inputBufferSize - offset;
+        }
+        eleStream.read(data, frameSize);
+        if (eleStream.gcount() != frameSize) {
+            ALOGE("read() from file failed. Incorrect bytes read");
+            return -1;
+        }
+        offset += frameSize;
+
+        if (frameSize) {
+            if (mIsAudioEncoder) {
+                std::shared_ptr<C2LinearBlock> block;
+                status = mLinearPool->fetchLinearBlock(
+                        frameSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+                if (status != C2_OK || !block) {
+                    cout << "fetchLinearBlock failed : " << status << endl;
+                    return status;
+                }
+                C2WriteView view = block->map().get();
+                if (view.error() != C2_OK) {
+                    cout << "C2LinearBlock::map() failed : " << view.error() << endl;
+                    return view.error();
+                }
+
+                memcpy(view.base(), data, frameSize);
+                work->input.buffers.emplace_back(new LinearBuffer(block));
+            } else {
+                std::shared_ptr<C2GraphicBlock> block;
+                status = mGraphicPool->fetchGraphicBlock(
+                        mWidth, mHeight, HAL_PIXEL_FORMAT_YV12,
+                        {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+                if (status != C2_OK || !block) {
+                    cout << "fetchGraphicBlock failed : " << status << endl;
+                    return status;
+                }
+                C2GraphicView view = block->map().get();
+                if (view.error() != C2_OK) {
+                    cout << "C2GraphicBlock::map() failed : " << view.error() << endl;
+                    return view.error();
+                }
+
+                uint8_t *pY = view.data()[C2PlanarLayout::PLANE_Y];
+                uint8_t *pU = view.data()[C2PlanarLayout::PLANE_U];
+                uint8_t *pV = view.data()[C2PlanarLayout::PLANE_V];
+                memcpy(pY, data, mWidth * mHeight);
+                memcpy(pU, data + mWidth * mHeight, (mWidth * mHeight >> 2));
+                memcpy(pV, data + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
+                work->input.buffers.emplace_back(new GraphicBuffer(block));
+            }
+            mStats->addFrameSize(frameSize);
+        }
+
+        work->worklets.clear();
+        work->worklets.emplace_back(new C2Worklet);
+
+        std::list<std::unique_ptr<C2Work>> items;
+        items.push_back(std::move(work));
+        // queue() invokes process() function of C2 Plugin.
+        status = mComponent->queue(&items);
+        if (status != C2_OK) {
+            ALOGE("queue failed");
+            return status;
+        }
+        ALOGV("Frame #%d size = %d queued", mNumInputFrame, frameSize);
+        numFrames--;
+        mNumInputFrame++;
+    }
+    free(data);
+    return status;
+}
+
+void C2Encoder::deInitCodec() {
+    ALOGV("In %s", __func__);
+    if (!mComponent) return;
+
+    int64_t sTime = mStats->getCurTime();
+    mComponent->stop();
+    mComponent->release();
+    mComponent = nullptr;
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void C2Encoder::dumpStatistics(string inputReference, int64_t durationUs) {
+    string operation = "c2encode";
+    mStats->dumpStatistics(operation, inputReference, durationUs);
+}
+
+void C2Encoder::resetEncoder() {
+    mIsAudioEncoder = false;
+    mNumInputFrame = 0;
+    mEos = false;
+    if (mStats) mStats->reset();
+}
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.h b/media/tests/benchmark/src/native/encoder/C2Encoder.h
new file mode 100644
index 0000000..a4ca097
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 __C2_ENCODER_H__
+#define __C2_ENCODER_H__
+
+#include <stdio.h>
+#include <algorithm>
+#include <fstream>
+
+#include "BenchmarkC2Common.h"
+
+#define DEFAULT_AUDIO_FRAME_SIZE 4096
+
+constexpr int32_t KDefaultFrameRate = 25;
+
+class C2Encoder : public BenchmarkC2Common {
+  public:
+    C2Encoder()
+        : mIsAudioEncoder(false),
+          mWidth(0),
+          mHeight(0),
+          mNumInputFrame(0),
+          mComponent(nullptr) {}
+
+    int32_t createCodec2Component(string codecName, AMediaFormat *format);
+
+    int32_t encodeFrames(ifstream &eleStream, size_t inputBufferSize);
+
+    int32_t getInputMaxBufSize();
+
+    void deInitCodec();
+
+    void dumpStatistics(string inputReference, int64_t durationUs);
+
+    void resetEncoder();
+
+  private:
+    bool mIsAudioEncoder;
+
+    int32_t mWidth;
+    int32_t mHeight;
+    int32_t mFrameRate;
+    int32_t mSampleRate;
+
+    int32_t mNumInputFrame;
+    int32_t mInputMaxBufSize;
+
+    std::shared_ptr<android::Codec2Client::Listener> mListener;
+    std::shared_ptr<android::Codec2Client::Component> mComponent;
+};
+
+#endif  // __C2_ENCODER_H__
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
new file mode 100644
index 0000000..26fb1b9
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2019 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 "encoder"
+
+#include <fstream>
+
+#include "Encoder.h"
+
+void Encoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        if (mSawInputEOS || bufIdx < 0) return;
+        if (mSignalledError) {
+            CallBackHandle::mSawError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+
+        size_t bufSize = 0;
+        char *buf = (char *)AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
+        if (!buf) {
+            mErrorCode = AMEDIA_ERROR_IO;
+            mSignalledError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+
+        if (mInputBufferSize < mOffset) {
+            ALOGE("Out of bound access of input buffer\n");
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
+            mSignalledError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+        size_t bytesToRead = mParams.frameSize;
+        if (mInputBufferSize - mOffset < mParams.frameSize) {
+            bytesToRead = mInputBufferSize - mOffset;
+        }
+        //b/148655275 - Update Frame size, as Format value may not be valid
+        if (bufSize < bytesToRead) {
+            if(mNumInputFrame == 0) {
+                mParams.frameSize = bufSize;
+                bytesToRead = bufSize;
+                mParams.numFrames = (mInputBufferSize + mParams.frameSize - 1) / mParams.frameSize;
+            } else {
+                ALOGE("bytes to read %zu bufSize %zu \n", bytesToRead, bufSize);
+                mErrorCode = AMEDIA_ERROR_MALFORMED;
+                mSignalledError = true;
+                mEncoderDoneCondition.notify_one();
+                return;
+            }
+        }
+        if (bytesToRead < mParams.frameSize && mNumInputFrame < mParams.numFrames - 1) {
+            ALOGE("Partial frame at frameID %d bytesToRead %zu frameSize %d total numFrames %d\n",
+                  mNumInputFrame, bytesToRead, mParams.frameSize, mParams.numFrames);
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
+            mSignalledError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+        mEleStream->read(buf, bytesToRead);
+        size_t bytesgcount = mEleStream->gcount();
+        if (bytesgcount != bytesToRead) {
+            ALOGE("bytes to read %zu actual bytes read %zu \n", bytesToRead, bytesgcount);
+            mErrorCode = AMEDIA_ERROR_MALFORMED;
+            mSignalledError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+
+        uint32_t flag = 0;
+        if (mNumInputFrame == mParams.numFrames - 1 || bytesToRead == 0) {
+            ALOGD("Sending EOS on input Last frame\n");
+            flag |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
+        }
+
+        uint64_t presentationTimeUs;
+        if (!strncmp(mMime, "video/", 6)) {
+            presentationTimeUs = mNumInputFrame * (1000000 / mParams.frameRate);
+        } else {
+            presentationTimeUs =
+                    (uint64_t)mNumInputFrame * mParams.frameSize * 1000000 / mParams.sampleRate;
+        }
+
+        if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
+        ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRIu64 " mSawInputEOS : %s", __FUNCTION__,
+              bytesToRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
+
+        media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+                                                             bytesToRead, presentationTimeUs, flag);
+        if (AMEDIA_OK != status) {
+            mErrorCode = status;
+            mSignalledError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+        mNumInputFrame++;
+        mOffset += bytesToRead;
+    }
+}
+
+void Encoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
+                                AMediaCodecBufferInfo *bufferInfo) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        if (mSawOutputEOS || bufIdx < 0) return;
+        if (mSignalledError) {
+            CallBackHandle::mSawError = true;
+            mEncoderDoneCondition.notify_one();
+            return;
+        }
+
+        mStats->addFrameSize(bufferInfo->size);
+        AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
+        mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+        mNumOutputFrame++;
+        ALOGV("%s index : %d  mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
+              mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
+        if (mSawOutputEOS) {
+            CallBackHandle::mIsDone = true;
+            mEncoderDoneCondition.notify_one();
+        }
+    }
+}
+
+void Encoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
+        mFormat = format;
+    }
+}
+
+void Encoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+    ALOGV("In %s", __func__);
+    if (mediaCodec == mCodec && mediaCodec) {
+        ALOGE("Received Error %d", err);
+        mErrorCode = err;
+        mSignalledError = true;
+        mEncoderDoneCondition.notify_one();
+    }
+}
+
+void Encoder::setupEncoder() {
+    if (!mFormat) mFormat = AMediaFormat_new();
+}
+
+void Encoder::deInitCodec() {
+    if (mFormat) {
+        AMediaFormat_delete(mFormat);
+        mFormat = nullptr;
+    }
+    if (!mCodec) return;
+    int64_t sTime = mStats->getCurTime();
+    AMediaCodec_stop(mCodec);
+    AMediaCodec_delete(mCodec);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void Encoder::resetEncoder() {
+    if (mStats) mStats->reset();
+    if (mEleStream) mEleStream = nullptr;
+    if (mMime) mMime = nullptr;
+    mInputBufferSize = 0;
+    memset(&mParams, 0, sizeof mParams);
+}
+
+void Encoder::dumpStatistics(string inputReference, int64_t durationUs, string componentName,
+                             string mode, string statsFile) {
+    string operation = "encode";
+    mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
+}
+
+int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize, bool asyncMode,
+                        encParameter encParams, char *mime) {
+    ALOGV("In %s", __func__);
+    mEleStream = &eleStream;
+    mInputBufferSize = eleSize;
+    mParams = encParams;
+    mOffset = 0;
+    mMime = mime;
+    AMediaFormat_setString(mFormat, AMEDIAFORMAT_KEY_MIME, mMime);
+
+    // Set Format
+    if (!strncmp(mMime, "video/", 6)) {
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_WIDTH, mParams.width);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_HEIGHT, mParams.height);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_FRAME_RATE, mParams.frameRate);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_BIT_RATE, mParams.bitrate);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1);
+        if (mParams.profile && mParams.level) {
+            AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_PROFILE, mParams.profile);
+            AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_LEVEL, mParams.level);
+        }
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, mParams.colorFormat);
+    } else {
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE, mParams.sampleRate);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mParams.numChannels);
+        AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_BIT_RATE, mParams.bitrate);
+    }
+    const char *s = AMediaFormat_toString(mFormat);
+    ALOGI("Input format: %s\n", s);
+
+    int64_t sTime = mStats->getCurTime();
+    mCodec = createMediaCodec(mFormat, mMime, codecName, true /*isEncoder*/);
+    if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+
+    if (!strncmp(mMime, "video/", 6)) {
+        mParams.frameSize = mParams.width * mParams.height * 3 / 2;
+    } else {
+        mParams.frameSize = kDefaultAudioEncodeFrameSize;
+        // Get mInputMaxBufSize
+        AMediaFormat *inputFormat = AMediaCodec_getInputFormat(mCodec);
+        AMediaFormat_getInt32(inputFormat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, &mParams.maxFrameSize);
+        if (mParams.maxFrameSize < 0) {
+            mParams.maxFrameSize = kDefaultAudioEncodeFrameSize;
+        }
+        if (mParams.frameSize > mParams.maxFrameSize) {
+            mParams.frameSize = mParams.maxFrameSize;
+        }
+    }
+    mParams.numFrames = (mInputBufferSize + mParams.frameSize - 1) / mParams.frameSize;
+
+    sTime = mStats->getCurTime();
+    if (asyncMode) {
+        AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
+                                                OnFormatChangedCB, OnErrorCB};
+        AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
+        mIOThread = thread(&CallBackHandle::ioThread, this);
+    }
+    AMediaCodec_start(mCodec);
+    eTime = mStats->getCurTime();
+    timeTaken += mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+
+    mStats->setStartTime();
+    if (!asyncMode) {
+        while (!mSawOutputEOS && !mSignalledError) {
+            // Queue input data
+            if (!mSawInputEOS) {
+                ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
+                if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+                    ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
+                    mErrorCode = (media_status_t)inIdx;
+                    return mErrorCode;
+                } else if (inIdx >= 0) {
+                    mStats->addInputTime();
+                    onInputAvailable(mCodec, inIdx);
+                }
+            }
+
+            // Dequeue output data
+            AMediaCodecBufferInfo info;
+            ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
+            if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+                mFormat = AMediaCodec_getOutputFormat(mCodec);
+                const char *s = AMediaFormat_toString(mFormat);
+                ALOGI("Output format: %s\n", s);
+            } else if (outIdx >= 0) {
+                mStats->addOutputTime();
+                onOutputAvailable(mCodec, outIdx, &info);
+            } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
+                         outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
+                ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
+                mErrorCode = (media_status_t)outIdx;
+                return mErrorCode;
+            }
+        }
+    } else {
+        unique_lock<mutex> lock(mMutex);
+        mEncoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
+    }
+    if (mSignalledError) {
+        ALOGE("Received Error while Encoding");
+        return mErrorCode;
+    }
+
+    if (codecName.empty()) {
+        char *encName;
+        AMediaCodec_getName(mCodec, &encName);
+        codecName.assign(encName);
+        AMediaCodec_releaseName(mCodec, encName);
+    }
+    return AMEDIA_OK;
+}
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
new file mode 100644
index 0000000..5ad142b
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 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 __ENCODER_H__
+#define __ENCODER_H__
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include "media/NdkImage.h"
+#include "BenchmarkCommon.h"
+#include "Stats.h"
+
+
+struct encParameter {
+    int32_t bitrate = -1;
+    int32_t numFrames = -1;
+    int32_t frameSize = -1;
+    int32_t sampleRate = 0;
+    int32_t numChannels = 0;
+    int32_t maxFrameSize = -1;
+    int32_t width = 0;
+    int32_t height = 0;
+    int32_t frameRate = -1;
+    int32_t profile = 0;
+    int32_t level = 0;
+    int32_t colorFormat = AIMAGE_FORMAT_YUV_420_888;
+};
+
+class Encoder : public CallBackHandle {
+  public:
+    Encoder()
+        : mCodec(nullptr),
+          mFormat(nullptr),
+          mNumInputFrame(0),
+          mNumOutputFrame(0),
+          mSawInputEOS(false),
+          mSawOutputEOS(false),
+          mSignalledError(false),
+          mErrorCode(AMEDIA_OK) {}
+
+    virtual ~Encoder() {}
+
+    // Encoder related utilities
+    void setupEncoder();
+
+    void deInitCodec();
+
+    void resetEncoder();
+
+    // Async callback APIs
+    void onInputAvailable(AMediaCodec *codec, int32_t index) override;
+
+    void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+
+    void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
+    void onOutputAvailable(AMediaCodec *codec, int32_t index,
+                           AMediaCodecBufferInfo *bufferInfo) override;
+
+    // Process the frames and give encoded output
+    int32_t encode(std::string &codecName, std::ifstream &eleStream, size_t eleSize, bool asyncMode,
+                   encParameter encParams, char *mime);
+
+    void dumpStatistics(string inputReference, int64_t durationUs, string codecName = "",
+                        string mode = "", string statsFile = "");
+
+  private:
+    AMediaCodec *mCodec;
+    AMediaFormat *mFormat;
+
+    int32_t mNumInputFrame;
+    int32_t mNumOutputFrame;
+    bool mSawInputEOS;
+    bool mSawOutputEOS;
+    bool mSignalledError;
+    media_status_t mErrorCode;
+
+    char *mMime;
+    int32_t mOffset;
+    std::ifstream *mEleStream;
+    size_t mInputBufferSize;
+    encParameter mParams;
+
+    // Asynchronous locks
+    std::mutex mMutex;
+    std::condition_variable mEncoderDoneCondition;
+};
+#endif  // __ENCODER_H__
diff --git a/media/tests/benchmark/src/native/extractor/Android.bp b/media/tests/benchmark/src/native/extractor/Android.bp
new file mode 100644
index 0000000..7ed9476
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+    name: "libmediabenchmark_extractor",
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["Extractor.cpp"],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"]
+}
+
+cc_library_static {
+    name: "libmediabenchmark_codec2_extractor",
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: ["Extractor.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_codec2_common",
+    ],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.cpp b/media/tests/benchmark/src/native/extractor/Extractor.cpp
new file mode 100644
index 0000000..f0bb3b9
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 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 "extractor"
+
+#include <iostream>
+
+#include "Extractor.h"
+
+int32_t Extractor::initExtractor(int32_t fd, size_t fileSize) {
+    mStats = new Stats();
+
+    mFrameBuf = (uint8_t *)calloc(kMaxBufferSize, sizeof(uint8_t));
+    if (!mFrameBuf) return -1;
+
+    int64_t sTime = mStats->getCurTime();
+
+    mExtractor = AMediaExtractor_new();
+    if (!mExtractor) return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
+    media_status_t status = AMediaExtractor_setDataSourceFd(mExtractor, fd, 0, fileSize);
+    if (status != AMEDIA_OK) return status;
+
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+
+    return AMediaExtractor_getTrackCount(mExtractor);
+}
+
+void *Extractor::getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex) {
+    char csdName[kMaxCSDStrlen];
+    void *csdBuffer = nullptr;
+    frameInfo.presentationTimeUs = 0;
+    frameInfo.flags = AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
+    snprintf(csdName, sizeof(csdName), "csd-%d", csdIndex);
+
+    size_t size;
+    bool csdFound = AMediaFormat_getBuffer(mFormat, csdName, &csdBuffer, &size);
+    if (!csdFound) return nullptr;
+    frameInfo.size = (int32_t)size;
+    mStats->addFrameSize(frameInfo.size);
+
+    return csdBuffer;
+}
+
+int32_t Extractor::getFrameSample(AMediaCodecBufferInfo &frameInfo) {
+    int32_t size = AMediaExtractor_readSampleData(mExtractor, mFrameBuf, kMaxBufferSize);
+    if (size < 0) return -1;
+
+    frameInfo.flags = AMediaExtractor_getSampleFlags(mExtractor);
+    frameInfo.size = size;
+    mStats->addFrameSize(frameInfo.size);
+    frameInfo.presentationTimeUs = AMediaExtractor_getSampleTime(mExtractor);
+    AMediaExtractor_advance(mExtractor);
+
+    return 0;
+}
+
+int32_t Extractor::setupTrackFormat(int32_t trackId) {
+    AMediaExtractor_selectTrack(mExtractor, trackId);
+    mFormat = AMediaExtractor_getTrackFormat(mExtractor, trackId);
+    if (!mFormat) return AMEDIA_ERROR_INVALID_OBJECT;
+
+    bool durationFound = AMediaFormat_getInt64(mFormat, AMEDIAFORMAT_KEY_DURATION, &mDurationUs);
+    if (!durationFound) return AMEDIA_ERROR_INVALID_OBJECT;
+
+    return AMEDIA_OK;
+}
+
+int32_t Extractor::extract(int32_t trackId) {
+    int32_t status = setupTrackFormat(trackId);
+    if (status != AMEDIA_OK) return status;
+
+    int32_t idx = 0;
+    AMediaCodecBufferInfo frameInfo;
+    while (1) {
+        memset(&frameInfo, 0, sizeof(AMediaCodecBufferInfo));
+        void *csdBuffer = getCSDSample(frameInfo, idx);
+        if (!csdBuffer || !frameInfo.size) break;
+        idx++;
+    }
+
+    mStats->setStartTime();
+    while (1) {
+        int32_t status = getFrameSample(frameInfo);
+        if (status || !frameInfo.size) break;
+        mStats->addOutputTime();
+    }
+
+    if (mFormat) {
+        AMediaFormat_delete(mFormat);
+        mFormat = nullptr;
+    }
+
+    AMediaExtractor_unselectTrack(mExtractor, trackId);
+
+    return AMEDIA_OK;
+}
+
+void Extractor::dumpStatistics(string inputReference, string componentName, string statsFile) {
+    string operation = "extract";
+    mStats->dumpStatistics(operation, inputReference, mDurationUs, componentName, "", statsFile);
+}
+
+void Extractor::deInitExtractor() {
+    if (mFrameBuf) {
+        free(mFrameBuf);
+        mFrameBuf = nullptr;
+    }
+
+    int64_t sTime = mStats->getCurTime();
+    if (mExtractor) {
+        // TODO: (b/140128505) Multiple calls result in DoS.
+        // Uncomment call to AMediaExtractor_delete() once this is resolved
+        // AMediaExtractor_delete(mExtractor);
+        mExtractor = nullptr;
+    }
+    int64_t eTime = mStats->getCurTime();
+    int64_t deInitTime = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(deInitTime);
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.h b/media/tests/benchmark/src/native/extractor/Extractor.h
new file mode 100644
index 0000000..1694fc7
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 __EXTRACTOR_H__
+#define __EXTRACTOR_H__
+
+#include <media/NdkMediaExtractor.h>
+
+#include "BenchmarkCommon.h"
+#include "Stats.h"
+
+class Extractor {
+  public:
+    Extractor()
+        : mFormat(nullptr),
+          mExtractor(nullptr),
+          mStats(nullptr),
+          mFrameBuf{nullptr},
+          mDurationUs{0} {}
+
+    ~Extractor() {
+        if (mStats) delete mStats;
+    }
+
+    int32_t initExtractor(int32_t fd, size_t fileSize);
+
+    int32_t setupTrackFormat(int32_t trackId);
+
+    void *getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex);
+
+    int32_t getFrameSample(AMediaCodecBufferInfo &frameInfo);
+
+    int32_t extract(int32_t trackId);
+
+    void dumpStatistics(string inputReference, string componentName = "", string statsFile = "");
+
+    void deInitExtractor();
+
+    AMediaFormat *getFormat() { return mFormat; }
+
+    uint8_t *getFrameBuf() { return mFrameBuf; }
+
+    int64_t getClipDuration() { return mDurationUs; }
+
+  private:
+    AMediaFormat *mFormat;
+    AMediaExtractor *mExtractor;
+    Stats *mStats;
+    uint8_t *mFrameBuf;
+    int64_t mDurationUs;
+};
+
+#endif  // __EXTRACTOR_H__
\ No newline at end of file
diff --git a/media/tests/benchmark/src/native/muxer/Android.bp b/media/tests/benchmark/src/native/muxer/Android.bp
new file mode 100644
index 0000000..f669d4a
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+    name: "libmediabenchmark_muxer",
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["Muxer.cpp"],
+
+    static_libs: ["libmediabenchmark_extractor"],
+
+    export_include_dirs: ["."],
+
+    ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.cpp b/media/tests/benchmark/src/native/muxer/Muxer.cpp
new file mode 100644
index 0000000..3e150ca
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Muxer.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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 "muxer"
+
+#include <fstream>
+#include <iostream>
+
+#include "Muxer.h"
+
+int32_t Muxer::initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat) {
+    if (!mFormat) mFormat = mExtractor->getFormat();
+    if (!mStats) mStats = new Stats();
+
+    int64_t sTime = mStats->getCurTime();
+    mMuxer = AMediaMuxer_new(fd, (OutputFormat)outputFormat);
+    if (!mMuxer) {
+        ALOGV("Unable to create muxer");
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
+    /*
+     * AMediaMuxer_addTrack returns the index of the new track or a negative value
+     * in case of failure, which can be interpreted as a media_status_t.
+     */
+    ssize_t index = AMediaMuxer_addTrack(mMuxer, mFormat);
+    if (index < 0) {
+        ALOGV("Format not supported");
+        return index;
+    }
+    AMediaMuxer_start(mMuxer);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setInitTime(timeTaken);
+    return AMEDIA_OK;
+}
+
+void Muxer::deInitMuxer() {
+    if (mFormat) {
+        AMediaFormat_delete(mFormat);
+        mFormat = nullptr;
+    }
+    if (!mMuxer) return;
+    int64_t sTime = mStats->getCurTime();
+    AMediaMuxer_stop(mMuxer);
+    AMediaMuxer_delete(mMuxer);
+    int64_t eTime = mStats->getCurTime();
+    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+    mStats->setDeInitTime(timeTaken);
+}
+
+void Muxer::resetMuxer() {
+    if (mStats) mStats->reset();
+}
+
+void Muxer::dumpStatistics(string inputReference, string componentName, string statsFile) {
+    string operation = "mux";
+    mStats->dumpStatistics(operation, inputReference, mExtractor->getClipDuration(), componentName,
+                           "", statsFile);
+}
+
+int32_t Muxer::mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfos) {
+    // Mux frame data
+    size_t frameIdx = 0;
+    mStats->setStartTime();
+    while (frameIdx < frameInfos.size()) {
+        AMediaCodecBufferInfo info = frameInfos.at(frameIdx);
+        media_status_t status = AMediaMuxer_writeSampleData(mMuxer, 0, inputBuffer, &info);
+        if (status != 0) {
+            ALOGE("Error in AMediaMuxer_writeSampleData");
+            return status;
+        }
+        mStats->addOutputTime();
+        mStats->addFrameSize(info.size);
+        frameIdx++;
+    }
+    return AMEDIA_OK;
+}
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.h b/media/tests/benchmark/src/native/muxer/Muxer.h
new file mode 100644
index 0000000..860fdaf
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Muxer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 __MUXER_H__
+#define __MUXER_H__
+
+#include <media/NdkMediaMuxer.h>
+
+#include "BenchmarkCommon.h"
+#include "Stats.h"
+#include "Extractor.h"
+
+typedef enum {
+    MUXER_OUTPUT_FORMAT_MPEG_4 = 0,
+    MUXER_OUTPUT_FORMAT_WEBM = 1,
+    MUXER_OUTPUT_FORMAT_3GPP = 2,
+    MUXER_OUTPUT_FORMAT_OGG = 4,
+    MUXER_OUTPUT_FORMAT_INVALID = 5,
+} MUXER_OUTPUT_T;
+
+class Muxer {
+  public:
+    Muxer() : mFormat(nullptr), mMuxer(nullptr), mStats(nullptr) { mExtractor = new Extractor(); }
+
+    virtual ~Muxer() {
+        if (mStats) delete mStats;
+        if (mExtractor) delete mExtractor;
+    }
+
+    Stats *getStats() { return mStats; }
+    Extractor *getExtractor() { return mExtractor; }
+
+    /* Muxer related utilities */
+    int32_t initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat);
+    void deInitMuxer();
+    void resetMuxer();
+
+    /* Process the frames and give Muxed output */
+    int32_t mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameSizes);
+
+    void dumpStatistics(string inputReference, string codecName = "", string statsFile = "");
+
+  private:
+    AMediaFormat *mFormat;
+    AMediaMuxer *mMuxer;
+    Extractor *mExtractor;
+    Stats *mStats;
+};
+
+#endif  // __MUXER_H__
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
new file mode 100644
index 0000000..f46fa4a
--- /dev/null
+++ b/media/tests/benchmark/tests/Android.bp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+    name: "extractorTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["ExtractorTest.cpp"],
+
+    static_libs: ["libmediabenchmark_extractor"]
+}
+
+cc_test {
+    name: "decoderTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["DecoderTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_decoder",
+    ],
+}
+
+cc_test {
+    name: "muxerTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["MuxerTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_muxer",
+    ],
+}
+
+cc_test {
+    name: "encoderTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["EncoderTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_extractor",
+        "libmediabenchmark_decoder",
+        "libmediabenchmark_encoder",
+    ],
+}
+
+cc_test {
+    name: "C2DecoderTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+        "libmediabenchmark_soft_sanitize_all-defaults",
+    ],
+
+    srcs: ["C2DecoderTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_codec2_extractor",
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_codec2_decoder",
+    ],
+}
+
+cc_test {
+    name: "C2EncoderTest",
+    gtest: true,
+    defaults: [
+        "libmediabenchmark_codec2_common-defaults",
+    ],
+
+    srcs: ["C2EncoderTest.cpp"],
+
+    static_libs: [
+        "libmediabenchmark_codec2_extractor",
+        "libmediabenchmark_codec2_decoder",
+        "libmediabenchmark_codec2_common",
+        "libmediabenchmark_codec2_encoder",
+    ],
+}
diff --git a/media/tests/benchmark/tests/BenchmarkTestEnvironment.h b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
new file mode 100644
index 0000000..ae2eee1
--- /dev/null
+++ b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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 __BENCHMARK_TEST_ENVIRONMENT_H__
+#define __BENCHMARK_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class BenchmarkTestEnvironment : public ::testing::Environment {
+  public:
+    BenchmarkTestEnvironment() : res("/sdcard/media/") {}
+
+    // Parses the command line argument
+    int initFromOptions(int argc, char **argv);
+
+    void setRes(const char *_res) { res = _res; }
+
+    const string getRes() const { return res; }
+
+  private:
+    string res;
+};
+
+int BenchmarkTestEnvironment::initFromOptions(int argc, char **argv) {
+    static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+    while (true) {
+        int index = 0;
+        int c = getopt_long(argc, argv, "P:", options, &index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            case 'P': {
+                setRes(optarg);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (optind < argc) {
+        fprintf(stderr,
+                "unrecognized option: %s\n\n"
+                "usage: %s <gtest options> <test options>\n\n"
+                "test options are:\n\n"
+                "-P, --path: Resource files directory location\n",
+                argv[optind ?: 1], argv[0]);
+        return 2;
+    }
+    return 0;
+}
+
+#endif  // __BENCHMARK_TEST_ENVIRONMENT_H__
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
new file mode 100644
index 0000000..dedc743
--- /dev/null
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2019 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 "C2DecoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "BenchmarkTestEnvironment.h"
+#include "C2Decoder.h"
+#include "Extractor.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class C2DecoderTest : public ::testing::TestWithParam<pair<string, string>> {
+  public:
+    C2DecoderTest() : mDecoder(nullptr) {}
+
+    ~C2DecoderTest() {
+        if (!mCodecList.empty()) {
+            mCodecList.clear();
+        }
+        if (mDecoder) {
+            delete mDecoder;
+            mDecoder = nullptr;
+        }
+    }
+
+    virtual void SetUp() override { setupC2DecoderTest(); }
+
+    void setupC2DecoderTest();
+
+    vector<string> mCodecList;
+    C2Decoder *mDecoder;
+};
+
+void C2DecoderTest::setupC2DecoderTest() {
+    mDecoder = new C2Decoder();
+    ASSERT_NE(mDecoder, nullptr) << "C2Decoder creation failed";
+
+    int32_t status = mDecoder->setupCodec2();
+    ASSERT_EQ(status, 0) << "Codec2 setup failed";
+
+    mCodecList = mDecoder->getSupportedComponentList(false /* isEncoder*/);
+    ASSERT_GT(mCodecList.size(), 0) << "Codec2 client didn't recognise any component";
+}
+
+TEST_P(C2DecoderTest, Codec2Decode) {
+    ALOGV("Decode the samples given by extractor using codec2");
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
+
+    Extractor *extractor = new Extractor();
+    ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    ASSERT_LE(fileSize, kMaxBufferSize)
+            << "Input file size is greater than the threshold memory dedicated to the test";
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    for (int32_t curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        ASSERT_EQ(status, 0) << "Track Format invalid";
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+        int32_t idx = 0;
+
+        // Get CSD data
+        while (1) {
+            void *csdBuffer = extractor->getCSDSample(info, idx);
+            if (!csdBuffer || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+            idx++;
+        }
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        AMediaFormat *format = extractor->getFormat();
+        // Decode the given input stream for all C2 codecs supported by device
+        for (string codecName : mCodecList) {
+            if (codecName.find(GetParam().second) != string::npos &&
+                codecName.find("secure") == string::npos) {
+                status = mDecoder->createCodec2Component(codecName, format);
+                ASSERT_EQ(status, 0) << "Create component failed for " << codecName;
+
+                // Send the inputs to C2 Decoder and wait till all buffers are returned.
+                status = mDecoder->decodeFrames(inputBuffer, frameInfo);
+                ASSERT_EQ(status, 0) << "Decoder failed for " << codecName;
+
+                mDecoder->waitOnInputConsumption();
+                ASSERT_TRUE(mDecoder->mEos) << "Test Failed. Didn't receive EOS \n";
+
+                mDecoder->deInitCodec();
+                int64_t durationUs = extractor->getClipDuration();
+                ALOGV("codec : %s", codecName.c_str());
+                mDecoder->dumpStatistics(GetParam().first, durationUs);
+                mDecoder->resetDecoder();
+            }
+        }
+        free(inputBuffer);
+        fclose(inputFp);
+        extractor->deInitExtractor();
+        delete extractor;
+        delete mDecoder;
+        mDecoder = nullptr;
+    }
+}
+
+// TODO: (b/140549596)
+// Add wav files
+INSTANTIATE_TEST_SUITE_P(
+        AudioDecoderTest, C2DecoderTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
+                          make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "mp3"),
+                          make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
+                          make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrnb"),
+                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "vorbis"),
+                          make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
+                          make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
+
+INSTANTIATE_TEST_SUITE_P(
+        VideoDecoderTest, C2DecoderTest,
+        ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", "av1"),
+                          make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "mpeg2"),
+                          make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
+                          make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "h263"),
+                          make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "avc"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("C2 Decoder Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/tests/benchmark/tests/C2EncoderTest.cpp b/media/tests/benchmark/tests/C2EncoderTest.cpp
new file mode 100644
index 0000000..98eb17a
--- /dev/null
+++ b/media/tests/benchmark/tests/C2EncoderTest.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2019 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 "C2EncoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "BenchmarkTestEnvironment.h"
+#include "C2Encoder.h"
+#include "Decoder.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class C2EncoderTest : public ::testing::TestWithParam<pair<string, string>> {
+  public:
+    C2EncoderTest() : mEncoder(nullptr) {}
+
+    ~C2EncoderTest() {
+        if (!mCodecList.empty()) {
+            mCodecList.clear();
+        }
+        if (mEncoder) {
+            delete mEncoder;
+            mEncoder = nullptr;
+        }
+    }
+
+    virtual void SetUp() override { setupC2EncoderTest(); }
+
+    void setupC2EncoderTest();
+
+    vector<string> mCodecList;
+    C2Encoder *mEncoder;
+};
+
+void C2EncoderTest::setupC2EncoderTest() {
+    mEncoder = new C2Encoder();
+    ASSERT_NE(mEncoder, nullptr) << "C2Encoder creation failed";
+
+    int32_t status = mEncoder->setupCodec2();
+    ASSERT_EQ(status, 0) << "Codec2 setup failed";
+
+    mCodecList = mEncoder->getSupportedComponentList(true /* isEncoder*/);
+    ASSERT_GT(mCodecList.size(), 0) << "Codec2 client didn't recognise any component";
+}
+
+TEST_P(C2EncoderTest, Codec2Encode) {
+    ALOGV("Encodes the input using codec2 framework");
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open input file for reading";
+
+    Decoder *decoder = new Decoder();
+    ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
+
+    Extractor *extractor = decoder->getExtractor();
+    ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    ASSERT_LE(fileSize, kMaxBufferSize)
+            << "Input file size is greater than the threshold memory dedicated to the test";
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        ASSERT_EQ(status, 0) << "Track Format invalid";
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        string decName = "";
+        string outputFileName = "decode.out";
+        FILE *outFp = fopen(outputFileName.c_str(), "wb");
+        ASSERT_NE(outFp, nullptr) << "Unable to open output file" << outputFileName
+                                  << " for dumping decoder's output";
+
+        decoder->setupDecoder();
+        status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+        ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
+
+        // Encode the given input stream for all C2 codecs supported by device
+        AMediaFormat *format = extractor->getFormat();
+        ifstream eleStream;
+        eleStream.open(outputFileName.c_str(), ifstream::binary | ifstream::ate);
+        ASSERT_EQ(eleStream.is_open(), true) << outputFileName.c_str() << " - file not found";
+        size_t eleSize = eleStream.tellg();
+
+        for (string codecName : mCodecList) {
+            if (codecName.find(GetParam().second) != string::npos) {
+                status = mEncoder->createCodec2Component(codecName, format);
+                ASSERT_EQ(status, 0) << "Create component failed for " << codecName;
+
+                // Send the inputs to C2 Encoder and wait till all buffers are returned.
+                eleStream.seekg(0, ifstream::beg);
+                status = mEncoder->encodeFrames(eleStream, eleSize);
+                ASSERT_EQ(status, 0) << "Encoder failed for " << codecName;
+
+                mEncoder->waitOnInputConsumption();
+                ASSERT_TRUE(mEncoder->mEos) << "Test Failed. Didn't receive EOS \n";
+
+                mEncoder->deInitCodec();
+                int64_t durationUs = extractor->getClipDuration();
+                ALOGV("codec : %s", codecName.c_str());
+                mEncoder->dumpStatistics(GetParam().first, durationUs);
+                mEncoder->resetEncoder();
+            }
+        }
+
+        // Destroy the decoder for the given input
+        decoder->deInitCodec();
+        decoder->resetDecoder();
+        free(inputBuffer);
+    }
+    fclose(inputFp);
+    extractor->deInitExtractor();
+    delete decoder;
+    delete mEncoder;
+    mEncoder = nullptr;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        AudioEncoderTest, C2EncoderTest,
+        ::testing::Values(make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
+                          make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
+                          make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrwb"),
+                          make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
+                          make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
+
+INSTANTIATE_TEST_SUITE_P(
+        VideoEncoderTest, C2EncoderTest,
+        ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
+                          make_pair("crowd_176x144_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
+                          make_pair("crowd_176x144_25fps_6000kbps_h263.3gp", "h263"),
+                          make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "avc"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("C2 Encoder Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
new file mode 100644
index 0000000..9f96d3b
--- /dev/null
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 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 "decoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "BenchmarkTestEnvironment.h"
+#include "Decoder.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class DecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {};
+
+TEST_P(DecoderTest, Decode) {
+    ALOGV("Decode the samples given by extractor");
+    tuple<string /* InputFile */, string /* CodecName */, bool /* asyncMode */> params = GetParam();
+
+    string inputFile = gEnv->getRes() + get<0>(params);
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
+
+    Decoder *decoder = new Decoder();
+    ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
+
+    Extractor *extractor = decoder->getExtractor();
+    ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        ASSERT_EQ(status, 0) << "Track Format invalid";
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
+                    << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        string codecName = get<1>(params);
+        bool asyncMode = get<2>(params);
+        decoder->setupDecoder();
+        status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
+        ASSERT_EQ(status, AMEDIA_OK) << "Decoder failed for " << codecName;
+
+        decoder->deInitCodec();
+        ALOGV("codec : %s", codecName.c_str());
+        string inputReference = get<0>(params);
+        decoder->dumpStatistics(inputReference);
+        free(inputBuffer);
+        decoder->resetDecoder();
+    }
+    fclose(inputFp);
+    extractor->deInitExtractor();
+    delete decoder;
+}
+
+// TODO: (b/140549596)
+// Add wav files
+INSTANTIATE_TEST_SUITE_P(
+        AudioDecoderSyncTest, DecoderTest,
+        ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
+                          make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", false),
+                          make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
+                          make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
+                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "", false),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", false),
+                          make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
+
+INSTANTIATE_TEST_SUITE_P(
+        AudioDecoderAsyncTest, DecoderTest,
+        ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
+                          make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", true),
+                          make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
+                          make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
+                          make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.webm", "", true),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", true),
+                          make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
+
+INSTANTIATE_TEST_SUITE_P(VideDecoderSyncTest, DecoderTest,
+                         ::testing::Values(
+                                 // Hardware codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", false),
+                                 make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", false),
+                                 // Software codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+                                            "c2.android.vp9.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+                                            "c2.android.vp8.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
+                                            "c2.android.av1.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
+                                            "c2.android.mpeg2.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
+                                            "c2.android.mpeg4.decoder", false),
+                                 make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
+                                            "c2.android.h263.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+                                            "c2.android.avc.decoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+                                            "c2.android.hevc.decoder", false)));
+
+INSTANTIATE_TEST_SUITE_P(VideoDecoderAsyncTest, DecoderTest,
+                         ::testing::Values(
+                                 // Hardware codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", true),
+                                 make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", true),
+                                 // Software codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+                                            "c2.android.vp9.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+                                            "c2.android.vp8.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
+                                            "c2.android.av1.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
+                                            "c2.android.mpeg2.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
+                                            "c2.android.mpeg4.decoder", true),
+                                 make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
+                                            "c2.android.h263.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+                                            "c2.android.avc.decoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+                                            "c2.android.hevc.decoder", true)));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD("Decoder Test result = %d\n", status);
+    }
+    return status;
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
new file mode 100644
index 0000000..dc2a2dd
--- /dev/null
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2019 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 "encoderTest"
+
+#include <fstream>
+
+#include "BenchmarkTestEnvironment.h"
+#include "Decoder.h"
+#include "Encoder.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class EncoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {};
+
+TEST_P(EncoderTest, Encode) {
+    ALOGD("Encode test for all codecs");
+    tuple<string /* InputFile */, string /* CodecName */, bool /* asyncMode */> params = GetParam();
+
+    string inputFile = gEnv->getRes() + get<0>(params);
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
+
+    Decoder *decoder = new Decoder();
+    ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
+
+    Extractor *extractor = decoder->getExtractor();
+    ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    Encoder *encoder = new Encoder();
+    ASSERT_NE(encoder, nullptr) << "Decoder creation failed";
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        ASSERT_EQ(status, 0) << "Track Format invalid";
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
+
+        vector<AMediaCodecBufferInfo> frameInfo;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get frame data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to decoder
+            ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
+                    << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            frameInfo.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        string decName = "";
+        string outputFileName = "decode.out";
+        FILE *outFp = fopen(outputFileName.c_str(), "wb");
+        ASSERT_NE(outFp, nullptr) << "Unable to open output file" << outputFileName
+                                  << " for dumping decoder's output";
+
+        decoder->setupDecoder();
+        status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+        ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
+
+        ifstream eleStream;
+        eleStream.open(outputFileName.c_str(), ifstream::binary | ifstream::ate);
+        ASSERT_EQ(eleStream.is_open(), true) << outputFileName.c_str() << " - file not found";
+        size_t eleSize = eleStream.tellg();
+        eleStream.seekg(0, ifstream::beg);
+
+        AMediaFormat *format = extractor->getFormat();
+        const char *mime = nullptr;
+        AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+        ASSERT_NE(mime, nullptr) << "Invalid mime type";
+
+        // Get encoder params
+        encParameter encParams;
+        if (!strncmp(mime, "video/", 6)) {
+            ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &encParams.width));
+            ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &encParams.height));
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
+            if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
+                encParams.frameRate = 25;
+                if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
+                    encParams.bitrate = 600000 /* 600 Kbps */;
+                } else {
+                    encParams.bitrate = 8000000 /* 8 Mbps */;
+                }
+            }
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
+        } else {
+            ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE,
+                                              &encParams.sampleRate));
+            ASSERT_TRUE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
+                                              &encParams.numChannels));
+            encParams.bitrate =
+                    encParams.sampleRate * encParams.numChannels * 16 /* bitsPerSample */;
+        }
+
+        encoder->setupEncoder();
+        string codecName = get<1>(params);
+        bool asyncMode = get<2>(params);
+        status = encoder->encode(codecName, eleStream, eleSize, asyncMode, encParams, (char *)mime);
+        ASSERT_EQ(status, 0) << "Encoder failed for " << codecName;
+
+        encoder->deInitCodec();
+        ALOGV("codec : %s", codecName.c_str());
+        string inputReference = get<0>(params);
+        encoder->dumpStatistics(inputReference, extractor->getClipDuration());
+        eleStream.close();
+        if (outFp) fclose(outFp);
+
+        if (format) {
+            AMediaFormat_delete(format);
+            format = nullptr;
+        }
+        encoder->resetEncoder();
+        decoder->deInitCodec();
+        free(inputBuffer);
+        decoder->resetDecoder();
+    }
+    delete encoder;
+    fclose(inputFp);
+    extractor->deInitExtractor();
+    delete decoder;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        AudioEncoderSyncTest, EncoderTest,
+        ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
+                          make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
+                          make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", false),
+                          make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
+
+INSTANTIATE_TEST_SUITE_P(
+        AudioEncoderAsyncTest, EncoderTest,
+        ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
+                          make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
+                          make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
+                          make_tuple("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "", true),
+                          make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
+
+INSTANTIATE_TEST_SUITE_P(VideEncoderSyncTest, EncoderTest,
+                         ::testing::Values(
+                                 // Hardware codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", false),
+                                 // Software codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+                                            "c2.android.vp9.encoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+                                            "c2.android.vp8.encoder", false),
+                                 make_tuple("crowd_176x144_25fps_6000kbps_mpeg4.mp4",
+                                            "c2.android.mpeg4.encoder", false),
+                                 make_tuple("crowd_176x144_25fps_6000kbps_h263.3gp",
+                                            "c2.android.h263.encoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+                                            "c2.android.avc.encoder", false),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+                                            "c2.android.hevc.encoder", false)));
+
+INSTANTIATE_TEST_SUITE_P(VideoEncoderAsyncTest, EncoderTest,
+                         ::testing::Values(
+                                 // Hardware codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", true),
+                                 // Software codecs
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+                                            "c2.android.vp9.encoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+                                            "c2.android.vp8.encoder", true),
+                                 make_tuple("crowd_176x144_25fps_6000kbps_mpeg4.mp4",
+                                            "c2.android.mpeg4.encoder", true),
+                                 make_tuple("crowd_176x144_25fps_6000kbps_h263.3gp",
+                                            "c2.android.h263.encoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+                                            "c2.android.avc.encoder", true),
+                                 make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+                                            "c2.android.hevc.encoder", true)));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD("Encoder Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
new file mode 100644
index 0000000..ad8f1e6
--- /dev/null
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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 "extractorTest"
+
+#include <gtest/gtest.h>
+
+#include "BenchmarkTestEnvironment.h"
+#include "Extractor.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class ExtractorTest : public ::testing::TestWithParam<pair<string, int32_t>> {};
+
+TEST_P(ExtractorTest, Extract) {
+    Extractor *extractObj = new Extractor();
+    ASSERT_NE(extractObj, nullptr) << "Extractor creation failed";
+
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    int32_t trackCount = extractObj->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    int32_t trackID = GetParam().second;
+    int32_t status = extractObj->extract(trackID);
+    ASSERT_EQ(status, AMEDIA_OK) << "Extraction failed \n";
+
+    extractObj->deInitExtractor();
+
+    extractObj->dumpStatistics(GetParam().first);
+
+    fclose(inputFp);
+    delete extractObj;
+}
+
+INSTANTIATE_TEST_SUITE_P(ExtractorTestAll, ExtractorTest,
+                         ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", 0),
+                                           make_pair("crowd_1920x1080_25fps_6000kbps_h263.3gp", 0),
+                                           make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", 0),
+                                           make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", 0),
+                                           make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", 0),
+                                           make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", 0),
+                                           make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", 0),
+                                           make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", 0),
+                                           make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", 0),
+                                           make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0),
+                                           make_pair("bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0),
+                                           make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0),
+                                           make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0),
+                                           make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", 0),
+                                           make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm",
+                                                     0)));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGD(" Extractor Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
new file mode 100644
index 0000000..fa2635d
--- /dev/null
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -0,0 +1,158 @@
+
+/*
+ * Copyright (C) 2019 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 "muxerTest"
+
+#include <fstream>
+#include <iostream>
+
+#include "BenchmarkTestEnvironment.h"
+#include "Muxer.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/mux.out"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class MuxerTest : public ::testing::TestWithParam<pair<string, string>> {};
+
+static MUXER_OUTPUT_T getMuxerOutFormat(string fmt) {
+    static const struct {
+        string name;
+        MUXER_OUTPUT_T value;
+    } kFormatMaps[] = {{"mp4", MUXER_OUTPUT_FORMAT_MPEG_4},
+                       {"webm", MUXER_OUTPUT_FORMAT_WEBM},
+                       {"3gpp", MUXER_OUTPUT_FORMAT_3GPP},
+                       {"ogg", MUXER_OUTPUT_FORMAT_OGG}};
+
+    MUXER_OUTPUT_T format = MUXER_OUTPUT_FORMAT_INVALID;
+    for (size_t i = 0; i < sizeof(kFormatMaps) / sizeof(kFormatMaps[0]); ++i) {
+        if (!fmt.compare(kFormatMaps[i].name)) {
+            format = kFormatMaps[i].value;
+            break;
+        }
+    }
+    return format;
+}
+
+TEST_P(MuxerTest, Mux) {
+    ALOGV("Mux the samples given by extractor");
+    string inputFile = gEnv->getRes() + GetParam().first;
+    FILE *inputFp = fopen(inputFile.c_str(), "rb");
+    ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
+
+    string fmt = GetParam().second;
+    MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
+    ASSERT_NE(outputFormat, MUXER_OUTPUT_FORMAT_INVALID) << "Invalid muxer output format";
+
+    Muxer *muxerObj = new Muxer();
+    ASSERT_NE(muxerObj, nullptr) << "Muxer creation failed";
+
+    Extractor *extractor = muxerObj->getExtractor();
+    ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
+
+    // Read file properties
+    struct stat buf;
+    stat(inputFile.c_str(), &buf);
+    size_t fileSize = buf.st_size;
+    int32_t fd = fileno(inputFp);
+
+    int32_t trackCount = extractor->initExtractor(fd, fileSize);
+    ASSERT_GT(trackCount, 0) << "initExtractor failed";
+
+    for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+        int32_t status = extractor->setupTrackFormat(curTrack);
+        ASSERT_EQ(status, 0) << "Track Format invalid";
+
+        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
+
+        // AMediaCodecBufferInfo : <size of frame> <flags> <presentationTimeUs> <offset>
+        vector<AMediaCodecBufferInfo> frameInfos;
+        AMediaCodecBufferInfo info;
+        uint32_t inputBufferOffset = 0;
+
+        // Get Frame Data
+        while (1) {
+            status = extractor->getFrameSample(info);
+            if (status || !info.size) break;
+            // copy the meta data and buffer to be passed to muxer
+            ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
+                    << "Memory allocated not sufficient";
+
+            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            info.offset = inputBufferOffset;
+            frameInfos.push_back(info);
+            inputBufferOffset += info.size;
+        }
+
+        string outputFileName = OUTPUT_FILE_NAME;
+        FILE *outputFp = fopen(outputFileName.c_str(), "w+b");
+        ASSERT_NE(outputFp, nullptr)
+                << "Unable to open output file" << outputFileName << " for writing";
+
+        int32_t fd = fileno(outputFp);
+        status = muxerObj->initMuxer(fd, outputFormat);
+        ASSERT_EQ(status, 0) << "initMuxer failed";
+
+        status = muxerObj->mux(inputBuffer, frameInfos);
+        ASSERT_EQ(status, 0) << "Mux failed";
+
+        muxerObj->deInitMuxer();
+        muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str());
+        free(inputBuffer);
+        fclose(outputFp);
+        muxerObj->resetMuxer();
+    }
+    fclose(inputFp);
+    extractor->deInitExtractor();
+    delete muxerObj;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        MuxerTestAll, MuxerTest,
+        ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "webm"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "webm"),
+                          make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mp4"),
+                          make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "mp4"),
+                          make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "mp4"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "mp4"),
+                          make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "3gpp"),
+                          make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "3gpp"),
+                          make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"),
+                          make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"),
+                          make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"),
+                          make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.webm", "webm"),
+                          make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"),
+                          make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"),
+                          make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"),
+                          make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "mp4"),
+                          make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "3gpp"),
+                          make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "3gpp"),
+                          make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp")));
+
+int main(int argc, char **argv) {
+    gEnv = new BenchmarkTestEnvironment();
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        status = RUN_ALL_TESTS();
+        ALOGV("Test result = %d\n", status);
+    }
+    return status;
+}
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index e2cd4e3..e3f1e44 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -19,18 +19,22 @@
         "AImageReaderUtils.cpp",
         "BatteryNotifier.cpp",
         "ISchedulingPolicyService.cpp",
+        "LimitProcessMemory.cpp",
         "MemoryLeakTrackUtil.cpp",
         "ProcessInfo.cpp",
         "SchedulingPolicyService.cpp",
         "ServiceUtilities.cpp",
         "TimeCheck.cpp",
     ],
+    static_libs: [
+        "libc_malloc_debug_backtrace",
+    ],
     shared_libs: [
+        "libaudioutils", // for clock.h
         "libbinder",
         "libcutils",
         "liblog",
         "libutils",
-        "libmemunreachable",
         "libhidlbase",
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hidl.token@1.0-utils",
@@ -44,15 +48,14 @@
         "-Werror",
     ],
 
-    product_variables: {
-        product_is_iot: {
-            cflags: ["-DTARGET_ANDROID_THINGS"],
-        },
-    },
+    header_libs: [
+        "bionic_libc_platform_headers",
+        "libmedia_headers",
+    ],
 
     include_dirs: [
-        // For android_mallopt definitions.
-        "bionic/libc/private"
+        // For DEBUGGER_SIGNAL
+        "system/core/debuggerd/include",
     ],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
diff --git a/media/utils/ISchedulingPolicyService.cpp b/media/utils/ISchedulingPolicyService.cpp
index b210404..e60e230 100644
--- a/media/utils/ISchedulingPolicyService.cpp
+++ b/media/utils/ISchedulingPolicyService.cpp
@@ -62,12 +62,12 @@
         return reply.readInt32();
     }
 
-    virtual int requestCpusetBoost(bool enable, const sp<IInterface>& client)
+    virtual int requestCpusetBoost(bool enable, const sp<IBinder>& client)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
         data.writeInt32(enable);
-        data.writeStrongBinder(IInterface::asBinder(client));
+        data.writeStrongBinder(client);
         status_t status = remote()->transact(REQUEST_CPUSET_BOOST, data, &reply, 0);
         if (status != NO_ERROR) {
             return status;
diff --git a/media/utils/ISchedulingPolicyService.h b/media/utils/ISchedulingPolicyService.h
index e4f7c0d..6fa100a 100644
--- a/media/utils/ISchedulingPolicyService.h
+++ b/media/utils/ISchedulingPolicyService.h
@@ -29,7 +29,7 @@
     virtual int         requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
                                         int32_t prio, bool isForApp, bool asynchronous) = 0;
 
-    virtual int         requestCpusetBoost(bool enable, const sp<IInterface>& client) = 0;
+    virtual int         requestCpusetBoost(bool enable, const sp<IBinder>& client) = 0;
 };
 
 class BnSchedulingPolicyService : public BnInterface<ISchedulingPolicyService>
diff --git a/media/utils/LimitProcessMemory.cpp b/media/utils/LimitProcessMemory.cpp
new file mode 100644
index 0000000..623138f
--- /dev/null
+++ b/media/utils/LimitProcessMemory.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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_TAG "MediaUtils"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <cutils/properties.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+#include <bionic/malloc.h>
+#include <mediautils/LimitProcessMemory.h>
+
+extern "C" void __scudo_set_rss_limit(size_t, int) __attribute__((weak));
+
+namespace android {
+
+void limitProcessMemory(const char *property, size_t numberOfBytes,
+                        size_t percentageOfTotalMem) {
+    long pageSize = sysconf(_SC_PAGESIZE);
+    long numPages = sysconf(_SC_PHYS_PAGES);
+    size_t maxMem = SIZE_MAX;
+
+    if (pageSize > 0 && numPages > 0) {
+        if (size_t(numPages) < SIZE_MAX / size_t(pageSize)) {
+            maxMem = size_t(numPages) * size_t(pageSize);
+        }
+        ALOGV("physMem: %zu", maxMem);
+        if (percentageOfTotalMem > 100) {
+            ALOGW("requested %zu%% of total memory, using 100%%", percentageOfTotalMem);
+            percentageOfTotalMem = 100;
+        }
+        maxMem = maxMem / 100 * percentageOfTotalMem;
+        if (numberOfBytes < maxMem) {
+            maxMem = numberOfBytes;
+        }
+        ALOGV("requested limit: %zu", maxMem);
+    } else {
+        ALOGW("couldn't determine total RAM");
+    }
+
+    int64_t propVal = property_get_int64(property, maxMem);
+    if (propVal > 0 && uint64_t(propVal) <= SIZE_MAX) {
+        maxMem = propVal;
+    }
+
+    // If Scudo is in use, enforce the hard RSS limit (in MB).
+    if (maxMem != SIZE_MAX && &__scudo_set_rss_limit != 0) {
+      __scudo_set_rss_limit(maxMem >> 20, 1);
+      ALOGV("Scudo hard RSS limit set to %zu MB", maxMem >> 20);
+      return;
+    }
+
+    if (!android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &maxMem,
+                         sizeof(maxMem))) {
+      ALOGW("couldn't set allocation limit");
+    }
+}
+
+} // namespace android
diff --git a/media/utils/MemoryLeakTrackUtil.cpp b/media/utils/MemoryLeakTrackUtil.cpp
index 2988b52..fdb8c4f 100644
--- a/media/utils/MemoryLeakTrackUtil.cpp
+++ b/media/utils/MemoryLeakTrackUtil.cpp
@@ -19,10 +19,10 @@
 #define LOG_TAG "MemoryLeackTrackUtil"
 #include <utils/Log.h>
 
-#include "media/MemoryLeakTrackUtil.h"
+#include <mediautils/MemoryLeakTrackUtil.h>
 #include <sstream>
 
-#include <bionic_malloc.h>
+#include <bionic/malloc.h>
 
 /*
  * The code here originally resided in MediaPlayerService.cpp
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index 27f1a79..113e4a7 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -23,6 +23,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IProcessInfoService.h>
 #include <binder/IServiceManager.h>
+#include <private/android_filesystem_config.h>
 
 namespace android {
 
@@ -55,8 +56,9 @@
 
 bool ProcessInfo::isValidPid(int pid) {
     int callingPid = IPCThreadState::self()->getCallingPid();
+    int callingUid = IPCThreadState::self()->getCallingUid();
     // Trust it if this is called from the same process otherwise pid has to match the calling pid.
-    return (callingPid == getpid()) || (callingPid == pid);
+    return (callingPid == getpid()) || (callingPid == pid) || (callingUid == AID_MEDIA);
 }
 
 ProcessInfo::~ProcessInfo() {}
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
index 4e9792f..ad38862 100644
--- a/media/utils/SchedulingPolicyService.cpp
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -59,7 +59,7 @@
     return ret;
 }
 
-int requestCpusetBoost(bool enable, const sp<IInterface> &client)
+int requestCpusetBoost(bool enable, const sp<IBinder> &client)
 {
     int ret;
     sMutex.lock();
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index bc8fff6..87ea084 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "ServiceUtilities"
 
+#include <audio_utils/clock.h>
 #include <binder/AppOpsManager.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -24,6 +25,7 @@
 
 #include <iterator>
 #include <algorithm>
+#include <pwd.h>
 
 /* When performing permission checks we do not use permission cache for
  * runtime permissions (protection level dangerous) as they may change at
@@ -61,12 +63,12 @@
 
 static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
         uid_t uid, bool start) {
-    // Okay to not track in app ops as audio server is us and if
+    // Okay to not track in app ops as audio server or media server is us and if
     // device is rooted security model is considered compromised.
     // system_server loses its RECORD_AUDIO permission when a secondary
     // user is active, but it is a core system service so let it through.
     // TODO(b/141210120): UserManager.DISALLOW_RECORD_AUDIO should not affect system user 0
-    if (isAudioServerOrSystemServerOrRootUid(uid)) return true;
+    if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return true;
 
     // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
     // may open a record track on behalf of a client.  Note that pid may be a tid.
@@ -143,6 +145,15 @@
     return ok;
 }
 
+bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid) {
+    if (isAudioServerOrRootUid(uid)) return true;
+    static const String16 sCaptureVoiceCommOutput(
+        "android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT");
+    bool ok = PermissionCache::checkPermission(sCaptureVoiceCommOutput, pid, uid);
+    if (!ok) ALOGE("Request requires android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT");
+    return ok;
+}
+
 bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
     // CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
     bool ok = recordingAllowed(opPackageName, pid, uid);
@@ -167,30 +178,33 @@
 }
 
 bool modifyAudioRoutingAllowed() {
+    return modifyAudioRoutingAllowed(
+        IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
+}
+
+bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid) {
+    if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
-    bool ok = PermissionCache::checkCallingPermission(sModifyAudioRouting);
-    if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING");
+    bool ok = PermissionCache::checkPermission(sModifyAudioRouting, pid, uid);
+    if (!ok) ALOGE("%s(): android.permission.MODIFY_AUDIO_ROUTING denied for uid %d",
+        __func__, uid);
     return ok;
 }
 
 bool modifyDefaultAudioEffectsAllowed() {
+    return modifyDefaultAudioEffectsAllowed(
+        IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
+}
+
+bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid) {
+    if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
+
     static const String16 sModifyDefaultAudioEffectsAllowed(
             "android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
     // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
-    bool ok = PermissionCache::checkCallingPermission(sModifyDefaultAudioEffectsAllowed);
-
-#ifdef TARGET_ANDROID_THINGS
-    if (!ok) {
-        // Use a secondary permission on Android Things to allow a more lenient level of protection.
-        static const String16 sModifyDefaultAudioEffectsAndroidThingsAllowed(
-                "com.google.android.things.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
-        ok = PermissionCache::checkCallingPermission(
-                sModifyDefaultAudioEffectsAndroidThingsAllowed);
-    }
-    if (!ok) ALOGE("com.google.android.things.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
-#else
-    if (!ok) ALOGE("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
-#endif
+    bool ok = PermissionCache::checkPermission(sModifyDefaultAudioEffectsAllowed, pid, uid);
+    ALOGE_IF(!ok, "%s(): android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS denied for uid %d",
+            __func__, uid);
     return ok;
 }
 
@@ -236,9 +250,9 @@
     off_t size = lseek(heap->getHeapID(), 0, SEEK_END);
     lseek(heap->getHeapID(), 0, SEEK_SET);
 
-    if (iMemory->pointer() == NULL || size < (off_t)iMemory->size()) {
+    if (iMemory->unsecurePointer() == NULL || size < (off_t)iMemory->size()) {
         ALOGE("%s check failed: pointer %p size %zu fd size %u",
-              __FUNCTION__, iMemory->pointer(), iMemory->size(), (uint32_t)size);
+              __FUNCTION__, iMemory->unsecurePointer(), iMemory->size(), (uint32_t)size);
         return BAD_VALUE;
     }
 
@@ -326,4 +340,130 @@
     }
 }
 
+// How long we hold info before we re-fetch it (24 hours) if we found it previously.
+static constexpr nsecs_t INFO_EXPIRATION_NS = 24 * 60 * 60 * NANOS_PER_SECOND;
+// Maximum info records we retain before clearing everything.
+static constexpr size_t INFO_CACHE_MAX = 1000;
+
+// The original code is from MediaMetricsService.cpp.
+mediautils::UidInfo::Info mediautils::UidInfo::getInfo(uid_t uid)
+{
+    const nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+    struct mediautils::UidInfo::Info info;
+    {
+        std::lock_guard _l(mLock);
+        auto it = mInfoMap.find(uid);
+        if (it != mInfoMap.end()) {
+            info = it->second;
+            ALOGV("%s: uid %d expiration %lld now %lld",
+                    __func__, uid, (long long)info.expirationNs, (long long)now);
+            if (info.expirationNs <= now) {
+                // purge the stale entry and fall into re-fetching
+                ALOGV("%s: entry for uid %d expired, now %lld",
+                        __func__, uid, (long long)now);
+                mInfoMap.erase(it);
+                info.uid = (uid_t)-1;  // this is always fully overwritten
+            }
+        }
+    }
+
+    // if we did not find it in our map, look it up
+    if (info.uid == (uid_t)(-1)) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<content::pm::IPackageManagerNative> package_mgr;
+        if (sm.get() == nullptr) {
+            ALOGE("%s: Cannot find service manager", __func__);
+        } else {
+            sp<IBinder> binder = sm->getService(String16("package_native"));
+            if (binder.get() == nullptr) {
+                ALOGE("%s: Cannot find package_native", __func__);
+            } else {
+                package_mgr = interface_cast<content::pm::IPackageManagerNative>(binder);
+            }
+        }
+
+        // find package name
+        std::string pkg;
+        if (package_mgr != nullptr) {
+            std::vector<std::string> names;
+            binder::Status status = package_mgr->getNamesForUids({(int)uid}, &names);
+            if (!status.isOk()) {
+                ALOGE("%s: getNamesForUids failed: %s",
+                        __func__, status.exceptionMessage().c_str());
+            } else {
+                if (!names[0].empty()) {
+                    pkg = names[0].c_str();
+                }
+            }
+        }
+
+        if (pkg.empty()) {
+            struct passwd pw{}, *result;
+            char buf[8192]; // extra buffer space - should exceed what is
+                            // required in struct passwd_pw (tested),
+                            // and even then this is only used in backup
+                            // when the package manager is unavailable.
+            if (getpwuid_r(uid, &pw, buf, sizeof(buf), &result) == 0
+                    && result != nullptr
+                    && result->pw_name != nullptr) {
+                pkg = result->pw_name;
+            }
+        }
+
+        // strip any leading "shared:" strings that came back
+        if (pkg.compare(0, 7, "shared:") == 0) {
+            pkg.erase(0, 7);
+        }
+
+        // determine how pkg was installed and the versionCode
+        std::string installer;
+        int64_t versionCode = 0;
+        bool notFound = false;
+        if (pkg.empty()) {
+            pkg = std::to_string(uid); // not found
+            notFound = true;
+        } else if (strchr(pkg.c_str(), '.') == nullptr) {
+            // not of form 'com.whatever...'; assume internal
+            // so we don't need to look it up in package manager.
+        } else if (strncmp(pkg.c_str(), "android.", 8) == 0) {
+            // android.* packages are assumed fine
+        } else if (package_mgr.get() != nullptr) {
+            String16 pkgName16(pkg.c_str());
+            binder::Status status = package_mgr->getInstallerForPackage(pkgName16, &installer);
+            if (!status.isOk()) {
+                ALOGE("%s: getInstallerForPackage failed: %s",
+                        __func__, status.exceptionMessage().c_str());
+            }
+
+            // skip if we didn't get an installer
+            if (status.isOk()) {
+                status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode);
+                if (!status.isOk()) {
+                    ALOGE("%s: getVersionCodeForPackage failed: %s",
+                            __func__, status.exceptionMessage().c_str());
+                }
+            }
+
+            ALOGV("%s: package '%s' installed by '%s' versioncode %lld",
+                    __func__, pkg.c_str(), installer.c_str(), (long long)versionCode);
+        }
+
+        // add it to the map, to save a subsequent lookup
+        std::lock_guard _l(mLock);
+        // first clear if we have too many cached elements.  This would be rare.
+        if (mInfoMap.size() >= INFO_CACHE_MAX) mInfoMap.clear();
+
+        // always overwrite
+        info.uid = uid;
+        info.package = std::move(pkg);
+        info.installer = std::move(installer);
+        info.versionCode = versionCode;
+        info.expirationNs = now + (notFound ? 0 : INFO_EXPIRATION_NS);
+        ALOGV("%s: adding uid %d package '%s' expirationNs: %lld",
+                __func__, uid, info.package.c_str(), (long long)info.expirationNs);
+        mInfoMap[uid] = info;
+    }
+    return info;
+}
+
 } // namespace android
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index f16776f..59d74de 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -14,13 +14,50 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "TimeCheck"
 
 #include <utils/Log.h>
-#include <media/TimeCheck.h>
-#include <media/EventLog.h>
+#include <mediautils/TimeCheck.h>
+#include <mediautils/EventLog.h>
+#include "debuggerd/handler.h"
 
 namespace android {
 
+// Audio HAL server pids vector used to generate audio HAL processes tombstone
+// when audioserver watchdog triggers.
+// We use a lockless storage to avoid potential deadlocks in the context of watchdog
+// trigger.
+// Protection again simultaneous writes is not needed given one update takes place
+// during AudioFlinger construction and other comes necessarily later once the IAudioFlinger
+// interface is available.
+// The use of an atomic index just guaranties that current vector is fully initialized
+// when read.
+/* static */
+void TimeCheck::accessAudioHalPids(std::vector<pid_t>* pids, bool update) {
+    static constexpr int kNumAudioHalPidsVectors = 3;
+    static std::vector<pid_t> audioHalPids[kNumAudioHalPidsVectors];
+    static std::atomic<int> curAudioHalPids = 0;
+
+    if (update) {
+        audioHalPids[(curAudioHalPids + 1) % kNumAudioHalPidsVectors] = *pids;
+        curAudioHalPids++;
+    } else {
+        *pids = audioHalPids[curAudioHalPids];
+    }
+}
+
+/* static */
+void TimeCheck::setAudioHalPids(const std::vector<pid_t>& pids) {
+    accessAudioHalPids(&(const_cast<std::vector<pid_t>&>(pids)), true);
+}
+
+/* static */
+std::vector<pid_t> TimeCheck::getAudioHalPids() {
+    std::vector<pid_t> pids;
+    accessAudioHalPids(&pids, false);
+    return pids;
+}
+
 /* static */
 sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
 {
@@ -63,7 +100,6 @@
 bool TimeCheck::TimeCheckThread::threadLoop()
 {
     status_t status = TIMED_OUT;
-    const char *tag;
     {
         AutoMutex _l(mMutex);
 
@@ -72,6 +108,7 @@
         }
 
         nsecs_t endTimeNs = INT64_MAX;
+        const char *tag = "<unspecified>";
         // KeyedVector mMonitorRequests is ordered so take first entry as next timeout
         if (mMonitorRequests.size() != 0) {
             endTimeNs = mMonitorRequests.keyAt(0);
@@ -83,6 +120,18 @@
             status = mCond.waitRelative(mMutex, waitTimeNs);
         }
         if (status != NO_ERROR) {
+            // Generate audio HAL processes tombstones and allow time to complete
+            // before forcing restart
+            std::vector<pid_t> pids = getAudioHalPids();
+            if (pids.size() != 0) {
+                for (const auto& pid : pids) {
+                    ALOGI("requesting tombstone for pid: %d", pid);
+                    sigqueue(pid, DEBUGGER_SIGNAL, {.sival_int = 0});
+                }
+                sleep(1);
+            } else {
+                ALOGI("No HAL process pid available, skipping tombstones");
+            }
             LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag);
             LOG_ALWAYS_FATAL("TimeCheck timeout for %s", tag);
         }
diff --git a/media/utils/include/mediautils/LimitProcessMemory.h b/media/utils/include/mediautils/LimitProcessMemory.h
new file mode 100644
index 0000000..7f48b4f
--- /dev/null
+++ b/media/utils/include/mediautils/LimitProcessMemory.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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 ANDROID_MEDIAUTILS_LIMIT_PROCESS_MEMORY_H
+#define ANDROID_MEDIAUTILS_LIMIT_PROCESS_MEMORY_H
+
+namespace android {
+
+/**
+   Limit the amount of memory a process can allocate using setrlimit(RLIMIT_AS).
+   The value to use will be read from the specified system property, or if the
+   property doesn't exist it will use the specified number of bytes or the
+   specified percentage of total memory, whichever is smaller.
+*/
+void limitProcessMemory(
+    const char *property,
+    size_t numberOfBytes,
+    size_t percentageOfTotalMem);
+
+}   // namespace android
+
+#endif // ANDROID_MEDIAUTILS_LIMIT_PROCESS_MEMORY_H
diff --git a/media/libmedia/include/media/MemoryLeakTrackUtil.h b/media/utils/include/mediautils/MemoryLeakTrackUtil.h
similarity index 100%
rename from media/libmedia/include/media/MemoryLeakTrackUtil.h
rename to media/utils/include/mediautils/MemoryLeakTrackUtil.h
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
index a33539f..546cec5 100644
--- a/media/utils/include/mediautils/SchedulingPolicyService.h
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -21,7 +21,7 @@
 
 namespace android {
 
-class IInterface;
+class IBinder;
 // Request elevated priority for thread tid, whose thread group leader must be pid.
 // The priority parameter is currently restricted to either 1 or 2.
 // The asynchronous parameter should be 'true' to return immediately,
@@ -35,7 +35,7 @@
 // for the server to receive death notifications. When 'enable' is 'false', server
 // will attempt to move media.codec process back to the original cpuset, and
 // 'client' is ignored in this case.
-int requestCpusetBoost(bool enable, const sp<IInterface> &client);
+int requestCpusetBoost(bool enable, const sp<IBinder> &client);
 
 }   // namespace android
 
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index e1089d5..212599a 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -28,6 +28,7 @@
 #include <map>
 #include <optional>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 namespace android {
@@ -58,10 +59,11 @@
     return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER;
 }
 
-// used for calls that should come from system_server or audio_server and
+// used for calls that should come from system_server or audio_server or media server and
 // include AID_ROOT for command-line tests.
-static inline bool isAudioServerOrSystemServerOrRootUid(uid_t uid) {
-    return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER || uid == AID_ROOT;
+static inline bool isAudioServerOrMediaServerOrSystemServerOrRootUid(uid_t uid) {
+    return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER
+              || uid == AID_MEDIA || uid == AID_ROOT;
 }
 
 // Mediaserver may forward the client PID and UID as part of a binder interface call;
@@ -81,10 +83,13 @@
 void finishRecording(const String16& opPackageName, uid_t uid);
 bool captureAudioOutputAllowed(pid_t pid, uid_t uid);
 bool captureMediaOutputAllowed(pid_t pid, uid_t uid);
+bool captureVoiceCommunicationOutputAllowed(pid_t pid, uid_t uid);
 bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
 bool settingsAllowed();
 bool modifyAudioRoutingAllowed();
+bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid);
 bool modifyDefaultAudioEffectsAllowed();
+bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid);
 bool dumpAllowed();
 bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
 bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
@@ -115,6 +120,40 @@
     using Packages = std::vector<Package>;
     std::map<uid_t, Packages> mDebugLog;
 };
-}
+
+namespace mediautils {
+
+/**
+ * This class is used to retrieve (and cache) package information
+ * for a given uid.
+ */
+class UidInfo {
+public:
+    struct Info {
+        uid_t uid = -1;           // uid used for lookup.
+        std::string package;      // package name.
+        std::string installer;    // installer for the package (e.g. preload, play store).
+        int64_t versionCode = 0;  // reported version code.
+        int64_t expirationNs = 0; // after this time in SYSTEM_TIME_REALTIME we refetch.
+    };
+
+    /**
+     * Returns the package information for a UID.
+     *
+     * The package name will be the uid if we cannot find the associated name.
+     *
+     * \param uid is the uid of the app or service.
+     */
+    Info getInfo(uid_t uid);
+
+private:
+    std::mutex mLock;
+    // TODO: use concurrent hashmap with striped lock.
+    std::unordered_map<uid_t, Info> mInfoMap; // GUARDED_BY(mLock)
+};
+
+} // namespace mediautils
+
+} // namespace android
 
 #endif // ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index 6c5f656..5ba6d7c 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -20,7 +20,7 @@
 
 #include <utils/KeyedVector.h>
 #include <utils/Thread.h>
-
+#include <vector>
 
 namespace android {
 
@@ -35,6 +35,8 @@
 
             TimeCheck(const char *tag, uint32_t timeoutMs = kDefaultTimeOutMs);
             ~TimeCheck();
+    static  void setAudioHalPids(const std::vector<pid_t>& pids);
+    static  std::vector<pid_t> getAudioHalPids();
 
 private:
 
@@ -63,6 +65,7 @@
     };
 
     static sp<TimeCheckThread> getTimeCheckThread();
+    static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
 
     const           nsecs_t mEndTimeNs;
 };
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 96ad54b..3873600 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -9,6 +9,7 @@
         "AudioStreamOut.cpp",
         "AudioWatchdog.cpp",
         "BufLog.cpp",
+        "DeviceEffectManager.cpp",
         "Effects.cpp",
         "FastCapture.cpp",
         "FastCaptureDumpState.cpp",
@@ -34,6 +35,7 @@
     ],
 
     shared_libs: [
+        "libaudiofoundation",
         "libaudiohal",
         "libaudioprocessing",
         "libaudiospdif",
@@ -60,6 +62,11 @@
         "libsndfile",
     ],
 
+    header_libs: [
+        "libaudiohal_headers",
+        "libmedia_headers",
+    ],
+
     cflags: [
         "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
         "-fvisibility=hidden",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8bbdc69..f014209 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -19,6 +19,9 @@
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
 
+// Define AUDIO_ARRAYS_STATIC_CHECK to check all audio arrays are correct
+#define AUDIO_ARRAYS_STATIC_CHECK 1
+
 #include "Configuration.h"
 #include <dirent.h>
 #include <math.h>
@@ -26,6 +29,7 @@
 #include <string>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <thread>
 
 #include <android/os/IExternalVibratorService.h>
 #include <binder/IPCThreadState.h>
@@ -37,6 +41,7 @@
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <media/AudioParameter.h>
+#include <media/MediaMetricsItem.h>
 #include <media/TypeConverter.h>
 #include <memunreachable/memunreachable.h>
 #include <utils/String16.h>
@@ -62,11 +67,12 @@
 #include <powermanager/PowerManager.h>
 
 #include <media/IMediaLogService.h>
-#include <media/MemoryLeakTrackUtil.h>
 #include <media/nbaio/Pipe.h>
 #include <media/nbaio/PipeReader.h>
 #include <mediautils/BatteryNotifier.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
 #include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include <private/android_filesystem_config.h>
 
 //#define BUFLOG_NDEBUG 0
@@ -129,7 +135,7 @@
 
 static sp<os::IExternalVibratorService> getExternalVibratorService() {
     if (sExternalVibratorService == 0) {
-        sp <IBinder> binder = defaultServiceManager()->getService(
+        sp<IBinder> binder = defaultServiceManager()->getService(
             String16("external_vibrator_service"));
         if (binder != 0) {
             sExternalVibratorService =
@@ -139,6 +145,19 @@
     return sExternalVibratorService;
 }
 
+class DevicesFactoryHalCallbackImpl : public DevicesFactoryHalCallback {
+  public:
+    void onNewDevicesAvailable() override {
+        // Start a detached thread to execute notification in parallel.
+        // This is done to prevent mutual blocking of audio_flinger and
+        // audio_policy services during system initialization.
+        std::thread notifier([]() {
+            AudioSystem::onNewAudioModulesAvailable();
+        });
+        notifier.detach();
+    }
+};
+
 // ----------------------------------------------------------------------------
 
 std::string formatToString(audio_format_t format) {
@@ -166,6 +185,7 @@
       mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
       mGlobalEffectEnableTime(0),
       mPatchPanel(this),
+      mDeviceEffectManager(this),
       mSystemReady(false)
 {
     // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
@@ -190,6 +210,14 @@
     mEffectsFactoryHal = EffectsFactoryHalInterface::create();
 
     mMediaLogNotifier->run("MediaLogNotifier");
+    std::vector<pid_t> halPids;
+    mDevicesFactoryHal->getHalPids(&halPids);
+    TimeCheck::setAudioHalPids(halPids);
+
+    // Notify that we have started (also called when audioserver service restarts)
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
+        .record();
 }
 
 void AudioFlinger::onFirstRef()
@@ -213,6 +241,14 @@
     mMode = AUDIO_MODE_NORMAL;
 
     gAudioFlinger = this;
+
+    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
+    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
+}
+
+status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
+  TimeCheck::setAudioHalPids(pids);
+  return NO_ERROR;
 }
 
 AudioFlinger::~AudioFlinger()
@@ -335,6 +371,9 @@
         thread->configure(&localAttr, streamType, actualSessionId, callback, *deviceId, portId);
         *handle = portId;
         *sessionId = actualSessionId;
+        config->sample_rate = thread->sampleRate();
+        config->channel_mask = thread->channelMask();
+        config->format = thread->format();
     } else {
         if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
             AudioSystem::releaseOutput(portId);
@@ -370,6 +409,26 @@
     }
 }
 
+status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
+        audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+    AutoMutex lock(mHardwareLock);
+    AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
+    if (audioHwDevice == nullptr) {
+        return NO_INIT;
+    }
+    return audioHwDevice->hwDevice()->addDeviceEffect(deviceId, effect);
+}
+
+status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId,
+        audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+    AutoMutex lock(mHardwareLock);
+    AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
+    if (audioHwDevice == nullptr) {
+        return NO_INIT;
+    }
+    return audioHwDevice->hwDevice()->removeDeviceEffect(deviceId, effect);
+}
+
 static const char * const audio_interfaces[] = {
     AUDIO_HARDWARE_MODULE_ID_PRIMARY,
     AUDIO_HARDWARE_MODULE_ID_A2DP,
@@ -378,10 +437,11 @@
 
 AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
         audio_module_handle_t module,
-        audio_devices_t devices)
+        audio_devices_t deviceType)
 {
     // if module is 0, the request comes from an old policy manager and we should load
     // well known modules
+    AutoMutex lock(mHardwareLock);
     if (module == 0) {
         ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
         for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
@@ -393,7 +453,7 @@
             sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
             uint32_t supportedDevices;
             if (dev->getSupportedDevices(&supportedDevices) == OK &&
-                    (supportedDevices & devices) == devices) {
+                    (supportedDevices & deviceType) == deviceType) {
                 return audioHwDevice;
             }
         }
@@ -410,31 +470,32 @@
 
 void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
 {
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
 
     result.append("Clients:\n");
     for (size_t i = 0; i < mClients.size(); ++i) {
         sp<Client> client = mClients.valueAt(i).promote();
         if (client != 0) {
-            snprintf(buffer, SIZE, "  pid: %d\n", client->pid());
-            result.append(buffer);
+            result.appendFormat("  pid: %d\n", client->pid());
         }
     }
 
     result.append("Notification Clients:\n");
+    result.append("   pid    uid  name\n");
     for (size_t i = 0; i < mNotificationClients.size(); ++i) {
-        snprintf(buffer, SIZE, "  pid: %d\n", mNotificationClients.keyAt(i));
-        result.append(buffer);
+        const pid_t pid = mNotificationClients[i]->getPid();
+        const uid_t uid = mNotificationClients[i]->getUid();
+        const mediautils::UidInfo::Info info = mUidInfo.getInfo(uid);
+        result.appendFormat("%6d %6u  %s\n", pid, uid, info.package.c_str());
     }
 
     result.append("Global session refs:\n");
-    result.append("  session   pid count\n");
+    result.append("  session  cnt     pid    uid  name\n");
     for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
         AudioSessionRef *r = mAudioSessionRefs[i];
-        snprintf(buffer, SIZE, "  %7d %5d %5d\n", r->mSessionid, r->mPid, r->mCnt);
-        result.append(buffer);
+        const mediautils::UidInfo::Info info = mUidInfo.getInfo(r->mUid);
+        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());
 }
@@ -546,6 +607,8 @@
 
         mPatchPanel.dump(fd);
 
+        mDeviceEffectManager.dump(fd);
+
         // dump external setParameters
         auto dumpLogger = [fd](SimpleLog& logger, const char* name) {
             dprintf(fd, "\n%s setParameters:\n", name);
@@ -652,7 +715,7 @@
         return new NBLog::Writer();
     }
 success:
-    NBLog::Shared *sharedRawPtr = (NBLog::Shared *) shared->pointer();
+    NBLog::Shared *sharedRawPtr = (NBLog::Shared *) shared->unsecurePointer();
     new((void *) sharedRawPtr) NBLog::Shared(); // placement new here, but the corresponding
                                                 // explicit destructor not needed since it is POD
     sMediaLogService->registerWriter(shared, size, name);
@@ -789,7 +852,7 @@
                                       input.notificationsPerBuffer, input.speed,
                                       input.sharedBuffer, sessionId, &output.flags,
                                       callingPid, input.clientInfo.clientTid, clientUid,
-                                      &lStatus, portId);
+                                      &lStatus, portId, input.audioTrackCallback);
         LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
         // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
@@ -1019,17 +1082,18 @@
     mMasterVolume = value;
 
     // Set master volume in the HALs which support it.
-    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+    {
         AutoMutex lock(mHardwareLock);
-        AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+            AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
 
-        mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-        if (dev->canSetMasterVolume()) {
-            dev->hwDevice()->setMasterVolume(value);
+            mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+            if (dev->canSetMasterVolume()) {
+                dev->hwDevice()->setMasterVolume(value);
+            }
+            mHardwareStatus = AUDIO_HW_IDLE;
         }
-        mHardwareStatus = AUDIO_HW_IDLE;
     }
-
     // Now set the master volume in each playback thread.  Playback threads
     // assigned to HALs which do not have master volume support will apply
     // master volume during the mix operation.  Threads with HALs which do
@@ -1096,6 +1160,9 @@
 
     { // scope for the lock
         AutoMutex lock(mHardwareLock);
+        if (mPrimaryHardwareDev == nullptr) {
+            return INVALID_OPERATION;
+        }
         sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
         mHardwareStatus = AUDIO_HW_SET_MODE;
         ret = dev->setMode(mode);
@@ -1109,6 +1176,10 @@
             mPlaybackThreads.valueAt(i)->setMode(mode);
     }
 
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE)
+        .set(AMEDIAMETRICS_PROP_AUDIOMODE, toString(mode))
+        .record();
     return ret;
 }
 
@@ -1125,15 +1196,24 @@
     }
 
     AutoMutex lock(mHardwareLock);
+    if (mPrimaryHardwareDev == nullptr) {
+        return INVALID_OPERATION;
+    }
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    if (primaryDev == nullptr) {
+        ALOGW("%s: no primary HAL device", __func__);
+        return INVALID_OPERATION;
+    }
     mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
+    ret = primaryDev->setMicMute(state);
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
-        status_t result = dev->setMicMute(state);
-        if (result != NO_ERROR) {
-            ret = result;
+        if (dev != primaryDev) {
+            (void)dev->setMicMute(state);
         }
     }
     mHardwareStatus = AUDIO_HW_IDLE;
+    ALOGW_IF(ret != NO_ERROR, "%s: error %d setting state to HAL", __func__, ret);
     return ret;
 }
 
@@ -1143,32 +1223,33 @@
     if (ret != NO_ERROR) {
         return false;
     }
-    bool mute = true;
-    bool state = AUDIO_MODE_INVALID;
     AutoMutex lock(mHardwareLock);
-    mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
-    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
-        status_t result = dev->getMicMute(&state);
-        if (result == NO_ERROR) {
-            mute = mute && state;
-        }
+    if (mPrimaryHardwareDev == nullptr) {
+        return false;
     }
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    if (primaryDev == nullptr) {
+        ALOGW("%s: no primary HAL device", __func__);
+        return false;
+    }
+    bool state;
+    mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
+    ret = primaryDev->getMicMute(&state);
     mHardwareStatus = AUDIO_HW_IDLE;
-
-    return mute;
+    ALOGE_IF(ret != NO_ERROR, "%s: error %d getting state from HAL", __func__, ret);
+    return (ret == NO_ERROR) && state;
 }
 
-void AudioFlinger::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)
 {
-    ALOGV("AudioFlinger::setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);
+    ALOGV("AudioFlinger::setRecordSilenced(portId:%d, silenced:%d)", portId, silenced);
 
     AutoMutex lock(mLock);
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
-        mRecordThreads[i]->setRecordSilenced(uid, silenced);
+        mRecordThreads[i]->setRecordSilenced(portId, silenced);
     }
     for (size_t i = 0; i < mMmapThreads.size(); i++) {
-        mMmapThreads[i]->setRecordSilenced(uid, silenced);
+        mMmapThreads[i]->setRecordSilenced(portId, silenced);
     }
 }
 
@@ -1188,15 +1269,17 @@
     mMasterMute = muted;
 
     // Set master mute in the HALs which support it.
-    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+    {
         AutoMutex lock(mHardwareLock);
-        AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+            AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
 
-        mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
-        if (dev->canSetMasterMute()) {
-            dev->hwDevice()->setMasterMute(muted);
+            mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+            if (dev->canSetMasterMute()) {
+                dev->hwDevice()->setMasterMute(muted);
+            }
+            mHardwareStatus = AUDIO_HW_IDLE;
         }
-        mHardwareStatus = AUDIO_HW_IDLE;
     }
 
     // Now set the master mute in each playback thread.  Playback threads
@@ -1354,6 +1437,13 @@
     }
 }
 
+void AudioFlinger::updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+{
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        mRecordThreads.valueAt(i)->updateOutDevices(devices);
+    }
+}
+
 // forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::forwardParametersToDownstreamPatches_l(
         audio_io_handle_t upStream, const String8& keyValuePairs,
@@ -1384,8 +1474,8 @@
         String8(AudioParameter::keyFrameCount),
         String8(AudioParameter::keyInputSource),
         String8(AudioParameter::keyMonoOutput),
-        String8(AudioParameter::keyStreamConnect),
-        String8(AudioParameter::keyStreamDisconnect),
+        String8(AudioParameter::keyDeviceConnect),
+        String8(AudioParameter::keyDeviceDisconnect),
         String8(AudioParameter::keyStreamSupportedFormats),
         String8(AudioParameter::keyStreamSupportedChannels),
         String8(AudioParameter::keyStreamSupportedSamplingRates),
@@ -1520,16 +1610,13 @@
     if (ioHandle == AUDIO_IO_HANDLE_NONE) {
         String8 out_s8;
 
+        AutoMutex lock(mHardwareLock);
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             String8 s;
-            status_t result;
-            {
-            AutoMutex lock(mHardwareLock);
             mHardwareStatus = AUDIO_HW_GET_PARAMETER;
             sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
-            result = dev->getParameters(keys, &s);
+            status_t result = dev->getParameters(keys, &s);
             mHardwareStatus = AUDIO_HW_IDLE;
-            }
             if (result == OK) out_s8 += s;
         }
         return out_s8;
@@ -1562,41 +1649,68 @@
     }
 
     AutoMutex lock(mHardwareLock);
+    if (mPrimaryHardwareDev == nullptr) {
+        return 0;
+    }
     mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
-    audio_config_t config, proposed;
-    memset(&proposed, 0, sizeof(proposed));
-    proposed.sample_rate = sampleRate;
-    proposed.channel_mask = channelMask;
-    proposed.format = format;
 
     sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
-    size_t frames;
-    for (;;) {
-        // Note: config is currently a const parameter for get_input_buffer_size()
-        // but we use a copy from proposed in case config changes from the call.
-        config = proposed;
-        status_t result = dev->getInputBufferSize(&config, &frames);
-        if (result == OK && frames != 0) {
-            break; // hal success, config is the result
-        }
-        // change one parameter of the configuration each iteration to a more "common" value
-        // to see if the device will support it.
-        if (proposed.format != AUDIO_FORMAT_PCM_16_BIT) {
-            proposed.format = AUDIO_FORMAT_PCM_16_BIT;
-        } else if (proposed.sample_rate != 44100) { // 44.1 is claimed as must in CDD as well as
-            proposed.sample_rate = 44100;           // legacy AudioRecord.java. TODO: Query hw?
-        } else {
-            ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, "
-                    "format %#x, channelMask 0x%X",
-                    sampleRate, format, channelMask);
-            break; // retries failed, break out of loop with frames == 0.
-        }
-    }
+    std::vector<audio_channel_mask_t> channelMasks = {channelMask};
+    if (channelMask != AUDIO_CHANNEL_IN_MONO)
+        channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
+    if (channelMask != AUDIO_CHANNEL_IN_STEREO)
+        channelMasks.push_back(AUDIO_CHANNEL_IN_STEREO);
+
+    std::vector<audio_format_t> formats = {format};
+    if (format != AUDIO_FORMAT_PCM_16_BIT)
+        formats.push_back(AUDIO_FORMAT_PCM_16_BIT);
+
+    std::vector<uint32_t> sampleRates = {sampleRate};
+    static const uint32_t SR_44100 = 44100;
+    static const uint32_t SR_48000 = 48000;
+
+    if (sampleRate != SR_48000)
+        sampleRates.push_back(SR_48000);
+    if (sampleRate != SR_44100)
+        sampleRates.push_back(SR_44100);
+
     mHardwareStatus = AUDIO_HW_IDLE;
-    if (frames > 0 && config.sample_rate != sampleRate) {
-        frames = destinationFramesPossible(frames, sampleRate, config.sample_rate);
+
+    // Change parameters of the configuration each iteration until we find a
+    // configuration that the device will support.
+    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+    for (auto testChannelMask : channelMasks) {
+        config.channel_mask = testChannelMask;
+        for (auto testFormat : formats) {
+            config.format = testFormat;
+            for (auto testSampleRate : sampleRates) {
+                config.sample_rate = testSampleRate;
+
+                size_t bytes = 0;
+                status_t result = dev->getInputBufferSize(&config, &bytes);
+                if (result != OK || bytes == 0) {
+                    continue;
+                }
+
+                if (config.sample_rate != sampleRate || config.channel_mask != channelMask ||
+                    config.format != format) {
+                    uint32_t dstChannelCount = audio_channel_count_from_in_mask(channelMask);
+                    uint32_t srcChannelCount =
+                        audio_channel_count_from_in_mask(config.channel_mask);
+                    size_t srcFrames =
+                        bytes / audio_bytes_per_frame(srcChannelCount, config.format);
+                    size_t dstFrames = destinationFramesPossible(
+                        srcFrames, config.sample_rate, sampleRate);
+                    bytes = dstFrames * audio_bytes_per_frame(dstChannelCount, format);
+                }
+                return bytes;
+            }
+        }
     }
-    return frames; // may be converted to bytes at the Java level.
+
+    ALOGW("getInputBufferSize failed with minimum buffer size sampleRate %u, "
+              "format %#x, channelMask %#x",sampleRate, format, channelMask);
+    return 0;
 }
 
 uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
@@ -1623,11 +1737,18 @@
     }
 
     AutoMutex lock(mHardwareLock);
+    if (mPrimaryHardwareDev == nullptr) {
+        return INVALID_OPERATION;
+    }
     sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
     mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
     ret = dev->setVoiceVolume(value);
     mHardwareStatus = AUDIO_HW_IDLE;
 
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME)
+        .set(AMEDIAMETRICS_PROP_VOICEVOLUME, (double)value)
+        .record();
     return ret;
 }
 
@@ -1651,13 +1772,16 @@
         return;
     }
     pid_t pid = IPCThreadState::self()->getCallingPid();
+    const uid_t uid = IPCThreadState::self()->getCallingUid();
     {
         Mutex::Autolock _cl(mClientLock);
         if (mNotificationClients.indexOfKey(pid) < 0) {
             sp<NotificationClient> notificationClient = new NotificationClient(this,
                                                                                 client,
-                                                                                pid);
-            ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+                                                                                pid,
+                                                                                uid);
+            ALOGV("registerClient() client %p, pid %d, uid %u",
+                    notificationClient.get(), pid, uid);
 
             mNotificationClients.add(pid, notificationClient);
 
@@ -1797,8 +1921,9 @@
 
 AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
                                                      const sp<IAudioFlingerClient>& client,
-                                                     pid_t pid)
-    : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
+                                                     pid_t pid,
+                                                     uid_t uid)
+    : mAudioFlinger(audioFlinger), mPid(pid), mUid(uid), mAudioFlingerClient(client)
 {
 }
 
@@ -2027,10 +2152,11 @@
         return AUDIO_MODULE_HANDLE_NONE;
     }
     Mutex::Autolock _l(mLock);
+    AutoMutex lock(mHardwareLock);
     return loadHwModule_l(name);
 }
 
-// loadHwModule_l() must be called with AudioFlinger::mLock held
+// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
 audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
 {
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -2062,44 +2188,49 @@
     // master mute and volume settings.
 
     AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
-    {  // scope for auto-lock pattern
-        AutoMutex lock(mHardwareLock);
-
-        if (0 == mAudioHwDevs.size()) {
-            mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
-            float mv;
-            if (OK == dev->getMasterVolume(&mv)) {
-                mMasterVolume = mv;
-            }
-
-            mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
-            bool mm;
-            if (OK == dev->getMasterMute(&mm)) {
-                mMasterMute = mm;
-            }
+    if (0 == mAudioHwDevs.size()) {
+        mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
+        float mv;
+        if (OK == dev->getMasterVolume(&mv)) {
+            mMasterVolume = mv;
         }
 
-        mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-        if (OK == dev->setMasterVolume(mMasterVolume)) {
-            flags = static_cast<AudioHwDevice::Flags>(flags |
-                    AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
+        mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
+        bool mm;
+        if (OK == dev->getMasterMute(&mm)) {
+            mMasterMute = mm;
         }
-
-        mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
-        if (OK == dev->setMasterMute(mMasterMute)) {
-            flags = static_cast<AudioHwDevice::Flags>(flags |
-                    AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
-        }
-
-        mHardwareStatus = AUDIO_HW_IDLE;
     }
+
+    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+    if (OK == dev->setMasterVolume(mMasterVolume)) {
+        flags = static_cast<AudioHwDevice::Flags>(flags |
+                AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
+    }
+
+    mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+    if (OK == dev->setMasterMute(mMasterMute)) {
+        flags = static_cast<AudioHwDevice::Flags>(flags |
+                AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
+    }
+
+    mHardwareStatus = AUDIO_HW_IDLE;
+
     if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_MSD) == 0) {
         // An MSD module is inserted before hardware modules in order to mix encoded streams.
         flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_IS_INSERT);
     }
 
     audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
-    mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
+    AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
+    if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
+        mPrimaryHardwareDev = audioDevice;
+        mHardwareStatus = AUDIO_HW_SET_MODE;
+        mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+        mHardwareStatus = AUDIO_HW_IDLE;
+    }
+
+    mAudioHwDevs.add(handle, audioDevice);
 
     ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
 
@@ -2185,6 +2316,7 @@
     }
 
     Mutex::Autolock _l(mLock);
+    AutoMutex lock(mHardwareLock);
     ssize_t index = mAudioHwDevs.indexOfKey(module);
     if (index < 0) {
         ALOGW("%s() bad hw module %d", __func__, module);
@@ -2206,8 +2338,15 @@
         return mHwAvSyncIds.valueAt(index);
     }
 
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
-    if (dev == NULL) {
+    sp<DeviceHalInterface> dev;
+    {
+        AutoMutex lock(mHardwareLock);
+        if (mPrimaryHardwareDev == nullptr) {
+            return AUDIO_HW_SYNC_INVALID;
+        }
+        dev = mPrimaryHardwareDev->hwDevice();
+    }
+    if (dev == nullptr) {
         return AUDIO_HW_SYNC_INVALID;
     }
     String8 reply;
@@ -2275,8 +2414,21 @@
 status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
 {
     AutoMutex lock(mHardwareLock);
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
-    status_t status = dev->getMicrophones(microphones);
+    status_t status = INVALID_OPERATION;
+
+    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+        std::vector<media::MicrophoneInfo> mics;
+        AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+        mHardwareStatus = AUDIO_HW_GET_MICROPHONES;
+        status_t devStatus = dev->hwDevice()->getMicrophones(&mics);
+        mHardwareStatus = AUDIO_HW_IDLE;
+        if (devStatus == NO_ERROR) {
+            microphones->insert(microphones->begin(), mics.begin(), mics.end());
+            // report success if at least one HW module supports the function.
+            status = NO_ERROR;
+        }
+    }
+
     return status;
 }
 
@@ -2301,13 +2453,13 @@
 
 
 sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
-                                                            audio_io_handle_t *output,
-                                                            audio_config_t *config,
-                                                            audio_devices_t devices,
-                                                            const String8& address,
-                                                            audio_output_flags_t flags)
+                                                        audio_io_handle_t *output,
+                                                        audio_config_t *config,
+                                                        audio_devices_t deviceType,
+                                                        const String8& address,
+                                                        audio_output_flags_t flags)
 {
-    AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
+    AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
     if (outHwDev == NULL) {
         return 0;
     }
@@ -2348,7 +2500,7 @@
     status_t status = outHwDev->openOutputStream(
             &outputStream,
             *output,
-            devices,
+            deviceType,
             flags,
             config,
             address.string());
@@ -2358,8 +2510,7 @@
     if (status == NO_ERROR) {
         if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
             sp<MmapPlaybackThread> thread =
-                    new MmapPlaybackThread(this, *output, outHwDev, outputStream,
-                                          devices, AUDIO_DEVICE_NONE, mSystemReady);
+                    new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
             mMmapThreads.add(*output, thread);
             ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
                   *output, thread.get());
@@ -2367,17 +2518,17 @@
         } else {
             sp<PlaybackThread> thread;
             if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-                thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
+                thread = new OffloadThread(this, outputStream, *output, mSystemReady);
                 ALOGV("openOutput_l() created offload output: ID %d thread %p",
                       *output, thread.get());
             } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                     || !isValidPcmSinkFormat(config->format)
                     || !isValidPcmSinkChannelMask(config->channel_mask)) {
-                thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
+                thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
                 ALOGV("openOutput_l() created direct output: ID %d thread %p",
                       *output, thread.get());
             } else {
-                thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
+                thread = new MixerThread(this, outputStream, *output, mSystemReady);
                 ALOGV("openOutput_l() created mixer output: ID %d thread %p",
                       *output, thread.get());
             }
@@ -2393,27 +2544,29 @@
 status_t AudioFlinger::openOutput(audio_module_handle_t module,
                                   audio_io_handle_t *output,
                                   audio_config_t *config,
-                                  audio_devices_t *devices,
-                                  const String8& address,
+                                  const sp<DeviceDescriptorBase>& device,
                                   uint32_t *latencyMs,
                                   audio_output_flags_t flags)
 {
-    ALOGI("openOutput() this %p, module %d Device %#x, SamplingRate %d, Format %#08x, "
+    ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
               "Channels %#x, flags %#x",
               this, module,
-              (devices != NULL) ? *devices : 0,
+              device->toString().c_str(),
               config->sample_rate,
               config->format,
               config->channel_mask,
               flags);
 
-    if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
+    audio_devices_t deviceType = device->type();
+    const String8 address = String8(device->address().c_str());
+
+    if (deviceType == AUDIO_DEVICE_NONE) {
         return BAD_VALUE;
     }
 
     Mutex::Autolock _l(mLock);
 
-    sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
+    sp<ThreadBase> thread = openOutput_l(module, output, config, deviceType, address, flags);
     if (thread != 0) {
         if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
@@ -2422,12 +2575,13 @@
             // notify client processes of the new output creation
             playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
 
-            // the first primary output opened designates the primary hw device
-            if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
+            // the first primary output opened designates the primary hw device if no HW module
+            // named "primary" was already loaded.
+            AutoMutex lock(mHardwareLock);
+            if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
                 ALOGI("Using module %d as the primary audio interface", module);
                 mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
 
-                AutoMutex lock(mHardwareLock);
                 mHardwareStatus = AUDIO_HW_SET_MODE;
                 mPrimaryHardwareDev->hwDevice()->setMode(mMode);
                 mHardwareStatus = AUDIO_HW_IDLE;
@@ -2629,9 +2783,6 @@
         return 0;
     }
 
-    // Some flags are specific to framework and must not leak to the HAL.
-    flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FRAMEWORK_FLAGS);
-
     // Audio Policy can request a specific handle for hardware hotword.
     // The goal here is not to re-open an already opened input.
     // It is to use a pre-assigned I/O handle.
@@ -2683,9 +2834,7 @@
         AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
         if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
             sp<MmapCaptureThread> thread =
-                    new MmapCaptureThread(this, *input,
-                                          inHwDev, inputStream,
-                                          primaryOutputDevice_l(), devices, mSystemReady);
+                    new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady);
             mMmapThreads.add(*input, thread);
             ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
                     thread.get());
@@ -2694,13 +2843,7 @@
             // Start record thread
             // RecordThread requires both input and output device indication to forward to audio
             // pre processing modules
-            sp<RecordThread> thread = new RecordThread(this,
-                                      inputStream,
-                                      *input,
-                                      primaryOutputDevice_l(),
-                                      devices,
-                                      mSystemReady
-                                      );
+            sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);
             mRecordThreads.add(*input, thread);
             ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
             return thread;
@@ -2835,14 +2978,18 @@
     return nextUniqueId(use);
 }
 
-void AudioFlinger::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
+void AudioFlinger::acquireAudioSessionId(
+        audio_session_t audioSession, pid_t pid, uid_t uid)
 {
     Mutex::Autolock _l(mLock);
     pid_t caller = IPCThreadState::self()->getCallingPid();
     ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
     const uid_t callerUid = IPCThreadState::self()->getCallingUid();
-    if (pid != -1 && isAudioServerUid(callerUid)) { // check must match releaseAudioSessionId()
-        caller = pid;
+    if (pid != (pid_t)-1 && isAudioServerOrMediaServerUid(callerUid)) {
+        caller = pid;  // check must match releaseAudioSessionId()
+    }
+    if (uid == (uid_t)-1 || !isAudioServerOrMediaServerUid(callerUid)) {
+        uid = callerUid;
     }
 
     {
@@ -2866,7 +3013,7 @@
             return;
         }
     }
-    mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
+    mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller, uid));
     ALOGV(" added new entry for %d", audioSession);
 }
 
@@ -2878,8 +3025,8 @@
         pid_t caller = IPCThreadState::self()->getCallingPid();
         ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
         const uid_t callerUid = IPCThreadState::self()->getCallingUid();
-        if (pid != -1 && isAudioServerUid(callerUid)) { // check must match acquireAudioSessionId()
-            caller = pid;
+        if (pid != (pid_t)-1 && isAudioServerOrMediaServerUid(callerUid)) {
+            caller = pid;  // check must match acquireAudioSessionId()
         }
         size_t num = mAudioSessionRefs.size();
         for (size_t i = 0; i < num; i++) {
@@ -2932,7 +3079,7 @@
         Mutex::Autolock _l(t->mLock);
         for (size_t j = 0; j < t->mEffectChains.size(); j++) {
             sp<EffectChain> ec = t->mEffectChains[j];
-            if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
+            if (!audio_is_global_session(ec->sessionId())) {
                 chains.push(ec);
             }
         }
@@ -2959,7 +3106,7 @@
     for (size_t i = 0; i < chains.size(); i++) {
         sp<EffectChain> ec = chains[i];
         int sessionid = ec->sessionId();
-        sp<ThreadBase> t = ec->mThread.promote();
+        sp<ThreadBase> t = ec->thread().promote();
         if (t == 0) {
             continue;
         }
@@ -2982,7 +3129,7 @@
                 effect->unPin();
                 t->removeEffect_l(effect, /*release*/ true);
                 if (effect->purgeHandles()) {
-                    t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
+                    effect->checkSuspendOnEffectEnabled(false, true /*threadLocked*/);
                 }
                 removedEffects.push_back(effect);
             }
@@ -3103,6 +3250,10 @@
 
 AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
 {
+    AutoMutex lock(mHardwareLock);
+    if (mPrimaryHardwareDev == nullptr) {
+        return nullptr;
+    }
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
         if(thread->isDuplicating()) {
@@ -3113,18 +3264,18 @@
             return thread;
         }
     }
-    return NULL;
+    return nullptr;
 }
 
-audio_devices_t AudioFlinger::primaryOutputDevice_l() const
+DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
 {
     PlaybackThread *thread = primaryPlaybackThread_l();
 
     if (thread == NULL) {
-        return 0;
+        return DeviceTypeSet();
     }
 
-    return thread->outDevice();
+    return thread->outDeviceTypes();
 }
 
 AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
@@ -3282,8 +3433,10 @@
         int32_t priority,
         audio_io_handle_t io,
         audio_session_t sessionId,
+        const AudioDeviceTypeAddr& device,
         const String16& opPackageName,
         pid_t pid,
+        bool probe,
         status_t *status,
         int *id,
         int *enabled)
@@ -3334,6 +3487,17 @@
             lStatus = BAD_VALUE;
             goto Exit;
         }
+    } else if (sessionId == AUDIO_SESSION_DEVICE) {
+        if (!modifyDefaultAudioEffectsAllowed(pid, callingUid)) {
+            ALOGE("%s: device effect permission denied for uid %d", __func__, callingUid);
+            lStatus = PERMISSION_DENIED;
+            goto Exit;
+        }
+        if (io != AUDIO_IO_HANDLE_NONE) {
+            ALOGE("%s: io handle should not be specified for device effect", __func__);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
     } else {
         // general sessionId.
 
@@ -3369,7 +3533,7 @@
         // check recording permission for visualizer
         if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
             // TODO: Do we need to start/stop op - i.e. is there recording being performed?
-            !recordingAllowed(opPackageName, pid, IPCThreadState::self()->getCallingUid())) {
+            !recordingAllowed(opPackageName, pid, callingUid)) {
             lStatus = PERMISSION_DENIED;
             goto Exit;
         }
@@ -3386,6 +3550,23 @@
 
         Mutex::Autolock _l(mLock);
 
+        if (sessionId == AUDIO_SESSION_DEVICE) {
+            sp<Client> client = registerPid(pid);
+            ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
+            handle = mDeviceEffectManager.createEffect_l(
+                    &desc, device, client, effectClient, mPatchPanel.patches_l(),
+                    enabled, &lStatus, probe);
+            if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+                // remove local strong reference to Client with mClientLock held
+                Mutex::Autolock _cl(mClientLock);
+                client.clear();
+            } else {
+                // handle must be valid here, but check again to be safe.
+                if (handle.get() != nullptr && id != nullptr) *id = handle->id();
+            }
+            goto Register;
+        }
+
         // If output is not specified try to find a matching audio session ID in one of the
         // output threads.
         // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
@@ -3467,9 +3648,9 @@
         sp<Client> client = registerPid(pid);
 
         // create effect on selected output thread
-        bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
+        bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
         handle = thread->createEffect_l(client, effectClient, priority, sessionId,
-                &desc, enabled, &lStatus, pinned);
+                &desc, enabled, &lStatus, pinned, probe);
         if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
             // remove local strong reference to Client with mClientLock held
             Mutex::Autolock _cl(mClientLock);
@@ -3480,9 +3661,10 @@
         }
     }
 
-    if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+Register:
+    if (!probe && (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS)) {
         // Check CPU and memory usage
-        sp<EffectModule> effect = handle->effect().promote();
+        sp<EffectBase> effect = handle->effect().promote();
         if (effect != nullptr) {
             status_t rStatus = effect->updatePolicyState();
             if (rStatus != NO_ERROR) {
@@ -3592,7 +3774,7 @@
         // if the move request is not received from audio policy manager, the effect must be
         // re-registered with the new strategy and output
         if (dstChain == 0) {
-            dstChain = effect->chain().promote();
+            dstChain = effect->callback()->chain().promote();
             if (dstChain == 0) {
                 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
                 status = NO_INIT;
@@ -3642,7 +3824,7 @@
             goto Exit;
         }
 
-        dstChain = effect->chain().promote();
+        dstChain = effect->callback()->chain().promote();
         if (dstChain == 0) {
             thread->addEffect_l(effect);
             status = INVALID_OPERATION;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 72e669a..20f561e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <limits.h>
 
+#include <android/media/IAudioTrackCallback.h>
 #include <android/os/BnExternalVibrationController.h>
 #include <android-base/macros.h>
 
@@ -65,13 +66,17 @@
 #include <media/audiohal/EffectBufferHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
 #include <media/AudioBufferProvider.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioMixer.h>
+#include <media/DeviceDescriptorBase.h>
 #include <media/ExtendedAudioBufferProvider.h>
-#include <media/LinearMap.h>
 #include <media/VolumeShaper.h>
+#include <mediautils/ServiceUtilities.h>
 
 #include <audio_utils/clock.h>
 #include <audio_utils/FdToString.h>
+#include <audio_utils/LinearMap.h>
 #include <audio_utils/SimpleLog.h>
 #include <audio_utils/TimestampVerifier.h>
 
@@ -83,6 +88,8 @@
 #include "SpdifStreamOut.h"
 #include "AudioHwDevice.h"
 #include "NBAIO_Tee.h"
+#include "ThreadMetrics.h"
+#include "TrackMetrics.h"
 
 #include <powermanager/IPowerManager.h>
 
@@ -100,6 +107,7 @@
 class AudioBuffer;
 class AudioResampler;
 class DeviceHalInterface;
+class DevicesFactoryHalCallback;
 class DevicesFactoryHalInterface;
 class EffectsFactoryHalInterface;
 class FastMixer;
@@ -162,7 +170,7 @@
     virtual     status_t    setMicMute(bool state);
     virtual     bool        getMicMute() const;
 
-    virtual     void        setRecordSilenced(uid_t uid, bool silenced);
+    virtual     void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
 
     virtual     status_t    setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
     virtual     String8     getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
@@ -175,8 +183,7 @@
     virtual status_t openOutput(audio_module_handle_t module,
                                 audio_io_handle_t *output,
                                 audio_config_t *config,
-                                audio_devices_t *devices,
-                                const String8& address,
+                                const sp<DeviceDescriptorBase>& device,
                                 uint32_t *latencyMs,
                                 audio_output_flags_t flags);
 
@@ -211,7 +218,7 @@
     // This is the binder API.  For the internal API see nextUniqueId().
     virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
 
-    virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid);
+    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override;
 
     virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
 
@@ -230,8 +237,10 @@
                         int32_t priority,
                         audio_io_handle_t io,
                         audio_session_t sessionId,
+                        const AudioDeviceTypeAddr& device,
                         const String16& opPackageName,
                         pid_t pid,
+                        bool probe,
                         status_t *status /*non-NULL*/,
                         int *id,
                         int *enabled);
@@ -279,6 +288,8 @@
 
     virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
 
+    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+
     virtual     status_t    onTransact(
                                 uint32_t code,
                                 const Parcel& data,
@@ -303,6 +314,12 @@
 
     static int onExternalVibrationStart(const sp<os::ExternalVibration>& externalVibration);
     static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
+
+    status_t addEffectToHal(audio_port_handle_t deviceId,
+            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+    status_t removeEffectFromHal(audio_port_handle_t deviceId,
+            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+
 private:
     // FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
     static const size_t kLogMemorySize = 400 * 1024;
@@ -331,7 +348,10 @@
 
         virtual ~SyncEvent() {}
 
-        void trigger() { Mutex::Autolock _l(mLock); if (mCallback) mCallback(this); }
+        void trigger() {
+            Mutex::Autolock _l(mLock);
+            if (mCallback) mCallback(wp<SyncEvent>(this));
+        }
         bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
         void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
         AudioSystem::sync_event_t type() const { return mType; }
@@ -372,7 +392,7 @@
     virtual     void        onFirstRef();
 
     AudioHwDevice*          findSuitableHwDev_l(audio_module_handle_t module,
-                                                audio_devices_t devices);
+                                                audio_devices_t deviceType);
 
     // Set kEnableExtendedChannels to true to enable greater than stereo output
     // for the MixerThread and device sink.  Number of channels allowed is
@@ -469,10 +489,13 @@
     public:
                             NotificationClient(const sp<AudioFlinger>& audioFlinger,
                                                 const sp<IAudioFlingerClient>& client,
-                                                pid_t pid);
+                                                pid_t pid,
+                                                uid_t uid);
         virtual             ~NotificationClient();
 
                 sp<IAudioFlingerClient> audioFlingerClient() const { return mAudioFlingerClient; }
+                pid_t getPid() const { return mPid; }
+                uid_t getUid() const { return mUid; }
 
                 // IBinder::DeathRecipient
                 virtual     void        binderDied(const wp<IBinder>& who);
@@ -482,6 +505,7 @@
 
         const sp<AudioFlinger>  mAudioFlinger;
         const pid_t             mPid;
+        const uid_t             mUid;
         const sp<IAudioFlingerClient> mAudioFlingerClient;
     };
 
@@ -528,9 +552,14 @@
     class AsyncCallbackThread;
     class Track;
     class RecordTrack;
+    class EffectBase;
     class EffectModule;
     class EffectHandle;
     class EffectChain;
+    class DeviceEffectProxy;
+    class DeviceEffectManager;
+    class PatchPanel;
+    class DeviceEffectManagerCallback;
 
     struct AudioStreamIn;
     struct TeePatch;
@@ -547,6 +576,16 @@
         bool        mute;
     };
 
+    // Abstraction for the Audio Source for the RecordThread (HAL or PassthruPatchRecord).
+    struct Source
+    {
+        virtual ~Source() = default;
+        // The following methods have the same signatures as in StreamHalInterface.
+        virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
+        virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
+        virtual status_t standby() = 0;
+    };
+
     // --- PlaybackThread ---
 #ifdef FLOAT_EFFECT_CHAIN
 #define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
@@ -558,9 +597,11 @@
 
 #include "Threads.h"
 
+#include "PatchPanel.h"
+
 #include "Effects.h"
 
-#include "PatchPanel.h"
+#include "DeviceEffectManager.h"
 
     // Find io handle by session id.
     // Preference is given to an io handle with a matching effect chain to session id.
@@ -642,7 +683,8 @@
                                           struct audio_mmap_buffer_info *info);
         virtual status_t getMmapPosition(struct audio_mmap_position *position);
         virtual status_t start(const AudioClient& client,
-                                         audio_port_handle_t *handle);
+                               const audio_attributes_t *attr,
+                               audio_port_handle_t *handle);
         virtual status_t stop(audio_port_handle_t handle);
         virtual status_t standby();
 
@@ -668,11 +710,11 @@
                                            audio_devices_t outputDevice,
                                            const String8& outputDeviceAddress);
               sp<ThreadBase> openOutput_l(audio_module_handle_t module,
-                                              audio_io_handle_t *output,
-                                              audio_config_t *config,
-                                              audio_devices_t devices,
-                                              const String8& address,
-                                              audio_output_flags_t flags);
+                                          audio_io_handle_t *output,
+                                          audio_config_t *config,
+                                          audio_devices_t deviceType,
+                                          const String8& address,
+                                          audio_output_flags_t flags);
 
               void closeOutputFinish(const sp<PlaybackThread>& thread);
               void closeInputFinish(const sp<RecordThread>& thread);
@@ -707,7 +749,7 @@
 
               // return thread associated with primary hardware device, or NULL
               PlaybackThread *primaryPlaybackThread_l() const;
-              audio_devices_t primaryOutputDevice_l() const;
+              DeviceTypeSet primaryOutputDevice_l() const;
 
               // return the playback thread with smallest HAL buffer size, and prefer fast
               PlaybackThread *fastPlaybackThread_l() const;
@@ -741,6 +783,7 @@
                 std::vector< sp<EffectModule> > purgeStaleEffects_l();
 
                 void broacastParametersToRecordThreads_l(const String8& keyValuePairs);
+                void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
                 void forwardParametersToDownstreamPatches_l(
                         audio_io_handle_t upStream, const String8& keyValuePairs,
                         std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
@@ -749,7 +792,7 @@
     // For emphasis, we could also make all pointers to them be "const *",
     // but that would clutter the code unnecessarily.
 
-    struct AudioStreamIn {
+    struct AudioStreamIn : public Source {
         AudioHwDevice* const audioHwDev;
         sp<StreamInHalInterface> stream;
         audio_input_flags_t flags;
@@ -758,6 +801,13 @@
 
         AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
             audioHwDev(dev), stream(in), flags(flags) {}
+        status_t read(void *buffer, size_t bytes, size_t *read) override {
+            return stream->read(buffer, bytes, read);
+        }
+        status_t getCapturePosition(int64_t *frames, int64_t *time) override {
+            return stream->getCapturePosition(frames, time);
+        }
+        status_t standby() override { return stream->standby(); }
     };
 
     struct TeePatch {
@@ -767,10 +817,11 @@
 
     // for mAudioSessionRefs only
     struct AudioSessionRef {
-        AudioSessionRef(audio_session_t sessionid, pid_t pid) :
-            mSessionid(sessionid), mPid(pid), mCnt(1) {}
+        AudioSessionRef(audio_session_t sessionid, pid_t pid, uid_t uid) :
+            mSessionid(sessionid), mPid(pid), mUid(uid), mCnt(1) {}
         const audio_session_t mSessionid;
         const pid_t mPid;
+        const uid_t mUid;
         int         mCnt;
     };
 
@@ -786,11 +837,13 @@
                 // NOTE: If both mLock and mHardwareLock mutexes must be held,
                 // always take mLock before mHardwareLock
 
-                // These two fields are immutable after onFirstRef(), so no lock needed to access
-                AudioHwDevice*                      mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL
+                // guarded by mHardwareLock
+                AudioHwDevice* mPrimaryHardwareDev;
                 DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>  mAudioHwDevs;
 
+                // These two fields are immutable after onFirstRef(), so no lock needed to access
                 sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
+                sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
 
     // for dump, indicates which hardware operation is currently in progress (but not stream ops)
     enum hardware_call_state {
@@ -815,6 +868,7 @@
         AUDIO_HW_GET_PARAMETER,         // get_parameters
         AUDIO_HW_SET_MASTER_MUTE,       // set_master_mute
         AUDIO_HW_GET_MASTER_MUTE,       // get_master_mute
+        AUDIO_HW_GET_MICROPHONES,       // getMicrophones
     };
 
     mutable     hardware_call_state                 mHardwareStatus;    // for dump only
@@ -898,11 +952,17 @@
     PatchPanel mPatchPanel;
     sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
 
+    DeviceEffectManager mDeviceEffectManager;
+
     bool       mSystemReady;
 
+    mediautils::UidInfo mUidInfo;
+
     SimpleLog  mRejectedSetParameterLog;
     SimpleLog  mAppSetParameterLog;
     SimpleLog  mSystemSetParameterLog;
+
+    static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
 };
 
 #undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index b109d06..dda164c 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -34,7 +34,7 @@
 status_t AudioHwDevice::openOutputStream(
         AudioStreamOut **ppStreamOut,
         audio_io_handle_t handle,
-        audio_devices_t devices,
+        audio_devices_t deviceType,
         audio_output_flags_t flags,
         struct audio_config *config,
         const char *address)
@@ -50,7 +50,7 @@
             config->sample_rate,
             config->format,
             config->channel_mask);
-    status_t status = outputStream->open(handle, devices, config, address);
+    status_t status = outputStream->open(handle, deviceType, config, address);
 
     if (status != NO_ERROR) {
         delete outputStream;
@@ -75,7 +75,7 @@
         if (wrapperNeeded) {
             if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
                 outputStream = new SpdifStreamOut(this, flags, originalConfig.format);
-                status = outputStream->open(handle, devices, &originalConfig, address);
+                status = outputStream->open(handle, deviceType, &originalConfig, address);
                 if (status != NO_ERROR) {
                     ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
                         status);
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index d4299b0..6709d17 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -76,7 +76,7 @@
     status_t openOutputStream(
             AudioStreamOut **ppStreamOut,
             audio_io_handle_t handle,
-            audio_devices_t devices,
+            audio_devices_t deviceType,
             audio_output_flags_t flags,
             struct audio_config *config,
             const char *address);
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index a60a5f2..7e06096 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -118,7 +118,7 @@
 
 status_t AudioStreamOut::open(
         audio_io_handle_t handle,
-        audio_devices_t devices,
+        audio_devices_t deviceType,
         struct audio_config *config,
         const char *address)
 {
@@ -130,7 +130,7 @@
 
     int status = hwDev()->openOutputStream(
             handle,
-            devices,
+            deviceType,
             customFlags,
             config,
             address,
@@ -152,7 +152,7 @@
 
         status = hwDev()->openOutputStream(
                 handle,
-                devices,
+                deviceType,
                 customFlags,
                 &customConfig,
                 address,
@@ -164,6 +164,10 @@
         stream = outStream;
         mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
         status = stream->getFrameSize(&mHalFrameSize);
+        LOG_ALWAYS_FATAL_IF(status != OK, "Error retrieving frame size from HAL: %d", status);
+        LOG_ALWAYS_FATAL_IF(mHalFrameSize <= 0, "Error frame size was %zu but must be greater than"
+                " zero", mHalFrameSize);
+
     }
 
     return status;
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index b16b1af..16fbcf2 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -47,7 +47,7 @@
 
     virtual status_t open(
             audio_io_handle_t handle,
-            audio_devices_t devices,
+            audio_devices_t deviceType,
             struct audio_config *config,
             const char *address);
 
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
new file mode 100644
index 0000000..5ff7215
--- /dev/null
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -0,0 +1,279 @@
+/*
+**
+** Copyright 2019, 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_TAG "AudioFlinger::DeviceEffectManager"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <audio_utils/primitives.h>
+
+#include "AudioFlinger.h"
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+
+// ----------------------------------------------------------------------------
+
+
+namespace android {
+
+void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle,
+        const PatchPanel::Patch& patch) {
+    ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
+            __func__, handle, patch.mHalHandle,
+            patch.mAudioPatch.num_sinks,
+            patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
+
+    mCommandThread->createAudioPatchCommand(handle, patch);
+}
+
+void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
+        const PatchPanel::Patch& patch) {
+    ALOGV("%s handle %d mHalHandle %d device sink %08x",
+            __func__, handle, patch.mHalHandle,
+            patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
+    Mutex::Autolock _l(mLock);
+    for (auto& effect : mDeviceEffects) {
+        status_t status = effect.second->onCreatePatch(handle, patch);
+        ALOGV("%s Effect onCreatePatch status %d", __func__, status);
+        ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
+    }
+}
+
+void AudioFlinger::DeviceEffectManager::releaseAudioPatch(audio_patch_handle_t handle) {
+    ALOGV("%s", __func__);
+    mCommandThread->releaseAudioPatchCommand(handle);
+}
+
+void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
+    ALOGV("%s", __func__);
+    Mutex::Autolock _l(mLock);
+    for (auto& effect : mDeviceEffects) {
+        effect.second->onReleasePatch(handle);
+    }
+}
+
+// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+        effect_descriptor_t *descriptor,
+        const AudioDeviceTypeAddr& device,
+        const sp<AudioFlinger::Client>& client,
+        const sp<IEffectClient>& effectClient,
+        const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+        int *enabled,
+        status_t *status,
+        bool probe) {
+    sp<DeviceEffectProxy> effect;
+    sp<EffectHandle> handle;
+    status_t lStatus;
+
+    lStatus = checkEffectCompatibility(descriptor);
+    if (probe || lStatus != NO_ERROR) {
+       *status = lStatus;
+       return handle;
+    }
+
+    {
+        Mutex::Autolock _l(mLock);
+        auto iter = mDeviceEffects.find(device);
+        if (iter != mDeviceEffects.end()) {
+            effect = iter->second;
+        } else {
+            effect = new DeviceEffectProxy(device, mMyCallback,
+                    descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT));
+        }
+        // create effect handle and connect it to effect module
+        handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/);
+        lStatus = handle->initCheck();
+        if (lStatus == NO_ERROR) {
+            lStatus = effect->addHandle(handle.get());
+            if (lStatus == NO_ERROR) {
+                effect->init(patches);
+                mDeviceEffects.emplace(device, effect);
+            }
+        }
+    }
+    if (enabled != NULL) {
+        *enabled = (int)effect->isEnabled();
+    }
+    *status = lStatus;
+    return handle;
+}
+
+status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
+        const effect_descriptor_t *desc) {
+
+    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
+        && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC) {
+        ALOGW("%s() non pre/post processing device effect %s", __func__, desc->name);
+        return BAD_VALUE;
+    }
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::DeviceEffectManager::createEffectHal(
+        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
+        sp<EffectHalInterface> *effect) {
+    status_t status = NO_INIT;
+    sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
+    if (effectsFactory != 0) {
+        status = effectsFactory->createEffect(
+                pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
+    }
+    return status;
+}
+
+void AudioFlinger::DeviceEffectManager::dump(int fd) {
+    const bool locked = dumpTryLock(mLock);
+    if (!locked) {
+        String8 result("DeviceEffectManager may be deadlocked\n");
+        write(fd, result.string(), result.size());
+    }
+
+    String8 heading("\nDevice Effects:\n");
+    write(fd, heading.string(), 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());
+        write(fd, outStr.string(), outStr.size());
+        iter.second->dump(fd, 4);
+    }
+
+    if (locked) {
+        mLock.unlock();
+    }
+}
+
+
+size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
+{
+    Mutex::Autolock _l(mLock);
+    mDeviceEffects.erase(effect->device());
+    return mDeviceEffects.size();
+}
+
+bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
+        EffectHandle *handle, bool unpinIfLast) {
+    sp<EffectBase> effectBase = handle->effect().promote();
+    if (effectBase == nullptr) {
+        return false;
+    }
+
+    sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
+    if (effect == nullptr) {
+        return false;
+    }
+    // restore suspended effects if the disconnected handle was enabled and the last one.
+    bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
+    if (remove) {
+        mManager.removeEffect(effect);
+        if (handle->enabled()) {
+            effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
+        }
+    }
+    return true;
+}
+
+// -----------  DeviceEffectManager::CommandThread implementation ----------
+
+
+AudioFlinger::DeviceEffectManager::CommandThread::~CommandThread()
+{
+    Mutex::Autolock _l(mLock);
+    mCommands.clear();
+}
+
+void AudioFlinger::DeviceEffectManager::CommandThread::onFirstRef()
+{
+    run("DeviceEffectManage_CommandThread", ANDROID_PRIORITY_AUDIO);
+}
+
+bool AudioFlinger::DeviceEffectManager::CommandThread::threadLoop()
+{
+    mLock.lock();
+    while (!exitPending())
+    {
+        while (!mCommands.empty() && !exitPending()) {
+            sp<Command> command = mCommands.front();
+            mCommands.pop_front();
+            mLock.unlock();
+
+            switch (command->mCommand) {
+            case CREATE_AUDIO_PATCH: {
+                CreateAudioPatchData *data = (CreateAudioPatchData *)command->mData.get();
+                ALOGV("CommandThread() processing create audio patch handle %d", data->mHandle);
+                mManager.onCreateAudioPatch(data->mHandle, data->mPatch);
+                } break;
+            case RELEASE_AUDIO_PATCH: {
+                ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mData.get();
+                ALOGV("CommandThread() processing release audio patch handle %d", data->mHandle);
+                mManager.onReleaseAudioPatch(data->mHandle);
+                } break;
+            default:
+                ALOGW("CommandThread() unknown command %d", command->mCommand);
+            }
+            mLock.lock();
+        }
+
+        // At this stage we have either an empty command queue or the first command in the queue
+        // has a finite delay. So unless we are exiting it is safe to wait.
+        if (!exitPending()) {
+            ALOGV("CommandThread() going to sleep");
+            mWaitWorkCV.wait(mLock);
+        }
+    }
+    mLock.unlock();
+    return false;
+}
+
+void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
+    Mutex::Autolock _l(mLock);
+    mCommands.push_back(command);
+    mWaitWorkCV.signal();
+}
+
+void AudioFlinger::DeviceEffectManager::CommandThread::createAudioPatchCommand(
+        audio_patch_handle_t handle, const PatchPanel::Patch& patch)
+{
+    sp<Command> command = new Command(CREATE_AUDIO_PATCH, new CreateAudioPatchData(handle, patch));
+    ALOGV("CommandThread() adding create patch handle %d mHalHandle %d.", handle, patch.mHalHandle);
+    sendCommand(command);
+}
+
+void AudioFlinger::DeviceEffectManager::CommandThread::releaseAudioPatchCommand(
+        audio_patch_handle_t handle)
+{
+    sp<Command> command = new Command(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
+    ALOGV("CommandThread() adding release patch");
+    sendCommand(command);
+}
+
+void AudioFlinger::DeviceEffectManager::CommandThread::exit()
+{
+    ALOGV("CommandThread::exit");
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    // Note that we can call it from the thread loop if all other references have been released
+    // but it will safely return WOULD_BLOCK in this case
+    requestExitAndWait();
+}
+
+} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
new file mode 100644
index 0000000..81e6065
--- /dev/null
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -0,0 +1,204 @@
+/*
+**
+** Copyright 2019, 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 INCLUDING_FROM_AUDIOFLINGER_H
+    #error This header file should only be included from AudioFlinger.h
+#endif
+
+// DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same.
+class DeviceEffectManager {
+public:
+    explicit DeviceEffectManager(AudioFlinger* audioFlinger)
+        : mCommandThread(new CommandThread(*this)), mAudioFlinger(*audioFlinger),
+        mMyCallback(new DeviceEffectManagerCallback(this)) {}
+
+            ~DeviceEffectManager() {
+                mCommandThread->exit();
+            }
+
+    sp<EffectHandle> createEffect_l(effect_descriptor_t *descriptor,
+                const AudioDeviceTypeAddr& device,
+                const sp<AudioFlinger::Client>& client,
+                const sp<IEffectClient>& effectClient,
+                const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+                int *enabled,
+                status_t *status,
+                bool probe);
+    void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
+    void releaseAudioPatch(audio_patch_handle_t handle);
+
+    size_t removeEffect(const sp<DeviceEffectProxy>& effect);
+    status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+           int32_t sessionId, int32_t deviceId,
+           sp<EffectHalInterface> *effect);
+    status_t addEffectToHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
+            sp<EffectHalInterface> effect) {
+        return mAudioFlinger.addEffectToHal(deviceId, hwModuleId, effect);
+    };
+    status_t removeEffectFromHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
+            sp<EffectHalInterface> effect) {
+        return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect);
+    };
+
+    AudioFlinger& audioFlinger() const { return mAudioFlinger; }
+
+    void dump(int fd);
+
+private:
+
+    // Thread to execute create and release patch commands asynchronously. This is needed because
+    // PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
+    // with mutex locked and effect management requires to call back into audio policy service
+    class Command;
+    class CommandThread : public Thread {
+    public:
+
+        enum {
+            CREATE_AUDIO_PATCH,
+            RELEASE_AUDIO_PATCH,
+        };
+
+        CommandThread(DeviceEffectManager& manager)
+            : Thread(false), mManager(manager) {}
+        ~CommandThread() override;
+
+        // Thread virtuals
+        void onFirstRef() override;
+        bool threadLoop() override;
+
+                void exit();
+
+                void createAudioPatchCommand(audio_patch_handle_t handle,
+                        const PatchPanel::Patch& patch);
+                void releaseAudioPatchCommand(audio_patch_handle_t handle);
+
+    private:
+        class CommandData;
+
+        // descriptor for requested tone playback event
+        class Command: public RefBase {
+        public:
+            Command() = default;
+            Command(int command, sp<CommandData> data)
+                : mCommand(command), mData(data) {}
+
+            int mCommand = -1;
+            sp<CommandData> mData;
+        };
+
+        class CommandData: public RefBase {
+        public:
+            virtual ~CommandData() = default;
+        };
+
+        class CreateAudioPatchData : public CommandData {
+        public:
+            CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch)
+                :   mHandle(handle), mPatch(patch) {}
+
+            audio_patch_handle_t mHandle;
+            const PatchPanel::Patch mPatch;
+        };
+
+        class ReleaseAudioPatchData : public CommandData {
+        public:
+            ReleaseAudioPatchData(audio_patch_handle_t handle)
+                :   mHandle(handle) {}
+
+            audio_patch_handle_t mHandle;
+        };
+
+        void sendCommand(sp<Command> command);
+
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+        std::deque <sp<Command>> mCommands; // list of pending commands
+        DeviceEffectManager& mManager;
+    };
+
+    void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
+    void onReleaseAudioPatch(audio_patch_handle_t handle);
+
+    status_t checkEffectCompatibility(const effect_descriptor_t *desc);
+
+    Mutex mLock;
+    sp<CommandThread> mCommandThread;
+    AudioFlinger &mAudioFlinger;
+    const sp<DeviceEffectManagerCallback> mMyCallback;
+    std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects;
+};
+
+class DeviceEffectManagerCallback :  public EffectCallbackInterface {
+public:
+            DeviceEffectManagerCallback(DeviceEffectManager *manager)
+                : mManager(*manager) {}
+
+    status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+           int32_t sessionId, int32_t deviceId,
+           sp<EffectHalInterface> *effect) override {
+                return mManager.createEffectHal(pEffectUuid, sessionId, deviceId, effect);
+            }
+    status_t allocateHalBuffer(size_t size __unused,
+            sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
+    bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override { return false; }
+
+    audio_io_handle_t io() const override  { return AUDIO_IO_HANDLE_NONE; }
+    bool isOutput() const override { return false; }
+    bool isOffload() const override { return false; }
+    bool isOffloadOrDirect() const override { return false; }
+    bool isOffloadOrMmap() const override { return false; }
+
+    uint32_t  sampleRate() const override { return 0; }
+    audio_channel_mask_t channelMask() const override { return AUDIO_CHANNEL_NONE; }
+    uint32_t channelCount() const override { return 0; }
+    size_t    frameCount() const override  { return 0; }
+    uint32_t  latency() const override  { return 0; }
+
+    status_t addEffectToHal(sp<EffectHalInterface> effect __unused) override {
+        return NO_ERROR;
+    }
+    status_t removeEffectFromHal(sp<EffectHalInterface> effect __unused) override {
+        return NO_ERROR;
+    }
+
+    bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+    void setVolumeForOutput(float left __unused, float right __unused) const override {}
+
+    // check if effects should be suspended or restored when a given effect is enable or disabled
+    void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+                          bool enabled __unused, bool threadLocked __unused) override {}
+    void resetVolume() override {}
+    uint32_t strategy() const override  { return 0; }
+    int32_t activeTrackCnt() const override { return 0; }
+    void onEffectEnable(const sp<EffectBase>& effect __unused) override {}
+    void onEffectDisable(const sp<EffectBase>& effect __unused) override {}
+
+    wp<EffectChain> chain() const override { return nullptr; }
+
+    int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
+
+    status_t addEffectToHal(audio_port_handle_t deviceId,
+            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+        return mManager.addEffectToHal(deviceId, hwModuleId, effect);
+    }
+    status_t removeEffectFromHal(audio_port_handle_t deviceId,
+            audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+        return mManager.removeEffectFromHal(deviceId, hwModuleId, effect);
+    }
+private:
+    DeviceEffectManager& mManager;
+};
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 13152d0..3dfeb83 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -29,7 +29,10 @@
 #include <system/audio_effects/effect_visualizer.h>
 #include <audio_utils/channels.h>
 #include <audio_utils/primitives.h>
+#include <media/AudioCommonTypes.h>
+#include <media/AudioContainers.h>
 #include <media/AudioEffect.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <mediautils/ServiceUtilities.h>
@@ -56,81 +59,115 @@
 namespace android {
 
 // ----------------------------------------------------------------------------
-//  EffectModule implementation
+//  EffectBase implementation
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectModule"
+#define LOG_TAG "AudioFlinger::EffectBase"
 
-AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
-                                        const wp<AudioFlinger::EffectChain>& chain,
+AudioFlinger::EffectBase::EffectBase(const sp<AudioFlinger::EffectCallbackInterface>& callback,
                                         effect_descriptor_t *desc,
                                         int id,
                                         audio_session_t sessionId,
                                         bool pinned)
     : mPinned(pinned),
-      mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
-      mDescriptor(*desc),
-      // clear mConfig to ensure consistent initial value of buffer framecount
-      // in case buffers are associated by setInBuffer() or setOutBuffer()
-      // prior to configure().
-      mConfig{{}, {}},
-      mStatus(NO_INIT), mState(IDLE),
-      mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
-      mDisableWaitCnt(0),    // set by process() and updateState()
-      mSuspended(false),
-      mOffloaded(false),
-      mAudioFlinger(thread->mAudioFlinger)
-#ifdef FLOAT_EFFECT_CHAIN
-      , mSupportsFloat(false)
-#endif
+      mCallback(callback), mId(id), mSessionId(sessionId),
+      mDescriptor(*desc)
 {
-    ALOGV("Constructor %p pinned %d", this, pinned);
-    int lStatus;
+}
 
-    // create effect engine from effect factory
-    mStatus = -ENODEV;
-    sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
-    if (audioFlinger != 0) {
-        sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
-        if (effectsFactory != 0) {
-            mStatus = effectsFactory->createEffect(
-                    &desc->uuid, sessionId, thread->id(), &mEffectInterface);
+// must be called with EffectModule::mLock held
+status_t AudioFlinger::EffectBase::setEnabled_l(bool enabled)
+{
+
+    ALOGV("setEnabled %p enabled %d", this, enabled);
+
+    if (enabled != isEnabled()) {
+        switch (mState) {
+        // going from disabled to enabled
+        case IDLE:
+            mState = STARTING;
+            break;
+        case STOPPED:
+            mState = RESTART;
+            break;
+        case STOPPING:
+            mState = ACTIVE;
+            break;
+
+        // going from enabled to disabled
+        case RESTART:
+            mState = STOPPED;
+            break;
+        case STARTING:
+            mState = IDLE;
+            break;
+        case ACTIVE:
+            mState = STOPPING;
+            break;
+        case DESTROYED:
+            return NO_ERROR; // simply ignore as we are being destroyed
+        }
+        for (size_t i = 1; i < mHandles.size(); i++) {
+            EffectHandle *h = mHandles[i];
+            if (h != NULL && !h->disconnected()) {
+                h->setEnabled(enabled);
+            }
         }
     }
-
-    if (mStatus != NO_ERROR) {
-        return;
-    }
-    lStatus = init();
-    if (lStatus < 0) {
-        mStatus = lStatus;
-        goto Error;
-    }
-
-    setOffloaded(thread->type() == ThreadBase::OFFLOAD, thread->id());
-    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
-
-    return;
-Error:
-    mEffectInterface.clear();
-    ALOGV("Constructor Error %d", mStatus);
+    return NO_ERROR;
 }
 
-AudioFlinger::EffectModule::~EffectModule()
+status_t AudioFlinger::EffectBase::setEnabled(bool enabled, bool fromHandle)
 {
-    ALOGV("Destructor %p", this);
-    if (mEffectInterface != 0) {
-        char uuidStr[64];
-        AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
-        ALOGW("EffectModule %p destructor called with unreleased interface, effect %s",
-                this, uuidStr);
-        release_l();
+    status_t status;
+    {
+        Mutex::Autolock _l(mLock);
+        status = setEnabled_l(enabled);
     }
-
+    if (fromHandle) {
+        if (enabled) {
+            if (status != NO_ERROR) {
+                mCallback->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
+            } else {
+                mCallback->onEffectEnable(this);
+            }
+        } else {
+            mCallback->onEffectDisable(this);
+        }
+    }
+    return status;
 }
 
-status_t AudioFlinger::EffectModule::addHandle(EffectHandle *handle)
+bool AudioFlinger::EffectBase::isEnabled() const
+{
+    switch (mState) {
+    case RESTART:
+    case STARTING:
+    case ACTIVE:
+        return true;
+    case IDLE:
+    case STOPPING:
+    case STOPPED:
+    case DESTROYED:
+    default:
+        return false;
+    }
+}
+
+void AudioFlinger::EffectBase::setSuspended(bool suspended)
+{
+    Mutex::Autolock _l(mLock);
+    mSuspended = suspended;
+}
+
+bool AudioFlinger::EffectBase::suspended() const
+{
+    Mutex::Autolock _l(mLock);
+    return mSuspended;
+}
+
+status_t AudioFlinger::EffectBase::addHandle(EffectHandle *handle)
 {
     status_t status;
 
@@ -169,15 +206,15 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::updatePolicyState()
+status_t AudioFlinger::EffectBase::updatePolicyState()
 {
     status_t status = NO_ERROR;
     bool doRegister = false;
     bool registered = false;
     bool doEnable = false;
     bool enabled = false;
-    audio_io_handle_t io;
-    uint32_t strategy;
+    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
+    uint32_t strategy = PRODUCT_STRATEGY_NONE;
 
     {
         Mutex::Autolock _l(mLock);
@@ -186,14 +223,8 @@
             doRegister = true;
             mPolicyRegistered = mHandles.size() > 0;
             if (mPolicyRegistered) {
-              sp <EffectChain> chain = mChain.promote();
-              sp <ThreadBase> thread = mThread.promote();
-
-              if (thread == nullptr || chain == nullptr) {
-                    return INVALID_OPERATION;
-                }
-                io = thread->id();
-                strategy = chain->strategy();
+                io = mCallback->io();
+                strategy = mCallback->strategy();
             }
         }
         // enable effect when registered according to enable state requested by controlling handle
@@ -231,13 +262,13 @@
 }
 
 
-ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
+ssize_t AudioFlinger::EffectBase::removeHandle(EffectHandle *handle)
 {
     Mutex::Autolock _l(mLock);
     return removeHandle_l(handle);
 }
 
-ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle)
+ssize_t AudioFlinger::EffectBase::removeHandle_l(EffectHandle *handle)
 {
     size_t size = mHandles.size();
     size_t i;
@@ -261,19 +292,15 @@
         }
     }
 
-    // Prevent calls to process() and other functions on effect interface from now on.
-    // The effect engine will be released by the destructor when the last strong reference on
-    // this object is released which can happen after next process is called.
     if (mHandles.size() == 0 && !mPinned) {
         mState = DESTROYED;
-        mEffectInterface->close();
     }
 
     return mHandles.size();
 }
 
 // must be called with EffectModule::mLock held
-AudioFlinger::EffectHandle *AudioFlinger::EffectModule::controlHandle_l()
+AudioFlinger::EffectHandle *AudioFlinger::EffectBase::controlHandle_l()
 {
     // the first valid handle in the list has control over the module
     for (size_t i = 0; i < mHandles.size(); i++) {
@@ -287,22 +314,271 @@
 }
 
 // unsafe method called when the effect parent thread has been destroyed
-ssize_t AudioFlinger::EffectModule::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
+ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
 {
     ALOGV("disconnect() %p handle %p", this, handle);
+    if (mCallback->disconnectEffectHandle(handle, unpinIfLast)) {
+        return mHandles.size();
+    }
+
     Mutex::Autolock _l(mLock);
     ssize_t numHandles = removeHandle_l(handle);
     if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
-        sp<AudioFlinger> af = mAudioFlinger.promote();
-        if (af != 0) {
-            mLock.unlock();
-            af->updateOrphanEffectChains(this);
-            mLock.lock();
-        }
+        mLock.unlock();
+        mCallback->updateOrphanEffectChains(this);
+        mLock.lock();
     }
     return numHandles;
 }
 
+bool AudioFlinger::EffectBase::purgeHandles()
+{
+    bool enabled = false;
+    Mutex::Autolock _l(mLock);
+    EffectHandle *handle = controlHandle_l();
+    if (handle != NULL) {
+        enabled = handle->enabled();
+    }
+    mHandles.clear();
+    return enabled;
+}
+
+void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
+    mCallback->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
+}
+
+static String8 effectFlagsToString(uint32_t flags) {
+    String8 s;
+
+    s.append("conn. mode: ");
+    switch (flags & EFFECT_FLAG_TYPE_MASK) {
+    case EFFECT_FLAG_TYPE_INSERT: s.append("insert"); break;
+    case EFFECT_FLAG_TYPE_AUXILIARY: s.append("auxiliary"); break;
+    case EFFECT_FLAG_TYPE_REPLACE: s.append("replace"); break;
+    case EFFECT_FLAG_TYPE_PRE_PROC: s.append("preproc"); break;
+    case EFFECT_FLAG_TYPE_POST_PROC: s.append("postproc"); break;
+    default: s.append("unknown/reserved"); break;
+    }
+    s.append(", ");
+
+    s.append("insert pref: ");
+    switch (flags & EFFECT_FLAG_INSERT_MASK) {
+    case EFFECT_FLAG_INSERT_ANY: s.append("any"); break;
+    case EFFECT_FLAG_INSERT_FIRST: s.append("first"); break;
+    case EFFECT_FLAG_INSERT_LAST: s.append("last"); break;
+    case EFFECT_FLAG_INSERT_EXCLUSIVE: s.append("exclusive"); break;
+    default: s.append("unknown/reserved"); break;
+    }
+    s.append(", ");
+
+    s.append("volume mgmt: ");
+    switch (flags & EFFECT_FLAG_VOLUME_MASK) {
+    case EFFECT_FLAG_VOLUME_NONE: s.append("none"); break;
+    case EFFECT_FLAG_VOLUME_CTRL: s.append("implements control"); break;
+    case EFFECT_FLAG_VOLUME_IND: s.append("requires indication"); break;
+    case EFFECT_FLAG_VOLUME_MONITOR: s.append("monitors volume"); break;
+    default: s.append("unknown/reserved"); break;
+    }
+    s.append(", ");
+
+    uint32_t devind = flags & EFFECT_FLAG_DEVICE_MASK;
+    if (devind) {
+        s.append("device indication: ");
+        switch (devind) {
+        case EFFECT_FLAG_DEVICE_IND: s.append("requires updates"); break;
+        default: s.append("unknown/reserved"); break;
+        }
+        s.append(", ");
+    }
+
+    s.append("input mode: ");
+    switch (flags & EFFECT_FLAG_INPUT_MASK) {
+    case EFFECT_FLAG_INPUT_DIRECT: s.append("direct"); break;
+    case EFFECT_FLAG_INPUT_PROVIDER: s.append("provider"); break;
+    case EFFECT_FLAG_INPUT_BOTH: s.append("direct+provider"); break;
+    default: s.append("not set"); break;
+    }
+    s.append(", ");
+
+    s.append("output mode: ");
+    switch (flags & EFFECT_FLAG_OUTPUT_MASK) {
+    case EFFECT_FLAG_OUTPUT_DIRECT: s.append("direct"); break;
+    case EFFECT_FLAG_OUTPUT_PROVIDER: s.append("provider"); break;
+    case EFFECT_FLAG_OUTPUT_BOTH: s.append("direct+provider"); break;
+    default: s.append("not set"); break;
+    }
+    s.append(", ");
+
+    uint32_t accel = flags & EFFECT_FLAG_HW_ACC_MASK;
+    if (accel) {
+        s.append("hardware acceleration: ");
+        switch (accel) {
+        case EFFECT_FLAG_HW_ACC_SIMPLE: s.append("non-tunneled"); break;
+        case EFFECT_FLAG_HW_ACC_TUNNEL: s.append("tunneled"); break;
+        default: s.append("unknown/reserved"); break;
+        }
+        s.append(", ");
+    }
+
+    uint32_t modeind = flags & EFFECT_FLAG_AUDIO_MODE_MASK;
+    if (modeind) {
+        s.append("mode indication: ");
+        switch (modeind) {
+        case EFFECT_FLAG_AUDIO_MODE_IND: s.append("required"); break;
+        default: s.append("unknown/reserved"); break;
+        }
+        s.append(", ");
+    }
+
+    uint32_t srcind = flags & EFFECT_FLAG_AUDIO_SOURCE_MASK;
+    if (srcind) {
+        s.append("source indication: ");
+        switch (srcind) {
+        case EFFECT_FLAG_AUDIO_SOURCE_IND: s.append("required"); break;
+        default: s.append("unknown/reserved"); break;
+        }
+        s.append(", ");
+    }
+
+    if (flags & EFFECT_FLAG_OFFLOAD_MASK) {
+        s.append("offloadable, ");
+    }
+
+    int len = s.length();
+    if (s.length() > 2) {
+        (void) s.lockBuffer(len);
+        s.unlockBuffer(len - 2);
+    }
+    return s;
+}
+
+void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+{
+    String8 result;
+
+    result.appendFormat("\tEffect ID %d:\n", mId);
+
+    bool locked = AudioFlinger::dumpTryLock(mLock);
+    // failed to lock - AudioFlinger is probably deadlocked
+    if (!locked) {
+        result.append("\t\tCould not lock Fx mutex:\n");
+    }
+
+    result.append("\t\tSession State Registered Enabled Suspended:\n");
+    result.appendFormat("\t\t%05d   %03d   %s          %s       %s\n",
+            mSessionId, mState, mPolicyRegistered ? "y" : "n",
+            mPolicyEnabled ? "y" : "n", mSuspended ? "y" : "n");
+
+    result.append("\t\tDescriptor:\n");
+    char uuidStr[64];
+    AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
+    result.appendFormat("\t\t- UUID: %s\n", uuidStr);
+    AudioEffect::guidToString(&mDescriptor.type, uuidStr, sizeof(uuidStr));
+    result.appendFormat("\t\t- TYPE: %s\n", uuidStr);
+    result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
+            mDescriptor.apiVersion,
+            mDescriptor.flags,
+            effectFlagsToString(mDescriptor.flags).string());
+    result.appendFormat("\t\t- name: %s\n",
+            mDescriptor.name);
+
+    result.appendFormat("\t\t- implementor: %s\n",
+            mDescriptor.implementor);
+
+    result.appendFormat("\t\t%zu Clients:\n", mHandles.size());
+    result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
+    char buffer[256];
+    for (size_t i = 0; i < mHandles.size(); ++i) {
+        EffectHandle *handle = mHandles[i];
+        if (handle != NULL && !handle->disconnected()) {
+            handle->dumpToBuffer(buffer, sizeof(buffer));
+            result.append(buffer);
+        }
+    }
+    if (locked) {
+        mLock.unlock();
+    }
+
+    write(fd, result.string(), result.length());
+}
+
+// ----------------------------------------------------------------------------
+//  EffectModule implementation
+// ----------------------------------------------------------------------------
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectModule"
+
+AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+                                         effect_descriptor_t *desc,
+                                         int id,
+                                         audio_session_t sessionId,
+                                         bool pinned,
+                                         audio_port_handle_t deviceId)
+    : EffectBase(callback, desc, id, sessionId, pinned),
+      // clear mConfig to ensure consistent initial value of buffer framecount
+      // in case buffers are associated by setInBuffer() or setOutBuffer()
+      // prior to configure().
+      mConfig{{}, {}},
+      mStatus(NO_INIT),
+      mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
+      mDisableWaitCnt(0),    // set by process() and updateState()
+      mOffloaded(false)
+#ifdef FLOAT_EFFECT_CHAIN
+      , mSupportsFloat(false)
+#endif
+{
+    ALOGV("Constructor %p pinned %d", this, pinned);
+    int lStatus;
+
+    // create effect engine from effect factory
+    mStatus = callback->createEffectHal(
+            &desc->uuid, sessionId, deviceId, &mEffectInterface);
+    if (mStatus != NO_ERROR) {
+        return;
+    }
+    lStatus = init();
+    if (lStatus < 0) {
+        mStatus = lStatus;
+        goto Error;
+    }
+
+    setOffloaded(callback->isOffload(), callback->io());
+    ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
+
+    return;
+Error:
+    mEffectInterface.clear();
+    ALOGV("Constructor Error %d", mStatus);
+}
+
+AudioFlinger::EffectModule::~EffectModule()
+{
+    ALOGV("Destructor %p", this);
+    if (mEffectInterface != 0) {
+        char uuidStr[64];
+        AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
+        ALOGW("EffectModule %p destructor called with unreleased interface, effect %s",
+                this, uuidStr);
+        release_l();
+    }
+
+}
+
+ssize_t AudioFlinger::EffectModule::removeHandle_l(EffectHandle *handle)
+{
+    ssize_t status = EffectBase::removeHandle_l(handle);
+
+    // Prevent calls to process() and other functions on effect interface from now on.
+    // The effect engine will be released by the destructor when the last strong reference on
+    // this object is released which can happen after next process is called.
+    if (status == 0 && !mPinned) {
+        mEffectInterface->close();
+    }
+
+    return status;
+}
+
 bool AudioFlinger::EffectModule::updateState() {
     Mutex::Autolock _l(mLock);
 
@@ -462,7 +738,7 @@
             }
             if (!mSupportsFloat) { // convert input to int16_t as effect doesn't support float.
                 if (!auxType) {
-                    if (mInConversionBuffer.get() == nullptr) {
+                    if (mInConversionBuffer == nullptr) {
                         ALOGW("%s: mInConversionBuffer is null, bypassing", __func__);
                         goto data_bypass;
                     }
@@ -473,7 +749,7 @@
                     inBuffer = mInConversionBuffer;
                 }
                 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
-                    if (mOutConversionBuffer.get() == nullptr) {
+                    if (mOutConversionBuffer == nullptr) {
                         ALOGW("%s: mOutConversionBuffer is null, bypassing", __func__);
                         goto data_bypass;
                     }
@@ -540,8 +816,7 @@
                 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
         // If an insert effect is idle and input buffer is different from output buffer,
         // accumulate input onto output
-        sp<EffectChain> chain = mChain.promote();
-        if (chain.get() != nullptr && chain->activeTrackCnt() != 0) {
+        if (mCallback->activeTrackCnt() != 0) {
             // similar handling with data_bypass above.
             if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
                 accumulateInputToOutput();
@@ -564,7 +839,6 @@
 {
     ALOGVV("configure() started");
     status_t status;
-    sp<ThreadBase> thread;
     uint32_t size;
     audio_channel_mask_t channelMask;
 
@@ -573,17 +847,11 @@
         goto exit;
     }
 
-    thread = mThread.promote();
-    if (thread == 0) {
-        status = DEAD_OBJECT;
-        goto exit;
-    }
-
     // TODO: handle configuration of effects replacing track process
     // TODO: handle configuration of input (record) SW effects above the HAL,
     // similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
     // in which case input channel masks should be used here.
-    channelMask = thread->channelMask();
+    channelMask = mCallback->channelMask();
     mConfig.inputCfg.channels = channelMask;
     mConfig.outputCfg.channels = channelMask;
 
@@ -620,11 +888,11 @@
     mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
 
     // Don't use sample rate for thread if effect isn't offloadable.
-    if ((thread->type() == ThreadBase::OFFLOAD) && !isOffloaded()) {
+    if (mCallback->isOffloadOrDirect() && !isOffloaded()) {
         mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
         ALOGV("Overriding effect input as 48kHz");
     } else {
-        mConfig.inputCfg.samplingRate = thread->sampleRate();
+        mConfig.inputCfg.samplingRate = mCallback->sampleRate();
     }
     mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
     mConfig.inputCfg.bufferProvider.cookie = NULL;
@@ -635,7 +903,7 @@
     mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
     mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
     // Insert effect:
-    // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
+    // - in global sessions (e.g AUDIO_SESSION_OUTPUT_MIX),
     // always overwrites output buffer: input buffer == output buffer
     // - in other sessions:
     //      last effect in the chain accumulates in output buffer: input buffer != output buffer
@@ -650,11 +918,12 @@
     }
     mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
     mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
-    mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+    mConfig.inputCfg.buffer.frameCount = mCallback->frameCount();
     mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
 
-    ALOGV("configure() %p thread %p buffer %p framecount %zu",
-            this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+    ALOGV("configure() %p chain %p buffer %p framecount %zu",
+          this, mCallback->chain().promote().get(),
+          mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
 
     status_t cmdStatus;
     size = sizeof(int);
@@ -669,7 +938,7 @@
 
 #ifdef MULTICHANNEL_EFFECT_CHAIN
     if (status != NO_ERROR &&
-            thread->isOutput() &&
+            mCallback->isOutput() &&
             (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
                     || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
         // Older effects may require exact STEREO position mask.
@@ -736,11 +1005,7 @@
             size = sizeof(int);
             *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
 
-            uint32_t latency = 0;
-            PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
-            if (pbt != NULL) {
-                latency = pbt->latency_l();
-            }
+            uint32_t latency = mCallback->latency();
 
             *((int32_t *)p->data + 1)= latency;
             mEffectInterface->command(EFFECT_CMD_SET_PARAM,
@@ -787,31 +1052,20 @@
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
          (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
-        sp<ThreadBase> thread = mThread.promote();
-        if (thread != 0) {
-            sp<StreamHalInterface> stream = thread->stream();
-            if (stream != 0) {
-                status_t result = stream->addEffect(mEffectInterface);
-                ALOGE_IF(result != OK, "Error when adding effect: %d", result);
-            }
-        }
+        (void)mCallback->addEffectToHal(mEffectInterface);
     }
 }
 
 // start() must be called with PlaybackThread::mLock or EffectChain::mLock held
 status_t AudioFlinger::EffectModule::start()
 {
-    sp<EffectChain> chain;
     status_t status;
     {
         Mutex::Autolock _l(mLock);
         status = start_l();
-        if (status == NO_ERROR) {
-            chain = mChain.promote();
-        }
     }
-    if (chain != 0) {
-        chain->resetVolume_l();
+    if (status == NO_ERROR) {
+        mCallback->resetVolume();
     }
     return status;
 }
@@ -858,11 +1112,10 @@
     uint32_t size = sizeof(status_t);
 
     if (isVolumeControl() && isOffloadedOrDirect()) {
-        sp<EffectChain>chain = mChain.promote();
         // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
         // resetVolume_l --> setVolume_l --> EffectModule::setVolume
         mSetVolumeReentrantTid = gettid();
-        chain->resetVolume_l();
+        mCallback->resetVolume();
         mSetVolumeReentrantTid = INVALID_PID;
     }
 
@@ -875,7 +1128,7 @@
         status = cmdStatus;
     }
     if (status == NO_ERROR) {
-        status = remove_effect_from_hal_l();
+        status = removeEffectFromHal_l();
     }
     return status;
 }
@@ -884,25 +1137,18 @@
 void AudioFlinger::EffectModule::release_l()
 {
     if (mEffectInterface != 0) {
-        remove_effect_from_hal_l();
+        removeEffectFromHal_l();
         // release effect engine
         mEffectInterface->close();
         mEffectInterface.clear();
     }
 }
 
-status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
+status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
              (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
-        sp<ThreadBase> thread = mThread.promote();
-        if (thread != 0) {
-            sp<StreamHalInterface> stream = thread->stream();
-            if (stream != 0) {
-                status_t result = stream->removeEffect(mEffectInterface);
-                ALOGE_IF(result != OK, "Error when removing effect: %d", result);
-            }
-        }
+        mCallback->removeEffectFromHal(mEffectInterface);
     }
     return NO_ERROR;
 }
@@ -992,70 +1238,6 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
-{
-    Mutex::Autolock _l(mLock);
-    return setEnabled_l(enabled);
-}
-
-// must be called with EffectModule::mLock held
-status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
-{
-
-    ALOGV("setEnabled %p enabled %d", this, enabled);
-
-    if (enabled != isEnabled()) {
-        switch (mState) {
-        // going from disabled to enabled
-        case IDLE:
-            mState = STARTING;
-            break;
-        case STOPPED:
-            mState = RESTART;
-            break;
-        case STOPPING:
-            mState = ACTIVE;
-            break;
-
-        // going from enabled to disabled
-        case RESTART:
-            mState = STOPPED;
-            break;
-        case STARTING:
-            mState = IDLE;
-            break;
-        case ACTIVE:
-            mState = STOPPING;
-            break;
-        case DESTROYED:
-            return NO_ERROR; // simply ignore as we are being destroyed
-        }
-        for (size_t i = 1; i < mHandles.size(); i++) {
-            EffectHandle *h = mHandles[i];
-            if (h != NULL && !h->disconnected()) {
-                h->setEnabled(enabled);
-            }
-        }
-    }
-    return NO_ERROR;
-}
-
-bool AudioFlinger::EffectModule::isEnabled() const
-{
-    switch (mState) {
-    case RESTART:
-    case STARTING:
-    case ACTIVE:
-        return true;
-    case IDLE:
-    case STOPPING:
-    case STOPPED:
-    case DESTROYED:
-    default:
-        return false;
-    }
-}
-
 bool AudioFlinger::EffectModule::isProcessEnabled() const
 {
     if (mStatus != NO_ERROR) {
@@ -1078,7 +1260,7 @@
 
 bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
 {
-    return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT);
+    return mCallback->isOffloadOrDirect();
 }
 
 bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
@@ -1108,7 +1290,7 @@
     const uint32_t inChannelCount =
             audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
     const bool formatMismatch = !mSupportsFloat || mInChannelCountRequested != inChannelCount;
-    if (!auxType && formatMismatch && mInBuffer.get() != nullptr) {
+    if (!auxType && formatMismatch && mInBuffer != nullptr) {
         // we need to translate - create hidl shared buffer and intercept
         const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
         // Use FCC_2 in case mInChannelCountRequested is mono and the effect is stereo.
@@ -1118,15 +1300,13 @@
         ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
                 __func__, inChannels, inFrameCount, size);
 
-        if (size > 0 && (mInConversionBuffer.get() == nullptr
+        if (size > 0 && (mInConversionBuffer == nullptr
                 || size > mInConversionBuffer->getSize())) {
             mInConversionBuffer.clear();
             ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
-            sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
-            LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
-            (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mInConversionBuffer);
+            (void)mCallback->allocateHalBuffer(size, &mInConversionBuffer);
         }
-        if (mInConversionBuffer.get() != nullptr) {
+        if (mInConversionBuffer != nullptr) {
             mInConversionBuffer->setFrameCount(inFrameCount);
             mEffectInterface->setInBuffer(mInConversionBuffer);
         } else if (size > 0) {
@@ -1155,7 +1335,7 @@
     const uint32_t outChannelCount =
             audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
     const bool formatMismatch = !mSupportsFloat || mOutChannelCountRequested != outChannelCount;
-    if (formatMismatch && mOutBuffer.get() != nullptr) {
+    if (formatMismatch && mOutBuffer != nullptr) {
         const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
         // Use FCC_2 in case mOutChannelCountRequested is mono and the effect is stereo.
         const uint32_t outChannels = std::max((uint32_t)FCC_2, mOutChannelCountRequested);
@@ -1164,15 +1344,13 @@
         ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
                 __func__, outChannels, outFrameCount, size);
 
-        if (size > 0 && (mOutConversionBuffer.get() == nullptr
+        if (size > 0 && (mOutConversionBuffer == nullptr
                 || size > mOutConversionBuffer->getSize())) {
             mOutConversionBuffer.clear();
             ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
-            sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
-            LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
-            (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mOutConversionBuffer);
+            (void)mCallback->allocateHalBuffer(size, &mOutConversionBuffer);
         }
-        if (mOutConversionBuffer.get() != nullptr) {
+        if (mOutConversionBuffer != nullptr) {
             mOutConversionBuffer->setFrameCount(outFrameCount);
             mEffectInterface->setOutBuffer(mOutConversionBuffer);
         } else if (size > 0) {
@@ -1218,20 +1396,22 @@
 
 void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
 {
-    sp<ThreadBase> thread = mThread.promote();
-    if (thread != 0 &&
-        (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT) &&
-        !isNonOffloadableEnabled_l()) {
-        PlaybackThread *t = (PlaybackThread *)thread.get();
+    // for offload or direct thread, if the effect chain has non-offloadable
+    // effect and any effect module within the chain has volume control, then
+    // volume control is delegated to effect, otherwise, set volume to hal.
+    if (mEffectCallback->isOffloadOrDirect() &&
+        !(isNonOffloadableEnabled_l() && hasVolumeControlEnabled_l())) {
         float vol_l = (float)left / (1 << 24);
         float vol_r = (float)right / (1 << 24);
-        t->setVolumeForOutput_l(vol_l, vol_r);
+        mEffectCallback->setVolumeForOutput(vol_l, vol_r);
     }
 }
 
-status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
+status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+        const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
 {
-    if (device == AUDIO_DEVICE_NONE) {
+    audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
+    if (deviceType == AUDIO_DEVICE_NONE) {
         return NO_ERROR;
     }
 
@@ -1243,17 +1423,26 @@
     if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
         status_t cmdStatus;
         uint32_t size = sizeof(status_t);
-        uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
-                            EFFECT_CMD_SET_INPUT_DEVICE;
-        status = mEffectInterface->command(cmd,
+        // FIXME: use audio device types and addresses when the hal interface is ready.
+        status = mEffectInterface->command(cmdCode,
                                            sizeof(uint32_t),
-                                           &device,
+                                           &deviceType,
                                            &size,
                                            &cmdStatus);
     }
     return status;
 }
 
+status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+{
+    return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
+}
+
+status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+{
+    return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
+}
+
 status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
@@ -1294,30 +1483,6 @@
     return status;
 }
 
-void AudioFlinger::EffectModule::setSuspended(bool suspended)
-{
-    Mutex::Autolock _l(mLock);
-    mSuspended = suspended;
-}
-
-bool AudioFlinger::EffectModule::suspended() const
-{
-    Mutex::Autolock _l(mLock);
-    return mSuspended;
-}
-
-bool AudioFlinger::EffectModule::purgeHandles()
-{
-    bool enabled = false;
-    Mutex::Autolock _l(mLock);
-    EffectHandle *handle = controlHandle_l();
-    if (handle != NULL) {
-        enabled = handle->enabled();
-    }
-    mHandles.clear();
-    return enabled;
-}
-
 status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
 {
     Mutex::Autolock _l(mLock);
@@ -1357,115 +1522,10 @@
     return mOffloaded;
 }
 
-String8 effectFlagsToString(uint32_t flags) {
-    String8 s;
-
-    s.append("conn. mode: ");
-    switch (flags & EFFECT_FLAG_TYPE_MASK) {
-    case EFFECT_FLAG_TYPE_INSERT: s.append("insert"); break;
-    case EFFECT_FLAG_TYPE_AUXILIARY: s.append("auxiliary"); break;
-    case EFFECT_FLAG_TYPE_REPLACE: s.append("replace"); break;
-    case EFFECT_FLAG_TYPE_PRE_PROC: s.append("preproc"); break;
-    case EFFECT_FLAG_TYPE_POST_PROC: s.append("postproc"); break;
-    default: s.append("unknown/reserved"); break;
-    }
-    s.append(", ");
-
-    s.append("insert pref: ");
-    switch (flags & EFFECT_FLAG_INSERT_MASK) {
-    case EFFECT_FLAG_INSERT_ANY: s.append("any"); break;
-    case EFFECT_FLAG_INSERT_FIRST: s.append("first"); break;
-    case EFFECT_FLAG_INSERT_LAST: s.append("last"); break;
-    case EFFECT_FLAG_INSERT_EXCLUSIVE: s.append("exclusive"); break;
-    default: s.append("unknown/reserved"); break;
-    }
-    s.append(", ");
-
-    s.append("volume mgmt: ");
-    switch (flags & EFFECT_FLAG_VOLUME_MASK) {
-    case EFFECT_FLAG_VOLUME_NONE: s.append("none"); break;
-    case EFFECT_FLAG_VOLUME_CTRL: s.append("implements control"); break;
-    case EFFECT_FLAG_VOLUME_IND: s.append("requires indication"); break;
-    case EFFECT_FLAG_VOLUME_MONITOR: s.append("monitors volume"); break;
-    default: s.append("unknown/reserved"); break;
-    }
-    s.append(", ");
-
-    uint32_t devind = flags & EFFECT_FLAG_DEVICE_MASK;
-    if (devind) {
-        s.append("device indication: ");
-        switch (devind) {
-        case EFFECT_FLAG_DEVICE_IND: s.append("requires updates"); break;
-        default: s.append("unknown/reserved"); break;
-        }
-        s.append(", ");
-    }
-
-    s.append("input mode: ");
-    switch (flags & EFFECT_FLAG_INPUT_MASK) {
-    case EFFECT_FLAG_INPUT_DIRECT: s.append("direct"); break;
-    case EFFECT_FLAG_INPUT_PROVIDER: s.append("provider"); break;
-    case EFFECT_FLAG_INPUT_BOTH: s.append("direct+provider"); break;
-    default: s.append("not set"); break;
-    }
-    s.append(", ");
-
-    s.append("output mode: ");
-    switch (flags & EFFECT_FLAG_OUTPUT_MASK) {
-    case EFFECT_FLAG_OUTPUT_DIRECT: s.append("direct"); break;
-    case EFFECT_FLAG_OUTPUT_PROVIDER: s.append("provider"); break;
-    case EFFECT_FLAG_OUTPUT_BOTH: s.append("direct+provider"); break;
-    default: s.append("not set"); break;
-    }
-    s.append(", ");
-
-    uint32_t accel = flags & EFFECT_FLAG_HW_ACC_MASK;
-    if (accel) {
-        s.append("hardware acceleration: ");
-        switch (accel) {
-        case EFFECT_FLAG_HW_ACC_SIMPLE: s.append("non-tunneled"); break;
-        case EFFECT_FLAG_HW_ACC_TUNNEL: s.append("tunneled"); break;
-        default: s.append("unknown/reserved"); break;
-        }
-        s.append(", ");
-    }
-
-    uint32_t modeind = flags & EFFECT_FLAG_AUDIO_MODE_MASK;
-    if (modeind) {
-        s.append("mode indication: ");
-        switch (modeind) {
-        case EFFECT_FLAG_AUDIO_MODE_IND: s.append("required"); break;
-        default: s.append("unknown/reserved"); break;
-        }
-        s.append(", ");
-    }
-
-    uint32_t srcind = flags & EFFECT_FLAG_AUDIO_SOURCE_MASK;
-    if (srcind) {
-        s.append("source indication: ");
-        switch (srcind) {
-        case EFFECT_FLAG_AUDIO_SOURCE_IND: s.append("required"); break;
-        default: s.append("unknown/reserved"); break;
-        }
-        s.append(", ");
-    }
-
-    if (flags & EFFECT_FLAG_OFFLOAD_MASK) {
-        s.append("offloadable, ");
-    }
-
-    int len = s.length();
-    if (s.length() > 2) {
-        (void) s.lockBuffer(len);
-        s.unlockBuffer(len - 2);
-    }
-    return s;
-}
-
 static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
     std::stringstream ss;
 
-    if (buffer.get() == nullptr) {
+    if (buffer == nullptr) {
         return "nullptr"; // make different than below
     } else if (buffer->externalData() != nullptr) {
         ss << (isInput ? buffer->externalData() : buffer->audioBuffer()->raw)
@@ -1477,38 +1537,16 @@
     return ss.str();
 }
 
-void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
 {
+    EffectBase::dump(fd, args);
+
     String8 result;
-
-    result.appendFormat("\tEffect ID %d:\n", mId);
-
     bool locked = AudioFlinger::dumpTryLock(mLock);
-    // failed to lock - AudioFlinger is probably deadlocked
-    if (!locked) {
-        result.append("\t\tCould not lock Fx mutex:\n");
-    }
 
-    result.append("\t\tSession Status State Registered Enabled Suspended Engine:\n");
-    result.appendFormat("\t\t%05d   %03d    %03d   %s          %s       %s         %p\n",
-            mSessionId, mStatus, mState, mPolicyRegistered ? "y" : "n", mPolicyEnabled ? "y" : "n",
-            mSuspended ? "y" : "n", mEffectInterface.get());
-
-    result.append("\t\tDescriptor:\n");
-    char uuidStr[64];
-    AudioEffect::guidToString(&mDescriptor.uuid, uuidStr, sizeof(uuidStr));
-    result.appendFormat("\t\t- UUID: %s\n", uuidStr);
-    AudioEffect::guidToString(&mDescriptor.type, uuidStr, sizeof(uuidStr));
-    result.appendFormat("\t\t- TYPE: %s\n", uuidStr);
-    result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
-            mDescriptor.apiVersion,
-            mDescriptor.flags,
-            effectFlagsToString(mDescriptor.flags).string());
-    result.appendFormat("\t\t- name: %s\n",
-            mDescriptor.name);
-
-    result.appendFormat("\t\t- implementor: %s\n",
-            mDescriptor.implementor);
+    result.append("\t\tStatus Engine:\n");
+    result.appendFormat("\t\t%03d    %p\n",
+            mStatus, mEffectInterface.get());
 
     result.appendFormat("\t\t- data: %s\n", mSupportsFloat ? "float" : "int16");
 
@@ -1542,17 +1580,6 @@
             dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
 #endif
 
-    result.appendFormat("\t\t%zu Clients:\n", mHandles.size());
-    result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
-    char buffer[256];
-    for (size_t i = 0; i < mHandles.size(); ++i) {
-        EffectHandle *handle = mHandles[i];
-        if (handle != NULL && !handle->disconnected()) {
-            handle->dumpToBuffer(buffer, sizeof(buffer));
-            result.append(buffer);
-        }
-    }
-
     write(fd, result.string(), result.length());
 
     if (mEffectInterface != 0) {
@@ -1572,7 +1599,7 @@
 #undef LOG_TAG
 #define LOG_TAG "AudioFlinger::EffectHandle"
 
-AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
+AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
                                         const sp<AudioFlinger::Client>& client,
                                         const sp<IEffectClient>& effectClient,
                                         int32_t priority)
@@ -1580,7 +1607,7 @@
     mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
     mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false)
 {
-    ALOGV("constructor %p", this);
+    ALOGV("constructor %p client %p", this, client.get());
 
     if (client == 0) {
         return;
@@ -1588,7 +1615,7 @@
     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
     mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
     if (mCblkMemory == 0 ||
-            (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer())) == NULL) {
+            (mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
         ALOGE("not enough memory for Effect size=%zu", EFFECT_PARAM_BUFFER_SIZE +
                 sizeof(effect_param_cblk_t));
         mCblkMemory.clear();
@@ -1613,7 +1640,7 @@
 {
     AutoMutex _l(mLock);
     ALOGV("enable %p", this);
-    sp<EffectModule> effect = mEffect.promote();
+    sp<EffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         return DEAD_OBJECT;
     }
@@ -1633,38 +1660,16 @@
         return status;
     }
 
-    sp<ThreadBase> thread = effect->thread().promote();
-    if (thread != 0) {
-        thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId());
-    }
+    effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/);
 
     // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
     if (effect->suspended()) {
         return NO_ERROR;
     }
 
-    status = effect->setEnabled(true);
+    status = effect->setEnabled(true, true /*fromHandle*/);
     if (status != NO_ERROR) {
-        if (thread != 0) {
-            thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
-        }
         mEnabled = false;
-    } else {
-        if (thread != 0) {
-            if (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::MMAP) {
-                Mutex::Autolock _l(thread->mLock);
-                thread->broadcast_l();
-            }
-            if (!effect->isOffloadable()) {
-                if (thread->type() == ThreadBase::OFFLOAD) {
-                    PlaybackThread *t = (PlaybackThread *)thread.get();
-                    t->invalidateTracks(AUDIO_STREAM_MUSIC);
-                }
-                if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
-                    thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
-                }
-            }
-        }
     }
     return status;
 }
@@ -1673,7 +1678,7 @@
 {
     ALOGV("disable %p", this);
     AutoMutex _l(mLock);
-    sp<EffectModule> effect = mEffect.promote();
+    sp<EffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         return DEAD_OBJECT;
     }
@@ -1692,17 +1697,7 @@
         return NO_ERROR;
     }
 
-    status_t status = effect->setEnabled(false);
-
-    sp<ThreadBase> thread = effect->thread().promote();
-    if (thread != 0) {
-        thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
-        if (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::MMAP) {
-            Mutex::Autolock _l(thread->mLock);
-            thread->broadcast_l();
-        }
-    }
-
+    status_t status = effect->setEnabled(false, true /*fromHandle*/);
     return status;
 }
 
@@ -1724,12 +1719,9 @@
     }
     mDisconnected = true;
     {
-        sp<EffectModule> effect = mEffect.promote();
+        sp<EffectBase> effect = mEffect.promote();
         if (effect != 0) {
-            sp<ThreadBase> thread = effect->thread().promote();
-            if (thread != 0) {
-                thread->disconnectEffectHandle(this, unpinIfLast);
-            } else if (effect->disconnectHandle(this, unpinIfLast) > 0) {
+            if (effect->disconnectHandle(this, unpinIfLast) > 0) {
                 ALOGW("%s Effect handle %p disconnected after thread destruction",
                     __func__, this);
             }
@@ -1795,7 +1787,7 @@
     }
 
     AutoMutex _l(mLock);
-    sp<EffectModule> effect = mEffect.promote();
+    sp<EffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         return DEAD_OBJECT;
     }
@@ -1803,12 +1795,13 @@
     if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
         return INVALID_OPERATION;
     }
-    if (mClient == 0) {
-        return INVALID_OPERATION;
-    }
 
     // handle commands that are not forwarded transparently to effect engine
     if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
+        if (mClient == 0) {
+            return INVALID_OPERATION;
+        }
+
         if (*replySize < sizeof(int)) {
             android_errorWriteLog(0x534e4554, "32095713");
             return BAD_VALUE;
@@ -1843,12 +1836,13 @@
             }
 
             // copy to local memory in case of client corruption b/32220769
-            param = (effect_param_t *)realloc(param, size);
-            if (param == NULL) {
+            auto *newParam = (effect_param_t *)realloc(param, size);
+            if (newParam == NULL) {
                 ALOGW("command(): out of memory");
                 status = NO_MEMORY;
                 break;
             }
+            param = newParam;
             memcpy(param, p, size);
 
             int reply = 0;
@@ -1947,18 +1941,20 @@
 #undef LOG_TAG
 #define LOG_TAG "AudioFlinger::EffectChain"
 
-AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
-                                        audio_session_t sessionId)
-    : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
+AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
+                                       audio_session_t sessionId)
+    : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
-      mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
+      mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
+      mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
 {
     mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
-    if (thread == NULL) {
+    sp<ThreadBase> p = thread.promote();
+    if (p == nullptr) {
         return;
     }
-    mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
-                                    thread->frameCount();
+    mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
+                                    p->frameCount();
 }
 
 AudioFlinger::EffectChain::~EffectChain()
@@ -2020,43 +2016,30 @@
 void AudioFlinger::EffectChain::clearInputBuffer()
 {
     Mutex::Autolock _l(mLock);
-    sp<ThreadBase> thread = mThread.promote();
-    if (thread == 0) {
-        ALOGW("clearInputBuffer(): cannot promote mixer thread");
-        return;
-    }
-    clearInputBuffer_l(thread);
+    clearInputBuffer_l();
 }
 
 // Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::clearInputBuffer_l(const sp<ThreadBase>& thread)
+void AudioFlinger::EffectChain::clearInputBuffer_l()
 {
     if (mInBuffer == NULL) {
         return;
     }
     const size_t frameSize =
-            audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * thread->channelCount();
+            audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * mEffectCallback->channelCount();
 
-    memset(mInBuffer->audioBuffer()->raw, 0, thread->frameCount() * frameSize);
+    memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
     mInBuffer->commit();
 }
 
 // Must be called with EffectChain::mLock locked
 void AudioFlinger::EffectChain::process_l()
 {
-    sp<ThreadBase> thread = mThread.promote();
-    if (thread == 0) {
-        ALOGW("process_l(): cannot promote mixer thread");
-        return;
-    }
-    bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
-            (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
     // never process effects when:
     // - on an OFFLOAD thread
     // - no more tracks are on the session and the effect tail has been rendered
-    bool doProcess = (thread->type() != ThreadBase::OFFLOAD)
-                  && (thread->type() != ThreadBase::MMAP);
-    if (!isGlobalSession) {
+    bool doProcess = !mEffectCallback->isOffloadOrMmap();
+    if (!audio_is_global_session(mSessionId)) {
         bool tracksOnSession = (trackCnt() != 0);
 
         if (!tracksOnSession && mTailBufferCount == 0) {
@@ -2067,7 +2050,7 @@
             // if no track is active and the effect tail has not been rendered,
             // the input buffer must be cleared here as the mixer process will not do it
             if (tracksOnSession || mTailBufferCount > 0) {
-                clearInputBuffer_l(thread);
+                clearInputBuffer_l();
                 if (mTailBufferCount > 0) {
                     mTailBufferCount--;
                 }
@@ -2103,14 +2086,13 @@
 
 // createEffect_l() must be called with ThreadBase::mLock held
 status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
-                                                   ThreadBase *thread,
                                                    effect_descriptor_t *desc,
                                                    int id,
                                                    audio_session_t sessionId,
                                                    bool pinned)
 {
     Mutex::Autolock _l(mLock);
-    effect = new EffectModule(thread, this, desc, id, sessionId, pinned);
+    effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
     status_t lStatus = effect->status();
     if (lStatus == NO_ERROR) {
         lStatus = addEffect_ll(effect);
@@ -2133,12 +2115,7 @@
     effect_descriptor_t desc = effect->desc();
     uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
 
-    effect->setChain(this);
-    sp<ThreadBase> thread = mThread.promote();
-    if (thread == 0) {
-        return NO_INIT;
-    }
-    effect->setThread(thread);
+    effect->setCallback(mEffectCallback);
 
     if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
         // Auxiliary effects are inserted at the beginning of mEffects vector as
@@ -2149,13 +2126,13 @@
         // 32 bit format. This is to avoid saturation in AudoMixer
         // accumulation stage. Saturation is done in EffectModule::process() before
         // calling the process in effect engine
-        size_t numSamples = thread->frameCount();
+        size_t numSamples = mEffectCallback->frameCount();
         sp<EffectBufferHalInterface> halBuffer;
 #ifdef FLOAT_EFFECT_CHAIN
-        status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+        status_t result = mEffectCallback->allocateHalBuffer(
                 numSamples * sizeof(float), &halBuffer);
 #else
-        status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+        status_t result = mEffectCallback->allocateHalBuffer(
                 numSamples * sizeof(int32_t), &halBuffer);
 #endif
         if (result != OK) return result;
@@ -2288,12 +2265,21 @@
     return mEffects.size();
 }
 
-// setDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
+// setDevices_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
-        mEffects[i]->setDevice(device);
+        mEffects[i]->setDevices(devices);
+    }
+}
+
+// setInputDevice_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+{
+    size_t size = mEffects.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->setInputDevice(device);
     }
 }
 
@@ -2315,6 +2301,13 @@
     }
 }
 
+bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
+    for (const auto &effect : mEffects) {
+        if (effect->isVolumeControlEnabled()) return true;
+    }
+    return false;
+}
+
 // setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
 bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
 {
@@ -2464,7 +2457,7 @@
             if (effect != 0) {
                 desc->mEffect = effect;
                 effect->setSuspended(true);
-                effect->setEnabled(false);
+                effect->setEnabled(false, false /*fromHandle*/);
             }
         }
     } else {
@@ -2622,7 +2615,7 @@
         // if effect is requested to suspended but was not yet enabled, suspend it now.
         if (desc->mEffect == 0) {
             desc->mEffect = effect;
-            effect->setEnabled(false);
+            effect->setEnabled(false, false /*fromHandle*/);
             effect->setSuspended(true);
         }
     } else {
@@ -2657,10 +2650,7 @@
 void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
 {
     Mutex::Autolock _l(mLock);
-    mThread = thread;
-    for (size_t i = 0; i < mEffects.size(); i++) {
-        mEffects[i]->setThread(thread);
-    }
+    mEffectCallback->setThread(thread);
 }
 
 void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
@@ -2720,4 +2710,549 @@
     return true;
 }
 
+// EffectCallbackInterface implementation
+status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
+        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
+        sp<EffectHalInterface> *effect) {
+    status_t status = NO_INIT;
+    sp<AudioFlinger> af = mAudioFlinger.promote();
+    if (af == nullptr) {
+        return status;
+    }
+    sp<EffectsFactoryHalInterface> effectsFactory = af->getEffectsFactory();
+    if (effectsFactory != 0) {
+        status = effectsFactory->createEffect(pEffectUuid, sessionId, io(), deviceId, effect);
+    }
+    return status;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
+        const sp<AudioFlinger::EffectBase>& effect) {
+    sp<AudioFlinger> af = mAudioFlinger.promote();
+    if (af == nullptr) {
+        return false;
+    }
+    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
+    return af->updateOrphanEffectChains(effect->asEffectModule());
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
+        size_t size, sp<EffectBufferHalInterface>* buffer) {
+    sp<AudioFlinger> af = mAudioFlinger.promote();
+    LOG_ALWAYS_FATAL_IF(af == nullptr, "allocateHalBuffer() could not retrieved audio flinger");
+    return af->mEffectsFactoryHal->allocateBuffer(size, buffer);
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
+        sp<EffectHalInterface> effect) {
+    status_t result = NO_INIT;
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return result;
+    }
+    sp <StreamHalInterface> st = t->stream();
+    if (st == nullptr) {
+        return result;
+    }
+    result = st->addEffect(effect);
+    ALOGE_IF(result != OK, "Error when adding effect: %d", result);
+    return result;
+}
+
+status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
+        sp<EffectHalInterface> effect) {
+    status_t result = NO_INIT;
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return result;
+    }
+    sp <StreamHalInterface> st = t->stream();
+    if (st == nullptr) {
+        return result;
+    }
+    result = st->removeEffect(effect);
+    ALOGE_IF(result != OK, "Error when removing effect: %d", result);
+    return result;
+}
+
+audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return AUDIO_IO_HANDLE_NONE;
+    }
+    return t->id();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return true;
+    }
+    return t->isOutput();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return false;
+    }
+    return t->type() == ThreadBase::OFFLOAD;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return false;
+    }
+    return t->type() == ThreadBase::OFFLOAD || t->type() == ThreadBase::DIRECT;
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return false;
+    }
+    return t->isOffloadOrMmap();
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return 0;
+    }
+    return t->sampleRate();
+}
+
+audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::channelMask() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return AUDIO_CHANNEL_NONE;
+    }
+    return t->channelMask();
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::channelCount() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return 0;
+    }
+    return t->channelCount();
+}
+
+size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return 0;
+    }
+    return t->frameCount();
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return 0;
+    }
+    return t->latency_l();
+}
+
+void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return;
+    }
+    t->setVolumeForOutput_l(left, right);
+}
+
+void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
+        const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return;
+    }
+    t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
+
+    sp<EffectChain> c = mChain.promote();
+    if (c == nullptr) {
+        return;
+    }
+    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
+    c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
+}
+
+void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return;
+    }
+    // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
+    t->onEffectEnable(effect->asEffectModule());
+}
+
+void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
+    checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
+
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return;
+    }
+    t->onEffectDisable();
+}
+
+bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
+                                                      bool unpinIfLast) {
+    sp<ThreadBase> t = mThread.promote();
+    if (t == nullptr) {
+        return false;
+    }
+    t->disconnectEffectHandle(handle, unpinIfLast);
+    return true;
+}
+
+void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
+    sp<EffectChain> c = mChain.promote();
+    if (c == nullptr) {
+        return;
+    }
+    c->resetVolume_l();
+
+}
+
+uint32_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
+    sp<EffectChain> c = mChain.promote();
+    if (c == nullptr) {
+        return PRODUCT_STRATEGY_NONE;
+    }
+    return c->strategy();
+}
+
+int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
+    sp<EffectChain> c = mChain.promote();
+    if (c == nullptr) {
+        return 0;
+    }
+    return c->activeTrackCnt();
+}
+
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
+
+status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
+{
+    status_t status = EffectBase::setEnabled(enabled, fromHandle);
+    Mutex::Autolock _l(mProxyLock);
+    if (status == NO_ERROR) {
+        for (auto& handle : mEffectHandles) {
+            if (enabled) {
+                status = handle.second->enable();
+            } else {
+                status = handle.second->disable();
+            }
+        }
+    }
+    ALOGV("%s enable %d status %d", __func__, enabled, status);
+    return status;
+}
+
+status_t AudioFlinger::DeviceEffectProxy::init(
+        const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
+//For all audio patches
+//If src or sink device match
+//If the effect is HW accelerated
+//	if no corresponding effect module
+//		Create EffectModule: mHalEffect
+//Create and attach EffectHandle
+//If the effect is not HW accelerated and the patch sink or src is a mixer port
+//	Create Effect on patch input or output thread on session -1
+//Add EffectHandle to EffectHandle map of Effect Proxy:
+    ALOGV("%s device type %d address %s", __func__,  mDevice.mType, mDevice.getAddress());
+    status_t status = NO_ERROR;
+    for (auto &patch : patches) {
+        status = onCreatePatch(patch.first, patch.second);
+        ALOGV("%s onCreatePatch status %d", __func__, status);
+        if (status == BAD_VALUE) {
+            return status;
+        }
+    }
+    return status;
+}
+
+status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
+        audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
+    status_t status = NAME_NOT_FOUND;
+    sp<EffectHandle> handle;
+    // only consider source[0] as this is the only "true" source of a patch
+    status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
+    ALOGV("%s source checkPort status %d", __func__, status);
+    for (uint32_t i = 0; i < patch.mAudioPatch.num_sinks && status == NAME_NOT_FOUND; i++) {
+        status = checkPort(patch, &patch.mAudioPatch.sinks[i], &handle);
+        ALOGV("%s sink %d checkPort status %d", __func__, i, status);
+    }
+    if (status == NO_ERROR || status == ALREADY_EXISTS) {
+        Mutex::Autolock _l(mProxyLock);
+        mEffectHandles.emplace(patchHandle, handle);
+    }
+    ALOGW_IF(status == BAD_VALUE,
+            "%s cannot attach effect %s on patch %d", __func__, mDescriptor.name, patchHandle);
+
+    return status;
+}
+
+status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
+        const struct audio_port_config *port, sp <EffectHandle> *handle) {
+
+    ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
+            __func__, port->type, port->ext.device.type,
+            port->ext.device.address, port->id, patch.isSoftware());
+    if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
+        || port->ext.device.address != mDevice.mAddress) {
+        return NAME_NOT_FOUND;
+    }
+    status_t status = NAME_NOT_FOUND;
+
+    if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
+        Mutex::Autolock _l(mProxyLock);
+        mDevicePort = *port;
+        mHalEffect = new EffectModule(mMyCallback,
+                                      const_cast<effect_descriptor_t *>(&mDescriptor),
+                                      mMyCallback->newEffectId(), AUDIO_SESSION_DEVICE,
+                                      false /* pinned */, port->id);
+        if (audio_is_input_device(mDevice.mType)) {
+            mHalEffect->setInputDevice(mDevice);
+        } else {
+            mHalEffect->setDevices({mDevice});
+        }
+        *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/);
+        status = (*handle)->initCheck();
+        if (status == OK) {
+            status = mHalEffect->addHandle((*handle).get());
+        } else {
+            mHalEffect.clear();
+            mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
+        }
+    } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
+        sp <ThreadBase> thread;
+        if (audio_port_config_has_input_direction(port)) {
+            if (patch.isSoftware()) {
+                thread = patch.mRecord.thread();
+            } else {
+                thread = patch.thread().promote();
+            }
+        } else {
+            if (patch.isSoftware()) {
+                thread = patch.mPlayback.thread();
+            } else {
+                thread = patch.thread().promote();
+            }
+        }
+        int enabled;
+        *handle = thread->createEffect_l(nullptr, nullptr, 0, AUDIO_SESSION_DEVICE,
+                                         const_cast<effect_descriptor_t *>(&mDescriptor),
+                                         &enabled, &status, false, false /*probe*/);
+        ALOGV("%s thread->createEffect_l status %d", __func__, status);
+    } else {
+        status = BAD_VALUE;
+    }
+    if (status == NO_ERROR || status == ALREADY_EXISTS) {
+        if (isEnabled()) {
+            (*handle)->enable();
+        } else {
+            (*handle)->disable();
+        }
+    }
+    return status;
+}
+
+void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
+    Mutex::Autolock _l(mProxyLock);
+    mEffectHandles.erase(patchHandle);
+}
+
+
+size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
+{
+    Mutex::Autolock _l(mProxyLock);
+    if (effect == mHalEffect) {
+        mHalEffect.clear();
+        mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
+    }
+    return mHalEffect == nullptr ? 0 : 1;
+}
+
+status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
+    sp<EffectHalInterface> effect) {
+    if (mHalEffect == nullptr) {
+        return NO_INIT;
+    }
+    return mManagerCallback->addEffectToHal(
+            mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
+}
+
+status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
+    sp<EffectHalInterface> effect) {
+    if (mHalEffect == nullptr) {
+        return NO_INIT;
+    }
+    return mManagerCallback->removeEffectFromHal(
+            mDevicePort.id, mDevicePort.ext.device.hw_module, effect);
+}
+
+bool AudioFlinger::DeviceEffectProxy::isOutput() const {
+    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
+        return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
+    }
+    return true;
+}
+
+uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
+    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
+            (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
+        return mDevicePort.sample_rate;
+    }
+    return DEFAULT_OUTPUT_SAMPLE_RATE;
+}
+
+audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
+    if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
+            (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
+        return mDevicePort.channel_mask;
+    }
+    return AUDIO_CHANNEL_OUT_STEREO;
+}
+
+uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
+    if (isOutput()) {
+        return audio_channel_count_from_out_mask(channelMask());
+    }
+    return audio_channel_count_from_in_mask(channelMask());
+}
+
+void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
+    const Vector<String16> args;
+    EffectBase::dump(fd, args);
+
+    const bool locked = dumpTryLock(mProxyLock);
+    if (!locked) {
+        String8 result("DeviceEffectProxy may be deadlocked\n");
+        write(fd, result.string(), result.size());
+    }
+
+    String8 outStr;
+    if (mHalEffect != nullptr) {
+        outStr.appendFormat("%*sHAL Effect Id: %d\n", spaces, "", mHalEffect->id());
+    } else {
+        outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
+    }
+    write(fd, outStr.string(), outStr.size());
+    outStr.clear();
+
+    outStr.appendFormat("%*sSub Effects:\n", spaces, "");
+    write(fd, outStr.string(), 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());
+        outStr.clear();
+        sp<EffectBase> effect = iter.second->effect().promote();
+        if (effect != nullptr) {
+            effect->dump(fd, args);
+        }
+    }
+
+    if (locked) {
+        mLock.unlock();
+    }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
+
+int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
+    return mManagerCallback->newEffectId();
+}
+
+
+bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
+        EffectHandle *handle, bool unpinIfLast) {
+    sp<EffectBase> effectBase = handle->effect().promote();
+    if (effectBase == nullptr) {
+        return false;
+    }
+
+    sp<EffectModule> effect = effectBase->asEffectModule();
+    if (effect == nullptr) {
+        return false;
+    }
+
+    // restore suspended effects if the disconnected handle was enabled and the last one.
+    bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
+    if (remove) {
+        sp<DeviceEffectProxy> proxy = mProxy.promote();
+        if (proxy != nullptr) {
+            proxy->removeEffect(effect);
+        }
+        if (handle->enabled()) {
+            effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
+        }
+    }
+    return true;
+}
+
+status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
+        const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
+        sp<EffectHalInterface> *effect) {
+    return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
+}
+
+status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
+        sp<EffectHalInterface> effect) {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return NO_INIT;
+    }
+    return proxy->addEffectToHal(effect);
+}
+
+status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
+        sp<EffectHalInterface> effect) {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return NO_INIT;
+    }
+    return proxy->addEffectToHal(effect);
+}
+
+bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return true;
+    }
+    return proxy->isOutput();
+}
+
+uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return DEFAULT_OUTPUT_SAMPLE_RATE;
+    }
+    return proxy->sampleRate();
+}
+
+audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelMask() const {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return AUDIO_CHANNEL_OUT_STEREO;
+    }
+    return proxy->channelMask();
+}
+
+uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::channelCount() const {
+    sp<DeviceEffectProxy> proxy = mProxy.promote();
+    if (proxy == nullptr) {
+        return 2;
+    }
+    return proxy->channelCount();
+}
+
 } // namespace android
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 220874d..2826297 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -21,34 +21,78 @@
 
 //--- Audio Effect Management
 
-// EffectModule and EffectChain classes both have their own mutex to protect
+// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
+// interactions between the EffectModule and the reset of the audio framework.
+class EffectCallbackInterface : public RefBase {
+public:
+            ~EffectCallbackInterface() override = default;
+
+    // Trivial methods usually implemented with help from ThreadBase
+    virtual audio_io_handle_t io() const = 0;
+    virtual bool isOutput() const = 0;
+    virtual bool isOffload() const = 0;
+    virtual bool isOffloadOrDirect() const = 0;
+    virtual bool isOffloadOrMmap() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t channelMask() const = 0;
+    virtual uint32_t channelCount() const = 0;
+    virtual size_t frameCount() const = 0;
+
+    // Non trivial methods usually implemented with help from ThreadBase:
+    //   pay attention to mutex locking order
+    virtual uint32_t latency() const { return 0; }
+    virtual status_t addEffectToHal(sp<EffectHalInterface> effect) = 0;
+    virtual status_t removeEffectFromHal(sp<EffectHalInterface> effect) = 0;
+    virtual void setVolumeForOutput(float left, float right) const = 0;
+    virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
+    virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
+                                             bool enabled,
+                                             bool threadLocked) = 0;
+    virtual void onEffectEnable(const sp<EffectBase>& effect) = 0;
+    virtual void onEffectDisable(const sp<EffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
+    virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+                    int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
+    virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+    virtual bool updateOrphanEffectChains(const sp<EffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
+    virtual uint32_t strategy() const = 0;
+    virtual int32_t activeTrackCnt() const = 0;
+    virtual void resetVolume() = 0;
+
+    virtual wp<EffectChain> chain() const = 0;
+};
+
+// EffectBase(EffectModule) and EffectChain classes both have their own mutex to protect
 // state changes or resource modifications. Always respect the following order
 // if multiple mutexes must be acquired to avoid cross deadlock:
-// AudioFlinger -> ThreadBase -> EffectChain -> EffectModule
-// AudioHandle -> ThreadBase -> EffectChain -> EffectModule
+// AudioFlinger -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
+// AudioHandle -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
+
+// NOTE: When implementing the EffectCallbackInterface, in an EffectChain or other, it is important
+// to pay attention to this locking order as some callback methods can be called from a state where
+// EffectModule and/or EffectChain mutexes are held.
+
 // In addition, methods that lock the AudioPolicyService mutex (getOutputForEffect(),
 // startOutput(), getInputForAttr(), releaseInput()...) should never be called with AudioFlinger or
 // Threadbase mutex locked to avoid cross deadlock with other clients calling AudioPolicyService
 // methods that in turn call AudioFlinger thus locking the same mutexes in the reverse order.
 
-// The EffectModule class is a wrapper object controlling the effect engine implementation
-// in the effect library. It prevents concurrent calls to process() and command() functions
-// from different client threads. It keeps a list of EffectHandle objects corresponding
-// to all client applications using this effect and notifies applications of effect state,
-// control or parameter changes. It manages the activation state machine to send appropriate
-// reset, enable, disable commands to effect engine and provide volume
-// ramping when effects are activated/deactivated.
-// When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
-// the attached track(s) to accumulate their auxiliary channel.
-class EffectModule : public RefBase {
+
+// The EffectBase class contains common properties, state and behavior for and EffectModule or
+// other derived classes managing an audio effect instance within the effect framework.
+// It also contains the class mutex (see comment on locking order above).
+class EffectBase : public RefBase {
 public:
-    EffectModule(ThreadBase *thread,
-                    const wp<AudioFlinger::EffectChain>& chain,
-                    effect_descriptor_t *desc,
-                    int id,
-                    audio_session_t sessionId,
-                    bool pinned);
-    virtual ~EffectModule();
+    EffectBase(const sp<EffectCallbackInterface>& callback,
+               effect_descriptor_t *desc,
+               int id,
+               audio_session_t sessionId,
+               bool pinned);
+
+    ~EffectBase() override = default;
 
     enum effect_state {
         IDLE,
@@ -60,71 +104,14 @@
         DESTROYED
     };
 
-    int         id() const { return mId; }
-    void process();
-    bool updateState();
-    status_t command(uint32_t cmdCode,
-                     uint32_t cmdSize,
-                     void *pCmdData,
-                     uint32_t *replySize,
-                     void *pReplyData);
-
-    void reset_l();
-    status_t configure();
-    status_t init();
+    int id() const { return mId; }
     effect_state state() const {
         return mState;
     }
-    uint32_t status() {
-        return mStatus;
-    }
     audio_session_t sessionId() const {
         return mSessionId;
     }
-    status_t    setEnabled(bool enabled);
-    status_t    setEnabled_l(bool enabled);
-    bool isEnabled() const;
-    bool isProcessEnabled() const;
-    bool isOffloadedOrDirect() const;
-    bool isVolumeControlEnabled() const;
-
-    void        setInBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *inBuffer() const {
-        return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
-    }
-    void        setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *outBuffer() const {
-        return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
-    }
-    void        setChain(const wp<EffectChain>& chain) { mChain = chain; }
-    void        setThread(const wp<ThreadBase>& thread)
-                    { mThread = thread; mThreadType = thread.promote()->type(); }
-    const wp<ThreadBase>& thread() { return mThread; }
-
-    status_t addHandle(EffectHandle *handle);
-    ssize_t  disconnectHandle(EffectHandle *handle, bool unpinIfLast);
-    ssize_t removeHandle(EffectHandle *handle);
-    ssize_t removeHandle_l(EffectHandle *handle);
-
     const effect_descriptor_t& desc() const { return mDescriptor; }
-    wp<EffectChain>&     chain() { return mChain; }
-
-    status_t         setDevice(audio_devices_t device);
-    status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
-    status_t         setMode(audio_mode_t mode);
-    status_t         setAudioSource(audio_source_t source);
-    status_t         start();
-    status_t         stop();
-    void             setSuspended(bool suspended);
-    bool             suspended() const;
-
-    EffectHandle*    controlHandle_l();
-
-    bool             isPinned() const { return mPinned; }
-    void             unPin() { mPinned = false; }
-    bool             purgeHandles();
-    void             lock() { mLock.lock(); }
-    void             unlock() { mLock.unlock(); }
     bool             isOffloadable() const
                         { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
     bool             isImplementationSoftware() const
@@ -137,18 +124,143 @@
     bool             isVolumeMonitor() const
                         { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
                             == EFFECT_FLAG_VOLUME_MONITOR; }
-    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
-    bool             isOffloaded() const;
-    void             addEffectToHal_l();
-    void             release_l();
+
+    virtual status_t setEnabled(bool enabled, bool fromHandle);
+    status_t    setEnabled_l(bool enabled);
+    bool isEnabled() const;
+
+    void             setSuspended(bool suspended);
+    bool             suspended() const;
+
+    virtual status_t command(uint32_t cmdCode __unused,
+                 uint32_t cmdSize __unused,
+                 void *pCmdData __unused,
+                 uint32_t *replySize __unused,
+                 void *pReplyData __unused) { return NO_ERROR; };
+
+    void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
+    sp<EffectCallbackInterface>&     callback() { return mCallback; }
+
+    status_t addHandle(EffectHandle *handle);
+    ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
+    ssize_t removeHandle(EffectHandle *handle);
+    virtual ssize_t removeHandle_l(EffectHandle *handle);
+    EffectHandle* controlHandle_l();
+    bool purgeHandles();
+
+    void             checkSuspendOnEffectEnabled(bool enabled, bool threadLocked);
+
+    bool             isPinned() const { return mPinned; }
+    void             unPin() { mPinned = false; }
+
+    void             lock() { mLock.lock(); }
+    void             unlock() { mLock.unlock(); }
 
     status_t         updatePolicyState();
 
+    virtual          sp<EffectModule> asEffectModule() { return nullptr; }
+    virtual          sp<DeviceEffectProxy> asDeviceEffectProxy() { return nullptr; }
+
     void             dump(int fd, const Vector<String16>& args);
 
 private:
     friend class AudioFlinger;      // for mHandles
-    bool                mPinned;
+    bool             mPinned = false;
+
+    DISALLOW_COPY_AND_ASSIGN(EffectBase);
+
+mutable Mutex                 mLock;      // mutex for process, commands and handles list protection
+    sp<EffectCallbackInterface> mCallback; // parent effect chain
+    const int                 mId;        // this instance unique ID
+    const audio_session_t     mSessionId; // audio session ID
+    const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
+    effect_state              mState = IDLE; // current activation state
+    // effect is suspended: temporarily disabled by framework
+    bool                      mSuspended = false;
+
+    Vector<EffectHandle *>    mHandles;   // list of client handles
+                // First handle in mHandles has highest priority and controls the effect module
+
+    // Audio policy effect state management
+    // Mutex protecting transactions with audio policy manager as mLock cannot
+    // be held to avoid cross deadlocks with audio policy mutex
+    Mutex                     mPolicyLock;
+    // Effect is registered in APM or not
+    bool                      mPolicyRegistered = false;
+    // Effect enabled state communicated to APM. Enabled state corresponds to
+    // state requested by the EffectHandle with control
+    bool                      mPolicyEnabled = false;
+};
+
+// The EffectModule class is a wrapper object controlling the effect engine implementation
+// in the effect library. It prevents concurrent calls to process() and command() functions
+// from different client threads. It keeps a list of EffectHandle objects corresponding
+// to all client applications using this effect and notifies applications of effect state,
+// control or parameter changes. It manages the activation state machine to send appropriate
+// reset, enable, disable commands to effect engine and provide volume
+// ramping when effects are activated/deactivated.
+// When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
+// the attached track(s) to accumulate their auxiliary channel.
+class EffectModule : public EffectBase {
+public:
+    EffectModule(const sp<EffectCallbackInterface>& callabck,
+                    effect_descriptor_t *desc,
+                    int id,
+                    audio_session_t sessionId,
+                    bool pinned,
+                    audio_port_handle_t deviceId);
+    virtual ~EffectModule();
+
+    void process();
+    bool updateState();
+    status_t command(uint32_t cmdCode,
+                     uint32_t cmdSize,
+                     void *pCmdData,
+                     uint32_t *replySize,
+                     void *pReplyData) override;
+
+    void reset_l();
+    status_t configure();
+    status_t init();
+
+    uint32_t status() {
+        return mStatus;
+    }
+
+    bool isProcessEnabled() const;
+    bool isOffloadedOrDirect() const;
+    bool isVolumeControlEnabled() const;
+
+    void        setInBuffer(const sp<EffectBufferHalInterface>& buffer);
+    int16_t     *inBuffer() const {
+        return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
+    }
+    void        setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
+    int16_t     *outBuffer() const {
+        return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
+    }
+
+    ssize_t removeHandle_l(EffectHandle *handle) override;
+
+    status_t         setDevices(const AudioDeviceTypeAddrVector &devices);
+    status_t         setInputDevice(const AudioDeviceTypeAddr &device);
+    status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
+    status_t         setMode(audio_mode_t mode);
+    status_t         setAudioSource(audio_source_t source);
+    status_t         start();
+    status_t         stop();
+
+    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
+    bool             isOffloaded() const;
+    void             addEffectToHal_l();
+    void             release_l();
+
+    sp<EffectModule> asEffectModule() override { return this; }
+
+    void             dump(int fd, const Vector<String16>& args);
+
+private:
+    friend class AudioFlinger;      // for mHandles
 
     // Maximum time allocated to effect engines to complete the turn off sequence
     static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -157,29 +269,19 @@
 
     status_t start_l();
     status_t stop_l();
-    status_t remove_effect_from_hal_l();
+    status_t removeEffectFromHal_l();
+    status_t sendSetAudioDevicesCommand(const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode);
 
-mutable Mutex               mLock;      // mutex for process, commands and handles list protection
-    wp<ThreadBase>      mThread;    // parent thread
-    ThreadBase::type_t  mThreadType; // parent thread type
-    wp<EffectChain>     mChain;     // parent effect chain
-    const int           mId;        // this instance unique ID
-    const audio_session_t mSessionId; // audio session ID
-    const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
     effect_config_t     mConfig;    // input and output audio configuration
     sp<EffectHalInterface> mEffectInterface; // Effect module HAL
     sp<EffectBufferHalInterface> mInBuffer;  // Buffers for interacting with HAL
     sp<EffectBufferHalInterface> mOutBuffer;
     status_t            mStatus;    // initialization status
-    effect_state        mState;     // current activation state
-    Vector<EffectHandle *> mHandles;    // list of client handles
                 // First handle in mHandles has highest priority and controls the effect module
     uint32_t mMaxDisableWaitCnt;    // maximum grace period before forcing an effect off after
                                     // sending disable command.
     uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
-    bool     mSuspended;            // effect is suspended: temporarily disabled by framework
     bool     mOffloaded;            // effect is currently offloaded to the audio DSP
-    wp<AudioFlinger>    mAudioFlinger;
 
 #ifdef FLOAT_EFFECT_CHAIN
     bool    mSupportsFloat;         // effect supports float processing
@@ -206,16 +308,6 @@
     static constexpr pid_t INVALID_PID = (pid_t)-1;
     // this tid is allowed to call setVolume() without acquiring the mutex.
     pid_t mSetVolumeReentrantTid = INVALID_PID;
-
-    // Audio policy effect state management
-    // Mutex protecting transactions with audio policy manager as mLock cannot
-    // be held to avoid cross deadlocks with audio policy mutex
-    Mutex   mPolicyLock;
-    // Effect is registered in APM or not
-    bool    mPolicyRegistered = false;
-    // Effect enabled state communicated to APM. Enabled state corresponds to
-    // state requested by the EffectHandle with control
-    bool    mPolicyEnabled = false;
 };
 
 // The EffectHandle class implements the IEffect interface. It provides resources
@@ -227,7 +319,7 @@
 class EffectHandle: public android::BnEffect {
 public:
 
-    EffectHandle(const sp<EffectModule>& effect,
+    EffectHandle(const sp<EffectBase>& effect,
             const sp<AudioFlinger::Client>& client,
             const sp<IEffectClient>& effectClient,
             int32_t priority);
@@ -265,9 +357,9 @@
     bool enabled() const { return mEnabled; }
 
     // Getters
-    wp<EffectModule> effect() const { return mEffect; }
+    wp<EffectBase> effect() const { return mEffect; }
     int id() const {
-        sp<EffectModule> effect = mEffect.promote();
+        sp<EffectBase> effect = mEffect.promote();
         if (effect == 0) {
             return 0;
         }
@@ -284,7 +376,7 @@
     DISALLOW_COPY_AND_ASSIGN(EffectHandle);
 
     Mutex mLock;                        // protects IEffect method calls
-    wp<EffectModule> mEffect;           // pointer to controlled EffectModule
+    wp<EffectBase> mEffect;           // pointer to controlled EffectModule
     sp<IEffectClient> mEffectClient;    // callback interface for client notifications
     /*const*/ sp<Client> mClient;       // client for shared memory allocation, see disconnect()
     sp<IMemory>         mCblkMemory;    // shared memory for control block
@@ -310,7 +402,6 @@
 class EffectChain : public RefBase {
 public:
     EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
-    EffectChain(ThreadBase *thread, audio_session_t sessionId);
     virtual ~EffectChain();
 
     // special key used for an entry in mSuspendedEffects keyed vector
@@ -331,7 +422,6 @@
     }
 
     status_t createEffect_l(sp<EffectModule>& effect,
-                            ThreadBase *thread,
                             effect_descriptor_t *desc,
                             int id,
                             audio_session_t sessionId,
@@ -350,7 +440,8 @@
     // FIXME use float to improve the dynamic range
     bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
     void resetVolume_l();
-    void setDevice_l(audio_devices_t device);
+    void setDevices_l(const AudioDeviceTypeAddrVector &devices);
+    void setInputDevice_l(const AudioDeviceTypeAddr &device);
     void setMode_l(audio_mode_t mode);
     void setAudioSource_l(audio_source_t source);
 
@@ -386,9 +477,8 @@
                               bool suspend);
     // suspend all eligible effects
     void setEffectSuspendedAll_l(bool suspend);
-    // check if effects should be suspend or restored when a given effect is enable or disabled
-    void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
-                                          bool enabled);
+    // check if effects should be suspended or restored when a given effect is enable or disabled
+    void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, bool enabled);
 
     void clearInputBuffer();
 
@@ -413,9 +503,70 @@
     // isCompatibleWithThread_l() must be called with thread->mLock held
     bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
 
+    sp<EffectCallbackInterface> effectCallback() const { return mEffectCallback; }
+    wp<ThreadBase> thread() const { return mEffectCallback->thread(); }
+
     void dump(int fd, const Vector<String16>& args);
 
 private:
+
+    class EffectCallback :  public EffectCallbackInterface {
+    public:
+        // Note: ctors taking a weak pointer to their owner must not promote it
+        // during construction (but may keep a reference for later promotion).
+        EffectCallback(const wp<EffectChain>& owner,
+                       const wp<ThreadBase>& thread)
+            : mChain(owner) {
+            setThread(thread);
+        }
+
+        status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+               int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
+        status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+        bool updateOrphanEffectChains(const sp<EffectBase>& effect) override;
+
+        audio_io_handle_t io() const override;
+        bool isOutput() const override;
+        bool isOffload() const override;
+        bool isOffloadOrDirect() const override;
+        bool isOffloadOrMmap() const override;
+
+        uint32_t sampleRate() const override;
+        audio_channel_mask_t channelMask() const override;
+        uint32_t channelCount() const override;
+        size_t frameCount() const override;
+        uint32_t latency() const override;
+
+        status_t addEffectToHal(sp<EffectHalInterface> effect) override;
+        status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        void setVolumeForOutput(float left, float right) const override;
+
+        // check if effects should be suspended/restored when a given effect is enable/disabled
+        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
+                              bool enabled, bool threadLocked) override;
+        void resetVolume() override;
+        uint32_t strategy() const override;
+        int32_t activeTrackCnt() const override;
+        void onEffectEnable(const sp<EffectBase>& effect) override;
+        void onEffectDisable(const sp<EffectBase>& effect) override;
+
+        wp<EffectChain> chain() const override { return mChain; }
+
+        wp<ThreadBase> thread() { return mThread; }
+
+        void setThread(const wp<ThreadBase>& thread) {
+            mThread = thread;
+            sp<ThreadBase> p = thread.promote();
+            mAudioFlinger = p ? p->mAudioFlinger : nullptr;
+        }
+
+    private:
+        wp<EffectChain> mChain;
+        wp<ThreadBase> mThread;
+        wp<AudioFlinger> mAudioFlinger;
+    };
+
     friend class AudioFlinger;  // for mThread, mEffects
     DISALLOW_COPY_AND_ASSIGN(EffectChain);
 
@@ -441,13 +592,15 @@
 
     static bool isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type);
 
-    void clearInputBuffer_l(const sp<ThreadBase>& thread);
+    void clearInputBuffer_l();
 
     void setThread(const sp<ThreadBase>& thread);
 
+    // true if any effect module within the chain has volume control
+    bool hasVolumeControlEnabled_l() const;
+
     void setVolumeForOutput_l(uint32_t left, uint32_t right);
 
-             wp<ThreadBase> mThread;     // parent mixer thread
     mutable  Mutex mLock;        // mutex protecting effect list
              Vector< sp<EffectModule> > mEffects; // list of effect modules
              audio_session_t mSessionId; // audio session ID
@@ -471,4 +624,102 @@
              // timeLow fields among effect type UUIDs.
              // Updated by setEffectSuspended_l() and setEffectSuspendedAll_l() only.
              KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
+
+             const sp<EffectCallback> mEffectCallback;
+};
+
+class DeviceEffectProxy : public EffectBase {
+public:
+        DeviceEffectProxy (const AudioDeviceTypeAddr& device,
+                const sp<DeviceEffectManagerCallback>& callback,
+                effect_descriptor_t *desc, int id)
+            : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
+                mDevice(device), mManagerCallback(callback),
+                mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this),
+                                              callback)) {}
+
+    status_t setEnabled(bool enabled, bool fromHandle) override;
+    sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
+
+    status_t init(const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches);
+    status_t onCreatePatch(audio_patch_handle_t patchHandle, const PatchPanel::Patch& patch);
+    void onReleasePatch(audio_patch_handle_t patchHandle);
+
+    size_t removeEffect(const sp<EffectModule>& effect);
+
+    status_t addEffectToHal(sp<EffectHalInterface> effect);
+    status_t removeEffectFromHal(sp<EffectHalInterface> effect);
+
+    const AudioDeviceTypeAddr& device() { return mDevice; };
+    bool isOutput() const;
+    uint32_t sampleRate() const;
+    audio_channel_mask_t channelMask() const;
+    uint32_t channelCount() const;
+
+    void dump(int fd, int spaces);
+
+private:
+
+    class ProxyCallback :  public EffectCallbackInterface {
+    public:
+        // Note: ctors taking a weak pointer to their owner must not promote it
+        // during construction (but may keep a reference for later promotion).
+        ProxyCallback(const wp<DeviceEffectProxy>& owner,
+                const sp<DeviceEffectManagerCallback>& callback)
+            : mProxy(owner), mManagerCallback(callback) {}
+
+        status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+               int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
+        status_t allocateHalBuffer(size_t size __unused,
+                sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
+        bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override {
+                    return false;
+        }
+
+        audio_io_handle_t io() const override { return AUDIO_IO_HANDLE_NONE; }
+        bool isOutput() const override;
+        bool isOffload() const override { return false; }
+        bool isOffloadOrDirect() const override { return false; }
+        bool isOffloadOrMmap() const override { return false; }
+
+        uint32_t sampleRate() const override;
+        audio_channel_mask_t channelMask() const override;
+        uint32_t channelCount() const override;
+        size_t frameCount() const override  { return 0; }
+        uint32_t latency() const override  { return 0; }
+
+        status_t addEffectToHal(sp<EffectHalInterface> effect) override;
+        status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+
+        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        void setVolumeForOutput(float left __unused, float right __unused) const override {}
+
+        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+                              bool enabled __unused, bool threadLocked __unused) override {}
+        void resetVolume() override {}
+        uint32_t strategy() const override  { return 0; }
+        int32_t activeTrackCnt() const override { return 0; }
+        void onEffectEnable(const sp<EffectBase>& effect __unused) override {}
+        void onEffectDisable(const sp<EffectBase>& effect __unused) override {}
+
+        wp<EffectChain> chain() const override { return nullptr; }
+
+        int newEffectId();
+
+    private:
+        const wp<DeviceEffectProxy> mProxy;
+        const sp<DeviceEffectManagerCallback> mManagerCallback;
+    };
+
+    status_t checkPort(const PatchPanel::Patch& patch, const struct audio_port_config *port,
+            sp<EffectHandle> *handle);
+
+    const AudioDeviceTypeAddr mDevice;
+    const sp<DeviceEffectManagerCallback> mManagerCallback;
+    const sp<ProxyCallback> mMyCallback;
+
+    Mutex mProxyLock;
+    std::map<audio_patch_handle_t, sp<EffectHandle>> mEffectHandles; // protected by mProxyLock
+    sp<EffectModule> mHalEffect; // protected by mProxyLock
+    struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
 };
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index c5b9953..3eacc8c 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -105,13 +105,8 @@
     return mSQ.poll();
 }
 
-void FastMixer::setNBLogWriter(NBLog::Writer *logWriter)
+void FastMixer::setNBLogWriter(NBLog::Writer *logWriter __unused)
 {
-    // FIXME If mMixer is set or changed prior to this, we don't inform correctly.
-    //       Should cache logWriter and re-apply it at the assignment to mMixer.
-    if (mMixer != NULL) {
-        mMixer->setNBLogWriter(logWriter);
-    }
 }
 
 void FastMixer::onIdle()
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 04b32c2..47fe0b3 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -124,7 +124,7 @@
             mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
             tlNBLogWriter = next->mNBLogWriter != NULL ?
                     next->mNBLogWriter : mDummyNBLogWriter.get();
-            setNBLogWriter(tlNBLogWriter); // FastMixer informs its AudioMixer, FastCapture ignores
+            setNBLogWriter(tlNBLogWriter); // This is used for debugging only
 
             // We want to always have a valid reference to the previous (non-idle) state.
             // However, the state queue only guarantees access to current and previous states.
@@ -309,7 +309,7 @@
                     // compute the delta value of clock_gettime(CLOCK_MONOTONIC)
                     uint32_t monotonicNs = nsec;
                     if (sec > 0 && sec < 4) {
-                        monotonicNs += sec * 1000000000;
+                        monotonicNs += sec * 1000000000U; // unsigned to prevent signed overflow.
                     }
                     // compute raw CPU load = delta value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
                     uint32_t loadNs = 0;
@@ -325,7 +325,7 @@
                             }
                             loadNs = nsec;
                             if (sec > 0 && sec < 4) {
-                                loadNs += sec * 1000000000;
+                                loadNs += sec * 1000000000U; // unsigned to prevent signed overflow.
                             }
                         } else {
                             // first time through the loop
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index edb331d..b58fd8b 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -25,6 +25,7 @@
 
 #include "AudioFlinger.h"
 #include <media/AudioParameter.h>
+#include <media/DeviceDescriptorBase.h>
 #include <media/PatchBuilder.h>
 #include <mediautils/ServiceUtilities.h>
 
@@ -167,9 +168,9 @@
                 if (hwDevice != 0) {
                     hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                 }
+                halHandle = removedPatch.mHalHandle;
             }
-            mPatches.erase(iter);
-            removeSoftwarePatchFromInsertedModules(*handle);
+            erasePatch(*handle);
         }
     }
 
@@ -324,10 +325,14 @@
                         }
                     }
                     status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+                    if (status == NO_ERROR) {
+                        newPatch.setThread(thread);
+                    }
+
                     // remove stale audio patch with same input as sink if any
                     for (auto& iter : mPatches) {
                         if (iter.second.mAudioPatch.sinks[0].ext.mix.handle == thread->id()) {
-                            mPatches.erase(iter.first);
+                            erasePatch(iter.first);
                             break;
                         }
                     }
@@ -351,7 +356,7 @@
                 goto exit;
             }
             // limit to connections between devices and output streams
-            audio_devices_t type = AUDIO_DEVICE_NONE;
+            DeviceDescriptorBaseVector devices;
             for (unsigned int i = 0; i < patch->num_sinks; i++) {
                 if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
                     ALOGW("%s() invalid sink type %d for mix source",
@@ -364,7 +369,11 @@
                     status = BAD_VALUE;
                     goto exit;
                 }
-                type |= patch->sinks[i].ext.device.type;
+                sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(
+                        patch->sinks[i].ext.device.type);
+                device->setAddress(patch->sinks[i].ext.device.address);
+                device->applyAudioPortConfig(&patch->sinks[i]);
+                devices.push_back(device);
             }
             sp<ThreadBase> thread =
                             mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
@@ -378,18 +387,18 @@
                 }
             }
             if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
-                AudioParameter param = AudioParameter();
-                param.addInt(String8(AudioParameter::keyRouting), (int)type);
-
-                mAudioFlinger.broacastParametersToRecordThreads_l(param.toString());
+                mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
             }
 
             status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+            if (status == NO_ERROR) {
+                newPatch.setThread(thread);
+            }
 
             // remove stale audio patch with same output as source if any
             for (auto& iter : mPatches) {
                 if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id()) {
-                    mPatches.erase(iter.first);
+                    erasePatch(iter.first);
                     break;
                 }
             }
@@ -403,11 +412,11 @@
     if (status == NO_ERROR) {
         *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
         newPatch.mHalHandle = halHandle;
+        mAudioFlinger.mDeviceEffectManager.createAudioPatch(*handle, newPatch);
         mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
         if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
             addSoftwarePatchToInsertedModules(insertedModule, *handle);
         }
-        ALOGV("%s() added new patch handle %d halHandle %d", __func__, *handle, halHandle);
     } else {
         newPatch.clearConnections(this);
     }
@@ -445,18 +454,6 @@
         *mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    // use a pseudo LCM between input and output framecount
-    size_t playbackFrameCount = mPlayback.thread()->frameCount();
-    int playbackShift = __builtin_ctz(playbackFrameCount);
-    size_t recordFrameCount = mRecord.thread()->frameCount();
-    int shift = __builtin_ctz(recordFrameCount);
-    if (playbackShift < shift) {
-        shift = playbackShift;
-    }
-    size_t frameCount = (playbackFrameCount * recordFrameCount) >> shift;
-    ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
-            __func__, playbackFrameCount, recordFrameCount, frameCount);
-
     // create a special record track to capture from record thread
     uint32_t channelCount = mPlayback.thread()->channelCount();
     audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount);
@@ -483,19 +480,6 @@
         // Fast mode is not available in this case.
         inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST);
     }
-    sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord(
-                                             mRecord.thread().get(),
-                                             sampleRate,
-                                             inChannelMask,
-                                             format,
-                                             frameCount,
-                                             NULL,
-                                             (size_t)0 /* bufferSize */,
-                                             inputFlags);
-    status = mRecord.checkTrack(tempRecordTrack.get());
-    if (status != NO_ERROR) {
-        return status;
-    }
 
     audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ?
             mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE;
@@ -512,9 +496,54 @@
         outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST);
     }
 
+    sp<RecordThread::PatchRecord> tempRecordTrack;
+    const bool usePassthruPatchRecord =
+            (inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT);
+    const size_t playbackFrameCount = mPlayback.thread()->frameCount();
+    const size_t recordFrameCount = mRecord.thread()->frameCount();
+    size_t frameCount = 0;
+    if (usePassthruPatchRecord) {
+        // PassthruPatchRecord producesBufferOnDemand, so use
+        // maximum of playback and record thread framecounts
+        frameCount = std::max(playbackFrameCount, recordFrameCount);
+        ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
+            __func__, playbackFrameCount, recordFrameCount, frameCount);
+        tempRecordTrack = new RecordThread::PassthruPatchRecord(
+                                                 mRecord.thread().get(),
+                                                 sampleRate,
+                                                 inChannelMask,
+                                                 format,
+                                                 frameCount,
+                                                 inputFlags);
+    } else {
+        // use a pseudo LCM between input and output framecount
+        int playbackShift = __builtin_ctz(playbackFrameCount);
+        int shift = __builtin_ctz(recordFrameCount);
+        if (playbackShift < shift) {
+            shift = playbackShift;
+        }
+        frameCount = (playbackFrameCount * recordFrameCount) >> shift;
+        ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
+            __func__, playbackFrameCount, recordFrameCount, frameCount);
+
+        tempRecordTrack = new RecordThread::PatchRecord(
+                                                 mRecord.thread().get(),
+                                                 sampleRate,
+                                                 inChannelMask,
+                                                 format,
+                                                 frameCount,
+                                                 nullptr,
+                                                 (size_t)0 /* bufferSize */,
+                                                 inputFlags);
+    }
+    status = mRecord.checkTrack(tempRecordTrack.get());
+    if (status != NO_ERROR) {
+        return status;
+    }
+
     // create a special playback track to render to playback thread.
     // this track is given the same buffer as the PatchRecord buffer
-    sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack(
+    sp<PlaybackThread::PatchTrack> tempPatchTrack = new PlaybackThread::PatchTrack(
                                            mPlayback.thread().get(),
                                            streamType,
                                            sampleRate,
@@ -530,8 +559,14 @@
     }
 
     // tie playback and record tracks together
-    mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack);
-    mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack);
+    // In the case of PassthruPatchRecord no I/O activity happens on RecordThread,
+    // everything is driven from PlaybackThread. Thus AudioBufferProvider methods
+    // of PassthruPatchRecord can only be called if the corresponding PatchTrack
+    // is alive. There is no need to hold a reference, and there is no need
+    // to clear it. In fact, since playback stopping is asynchronous, there is
+    // no proper time when clearing could be done.
+    mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack, !usePassthruPatchRecord);
+    mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack, true /*holdReference*/);
 
     // start capture and playback
     mRecord.track()->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE);
@@ -613,8 +648,21 @@
 String8 AudioFlinger::PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const
 {
     // TODO: Consider table dump form for patches, just like tracks.
-    String8 result = String8::format("Patch %d: thread %p => thread %p",
-            myHandle, mRecord.const_thread().get(), mPlayback.const_thread().get());
+    String8 result = String8::format("Patch %d: %s (thread %p => thread %p)",
+            myHandle, isSoftware() ? "Software bridge between" : "No software bridge",
+            mRecord.const_thread().get(), mPlayback.const_thread().get());
+
+    bool hasSinkDevice =
+            mAudioPatch.num_sinks > 0 && mAudioPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE;
+    bool hasSourceDevice =
+            mAudioPatch.num_sources > 0 && mAudioPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE;
+    result.appendFormat(" thread %p %s (%d) first device type %08x", mThread.unsafe_get(),
+            hasSinkDevice ? "num sinks" :
+                (hasSourceDevice ? "num sources" : "no devices"),
+            hasSinkDevice ? mAudioPatch.num_sinks :
+                (hasSourceDevice ? mAudioPatch.num_sources : 0),
+            hasSinkDevice ? mAudioPatch.sinks[0].ext.device.type :
+                (hasSourceDevice ? mAudioPatch.sources[0].ext.device.type : 0));
 
     // add latency if it exists
     double latencyMs;
@@ -690,11 +738,16 @@
             status = BAD_VALUE;
     }
 
-    mPatches.erase(iter);
-    removeSoftwarePatchFromInsertedModules(handle);
+    erasePatch(handle);
     return status;
 }
 
+void AudioFlinger::PatchPanel::erasePatch(audio_patch_handle_t handle) {
+    mPatches.erase(handle);
+    removeSoftwarePatchFromInsertedModules(handle);
+    mAudioFlinger.mDeviceEffectManager.releaseAudioPatch(handle);
+}
+
 /* List connected audio ports and they attributes */
 status_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused,
                                   struct audio_patch *patches __unused)
@@ -778,16 +831,13 @@
     String8 patchPanelDump;
     const char *indent = "  ";
 
-    // Only dump software patches.
     bool headerPrinted = false;
     for (const auto& iter : mPatches) {
-        if (iter.second.isSoftware()) {
-            if (!headerPrinted) {
-                patchPanelDump += "\nSoftware patches:\n";
-                headerPrinted = true;
-            }
-            patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).string());
+        if (!headerPrinted) {
+            patchPanelDump += "\nPatches:\n";
+            headerPrinted = true;
         }
+        patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).string());
     }
 
     headerPrinted = false;
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 181e27c..89d4eb1 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -76,13 +76,18 @@
 
     void dump(int fd) const;
 
-private:
     template<typename ThreadType, typename TrackType>
-    class Endpoint {
+    class Endpoint final {
     public:
         Endpoint() = default;
         Endpoint(const Endpoint&) = delete;
-        Endpoint& operator=(const Endpoint&) = delete;
+        Endpoint& operator=(const Endpoint& other) noexcept {
+            mThread = other.mThread;
+            mCloseThread = other.mCloseThread;
+            mHandle = other.mHandle;
+            mTrack = other.mTrack;
+            return *this;
+        }
         Endpoint(Endpoint&& other) noexcept { swap(other); }
         Endpoint& operator=(Endpoint&& other) noexcept {
             swap(other);
@@ -98,8 +103,8 @@
             return trackOrNull->initCheck();
         }
         audio_patch_handle_t handle() const { return mHandle; }
-        sp<ThreadType> thread() { return mThread; }
-        sp<TrackType> track() { return mTrack; }
+        sp<ThreadType> thread() const { return mThread; }
+        sp<TrackType> track() const { return mTrack; }
         sp<const ThreadType> const_thread() const { return mThread; }
         sp<const TrackType> const_track() const { return mTrack; }
 
@@ -123,18 +128,20 @@
             mCloseThread = closeThread;
         }
         template <typename T>
-        void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer) {
+        void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer, bool holdReference) {
             mTrack = track;
             mThread->addPatchTrack(mTrack);
-            mTrack->setPeerProxy(peer, true /* holdReference */);
+            mTrack->setPeerProxy(peer, holdReference);
+            mClearPeerProxy = holdReference;
         }
-        void clearTrackPeer() { if (mTrack) mTrack->clearPeerProxy(); }
+        void clearTrackPeer() { if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); }
         void stopTrack() { if (mTrack) mTrack->stop(); }
 
         void swap(Endpoint &other) noexcept {
             using std::swap;
             swap(mThread, other.mThread);
             swap(mCloseThread, other.mCloseThread);
+            swap(mClearPeerProxy, other.mClearPeerProxy);
             swap(mHandle, other.mHandle);
             swap(mTrack, other.mTrack);
         }
@@ -146,18 +153,41 @@
     private:
         sp<ThreadType> mThread;
         bool mCloseThread = true;
+        bool mClearPeerProxy = true;
         audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
         sp<TrackType> mTrack;
     };
 
-    class Patch {
+    class Patch final {
     public:
         explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {}
+        Patch() = default;
         ~Patch();
-        Patch(const Patch&) = delete;
-        Patch(Patch&&) = default;
-        Patch& operator=(const Patch&) = delete;
-        Patch& operator=(Patch&&) = default;
+        Patch(const Patch& other) noexcept {
+            mAudioPatch = other.mAudioPatch;
+            mHalHandle = other.mHalHandle;
+            mPlayback = other.mPlayback;
+            mRecord = other.mRecord;
+            mThread = other.mThread;
+        }
+        Patch(Patch&& other) noexcept { swap(other); }
+        Patch& operator=(Patch&& other) noexcept {
+            swap(other);
+            return *this;
+        }
+
+        void swap(Patch &other) noexcept {
+            using std::swap;
+            swap(mAudioPatch, other.mAudioPatch);
+            swap(mHalHandle, other.mHalHandle);
+            swap(mPlayback, other.mPlayback);
+            swap(mRecord, other.mRecord);
+            swap(mThread, other.mThread);
+        }
+
+        friend void swap(Patch &a, Patch &b) noexcept {
+            a.swap(b);
+        }
 
         status_t createConnections(PatchPanel *panel);
         void clearConnections(PatchPanel *panel);
@@ -165,6 +195,9 @@
             return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
                     mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
 
+        void setThread(sp<ThreadBase> thread) { mThread = thread; }
+        wp<ThreadBase> thread() const { return mThread; }
+
         // returns the latency of the patch (from record to playback).
         status_t getLatencyMs(double *latencyMs) const;
 
@@ -182,13 +215,20 @@
         Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback;
         // connects source device to record thread input
         Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
+
+        wp<ThreadBase> mThread;
     };
 
+    // Call with AudioFlinger mLock held
+    std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; }
+
+private:
     AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
     sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
     void addSoftwarePatchToInsertedModules(
             audio_module_handle_t module, audio_patch_handle_t handle);
     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
+    void erasePatch(audio_patch_handle_t handle);
 
     AudioFlinger &mAudioFlinger;
     std::map<audio_patch_handle_t, Patch> mPatches;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 17adba5..d8eebf3 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -171,6 +171,16 @@
 
             void    setTeePatches(TeePatches teePatches);
 
+    void tallyUnderrunFrames(size_t frames) override {
+       if (isOut()) { // we expect this from output tracks only
+           mAudioTrackServerProxy->tallyUnderrunFrames(frames);
+           // Fetch absolute numbers from AudioTrackShared as it counts
+           // contiguous underruns as a one -- we want a consistent number.
+           // TODO: isolate this counting into a class.
+           mTrackMetrics.logUnderruns(mAudioTrackServerProxy->getUnderrunCount(),
+                   mAudioTrackServerProxy->getUnderrunFrames());
+       }
+    }
 protected:
     // for numerous
     friend class PlaybackThread;
@@ -271,8 +281,6 @@
 
 private:
     void                interceptBuffer(const AudioBufferProvider::Buffer& buffer);
-    /** Write the source data in the buffer provider. @return written frame count. */
-    size_t              writeFrames(AudioBufferProvider* dest, const void* src, size_t frameCount);
     template <class F>
     void                forEachTeePatchTrack(F f) {
         for (auto& tp : mTeePatches) { f(tp.patchTrack); }
@@ -396,6 +404,8 @@
                                                                     *  even if it might glitch. */);
     virtual             ~PatchTrack();
 
+            size_t      framesReady() const override;
+
     virtual status_t    start(AudioSystem::sync_event_t event =
                                     AudioSystem::SYNC_EVENT_NONE,
                              audio_session_t triggerSession = AUDIO_SESSION_NONE);
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index c8397cd..d87239d 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -25,7 +25,8 @@
     ~OpRecordAudioMonitor() override;
     bool hasOpRecordAudio() const;
 
-    static sp<OpRecordAudioMonitor> createIfNeeded(uid_t uid, const String16& opPackageName);
+    static sp<OpRecordAudioMonitor> createIfNeeded
+        (uid_t uid, const audio_attributes_t& attr, const String16& opPackageName);
 
 private:
     OpRecordAudioMonitor(uid_t uid, const String16& opPackageName);
@@ -167,6 +168,8 @@
                 const Timeout& timeout = {});
     virtual             ~PatchRecord();
 
+    virtual Source* getSource() { return nullptr; }
+
     // AudioBufferProvider interface
     virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
     virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -175,4 +178,71 @@
     virtual status_t    obtainBuffer(Proxy::Buffer *buffer,
                                      const struct timespec *timeOut = NULL);
     virtual void        releaseBuffer(Proxy::Buffer *buffer);
+
+    size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) {
+        return writeFrames(this, src, frameCount, frameSize);
+    }
+
+protected:
+    /** Write the source data into the buffer provider. @return written frame count. */
+    static size_t writeFrames(AudioBufferProvider* dest, const void* src,
+            size_t frameCount, size_t frameSize);
+
 };  // end of PatchRecord
+
+class PassthruPatchRecord : public PatchRecord, public Source {
+public:
+    PassthruPatchRecord(RecordThread *recordThread,
+                        uint32_t sampleRate,
+                        audio_channel_mask_t channelMask,
+                        audio_format_t format,
+                        size_t frameCount,
+                        audio_input_flags_t flags);
+
+    Source* getSource() override { return static_cast<Source*>(this); }
+
+    // Source interface
+    status_t read(void *buffer, size_t bytes, size_t *read) override;
+    status_t getCapturePosition(int64_t *frames, int64_t *time) override;
+    status_t standby() override;
+
+    // AudioBufferProvider interface
+    // This interface is used by RecordThread to pass the data obtained
+    // from HAL or other source to the client. PassthruPatchRecord receives
+    // the data in 'obtainBuffer' so these calls are stubbed out.
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
+
+    // PatchProxyBufferProvider interface
+    // This interface is used from DirectOutputThread to acquire data from HAL.
+    bool producesBufferOnDemand() const override { return true; }
+    status_t obtainBuffer(Proxy::Buffer *buffer, const struct timespec *timeOut = nullptr) override;
+    void releaseBuffer(Proxy::Buffer *buffer) override;
+
+private:
+    // This is to use with PatchRecord::writeFrames
+    struct PatchRecordAudioBufferProvider : public AudioBufferProvider {
+        explicit PatchRecordAudioBufferProvider(PassthruPatchRecord& passthru) :
+                mPassthru(passthru) {}
+        status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override {
+            return mPassthru.PatchRecord::getNextBuffer(buffer);
+        }
+        void releaseBuffer(AudioBufferProvider::Buffer* buffer) override {
+            return mPassthru.PatchRecord::releaseBuffer(buffer);
+        }
+    private:
+        PassthruPatchRecord& mPassthru;
+    };
+
+    sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+
+    PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
+    std::unique_ptr<void, decltype(free)*> mSinkBuffer;  // frame size aligned continuous buffer
+    std::unique_ptr<void, decltype(free)*> mStubBuffer;  // buffer used for AudioBufferProvider
+    size_t mUnconsumedFrames = 0;
+    std::mutex mReadLock;
+    std::condition_variable mReadCV;
+    size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
+    status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
+    int64_t mLastReadFrames = 0;  // accessed on RecordThread only
+};
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index a44ab2a..c7aba79 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -59,6 +59,7 @@
     // TODO Move this into the audio_utils as a static method.
     switch(config->format) {
         case AUDIO_FORMAT_E_AC3:
+        case AUDIO_FORMAT_E_AC3_JOC:
             mRateMultiplier = 4;
             break;
         case AUDIO_FORMAT_AC3:
diff --git a/services/audioflinger/ThreadMetrics.h b/services/audioflinger/ThreadMetrics.h
new file mode 100644
index 0000000..6526655
--- /dev/null
+++ b/services/audioflinger/ThreadMetrics.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_THREADMETRICS_H
+#define ANDROID_AUDIO_THREADMETRICS_H
+
+#include <mutex>
+
+namespace android {
+
+/**
+ * ThreadMetrics handles the AudioFlinger thread log statistics.
+ *
+ * We aggregate metrics for a particular device for proper analysis.
+ * This includes power, performance, and usage metrics.
+ *
+ * This class is thread-safe with a lock for safety.  There is no risk of deadlock
+ * as this class only executes external one-way calls in Mediametrics and does not
+ * call any other AudioFlinger class.
+ *
+ * Terminology:
+ * An AudioInterval is a contiguous playback segment.
+ * An AudioIntervalGroup is a group of continuous playback segments on the same device.
+ *
+ * We currently deliver metrics based on an AudioIntervalGroup.
+ */
+class ThreadMetrics final {
+public:
+    ThreadMetrics(std::string metricsId, bool isOut)
+        : mMetricsId(std::move(metricsId))
+        , mIsOut(isOut)
+        {}
+
+    ~ThreadMetrics() {
+        logEndInterval(); // close any open interval groups
+        std::lock_guard l(mLock);
+        deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
+            .record();
+    }
+
+    // Called under the following circumstances
+    // 1) Upon a createPatch and we are not in standby
+    // 2) We come out of standby
+    void logBeginInterval() {
+        std::lock_guard l(mLock);
+        // The devices we look for change depend on whether the Thread is input or output.
+        const std::string& patchDevices = mIsOut ? mCreatePatchOutDevices : mCreatePatchInDevices;
+        if (mDevices != patchDevices) {
+            deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
+            mDevices = patchDevices; // set after endAudioIntervalGroup
+            resetIntervalGroupMetrics();
+            deliverDeviceMetrics(
+                    AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP, mDevices.c_str());
+        }
+        if (mIntervalStartTimeNs == 0) {
+            ++mIntervalCount;
+            mIntervalStartTimeNs = systemTime();
+        }
+    }
+
+    void logConstructor(pid_t pid, const char *threadType, int32_t id) const {
+        mediametrics::LogItem(mMetricsId)
+            .setPid(pid)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
+            .set(AMEDIAMETRICS_PROP_TYPE, threadType)
+            .set(AMEDIAMETRICS_PROP_THREADID, id)
+            .record();
+    }
+
+    void logCreatePatch(const std::string& inDevices, const std::string& outDevices) {
+        std::lock_guard l(mLock);
+        mCreatePatchInDevices = inDevices;
+        mCreatePatchOutDevices = outDevices;
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATEAUDIOPATCH)
+            .set(AMEDIAMETRICS_PROP_INPUTDEVICES, inDevices)
+            .set(AMEDIAMETRICS_PROP_OUTPUTDEVICES, outDevices)
+            .record();
+    }
+
+    // Called when we are removed from the Thread.
+    void logEndInterval() {
+        std::lock_guard l(mLock);
+        if (mIntervalStartTimeNs != 0) {
+            const int64_t elapsedTimeNs = systemTime() - mIntervalStartTimeNs;
+            mIntervalStartTimeNs = 0;
+            mCumulativeTimeNs += elapsedTimeNs;
+            mDeviceTimeNs += elapsedTimeNs;
+        }
+    }
+
+    void logThrottleMs(double throttleMs) const {
+        mediametrics::LogItem(mMetricsId)
+            // ms units always double
+            .set(AMEDIAMETRICS_PROP_THROTTLEMS, (double)throttleMs)
+            .record();
+    }
+
+    void logLatency(double latencyMs) {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_LATENCYMS, latencyMs)
+            .record();
+        std::lock_guard l(mLock);
+        mDeviceLatencyMs.add(latencyMs);
+    }
+
+    void logUnderrunFrames(size_t frames) {
+        std::lock_guard l(mLock);
+        if (mLastUnderrun == false && frames > 0) {
+            ++mUnderrunCount; // count non-continguous underrun sequences.
+        }
+        mLastUnderrun = (frames > 0);
+        mUnderrunFrames += frames;
+    }
+
+    const std::string& getMetricsId() const {
+        return mMetricsId;
+    }
+
+private:
+    // no lock required - all arguments and constants.
+    void deliverDeviceMetrics(const char *eventName, const char *devices) const {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, eventName)
+            .set(mIsOut ? AMEDIAMETRICS_PROP_OUTPUTDEVICES
+                   : AMEDIAMETRICS_PROP_INPUTDEVICES, devices)
+           .record();
+    }
+
+    void deliverCumulativeMetrics(const char *eventName) const REQUIRES(mLock) {
+        if (mIntervalCount > 0) {
+            mediametrics::LogItem item(mMetricsId);
+            item.set(AMEDIAMETRICS_PROP_CUMULATIVETIMENS, mCumulativeTimeNs)
+                .set(AMEDIAMETRICS_PROP_DEVICETIMENS, mDeviceTimeNs)
+                .set(AMEDIAMETRICS_PROP_EVENT, eventName)
+                .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
+            if (mDeviceLatencyMs.getN() > 0) {
+                item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean());
+            }
+            if (mUnderrunCount > 0) {
+                item.set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t)mUnderrunCount)
+                    .set(AMEDIAMETRICS_PROP_UNDERRUNFRAMES, (int64_t)mUnderrunFrames);
+            }
+            item.record();
+        }
+    }
+
+    void resetIntervalGroupMetrics() REQUIRES(mLock) {
+        // mDevices is not reset by clear
+
+        mIntervalCount = 0;
+        mIntervalStartTimeNs = 0;
+        // mCumulativeTimeNs is not reset by clear.
+        mDeviceTimeNs = 0;
+
+        mDeviceLatencyMs.reset();
+
+        mLastUnderrun = false;
+        mUnderrunCount = 0;
+        mUnderrunFrames = 0;
+    }
+
+    const std::string mMetricsId;
+    const bool        mIsOut;  // if true, than a playback track, otherwise used for record.
+
+    mutable           std::mutex mLock;
+
+    // Devices in the interval group.
+    std::string       mDevices GUARDED_BY(mLock); // last input or output devices based on mIsOut.
+    std::string       mCreatePatchInDevices GUARDED_BY(mLock);
+    std::string       mCreatePatchOutDevices GUARDED_BY(mLock);
+
+    // Number of intervals and playing time
+    int32_t           mIntervalCount GUARDED_BY(mLock) = 0;
+    int64_t           mIntervalStartTimeNs GUARDED_BY(mLock) = 0;
+    int64_t           mCumulativeTimeNs GUARDED_BY(mLock) = 0;
+    int64_t           mDeviceTimeNs GUARDED_BY(mLock) = 0;
+
+    // latency and startup for each interval.
+    audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
+
+    // underrun count and frames
+    bool              mLastUnderrun GUARDED_BY(mLock) = false; // checks consecutive underruns
+    int64_t           mUnderrunCount GUARDED_BY(mLock) = 0;    // number of consecutive underruns
+    int64_t           mUnderrunFrames GUARDED_BY(mLock) = 0;   // total estimated frames underrun
+};
+
+} // namespace android
+
+#endif // ANDROID_AUDIO_THREADMETRICS_H
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 039e4f7..2af27d8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -24,11 +24,14 @@
 #include <math.h>
 #include <fcntl.h>
 #include <memory>
+#include <sstream>
 #include <string>
 #include <linux/futex.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
 #include <cutils/properties.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioParameter.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/RecordBufferConverter.h>
@@ -39,6 +42,7 @@
 #include <private/media/AudioTrackShared.h>
 #include <private/android_filesystem_config.h>
 #include <audio_utils/Balance.h>
+#include <audio_utils/Metadata.h>
 #include <audio_utils/channels.h>
 #include <audio_utils/mono_blend.h>
 #include <audio_utils/primitives.h>
@@ -210,6 +214,34 @@
 
 // ----------------------------------------------------------------------------
 
+// TODO: move all toString helpers to audio.h
+// under  #ifdef __cplusplus #endif
+static std::string patchSinksToString(const struct audio_patch *patch)
+{
+    std::stringstream ss;
+    for (size_t i = 0; i < patch->num_sinks; ++i) {
+        if (i > 0) {
+            ss << "|";
+        }
+        ss << "(" << toString(patch->sinks[i].ext.device.type)
+            << ", " << patch->sinks[i].ext.device.address << ")";
+    }
+    return ss.str();
+}
+
+static std::string patchSourcesToString(const struct audio_patch *patch)
+{
+    std::stringstream ss;
+    for (size_t i = 0; i < patch->num_sources; ++i) {
+        if (i > 0) {
+            ss << "|";
+        }
+        ss << "(" << toString(patch->sources[i].ext.device.type)
+            << ", " << patch->sources[i].ext.device.address << ")";
+    }
+    return ss.str();
+}
+
 static pthread_once_t sFastTrackMultiplierOnce = PTHREAD_ONCE_INIT;
 
 static void sFastTrackMultiplierInit()
@@ -452,30 +484,35 @@
         return "RECORD";
     case OFFLOAD:
         return "OFFLOAD";
-    case MMAP:
-        return "MMAP";
+    case MMAP_PLAYBACK:
+        return "MMAP_PLAYBACK";
+    case MMAP_CAPTURE:
+        return "MMAP_CAPTURE";
     default:
         return "unknown";
     }
 }
 
 AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady)
+        type_t type, bool systemReady, bool isOut)
     :   Thread(false /*canCallJava*/),
         mType(type),
         mAudioFlinger(audioFlinger),
+        mThreadMetrics(std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(id),
+               isOut),
+        mIsOut(isOut),
         // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, mFormat, mBufferSize
         // are set by PlaybackThread::readOutputParameters_l() or
         // RecordThread::readInputParameters_l()
         //FIXME: mStandby should be true here. Is this some kind of hack?
-        mStandby(false), mOutDevice(outDevice), mInDevice(inDevice),
-        mPrevOutDevice(AUDIO_DEVICE_NONE), mPrevInDevice(AUDIO_DEVICE_NONE),
+        mStandby(false),
         mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
         // mName will be set by concrete (non-virtual) subclass
         mDeathRecipient(new PMDeathRecipient(this)),
         mSystemReady(systemReady),
         mSignalPending(false)
 {
+    mThreadMetrics.logConstructor(getpid(), threadTypeToString(type), id);
     memset(&mPatch, 0, sizeof(struct audio_patch));
 }
 
@@ -646,6 +683,18 @@
     return sendConfigEvent_l(configEvent);
 }
 
+status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+        const DeviceDescriptorBaseVector& outDevices)
+{
+    if (type() != RECORD) {
+        // The update out device operation is only for record thread.
+        return INVALID_OPERATION;
+    }
+    Mutex::Autolock _l(mLock);
+    sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
+    return sendConfigEvent_l(configEvent);
+}
+
 
 // post condition: mConfigEvents.isEmpty()
 void AudioFlinger::ThreadBase::processConfigEvents_l()
@@ -680,24 +729,29 @@
             }
         } break;
         case CFG_EVENT_CREATE_AUDIO_PATCH: {
-            const audio_devices_t oldDevice = getDevice();
+            const DeviceTypeSet oldDevices = getDeviceTypes();
             CreateAudioPatchConfigEventData *data =
                                             (CreateAudioPatchConfigEventData *)event->mData.get();
             event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
-            const audio_devices_t newDevice = getDevice();
-            mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
-                    (unsigned)oldDevice, toString(oldDevice).c_str(),
-                    (unsigned)newDevice, toString(newDevice).c_str());
+            const DeviceTypeSet newDevices = getDeviceTypes();
+            mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+                    dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+                    dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
         } break;
         case CFG_EVENT_RELEASE_AUDIO_PATCH: {
-            const audio_devices_t oldDevice = getDevice();
+            const DeviceTypeSet oldDevices = getDeviceTypes();
             ReleaseAudioPatchConfigEventData *data =
                                             (ReleaseAudioPatchConfigEventData *)event->mData.get();
             event->mStatus = releaseAudioPatch_l(data->mHandle);
-            const audio_devices_t newDevice = getDevice();
-            mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
-                    (unsigned)oldDevice, toString(oldDevice).c_str(),
-                    (unsigned)newDevice, toString(newDevice).c_str());
+            const DeviceTypeSet newDevices = getDeviceTypes();
+            mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+                    dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+                    dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
+        } break;
+        case CFG_EVENT_UPDATE_OUT_DEVICE: {
+            UpdateOutDevicesConfigEventData *data =
+                    (UpdateOutDevicesConfigEventData *)event->mData.get();
+            updateOutDevices(data->mOutDevices);
         } break;
         default:
             ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
@@ -840,8 +894,10 @@
         dprintf(fd, " none\n");
     }
     // Note: output device may be used by capture threads for effects such as AEC.
-    dprintf(fd, "  Output device: %#x (%s)\n", mOutDevice, toString(mOutDevice).c_str());
-    dprintf(fd, "  Input device: %#x (%s)\n", mInDevice, toString(mInDevice).c_str());
+    dprintf(fd, "  Output devices: %s (%s)\n",
+            dumpDeviceTypes(outDeviceTypes()).c_str(), toString(outDeviceTypes()).c_str());
+    dprintf(fd, "  Input device: %#x (%s)\n",
+            inDeviceType(), toString(inDeviceType()).c_str());
     dprintf(fd, "  Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
 
     // Dump timestamp statistics for the Thread types that support it.
@@ -913,8 +969,10 @@
         return String16("AudioIn");
     case OFFLOAD:
         return String16("AudioOffload");
-    case MMAP:
-        return String16("Mmap");
+    case MMAP_PLAYBACK:
+        return String16("MmapPlayback");
+    case MMAP_CAPTURE:
+        return String16("MmapCapture");
     default:
         ALOG_ASSERT(false);
         return String16("AudioUnknown");
@@ -1011,6 +1069,12 @@
     mPowerManager.clear();
 }
 
+void AudioFlinger::ThreadBase::updateOutDevices(
+        const DeviceDescriptorBaseVector& outDevices __unused)
+{
+    ALOGE("%s should only be called in RecordThread", __func__);
+}
+
 void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
 {
     sp<ThreadBase> thread = mThread.promote();
@@ -1120,32 +1184,26 @@
     }
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
-                                                            bool enabled,
-                                                            audio_session_t sessionId)
-{
-    Mutex::Autolock _l(mLock);
-    checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
-}
+void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+                                                           audio_session_t sessionId,
+                                                           bool threadLocked) {
+    if (!threadLocked) {
+        mLock.lock();
+    }
 
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
-                                                            bool enabled,
-                                                            audio_session_t sessionId)
-{
     if (mType != RECORD) {
         // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
         // another session. This gives the priority to well behaved effect control panels
         // and applications not using global effects.
         // Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
         // global effects
-        if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
+        if (!audio_is_global_session(sessionId)) {
             setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
         }
     }
 
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
-    if (chain != 0) {
-        chain->checkSuspendOnEffectEnabled(effect, enabled);
+    if (!threadLocked) {
+        mLock.unlock();
     }
 }
 
@@ -1153,8 +1211,9 @@
 status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
-    // No global effect sessions on record threads
-    if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+    // No global output effect sessions on record threads
+    if (sessionId == AUDIO_SESSION_OUTPUT_MIX
+            || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
         ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
                 desc->name, mThreadName);
         return BAD_VALUE;
@@ -1228,6 +1287,13 @@
                             " on output stage session", desc->name);
                     return BAD_VALUE;
                 }
+            } else if (sessionId == AUDIO_SESSION_DEVICE) {
+                // only post processing on output stage session
+                if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC) {
+                    ALOGW("checkEffectCompatibility_l(): non post processing effect %s not allowed"
+                            " on device session", desc->name);
+                    return BAD_VALUE;
+                }
             } else {
                 // no restriction on effects applied on non fast tracks
                 if ((hasAudioSession_l(sessionId) & ThreadBase::FAST_SESSION) == 0) {
@@ -1269,7 +1335,7 @@
             return BAD_VALUE;
         }
 #endif
-        if ((sessionId == AUDIO_SESSION_OUTPUT_STAGE) || (sessionId == AUDIO_SESSION_OUTPUT_MIX)) {
+        if (audio_is_global_session(sessionId)) {
             ALOGW("checkEffectCompatibility_l(): global effect %s on DUPLICATING"
                     " thread %s", desc->name, mThreadName);
             return BAD_VALUE;
@@ -1301,7 +1367,8 @@
         effect_descriptor_t *desc,
         int *enabled,
         status_t *status,
-        bool pinned)
+        bool pinned,
+        bool probe)
 {
     sp<EffectModule> effect;
     sp<EffectHandle> handle;
@@ -1323,7 +1390,7 @@
         Mutex::Autolock _l(mLock);
 
         lStatus = checkEffectCompatibility_l(desc, sessionId);
-        if (lStatus != NO_ERROR) {
+        if (probe || lStatus != NO_ERROR) {
             goto Exit;
         }
 
@@ -1345,14 +1412,15 @@
         if (effect == 0) {
             effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
             // create a new effect module if none present in the chain
-            lStatus = chain->createEffect_l(effect, this, desc, effectId, sessionId, pinned);
+            lStatus = chain->createEffect_l(effect, desc, effectId, sessionId, pinned);
             if (lStatus != NO_ERROR) {
                 goto Exit;
             }
             effectCreated = true;
 
-            effect->setDevice(mOutDevice);
-            effect->setDevice(mInDevice);
+            // FIXME: use vector of device and address when effect interface is ready.
+            effect->setDevices(outDeviceTypeAddrs());
+            effect->setInputDevice(inDeviceTypeAddr());
             effect->setMode(mAudioFlinger->getMode());
             effect->setAudioSource(mAudioSource);
         }
@@ -1368,7 +1436,7 @@
     }
 
 Exit:
-    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+    if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
         Mutex::Autolock _l(mLock);
         if (effectCreated) {
             chain->removeEffect_l(effect);
@@ -1390,9 +1458,12 @@
     sp<EffectModule> effect;
     {
         Mutex::Autolock _l(mLock);
-
-        effect = handle->effect().promote();
-        if (effect == 0) {
+        sp<EffectBase> effectBase = handle->effect().promote();
+        if (effectBase == nullptr) {
+            return;
+        }
+        effect = effectBase->asEffectModule();
+        if (effect == nullptr) {
             return;
         }
         // restore suspended effects if the disconnected handle was enabled and the last one.
@@ -1404,11 +1475,34 @@
     if (remove) {
         mAudioFlinger->updateOrphanEffectChains(effect);
         if (handle->enabled()) {
-            checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
+            effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
         }
     }
 }
 
+void AudioFlinger::ThreadBase::onEffectEnable(const sp<EffectModule>& effect) {
+    if (isOffloadOrMmap()) {
+        Mutex::Autolock _l(mLock);
+        broadcast_l();
+    }
+    if (!effect->isOffloadable()) {
+        if (mType == ThreadBase::OFFLOAD) {
+            PlaybackThread *t = (PlaybackThread *)this;
+            t->invalidateTracks(AUDIO_STREAM_MUSIC);
+        }
+        if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
+            mAudioFlinger->onNonOffloadableGlobalEffectEnable();
+        }
+    }
+}
+
+void AudioFlinger::ThreadBase::onEffectDisable() {
+    if (isOffloadOrMmap()) {
+        Mutex::Autolock _l(mLock);
+        broadcast_l();
+    }
+}
+
 sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
         int effectId)
 {
@@ -1468,8 +1562,8 @@
         return status;
     }
 
-    effect->setDevice(mOutDevice);
-    effect->setDevice(mInDevice);
+    effect->setDevices(outDeviceTypeAddrs());
+    effect->setInputDevice(inDeviceTypeAddr());
     effect->setMode(mAudioFlinger->getMode());
     effect->setAudioSource(mAudioSource);
 
@@ -1484,7 +1578,7 @@
         detachAuxEffect_l(effect->id());
     }
 
-    sp<EffectChain> chain = effect->chain().promote();
+    sp<EffectChain> chain = effect->callback()->chain().promote();
     if (chain != 0) {
         // remove effect chain if removing last effect
         if (chain->removeEffect_l(effect, release) == 0) {
@@ -1594,6 +1688,7 @@
 #ifdef TEE_SINK
     track->dumpTee(-1 /* fd */, "_REMOVE");
 #endif
+    track->logEndInterval(); // log to MediaMetrics
     return index;
 }
 
@@ -1690,7 +1785,7 @@
     mLastRecordedTimestampVerifierN = mTimestampVerifier.getN();
     mLastRecordedTimeNs = timeNs;
 
-    std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("audiothread"));
+    std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("audiothread"));
 
 #define MM_PREFIX "android.media.audiothread." // avoid cut-n-paste errors.
 
@@ -1702,8 +1797,8 @@
     item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
     item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
     item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
-    item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
-    item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+    item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes()).c_str());
+    item->setCString(MM_PREFIX "inDevice", toString(inDeviceType()).c_str());
 
     // thread statistics
     if (mIoJitterMs.getN() > 0) {
@@ -1734,10 +1829,9 @@
 AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
                                              AudioStreamOut* output,
                                              audio_io_handle_t id,
-                                             audio_devices_t device,
                                              type_t type,
                                              bool systemReady)
-    :   ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
+    :   ThreadBase(audioFlinger, id, type, systemReady, true /* isOut */),
         mNormalFrameCount(0), mSinkBuffer(NULL),
         mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
         mMixerBuffer(NULL),
@@ -1783,7 +1877,7 @@
     // and the mute set to false).
     mMasterVolume = audioFlinger->masterVolume_l();
     mMasterMute = audioFlinger->masterMute_l();
-    if (mOutput && mOutput->audioHwDev) {
+    if (mOutput->audioHwDev) {
         if (mOutput->audioHwDev->canSetMasterVolume()) {
             mMasterVolume = 1.0;
         }
@@ -1799,9 +1893,10 @@
 
     // TODO: We may also match on address as well as device type for
     // AUDIO_DEVICE_OUT_BUS, AUDIO_DEVICE_OUT_ALL_A2DP, AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-    if (type == MIXER || type == DIRECT) {
-        mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
-                "audio.timestamp.corrected_output_devices",
+    if (type == MIXER || type == DIRECT || type == OFFLOAD) {
+        // TODO: This property should be ensure that only contains one single device type.
+        mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+                "audio.timestamp.corrected_output_device",
                 (int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
                                        : AUDIO_DEVICE_NONE));
     }
@@ -1812,9 +1907,11 @@
         mStreamTypes[stream].volume = 0.0f;
         mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
     }
-    // Audio patch volume is always max
+    // Audio patch and call assistant volume are always max
     mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
     mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
+    mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
+    mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
 }
 
 AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -1829,6 +1926,16 @@
 
 void AudioFlinger::PlaybackThread::onFirstRef()
 {
+    if (mOutput == nullptr || mOutput->stream == nullptr) {
+        ALOGE("The stream is not open yet"); // This should not happen.
+    } else {
+        // setEventCallback will need a strong pointer as a parameter. Calling it
+        // here instead of constructor of PlaybackThread so that the onFirstRef
+        // callback would not be made on an incompletely constructed object.
+        if (mOutput->stream->setEventCallback(this) != OK) {
+            ALOGE("Failed to add event callback");
+        }
+    }
     run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
@@ -1909,6 +2016,7 @@
 
 void AudioFlinger::PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
 {
+    dprintf(fd, "  Master volume: %f\n", mMasterVolume);
     dprintf(fd, "  Master mute: %s\n", mMasterMute ? "on" : "off");
     if (mHapticChannelMask != AUDIO_CHANNEL_NONE) {
         dprintf(fd, "  Haptic channel mask: %#x (%s)\n", mHapticChannelMask,
@@ -1958,7 +2066,8 @@
         pid_t tid,
         uid_t uid,
         status_t *status,
-        audio_port_handle_t portId)
+        audio_port_handle_t portId,
+        const sp<media::IAudioTrackCallback>& callback)
 {
     size_t frameCount = *pFrameCount;
     size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2024,6 +2133,7 @@
         { // scope for mLock
             Mutex::Autolock _l(mLock);
             for (audio_session_t session : {
+                    AUDIO_SESSION_DEVICE,
                     AUDIO_SESSION_OUTPUT_STAGE,
                     AUDIO_SESSION_OUTPUT_MIX,
                     sessionId,
@@ -2079,9 +2189,9 @@
             // More than 2 channels does not require stronger alignment than stereo
             alignment <<= 1;
         }
-        if (((uintptr_t)sharedBuffer->pointer() & (alignment - 1)) != 0) {
+        if (((uintptr_t)sharedBuffer->unsecurePointer() & (alignment - 1)) != 0) {
             ALOGE("Invalid buffer alignment: address %p, channel count %u",
-                  sharedBuffer->pointer(), channelCount);
+                  sharedBuffer->unsecurePointer(), channelCount);
             lStatus = BAD_VALUE;
             goto Exit;
         }
@@ -2247,6 +2357,12 @@
             goto Exit;
         }
         mTracks.add(track);
+        {
+            Mutex::Autolock _atCbL(mAudioTrackCbLock);
+            if (callback.get() != nullptr) {
+                mAudioTrackCallbacks.emplace(callback);
+            }
+        }
 
         sp<EffectChain> chain = getEffectChain_l(sessionId);
         if (chain != 0) {
@@ -2440,6 +2556,7 @@
             chain->incActiveTrackCnt();
         }
 
+        track->logBeginInterval(patchSinksToString(&mPatch)); // log to MediaMetrics
         status = NO_ERROR;
     }
 
@@ -2549,6 +2666,29 @@
     mCallbackThread->setAsyncError();
 }
 
+void AudioFlinger::PlaybackThread::onCodecFormatChanged(
+        const std::basic_string<uint8_t>& metadataBs)
+{
+    std::thread([this, metadataBs]() {
+            audio_utils::metadata::Data metadata =
+                    audio_utils::metadata::dataFromByteString(metadataBs);
+            if (metadata.empty()) {
+                ALOGW("Can not transform the buffer to audio metadata, %s, %d",
+                      reinterpret_cast<char*>(const_cast<uint8_t*>(metadataBs.data())),
+                      (int)metadataBs.size());
+                return;
+            }
+
+            audio_utils::metadata::ByteString metaDataStr =
+                    audio_utils::metadata::byteStringFromData(metadata);
+            std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
+            Mutex::Autolock _l(mAudioTrackCbLock);
+            for (const auto& callback : mAudioTrackCallbacks) {
+                callback->onCodecFormatChanged(metadataVec);
+            }
+    }).detach();
+}
+
 void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
@@ -2609,7 +2749,7 @@
     LOG_ALWAYS_FATAL_IF(result != OK,
             "Error when retrieving output stream buffer size: %d", result);
     mFrameCount = mBufferSize / mFrameSize;
-    if (mFrameCount & 15) {
+    if ((mType == MIXER || mType == DUPLICATING) && (mFrameCount & 15)) {
         ALOGW("HAL output buffer size is %zu frames but AudioMixer requires multiples of 16 frames",
                 mFrameCount);
     }
@@ -2738,6 +2878,30 @@
         mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
             this/* srcThread */, this/* dstThread */);
     }
+
+    audio_output_flags_t flags = mOutput->flags;
+    mediametrics::LogItem item(mThreadMetrics.getMetricsId()); // TODO: method in ThreadMetrics?
+    item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
+        .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+        .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)mChannelCount)
+        .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mNormalFrameCount)
+        .set(AMEDIAMETRICS_PROP_FLAGS, toString(flags).c_str())
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELMASK,
+                (int32_t)mHapticChannelMask)
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELCOUNT,
+                (int32_t)mHapticChannelCount)
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_ENCODING,
+                formatToString(mHALFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_FRAMECOUNT,
+                (int32_t)mFrameCount) // sic - added HAL
+        ;
+    uint32_t latencyMs;
+    if (mOutput->stream->getLatency(&latencyMs) == NO_ERROR) {
+        item.set(AMEDIAMETRICS_PROP_PREFIX_HAL AMEDIAMETRICS_PROP_LATENCYMS, (double)latencyMs);
+    }
+    item.record();
 }
 
 void AudioFlinger::PlaybackThread::updateMetadata_l()
@@ -2891,7 +3055,11 @@
 {
     if (!mMasterMute) {
         char value[PROPERTY_VALUE_MAX];
-        if (mOutDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+        if (mOutDeviceTypeAddrs.empty()) {
+            ALOGD("ro.audio.silent is ignored since no output device is set");
+            return;
+        }
+        if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
             ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
             return;
         }
@@ -2953,9 +3121,11 @@
             ALOG_ASSERT(mCallbackThread != 0);
             mCallbackThread->setWriteBlocked(mWriteAckSequence);
         }
+        ATRACE_BEGIN("write");
         // FIXME We should have an implementation of timestamps for direct output threads.
         // They are used e.g for multichannel PCM playback over HDMI.
         bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
+        ATRACE_END();
 
         if (mUseAsyncWrite &&
                 ((bytesWritten < 0) || (bytesWritten == (ssize_t)mBytesRemaining))) {
@@ -2968,7 +3138,10 @@
 
     mNumWrites++;
     mInWrite = false;
-    mStandby = false;
+    if (mStandby) {
+        mThreadMetrics.logBeginInterval();
+        mStandby = false;
+    }
     return bytesWritten;
 }
 
@@ -3033,7 +3206,7 @@
     // make sure standby delay is not too short when connected to an A2DP sink to avoid
     // truncating audio when going to standby.
     mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs;
-    if ((mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) {
+    if (!Intersection(outDeviceTypes(),  getAudioDeviceOutAllA2dpSet()).empty()) {
         if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) {
             mStandbyDelayNs = kDefaultStandbyTimeInNsecs;
         }
@@ -3074,7 +3247,7 @@
     halOutBuffer = halInBuffer;
     effect_buffer_t *buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
     ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
-    if (session > AUDIO_SESSION_OUTPUT_MIX) {
+    if (!audio_is_global_session(session)) {
         // Only one effect chain can be present in direct output thread and it uses
         // the sink buffer as input
         if (mType != DIRECT) {
@@ -3114,8 +3287,11 @@
     chain->setThread(this);
     chain->setInBuffer(halInBuffer);
     chain->setOutBuffer(halOutBuffer);
-    // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
-    // chains list in order to be processed last as it contains output stage effects.
+    // Effect chain for session AUDIO_SESSION_DEVICE is inserted at end of effect
+    // chains list in order to be processed last as it contains output device effects.
+    // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted just before to apply post
+    // processing effects specific to an output stream before effects applied to all streams
+    // routed to a given device.
     // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
     // session AUDIO_SESSION_OUTPUT_STAGE to be processed
     // after track specific effects and before output stage.
@@ -3125,7 +3301,8 @@
     // chains list to be processed before output mix effects. Relative order between other
     // sessions is not important.
     static_assert(AUDIO_SESSION_OUTPUT_MIX == 0 &&
-            AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX,
+            AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX &&
+            AUDIO_SESSION_DEVICE < AUDIO_SESSION_OUTPUT_STAGE,
             "audio_session_t constants misdefined");
     size_t size = mEffectChains.size();
     size_t i = 0;
@@ -3281,8 +3458,8 @@
 
         // If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
         //
-        // Note: we access outDevice() outside of mLock.
-        if (isMsdDevice() && (outDevice() & AUDIO_DEVICE_OUT_BUS) != 0) {
+        // Note: we access outDeviceTypes() outside of mLock.
+        if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
             // Here, we try for the AF lock, but do not block on it as the latency
             // is more informational.
             if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
@@ -3503,8 +3680,9 @@
                     // This is where we go into standby
                     if (!mStandby) {
                         LOG_AUDIO_STATE();
+                        mThreadMetrics.logEndInterval();
+                        mStandby = true;
                     }
-                    mStandby = true;
                     sendStatistics(false /* force */);
                 }
 
@@ -3587,7 +3765,13 @@
 
                     // Tally underrun frames as we are inserting 0s here.
                     for (const auto& track : activeTracks) {
-                        if (track->mFillingUpStatus == Track::FS_ACTIVE) {
+                        if (track->mFillingUpStatus == Track::FS_ACTIVE
+                                && !track->isStopped()
+                                && !track->isPaused()
+                                && !track->isTerminated()) {
+                            ALOGV("%s: track(%d) %s underrun due to thread sleep of %zu frames",
+                                    __func__, track->id(), track->getTrackStateAsString(),
+                                    mNormalFrameCount);
                             track->mAudioTrackServerProxy->tallyUnderrunFrames(mNormalFrameCount);
                         }
                     }
@@ -3802,6 +3986,8 @@
 
                         const int32_t throttleMs = (int32_t)mHalfBufferMs - deltaMs;
                         if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) {
+                            mThreadMetrics.logThrottleMs((double)throttleMs);
+
                             usleep(throttleMs * 1000);
                             // notify of throttle start on verbose log
                             ALOGV_IF(mThreadThrottleEndMs == mThreadThrottleTimeMs,
@@ -3818,8 +4004,10 @@
                             if (diff > 0) {
                                 // notify of throttle end on debug log
                                 // but prevent spamming for bluetooth
-                                ALOGD_IF(!audio_is_a2dp_out_device(outDevice()) &&
-                                         !audio_is_hearing_aid_out_device(outDevice()),
+                                ALOGD_IF(!isSingleDeviceType(
+                                                 outDeviceTypes(), audio_is_a2dp_out_device) &&
+                                         !isSingleDeviceType(
+                                                 outDeviceTypes(), audio_is_hearing_aid_out_device),
                                         "mixer(%p) throttle end: throttle time(%u)", this, diff);
                                 mThreadThrottleEndMs = mThreadThrottleTimeMs;
                             }
@@ -4004,25 +4192,31 @@
 
     // store new device and send to effects
     audio_devices_t type = AUDIO_DEVICE_NONE;
+    AudioDeviceTypeAddrVector deviceTypeAddrs;
     for (unsigned int i = 0; i < patch->num_sinks; i++) {
+        LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+                            && !mOutput->audioHwDev->supportsAudioPatches(),
+                            "Enumerated device type(%#x) must not be used "
+                            "as it does not support audio patches",
+                            patch->sinks[i].ext.device.type);
         type |= patch->sinks[i].ext.device.type;
+        deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+                patch->sinks[i].ext.device.address));
     }
 
     audio_port_handle_t sinkPortId = patch->sinks[0].id;
 #ifdef ADD_BATTERY_DATA
     // when changing the audio output device, call addBatteryData to notify
     // the change
-    if (mOutDevice != type) {
+    if (outDeviceTypes() != deviceTypes) {
         uint32_t params = 0;
         // check whether speaker is on
-        if (type & AUDIO_DEVICE_OUT_SPEAKER) {
+        if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) > 0) {
             params |= IMediaPlayerService::kBatteryDataSpeakerOn;
         }
 
-        audio_devices_t deviceWithoutSpeaker
-            = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
         // check if any other device (except speaker) is on
-        if (type & deviceWithoutSpeaker) {
+        if (!isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_SPEAKER)) {
             params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
         }
 
@@ -4033,14 +4227,16 @@
 #endif
 
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(type);
+        mEffectChains[i]->setDevices_l(deviceTypeAddrs);
     }
 
-    // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
-    // the thread is created so that the first patch creation triggers an ioConfigChanged callback
-    bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
-    mOutDevice = type;
+    // mPatch.num_sinks is not set when the thread is created so that
+    // the first patch creation triggers an ioConfigChanged callback
+    bool configChanged = (mPatch.num_sinks == 0) ||
+                         (mPatch.sinks[0].id != sinkPortId);
     mPatch = *patch;
+    mOutDeviceTypeAddrs = deviceTypeAddrs;
+    checkSilentMode_l();
 
     if (mOutput->audioHwDev->supportsAudioPatches()) {
         sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4065,9 +4261,18 @@
         status = mOutput->stream->setParameters(param.toString());
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
+    const std::string patchSinksAsString = patchSinksToString(patch);
+
+    mThreadMetrics.logEndInterval();
+    mThreadMetrics.logCreatePatch(/* inDevices */ {}, patchSinksAsString);
+    mThreadMetrics.logBeginInterval();
+    // also dispatch to active AudioTracks for MediaMetrics
+    for (const auto &track : mActiveTracks) {
+        track->logEndInterval();
+        track->logBeginInterval(patchSinksAsString);
+    }
+
     if (configChanged) {
-        mPrevOutDevice = type;
-        mDeviceId = sinkPortId;
         sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
     }
     return status;
@@ -4091,7 +4296,8 @@
 {
     status_t status = NO_ERROR;
 
-    mOutDevice = AUDIO_DEVICE_NONE;
+    mPatch = audio_patch{};
+    mOutDeviceTypeAddrs.clear();
 
     if (mOutput->audioHwDev->supportsAudioPatches()) {
         sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4131,8 +4337,8 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-        audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
-    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady),
+        audio_io_handle_t id, bool systemReady, type_t type)
+    :   PlaybackThread(audioFlinger, output, id, type, systemReady),
         // mAudioMixer below
         // mFastMixer below
         mFastMixerFutex(0),
@@ -4142,7 +4348,7 @@
         // mNormalSink below
 {
     setMasterBalance(audioFlinger->getMasterBalance_l());
-    ALOGV("MixerThread() id=%d device=%#x type=%d", id, device, type);
+    ALOGV("MixerThread() id=%d type=%d", id, type);
     ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
             "mFrameCount=%zu, mNormalFrameCount=%zu",
             mSampleRate, mChannelMask, mChannelCount, mFormat, mFrameSize, mFrameCount,
@@ -4184,7 +4390,7 @@
         // scheduled reliably with CFS. However, the BT A2DP HAL is
         // bursty (does not pull at a regular rate) and so cannot operate with FastMixer.
         initFastMixer = mFrameCount < mNormalFrameCount
-                && (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) == 0;
+                && Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty();
         break;
     }
     ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
@@ -4607,20 +4813,24 @@
     // DeferredOperations handles statistics after setting mixerStatus.
     class DeferredOperations {
     public:
-        DeferredOperations(mixer_state *mixerStatus)
-            : mMixerStatus(mixerStatus) { }
+        DeferredOperations(mixer_state *mixerStatus, ThreadMetrics *threadMetrics)
+            : mMixerStatus(mixerStatus)
+            , mThreadMetrics(threadMetrics) {}
 
         // when leaving scope, tally frames properly.
         ~DeferredOperations() {
             // Tally underrun frames only if we are actually mixing (MIXER_TRACKS_READY)
             // because that is when the underrun occurs.
             // We do not distinguish between FastTracks and NormalTracks here.
-            if (*mMixerStatus == MIXER_TRACKS_READY) {
+            size_t maxUnderrunFrames = 0;
+            if (*mMixerStatus == MIXER_TRACKS_READY && mUnderrunFrames.size() > 0) {
                 for (const auto &underrun : mUnderrunFrames) {
-                    underrun.first->mAudioTrackServerProxy->tallyUnderrunFrames(
-                            underrun.second);
+                    underrun.first->tallyUnderrunFrames(underrun.second);
+                    maxUnderrunFrames = max(underrun.second, maxUnderrunFrames);
                 }
             }
+            // send the max underrun frames for this mixer period
+            mThreadMetrics->logUnderrunFrames(maxUnderrunFrames);
         }
 
         // tallyUnderrunFrames() is called to update the track counters
@@ -4632,8 +4842,10 @@
 
     private:
         const mixer_state * const mMixerStatus;
+        ThreadMetrics * const mThreadMetrics;
         std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
-    } deferredOperations(&mixerStatus); // implicit nested scope for variable capture
+    } deferredOperations(&mixerStatus, &mThreadMetrics);
+    // implicit nested scope for variable capture
 
     bool noFastHapticTrack = true;
     for (size_t i=0 ; i<count ; i++) {
@@ -5111,11 +5323,20 @@
                     mixerStatus != MIXER_TRACKS_ENABLED) {
                 mixerStatus = MIXER_TRACKS_READY;
             }
+
+            // Enable the next few lines to instrument a test for underrun log handling.
+            // TODO: Remove when we have a better way of testing the underrun log.
+#if 0
+            static int i;
+            if ((++i & 0xf) == 0) {
+                deferredOperations.tallyUnderrunFrames(track, 10 /* underrunFrames */);
+            }
+#endif
         } else {
             size_t underrunFrames = 0;
             if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
-                ALOGV("track(%d) underrun,  framesReady(%zu) < framesDesired(%zd)",
-                        trackId, framesReady, desiredFrames);
+                ALOGV("track(%d) underrun, track state %s  framesReady(%zu) < framesDesired(%zd)",
+                        trackId, track->getTrackStateAsString(), framesReady, desiredFrames);
                 underrunFrames = desiredFrames;
             }
             deferredOperations.tallyUnderrunFrames(track, underrunFrames);
@@ -5301,11 +5522,11 @@
         return false;
     }
     // Check validity as we don't call AudioMixer::create() here.
-    if (!AudioMixer::isValidFormat(format)) {
+    if (!mAudioMixer->isValidFormat(format)) {
         ALOGW("%s: invalid format: %#x", __func__, format);
         return false;
     }
-    if (!AudioMixer::isValidChannelMask(channelMask)) {
+    if (!mAudioMixer->isValidChannelMask(channelMask)) {
         ALOGW("%s: invalid channelMask: %#x", __func__, channelMask);
         return false;
     }
@@ -5355,46 +5576,17 @@
         }
     }
     if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-#ifdef ADD_BATTERY_DATA
-        // when changing the audio output device, call addBatteryData to notify
-        // the change
-        if (mOutDevice != value) {
-            uint32_t params = 0;
-            // check whether speaker is on
-            if (value & AUDIO_DEVICE_OUT_SPEAKER) {
-                params |= IMediaPlayerService::kBatteryDataSpeakerOn;
-            }
-
-            audio_devices_t deviceWithoutSpeaker
-                = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
-            // check if any other device (except speaker) is on
-            if (value & deviceWithoutSpeaker) {
-                params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
-            }
-
-            if (params != 0) {
-                addBatteryData(params);
-            }
-        }
-#endif
-
-        // forward device change to effects that have requested to be
-        // aware of attached audio device.
-        if (value != AUDIO_DEVICE_NONE) {
-            a2dpDeviceChanged =
-                    (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
-            mOutDevice = value;
-            for (size_t i = 0; i < mEffectChains.size(); i++) {
-                mEffectChains[i]->setDevice_l(mOutDevice);
-            }
-        }
+        LOG_FATAL("Should not set routing device in MixerThread");
     }
 
     if (status == NO_ERROR) {
         status = mOutput->stream->setParameters(keyValuePair);
         if (!mStandby && status == INVALID_OPERATION) {
             mOutput->standby();
-            mStandby = true;
+            if (!mStandby) {
+                mThreadMetrics.logEndInterval();
+                mStandby = true;
+            }
             mBytesWritten = 0;
             status = mOutput->stream->setParameters(keyValuePair);
         }
@@ -5488,9 +5680,8 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device,
-        ThreadBase::type_t type, bool systemReady)
-    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady)
+        AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady)
+    :   PlaybackThread(audioFlinger, output, id, type, systemReady)
 {
     setMasterBalance(audioFlinger->getMasterBalance_l());
 }
@@ -5658,10 +5849,17 @@
             minFrames = 1;
         }
 
-        if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() &&
+        const size_t framesReady = track->framesReady();
+        const int trackId = track->id();
+        if (ATRACE_ENABLED()) {
+            std::string traceName("nRdy");
+            traceName += std::to_string(trackId);
+            ATRACE_INT(traceName.c_str(), framesReady);
+        }
+        if ((framesReady >= minFrames) && track->isReady() && !track->isPaused() &&
                 !track->isStopping_2() && !track->isStopped())
         {
-            ALOGVV("track(%d) s=%08x [OK]", track->id(), cblk->mServer);
+            ALOGVV("track(%d) s=%08x [OK]", trackId, cblk->mServer);
 
             if (track->mFillingUpStatus == Track::FS_FILLED) {
                 track->mFillingUpStatus = Track::FS_ACTIVE;
@@ -5724,7 +5922,7 @@
                 int64_t framesWritten = mBytesWritten / mFrameSize;
                 if (mStandby || !last ||
                         track->presentationComplete(framesWritten, audioHALFrames) ||
-                        track->isPaused()) {
+                        track->isPaused() || mHwPaused) {
                     if (track->isStopping_2()) {
                         track->mState = TrackBase::STOPPED;
                     }
@@ -5738,7 +5936,7 @@
                 // fill a buffer, then remove it from active list.
                 // Only consider last track started for mixer state control
                 if (--(track->mRetryCount) <= 0) {
-                    ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", track->id());
+                    ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
                     tracksToRemove->add(track);
                     // indicate to client process that the track was disabled because of underrun;
                     // it will then automatically call start() when data is available
@@ -5746,7 +5944,7 @@
                 } else if (last) {
                     ALOGW("pause because of UNDERRUN, framesReady = %zu,"
                             "minFrames = %u, mFormat = %#x",
-                            track->framesReady(), minFrames, mFormat);
+                            framesReady, minFrames, mFormat);
                     mixerStatus = MIXER_TRACKS_ENABLED;
                     if (mHwSupportsPause && !mHwPaused && !mStandby) {
                         doHwPause = true;
@@ -5858,10 +6056,6 @@
     bool trackPaused = false;
     bool trackStopped = false;
 
-    if ((mType == DIRECT) && audio_is_linear_pcm(mFormat) && !usesHwAvSync()) {
-        return !mStandby;
-    }
-
     // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
     // after a timeout and we will enter standby then.
     if (mTracks.size() > 0) {
@@ -5885,16 +6079,7 @@
     AudioParameter param = AudioParameter(keyValuePair);
     int value;
     if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-        // forward device change to effects that have requested to be
-        // aware of attached audio device.
-        if (value != AUDIO_DEVICE_NONE) {
-            a2dpDeviceChanged =
-                    (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
-            mOutDevice = value;
-            for (size_t i = 0; i < mEffectChains.size(); i++) {
-                mEffectChains[i]->setDevice_l(mOutDevice);
-            }
-        }
+        LOG_FATAL("Should not set routing device in DirectOutputThread");
     }
     if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
         // do not accept frame count changes if tracks are open as the track buffer
@@ -5910,7 +6095,10 @@
         status = mOutput->stream->setParameters(keyValuePair);
         if (!mStandby && status == INVALID_OPERATION) {
             mOutput->standby();
-            mStandby = true;
+            if (!mStandby) {
+                mThreadMetrics.logEndInterval();
+                mStandby = true;
+            }
             mBytesWritten = 0;
             status = mOutput->stream->setParameters(keyValuePair);
         }
@@ -5978,6 +6166,7 @@
     mHwPaused = false;
     mFlushPending = false;
     mTimestampVerifier.discontinuity(); // DIRECT and OFFLOADED flush resets frame count.
+    mTimestamp.clear();
 }
 
 int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
@@ -6106,8 +6295,8 @@
 
 // ----------------------------------------------------------------------------
 AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
-    :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
+        AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
+    :   DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
         mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
         mOffloadUnderrunPosition(~0LL)
 {
@@ -6354,7 +6543,9 @@
             }
         }
         // compute volume for this track
-        processVolume_l(track, last);
+        if (track->isReady()) {  // check ready to prevent premature start.
+            processVolume_l(track, last);
+        }
     }
 
     // make sure the pause/flush/resume sequence is executed in the right order.
@@ -6430,7 +6621,7 @@
 
 AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
         AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
-    :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(),
+    :   MixerThread(audioFlinger, mainThread->getOutput(), id,
                     systemReady, DUPLICATING),
         mWaitTimeMs(UINT_MAX)
 {
@@ -6502,7 +6693,10 @@
 
         // TODO: Report correction for the other output tracks and show in the dump.
     }
-    mStandby = false;
+    if (mStandby) {
+        mThreadMetrics.logBeginInterval();
+        mStandby = false;
+    }
     return (ssize_t)mSinkBufferSize;
 }
 
@@ -6662,12 +6856,11 @@
 AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
                                          AudioStreamIn *input,
                                          audio_io_handle_t id,
-                                         audio_devices_t outDevice,
-                                         audio_devices_t inDevice,
                                          bool systemReady
                                          ) :
-    ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
+    ThreadBase(audioFlinger, id, RECORD, systemReady, false /* isOut */),
     mInput(input),
+    mSource(mInput),
     mActiveTracks(&this->mLocalLog),
     mRsmpInBuffer(NULL),
     // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
@@ -6697,8 +6890,9 @@
 
     // TODO: We may also match on address as well as device type for
     // AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_IN_REMOTE_SUBMIX
-    mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
-            "audio.timestamp.corrected_input_devices",
+    // TODO: This property should be ensure that only contains one single device type.
+    mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+            "audio.timestamp.corrected_input_device",
             (int64_t)(mIsMsdDevice ? AUDIO_DEVICE_IN_BUS // turn on by default for MSD
                                    : AUDIO_DEVICE_NONE));
 
@@ -6745,7 +6939,7 @@
         sp<IMemory> pipeMemory;
         if ((roHeap == 0) ||
                 (pipeMemory = roHeap->allocate(pipeSize)) == 0 ||
-                (pipeBuffer = pipeMemory->pointer()) == nullptr) {
+                (pipeBuffer = pipeMemory->unsecurePointer()) == nullptr) {
             ALOGE("not enough memory for pipe buffer size=%zu; "
                     "roHeap=%p, pipeMemory=%p, pipeBuffer=%p; roHeapSize: %lld",
                     pipeSize, roHeap.get(), pipeMemory.get(), pipeBuffer,
@@ -6954,7 +7148,10 @@
 
                 case TrackBase::STARTING_2:
                     doBroadcast = true;
-                    mStandby = false;
+                    if (mStandby) {
+                        mThreadMetrics.logBeginInterval();
+                        mStandby = false;
+                    }
                     activeTrack->mState = TrackBase::ACTIVE;
                     allStopped = false;
                     break;
@@ -7145,7 +7342,7 @@
         } else {
             ATRACE_BEGIN("read");
             size_t bytesRead;
-            status_t result = mInput->stream->read(
+            status_t result = mSource->read(
                     (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
             ATRACE_END();
             if (result < 0) {
@@ -7159,15 +7356,17 @@
 
         // Update server timestamp with server stats
         // systemTime() is optional if the hardware supports timestamps.
-        mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] += framesRead;
-        mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = lastIoEndNs;
+        if (framesRead >= 0) {
+            mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] += framesRead;
+            mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = lastIoEndNs;
+        }
 
         // Update server timestamp with kernel stats
         if (mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
             int64_t position, time;
             if (mStandby) {
                 mTimestampVerifier.discontinuity();
-            } else if (mInput->stream->getCapturePosition(&position, &time) == NO_ERROR
+            } else if (mSource->getCapturePosition(&position, &time) == NO_ERROR
                     && time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {
 
                 mTimestampVerifier.add(position, time, mSampleRate);
@@ -7418,6 +7617,7 @@
 {
     if (!mStandby) {
         inputStandBy();
+        mThreadMetrics.logEndInterval();
         mStandby = true;
     }
 }
@@ -7448,7 +7648,7 @@
             sq->end(false /*didModify*/);
         }
     }
-    status_t result = mInput->stream->standby();
+    status_t result = mSource->standby();
     ALOGE_IF(result != OK, "Error when putting input stream into standby: %d", result);
 
     // If going into standby, flush the pipe source.
@@ -7722,6 +7922,9 @@
             sendIoConfigEvent_l(
                 AUDIO_CLIENT_STARTED, recordTrack->creatorPid(), recordTrack->portId());
         }
+
+        recordTrack->logBeginInterval(patchSourcesToString(&mPatch)); // log to MediaMetrics
+
         // Catch up with current buffer indices if thread is already running.
         // This is what makes a new client discard all buffered data.  If the track's mRsmpInFront
         // was initialized to some value closer to the thread's mRsmpInFront, then the track could
@@ -7948,12 +8151,12 @@
     write(fd, result.string(), result.size());
 }
 
-void AudioFlinger::RecordThread::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mTracks.size() ; i++) {
         sp<RecordTrack> track = mTracks[i];
-        if (track != 0 && track->uid() == uid) {
+        if (track != 0 && track->portId() == portId) {
             track->setSilenced(silenced);
         }
     }
@@ -8067,7 +8270,7 @@
 {
     // disable AEC and NS if the device is a BT SCO headset supporting those
     // pre processings
-    bool suspend = audio_is_bluetooth_sco_device(mInDevice) &&
+    bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
                         mAudioFlinger->btNrecIsOff();
     if (mBtNrecSuspended.exchange(suspend) != suspend) {
         for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -8132,34 +8335,11 @@
         }
     }
     if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-        // forward device change to effects that have requested to be
-        // aware of attached audio device.
-        for (size_t i = 0; i < mEffectChains.size(); i++) {
-            mEffectChains[i]->setDevice_l(value);
-        }
-
-        // store input device and output device but do not forward output device to audio HAL.
-        // Note that status is ignored by the caller for output device
-        // (see AudioFlinger::setParameters()
-        if (audio_is_output_devices(value)) {
-            mOutDevice = value;
-            status = BAD_VALUE;
-        } else {
-            mInDevice = value;
-            if (value != AUDIO_DEVICE_NONE) {
-                mPrevInDevice = value;
-            }
-            checkBtNrec_l();
-        }
+        LOG_FATAL("Should not set routing device in RecordThread");
     }
     if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR &&
             mAudioSource != (audio_source_t)value) {
-        // forward device change to effects that have requested to be
-        // aware of attached audio device.
-        for (size_t i = 0; i < mEffectChains.size(); i++) {
-            mEffectChains[i]->setAudioSource_l((audio_source_t)value);
-        }
-        mAudioSource = (audio_source_t)value;
+        LOG_FATAL("Should not set audio source in RecordThread");
     }
 
     if (status == NO_ERROR) {
@@ -8246,13 +8426,14 @@
     }
     result = mInput->stream->getFrameSize(&mFrameSize);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving frame size from HAL: %d", result);
+    LOG_ALWAYS_FATAL_IF(mFrameSize <= 0, "Error frame size was %zu but must be greater than zero",
+            mFrameSize);
     result = mInput->stream->getBufferSize(&mBufferSize);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving buffer size from HAL: %d", result);
     mFrameCount = mBufferSize / mFrameSize;
-    ALOGV("%p RecordThread params: mChannelCount=%u, mFormat=%#x, mFrameSize=%lld, "
-            "mBufferSize=%lld, mFrameCount=%lld",
-            this, mChannelCount, mFormat, (long long)mFrameSize, (long long)mBufferSize,
-            (long long)mFrameCount);
+    ALOGV("%p RecordThread params: mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
+            "mBufferSize=%zu, mFrameCount=%zu",
+            this, mChannelCount, mFormat, mFrameSize, mBufferSize, mFrameCount);
     // This is the formula for calculating the temporary buffer size.
     // With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
     // 1 full output buffer, regardless of the alignment of the available input.
@@ -8281,6 +8462,17 @@
 
     // AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints.
     // But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks?
+
+    audio_input_flags_t flags = mInput->flags;
+    mediametrics::LogItem item(mThreadMetrics.getMetricsId());
+    item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
+        .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_FLAGS, toString(flags).c_str())
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+        .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)mChannelCount)
+        .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
+        .record();
 }
 
 uint32_t AudioFlinger::RecordThread::getInputFramesLost()
@@ -8361,11 +8553,11 @@
     status_t status = NO_ERROR;
 
     // store new device and send to effects
-    mInDevice = patch->sources[0].ext.device.type;
+    mInDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+    mInDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
     audio_port_handle_t deviceId = patch->sources[0].id;
-    mPatch = *patch;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(mInDevice);
+        mEffectChains[i]->setInputDevice_l(inDeviceTypeAddr());
     }
 
     checkBtNrec_l();
@@ -8404,12 +8596,20 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
+    if ((mPatch.num_sources == 0) || (mPatch.sources[0].id != deviceId)) {
         sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
-        mPrevInDevice = mInDevice;
-        mDeviceId = deviceId;
+        mPatch = *patch;
     }
 
+    const std::string pathSourcesAsString = patchSourcesToString(patch);
+    mThreadMetrics.logEndInterval();
+    mThreadMetrics.logCreatePatch(pathSourcesAsString, /* outDevices */ {});
+    mThreadMetrics.logBeginInterval();
+    // also dispatch to active AudioRecords
+    for (const auto &track : mActiveTracks) {
+        track->logEndInterval();
+        track->logBeginInterval(pathSourcesAsString);
+    }
     return status;
 }
 
@@ -8417,7 +8617,8 @@
 {
     status_t status = NO_ERROR;
 
-    mInDevice = AUDIO_DEVICE_NONE;
+    mPatch = audio_patch{};
+    mInDeviceTypeAddr.reset();
 
     if (mInput->audioHwDev->supportsAudioPatches()) {
         sp<DeviceHalInterface> hwDevice = mInput->audioHwDev->hwDevice();
@@ -8430,15 +8631,30 @@
     return status;
 }
 
+void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+{
+    mOutDevices = outDevices;
+    mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        mEffectChains[i]->setDevices_l(outDeviceTypeAddrs());
+    }
+}
+
 void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
     mTracks.add(record);
+    if (record->getSource()) {
+        mSource = record->getSource();
+    }
 }
 
 void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
+    if (mSource == record->getSource()) {
+        mSource = mInput;
+    }
     destroyTrack_l(record);
 }
 
@@ -8481,10 +8697,10 @@
 }
 
 status_t AudioFlinger::MmapThreadHandle::start(const AudioClient& client,
-        audio_port_handle_t *handle)
+        const audio_attributes_t *attr, audio_port_handle_t *handle)
 
 {
-    return mThread->start(client, handle);
+    return mThread->start(client, attr, handle);
 }
 
 status_t AudioFlinger::MmapThreadHandle::stop(audio_port_handle_t handle)
@@ -8500,9 +8716,8 @@
 
 AudioFlinger::MmapThread::MmapThread(
         const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
-        audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
-    : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
+        AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady, bool isOut)
+    : ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
       mSessionId(AUDIO_SESSION_NONE),
       mPortId(AUDIO_PORT_HANDLE_NONE),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
@@ -8585,11 +8800,15 @@
         ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
         return ret;
     }
-    mStandby = false;
+    if (mStandby) {
+        mThreadMetrics.logBeginInterval();
+        mStandby = false;
+    }
     return NO_ERROR;
 }
 
 status_t AudioFlinger::MmapThread::start(const AudioClient& client,
+                                         const audio_attributes_t *attr,
                                          audio_port_handle_t *handle)
 {
     ALOGV("%s clientUid %d mStandby %d mPortId %d *handle %d", __FUNCTION__,
@@ -8680,9 +8899,10 @@
     }
 
     // Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
-    sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
-                                        isOutput(), client.clientUid, client.clientPid,
-                                        IPCThreadState::self()->getCallingPid(), portId);
+    sp<MmapTrack> track = new MmapTrack(this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
+                                        mChannelMask, mSessionId, isOutput(), client.clientUid,
+                                        client.clientPid, IPCThreadState::self()->getCallingPid(),
+                                        portId);
 
     if (isOutput()) {
         // force volume update when a new track is added
@@ -8703,6 +8923,7 @@
         chain->incActiveTrackCnt();
     }
 
+    track->logBeginInterval(patchSinksToString(&mPatch)); // log to MediaMetrics
     *handle = portId;
     broadcast_l();
 
@@ -8771,7 +8992,10 @@
         return INVALID_OPERATION;
     }
     mHalStream->standby();
-    mStandby = true;
+    if (!mStandby) {
+        mThreadMetrics.logEndInterval();
+        mStandby = true;
+    }
     releaseWakeLock();
     return NO_ERROR;
 }
@@ -8785,9 +9009,32 @@
     LOG_ALWAYS_FATAL_IF(!audio_is_linear_pcm(mFormat), "HAL format %#x is not linear pcm", mFormat);
     result = mHalStream->getFrameSize(&mFrameSize);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving frame size from HAL: %d", result);
+    LOG_ALWAYS_FATAL_IF(mFrameSize <= 0, "Error frame size was %zu but must be greater than zero",
+            mFrameSize);
     result = mHalStream->getBufferSize(&mBufferSize);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving buffer size from HAL: %d", result);
     mFrameCount = mBufferSize / mFrameSize;
+
+    // TODO: make a readHalParameters call?
+    mediametrics::LogItem item(mThreadMetrics.getMetricsId());
+    item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
+        .set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+        .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+        .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)mChannelCount)
+        .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
+        /*
+        .set(AMEDIAMETRICS_PROP_FLAGS, toString(flags).c_str())
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELMASK,
+                (int32_t)mHapticChannelMask)
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELCOUNT,
+                (int32_t)mHapticChannelCount)
+        */
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_ENCODING,
+                formatToString(mHALFormat).c_str())
+        .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_FRAMECOUNT,
+                (int32_t)mFrameCount) // sic - added HAL
+        .record();
 }
 
 bool AudioFlinger::MmapThread::threadLoop()
@@ -8868,26 +9115,7 @@
     int value;
     bool sendToHal = true;
     if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-        audio_devices_t device = (audio_devices_t)value;
-        // forward device change to effects that have requested to be
-        // aware of attached audio device.
-        if (device != AUDIO_DEVICE_NONE) {
-            for (size_t i = 0; i < mEffectChains.size(); i++) {
-                mEffectChains[i]->setDevice_l(device);
-            }
-        }
-        if (audio_is_output_devices(device)) {
-            mOutDevice = device;
-            if (!isOutput()) {
-                sendToHal = false;
-            }
-        } else {
-            mInDevice = device;
-            if (device != AUDIO_DEVICE_NONE) {
-                mPrevInDevice = value;
-            }
-            // TODO: implement and call checkBtNrec_l();
-        }
+        LOG_FATAL("Should not happen set routing device in MmapThread");
     }
     if (sendToHal) {
         status = mHalStream->setParameters(keyValuePair);
@@ -8946,24 +9174,39 @@
     // store new device and send to effects
     audio_devices_t type = AUDIO_DEVICE_NONE;
     audio_port_handle_t deviceId;
+    AudioDeviceTypeAddrVector sinkDeviceTypeAddrs;
+    AudioDeviceTypeAddr sourceDeviceTypeAddr;
+    uint32_t numDevices = 0;
     if (isOutput()) {
         for (unsigned int i = 0; i < patch->num_sinks; i++) {
+            LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+                                && !mAudioHwDev->supportsAudioPatches(),
+                                "Enumerated device type(%#x) must not be used "
+                                "as it does not support audio patches",
+                                patch->sinks[i].ext.device.type);
             type |= patch->sinks[i].ext.device.type;
+            sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+                    patch->sinks[i].ext.device.address));
         }
         deviceId = patch->sinks[0].id;
+        numDevices = mPatch.num_sinks;
     } else {
         type = patch->sources[0].ext.device.type;
         deviceId = patch->sources[0].id;
+        numDevices = mPatch.num_sources;
+        sourceDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+        sourceDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
     }
 
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->setDevice_l(type);
+        if (isOutput()) {
+            mEffectChains[i]->setDevices_l(sinkDeviceTypeAddrs);
+        } else {
+            mEffectChains[i]->setInputDevice_l(sourceDeviceTypeAddr);
+        }
     }
 
-    if (isOutput()) {
-        mOutDevice = type;
-    } else {
-        mInDevice = type;
+    if (!isOutput()) {
         // store new source and send to effects
         if (mAudioSource != patch->sinks[0].ext.mix.usecase.source) {
             mAudioSource = patch->sinks[0].ext.mix.usecase.source;
@@ -9000,26 +9243,22 @@
         *handle = AUDIO_PATCH_HANDLE_NONE;
     }
 
-    if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
-        mPrevOutDevice = type;
-        sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+    if (numDevices == 0 || mDeviceId != deviceId) {
+        if (isOutput()) {
+            sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+            mOutDeviceTypeAddrs = sinkDeviceTypeAddrs;
+            checkSilentMode_l();
+        } else {
+            sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
+            mInDeviceTypeAddr = sourceDeviceTypeAddr;
+        }
         sp<MmapStreamCallback> callback = mCallback.promote();
         if (mDeviceId != deviceId && callback != 0) {
             mLock.unlock();
             callback->onRoutingChanged(deviceId);
             mLock.lock();
         }
-        mDeviceId = deviceId;
-    }
-    if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
-        mPrevInDevice = type;
-        sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
-        sp<MmapStreamCallback> callback = mCallback.promote();
-        if (mDeviceId != deviceId && callback != 0) {
-            mLock.unlock();
-            callback->onRoutingChanged(deviceId);
-            mLock.lock();
-        }
+        mPatch = *patch;
         mDeviceId = deviceId;
     }
     return status;
@@ -9029,7 +9268,9 @@
 {
     status_t status = NO_ERROR;
 
-    mInDevice = AUDIO_DEVICE_NONE;
+    mPatch = audio_patch{};
+    mOutDeviceTypeAddrs.clear();
+    mInDeviceTypeAddr.reset();
 
     bool supportsAudioPatches = mHalDevice->supportsAudioPatches(&supportsAudioPatches) == OK ?
                                         supportsAudioPatches : false;
@@ -9130,8 +9371,8 @@
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // No global effect sessions on mmap threads
-    if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
-        ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
+    if (audio_is_global_session(sessionId)) {
+        ALOGW("checkEffectCompatibility_l(): global effect %s on MMAP thread %s",
                 desc->name, mThreadName);
         return BAD_VALUE;
     }
@@ -9153,7 +9394,6 @@
     }
 
     return NO_ERROR;
-
 }
 
 void AudioFlinger::MmapThread::checkInvalidTracks_l()
@@ -9205,9 +9445,8 @@
 
 AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
         const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        AudioHwDevice *hwDev,  AudioStreamOut *output,
-        audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
-    : MmapThread(audioFlinger, id, hwDev, output->stream, outDevice, inDevice, systemReady),
+        AudioHwDevice *hwDev,  AudioStreamOut *output, bool systemReady)
+    : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady, true /* isOut */),
       mStreamType(AUDIO_STREAM_MUSIC),
       mStreamVolume(1.0),
       mStreamMute(false),
@@ -9417,9 +9656,8 @@
 
 AudioFlinger::MmapCaptureThread::MmapCaptureThread(
         const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-        AudioHwDevice *hwDev,  AudioStreamIn *input,
-        audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
-    : MmapThread(audioFlinger, id, hwDev, input->stream, outDevice, inDevice, systemReady),
+        AudioHwDevice *hwDev,  AudioStreamIn *input, bool systemReady)
+    : MmapThread(audioFlinger, id, hwDev, input->stream, systemReady, false /* isOut */),
       mInput(input)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioMmapIn_%X", id);
@@ -9491,11 +9729,11 @@
     mInput->stream->updateSinkMetadata(metadata);
 }
 
-void AudioFlinger::MmapCaptureThread::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mActiveTracks.size() ; i++) {
-        if (mActiveTracks[i]->uid() == uid) {
+        if (mActiveTracks[i]->portId() == portId) {
             mActiveTracks[i]->setSilenced_l(silenced);
             broadcast_l();
         }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 87bebf3..c1ac2e4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -30,15 +30,15 @@
         DUPLICATING,        // Thread class is DuplicatingThread
         RECORD,             // Thread class is RecordThread
         OFFLOAD,            // Thread class is OffloadThread
-        MMAP                // control thread for MMAP stream
+        MMAP_PLAYBACK,      // Thread class for MMAP playback stream
+        MMAP_CAPTURE,       // Thread class for MMAP capture stream
         // If you add any values here, also update ThreadBase::threadTypeToString()
     };
 
     static const char *threadTypeToString(type_t type);
 
     ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-                audio_devices_t outDevice, audio_devices_t inDevice, type_t type,
-                bool systemReady);
+               type_t type, bool systemReady, bool isOut);
     virtual             ~ThreadBase();
 
     virtual status_t    readyToRun();
@@ -52,6 +52,7 @@
         CFG_EVENT_SET_PARAMETER,
         CFG_EVENT_CREATE_AUDIO_PATCH,
         CFG_EVENT_RELEASE_AUDIO_PATCH,
+        CFG_EVENT_UPDATE_OUT_DEVICE,
     };
 
     class ConfigEventData: public RefBase {
@@ -219,6 +220,28 @@
         virtual ~ReleaseAudioPatchConfigEvent() {}
     };
 
+    class UpdateOutDevicesConfigEventData : public ConfigEventData {
+    public:
+        explicit UpdateOutDevicesConfigEventData(const DeviceDescriptorBaseVector& outDevices) :
+            mOutDevices(outDevices) {}
+
+        virtual void dump(char *buffer, size_t size) {
+            snprintf(buffer, size, "Devices: %s", android::toString(mOutDevices).c_str());
+        }
+
+        DeviceDescriptorBaseVector mOutDevices;
+    };
+
+    class UpdateOutDevicesConfigEvent : public ConfigEvent {
+    public:
+        explicit UpdateOutDevicesConfigEvent(const DeviceDescriptorBaseVector& outDevices) :
+            ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
+            mData = new UpdateOutDevicesConfigEventData(outDevices);
+        }
+
+        virtual ~UpdateOutDevicesConfigEvent();
+    };
+
     class PMDeathRecipient : public IBinder::DeathRecipient {
     public:
         explicit    PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -249,6 +272,8 @@
                 // Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects,
                 // and returns the [normal mix] buffer's frame count.
     virtual     size_t      frameCount() const = 0;
+    virtual     uint32_t    latency_l() const { return 0; }
+    virtual     void        setVolumeForOutput_l(float left __unused, float right __unused) const {}
 
                 // Return's the HAL's frame count i.e. fast mixer buffer size.
                 size_t      frameCountHAL() const { return mFrameCount; }
@@ -278,21 +303,46 @@
                 status_t    sendCreateAudioPatchConfigEvent(const struct audio_patch *patch,
                                                             audio_patch_handle_t *handle);
                 status_t    sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle);
+                status_t    sendUpdateOutDeviceConfigEvent(
+                                    const DeviceDescriptorBaseVector& outDevices);
                 void        processConfigEvents_l();
     virtual     void        cacheParameters_l() = 0;
     virtual     status_t    createAudioPatch_l(const struct audio_patch *patch,
                                                audio_patch_handle_t *handle) = 0;
     virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle) = 0;
+    virtual     void        updateOutDevices(const DeviceDescriptorBaseVector& outDevices);
     virtual     void        toAudioPortConfig(struct audio_port_config *config) = 0;
 
 
                 // see note at declaration of mStandby, mOutDevice and mInDevice
                 bool        standby() const { return mStandby; }
-                audio_devices_t outDevice() const { return mOutDevice; }
-                audio_devices_t inDevice() const { return mInDevice; }
-                audio_devices_t getDevice() const { return isOutput() ? mOutDevice : mInDevice; }
+                const DeviceTypeSet outDeviceTypes() const {
+                    return getAudioDeviceTypes(mOutDeviceTypeAddrs);
+                }
+                audio_devices_t inDeviceType() const { return mInDeviceTypeAddr.mType; }
+                DeviceTypeSet getDeviceTypes() const {
+                    return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+                }
 
-    virtual     bool        isOutput() const = 0;
+                const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const {
+                    return mOutDeviceTypeAddrs;
+                }
+                const AudioDeviceTypeAddr& inDeviceTypeAddr() const {
+                    return mInDeviceTypeAddr;
+                }
+
+                bool        isOutput() const { return mIsOut; }
+
+                bool        isOffloadOrMmap() const {
+                    switch (mType) {
+                    case OFFLOAD:
+                    case MMAP_PLAYBACK:
+                    case MMAP_CAPTURE:
+                        return true;
+                    default:
+                        return false;
+                    }
+                }
 
     virtual     sp<StreamHalInterface> stream() const = 0;
 
@@ -304,7 +354,8 @@
                                     effect_descriptor_t *desc,
                                     int *enabled,
                                     status_t *status /*non-NULL*/,
-                                    bool pinned);
+                                    bool pinned,
+                                    bool probe);
 
                 // return values for hasAudioSession (bit field)
                 enum effect_state {
@@ -388,14 +439,9 @@
 
                 // check if some effects must be suspended/restored when an effect is enabled
                 // or disabled
-                void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
-                                                 bool enabled,
-                                                 audio_session_t sessionId =
-                                                        AUDIO_SESSION_OUTPUT_MIX);
-                void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
-                                                   bool enabled,
-                                                   audio_session_t sessionId =
-                                                        AUDIO_SESSION_OUTPUT_MIX);
+                void checkSuspendOnEffectEnabled(bool enabled,
+                                                 audio_session_t sessionId,
+                                                 bool threadLocked);
 
                 virtual status_t    setSyncEvent(const sp<SyncEvent>& event) = 0;
                 virtual bool        isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
@@ -429,6 +475,9 @@
 
     mutable     Mutex                   mLock;
 
+                void onEffectEnable(const sp<EffectModule>& effect);
+                void onEffectDisable();
+
 protected:
 
                 // entry describing an effect being suspended in mSuspendedSessions keyed vector
@@ -487,6 +536,8 @@
                 Condition               mWaitWorkCV;
 
                 const sp<AudioFlinger>  mAudioFlinger;
+                ThreadMetrics           mThreadMetrics;
+                const bool              mIsOut;
 
                 // updated by PlaybackThread::readOutputParameters_l() or
                 // RecordThread::readInputParameters_l()
@@ -502,26 +553,21 @@
                                                            // HAL format if Fastmixer is used.
                 audio_format_t          mHALFormat;
                 size_t                  mBufferSize;       // HAL buffer size for read() or write()
-
+                AudioDeviceTypeAddrVector mOutDeviceTypeAddrs; // output device types and addresses
+                AudioDeviceTypeAddr       mInDeviceTypeAddr;   // input device type and address
                 Vector< sp<ConfigEvent> >     mConfigEvents;
                 Vector< sp<ConfigEvent> >     mPendingConfigEvents; // events awaiting system ready
 
                 // These fields are written and read by thread itself without lock or barrier,
-                // and read by other threads without lock or barrier via standby(), outDevice()
-                // and inDevice().
+                // and read by other threads without lock or barrier via standby(), outDeviceTypes()
+                // and inDeviceType().
                 // Because of the absence of a lock or barrier, any other thread that reads
                 // these fields must use the information in isolation, or be prepared to deal
                 // with possibility that it might be inconsistent with other information.
                 bool                    mStandby;     // Whether thread is currently in standby.
-                audio_devices_t         mOutDevice;   // output device
-                audio_devices_t         mInDevice;    // input device
-                audio_devices_t         mPrevOutDevice;   // previous output device
-                audio_devices_t         mPrevInDevice;    // previous input device
+
                 struct audio_patch      mPatch;
-                /**
-                 * @brief mDeviceId  current device port unique identifier
-                 */
-                audio_port_handle_t     mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
                 audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
@@ -544,7 +590,8 @@
                 ExtendedTimestamp       mTimestamp;
                 TimestampVerifier< // For timestamp statistics.
                         int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
-                audio_devices_t         mTimestampCorrectedDevices = AUDIO_DEVICE_NONE;
+                // Timestamp corrected device should be a single device.
+                audio_devices_t         mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
 
                 // ThreadLoop statistics per iteration.
                 int64_t                 mLastIoBeginNs = -1;
@@ -687,7 +734,7 @@
 
 // --- PlaybackThread ---
 class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
-    public VolumeInterface {
+                       public VolumeInterface, public StreamOutHalInterfaceEventCallback {
 public:
 
 #include "PlaybackTracks.h"
@@ -719,7 +766,7 @@
     static const nsecs_t kMaxNextBufferDelayNs = 100000000;
 
     PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
+                   audio_io_handle_t id, type_t type, bool systemReady);
     virtual             ~PlaybackThread();
 
     // Thread virtuals
@@ -763,6 +810,10 @@
     virtual     void        onAddNewTrack_l();
                 void        onAsyncError(); // error reported by AsyncCallbackThread
 
+    // StreamHalInterfaceCodecFormatCallback implementation
+                void        onCodecFormatChanged(
+                                const std::basic_string<uint8_t>& metadataBs) override;
+
     // ThreadBase virtuals
     virtual     void        preExit();
 
@@ -782,7 +833,7 @@
                 // return estimated latency in milliseconds, as reported by HAL
                 uint32_t    latency() const;
                 // same, but lock must already be held
-                uint32_t    latency_l() const;
+                uint32_t    latency_l() const override;
 
                 // VolumeInterface
     virtual     void        setMasterVolume(float value);
@@ -792,7 +843,7 @@
     virtual     void        setStreamMute(audio_stream_type_t stream, bool muted);
     virtual     float       streamVolume(audio_stream_type_t stream) const;
 
-                void        setVolumeForOutput_l(float left, float right) const;
+                void        setVolumeForOutput_l(float left, float right) const override;
 
                 sp<Track>   createTrack_l(
                                 const sp<AudioFlinger::Client>& client,
@@ -812,7 +863,8 @@
                                 pid_t tid,
                                 uid_t uid,
                                 status_t *status /*non-NULL*/,
-                                audio_port_handle_t portId);
+                                audio_port_handle_t portId,
+                                const sp<media::IAudioTrackCallback>& callback);
 
                 AudioStreamOut* getOutput() const;
                 AudioStreamOut* clearOutput();
@@ -872,9 +924,6 @@
 
                 // Return the asynchronous signal wait time.
     virtual     int64_t     computeWaitTimeNs_l() const { return INT64_MAX; }
-
-    virtual     bool        isOutput() const override { return true; }
-
                 // returns true if the track is allowed to be added to the thread.
     virtual     bool        isTrackAllowed_l(
                                     audio_channel_mask_t channelMask __unused,
@@ -886,10 +935,10 @@
                             }
 
                 bool        isTimestampCorrectionEnabled() const override {
-                                const audio_devices_t device =
-                                        mOutDevice & mTimestampCorrectedDevices;
-                                return audio_is_output_devices(device) && popcount(device) > 0;
+                                return audio_is_output_devices(mTimestampCorrectedDevice)
+                                        && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
                             }
+
 protected:
     // updated by readOutputParameters_l()
     size_t                          mNormalFrameCount;  // normal mixer and effects
@@ -1135,6 +1184,10 @@
     uint32_t                        mDrainSequence;
     sp<AsyncCallbackThread>         mCallbackThread;
 
+    Mutex                                    mAudioTrackCbLock;
+    // Record of IAudioTrackCallback
+    std::set<sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+
 private:
     // The HAL output sink is treated as non-blocking, but current implementation is blocking
     sp<NBAIO_Sink>          mOutputSink;
@@ -1171,7 +1224,6 @@
     MixerThread(const sp<AudioFlinger>& audioFlinger,
                 AudioStreamOut* output,
                 audio_io_handle_t id,
-                audio_devices_t device,
                 bool systemReady,
                 type_t type = MIXER);
     virtual             ~MixerThread();
@@ -1269,8 +1321,8 @@
 public:
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                       audio_io_handle_t id, audio_devices_t device, bool systemReady)
-        : DirectOutputThread(audioFlinger, output, id, device, DIRECT, systemReady) { }
+                       audio_io_handle_t id, bool systemReady)
+        : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady) { }
 
     virtual                 ~DirectOutputThread();
 
@@ -1305,8 +1357,7 @@
     bool mVolumeShaperActive = false;
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                        audio_io_handle_t id, audio_devices_t device, ThreadBase::type_t type,
-                        bool systemReady);
+                       audio_io_handle_t id, ThreadBase::type_t type, bool systemReady);
     void processVolume_l(Track *track, bool lastTrack);
 
     // prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -1345,7 +1396,7 @@
 public:
 
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                        audio_io_handle_t id, uint32_t device, bool systemReady);
+                  audio_io_handle_t id, bool systemReady);
     virtual                 ~OffloadThread() {};
     virtual     void        flushHw_l();
 
@@ -1516,8 +1567,6 @@
             RecordThread(const sp<AudioFlinger>& audioFlinger,
                     AudioStreamIn *input,
                     audio_io_handle_t id,
-                    audio_devices_t outDevice,
-                    audio_devices_t inDevice,
                     bool systemReady
                     );
             virtual     ~RecordThread();
@@ -1577,6 +1626,7 @@
     virtual status_t    createAudioPatch_l(const struct audio_patch *patch,
                                            audio_patch_handle_t *handle);
     virtual status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);
+            void        updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
 
             void        addPatchTrack(const sp<PatchRecord>& record);
             void        deletePatchTrack(const sp<PatchRecord>& record);
@@ -1611,12 +1661,11 @@
                             ThreadBase::acquireWakeLock_l();
                             mActiveTracks.updatePowerState(this, true /* force */);
                         }
-    virtual bool        isOutput() const override { return false; }
 
             void        checkBtNrec();
 
             // Sets the UID records silence
-            void        setRecordSilenced(uid_t uid, bool silenced);
+            void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
 
             status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
 
@@ -1629,8 +1678,8 @@
 
             bool        isTimestampCorrectionEnabled() const override {
                             // checks popcount for exactly one device.
-                            return audio_is_input_device(
-                                    mInDevice & mTimestampCorrectedDevices);
+                            return audio_is_input_device(mTimestampCorrectedDevice)
+                                    && inDeviceType() == mTimestampCorrectedDevice;
                         }
 
 protected:
@@ -1647,6 +1696,7 @@
             void    checkBtNrec_l();
 
             AudioStreamIn                       *mInput;
+            Source                              *mSource;
             SortedVector < sp<RecordTrack> >    mTracks;
             // mActiveTracks has dual roles:  it indicates the current active track(s), and
             // is used together with mStartStopCond to indicate start()/stop() progress
@@ -1708,6 +1758,8 @@
             std::atomic_bool                    mBtNrecSuspended;
 
             int64_t                             mFramesRead = 0;    // continuous running counter.
+
+            DeviceDescriptorBaseVector          mOutDevices;
 };
 
 class MmapThread : public ThreadBase
@@ -1717,8 +1769,8 @@
 #include "MmapTracks.h"
 
     MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-                      AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
-                      audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+               AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady,
+               bool isOut);
     virtual     ~MmapThread();
 
     virtual     void        configure(const audio_attributes_t *attr,
@@ -1734,7 +1786,9 @@
     status_t createMmapBuffer(int32_t minSizeFrames,
                                       struct audio_mmap_buffer_info *info);
     status_t getMmapPosition(struct audio_mmap_position *position);
-    status_t start(const AudioClient& client, audio_port_handle_t *handle);
+    status_t start(const AudioClient& client,
+                   const audio_attributes_t *attr,
+                   audio_port_handle_t *handle);
     status_t stop(audio_port_handle_t handle);
     status_t standby();
 
@@ -1785,12 +1839,18 @@
     virtual     void        invalidateTracks(audio_stream_type_t streamType __unused) {}
 
                 // Sets the UID records silence
-    virtual     void        setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}
+    virtual     void        setRecordSilenced(audio_port_handle_t portId __unused,
+                                              bool silenced __unused) {}
 
  protected:
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
                 void        dumpTracks_l(int fd, const Vector<String16>& args) override;
 
+                /**
+                 * @brief mDeviceId  current device port unique identifier
+                 */
+                audio_port_handle_t     mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
                 audio_attributes_t      mAttr;
                 audio_session_t         mSessionId;
                 audio_port_handle_t     mPortId;
@@ -1811,8 +1871,7 @@
 
 public:
     MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-                      AudioHwDevice *hwDev, AudioStreamOut *output,
-                      audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+                       AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady);
     virtual     ~MmapPlaybackThread() {}
 
     virtual     void        configure(const audio_attributes_t *attr,
@@ -1839,8 +1898,6 @@
     virtual     void        checkSilentMode_l();
                 void        processVolume_l() override;
 
-    virtual     bool        isOutput() const override { return true; }
-
                 void        updateMetadata_l() override;
 
     virtual     void        toAudioPortConfig(struct audio_port_config *config);
@@ -1861,18 +1918,17 @@
 
 public:
     MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
-                      AudioHwDevice *hwDev, AudioStreamIn *input,
-                      audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+                      AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady);
     virtual     ~MmapCaptureThread() {}
 
                 AudioStreamIn* clearInput();
 
                 status_t       exitStandby() override;
-    virtual     bool           isOutput() const override { return false; }
 
                 void           updateMetadata_l() override;
                 void           processVolume_l() override;
-                void           setRecordSilenced(uid_t uid, bool silenced) override;
+                void           setRecordSilenced(audio_port_handle_t portId,
+                                                 bool silenced) override;
 
     virtual     void           toAudioPortConfig(struct audio_port_config *config);
 
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 65589e2..01d5345 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -69,7 +69,8 @@
                                 bool isOut,
                                 alloc_type alloc = ALLOC_CBLK,
                                 track_type type = TYPE_DEFAULT,
-                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+                                std::string metricsId = {});
     virtual             ~TrackBase();
     virtual status_t    initCheck() const;
 
@@ -94,7 +95,11 @@
             bool        isPatchTrack() const { return (mType == TYPE_PATCH); }
             bool        isExternalTrack() const { return !isOutputTrack() && !isPatchTrack(); }
 
-    virtual void        invalidate() { mIsInvalid = true; }
+    virtual void        invalidate() {
+                            if (mIsInvalid) return;
+                            mTrackMetrics.logInvalidate();
+                            mIsInvalid = true;
+                        }
             bool        isInvalid() const { return mIsInvalid; }
 
             void        terminate() { mTerminated = true; }
@@ -202,9 +207,65 @@
            audio_format_t format() const { return mFormat; }
            int id() const { return mId; }
 
+    const char *getTrackStateAsString() const {
+        if (isTerminated()) {
+            return "TERMINATED";
+        }
+        switch (mState) {
+        case IDLE:
+            return "IDLE";
+        case STOPPING_1: // for Fast and Offload
+            return "STOPPING_1";
+        case STOPPING_2: // for Fast and Offload
+            return "STOPPING_2";
+        case STOPPED:
+            return "STOPPED";
+        case RESUMING:
+            return "RESUMING";
+        case ACTIVE:
+            return "ACTIVE";
+        case PAUSING:
+            return "PAUSING";
+        case PAUSED:
+            return "PAUSED";
+        case FLUSHED:
+            return "FLUSHED";
+        case STARTING_1: // for RecordTrack
+            return "STARTING_1";
+        case STARTING_2: // for RecordTrack
+            return "STARTING_2";
+        default:
+            return "UNKNOWN";
+        }
+    }
+
+    // Called by the PlaybackThread to indicate that the track is becoming active
+    // and a new interval should start with a given device list.
+    void logBeginInterval(const std::string& devices) {
+        mTrackMetrics.logBeginInterval(devices);
+    }
+
+    // Called by the PlaybackThread to indicate the track is no longer active.
+    void logEndInterval() {
+        mTrackMetrics.logEndInterval();
+    }
+
+    // Called to tally underrun frames in playback.
+    virtual void tallyUnderrunFrames(size_t /* frames */) {}
+
 protected:
     DISALLOW_COPY_AND_ASSIGN(TrackBase);
 
+    void releaseCblk() {
+        if (mCblk != nullptr) {
+            mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
+            if (mClient == 0) {
+                free(mCblk);
+            }
+            mCblk = nullptr;
+        }
+    }
+
     // AudioBufferProvider interface
     virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
     virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -238,7 +299,7 @@
 
     // Upper case characters are final states.
     // Lower case characters are transitory.
-    const char *getTrackStateString() const {
+    const char *getTrackStateAsCodedString() const {
         if (isTerminated()) {
             return "T ";
         }
@@ -311,6 +372,19 @@
     audio_port_handle_t mPortId; // unique ID for this track used by audio policy
     bool                mIsInvalid; // non-resettable latch, set by invalidate()
 
+    // It typically takes 5 threadloop mix iterations for latency to stabilize.
+    // However, this can be 12+ iterations for BT.
+    // To be sure, we wait for latency to dip (it usually increases at the start)
+    // to assess stability and then log to MediaMetrics.
+    // Rapid start / pause calls may cause inaccurate numbers.
+    static inline constexpr int32_t LOG_START_COUNTDOWN = 12;
+    int32_t             mLogStartCountdown = 0; // Mixer period countdown
+    int64_t             mLogStartTimeNs = 0;    // Monotonic time at start()
+    int64_t             mLogStartFrames = 0;    // Timestamp frames at start()
+    double              mLogLatencyMs = 0.;     // Track the last log latency
+
+    TrackMetrics        mTrackMetrics;
+
     bool                mServerLatencySupported = false;
     std::atomic<bool>   mServerLatencyFromTrack{}; // latency from track or server timestamp.
     std::atomic<double> mServerLatencyMs{};        // last latency pushed from server thread.
@@ -327,6 +401,7 @@
 
     virtual ~PatchProxyBufferProvider() {}
 
+    virtual bool        producesBufferOnDemand() const = 0;
     virtual status_t    obtainBuffer(Proxy::Buffer* buffer,
                                      const struct timespec *requested = NULL) = 0;
     virtual void        releaseBuffer(Proxy::Buffer* buffer) = 0;
@@ -349,6 +424,8 @@
                             mPeerProxy = nullptr;
                         }
 
+            bool        producesBufferOnDemand() const override { return false; }
+
 protected:
     const sp<ClientProxy>       mProxy;
     sp<RefBase>                 mPeerReferenceHold;   // keeps mPeerProxy alive during access.
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
new file mode 100644
index 0000000..af16448
--- /dev/null
+++ b/services/audioflinger/TrackMetrics.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_TRACKMETRICS_H
+#define ANDROID_AUDIO_TRACKMETRICS_H
+
+#include <mutex>
+
+namespace android {
+
+/**
+ * TrackMetrics handles the AudioFlinger track metrics.
+ *
+ * We aggregate metrics for a particular device for proper analysis.
+ * This includes power, performance, and usage metrics.
+ *
+ * This class is thread-safe with a lock for safety.  There is no risk of deadlock
+ * as this class only executes external one-way calls in Mediametrics and does not
+ * call any other AudioFlinger class.
+ *
+ * Terminology:
+ * An AudioInterval is a contiguous playback segment.
+ * An AudioIntervalGroup is a group of continuous playback segments on the same device.
+ *
+ * We currently deliver metrics based on an AudioIntervalGroup.
+ */
+class TrackMetrics final {
+public:
+    TrackMetrics(std::string metricsId, bool isOut)
+        : mMetricsId(std::move(metricsId))
+        , mIsOut(isOut)
+        {}  // we don't log a constructor item, we wait for more info in logConstructor().
+
+    ~TrackMetrics() {
+        logEndInterval();
+        std::lock_guard l(mLock);
+        deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
+        // we don't log a destructor item here.
+    }
+
+    // Called under the following circumstances
+    // 1) when we are added to the Thread
+    // 2) when we have a createPatch in the Thread.
+    void logBeginInterval(const std::string& devices) {
+        std::lock_guard l(mLock);
+        if (mDevices != devices) {
+            deliverCumulativeMetrics(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP);
+            mDevices = devices;
+            resetIntervalGroupMetrics();
+            deliverDeviceMetrics(
+                    AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP, devices.c_str());
+        }
+        ++mIntervalCount;
+        mIntervalStartTimeNs = systemTime();
+    }
+
+    void logConstructor(pid_t creatorPid, uid_t creatorUid,
+            const std::string& traits = {},
+            audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT) const {
+        // Once this item is logged by the server, the client can add properties.
+        // no lock required, all local or const variables.
+        mediametrics::LogItem item(mMetricsId);
+        item.setPid(creatorPid)
+            .setUid(creatorUid)
+            .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)creatorUid)
+            .set(AMEDIAMETRICS_PROP_EVENT,
+                    AMEDIAMETRICS_PROP_PREFIX_SERVER AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
+            .set(AMEDIAMETRICS_PROP_TRAITS, traits);
+        // log streamType from the service, since client doesn't know chosen streamType.
+        if (streamType != AUDIO_STREAM_DEFAULT) {
+            item.set(AMEDIAMETRICS_PROP_STREAMTYPE, toString(streamType).c_str());
+        }
+        item.record();
+    }
+
+    // Called when we are removed from the Thread.
+    void logEndInterval() {
+        std::lock_guard l(mLock);
+        if (mIntervalStartTimeNs != 0) {
+            const int64_t elapsedTimeNs = systemTime() - mIntervalStartTimeNs;
+            mIntervalStartTimeNs = 0;
+            mCumulativeTimeNs += elapsedTimeNs;
+            mDeviceTimeNs += elapsedTimeNs;
+        }
+    }
+
+    void logInvalidate() const {
+        // no lock required, all local or const variables.
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT,
+                 AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE)
+            .record();
+    }
+
+    void logLatencyAndStartup(double latencyMs, double startupMs) {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_LATENCYMS, latencyMs)
+            .set(AMEDIAMETRICS_PROP_STARTUPMS, startupMs)
+            .record();
+        std::lock_guard l(mLock);
+        mDeviceLatencyMs.add(latencyMs);
+        mDeviceStartupMs.add(startupMs);
+    }
+
+    // may be called multiple times during an interval
+    void logVolume(float volume) {
+        const int64_t timeNs = systemTime();
+        std::lock_guard l(mLock);
+        if (mStartVolumeTimeNs == 0) {
+            mDeviceVolume = mVolume = volume;
+            mLastVolumeChangeTimeNs = mStartVolumeTimeNs = timeNs;
+            return;
+        }
+        mDeviceVolume = (mDeviceVolume * (mLastVolumeChangeTimeNs - mStartVolumeTimeNs) +
+            mVolume * (timeNs - mLastVolumeChangeTimeNs)) / (timeNs - mStartVolumeTimeNs);
+        mVolume = volume;
+        mLastVolumeChangeTimeNs = timeNs;
+    }
+
+    // Use absolute numbers returned by AudioTrackShared.
+    void logUnderruns(size_t count, size_t frames) {
+        std::lock_guard l(mLock);
+        mUnderrunCount = count;
+        mUnderrunFrames = frames;
+        // Consider delivering a message here (also be aware of excessive spam).
+    }
+
+private:
+    // no lock required - all arguments and constants.
+    void deliverDeviceMetrics(const char *eventName, const char *devices) const {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, eventName)
+            .set(mIsOut ? AMEDIAMETRICS_PROP_OUTPUTDEVICES
+                   : AMEDIAMETRICS_PROP_INPUTDEVICES, devices)
+           .record();
+    }
+
+    void deliverCumulativeMetrics(const char *eventName) const REQUIRES(mLock) {
+        if (mIntervalCount > 0) {
+            mediametrics::LogItem item(mMetricsId);
+            item.set(AMEDIAMETRICS_PROP_CUMULATIVETIMENS, mCumulativeTimeNs)
+                .set(AMEDIAMETRICS_PROP_DEVICETIMENS, mDeviceTimeNs)
+                .set(AMEDIAMETRICS_PROP_EVENT, eventName)
+                .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
+            if (mIsOut) {
+                item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume);
+            }
+            if (mDeviceLatencyMs.getN() > 0) {
+                item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean())
+                    .set(AMEDIAMETRICS_PROP_DEVICESTARTUPMS, mDeviceStartupMs.getMean());
+            }
+            if (mUnderrunCount > 0) {
+                item.set(AMEDIAMETRICS_PROP_UNDERRUN,
+                        (int32_t)(mUnderrunCount - mUnderrunCountSinceIntervalGroup))
+                    .set(AMEDIAMETRICS_PROP_UNDERRUNFRAMES,
+                        (int64_t)(mUnderrunFrames - mUnderrunFramesSinceIntervalGroup));
+            }
+            item.record();
+        }
+    }
+
+    void resetIntervalGroupMetrics() REQUIRES(mLock) {
+        // mDevices is not reset by resetIntervalGroupMetrics.
+
+        mIntervalCount = 0;
+        mIntervalStartTimeNs = 0;
+        // mCumulativeTimeNs is not reset by resetIntervalGroupMetrics.
+        mDeviceTimeNs = 0;
+
+        mVolume = 0.f;
+        mDeviceVolume = 0.f;
+        mStartVolumeTimeNs = 0;
+        mLastVolumeChangeTimeNs = 0;
+
+        mDeviceLatencyMs.reset();
+        mDeviceStartupMs.reset();
+
+        mUnderrunCountSinceIntervalGroup = mUnderrunCount;
+        mUnderrunFramesSinceIntervalGroup = mUnderrunFrames;
+        // do not reset mUnderrunCount - it keeps continuously running for tracks.
+    }
+
+    const std::string mMetricsId;
+    const bool        mIsOut;  // if true, than a playback track, otherwise used for record.
+
+    mutable           std::mutex mLock;
+
+    // Devices in the interval group.
+    std::string       mDevices GUARDED_BY(mLock);
+
+    // Number of intervals and playing time
+    int32_t           mIntervalCount GUARDED_BY(mLock) = 0;
+    int64_t           mIntervalStartTimeNs GUARDED_BY(mLock) = 0;
+    int64_t           mCumulativeTimeNs GUARDED_BY(mLock) = 0;
+    int64_t           mDeviceTimeNs GUARDED_BY(mLock) = 0;
+
+    // Average volume
+    double            mVolume GUARDED_BY(mLock) = 0.f;
+    double            mDeviceVolume GUARDED_BY(mLock) = 0.f;
+    int64_t           mStartVolumeTimeNs GUARDED_BY(mLock) = 0;
+    int64_t           mLastVolumeChangeTimeNs GUARDED_BY(mLock) = 0;
+
+    // latency and startup for each interval.
+    audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
+    audio_utils::Statistics<double> mDeviceStartupMs GUARDED_BY(mLock);
+
+    // underrun count and frames
+    int64_t           mUnderrunCount GUARDED_BY(mLock) = 0;
+    int64_t           mUnderrunFrames GUARDED_BY(mLock) = 0;
+    int64_t           mUnderrunCountSinceIntervalGroup GUARDED_BY(mLock) = 0;
+    int64_t           mUnderrunFramesSinceIntervalGroup GUARDED_BY(mLock) = 0;
+};
+
+} // namespace android
+
+#endif // ANDROID_AUDIO_TRACKMETRICS_H
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 51e57b5..126015f 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -18,12 +18,14 @@
 
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
 
 #include "Configuration.h"
 #include <linux/futex.h>
 #include <math.h>
 #include <sys/syscall.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 
 #include <private/media/AudioTrackShared.h>
 
@@ -78,7 +80,8 @@
             bool isOut,
             alloc_type alloc,
             track_type type,
-            audio_port_handle_t portId)
+            audio_port_handle_t portId,
+            std::string metricsId)
     :   RefBase(),
         mThread(thread),
         mClient(client),
@@ -103,6 +106,7 @@
         mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
         mPortId(portId),
         mIsInvalid(false),
+        mTrackMetrics(std::move(metricsId), isOut),
         mCreatorPid(creatorPid)
 {
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -148,7 +152,7 @@
     if (client != 0) {
         mCblkMemory = client->heap()->allocate(size);
         if (mCblkMemory == 0 ||
-                (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) {
+                (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->unsecurePointer())) == NULL) {
             ALOGE("%s(%d): not enough memory for AudioTrack size=%zu", __func__, mId, size);
             client->heap()->dump("AudioTrack");
             mCblkMemory.clear();
@@ -170,7 +174,7 @@
             const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
             if (roHeap == 0 ||
                     (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
-                    (mBuffer = mBufferMemory->pointer()) == NULL) {
+                    (mBuffer = mBufferMemory->unsecurePointer()) == NULL) {
                 ALOGE("%s(%d): not enough memory for read-only buffer size=%zu",
                         __func__, mId, bufferSize);
                 if (roHeap != 0) {
@@ -185,7 +189,7 @@
         case ALLOC_PIPE:
             mBufferMemory = thread->pipeMemory();
             // mBuffer is the virtual address as seen from current process (mediaserver),
-            // and should normally be coming from mBufferMemory->pointer().
+            // and should normally be coming from mBufferMemory->unsecurePointer().
             // However in this case the TrackBase does not reference the buffer directly.
             // It should references the buffer via the pipe.
             // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
@@ -237,12 +241,7 @@
 {
     // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
     mServerProxy.clear();
-    if (mCblk != NULL) {
-        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
-        if (mClient == 0) {
-            free(mCblk);
-        }
-    }
+    releaseCblk();
     mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to
     if (mClient != 0) {
         // Client destructor must run with AudioFlinger client mutex locked
@@ -514,11 +513,17 @@
             audio_port_handle_t portId,
             size_t frameCountToBeReady)
     :   TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
-                  (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
+                  // TODO: Using unsecurePointer() has some associated security pitfalls
+                  //       (see declaration for details).
+                  //       Either document why it is safe in this case or address the
+                  //       issue (e.g. by copying).
+                  (sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
                   (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
                   sessionId, creatorPid, uid, true /*isOut*/,
                   (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
-                  type, portId),
+                  type,
+                  portId,
+                  std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
     mFillingUpStatus(FS_INVALID),
     // mRetryCount initialized later when needed
     mSharedBuffer(sharedBuffer),
@@ -545,25 +550,27 @@
     ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
 
     ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu",
-            __func__, mId, sharedBuffer->pointer(), sharedBuffer->size());
+            __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size());
 
     if (mCblk == NULL) {
         return;
     }
 
+    if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
+        ALOGE("%s(%d): no more tracks available", __func__, mId);
+        releaseCblk(); // this makes the track invalid.
+        return;
+    }
+
     if (sharedBuffer == 0) {
         mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                 mFrameSize, !isExternalTrack(), sampleRate);
     } else {
         mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
-                mFrameSize);
+                mFrameSize, sampleRate);
     }
     mServerProxy = mAudioTrackServerProxy;
 
-    if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
-        ALOGE("%s(%d): no more tracks available", __func__, mId);
-        return;
-    }
     // only allocate a fast track index if we were able to allocate a normal track name
     if (flags & AUDIO_OUTPUT_FLAG_FAST) {
         // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
@@ -593,6 +600,10 @@
         mExternalVibration = new os::ExternalVibration(
                 mUid, "" /* pkg */, mAttr, mAudioVibrationController);
     }
+
+    // Once this item is logged by the server, the client can add properties.
+    const char * const traits = sharedBuffer == 0 ? "" : "static";
+    mTrackMetrics.logConstructor(creatorPid, uid, traits, streamType);
 }
 
 AudioFlinger::PlaybackThread::Track::~Track()
@@ -740,7 +751,7 @@
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
             mPortId,
-            getTrackStateString(),
+            getTrackStateAsCodedString(),
             mCblk->mFlags,
 
             mFormat,
@@ -794,7 +805,7 @@
     status_t status = mServerProxy->obtainBuffer(&buf);
     buffer->frameCount = buf.mFrameCount;
     buffer->raw = buf.mRaw;
-    if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused()) {
+    if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused() && !isOffloaded()) {
         ALOGV("%s(%d): underrun,  framesReady(%zu) < framesDesired(%zd), state: %d",
                 __func__, mId, buf.mFrameCount, desiredFrames, mState);
         mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
@@ -822,16 +833,9 @@
     }
     for (auto& teePatch : mTeePatches) {
         RecordThread::PatchRecord* patchRecord = teePatch.patchRecord.get();
-
-        size_t framesWritten = writeFrames(patchRecord, sourceBuffer.i8, frameCount);
-        // On buffer wrap, the buffer frame count will be less than requested,
-        // when this happens a second buffer needs to be used to write the leftover audio
-        size_t framesLeft = frameCount - framesWritten;
-        if (framesWritten != 0 && framesLeft != 0) {
-            framesWritten +=
-                writeFrames(patchRecord, sourceBuffer.i8 + framesWritten * mFrameSize, framesLeft);
-            framesLeft = frameCount - framesWritten;
-        }
+        const size_t framesWritten = patchRecord->writeFrames(
+                sourceBuffer.i8, frameCount, mFrameSize);
+        const size_t framesLeft = frameCount - framesWritten;
         ALOGW_IF(framesLeft != 0, "%s(%d) PatchRecord %d can not provide big enough "
                  "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->mId,
                  framesWritten, frameCount, framesLeft);
@@ -843,26 +847,6 @@
              spent.count(), mTeePatches.size());
 }
 
-size_t AudioFlinger::PlaybackThread::Track::writeFrames(AudioBufferProvider* dest,
-                                                        const void* src,
-                                                        size_t frameCount) {
-    AudioBufferProvider::Buffer patchBuffer;
-    patchBuffer.frameCount = frameCount;
-    auto status = dest->getNextBuffer(&patchBuffer);
-    if (status != NO_ERROR) {
-       ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
-             __func__, status, strerror(-status));
-       return 0;
-    }
-    ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
-    memcpy(patchBuffer.raw, src, patchBuffer.frameCount * mFrameSize);
-    auto framesWritten = patchBuffer.frameCount;
-    dest->releaseBuffer(&patchBuffer);
-    return framesWritten;
-}
-
-// releaseBuffer() is not overridden
-
 // ExtendedAudioBufferProvider interface
 
 // framesReady() may return an approximation of the number of frames if called
@@ -990,6 +974,15 @@
             }
         }
 
+        // Audio timing metrics are computed a few mix cycles after starting.
+        {
+            mLogStartCountdown = LOG_START_COUNTDOWN;
+            mLogStartTimeNs = systemTime();
+            mLogStartFrames = mAudioTrackServerProxy->getTimestamp()
+                    .mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+            mLogLatencyMs = 0.;
+        }
+
         if (status == NO_ERROR || status == ALREADY_EXISTS) {
             // for streaming tracks, remove the buffer read stop limit.
             mAudioTrackServerProxy->start();
@@ -1252,6 +1245,7 @@
     if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates
         mFinalVolume = volume;
         setMetadataHasChanged();
+        mTrackMetrics.logVolume(volume);
     }
 }
 
@@ -1521,6 +1515,33 @@
 
     mServerLatencyFromTrack.store(useTrackTimestamp);
     mServerLatencyMs.store(latencyMs);
+
+    if (mLogStartCountdown > 0
+            && local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] > 0
+            && local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] > 0)
+    {
+        if (mLogStartCountdown > 1) {
+            --mLogStartCountdown;
+        } else if (latencyMs < mLogLatencyMs) { // wait for latency to stabilize (dip)
+            mLogStartCountdown = 0;
+            // startup is the difference in times for the current timestamp and our start
+            double startUpMs =
+                    (local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartTimeNs) * 1e-6;
+            // adjust for frames played.
+            startUpMs -= (local.mPosition[ExtendedTimestamp::LOCATION_KERNEL] - mLogStartFrames)
+                    * 1e3 / mSampleRate;
+            ALOGV("%s: latencyMs:%lf startUpMs:%lf"
+                    " localTime:%lld startTime:%lld"
+                    " localPosition:%lld startPosition:%lld",
+                    __func__, latencyMs, startUpMs,
+                    (long long)local.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+                    (long long)mLogStartTimeNs,
+                    (long long)local.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
+                    (long long)mLogStartFrames);
+            mTrackMetrics.logLatencyAndStartup(latencyMs, startUpMs);
+        }
+        mLogLatencyMs = latencyMs;
+    }
 }
 
 binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
@@ -1819,6 +1840,15 @@
     ALOGV("%s(%d)", __func__, mId);
 }
 
+size_t AudioFlinger::PlaybackThread::PatchTrack::framesReady() const
+{
+    if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
+        return std::numeric_limits<size_t>::max();
+    } else {
+        return Track::framesReady();
+    }
+}
+
 status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
                                                          audio_session_t triggerSession)
 {
@@ -1837,9 +1867,19 @@
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
     Proxy::Buffer buf;
     buf.mFrameCount = buffer->frameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PTnReq");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
     ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
     buffer->frameCount = buf.mFrameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PTnObt");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     if (buf.mFrameCount == 0) {
         return WOULD_BLOCK;
     }
@@ -1903,7 +1943,7 @@
 // static
 sp<AudioFlinger::RecordThread::OpRecordAudioMonitor>
 AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
-            uid_t uid, const String16& opPackageName)
+            uid_t uid, const audio_attributes_t& attr, const String16& opPackageName)
 {
     if (isServiceUid(uid)) {
         ALOGV("not silencing record for service uid:%d pack:%s",
@@ -1911,6 +1951,13 @@
         return nullptr;
     }
 
+    // Capturing from FM TUNER output is not controlled by OP_RECORD_AUDIO
+    // because it does not affect users privacy as does capturing from an actual microphone.
+    if (attr.source == AUDIO_SOURCE_FM_TUNER) {
+        ALOGV("not muting FM TUNER capture for uid %d", uid);
+        return nullptr;
+    }
+
     if (opPackageName.size() == 0) {
         Vector<String16> packages;
         // no package name, happens with SL ES clients
@@ -2069,14 +2116,15 @@
                   (type == TYPE_DEFAULT) ?
                           ((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
                           ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
-                  type, portId),
+                  type, portId,
+                  std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
         mOverflow(false),
         mFramesToDrop(0),
         mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
         mRecordBufferConverter(NULL),
         mFlags(flags),
         mSilenced(false),
-        mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(uid, opPackageName))
+        mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(uid, attr, opPackageName))
 {
     if (mCblk == NULL) {
         return;
@@ -2115,6 +2163,9 @@
             + "_" + std::to_string(mId)
             + "_R");
 #endif
+
+    // Once this item is logged by the server, the client can add properties.
+    mTrackMetrics.logConstructor(creatorPid, uid);
 }
 
 AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
@@ -2239,7 +2290,7 @@
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
             mPortId,
-            getTrackStateString(),
+            getTrackStateAsCodedString(),
             mCblk->mFlags,
 
             mFormat,
@@ -2400,6 +2451,39 @@
     ALOGV("%s(%d)", __func__, mId);
 }
 
+static size_t writeFramesHelper(
+        AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
+{
+    AudioBufferProvider::Buffer patchBuffer;
+    patchBuffer.frameCount = frameCount;
+    auto status = dest->getNextBuffer(&patchBuffer);
+    if (status != NO_ERROR) {
+       ALOGW("%s PathRecord getNextBuffer failed with error %d: %s",
+             __func__, status, strerror(-status));
+       return 0;
+    }
+    ALOG_ASSERT(patchBuffer.frameCount <= frameCount);
+    memcpy(patchBuffer.raw, src, patchBuffer.frameCount * frameSize);
+    size_t framesWritten = patchBuffer.frameCount;
+    dest->releaseBuffer(&patchBuffer);
+    return framesWritten;
+}
+
+// static
+size_t AudioFlinger::RecordThread::PatchRecord::writeFrames(
+        AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
+{
+    size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
+    // On buffer wrap, the buffer frame count will be less than requested,
+    // when this happens a second buffer needs to be used to write the leftover audio
+    const size_t framesLeft = frameCount - framesWritten;
+    if (framesWritten != 0 && framesLeft != 0) {
+        framesWritten += writeFramesHelper(dest, (const char*)src + framesWritten * frameSize,
+                        framesLeft, frameSize);
+    }
+    return framesWritten;
+}
+
 // AudioBufferProvider interface
 status_t AudioFlinger::RecordThread::PatchRecord::getNextBuffer(
                                                   AudioBufferProvider::Buffer* buffer)
@@ -2411,6 +2495,11 @@
     ALOGV_IF(status != NO_ERROR,
              "%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
     buffer->frameCount = buf.mFrameCount;
+    if (ATRACE_ENABLED()) {
+        std::string traceName("PRnObt");
+        traceName += std::to_string(id());
+        ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+    }
     if (buf.mFrameCount == 0) {
         return WOULD_BLOCK;
     }
@@ -2439,6 +2528,180 @@
     mProxy->releaseBuffer(buffer);
 }
 
+#undef LOG_TAG
+#define LOG_TAG "AF::PthrPatchRecord"
+
+static std::unique_ptr<void, decltype(free)*> allocAligned(size_t alignment, size_t size)
+{
+    void *ptr = nullptr;
+    (void)posix_memalign(&ptr, alignment, size);
+    return std::unique_ptr<void, decltype(free)*>(ptr, free);
+}
+
+AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
+        RecordThread *recordThread,
+        uint32_t sampleRate,
+        audio_channel_mask_t channelMask,
+        audio_format_t format,
+        size_t frameCount,
+        audio_input_flags_t flags)
+        : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount,
+                nullptr /*buffer*/, 0 /*bufferSize*/, flags),
+          mPatchRecordAudioBufferProvider(*this),
+          mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)),
+          mStubBuffer(allocAligned(32, mFrameCount * mFrameSize))
+{
+    memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
+}
+
+sp<StreamInHalInterface> AudioFlinger::RecordThread::PassthruPatchRecord::obtainStream(
+        sp<ThreadBase>* thread)
+{
+    *thread = mThread.promote();
+    if (!*thread) return nullptr;
+    RecordThread *recordThread = static_cast<RecordThread*>((*thread).get());
+    Mutex::Autolock _l(recordThread->mLock);
+    return recordThread->mInput ? recordThread->mInput->stream : nullptr;
+}
+
+// PatchProxyBufferProvider methods are called on DirectOutputThread
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::obtainBuffer(
+        Proxy::Buffer* buffer, const struct timespec* timeOut)
+{
+    if (mUnconsumedFrames) {
+        buffer->mFrameCount = std::min(buffer->mFrameCount, mUnconsumedFrames);
+        // mUnconsumedFrames is decreased in releaseBuffer to use actual frame consumption figure.
+        return PatchRecord::obtainBuffer(buffer, timeOut);
+    }
+
+    // Otherwise, execute a read from HAL and write into the buffer.
+    nsecs_t startTimeNs = 0;
+    if (timeOut && (timeOut->tv_sec != 0 || timeOut->tv_nsec != 0) && timeOut->tv_sec != INT_MAX) {
+        // Will need to correct timeOut by elapsed time.
+        startTimeNs = systemTime();
+    }
+    const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
+    buffer->mFrameCount = 0;
+    buffer->mRaw = nullptr;
+    sp<ThreadBase> thread;
+    sp<StreamInHalInterface> stream = obtainStream(&thread);
+    if (!stream) return NO_INIT;  // If there is no stream, RecordThread is not reading.
+
+    status_t result = NO_ERROR;
+    size_t bytesRead = 0;
+    {
+        ATRACE_NAME("read");
+        result = stream->read(mSinkBuffer.get(), framesToRead * mFrameSize, &bytesRead);
+        if (result != NO_ERROR) goto stream_error;
+        if (bytesRead == 0) return NO_ERROR;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mReadLock);
+        mReadBytes += bytesRead;
+        mReadError = NO_ERROR;
+    }
+    mReadCV.notify_one();
+    // writeFrames handles wraparound and should write all the provided frames.
+    // If it couldn't, there is something wrong with the client/server buffer of the software patch.
+    buffer->mFrameCount = writeFrames(
+            &mPatchRecordAudioBufferProvider,
+            mSinkBuffer.get(), bytesRead / mFrameSize, mFrameSize);
+    ALOGW_IF(buffer->mFrameCount < bytesRead / mFrameSize,
+            "Lost %zu frames obtained from HAL", bytesRead / mFrameSize - buffer->mFrameCount);
+    mUnconsumedFrames = buffer->mFrameCount;
+    struct timespec newTimeOut;
+    if (startTimeNs) {
+        // Correct the timeout by elapsed time.
+        nsecs_t newTimeOutNs = audio_utils_ns_from_timespec(timeOut) - (systemTime() - startTimeNs);
+        if (newTimeOutNs < 0) newTimeOutNs = 0;
+        newTimeOut.tv_sec = newTimeOutNs / NANOS_PER_SECOND;
+        newTimeOut.tv_nsec = newTimeOutNs - newTimeOut.tv_sec * NANOS_PER_SECOND;
+        timeOut = &newTimeOut;
+    }
+    return PatchRecord::obtainBuffer(buffer, timeOut);
+
+stream_error:
+    stream->standby();
+    {
+        std::lock_guard<std::mutex> lock(mReadLock);
+        mReadError = result;
+    }
+    mReadCV.notify_one();
+    return result;
+}
+
+void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+{
+    if (buffer->mFrameCount <= mUnconsumedFrames) {
+        mUnconsumedFrames -= buffer->mFrameCount;
+    } else {
+        ALOGW("Write side has consumed more frames than we had: %zu > %zu",
+                buffer->mFrameCount, mUnconsumedFrames);
+        mUnconsumedFrames = 0;
+    }
+    PatchRecord::releaseBuffer(buffer);
+}
+
+// AudioBufferProvider and Source methods are called on RecordThread
+// 'read' emulates actual audio data with 0's. This is OK as 'getNextBuffer'
+// and 'releaseBuffer' are stubbed out and ignore their input.
+// It's not possible to retrieve actual data here w/o blocking 'obtainBuffer'
+// until we copy it.
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::read(
+        void* buffer, size_t bytes, size_t* read)
+{
+    bytes = std::min(bytes, mFrameCount * mFrameSize);
+    {
+        std::unique_lock<std::mutex> lock(mReadLock);
+        mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
+        if (mReadError != NO_ERROR) {
+            mLastReadFrames = 0;
+            return mReadError;
+        }
+        *read = std::min(bytes, mReadBytes);
+        mReadBytes -= *read;
+    }
+    mLastReadFrames = *read / mFrameSize;
+    memset(buffer, 0, *read);
+    return 0;
+}
+
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::getCapturePosition(
+        int64_t* frames, int64_t* time)
+{
+    sp<ThreadBase> thread;
+    sp<StreamInHalInterface> stream = obtainStream(&thread);
+    return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
+}
+
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::standby()
+{
+    // RecordThread issues 'standby' command in two major cases:
+    // 1. Error on read--this case is handled in 'obtainBuffer'.
+    // 2. Track is stopping--as PassthruPatchRecord assumes continuous
+    //    output, this can only happen when the software patch
+    //    is being torn down. In this case, the RecordThread
+    //    will terminate and close the HAL stream.
+    return 0;
+}
+
+// As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
+status_t AudioFlinger::RecordThread::PassthruPatchRecord::getNextBuffer(
+        AudioBufferProvider::Buffer* buffer)
+{
+    buffer->frameCount = mLastReadFrames;
+    buffer->raw = buffer->frameCount != 0 ? mStubBuffer.get() : nullptr;
+    return NO_ERROR;
+}
+
+void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+        AudioBufferProvider::Buffer* buffer)
+{
+    buffer->frameCount = 0;
+    buffer->raw = nullptr;
+}
+
 // ----------------------------------------------------------------------------
 #undef LOG_TAG
 #define LOG_TAG "AF::MmapTrack"
@@ -2459,9 +2722,12 @@
                   nullptr /* buffer */, (size_t)0 /* bufferSize */,
                   sessionId, creatorPid, uid, isOut,
                   ALLOC_NONE,
-                  TYPE_DEFAULT, portId),
+                  TYPE_DEFAULT, portId,
+                  std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
         mPid(pid), mSilenced(false), mSilencedNotified(false)
 {
+    // Once this item is logged by the server, the client can add properties.
+    mTrackMetrics.logConstructor(creatorPid, uid);
 }
 
 AudioFlinger::MmapThread::MmapTrack::~MmapTrack()
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 30f29d6..8d0e5db 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -17,8 +17,10 @@
 #ifndef ANDROID_AUDIOPOLICY_INTERFACE_H
 #define ANDROID_AUDIOPOLICY_INTERFACE_H
 
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioSystem.h>
 #include <media/AudioPolicy.h>
+#include <media/DeviceDescriptorBase.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -67,12 +69,24 @@
         API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
     } input_type_t;
 
+    typedef enum {
+        API_OUTPUT_INVALID = -1,
+        API_OUTPUT_LEGACY  = 0,// e.g. audio playing to speaker
+        API_OUT_MIX_PLAYBACK,  // used for "remote submix" playback of audio from remote source
+                               // to local capture
+        API_OUTPUT_TELEPHONY_TX, // used for playback to telephony TX path
+    } output_type_t;
+
 public:
     virtual ~AudioPolicyInterface() {}
     //
     // configuration functions
     //
 
+    // Informs APM that new HAL modules are available. This typically happens
+    // due to registration of an audio HAL service.
+    virtual void onNewAudioModulesAvailable() = 0;
+
     // indicate a change in device connection status
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
@@ -113,7 +127,8 @@
                                         audio_output_flags_t *flags,
                                         audio_port_handle_t *selectedDeviceId,
                                         audio_port_handle_t *portId,
-                                        std::vector<audio_io_handle_t> *secondaryOutputs) = 0;
+                                        std::vector<audio_io_handle_t> *secondaryOutputs,
+                                        output_type_t *outputType) = 0;
     // indicates to the audio policy manager that the output starts being used by corresponding stream.
     virtual status_t startOutput(audio_port_handle_t portId) = 0;
     // indicates to the audio policy manager that the output stops being used by corresponding stream.
@@ -181,6 +196,10 @@
     // return the enabled output devices for the given stream type
     virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
 
+    // retrieves the list of enabled output devices for the given audio attributes
+    virtual status_t getDevicesForAttributes(const audio_attributes_t &attr,
+                                             AudioDeviceTypeAddrVector *devices) = 0;
+
     // Audio effect management
     virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0;
     virtual status_t registerEffect(const effect_descriptor_t *desc,
@@ -235,6 +254,10 @@
             = 0;
     virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
 
+    virtual status_t setUserIdDeviceAffinities(int userId,
+            const Vector<AudioDeviceTypeAddr>& devices) = 0;
+    virtual status_t removeUserIdDeviceAffinities(int userId) = 0;
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId,
@@ -258,7 +281,7 @@
     virtual status_t getHwOffloadEncodingFormatsSupportedForA2DP(
                 std::vector<audio_format_t> *formats) = 0;
 
-    virtual void     setAppState(uid_t uid, app_state_t state) = 0;
+    virtual void     setAppState(audio_port_handle_t portId, app_state_t state) = 0;
 
     virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
 
@@ -269,6 +292,16 @@
 
     virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
                                                        volume_group_t &volumeGroup) = 0;
+
+    virtual bool     isCallScreenModeSupported() = 0;
+
+    virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device) = 0;
+
+    virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+
+    virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device) = 0;
 };
 
 
@@ -296,8 +329,7 @@
     virtual status_t openOutput(audio_module_handle_t module,
                                 audio_io_handle_t *output,
                                 audio_config_t *config,
-                                audio_devices_t *devices,
-                                const String8& address,
+                                const sp<DeviceDescriptorBase>& device,
                                 uint32_t *latencyMs,
                                 audio_output_flags_t flags) = 0;
     // creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by
@@ -383,6 +415,12 @@
                                                 std::vector<effect_descriptor_t> effects,
                                                 audio_patch_handle_t patchHandle,
                                                 audio_source_t source) = 0;
+
+    // Used to notify the sound trigger module that an audio capture is about to
+    // take place. This should typically result in any active recognition
+    // sessions to be preempted on modules that do not support sound trigger
+    // recognition concurrently with audio capture.
+    virtual void setSoundTriggerCaptureState(bool active) = 0;
 };
 
 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
index a94fd87..eb6c19e 100644
--- a/services/audiopolicy/TEST_MAPPING
+++ b/services/audiopolicy/TEST_MAPPING
@@ -2,9 +2,6 @@
   "presubmit": [
     {
        "name": "audiopolicy_tests"
-    },
-    {
-       "name": "systemaudio_tests"
     }
   ]
 }
diff --git a/services/audiopolicy/audio_policy.conf b/services/audiopolicy/audio_policy.conf
deleted file mode 100644
index 9b83fef..0000000
--- a/services/audiopolicy/audio_policy.conf
+++ /dev/null
@@ -1,145 +0,0 @@
-#
-# Template audio policy configuration file
-#
-
-# Global configuration section:
-# - before audio HAL version 3.0:
-#   lists input and output devices always present on the device
-#   as well as the output device selected by default.
-#   Devices are designated by a string that corresponds to the enum in audio.h
-#
-#  global_configuration {
-#    attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
-#    default_output_device AUDIO_DEVICE_OUT_SPEAKER
-#    attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_REMOTE_SUBMIX
-#  }
-#
-# - after and including audio HAL 3.0 the global_configuration section is included in each
-#   hardware module section.
-#   it also includes the audio HAL version of this hw module:
-#  global_configuration {
-#    ...
-#     audio_hal_version <major.minor>  # audio HAL version in e.g. 3.0
-#  }
-#   other attributes (attached devices, default device) have to be included in the
-#   global_configuration section of each hardware module
-
-
-# audio hardware module section: contains descriptors for all audio hw modules present on the
-# device. Each hw module node is named after the corresponding hw module library base name.
-# For instance, "primary" corresponds to audio.primary.<device>.so.
-# The "primary" module is mandatory and must include at least one output with
-# AUDIO_OUTPUT_FLAG_PRIMARY flag.
-# Each module descriptor contains one or more output profile descriptors and zero or more
-# input profile descriptors. Each profile lists all the parameters supported by a given output
-# or input stream category.
-# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
-# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
-#
-# For audio HAL version posterior to 3.0 the following sections or sub sections can be present in
-# a hw module section:
-# - A "global_configuration" section: see above
-# - Optionally a "devices" section:
-#   This section contains descriptors for audio devices with attributes like an address or a
-#   gain controller. The syntax for the devices section and device descriptor is as follows:
-#    devices {
-#      <device name> {              # <device name>: any string without space
-#        type <device type>         # <device type> e.g. AUDIO_DEVICE_OUT_SPEAKER
-#        address <address>          # optional: device address, char string less than 64 in length
-#      }
-#    }
-# - one or more "gains" sections can be present in a device descriptor section.
-#   If present, they describe the capabilities of gain controllers attached to this input or
-#   output device. e.g. :
-#   <device name> {                  # <device name>: any string without space
-#     type <device type>             # <device type> e.g. AUDIO_DEVICE_OUT_SPEAKER
-#     address <address>              # optional: device address, char string less than 64 in length
-#     gains {
-#       <gain name> {
-#         mode <gain modes supported>              # e.g. AUDIO_GAIN_MODE_CHANNELS
-#         channel_mask <controlled channels>       # needed if mode AUDIO_GAIN_MODE_CHANNELS
-#         min_value_mB <min value in millibel>
-#         max_value_mB <max value in millibel>
-#         default_value_mB <default value in millibel>
-#         step_value_mB <step value in millibel>
-#         min_ramp_ms <min duration in ms>         # needed if mode AUDIO_GAIN_MODE_RAMP
-#         max_ramp_ms <max duration ms>            # needed if mode AUDIO_GAIN_MODE_RAMP
-#       }
-#     }
-#   }
-# - when a device descriptor is present, output and input profiles can refer to this device by
-# its name in their "devices" section instead of specifying a device type. e.g. :
-#   outputs {
-#     primary {
-#       sampling_rates 44100
-#       channel_masks AUDIO_CHANNEL_OUT_STEREO
-#       formats AUDIO_FORMAT_PCM_16_BIT
-#       devices <device name>
-#       flags AUDIO_OUTPUT_FLAG_PRIMARY
-#     }
-#   }
-# sample audio_policy.conf file below
-
-audio_hw_modules {
-  primary {
-    global_configuration {
-      attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
-      default_output_device AUDIO_DEVICE_OUT_SPEAKER
-      attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
-      audio_hal_version 3.0
-    }
-    devices {
-      speaker {
-        type AUDIO_DEVICE_OUT_SPEAKER
-        gains {
-          gain_1 {
-            mode AUDIO_GAIN_MODE_JOINT
-            min_value_mB -8400
-            max_value_mB 4000
-            default_value_mB 0
-            step_value_mB 100
-          }
-        }
-      }
-    }
-    outputs {
-      primary {
-        sampling_rates 48000
-        channel_masks AUDIO_CHANNEL_OUT_STEREO
-        formats AUDIO_FORMAT_PCM_16_BIT
-        devices speaker
-        flags AUDIO_OUTPUT_FLAG_PRIMARY
-      }
-    }
-    inputs {
-      primary {
-        sampling_rates 8000|16000
-        channel_masks AUDIO_CHANNEL_IN_MONO
-        formats AUDIO_FORMAT_PCM_16_BIT
-        devices AUDIO_DEVICE_IN_BUILTIN_MIC
-      }
-    }
-  }
-  r_submix {
-    global_configuration {
-      attached_input_devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
-      audio_hal_version 2.0
-    }
-    outputs {
-      submix {
-        sampling_rates 48000
-        channel_masks AUDIO_CHANNEL_OUT_STEREO
-        formats AUDIO_FORMAT_PCM_16_BIT
-        devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-      }
-    }
-    inputs {
-      submix {
-        sampling_rates 48000
-        channel_masks AUDIO_CHANNEL_IN_STEREO
-        formats AUDIO_FORMAT_PCM_16_BIT
-        devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
-      }
-    }
-  }
-}
diff --git a/services/audiopolicy/common/Android.bp b/services/audiopolicy/common/Android.bp
index a925b9a..6e0d2f6 100644
--- a/services/audiopolicy/common/Android.bp
+++ b/services/audiopolicy/common/Android.bp
@@ -1,4 +1,7 @@
 cc_library_headers {
     name: "libaudiopolicycommon",
+    header_libs: [
+        "libaudiofoundation_headers",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 1dbd1eb..7c8ce83 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -17,10 +17,13 @@
 #pragma once
 
 #include <media/AudioCommonTypes.h>
+#include <media/AudioContainers.h>
 #include <system/audio.h>
 #include <utils/Log.h>
 #include <math.h>
 
+#include "policy.h"
+
 namespace android {
 
 /**
@@ -82,43 +85,26 @@
      *
      * @return subset of device required to limit the number of volume category per device
      */
-    static audio_devices_t getDeviceForVolume(audio_devices_t device)
+    static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
     {
-        if (device == AUDIO_DEVICE_NONE) {
+        if (deviceTypes.empty()) {
             // this happens when forcing a route update and no track is active on an output.
             // In this case the returned category is not important.
-            device =  AUDIO_DEVICE_OUT_SPEAKER;
-        } else if (popcount(device) > 1) {
-            // Multiple device selection is either:
-            //  - speaker + one other device: give priority to speaker in this case.
-            //  - one A2DP device + another device: happens with duplicated output. In this case
-            // retain the device on the A2DP output as the other must not correspond to an active
-            // selection if not the speaker.
-            //  - HDMI-CEC system audio mode only output: give priority to available item in order.
-            if (device & AUDIO_DEVICE_OUT_SPEAKER) {
-                device = AUDIO_DEVICE_OUT_SPEAKER;
-            } else if (device & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
-                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-            } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
-                device = AUDIO_DEVICE_OUT_HDMI_ARC;
-            } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
-                device = AUDIO_DEVICE_OUT_AUX_LINE;
-            } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
-                device = AUDIO_DEVICE_OUT_SPDIF;
-            } else {
-                device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
-            }
+            return AUDIO_DEVICE_OUT_SPEAKER;
         }
 
+        audio_devices_t deviceType = apm_extract_one_audio_device(deviceTypes);
+
         /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
-        if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
-            device = AUDIO_DEVICE_OUT_SPEAKER;
+        if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
+            deviceType = AUDIO_DEVICE_OUT_SPEAKER;
+        }
 
-        ALOGW_IF(popcount(device) != 1,
-                 "getDeviceForVolume() invalid device combination: %08x",
-                 device);
+        ALOGW_IF(deviceType == AUDIO_DEVICE_NONE,
+                 "getDeviceForVolume() invalid device combination: %s, returning AUDIO_DEVICE_NONE",
+                 android::dumpDeviceTypes(deviceTypes).c_str());
 
-        return device;
+        return deviceType;
     }
 
     /**
@@ -128,9 +114,9 @@
      *
      * @return device category.
      */
-    static device_category getDeviceCategory(audio_devices_t device)
+    static device_category getDeviceCategory(const android::DeviceTypeSet& deviceTypes)
     {
-        switch(getDeviceForVolume(device)) {
+        switch(getDeviceForVolume(deviceTypes)) {
         case AUDIO_DEVICE_OUT_EARPIECE:
             return DEVICE_CATEGORY_EARPIECE;
         case AUDIO_DEVICE_OUT_WIRED_HEADSET:
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 605fc1c..0537365 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -19,6 +19,8 @@
 #include <system/audio.h>
 #include <vector>
 
+#include <media/AudioContainers.h>
+
 namespace android {
 
 using StreamTypeVector = std::vector<audio_stream_type_t>;
@@ -43,14 +45,6 @@
 #define MAX_MIXER_CHANNEL_COUNT FCC_8
 
 /**
- * A device mask for all audio input and output devices where matching inputs/outputs on device
- * type alone is not enough: the address must match too
- */
-#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX|AUDIO_DEVICE_OUT_BUS)
-
-#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
-
-/**
  * Alias to AUDIO_DEVICE_OUT_DEFAULT defined for clarification when this value is used by volume
  * control APIs (e.g setStreamVolumeIndex().
  */
@@ -71,6 +65,34 @@
 }
 
 /**
+ * Check whether the output device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static inline bool apm_audio_out_device_distinguishes_on_address(audio_devices_t device)
+{
+    return device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+           device == AUDIO_DEVICE_OUT_BUS;
+}
+
+/**
+ * Check whether the input device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static inline bool apm_audio_in_device_distinguishes_on_address(audio_devices_t device)
+{
+    return device == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
+           device == AUDIO_DEVICE_IN_BUS;
+}
+
+/**
  * Check whether the device type is one
  * where addresses are used to distinguish between one connected device and another
  *
@@ -80,10 +102,8 @@
  */
 static inline bool device_distinguishes_on_address(audio_devices_t device)
 {
-    return (((device & AUDIO_DEVICE_BIT_IN) != 0) &&
-            ((~AUDIO_DEVICE_BIT_IN & device & APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL) != 0)) ||
-           (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
-            ((device & APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL) != 0));
+    return apm_audio_in_device_distinguishes_on_address(device) ||
+           apm_audio_out_device_distinguishes_on_address(device);
 }
 
 /**
@@ -95,10 +115,7 @@
  */
 static inline bool device_has_encoding_capability(audio_devices_t device)
 {
-    if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
-        return true;
-    }
-    return false;
+    return audio_is_a2dp_out_device(device);
 }
 
 /**
@@ -184,3 +201,43 @@
 {
     return hasStream(streams, AUDIO_STREAM_VOICE_CALL);
 }
+
+/**
+ * @brief extract one device relevant from multiple device selection
+ * @param deviceTypes collection of audio device type
+ * @return the device type that is selected
+ */
+static inline audio_devices_t apm_extract_one_audio_device(
+        const android::DeviceTypeSet& deviceTypes) {
+    if (deviceTypes.empty()) {
+        return AUDIO_DEVICE_NONE;
+    } else if (deviceTypes.size() == 1) {
+        return *(deviceTypes.begin());
+    } else {
+        // Multiple device selection is either:
+        //  - speaker + one other device: give priority to speaker in this case.
+        //  - one A2DP device + another device: happens with duplicated output. In this case
+        // retain the device on the A2DP output as the other must not correspond to an active
+        // selection if not the speaker.
+        //  - HDMI-CEC system audio mode only output: give priority to available item in order.
+        if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
+            return AUDIO_DEVICE_OUT_SPEAKER;
+        } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
+            return AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+        } else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
+            return AUDIO_DEVICE_OUT_HDMI_ARC;
+        } else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
+            return AUDIO_DEVICE_OUT_AUX_LINE;
+        } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
+            return AUDIO_DEVICE_OUT_SPDIF;
+        } else {
+            std::vector<audio_devices_t> a2dpDevices = android::Intersection(
+                    deviceTypes, android::getAudioDeviceOutAllA2dpSet());
+            if (a2dpDevices.empty() || a2dpDevices.size() > 1) {
+                ALOGW("%s invalid device combination: %s",
+                      __func__, android::dumpDeviceTypes(deviceTypes).c_str());
+            }
+            return a2dpDevices.empty() ? AUDIO_DEVICE_NONE : a2dpDevices[0];
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index f02f3cf..57f0b5b 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -3,32 +3,37 @@
 
     srcs: [
         "src/AudioCollections.cpp",
-        "src/AudioGain.cpp",
         "src/AudioInputDescriptor.cpp",
         "src/AudioOutputDescriptor.cpp",
         "src/AudioPatch.cpp",
         "src/AudioPolicyMix.cpp",
-        "src/AudioPort.cpp",
-        "src/AudioProfile.cpp",
+        "src/AudioProfileVectorHelper.cpp",
         "src/AudioRoute.cpp",
         "src/ClientDescriptor.cpp",
         "src/DeviceDescriptor.cpp",
         "src/EffectDescriptor.cpp",
         "src/HwModule.cpp",
         "src/IOProfile.cpp",
+        "src/PolicyAudioPort.cpp",
         "src/Serializer.cpp",
         "src/SoundTriggerSession.cpp",
         "src/TypeConverter.cpp",
     ],
     shared_libs: [
+        "libaudiofoundation",
         "libcutils",
         "libhidlbase",
         "liblog",
         "libmedia",
+        "libmedia_helper",
         "libutils",
         "libxml2",
     ],
-    export_shared_lib_headers: ["libmedia"],
+    export_shared_lib_headers: [
+        "libaudiofoundation",
+        "libmedia",
+        "libmedia_helper",
+    ],
     static_libs: [
         "libaudioutils",
     ],
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
index a948ea9..b692592 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
@@ -25,20 +25,15 @@
 
 namespace android {
 
-class AudioPort;
+class PolicyAudioPort;
 class AudioRoute;
 
-class AudioPortVector : public Vector<sp<AudioPort> >
-{
-public:
-    sp<AudioPort> findByTagName(const String8 &tagName) const;
-};
+using PolicyAudioPortVector = Vector<sp<PolicyAudioPort>>;
+using AudioRouteVector = Vector<sp<AudioRoute>>;
 
+sp<PolicyAudioPort> findByTagName(const PolicyAudioPortVector& policyAudioPortVector,
+                                  const std::string &tagName);
 
-class AudioRouteVector : public Vector<sp<AudioRoute> >
-{
-public:
-    void dump(String8 *dst, int spaces) const;
-};
+void dumpAudioRouteVector(const AudioRouteVector& audioRouteVector, String8 *dst, int spaces);
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
deleted file mode 100644
index 4af93e1..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <system/audio.h>
-#include <vector>
-
-namespace android {
-
-class AudioGain: public RefBase
-{
-public:
-    AudioGain(int index, bool useInChannelMask);
-    virtual ~AudioGain() {}
-
-    void setMode(audio_gain_mode_t mode) { mGain.mode = mode; }
-    const audio_gain_mode_t &getMode() const { return mGain.mode; }
-
-    void setChannelMask(audio_channel_mask_t mask) { mGain.channel_mask = mask; }
-    const audio_channel_mask_t &getChannelMask() const { return mGain.channel_mask; }
-
-    void setMinValueInMb(int minValue) { mGain.min_value = minValue; }
-    int getMinValueInMb() const { return mGain.min_value; }
-
-    void setMaxValueInMb(int maxValue) { mGain.max_value = maxValue; }
-    int getMaxValueInMb() const { return mGain.max_value; }
-
-    void setDefaultValueInMb(int defaultValue) { mGain.default_value = defaultValue; }
-    int getDefaultValueInMb() const { return mGain.default_value; }
-
-    void setStepValueInMb(uint32_t stepValue) { mGain.step_value = stepValue; }
-    int getStepValueInMb() const { return mGain.step_value; }
-
-    void setMinRampInMs(uint32_t minRamp) { mGain.min_ramp_ms = minRamp; }
-    int getMinRampInMs() const { return mGain.min_ramp_ms; }
-
-    void setMaxRampInMs(uint32_t maxRamp) { mGain.max_ramp_ms = maxRamp; }
-    int getMaxRampInMs() const { return mGain.max_ramp_ms; }
-
-    // TODO: remove dump from here (split serialization)
-    void dump(String8 *dst, int spaces, int index) const;
-
-    void getDefaultConfig(struct audio_gain_config *config);
-    status_t checkConfig(const struct audio_gain_config *config);
-
-    void setUseForVolume(bool canUseForVolume) { mUseForVolume = canUseForVolume; }
-    bool canUseForVolume() const { return mUseForVolume; }
-
-    const struct audio_gain &getGain() const { return mGain; }
-
-private:
-    int               mIndex;
-    struct audio_gain mGain;
-    bool              mUseInChannelMask;
-    bool              mUseForVolume = false;
-};
-
-class AudioGains : public std::vector<sp<AudioGain> >
-{
-public:
-    bool canUseForVolume() const
-    {
-        for (const auto &gain: *this) {
-            if (gain->canUseForVolume()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    int32_t add(const sp<AudioGain> gain)
-    {
-        push_back(gain);
-        return 0;
-    }
-};
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
index 6e29632..6167f95 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
@@ -34,6 +34,8 @@
     virtual audio_patch_handle_t getPatchHandle() const = 0;
 
     virtual void setPatchHandle(audio_patch_handle_t handle) = 0;
+
+    virtual bool isMmap() = 0;
 };
 
 template <class IoDescriptor, class Filter>
@@ -41,11 +43,24 @@
         IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices)
 {
     auto activeClients = desc->clientsList(true /*activeOnly*/);
-    auto activeClientsWithRoute =
-        desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
     active = activeClients.size() > 0;
-    if (active && activeClients.size() == activeClientsWithRoute.size()) {
-        return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+
+    if (active) {
+        // On MMAP IOs, the preferred device is selected by the first client (virtual client
+        // created when the mmap stream is opened). This client is never active.
+        // On non MMAP IOs, the preferred device is honored only if all active clients have
+        // a preferred device in which case the first client drives the selection.
+        if (desc->isMmap()) {
+            // The client list is never empty on a MMAP IO
+            return devices.getDeviceFromId(
+                    desc->clientsList(false /*activeOnly*/)[0]->preferredDeviceId());
+        } else {
+            auto activeClientsWithRoute =
+                desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
+            if (activeClients.size() == activeClientsWithRoute.size()) {
+                return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+            }
+        }
     }
     return nullptr;
 }
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 37f9d14..6f47abc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -21,11 +21,11 @@
 #include <utils/SortedVector.h>
 #include <utils/KeyedVector.h>
 #include "AudioIODescriptorInterface.h"
-#include "AudioPort.h"
 #include "ClientDescriptor.h"
 #include "DeviceDescriptor.h"
 #include "EffectDescriptor.h"
 #include "IOProfile.h"
+#include "PolicyAudioPort.h"
 
 namespace android {
 
@@ -34,13 +34,17 @@
 
 // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
 // and keep track of the usage of this input.
-class AudioInputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
-    , public ClientMapHandler<RecordClientDescriptor>
+class AudioInputDescriptor: public AudioPortConfig,
+        public PolicyAudioPortConfig,
+        public AudioIODescriptorInterface,
+        public ClientMapHandler<RecordClientDescriptor>
 {
 public:
-    explicit AudioInputDescriptor(const sp<IOProfile>& profile,
-                                  AudioPolicyClientInterface *clientInterface);
-    audio_port_handle_t getId() const;
+    AudioInputDescriptor(const sp<IOProfile>& profile,
+                         AudioPolicyClientInterface *clientInterface);
+
+    virtual ~AudioInputDescriptor() = default;
+
     audio_module_handle_t getModuleHandle() const;
 
     audio_devices_t getDeviceType() const { return (mDevice != nullptr) ?
@@ -56,9 +60,18 @@
     wp<AudioPolicyMix>  mPolicyMix;                   // non NULL when used by a dynamic policy
     const sp<IOProfile> mProfile;                     // I/O profile this output derives from
 
+    // PolicyAudioPortConfig
+    virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
+        return mProfile;
+    }
+
+    // AudioPortConfig
+    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+                                          struct audio_port_config *backupConfig = NULL);
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
             const struct audio_port_config *srcConfig = NULL) const;
     virtual sp<AudioPort> getAudioPort() const { return mProfile; }
+
     void toAudioPort(struct audio_port *port) const;
     void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
     SortedVector<audio_session_t> getPreemptedSessions() const;
@@ -79,6 +92,12 @@
     audio_config_base_t getConfig() const override;
     audio_patch_handle_t getPatchHandle() const override;
     void setPatchHandle(audio_patch_handle_t handle) override;
+    bool isMmap() override {
+        if (getPolicyAudioPort() != nullptr) {
+            return getPolicyAudioPort()->isMmap();
+        }
+        return false;
+    }
 
     status_t open(const audio_config_t *config,
                   const sp<DeviceDescriptor> &device,
@@ -97,7 +116,7 @@
     RecordClientVector clientsList(bool activeOnly = false,
         audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
 
-    void setAppState(uid_t uid, app_state_t state);
+    void setAppState(audio_port_handle_t portId, app_state_t state);
 
     // implementation of ClientMapHandler<RecordClientDescriptor>
     void addClient(const sp<RecordClientDescriptor> &client) override;
@@ -111,7 +130,6 @@
     void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
 
     audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-    audio_port_handle_t  mId = AUDIO_PORT_HANDLE_NONE;
     sp<DeviceDescriptor> mDevice = nullptr; /**< current device this input is routed to */
 
     // Because a preemptible capture session can preempt another one, we end up in an endless loop
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index cd54085..39d1140 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -21,14 +21,15 @@
 
 #include <sys/types.h>
 
+#include <media/AudioContainers.h>
 #include <utils/Errors.h>
 #include <utils/Timers.h>
 #include <utils/KeyedVector.h>
 #include <system/audio.h>
 #include "AudioIODescriptorInterface.h"
-#include "AudioPort.h"
 #include "ClientDescriptor.h"
 #include "DeviceDescriptor.h"
+#include "PolicyAudioPort.h"
 #include <vector>
 
 namespace android {
@@ -138,27 +139,28 @@
 
 // descriptor for audio outputs. Used to maintain current configuration of each opened audio output
 // and keep track of the usage of this output by each audio stream type.
-class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
-    , public ClientMapHandler<TrackClientDescriptor>
+class AudioOutputDescriptor: public AudioPortConfig,
+        public PolicyAudioPortConfig,
+        public AudioIODescriptorInterface,
+        public ClientMapHandler<TrackClientDescriptor>
 {
 public:
-    AudioOutputDescriptor(const sp<AudioPort>& port,
+    AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
                           AudioPolicyClientInterface *clientInterface);
     virtual ~AudioOutputDescriptor() {}
 
     void dump(String8 *dst) const override;
     void        log(const char* indent);
 
-    audio_port_handle_t getId() const;
     virtual DeviceVector devices() const { return mDevices; }
     bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
     virtual DeviceVector supportedDevices() const  { return mDevices; }
     virtual bool isDuplicated() const { return false; }
     virtual uint32_t latency() { return 0; }
-    virtual bool isFixedVolume(audio_devices_t device);
+    virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
     virtual bool setVolume(float volumeDb,
                            VolumeSource volumeSource, const StreamTypeVector &streams,
-                           audio_devices_t device,
+                           const DeviceTypeSet& deviceTypes,
                            uint32_t delayMs,
                            bool force);
 
@@ -245,9 +247,19 @@
         mRoutingActivities[ps].setMutedByDevice(isMuted);
     }
 
+    // PolicyAudioPortConfig
+    virtual sp<PolicyAudioPort> getPolicyAudioPort() const
+    {
+        return mPolicyAudioPort;
+    }
+
+    // AudioPortConfig
+    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+                                          struct audio_port_config *backupConfig = NULL);
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                            const struct audio_port_config *srcConfig = NULL) const;
-    virtual sp<AudioPort> getAudioPort() const { return mPort; }
+    virtual sp<AudioPort> getAudioPort() const { return mPolicyAudioPort->asAudioPort(); }
+
     virtual void toAudioPort(struct audio_port *port) const;
 
     audio_module_handle_t getModuleHandle() const;
@@ -256,6 +268,12 @@
     audio_config_base_t getConfig() const override;
     audio_patch_handle_t getPatchHandle() const override;
     void setPatchHandle(audio_patch_handle_t handle) override;
+    bool isMmap() override {
+        if (getPolicyAudioPort() != nullptr) {
+            return getPolicyAudioPort()->isMmap();
+        }
+        return false;
+    }
 
     TrackClientVector clientsList(bool activeOnly = false,
                                   product_strategy_t strategy = PRODUCT_STRATEGY_NONE,
@@ -289,11 +307,10 @@
     wp<AudioPolicyMix> mPolicyMix;  // non NULL when used by a dynamic policy
 
 protected:
-    const sp<AudioPort> mPort;
+    const sp<PolicyAudioPort> mPolicyAudioPort;
     AudioPolicyClientInterface * const mClientInterface;
     uint32_t mGlobalActiveCount = 0;  // non-client-specific active count
     audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
 
     // The ActiveClients shows the clients that contribute to the @VolumeSource counts
     // and may include upstream clients from a duplicating thread.
@@ -319,10 +336,10 @@
     void setDevices(const DeviceVector &devices) { mDevices = devices; }
     bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
     virtual DeviceVector supportedDevices() const;
-    virtual bool deviceSupportsEncodedFormats(audio_devices_t device);
+    virtual bool devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes);
     virtual uint32_t latency();
     virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
-    virtual bool isFixedVolume(audio_devices_t device);
+    virtual bool isFixedVolume(const DeviceTypeSet& deviceTypes);
     sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; }
     sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; }
     void setClientActive(const sp<TrackClientDescriptor>& client, bool active) override;
@@ -334,7 +351,7 @@
     }
     virtual bool setVolume(float volumeDb,
                            VolumeSource volumeSource, const StreamTypeVector &streams,
-                           audio_devices_t device,
+                           const DeviceTypeSet& device,
                            uint32_t delayMs,
                            bool force);
 
@@ -408,7 +425,7 @@
 
     virtual bool setVolume(float volumeDb,
                            VolumeSource volumeSource, const StreamTypeVector &streams,
-                           audio_devices_t device,
+                           const DeviceTypeSet& deviceTypes,
                            uint32_t delayMs,
                            bool force);
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
index 0843fea..a5de655 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
@@ -31,12 +31,24 @@
 public:
     AudioPatch(const struct audio_patch *patch, uid_t uid);
 
+    audio_patch_handle_t getHandle() const { return mHandle; }
+
+    audio_patch_handle_t getAfHandle() const { return mAfPatchHandle; }
+
+    void setAfHandle(audio_patch_handle_t afHandle) { mAfPatchHandle = afHandle; }
+
+    uid_t getUid() const { return mUid; }
+
+    void setUid(uid_t uid) { mUid = uid; }
+
     void dump(String8 *dst, int spaces, int index) const;
 
-    audio_patch_handle_t mHandle;
     struct audio_patch mPatch;
+
+private:
+    const audio_patch_handle_t mHandle;
     uid_t mUid;
-    audio_patch_handle_t mAfPatchHandle;
+    audio_patch_handle_t mAfPatchHandle = AUDIO_PATCH_HANDLE_NONE;
 };
 
 class AudioPatchCollection : public DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> >
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 2264d8f..395bc70 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -19,17 +19,17 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include <AudioGain.h>
-#include <AudioPort.h>
 #include <AudioPatch.h>
 #include <DeviceDescriptor.h>
 #include <IOProfile.h>
 #include <HwModule.h>
+#include <PolicyAudioPort.h>
 #include <AudioInputDescriptor.h>
 #include <AudioOutputDescriptor.h>
 #include <AudioPolicyMix.h>
 #include <EffectDescriptor.h>
 #include <SoundTriggerSession.h>
+#include <media/AudioProfile.h>
 
 namespace android {
 
@@ -37,14 +37,16 @@
 {
 public:
     AudioPolicyConfig(HwModuleCollection &hwModules,
-                      DeviceVector &availableOutputDevices,
-                      DeviceVector &availableInputDevices,
+                      DeviceVector &outputDevices,
+                      DeviceVector &inputDevices,
                       sp<DeviceDescriptor> &defaultOutputDevice)
-        : mHwModules(hwModules),
-          mAvailableOutputDevices(availableOutputDevices),
-          mAvailableInputDevices(availableInputDevices),
+        : mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
+          mHwModules(hwModules),
+          mOutputDevices(outputDevices),
+          mInputDevices(inputDevices),
           mDefaultOutputDevice(defaultOutputDevice),
-          mIsSpeakerDrcEnabled(false)
+          mIsSpeakerDrcEnabled(false),
+          mIsCallScreenModeSupported(false)
     {}
 
     const std::string& getSource() const {
@@ -55,28 +57,36 @@
         mSource = file;
     }
 
+    const std::string& getEngineLibraryNameSuffix() const {
+        return mEngineLibraryNameSuffix;
+    }
+
+    void setEngineLibraryNameSuffix(const std::string& suffix) {
+        mEngineLibraryNameSuffix = suffix;
+    }
+
     void setHwModules(const HwModuleCollection &hwModules)
     {
         mHwModules = hwModules;
     }
 
-    void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
+    void addDevice(const sp<DeviceDescriptor> &device)
     {
-        if (audio_is_output_device(availableDevice->type())) {
-            mAvailableOutputDevices.add(availableDevice);
-        } else if (audio_is_input_device(availableDevice->type())) {
-            mAvailableInputDevices.add(availableDevice);
+        if (audio_is_output_device(device->type())) {
+            mOutputDevices.add(device);
+        } else if (audio_is_input_device(device->type())) {
+            mInputDevices.add(device);
         }
     }
 
-    void addAvailableInputDevices(const DeviceVector &availableInputDevices)
+    void addInputDevices(const DeviceVector &inputDevices)
     {
-        mAvailableInputDevices.add(availableInputDevices);
+        mInputDevices.add(inputDevices);
     }
 
-    void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
+    void addOutputDevices(const DeviceVector &outputDevices)
     {
-        mAvailableOutputDevices.add(availableOutputDevices);
+        mOutputDevices.add(outputDevices);
     }
 
     bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
@@ -86,16 +96,24 @@
         mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
     }
 
-    const HwModuleCollection getHwModules() const { return mHwModules; }
+    bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
 
-    const DeviceVector &getAvailableInputDevices() const
+    void setCallScreenModeSupported(bool isCallScreenModeSupported)
     {
-        return mAvailableInputDevices;
+        mIsCallScreenModeSupported = isCallScreenModeSupported;
     }
 
-    const DeviceVector &getAvailableOutputDevices() const
+
+    const HwModuleCollection getHwModules() const { return mHwModules; }
+
+    const DeviceVector &getInputDevices() const
     {
-        return mAvailableOutputDevices;
+        return mInputDevices;
+    }
+
+    const DeviceVector &getOutputDevices() const
+    {
+        return mOutputDevices;
     }
 
     void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
@@ -108,29 +126,28 @@
     void setDefault(void)
     {
         mSource = "AudioPolicyConfig::setDefault";
+        mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
         mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
-        mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+        mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
         sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
-        defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+        defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
         sp<AudioProfile> micProfile = new AudioProfile(
                 AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
         defaultInputDevice->addAudioProfile(micProfile);
-        mAvailableOutputDevices.add(mDefaultOutputDevice);
-        mAvailableInputDevices.add(defaultInputDevice);
+        mOutputDevices.add(mDefaultOutputDevice);
+        mInputDevices.add(defaultInputDevice);
 
         sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
         mHwModules.add(module);
-        mDefaultOutputDevice->attach(module);
-        defaultInputDevice->attach(module);
 
-        sp<OutputProfile> outProfile = new OutputProfile(String8("primary"));
+        sp<OutputProfile> outProfile = new OutputProfile("primary");
         outProfile->addAudioProfile(
                 new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
         outProfile->addSupportedDevice(mDefaultOutputDevice);
         outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
         module->addOutputProfile(outProfile);
 
-        sp<InputProfile> inProfile = new InputProfile(String8("primary"));
+        sp<InputProfile> inProfile = new InputProfile("primary");
         inProfile->addAudioProfile(micProfile);
         inProfile->addSupportedDevice(defaultInputDevice);
         module->addInputProfile(inProfile);
@@ -167,15 +184,19 @@
     }
 
 private:
+    static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+
     std::string mSource;
+    std::string mEngineLibraryNameSuffix;
     HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
-    DeviceVector &mAvailableOutputDevices;
-    DeviceVector &mAvailableInputDevices;
+    DeviceVector &mOutputDevices;
+    DeviceVector &mInputDevices;
     sp<DeviceDescriptor> &mDefaultOutputDevice;
     // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
     // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
     // Note: remove also speaker_drc_enabled from global configuration of XML config file.
     bool mIsSpeakerDrcEnabled;
+    bool mIsCallScreenModeSupported;
     SurroundFormats mSurroundFormats;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 094f506..b82305d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -18,6 +18,7 @@
 
 #include "DeviceDescriptor.h"
 #include <utils/RefBase.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioPolicy.h>
 #include <utils/Vector.h>
 #include <system/audio.h>
@@ -71,8 +72,8 @@
      */
     status_t getOutputForAttr(const audio_attributes_t& attributes, uid_t uid,
                               audio_output_flags_t flags,
-                              sp<SwAudioOutputDescriptor> &primaryDesc,
-                              std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
+                              sp<AudioPolicyMix> &primaryMix,
+                              std::vector<sp<AudioPolicyMix>> *secondaryMixes);
 
     sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
                                                        const DeviceVector &availableDeviceTypes,
@@ -104,12 +105,27 @@
     status_t removeUidDeviceAffinities(uid_t uid);
     status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
 
+    /**
+     * Updates the mix rules in order to make streams associated with the given user
+     * be routed to the given audio devices.
+     * @param userId the userId for which the device affinity is set
+     * @param devices the vector of devices that this userId may be routed to. A typical
+     *    use is to pass the devices associated with a given zone in a multi-zone setup.
+     * @return NO_ERROR if the update was successful, INVALID_OPERATION otherwise.
+     *    An example of failure is when there are already rules in place to restrict
+     *    a mix to the given userId (i.e. when a MATCH_USERID rule was set for it).
+     */
+    status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+    status_t removeUserIdDeviceAffinities(int userId);
+    status_t getDevicesForUserId(int userId, Vector<AudioDeviceTypeAddr>& devices) const;
+
     void dump(String8 *dst) const;
 
 private:
     enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
     MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
-                            const audio_attributes_t& attributes, uid_t uid);
+                            const audio_attributes_t& attributes,
+                            uid_t uid);
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
deleted file mode 100644
index d906f11..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-#include "AudioCollections.h"
-#include "AudioProfile.h"
-#include "AudioGain.h"
-#include "HandleGenerator.h"
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <system/audio.h>
-#include <cutils/config_utils.h>
-
-namespace android {
-
-class HwModule;
-class AudioRoute;
-
-class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
-{
-public:
-    AudioPort(const String8& name, audio_port_type_t type,  audio_port_role_t role) :
-        mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
-
-    virtual ~AudioPort() {}
-
-    void setName(const String8 &name) { mName = name; }
-    const String8 &getName() const { return mName; }
-
-    audio_port_type_t getType() const { return mType; }
-    audio_port_role_t getRole() const { return mRole; }
-
-    virtual const String8 getTagName() const = 0;
-
-    void setGains(const AudioGains &gains) { mGains = gains; }
-    const AudioGains &getGains() const { return mGains; }
-
-    virtual void setFlags(uint32_t flags)
-    {
-        //force direct flag if offload flag is set: offloading implies a direct output stream
-        // and all common behaviors are driven by checking only the direct flag
-        // this should normally be set appropriately in the policy configuration file
-        if (mRole == AUDIO_PORT_ROLE_SOURCE && (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-            flags |= AUDIO_OUTPUT_FLAG_DIRECT;
-        }
-        mFlags = flags;
-    }
-    uint32_t getFlags() const { return mFlags; }
-
-    virtual void attach(const sp<HwModule>& module);
-    virtual void detach();
-    bool isAttached() { return mModule != 0; }
-
-    // Audio port IDs are in a different namespace than AudioFlinger unique IDs
-    static audio_port_handle_t getNextUniqueId();
-
-    virtual void toAudioPort(struct audio_port *port) const;
-
-    virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
-
-    void addAudioProfile(const sp<AudioProfile> &profile) { mProfiles.add(profile); }
-
-    void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
-    AudioProfileVector &getAudioProfiles() { return mProfiles; }
-
-    bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
-
-    bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
-
-    // searches for an exact match
-    virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
-
-    // searches for a compatible match, currently implemented for input
-    // parameters are input|output, returned value is the best match.
-    status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
-                                         audio_channel_mask_t &channelMask,
-                                         audio_format_t &format) const
-    {
-        return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole);
-    }
-
-    void clearAudioProfiles() { return mProfiles.clearProfiles(); }
-
-    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
-
-    void pickAudioProfile(uint32_t &samplingRate,
-                          audio_channel_mask_t &channelMask,
-                          audio_format_t &format) const;
-
-    static const audio_format_t sPcmFormatCompareTable[];
-
-    static int compareFormats(audio_format_t format1, audio_format_t format2);
-
-    // Used to select an audio HAL output stream with a sample format providing the
-    // less degradation for a given AudioTrack sample format.
-    static bool isBetterFormatMatch(audio_format_t newFormat,
-                                        audio_format_t currentFormat,
-                                        audio_format_t targetFormat);
-    static uint32_t formatDistance(audio_format_t format1,
-                                   audio_format_t format2);
-    static const uint32_t kFormatDistanceMax = 4;
-
-    audio_module_handle_t getModuleHandle() const;
-    uint32_t getModuleVersionMajor() const;
-    const char *getModuleName() const;
-    sp<HwModule> getModule() const { return mModule; }
-
-    bool useInputChannelMask() const
-    {
-        return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
-                ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
-    }
-
-    inline bool isDirectOutput() const
-    {
-        return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
-                (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
-    }
-
-    void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
-    const AudioRouteVector &getRoutes() const { return mRoutes; }
-
-    void dump(String8 *dst, int spaces, bool verbose = true) const;
-
-    void log(const char* indent) const;
-
-    AudioGains mGains; // gain controllers
-
-private:
-    void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
-    void pickSamplingRate(uint32_t &rate,const SampleRateVector &samplingRates) const;
-
-    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
-    String8  mName;
-    audio_port_type_t mType;
-    audio_port_role_t mRole;
-    uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
-    AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
-    AudioRouteVector mRoutes; // Routes involving this port
-};
-
-class AudioPortConfig : public virtual RefBase
-{
-public:
-    status_t applyAudioPortConfig(const struct audio_port_config *config,
-                                  struct audio_port_config *backupConfig = NULL);
-    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const = 0;
-    virtual sp<AudioPort> getAudioPort() const = 0;
-    virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
-        return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
-                (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
-    }
-    bool hasGainController(bool canUseForVolume = false) const;
-
-    unsigned int mSamplingRate = 0u;
-    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
-    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
-    struct audio_gain_config mGain = { .index = -1 };
-    union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
-};
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
deleted file mode 100644
index b588d57..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-#include <vector>
-
-#include <system/audio.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/String8.h>
-
-#include "policy.h"
-
-namespace android {
-
-typedef SortedVector<uint32_t> SampleRateVector;
-typedef Vector<audio_format_t> FormatVector;
-
-template <typename T>
-bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
-{
-    if (left.size() != right.size()) {
-        return false;
-    }
-    for (size_t index = 0; index < right.size(); index++) {
-        if (left[index] != right[index]) {
-            return false;
-        }
-    }
-    return true;
-}
-
-template <typename T>
-bool operator!= (const SortedVector<T> &left, const SortedVector<T> &right)
-{
-    return !(left == right);
-}
-
-class ChannelsVector : public SortedVector<audio_channel_mask_t>
-{
-public:
-    ChannelsVector() = default;
-    ChannelsVector(const ChannelsVector&) = default;
-    ChannelsVector(const SortedVector<audio_channel_mask_t>& sv) :
-            SortedVector<audio_channel_mask_t>(sv) {}
-    ChannelsVector& operator=(const ChannelsVector&) = default;
-
-    // Applies audio_channel_mask_out_to_in to all elements and returns the result.
-    ChannelsVector asInMask() const;
-    // Applies audio_channel_mask_in_to_out to all elements and returns the result.
-    ChannelsVector asOutMask() const;
-};
-
-class AudioProfile : public virtual RefBase
-{
-public:
-    static sp<AudioProfile> createFullDynamic();
-
-    AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
-    AudioProfile(audio_format_t format,
-                 const ChannelsVector &channelMasks,
-                 const SampleRateVector &samplingRateCollection);
-
-    audio_format_t getFormat() const { return mFormat; }
-    const ChannelsVector &getChannels() const { return mChannelMasks; }
-    const SampleRateVector &getSampleRates() const { return mSamplingRates; }
-    void setChannels(const ChannelsVector &channelMasks);
-    void setSampleRates(const SampleRateVector &sampleRates);
-
-    void clear();
-    bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
-    bool supportsChannels(audio_channel_mask_t channels) const
-    {
-        return mChannelMasks.indexOf(channels) >= 0;
-    }
-    bool supportsRate(uint32_t rate) const { return mSamplingRates.indexOf(rate) >= 0; }
-
-    status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const;
-    status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask,
-                                        audio_channel_mask_t &updatedChannelMask,
-                                        audio_port_type_t portType,
-                                        audio_port_role_t portRole) const;
-    status_t checkCompatibleSamplingRate(uint32_t samplingRate,
-                                         uint32_t &updatedSamplingRate) const;
-
-    bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
-    bool hasValidRates() const { return !mSamplingRates.isEmpty(); }
-    bool hasValidChannels() const { return !mChannelMasks.isEmpty(); }
-
-    void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
-    bool isDynamicChannels() const { return mIsDynamicChannels; }
-
-    void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
-    bool isDynamicRate() const { return mIsDynamicRate; }
-
-    void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
-    bool isDynamicFormat() const { return mIsDynamicFormat; }
-
-    bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
-
-    void dump(String8 *dst, int spaces) const;
-
-private:
-    String8  mName;
-    audio_format_t mFormat;
-    ChannelsVector mChannelMasks;
-    SampleRateVector mSamplingRates;
-
-    bool mIsDynamicFormat = false;
-    bool mIsDynamicChannels = false;
-    bool mIsDynamicRate = false;
-};
-
-
-class AudioProfileVector : public Vector<sp<AudioProfile> >
-{
-public:
-    ssize_t add(const sp<AudioProfile> &profile);
-    // This API is intended to be used by the policy manager once retrieving capabilities
-    // for a profile with dynamic format, rate and channels attributes
-    ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
-
-    status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask,
-                               audio_format_t format) const;
-    status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask,
-                                    audio_format_t &format,
-                                    audio_port_type_t portType,
-                                    audio_port_role_t portRole) const;
-    void clearProfiles();
-    // Assuming that this profile vector contains input profiles,
-    // find the best matching config from 'outputProfiles', according to
-    // the given preferences for audio formats and channel masks.
-    // Note: std::vectors are used because specialized containers for formats
-    //       and channels can be sorted and use their own ordering.
-    status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
-            const std::vector<audio_format_t>& preferredFormats, // order: most pref -> least pref
-            const std::vector<audio_channel_mask_t>& preferredOutputChannels,
-            bool preferHigherSamplingRates,
-            audio_config_base *bestOutputConfig) const;
-
-    sp<AudioProfile> getFirstValidProfile() const;
-    sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
-    bool hasValidProfile() const { return getFirstValidProfile() != 0; }
-
-    FormatVector getSupportedFormats() const;
-    bool hasDynamicChannelsFor(audio_format_t format) const;
-    bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; }
-    bool hasDynamicProfile() const;
-    bool hasDynamicRateFor(audio_format_t format) const;
-
-    // One audio profile will be added for each format supported by Audio HAL
-    void setFormats(const FormatVector &formats);
-
-    void dump(String8 *dst, int spaces) const;
-
-private:
-    sp<AudioProfile> getProfileFor(audio_format_t format) const;
-    void setSampleRatesFor(const SampleRateVector &sampleRates, audio_format_t format);
-    void setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format);
-
-    static int compareFormats(const sp<AudioProfile> *profile1, const sp<AudioProfile> *profile2);
-};
-
-bool operator == (const AudioProfile &left, const AudioProfile &right);
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfileVectorHelper.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVectorHelper.h
new file mode 100644
index 0000000..f84bda7
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVectorHelper.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include <media/AudioProfile.h>
+#include <system/audio.h>
+
+namespace android {
+
+void sortAudioProfiles(AudioProfileVector &audioProfileVector);
+
+ssize_t addAudioProfileAndSort(AudioProfileVector &audioProfileVector,
+                               const sp<AudioProfile> &profile);
+
+// One audio profile will be added for each format supported by Audio HAL
+void addProfilesForFormats(AudioProfileVector &audioProfileVector,
+                           const FormatVector &formatVector);
+
+// This API is intended to be used by the policy manager once retrieving capabilities
+// for a profile with dynamic format, rate and channels attributes
+void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
+                                   const sp<AudioProfile> &profileToAdd);
+
+void appendAudioProfiles(AudioProfileVector &audioProfileVector,
+                         const AudioProfileVector &audioProfileVectorToAppend);
+
+status_t checkExactProfile(const AudioProfileVector &audioProfileVector,
+                           const uint32_t samplingRate,
+                           audio_channel_mask_t channelMask,
+                           audio_format_t format);
+
+status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
+                                uint32_t &samplingRate,
+                                audio_channel_mask_t &channelMask,
+                                audio_format_t &format,
+                                audio_port_type_t portType,
+                                audio_port_role_t portRole);
+
+// Assuming that this profile vector contains input profiles,
+// find the best matching config from 'outputProfiles', according to
+// the given preferences for audio formats and channel masks.
+// Note: std::vectors are used because specialized containers for formats
+//       and channels can be sorted and use their own ordering.
+status_t findBestMatchingOutputConfig(
+        const AudioProfileVector &audioProfileVector,
+        const AudioProfileVector &outputProfileVector,
+        const std::vector<audio_format_t> &preferredFormatVector, // order: most pref -> least pref
+        const std::vector<audio_channel_mask_t> &preferredOutputChannelVector,
+        bool preferHigherSamplingRates,
+        audio_config_base &bestOutputConfig);
+
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
index 0357ff4..a7def3e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
@@ -25,7 +25,7 @@
 namespace android
 {
 
-class AudioPort;
+class PolicyAudioPort;
 class DeviceDescriptor;
 
 typedef enum {
@@ -38,11 +38,11 @@
 public:
     explicit AudioRoute(audio_route_type_t type) : mType(type) {}
 
-    void setSources(const AudioPortVector &sources) { mSources = sources; }
-    const AudioPortVector &getSources() const { return mSources; }
+    void setSources(const PolicyAudioPortVector &sources) { mSources = sources; }
+    const PolicyAudioPortVector &getSources() const { return mSources; }
 
-    void setSink(const sp<AudioPort> &sink) { mSink = sink; }
-    const sp<AudioPort> &getSink() const { return mSink; }
+    void setSink(const sp<PolicyAudioPort> &sink) { mSink = sink; }
+    const sp<PolicyAudioPort> &getSink() const { return mSink; }
 
     audio_route_type_t getType() const { return mType; }
 
@@ -57,13 +57,14 @@
      * @return true if the audio route supports the connection between the sink and the source,
      * false otherwise
      */
-    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+    bool supportsPatch(const sp<PolicyAudioPort> &srcPort,
+                       const sp<PolicyAudioPort> &dstPort) const;
 
     void dump(String8 *dst, int spaces) const;
 
 private:
-    AudioPortVector mSources;
-    sp<AudioPort> mSink;
+    PolicyAudioPortVector mSources;
+    sp<PolicyAudioPort> mSink;
     audio_route_type_t mType;
 
 };
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 0d05a63..923310c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -35,6 +35,7 @@
 
 namespace android {
 
+class AudioPolicyMix;
 class DeviceDescriptor;
 class HwAudioOutputDescriptor;
 class SwAudioOutputDescriptor;
@@ -90,11 +91,12 @@
                           product_strategy_t strategy, VolumeSource volumeSource,
                           audio_output_flags_t flags,
                           bool isPreferredDeviceForExclusiveUse,
-                          std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) :
+                          std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs,
+                          wp<AudioPolicyMix> primaryMix) :
         ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId,
                          isPreferredDeviceForExclusiveUse),
         mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags),
-        mSecondaryOutputs(std::move(secondaryOutputs)) {}
+        mSecondaryOutputs(std::move(secondaryOutputs)), mPrimaryMix(primaryMix) {}
     ~TrackClientDescriptor() override = default;
 
     using ClientDescriptor::dump;
@@ -108,6 +110,9 @@
         return mSecondaryOutputs;
     };
     VolumeSource volumeSource() const { return mVolumeSource; }
+    const sp<AudioPolicyMix> getPrimaryMix() const {
+        return mPrimaryMix.promote();
+    };
 
     void setActive(bool active) override
     {
@@ -136,7 +141,7 @@
     const VolumeSource mVolumeSource;
     const audio_output_flags_t mFlags;
     const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs;
-
+    const wp<AudioPolicyMix> mPrimaryMix;
     /**
      * required for duplicating thread, prevent from removing active client from an output
      * involved in a duplication.
@@ -183,13 +188,17 @@
 {
 public:
     SourceClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_attributes_t attributes,
-                           const sp<AudioPatch>& patchDesc, const sp<DeviceDescriptor>& srcDevice,
+                           const struct audio_port_config &config,
+                           const sp<DeviceDescriptor>& srcDevice,
                            audio_stream_type_t stream, product_strategy_t strategy,
                            VolumeSource volumeSource);
+
     ~SourceClientDescriptor() override = default;
 
-    sp<AudioPatch> patchDesc() const { return mPatchDesc; }
-    sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; };
+    audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
+    void setPatchHandle(audio_patch_handle_t patchHandle) { mPatchHandle = patchHandle; }
+
+    sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
     wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
     void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
     wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
@@ -199,7 +208,7 @@
     void dump(String8 *dst, int spaces, int index) const override;
 
  private:
-    const sp<AudioPatch> mPatchDesc;
+    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
     const sp<DeviceDescriptor> mSrcDevice;
     wp<SwAudioOutputDescriptor> mSwOutput;
     wp<HwAudioOutputDescriptor> mHwOutput;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 33e506f..dd1499c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -16,7 +16,9 @@
 
 #pragma once
 
-#include "AudioPort.h"
+#include "PolicyAudioPort.h"
+#include <media/AudioContainers.h>
+#include <media/DeviceDescriptorBase.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 #include <utils/SortedVector.h>
@@ -26,21 +28,28 @@
 
 namespace android {
 
-class DeviceDescriptor : public AudioPort, public AudioPortConfig
+class AudioPolicyClientInterface;
+
+class DeviceDescriptor : public DeviceDescriptorBase,
+                         public PolicyAudioPort, public PolicyAudioPortConfig
 {
 public:
      // Note that empty name refers by convention to a generic device.
-    explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
-    DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
-            const String8 &tagName = String8(""));
+    explicit DeviceDescriptor(audio_devices_t type);
+    DeviceDescriptor(audio_devices_t type, const std::string &tagName,
+            const FormatVector &encodedFormats = FormatVector{});
+    DeviceDescriptor(audio_devices_t type, const std::string &tagName,
+            const std::string &address, const FormatVector &encodedFormats = FormatVector{});
+    DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr, const std::string &tagName = "",
+            const FormatVector &encodedFormats = FormatVector{});
 
     virtual ~DeviceDescriptor() {}
 
-    virtual const String8 getTagName() const { return mTagName; }
+    virtual void addAudioProfile(const sp<AudioProfile> &profile) {
+        addAudioProfileAndSort(mProfiles, profile);
+    }
 
-    audio_devices_t type() const { return mDeviceType; }
-    String8 address() const { return mAddress; }
-    void setAddress(const String8 &address) { mAddress = address; }
+    virtual const std::string getTagName() const { return mTagName; }
 
     const FormatVector& encodedFormats() const { return mEncodedFormats; }
 
@@ -56,36 +65,44 @@
 
     bool supportsFormat(audio_format_t format);
 
+    // PolicyAudioPortConfig
+    virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
+        return static_cast<PolicyAudioPort*>(const_cast<DeviceDescriptor*>(this));
+    }
+
     // AudioPortConfig
-    virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
+    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+                                          struct audio_port_config *backupConfig = NULL);
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
             const struct audio_port_config *srcConfig = NULL) const;
 
-    // AudioPort
+    // PolicyAudioPort
+    virtual sp<AudioPort> asAudioPort() const {
+        return static_cast<AudioPort*>(const_cast<DeviceDescriptor*>(this));
+    }
     virtual void attach(const sp<HwModule>& module);
     virtual void detach();
 
+    // AudioPort
     virtual void toAudioPort(struct audio_port *port) const;
-    virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
 
-    audio_port_handle_t getId() const;
+    void importAudioPortAndPickAudioProfile(const sp<PolicyAudioPort>& policyPort,
+                                            bool force = false);
+
+    void setEncapsulationInfoFromHal(AudioPolicyClientInterface *clientInterface);
+
     void dump(String8 *dst, int spaces, int index, bool verbose = true) const;
-    void log() const;
-    std::string toString() const;
 
 private:
-    String8 mAddress{""};
-    String8 mTagName; // Unique human readable identifier for a device port found in conf file.
-    audio_devices_t     mDeviceType;
+    std::string mTagName; // Unique human readable identifier for a device port found in conf file.
     FormatVector        mEncodedFormats;
-    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
     audio_format_t      mCurrentEncodedFormat;
 };
 
 class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
 {
 public:
-    DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
+    DeviceVector() : SortedVector() {}
     explicit DeviceVector(const sp<DeviceDescriptor>& item) : DeviceVector()
     {
         add(item);
@@ -97,13 +114,16 @@
     void remove(const DeviceVector &devices);
     ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
-    audio_devices_t types() const { return mDeviceTypes; }
+    DeviceTypeSet types() const { return mDeviceTypes; }
 
     // If 'address' is empty and 'codec' is AUDIO_FORMAT_DEFAULT, a device with a non-empty
     // address may be returned if there is no device with the specified 'type' and empty address.
     sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address,
                                    audio_format_t codec) const;
-    DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
+    DeviceVector getDevicesFromTypes(const DeviceTypeSet& types) const;
+    DeviceVector getDevicesFromType(audio_devices_t type) const {
+        return getDevicesFromTypes({type});
+    }
 
     /**
      * @brief getDeviceFromId
@@ -112,9 +132,35 @@
      * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
      */
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
-    sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
+    sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
     DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
-    audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
+
+    DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
+    sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
+
+    // Return device descriptor that is used to open an input/output stream.
+    // Null pointer will be returned if
+    //     1) this collection is empty
+    //     2) the device descriptors are not the same category(input or output)
+    //     3) there are more than one device type for input case
+    //     4) the combination of all devices is invalid for selection
+    sp<DeviceDescriptor> getDeviceForOpening() const;
+
+    // If there are devices with the given type and the devices to add is not empty,
+    // remove all the devices with the given type and add all the devices to add.
+    void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
+
+    bool containsDeviceAmongTypes(const DeviceTypeSet& deviceTypes) const {
+        return !Intersection(mDeviceTypes, deviceTypes).empty();
+    }
+
+    bool containsDeviceWithType(audio_devices_t deviceType) const {
+        return containsDeviceAmongTypes({deviceType});
+    }
+
+    bool onlyContainsDevicesWithType(audio_devices_t deviceType) const {
+        return isSingleDeviceType(mDeviceTypes, deviceType);
+    }
 
     bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
 
@@ -196,7 +242,7 @@
     {
         for (const auto &device : *this) {
             if (device->address() != "") {
-                return device->address();
+                return String8(device->address().c_str());
             }
         }
         return String8("");
@@ -208,7 +254,7 @@
 
 private:
     void refreshTypes();
-    audio_devices_t mDeviceTypes;
+    DeviceTypeSet mDeviceTypes;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index eb34da4..23f0c9a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -82,19 +82,19 @@
     status_t addInputProfile(const sp<IOProfile> &profile);
     status_t addProfile(const sp<IOProfile> &profile);
 
-    status_t addOutputProfile(const String8& name, const audio_config_t *config,
+    status_t addOutputProfile(const std::string& name, const audio_config_t *config,
             audio_devices_t device, const String8& address);
-    status_t removeOutputProfile(const String8& name);
-    status_t addInputProfile(const String8& name, const audio_config_t *config,
+    status_t removeOutputProfile(const std::string& name);
+    status_t addInputProfile(const std::string& name, const audio_config_t *config,
             audio_devices_t device, const String8& address);
-    status_t removeInputProfile(const String8& name);
+    status_t removeInputProfile(const std::string& name);
 
     audio_module_handle_t getHandle() const { return mHandle; }
     void setHandle(audio_module_handle_t handle);
 
-    sp<AudioPort> findPortByTagName(const String8 &tagName) const
+    sp<PolicyAudioPort> findPortByTagName(const std::string &tagName) const
     {
-        return mPorts.findByTagName(tagName);
+        return findByTagName(mPorts, tagName);
     }
 
     /**
@@ -106,7 +106,8 @@
      * @return true if the HwModule supports the connection between the sink and the source,
      * false otherwise
      */
-    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+    bool supportsPatch(const sp<PolicyAudioPort> &srcPort,
+                       const sp<PolicyAudioPort> &dstPort) const;
 
     // TODO remove from here (split serialization)
     void dump(String8 *dst) const;
@@ -122,7 +123,7 @@
     DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
     DeviceVector mDynamicDevices; /**< devices that can be added/removed at runtime (e.g. rsbumix)*/
     AudioRouteVector mRoutes;
-    AudioPortVector mPorts;
+    PolicyAudioPortVector mPorts;
 };
 
 class HwModuleCollection : public Vector<sp<HwModule> >
@@ -130,8 +131,8 @@
 public:
     sp<HwModule> getModuleFromName(const char *name) const;
 
-    sp<HwModule> getModuleForDeviceTypes(audio_devices_t device,
-                                         audio_format_t encodedFormat) const;
+    sp<HwModule> getModuleForDeviceType(audio_devices_t device,
+                                        audio_format_t encodedFormat) const;
 
     sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device,
                                     audio_format_t encodedFormat) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index e0b56d4..5f551d5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -16,8 +16,10 @@
 
 #pragma once
 
-#include "AudioPort.h"
 #include "DeviceDescriptor.h"
+#include "PolicyAudioPort.h"
+#include "policy.h"
+#include <media/AudioContainers.h>
 #include <utils/String8.h>
 #include <system/audio.h>
 
@@ -30,18 +32,28 @@
 // It is used by the policy manager to determine if an output or input is suitable for
 // a given use case,  open/close it accordingly and connect/disconnect audio tracks
 // to/from it.
-class IOProfile : public AudioPort
+class IOProfile : public AudioPort, public PolicyAudioPort
 {
 public:
-    IOProfile(const String8 &name, audio_port_role_t role)
+    IOProfile(const std::string &name, audio_port_role_t role)
         : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
           maxOpenCount(1),
           curOpenCount(0),
           maxActiveCount(1),
           curActiveCount(0) {}
 
+    virtual ~IOProfile() = default;
+
     // For a Profile aka MixPort, tag name and name are equivalent.
-    virtual const String8 getTagName() const { return getName(); }
+    virtual const std::string getTagName() const { return getName(); }
+
+    virtual void addAudioProfile(const sp<AudioProfile> &profile) {
+        addAudioProfileAndSort(mProfiles, profile);
+    }
+
+    virtual sp<AudioPort> asAudioPort() const {
+        return static_cast<AudioPort*>(const_cast<IOProfile*>(this));
+    }
 
     // FIXME: this is needed because shared MMAP stream clients use the same audio session.
     // Once capture clients are tracked individually and not per session this can be removed
@@ -51,7 +63,7 @@
     // flags are parsed before maxActiveCount by the serializer.
     void setFlags(uint32_t flags) override
     {
-        AudioPort::setFlags(flags);
+        PolicyAudioPort::setFlags(flags);
         if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
             maxActiveCount = 0;
         }
@@ -91,15 +103,12 @@
 
     bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
 
-    bool supportsDeviceTypes(audio_devices_t device) const
+    bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const
     {
-        if (audio_is_output_devices(device)) {
-            if (deviceSupportsEncodedFormats(device)) {
-                return mSupportedDevices.types() & device;
-            }
-            return false;
-        }
-        return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
+        const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty();
+        const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty();
+        return devicesSupported &&
+               (!areOutputDevices || devicesSupportEncodedFormats(deviceTypes));
     }
 
     /**
@@ -114,20 +123,22 @@
     bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
     {
         if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
-            return supportsDeviceTypes(device->type());
+            return supportsDeviceTypes(DeviceTypeSet({device->type()}));
         }
         return mSupportedDevices.contains(device);
     }
 
-    bool deviceSupportsEncodedFormats(audio_devices_t device) const
+    bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
     {
-        if (device == AUDIO_DEVICE_NONE) {
+        if (deviceTypes.empty()) {
             return true; // required for isOffloadSupported() check
         }
         DeviceVector deviceList =
-            mSupportedDevices.getDevicesFromTypeMask(device);
-        if (!deviceList.empty()) {
-            return deviceList.itemAt(0)->hasCurrentEncodedFormat();
+            mSupportedDevices.getDevicesFromTypes(deviceTypes);
+        for (const auto& device : deviceList) {
+            if (device->hasCurrentEncodedFormat()) {
+                return true;
+            }
         }
         return false;
     }
@@ -183,13 +194,13 @@
 class InputProfile : public IOProfile
 {
 public:
-    explicit InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
+    explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
 };
 
 class OutputProfile : public IOProfile
 {
 public:
-    explicit OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
+    explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
index d408446..fd8b81a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurves.h
@@ -16,8 +16,9 @@
 
 #pragma once
 
-#include <system/audio.h>
 #include <Volume.h>
+#include <media/AudioContainers.h>
+#include <system/audio.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 #include <vector>
@@ -33,7 +34,7 @@
     virtual void addCurrentVolumeIndex(audio_devices_t device, int index) = 0;
     virtual bool canBeMuted() const = 0;
     virtual int getVolumeIndexMin() const = 0;
-    virtual int getVolumeIndex(audio_devices_t device) const = 0;
+    virtual int getVolumeIndex(const DeviceTypeSet& device) const = 0;
     virtual int getVolumeIndexMax() const = 0;
     virtual float volIndexToDb(device_category device, int indexInUi) const = 0;
     virtual bool hasVolumeIndexForDevice(audio_devices_t device) const = 0;
diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
new file mode 100644
index 0000000..d2f6297
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include "AudioCollections.h"
+#include "AudioProfileVectorHelper.h"
+#include "HandleGenerator.h"
+#include <media/AudioGain.h>
+#include <media/AudioPort.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
+namespace android {
+
+class HwModule;
+class AudioRoute;
+
+class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
+{
+public:
+    PolicyAudioPort() : mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
+
+    virtual ~PolicyAudioPort() = default;
+
+    virtual const std::string getTagName() const = 0;
+
+    virtual sp<AudioPort> asAudioPort() const = 0;
+
+    virtual void setFlags(uint32_t flags)
+    {
+        //force direct flag if offload flag is set: offloading implies a direct output stream
+        // and all common behaviors are driven by checking only the direct flag
+        // this should normally be set appropriately in the policy configuration file
+        if (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE &&
+                (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+            flags |= AUDIO_OUTPUT_FLAG_DIRECT;
+        }
+        mFlags = flags;
+    }
+    uint32_t getFlags() const { return mFlags; }
+
+    virtual void attach(const sp<HwModule>& module);
+    virtual void detach();
+    bool isAttached() { return mModule != 0; }
+
+    // Audio port IDs are in a different namespace than AudioFlinger unique IDs
+    static audio_port_handle_t getNextUniqueId();
+
+    // searches for an exact match
+    virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
+
+    // searches for a compatible match, currently implemented for input
+    // parameters are input|output, returned value is the best match.
+    status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
+                                         audio_channel_mask_t &channelMask,
+                                         audio_format_t &format) const
+    {
+        return checkCompatibleProfile(
+                asAudioPort()->getAudioProfiles(), samplingRate, channelMask, format,
+                asAudioPort()->getType(), asAudioPort()->getRole());
+    }
+
+    void pickAudioProfile(uint32_t &samplingRate,
+                          audio_channel_mask_t &channelMask,
+                          audio_format_t &format) const;
+
+    static const audio_format_t sPcmFormatCompareTable[];
+
+    static int compareFormats(audio_format_t format1, audio_format_t format2);
+
+    // Used to select an audio HAL output stream with a sample format providing the
+    // less degradation for a given AudioTrack sample format.
+    static bool isBetterFormatMatch(audio_format_t newFormat,
+                                    audio_format_t currentFormat,
+                                    audio_format_t targetFormat);
+    static uint32_t formatDistance(audio_format_t format1,
+                                   audio_format_t format2);
+    static const uint32_t kFormatDistanceMax = 4;
+
+    audio_module_handle_t getModuleHandle() const;
+    uint32_t getModuleVersionMajor() const;
+    const char *getModuleName() const;
+    sp<HwModule> getModule() const { return mModule; }
+
+    inline bool isDirectOutput() const
+    {
+        return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) &&
+                (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
+                (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
+    }
+
+    inline bool isMmap() const
+    {
+        return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX)
+                && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
+                        ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
+                    || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) &&
+                        ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
+    }
+
+    void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
+    const AudioRouteVector &getRoutes() const { return mRoutes; }
+
+private:
+    void pickChannelMask(audio_channel_mask_t &channelMask,
+                         const ChannelMaskSet &channelMasks) const;
+    void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
+
+    uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
+    sp<HwModule> mModule;     // audio HW module exposing this I/O stream
+    AudioRouteVector mRoutes; // Routes involving this port
+};
+
+class PolicyAudioPortConfig : public virtual RefBase
+{
+public:
+    virtual ~PolicyAudioPortConfig() = default;
+
+    virtual sp<PolicyAudioPort> getPolicyAudioPort() const = 0;
+
+    status_t validationBeforeApplyConfig(const struct audio_port_config *config) const;
+
+    void applyPolicyAudioPortConfig(const struct audio_port_config *config) {
+        if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+            mFlags = config->flags;
+        }
+    }
+
+    void toPolicyAudioPortConfig(
+            struct audio_port_config *dstConfig,
+            const struct audio_port_config *srcConfig = NULL) const;
+
+
+    virtual bool hasSameHwModuleAs(const sp<PolicyAudioPortConfig>& other) const {
+        return (other.get() != nullptr) && (other->getPolicyAudioPort().get() != nullptr) &&
+                (getPolicyAudioPort().get() != nullptr) &&
+                (other->getPolicyAudioPort()->getModuleHandle() ==
+                        getPolicyAudioPort()->getModuleHandle());
+    }
+
+    union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
+};
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
deleted file mode 100644
index 0a27947..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#pragma once
-
-
-/////////////////////////////////////////////////
-//      Definitions for audio policy configuration file (audio_policy.conf)
-/////////////////////////////////////////////////
-
-#define AUDIO_HARDWARE_MODULE_ID_MAX_LEN 32
-
-#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
-#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
-
-// global configuration
-#define GLOBAL_CONFIG_TAG "global_configuration"
-
-#define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices"
-#define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device"
-#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices"
-#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled"
-#define AUDIO_HAL_VERSION_TAG "audio_hal_version"
-
-// hw modules descriptions
-#define AUDIO_HW_MODULE_TAG "audio_hw_modules"
-
-#define OUTPUTS_TAG "outputs"
-#define INPUTS_TAG "inputs"
-
-#define SAMPLING_RATES_TAG "sampling_rates"
-#define FORMATS_TAG "formats"
-#define CHANNELS_TAG "channel_masks"
-#define DEVICES_TAG "devices"
-#define FLAGS_TAG "flags"
-
-#define APM_DEVICES_TAG "devices"
-#define APM_DEVICE_TYPE "type"
-#define APM_DEVICE_ADDRESS "address"
-
-#define MIXERS_TAG "mixers"
-#define MIXER_TYPE "type"
-#define MIXER_TYPE_MUX "mux"
-#define MIXER_TYPE_MIX "mix"
-
-#define GAINS_TAG "gains"
-#define GAIN_MODE "mode"
-#define GAIN_CHANNELS "channel_mask"
-#define GAIN_MIN_VALUE "min_value_mB"
-#define GAIN_MAX_VALUE "max_value_mB"
-#define GAIN_DEFAULT_VALUE "default_value_mB"
-#define GAIN_STEP_VALUE "step_value_mB"
-#define GAIN_MIN_RAMP_MS "min_ramp_ms"
-#define GAIN_MAX_RAMP_MS "max_ramp_ms"
-
-#define DYNAMIC_VALUE_TAG "dynamic" // special value for "channel_masks", "sampling_rates" and
-                                    // "formats" in outputs descriptors indicating that supported
-                                    // values should be queried after opening the output.
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
index c90a582..cd10010 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
@@ -18,16 +18,16 @@
 //#define LOG_NDEBUG 0
 
 #include "AudioCollections.h"
-#include "AudioPort.h"
 #include "AudioRoute.h"
 #include "HwModule.h"
-#include "AudioGain.h"
+#include "PolicyAudioPort.h"
 
 namespace android {
 
-sp<AudioPort> AudioPortVector::findByTagName(const String8 &tagName) const
+sp<PolicyAudioPort> findByTagName(const PolicyAudioPortVector& policyAudioPortVector,
+                                  const std::string &tagName)
 {
-    for (const auto& port : *this) {
+    for (const auto& port : policyAudioPortVector) {
         if (port->getTagName() == tagName) {
             return port;
         }
@@ -35,15 +35,15 @@
     return nullptr;
 }
 
-void AudioRouteVector::dump(String8 *dst, int spaces) const
+void dumpAudioRouteVector(const AudioRouteVector& audioRouteVector, String8 *dst, int spaces)
 {
-    if (isEmpty()) {
+    if (audioRouteVector.isEmpty()) {
         return;
     }
-    dst->appendFormat("\n%*sAudio Routes (%zu):\n", spaces, "", size());
-    for (size_t i = 0; i < size(); i++) {
+    dst->appendFormat("\n%*sAudio Routes (%zu):\n", spaces, "", audioRouteVector.size());
+    for (size_t i = 0; i < audioRouteVector.size(); i++) {
         dst->appendFormat("%*s- Route %zu:\n", spaces, "", i + 1);
-        itemAt(i)->dump(dst, 4);
+        audioRouteVector.itemAt(i)->dump(dst, 4);
     }
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
deleted file mode 100644
index 2725870..0000000
--- a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2015 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_TAG "APM::AudioGain"
-//#define LOG_NDEBUG 0
-
-//#define VERY_VERBOSE_LOGGING
-#ifdef VERY_VERBOSE_LOGGING
-#define ALOGVV ALOGV
-#else
-#define ALOGVV(a...) do { } while(0)
-#endif
-
-#include "AudioGain.h"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include <math.h>
-
-namespace android {
-
-AudioGain::AudioGain(int index, bool useInChannelMask)
-{
-    mIndex = index;
-    mUseInChannelMask = useInChannelMask;
-    memset(&mGain, 0, sizeof(struct audio_gain));
-}
-
-void AudioGain::getDefaultConfig(struct audio_gain_config *config)
-{
-    config->index = mIndex;
-    config->mode = mGain.mode;
-    config->channel_mask = mGain.channel_mask;
-    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        config->values[0] = mGain.default_value;
-    } else {
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            config->values[i] = mGain.default_value;
-        }
-    }
-    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        config->ramp_duration_ms = mGain.min_ramp_ms;
-    }
-}
-
-status_t AudioGain::checkConfig(const struct audio_gain_config *config)
-{
-    if ((config->mode & ~mGain.mode) != 0) {
-        return BAD_VALUE;
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        if ((config->values[0] < mGain.min_value) ||
-                    (config->values[0] > mGain.max_value)) {
-            return BAD_VALUE;
-        }
-    } else {
-        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
-            return BAD_VALUE;
-        }
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(config->channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(config->channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            if ((config->values[i] < mGain.min_value) ||
-                    (config->values[i] > mGain.max_value)) {
-                return BAD_VALUE;
-            }
-        }
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
-                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
-            return BAD_VALUE;
-        }
-    }
-    return NO_ERROR;
-}
-
-void AudioGain::dump(String8 *dst, int spaces, int index) const
-{
-    dst->appendFormat("%*sGain %d:\n", spaces, "", index+1);
-    dst->appendFormat("%*s- mode: %08x\n", spaces, "", mGain.mode);
-    dst->appendFormat("%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
-    dst->appendFormat("%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
-    dst->appendFormat("%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
-    dst->appendFormat("%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
-    dst->appendFormat("%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
-    dst->appendFormat("%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
-    dst->appendFormat("%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
-}
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index a096e8f..b963121 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -22,7 +22,6 @@
 #include <policy.h>
 #include <AudioPolicyInterface.h>
 #include "AudioInputDescriptor.h"
-#include "AudioGain.h"
 #include "AudioPolicyMix.h"
 #include "HwModule.h"
 
@@ -35,8 +34,8 @@
 {
     if (profile != NULL) {
         profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
-        if (profile->mGains.size() > 0) {
-            profile->mGains[0]->getDefaultConfig(&mGain);
+        if (profile->getGains().size() > 0) {
+            profile->getGains()[0]->getDefaultConfig(&mGain);
         }
     }
 }
@@ -49,16 +48,29 @@
     return mProfile->getModuleHandle();
 }
 
-audio_port_handle_t AudioInputDescriptor::getId() const
-{
-    return mId;
-}
-
 audio_source_t AudioInputDescriptor::source() const
 {
     return getHighestPriorityAttributes().source;
 }
 
+status_t AudioInputDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
+                                                    audio_port_config *backupConfig)
+{
+    struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
+    status_t status = NO_ERROR;
+
+    toAudioPortConfig(&localBackupConfig);
+    if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
+        AudioPortConfig::applyAudioPortConfig(config, backupConfig);
+        applyPolicyAudioPortConfig(config);
+    }
+
+    if (backupConfig != NULL) {
+        *backupConfig = localBackupConfig;
+    }
+    return status;
+}
+
 void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
                                              const struct audio_port_config *srcConfig) const
 {
@@ -71,8 +83,8 @@
     }
 
     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+    toPolicyAudioPortConfig(dstConfig, srcConfig);
 
-    dstConfig->id = mId;
     dstConfig->role = AUDIO_PORT_ROLE_SINK;
     dstConfig->type = AUDIO_PORT_TYPE_MIX;
     dstConfig->ext.mix.hw_module = getModuleHandle();
@@ -213,7 +225,7 @@
     mDevice = device;
 
     ALOGV("opening input for device %s profile %p name %s",
-          mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string());
+          mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str());
 
     audio_devices_t deviceType = mDevice->type();
 
@@ -221,7 +233,7 @@
                                                   input,
                                                   &lConfig,
                                                   &deviceType,
-                                                  mDevice->address(),
+                                                  String8(mDevice->address().c_str()),
                                                   source,
                                                   flags);
     LOG_ALWAYS_FATAL_IF(mDevice->type() != deviceType,
@@ -235,7 +247,7 @@
         mSamplingRate = lConfig.sample_rate;
         mChannelMask = lConfig.channel_mask;
         mFormat = lConfig.format;
-        mId = AudioPort::getNextUniqueId();
+        mId = PolicyAudioPort::getNextUniqueId();
         mIoHandle = *input;
         mProfile->curOpenCount++;
     }
@@ -451,13 +463,13 @@
     return enabledEffects;
 }
 
-void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state)
+void AudioInputDescriptor::setAppState(audio_port_handle_t portId, app_state_t state)
 {
     RecordClientVector clients = clientsList(false /*activeOnly*/);
     RecordClientVector updatedClients;
 
     for (const auto& client : clients) {
-        if (uid == client->uid()) {
+        if (portId == client->portId()) {
             bool wasSilenced = client->isSilenced();
             client->setAppState(state);
             if (client->active() && wasSilenced != client->isSilenced()) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 8a60cf2..d6d472b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -21,27 +21,31 @@
 #include "AudioOutputDescriptor.h"
 #include "AudioPolicyMix.h"
 #include "IOProfile.h"
-#include "AudioGain.h"
 #include "Volume.h"
 #include "HwModule.h"
 #include "TypeConverter.h"
+#include <media/AudioGain.h>
 #include <media/AudioParameter.h>
 #include <media/AudioPolicy.h>
 
 // A device mask for all audio output devices that are considered "remote" when evaluating
 // active output devices in isStreamActiveRemotely()
-#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
 
 namespace android {
 
-AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
+static const DeviceTypeSet& getAllOutRemoteDevices() {
+    static const DeviceTypeSet allOutRemoteDevices = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
+    return allOutRemoteDevices;
+}
+
+AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
                                              AudioPolicyClientInterface *clientInterface)
-    : mPort(port), mClientInterface(clientInterface)
+    : mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
 {
-    if (mPort.get() != nullptr) {
-        mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
-        if (mPort->mGains.size() > 0) {
-            mPort->mGains[0]->getDefaultConfig(&mGain);
+    if (mPolicyAudioPort.get() != nullptr) {
+        mPolicyAudioPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
+        if (mPolicyAudioPort->asAudioPort()->getGains().size() > 0) {
+            mPolicyAudioPort->asAudioPort()->getGains()[0]->getDefaultConfig(&mGain);
         }
     }
 }
@@ -55,7 +59,8 @@
 
 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
 {
-    return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
+    return mPolicyAudioPort.get() != nullptr ?
+            mPolicyAudioPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
 }
 
 audio_patch_handle_t AudioOutputDescriptor::getPatchHandle() const
@@ -68,11 +73,6 @@
     mPatchHandle = handle;
 }
 
-audio_port_handle_t AudioOutputDescriptor::getId() const
-{
-    return mId;
-}
-
 bool AudioOutputDescriptor::sharesHwModuleWith(
         const sp<AudioOutputDescriptor>& outputDesc)
 {
@@ -144,7 +144,7 @@
     return false;
 }
 
-bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
+bool AudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes __unused)
 {
     return false;
 }
@@ -152,10 +152,16 @@
 bool AudioOutputDescriptor::setVolume(float volumeDb,
                                       VolumeSource volumeSource,
                                       const StreamTypeVector &/*streams*/,
-                                      audio_devices_t /*device*/,
+                                      const DeviceTypeSet& deviceTypes,
                                       uint32_t delayMs,
                                       bool force)
 {
+
+    if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) {
+        ALOGV("%s output ID %d unsupported device %s",
+                __func__, getId(), toString(deviceTypes).c_str());
+        return false;
+    }
     // We actually change the volume if:
     // - the float value returned by computeVolume() changed
     // - the force flag is set
@@ -167,9 +173,27 @@
     return false;
 }
 
-void AudioOutputDescriptor::toAudioPortConfig(
-                                                 struct audio_port_config *dstConfig,
-                                                 const struct audio_port_config *srcConfig) const
+status_t AudioOutputDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
+                                                     audio_port_config *backupConfig)
+{
+    struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
+    status_t status = NO_ERROR;
+
+    toAudioPortConfig(&localBackupConfig);
+    if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
+        AudioPortConfig::applyAudioPortConfig(config, backupConfig);
+        applyPolicyAudioPortConfig(config);
+    }
+
+    if (backupConfig != NULL) {
+        *backupConfig = localBackupConfig;
+    }
+    return status;
+}
+
+
+void AudioOutputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                              const struct audio_port_config *srcConfig) const
 {
     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
@@ -177,8 +201,8 @@
         dstConfig->config_mask |= srcConfig->config_mask;
     }
     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+    toPolicyAudioPortConfig(dstConfig, srcConfig);
 
-    dstConfig->id = mId;
     dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
     dstConfig->type = AUDIO_PORT_TYPE_MIX;
     dstConfig->ext.mix.hw_module = getModuleHandle();
@@ -188,7 +212,7 @@
 void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
 {
     // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
-    mPort->toAudioPort(port);
+    mPolicyAudioPort->asAudioPort()->toAudioPort(port);
     port->id = mId;
     port->ext.mix.hw_module = getModuleHandle();
 }
@@ -320,13 +344,13 @@
     return filteredDevices.filter(devices);
 }
 
-bool SwAudioOutputDescriptor::deviceSupportsEncodedFormats(audio_devices_t device)
+bool SwAudioOutputDescriptor::devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes)
 {
     if (isDuplicated()) {
-        return (mOutput1->deviceSupportsEncodedFormats(device)
-                    || mOutput2->deviceSupportsEncodedFormats(device));
+        return (mOutput1->devicesSupportEncodedFormats(deviceTypes)
+                    || mOutput2->devicesSupportEncodedFormats(deviceTypes));
     } else {
-       return mProfile->deviceSupportsEncodedFormats(device);
+       return mProfile->devicesSupportEncodedFormats(deviceTypes);
     }
 }
 
@@ -349,16 +373,16 @@
     AudioOutputDescriptor::setClientActive(client, active);
 }
 
-bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
+bool SwAudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes)
 {
     // unit gain if rerouting to external policy
-    if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+    if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
         if (mPolicyMix != NULL) {
             ALOGV("max gain when rerouting for output=%d", mIoHandle);
             return true;
         }
     }
-    if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
+    if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
         ALOGV("max gain when output device is telephony tx");
         return true;
     }
@@ -391,12 +415,12 @@
 
 bool SwAudioOutputDescriptor::setVolume(float volumeDb,
                                         VolumeSource vs, const StreamTypeVector &streamTypes,
-                                        audio_devices_t device,
+                                        const DeviceTypeSet& deviceTypes,
                                         uint32_t delayMs,
                                         bool force)
 {
     StreamTypeVector streams = streamTypes;
-    if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, device, delayMs, force)) {
+    if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, deviceTypes, delayMs, force)) {
         return false;
     }
     if (streams.empty()) {
@@ -406,7 +430,7 @@
         // APM loops on all group, so filter on active group to set the port gain,
         // let the other groups set the stream volume as per legacy
         // TODO: Pass in the device address and check against it.
-        if (device == devicePort->type() &&
+        if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
                 devicePort->hasGainController(true) && isActive(vs)) {
             ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
             // @todo: here we might be in trouble if the SwOutput has several active clients with
@@ -452,8 +476,11 @@
                                        audio_io_handle_t *output)
 {
     mDevices = devices;
-    const String8& address = devices.getFirstValidAddress();
-    audio_devices_t device = devices.types();
+    sp<DeviceDescriptor> device = devices.getDeviceForOpening();
+    LOG_ALWAYS_FATAL_IF(device == nullptr,
+                        "%s failed to get device descriptor for opening "
+                        "with the requested devices, all device types: %s",
+                        __func__, dumpDeviceTypes(devices.types()).c_str());
 
     audio_config_t lConfig;
     if (config == nullptr) {
@@ -483,27 +510,25 @@
     mFlags = (audio_output_flags_t)(mFlags | flags);
 
     ALOGV("opening output for device %s profile %p name %s",
-          mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string());
+          mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
 
     status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
                                                    output,
                                                    &lConfig,
-                                                   &device,
-                                                   address,
+                                                   device,
                                                    &mLatency,
                                                    mFlags);
-    LOG_ALWAYS_FATAL_IF(mDevices.types() != device,
-                        "%s openOutput returned device %08x when given device %08x",
-                        __FUNCTION__, mDevices.types(), device);
 
     if (status == NO_ERROR) {
         LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
-                            "%s openOutput returned output handle %d for device %08x",
-                            __FUNCTION__, *output, device);
+                            "%s openOutput returned output handle %d for device %s, "
+                            "selected device %s for opening",
+                            __FUNCTION__, *output, devices.toString().c_str(),
+                            device->toString().c_str());
         mSamplingRate = lConfig.sample_rate;
         mChannelMask = lConfig.channel_mask;
         mFormat = lConfig.format;
-        mId = AudioPort::getNextUniqueId();
+        mId = PolicyAudioPort::getNextUniqueId();
         mIoHandle = *output;
         mProfile->curOpenCount++;
     }
@@ -589,7 +614,7 @@
         return INVALID_OPERATION;
     }
 
-    mId = AudioPort::getNextUniqueId();
+    mId = PolicyAudioPort::getNextUniqueId();
     mIoHandle = *ioHandle;
     mOutput1 = output1;
     mOutput2 = output2;
@@ -632,12 +657,12 @@
 
 bool HwAudioOutputDescriptor::setVolume(float volumeDb,
                                         VolumeSource volumeSource, const StreamTypeVector &streams,
-                                        audio_devices_t device,
+                                        const DeviceTypeSet& deviceTypes,
                                         uint32_t delayMs,
                                         bool force)
 {
-    bool changed =
-        AudioOutputDescriptor::setVolume(volumeDb, volumeSource, streams, device, delayMs, force);
+    bool changed = AudioOutputDescriptor::setVolume(
+            volumeDb, volumeSource, streams, deviceTypes, delayMs, force);
 
     if (changed) {
       // TODO: use gain controller on source device if any to adjust volume
@@ -664,7 +689,10 @@
     for (size_t i = 0; i < this->size(); i++) {
         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
-                && ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
+                && (!(outputDesc->devices()
+                        .containsDeviceAmongTypes(getAllOutRemoteDevices())
+                        || outputDesc->devices()
+                            .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)))) {
             return true;
         }
     }
@@ -676,7 +704,7 @@
     nsecs_t sysTime = systemTime();
     for (size_t i = 0; i < size(); i++) {
         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
-        if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+        if (outputDesc->devices().containsDeviceAmongTypes(getAllOutRemoteDevices()) &&
                 outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
             // do not consider re routing (when the output is going to a dynamic policy)
             // as "remote playback"
@@ -696,7 +724,11 @@
         const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
         if (desc->sharesHwModuleWith(otherDesc) &&
                 otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
-            return true;
+            if (desc == otherDesc
+                    || !otherDesc->devices()
+                            .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+                return true;
+            }
         }
     }
     return false;
@@ -707,9 +739,8 @@
     for (size_t i = 0; i < size(); i++) {
         sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
         if (!outputDesc->isDuplicated() &&
-             outputDesc->devices().types()  & AUDIO_DEVICE_OUT_ALL_A2DP &&
-             outputDesc->deviceSupportsEncodedFormats(
-                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
+             outputDesc->devices().containsDeviceAmongTypes(getAudioDeviceOutAllA2dpSet()) &&
+             outputDesc->devicesSupportEncodedFormats(getAudioDeviceOutAllA2dpSet())) {
             return this->keyAt(i);
         }
     }
@@ -725,7 +756,7 @@
         sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
 
         for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
-            if (outputProfile->supportsDeviceTypes(AUDIO_DEVICE_OUT_ALL_A2DP)) {
+            if (outputProfile->supportsDeviceTypes(getAudioDeviceOutAllA2dpSet())) {
                 return true;
             }
         }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index 3a4db90..d79110a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -18,7 +18,6 @@
 //#define LOG_NDEBUG 0
 
 #include "AudioPatch.h"
-#include "AudioGain.h"
 #include "TypeConverter.h"
 
 #include <log/log.h>
@@ -27,10 +26,9 @@
 namespace android {
 
 AudioPatch::AudioPatch(const struct audio_patch *patch, uid_t uid) :
-    mHandle(HandleGenerator<audio_patch_handle_t>::getNextHandle()),
     mPatch(*patch),
-    mUid(uid),
-    mAfPatchHandle(AUDIO_PATCH_HANDLE_NONE)
+    mHandle(HandleGenerator<audio_patch_handle_t>::getNextHandle()),
+    mUid(uid)
 {
 }
 
@@ -69,7 +67,7 @@
     add(handle, patch);
     ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
             "sink handle %d",
-          handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
+          handle, patch->getAfHandle(), patch->mPatch.num_sources, patch->mPatch.num_sinks,
           patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
     return NO_ERROR;
 }
@@ -82,7 +80,7 @@
         ALOGW("removeAudioPatch() patch %d not in", handle);
         return ALREADY_EXISTS;
     }
-    ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle);
+    ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->getAfHandle());
     removeItemsAt(index);
     return NO_ERROR;
 }
@@ -124,7 +122,7 @@
         }
         if (patchesWritten < patchesMax) {
             patches[patchesWritten] = patch->mPatch;
-            patches[patchesWritten++].id = patch->mHandle;
+            patches[patchesWritten++].id = patch->getHandle();
         }
         (*num_patches)++;
         ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index c42923a..b6de4be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -20,16 +20,15 @@
 #include "AudioPolicyMix.h"
 #include "TypeConverter.h"
 #include "HwModule.h"
-#include "AudioPort.h"
+#include "PolicyAudioPort.h"
 #include "IOProfile.h"
-#include "AudioGain.h"
 #include <AudioOutputDescriptor.h>
 
 namespace android {
 
 void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
 {
-    dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1);
+    dst->appendFormat("%*sAudio Policy Mix %d (%p):\n", spaces, "", index + 1, this);
     std::string mixTypeLiteral;
     if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) {
         ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType);
@@ -45,6 +44,9 @@
 
     dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());
 
+    dst->appendFormat("%*s- output: %d\n", spaces, "",
+            mOutput == nullptr ? 0 : mOutput->mIoHandle);
+
     int indexCriterion = 0;
     for (const auto &criterion : mCriteria) {
         dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++);
@@ -61,6 +63,9 @@
         case RULE_MATCH_UID:
             ruleValue = std::to_string(criterion.mValue.mUid);
             break;
+        case RULE_MATCH_USERID:
+            ruleValue = std::to_string(criterion.mValue.mUserId);
+            break;
         default:
             unknownRule = true;
         }
@@ -148,11 +153,11 @@
 status_t AudioPolicyMixCollection::getOutputForAttr(
         const audio_attributes_t& attributes, uid_t uid,
         audio_output_flags_t flags,
-        sp<SwAudioOutputDescriptor> &primaryDesc,
-        std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
+        sp<AudioPolicyMix> &primaryMix,
+        std::vector<sp<AudioPolicyMix>> *secondaryMixes)
 {
     ALOGV("getOutputForAttr() querying %zu mixes:", size());
-    primaryDesc = 0;
+    primaryMix.clear();
     for (size_t i = 0; i < size(); i++) {
         sp<AudioPolicyMix> policyMix = itemAt(i);
         const bool primaryOutputMix = !is_mix_loopback_render(policyMix->mRouteFlags);
@@ -167,13 +172,7 @@
             return INVALID_OPERATION;
         }
 
-        sp<SwAudioOutputDescriptor> policyDesc = policyMix->getOutput();
-        if (!policyDesc) {
-            ALOGV("%s: Skiping %zu: Mix has no output", __func__, i);
-            continue;
-        }
-
-        if (primaryOutputMix && primaryDesc != 0) {
+        if (primaryOutputMix && primaryMix != nullptr) {
             ALOGV("%s: Skiping %zu: Primary output already found", __func__, i);
             continue; // Primary output already found
         }
@@ -189,16 +188,13 @@
             case MixMatchStatus::MATCH:;
         }
 
-        policyDesc->mPolicyMix = policyMix;
         if (primaryOutputMix) {
-            primaryDesc = policyDesc;
+            primaryMix = policyMix;
             ALOGV("%s: Mix %zu: set primary desc", __func__, i);
         } else {
-            if (policyDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) {
-                ALOGV("%s: Mix %zu ignored as secondaryOutput because not opened yet", __func__, i);
-            } else {
-                ALOGV("%s: Add a secondary desc %zu", __func__, i);
-                secondaryDescs->push_back(policyDesc);
+            ALOGV("%s: Add a secondary desc %zu", __func__, i);
+            if (secondaryMixes != nullptr) {
+                secondaryMixes->push_back(policyMix);
             }
         }
     }
@@ -220,12 +216,20 @@
                 hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
                 return MixMatchStatus::NO_MATCH;
             }
+            if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION &&
+                !mix->mVoiceCommunicationCaptureAllowed) {
+                return MixMatchStatus::NO_MATCH;
+            }
             if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
                   attributes.usage == AUDIO_USAGE_MEDIA ||
-                  attributes.usage == AUDIO_USAGE_GAME)) {
+                  attributes.usage == AUDIO_USAGE_GAME ||
+                  attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION)) {
                 return MixMatchStatus::NO_MATCH;
             }
         }
+
+        int userId = (int) multiuser_get_user_id(uid);
+
         // TODO if adding more player rules (currently only 2), make rule handling "generic"
         //      as there is no difference in the treatment of usage- or uid-based rules
         bool hasUsageMatchRules = false;
@@ -238,6 +242,12 @@
         bool uidMatchFound = false;
         bool uidExclusionFound = false;
 
+        bool hasUserIdExcludeRules = false;
+        bool userIdExclusionFound = false;
+        bool hasUserIdMatchRules = false;
+        bool userIdMatchFound = false;
+
+
         bool hasAddrMatch = false;
 
         // iterate over all mix criteria to list what rules this mix contains
@@ -289,6 +299,24 @@
                     uidExclusionFound = true;
                 }
                 break;
+            case RULE_MATCH_USERID:
+                ALOGV("\tmix has RULE_MATCH_USERID for userId %d",
+                    mix->mCriteria[j].mValue.mUserId);
+                hasUserIdMatchRules = true;
+                if (mix->mCriteria[j].mValue.mUserId == userId) {
+                    // found one userId match against all allowed userIds
+                    userIdMatchFound = true;
+                }
+                break;
+            case RULE_EXCLUDE_USERID:
+                ALOGV("\tmix has RULE_EXCLUDE_USERID for userId %d",
+                    mix->mCriteria[j].mValue.mUserId);
+                hasUserIdExcludeRules = true;
+                if (mix->mCriteria[j].mValue.mUserId == userId) {
+                    // found this userId is to be excluded
+                    userIdExclusionFound = true;
+                }
+                break;
             default:
                 break;
             }
@@ -305,12 +333,17 @@
                         " and RULE_EXCLUDE_UID in mix %zu", mixIndex);
                 return MixMatchStatus::INVALID_MIX;
             }
-
-            if ((hasUsageExcludeRules && usageExclusionFound)
-                    || (hasUidExcludeRules && uidExclusionFound)) {
-                break; // stop iterating on criteria because an exclusion was found (will fail)
+            if (hasUserIdMatchRules && hasUserIdExcludeRules) {
+                ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_USERID"
+                        " and RULE_EXCLUDE_USERID in mix %zu", mixIndex);
+                    return MixMatchStatus::INVALID_MIX;
             }
 
+            if ((hasUsageExcludeRules && usageExclusionFound)
+                    || (hasUidExcludeRules && uidExclusionFound)
+                    || (hasUserIdExcludeRules && userIdExclusionFound)) {
+                break; // stop iterating on criteria because an exclusion was found (will fail)
+            }
         }//iterate on mix criteria
 
         // determine if exiting on success (or implicit failure as desc is 0)
@@ -318,7 +351,9 @@
                 !((hasUsageExcludeRules && usageExclusionFound) ||
                   (hasUsageMatchRules && !usageMatchFound)  ||
                   (hasUidExcludeRules && uidExclusionFound) ||
-                  (hasUidMatchRules && !uidMatchFound))) {
+                  (hasUidMatchRules && !uidMatchFound) ||
+                  (hasUserIdExcludeRules && userIdExclusionFound) ||
+                  (hasUserIdMatchRules && !userIdMatchFound))) {
             ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
             return MixMatchStatus::MATCH;
         }
@@ -456,9 +491,9 @@
         }
         // check if this mix goes to a device in the list of devices
         bool deviceMatch = false;
+        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
         for (size_t j = 0; j < devices.size(); j++) {
-            if (devices[j].mType == mix->mDeviceType
-                    && devices[j].mAddress == mix->mDeviceAddress) {
+            if (mixDevice.equals(devices[j])) {
                 deviceMatch = true;
                 break;
             }
@@ -523,7 +558,110 @@
             }
         }
         if (ruleAllowsUid) {
-            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
+            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::setUserIdDeviceAffinities(int userId,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    // verify feasibility: for each player mix: if it already contains a
+    //    "match userId" rule for this userId, return an error
+    //    (adding a userId-device affinity would result in contradictory rules)
+    for (size_t i = 0; i < size(); i++) {
+        const AudioPolicyMix* mix = itemAt(i).get();
+        if (!mix->isDeviceAffinityCompatible()) {
+            continue;
+        }
+        if (mix->hasUserIdRule(true /*match*/, userId)) {
+            return INVALID_OPERATION;
+        }
+    }
+
+    // remove existing rules for this userId
+    removeUserIdDeviceAffinities(userId);
+
+    // for each player mix:
+    //   IF    device is not a target for the mix,
+    //     AND it doesn't have a "match userId" rule
+    //   THEN add a rule to exclude the userId
+    for (size_t i = 0; i < size(); i++) {
+        const AudioPolicyMix *mix = itemAt(i).get();
+        if (!mix->isDeviceAffinityCompatible()) {
+            continue;
+        }
+        // check if this mix goes to a device in the list of devices
+        bool deviceMatch = false;
+        const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+        for (size_t j = 0; j < devices.size(); j++) {
+            if (mixDevice.equals(devices[j])) {
+                deviceMatch = true;
+                break;
+            }
+        }
+        if (!deviceMatch && !mix->hasMatchUserIdRule()) {
+            // this mix doesn't go to one of the listed devices for the given userId,
+            // and it's not already restricting the mix on a userId,
+            // modify its rules to exclude the userId
+            if (!mix->hasUserIdRule(false /*match*/, userId)) {
+                // no need to do it again if userId is already excluded
+                mix->setExcludeUserId(userId);
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) {
+    // for each player mix: remove existing rules that match or exclude this userId
+    for (size_t i = 0; i < size(); i++) {
+        bool foundUserIdRule = false;
+        const AudioPolicyMix *mix = itemAt(i).get();
+        if (!mix->isDeviceAffinityCompatible()) {
+            continue;
+        }
+        std::vector<size_t> criteriaToRemove;
+        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+            const uint32_t rule = mix->mCriteria[j].mRule;
+            // is this rule excluding the userId? (not considering userId match rules
+            // as those are not used for userId-device affinity)
+            if (rule == RULE_EXCLUDE_USERID
+                    && userId == mix->mCriteria[j].mValue.mUserId) {
+                foundUserIdRule = true;
+                criteriaToRemove.insert(criteriaToRemove.begin(), j);
+            }
+        }
+        if (foundUserIdRule) {
+            for (size_t j = 0; j < criteriaToRemove.size(); j++) {
+                mix->mCriteria.removeAt(criteriaToRemove[j]);
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getDevicesForUserId(int userId,
+        Vector<AudioDeviceTypeAddr>& devices) const {
+    // for each player mix:
+    // find rules that don't exclude this userId, and add the device to the list
+    for (size_t i = 0; i < size(); i++) {
+        bool ruleAllowsUserId = true;
+        const AudioPolicyMix *mix = itemAt(i).get();
+        if (mix->mMixType != MIX_TYPE_PLAYERS) {
+            continue;
+        }
+        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+            const uint32_t rule = mix->mCriteria[j].mRule;
+            if (rule == RULE_EXCLUDE_USERID
+                    && userId == mix->mCriteria[j].mValue.mUserId) {
+                ruleAllowsUserId = false;
+                break;
+            }
+        }
+        if (ruleAllowsUserId) {
+            devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
         }
     }
     return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
deleted file mode 100644
index c11490a..0000000
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Copyright (C) 2015 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_TAG "APM::AudioPort"
-//#define LOG_NDEBUG 0
-#include "TypeConverter.h"
-#include "AudioPort.h"
-#include "HwModule.h"
-#include "AudioGain.h"
-#include <policy.h>
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-namespace android {
-
-// --- AudioPort class implementation
-void AudioPort::attach(const sp<HwModule>& module)
-{
-    ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string());
-    mModule = module;
-}
-
-void AudioPort::detach()
-{
-    mModule = nullptr;
-}
-
-// Note that is a different namespace than AudioFlinger unique IDs
-audio_port_handle_t AudioPort::getNextUniqueId()
-{
-    return getNextHandle();
-}
-
-audio_module_handle_t AudioPort::getModuleHandle() const
-{
-    return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
-}
-
-uint32_t AudioPort::getModuleVersionMajor() const
-{
-    return mModule != 0 ? mModule->getHalVersionMajor() : 0;
-}
-
-const char *AudioPort::getModuleName() const
-{
-    return mModule != 0 ? mModule->getName() : "invalid module";
-}
-
-void AudioPort::toAudioPort(struct audio_port *port) const
-{
-    // TODO: update this function once audio_port structure reflects the new profile definition.
-    // For compatibility reason: flatening the AudioProfile into audio_port structure.
-    SortedVector<audio_format_t> flatenedFormats;
-    SampleRateVector flatenedRates;
-    ChannelsVector flatenedChannels;
-    for (const auto& profile : mProfiles) {
-        if (profile->isValid()) {
-            audio_format_t formatToExport = profile->getFormat();
-            const SampleRateVector &ratesToExport = profile->getSampleRates();
-            const ChannelsVector &channelsToExport = profile->getChannels();
-
-            if (flatenedFormats.indexOf(formatToExport) < 0) {
-                flatenedFormats.add(formatToExport);
-            }
-            for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
-                uint32_t rate = ratesToExport[rateIndex];
-                if (flatenedRates.indexOf(rate) < 0) {
-                    flatenedRates.add(rate);
-                }
-            }
-            for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
-                audio_channel_mask_t channels = channelsToExport[chanIndex];
-                if (flatenedChannels.indexOf(channels) < 0) {
-                    flatenedChannels.add(channels);
-                }
-            }
-            if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
-                    flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
-                    flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
-                ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
-                return;
-            }
-        }
-    }
-    port->role = mRole;
-    port->type = mType;
-    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
-    port->num_sample_rates = flatenedRates.size();
-    port->num_channel_masks = flatenedChannels.size();
-    port->num_formats = flatenedFormats.size();
-    for (size_t i = 0; i < flatenedRates.size(); i++) {
-        port->sample_rates[i] = flatenedRates[i];
-    }
-    for (size_t i = 0; i < flatenedChannels.size(); i++) {
-        port->channel_masks[i] = flatenedChannels[i];
-    }
-    for (size_t i = 0; i < flatenedFormats.size(); i++) {
-        port->formats[i] = flatenedFormats[i];
-    }
-
-    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
-
-    uint32_t i;
-    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
-        port->gains[i] = mGains[i]->getGain();
-    }
-    port->num_gains = i;
-}
-
-void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
-{
-    for (const auto& profileToImport : port->mProfiles) {
-        if (profileToImport->isValid()) {
-            // Import only valid port, i.e. valid format, non empty rates and channels masks
-            bool hasSameProfile = false;
-            for (const auto& profile : mProfiles) {
-                if (*profile == *profileToImport) {
-                    // never import a profile twice
-                    hasSameProfile = true;
-                    break;
-                }
-            }
-            if (hasSameProfile) { // never import a same profile twice
-                continue;
-            }
-            addAudioProfile(profileToImport);
-        }
-    }
-}
-
-status_t AudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
-{
-    status_t status = NO_ERROR;
-    auto config_mask = config->config_mask;
-    if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
-        config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
-        status = checkGain(&config->gain, config->gain.index);
-        if (status != NO_ERROR) {
-            return status;
-        }
-    }
-    if (config_mask != 0) {
-        // TODO should we check sample_rate / channel_mask / format separately?
-        status = mProfiles.checkExactProfile(config->sample_rate,
-                                             config->channel_mask,
-                                             config->format);
-    }
-    return status;
-}
-
-void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
-{
-    pickedRate = 0;
-    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
-    // channel count / sampling rate combination chosen will be supported by the connected
-    // sink
-    if (isDirectOutput()) {
-        uint32_t samplingRate = UINT_MAX;
-        for (size_t i = 0; i < samplingRates.size(); i ++) {
-            if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
-                samplingRate = samplingRates[i];
-            }
-        }
-        pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
-    } else {
-        uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
-
-        // For mixed output and inputs, use max mixer sampling rates. Do not
-        // limit sampling rate otherwise
-        // For inputs, also see checkCompatibleSamplingRate().
-        if (mType != AUDIO_PORT_TYPE_MIX) {
-            maxRate = UINT_MAX;
-        }
-        // TODO: should mSamplingRates[] be ordered in terms of our preference
-        // and we return the first (and hence most preferred) match?  This is of concern if
-        // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
-        for (size_t i = 0; i < samplingRates.size(); i ++) {
-            if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
-                pickedRate = samplingRates[i];
-            }
-        }
-    }
-}
-
-void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
-                                const ChannelsVector &channelMasks) const
-{
-    pickedChannelMask = AUDIO_CHANNEL_NONE;
-    // For direct outputs, pick minimum channel count: this helps ensuring that the
-    // channel count / sampling rate combination chosen will be supported by the connected
-    // sink
-    if (isDirectOutput()) {
-        uint32_t channelCount = UINT_MAX;
-        for (size_t i = 0; i < channelMasks.size(); i ++) {
-            uint32_t cnlCount;
-            if (useInputChannelMask()) {
-                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
-            } else {
-                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
-            }
-            if ((cnlCount < channelCount) && (cnlCount > 0)) {
-                pickedChannelMask = channelMasks[i];
-                channelCount = cnlCount;
-            }
-        }
-    } else {
-        uint32_t channelCount = 0;
-        uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
-
-        // For mixed output and inputs, use max mixer channel count. Do not
-        // limit channel count otherwise
-        if (mType != AUDIO_PORT_TYPE_MIX) {
-            maxCount = UINT_MAX;
-        }
-        for (size_t i = 0; i < channelMasks.size(); i ++) {
-            uint32_t cnlCount;
-            if (useInputChannelMask()) {
-                cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
-            } else {
-                cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
-            }
-            if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
-                pickedChannelMask = channelMasks[i];
-                channelCount = cnlCount;
-            }
-        }
-    }
-}
-
-/* format in order of increasing preference */
-const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
-        AUDIO_FORMAT_DEFAULT,
-        AUDIO_FORMAT_PCM_16_BIT,
-        AUDIO_FORMAT_PCM_8_24_BIT,
-        AUDIO_FORMAT_PCM_24_BIT_PACKED,
-        AUDIO_FORMAT_PCM_32_BIT,
-        AUDIO_FORMAT_PCM_FLOAT,
-};
-
-int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
-{
-    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
-    // compressed format and better than any PCM format. This is by design of pickFormat()
-    if (!audio_is_linear_pcm(format1)) {
-        if (!audio_is_linear_pcm(format2)) {
-            return 0;
-        }
-        return 1;
-    }
-    if (!audio_is_linear_pcm(format2)) {
-        return -1;
-    }
-
-    int index1 = -1, index2 = -1;
-    for (size_t i = 0;
-            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
-            i ++) {
-        if (sPcmFormatCompareTable[i] == format1) {
-            index1 = i;
-        }
-        if (sPcmFormatCompareTable[i] == format2) {
-            index2 = i;
-        }
-    }
-    // format1 not found => index1 < 0 => format2 > format1
-    // format2 not found => index2 < 0 => format2 < format1
-    return index1 - index2;
-}
-
-uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
-{
-    if (format1 == format2) {
-        return 0;
-    }
-    if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
-        return kFormatDistanceMax;
-    }
-    int diffBytes = (int)audio_bytes_per_sample(format1) -
-            audio_bytes_per_sample(format2);
-
-    return abs(diffBytes);
-}
-
-bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
-                                    audio_format_t currentFormat,
-                                    audio_format_t targetFormat)
-{
-    return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
-}
-
-void AudioPort::pickAudioProfile(uint32_t &samplingRate,
-                                 audio_channel_mask_t &channelMask,
-                                 audio_format_t &format) const
-{
-    format = AUDIO_FORMAT_DEFAULT;
-    samplingRate = 0;
-    channelMask = AUDIO_CHANNEL_NONE;
-
-    // special case for uninitialized dynamic profile
-    if (!mProfiles.hasValidProfile()) {
-        return;
-    }
-    audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
-    // For mixed output and inputs, use best mixer output format.
-    // Do not limit format otherwise
-    if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
-        bestFormat = AUDIO_FORMAT_INVALID;
-    }
-
-    for (size_t i = 0; i < mProfiles.size(); i ++) {
-        if (!mProfiles[i]->isValid()) {
-            continue;
-        }
-        audio_format_t formatToCompare = mProfiles[i]->getFormat();
-        if ((compareFormats(formatToCompare, format) > 0) &&
-                (compareFormats(formatToCompare, bestFormat) <= 0)) {
-            uint32_t pickedSamplingRate = 0;
-            audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
-            pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
-            pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
-
-            if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
-                    && pickedSamplingRate != 0) {
-                format = formatToCompare;
-                channelMask = pickedChannelMask;
-                samplingRate = pickedSamplingRate;
-                // TODO: shall we return on the first one or still trying to pick a better Profile?
-            }
-        }
-    }
-    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
-          samplingRate, channelMask, format);
-}
-
-status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
-{
-    if (index < 0 || (size_t)index >= mGains.size()) {
-        return BAD_VALUE;
-    }
-    return mGains[index]->checkConfig(gainConfig);
-}
-
-void AudioPort::dump(String8 *dst, int spaces, bool verbose) const
-{
-    if (!mName.isEmpty()) {
-        dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
-    }
-    if (verbose) {
-        mProfiles.dump(dst, spaces);
-
-        if (mGains.size() != 0) {
-            dst->appendFormat("%*s- gains:\n", spaces, "");
-            for (size_t i = 0; i < mGains.size(); i++) {
-                mGains[i]->dump(dst, spaces + 2, i);
-            }
-        }
-    }
-}
-
-void AudioPort::log(const char* indent) const
-{
-    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
-}
-
-// --- AudioPortConfig class implementation
-
-status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
-                                               struct audio_port_config *backupConfig)
-{
-    struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
-    status_t status = NO_ERROR;
-
-    toAudioPortConfig(&localBackupConfig);
-
-    sp<AudioPort> audioport = getAudioPort();
-    if (audioport == 0) {
-        status = NO_INIT;
-        goto exit;
-    }
-    status = audioport->checkExactAudioProfile(config);
-    if (status != NO_ERROR) {
-        goto exit;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
-        mSamplingRate = config->sample_rate;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
-        mChannelMask = config->channel_mask;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
-        mFormat = config->format;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
-        mGain = config->gain;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
-        mFlags = config->flags;
-    }
-
-exit:
-    if (status != NO_ERROR) {
-        applyAudioPortConfig(&localBackupConfig);
-    }
-    if (backupConfig != NULL) {
-        *backupConfig = localBackupConfig;
-    }
-    return status;
-}
-
-namespace {
-
-template<typename T>
-void updateField(
-        const T& portConfigField, T audio_port_config::*port_config_field,
-        struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
-        unsigned int configMask, T defaultValue)
-{
-    if (dstConfig->config_mask & configMask) {
-        if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
-            dstConfig->*port_config_field = srcConfig->*port_config_field;
-        } else {
-            dstConfig->*port_config_field = portConfigField;
-        }
-    } else {
-        dstConfig->*port_config_field = defaultValue;
-    }
-}
-
-} // namespace
-
-void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
-                                        const struct audio_port_config *srcConfig) const
-{
-    updateField(mSamplingRate, &audio_port_config::sample_rate,
-            dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
-    updateField(mChannelMask, &audio_port_config::channel_mask,
-            dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
-            (audio_channel_mask_t)AUDIO_CHANNEL_NONE);
-    updateField(mFormat, &audio_port_config::format,
-            dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
-
-    sp<AudioPort> audioport = getAudioPort();
-    if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
-        dstConfig->gain = mGain;
-        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
-                && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
-            dstConfig->gain = srcConfig->gain;
-        }
-    } else {
-        dstConfig->gain.index = -1;
-    }
-    if (dstConfig->gain.index != -1) {
-        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
-    } else {
-        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
-    }
-
-    updateField(mFlags, &audio_port_config::flags,
-            dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
-}
-
-bool AudioPortConfig::hasGainController(bool canUseForVolume) const
-{
-    sp<AudioPort> audioport = getAudioPort();
-    if (audioport == nullptr) {
-        return false;
-    }
-    return canUseForVolume ? audioport->getGains().canUseForVolume()
-                           : audioport->getGains().size() > 0;
-}
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
deleted file mode 100644
index 69d6b0c..0000000
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (C) 2015 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 <algorithm>
-#include <set>
-#include <string>
-
-#define LOG_TAG "APM::AudioProfile"
-//#define LOG_NDEBUG 0
-
-#include <media/AudioResamplerPublic.h>
-#include <utils/Errors.h>
-
-#include "AudioGain.h"
-#include "AudioPort.h"
-#include "AudioProfile.h"
-#include "HwModule.h"
-#include "TypeConverter.h"
-
-namespace android {
-
-ChannelsVector ChannelsVector::asInMask() const
-{
-    ChannelsVector inMaskVector;
-    for (const auto& channel : *this) {
-        if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
-            inMaskVector.add(audio_channel_mask_out_to_in(channel));
-        }
-    }
-    return inMaskVector;
-}
-
-ChannelsVector ChannelsVector::asOutMask() const
-{
-    ChannelsVector outMaskVector;
-    for (const auto& channel : *this) {
-        if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
-            outMaskVector.add(audio_channel_mask_in_to_out(channel));
-        }
-    }
-    return outMaskVector;
-}
-
-bool operator == (const AudioProfile &left, const AudioProfile &compareTo)
-{
-    return (left.getFormat() == compareTo.getFormat()) &&
-            (left.getChannels() == compareTo.getChannels()) &&
-            (left.getSampleRates() == compareTo.getSampleRates());
-}
-
-static AudioProfile* createFullDynamicImpl()
-{
-    AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat,
-            ChannelsVector(), SampleRateVector());
-    dynamicProfile->setDynamicFormat(true);
-    dynamicProfile->setDynamicChannels(true);
-    dynamicProfile->setDynamicRate(true);
-    return dynamicProfile;
-}
-
-// static
-sp<AudioProfile> AudioProfile::createFullDynamic()
-{
-    static sp<AudioProfile> dynamicProfile = createFullDynamicImpl();
-    return dynamicProfile;
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
-                           audio_channel_mask_t channelMasks,
-                           uint32_t samplingRate) :
-        mName(String8("")),
-        mFormat(format)
-{
-    mChannelMasks.add(channelMasks);
-    mSamplingRates.add(samplingRate);
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
-                           const ChannelsVector &channelMasks,
-                           const SampleRateVector &samplingRateCollection) :
-        mName(String8("")),
-        mFormat(format),
-        mChannelMasks(channelMasks),
-        mSamplingRates(samplingRateCollection) {}
-
-void AudioProfile::setChannels(const ChannelsVector &channelMasks)
-{
-    if (mIsDynamicChannels) {
-        mChannelMasks = channelMasks;
-    }
-}
-
-void AudioProfile::setSampleRates(const SampleRateVector &sampleRates)
-{
-    if (mIsDynamicRate) {
-        mSamplingRates = sampleRates;
-    }
-}
-
-void AudioProfile::clear()
-{
-    if (mIsDynamicChannels) {
-        mChannelMasks.clear();
-    }
-    if (mIsDynamicRate) {
-        mSamplingRates.clear();
-    }
-}
-
-status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
-                                  audio_format_t format) const
-{
-    if (audio_formats_match(format, mFormat) &&
-            supportsChannels(channelMask) &&
-            supportsRate(samplingRate)) {
-        return NO_ERROR;
-    }
-    return BAD_VALUE;
-}
-
-status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
-                                                   uint32_t &updatedSamplingRate) const
-{
-    ALOG_ASSERT(samplingRate > 0);
-
-    if (mSamplingRates.isEmpty()) {
-        updatedSamplingRate = samplingRate;
-        return NO_ERROR;
-    }
-
-    // Search for the closest supported sampling rate that is above (preferred)
-    // or below (acceptable) the desired sampling rate, within a permitted ratio.
-    // The sampling rates are sorted in ascending order.
-    size_t orderOfDesiredRate = mSamplingRates.orderOf(samplingRate);
-
-    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
-    if (orderOfDesiredRate < mSamplingRates.size()) {
-        uint32_t candidate = mSamplingRates[orderOfDesiredRate];
-        if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
-            updatedSamplingRate = candidate;
-            return NO_ERROR;
-        }
-    }
-    // But if we have to up-sample from a lower sampling rate, that's OK.
-    if (orderOfDesiredRate != 0) {
-        uint32_t candidate = mSamplingRates[orderOfDesiredRate - 1];
-        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
-            updatedSamplingRate = candidate;
-            return NO_ERROR;
-        }
-    }
-    // leave updatedSamplingRate unmodified
-    return BAD_VALUE;
-}
-
-status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
-                                                  audio_channel_mask_t &updatedChannelMask,
-                                                  audio_port_type_t portType,
-                                                  audio_port_role_t portRole) const
-{
-    if (mChannelMasks.isEmpty()) {
-        updatedChannelMask = channelMask;
-        return NO_ERROR;
-    }
-    const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK;
-    const bool isIndex = audio_channel_mask_get_representation(channelMask)
-            == AUDIO_CHANNEL_REPRESENTATION_INDEX;
-    const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
-    int bestMatch = 0;
-    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
-        audio_channel_mask_t supported = mChannelMasks[i];
-        if (supported == channelMask) {
-            // Exact matches always taken.
-            updatedChannelMask = channelMask;
-            return NO_ERROR;
-        }
-
-        // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
-        if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
-            // Approximate (best) match:
-            // The match score measures how well the supported channel mask matches the
-            // desired mask, where increasing-is-better.
-            //
-            // TODO: Some tweaks may be needed.
-            // Should be a static function of the data processing library.
-            //
-            // In priority:
-            // match score = 1000 if legacy channel conversion equivalent (always prefer this)
-            // OR
-            // match score += 100 if the channel mask representations match
-            // match score += number of channels matched.
-            // match score += 100 if the channel mask representations DO NOT match
-            //   but the profile has positional channel mask and less than 2 channels.
-            //   This is for audio HAL convention to not list index masks for less than 2 channels
-            //
-            // If there are no matched channels, the mask may still be accepted
-            // but the playback or record will be silent.
-            const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
-                    == AUDIO_CHANNEL_REPRESENTATION_INDEX);
-            const uint32_t supportedChannelCount = audio_channel_count_from_in_mask(supported);
-            int match;
-            if (isIndex && isSupportedIndex) {
-                // index equivalence
-                match = 100 + __builtin_popcount(
-                        audio_channel_mask_get_bits(channelMask)
-                            & audio_channel_mask_get_bits(supported));
-            } else if (isIndex && !isSupportedIndex) {
-                const uint32_t equivalentBits = (1 << supportedChannelCount) - 1 ;
-                match = __builtin_popcount(
-                        audio_channel_mask_get_bits(channelMask) & equivalentBits);
-                if (supportedChannelCount <= FCC_2) {
-                    match += 100;
-                }
-            } else if (!isIndex && isSupportedIndex) {
-                const uint32_t equivalentBits = (1 << channelCount) - 1;
-                match = __builtin_popcount(
-                        equivalentBits & audio_channel_mask_get_bits(supported));
-            } else {
-                // positional equivalence
-                match = 100 + __builtin_popcount(
-                        audio_channel_mask_get_bits(channelMask)
-                            & audio_channel_mask_get_bits(supported));
-                switch (supported) {
-                case AUDIO_CHANNEL_IN_FRONT_BACK:
-                case AUDIO_CHANNEL_IN_STEREO:
-                    if (channelMask == AUDIO_CHANNEL_IN_MONO) {
-                        match = 1000;
-                    }
-                    break;
-                case AUDIO_CHANNEL_IN_MONO:
-                    if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
-                            || channelMask == AUDIO_CHANNEL_IN_STEREO) {
-                        match = 1000;
-                    }
-                    break;
-                default:
-                    break;
-                }
-            }
-            if (match > bestMatch) {
-                bestMatch = match;
-                updatedChannelMask = supported;
-            }
-        }
-    }
-    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
-}
-
-void AudioProfile::dump(String8 *dst, int spaces) const
-{
-    dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
-             mIsDynamicChannels ? "[dynamic channels]" : "",
-             mIsDynamicRate ? "[dynamic rates]" : "");
-    if (mName.length() != 0) {
-        dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
-    }
-    std::string formatLiteral;
-    if (FormatConverter::toString(mFormat, formatLiteral)) {
-        dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str());
-    }
-    if (!mSamplingRates.isEmpty()) {
-        dst->appendFormat("%*s- sampling rates:", spaces, "");
-        for (size_t i = 0; i < mSamplingRates.size(); i++) {
-            dst->appendFormat("%d", mSamplingRates[i]);
-            dst->append(i == (mSamplingRates.size() - 1) ? "" : ", ");
-        }
-        dst->append("\n");
-    }
-
-    if (!mChannelMasks.isEmpty()) {
-        dst->appendFormat("%*s- channel masks:", spaces, "");
-        for (size_t i = 0; i < mChannelMasks.size(); i++) {
-            dst->appendFormat("0x%04x", mChannelMasks[i]);
-            dst->append(i == (mChannelMasks.size() - 1) ? "" : ", ");
-        }
-        dst->append("\n");
-    }
-}
-
-ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
-{
-    ssize_t index = Vector::add(profile);
-    // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
-    // TODO: compareFormats could be a lambda to convert between pointer-to-format to format:
-    // [](const audio_format_t *format1, const audio_format_t *format2) {
-    //     return compareFormats(*format1, *format2);
-    // }
-    sort(compareFormats);
-    return index;
-}
-
-ssize_t AudioProfileVector::addProfileFromHal(const sp<AudioProfile> &profileToAdd)
-{
-    // Check valid profile to add:
-    if (!profileToAdd->hasValidFormat()) {
-        return -1;
-    }
-    if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
-        FormatVector formats;
-        formats.add(profileToAdd->getFormat());
-        setFormats(FormatVector(formats));
-        return 0;
-    }
-    if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) {
-        setSampleRatesFor(profileToAdd->getSampleRates(), profileToAdd->getFormat());
-        return 0;
-    }
-    if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
-        setChannelsFor(profileToAdd->getChannels(), profileToAdd->getFormat());
-        return 0;
-    }
-    // Go through the list of profile to avoid duplicates
-    for (size_t profileIndex = 0; profileIndex < size(); profileIndex++) {
-        const sp<AudioProfile> &profile = itemAt(profileIndex);
-        if (profile->isValid() && profile == profileToAdd) {
-            // Nothing to do
-            return profileIndex;
-        }
-    }
-    profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal
-    return add(profileToAdd);
-}
-
-status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate,
-                                               audio_channel_mask_t channelMask,
-                                               audio_format_t format) const
-{
-    if (isEmpty()) {
-        return NO_ERROR;
-    }
-
-    for (const auto& profile : *this) {
-        if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) {
-            return NO_ERROR;
-        }
-    }
-    return BAD_VALUE;
-}
-
-status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
-                                                    audio_channel_mask_t &channelMask,
-                                                    audio_format_t &format,
-                                                    audio_port_type_t portType,
-                                                    audio_port_role_t portRole) const
-{
-    if (isEmpty()) {
-        return NO_ERROR;
-    }
-
-    const bool checkInexact = // when port is input and format is linear pcm
-            portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK
-            && audio_is_linear_pcm(format);
-
-    // iterate from best format to worst format (reverse order)
-    for (ssize_t i = size() - 1; i >= 0 ; --i) {
-        const sp<AudioProfile> profile = itemAt(i);
-        audio_format_t formatToCompare = profile->getFormat();
-        if (formatToCompare == format ||
-                (checkInexact
-                        && formatToCompare != AUDIO_FORMAT_DEFAULT
-                        && audio_is_linear_pcm(formatToCompare))) {
-            // Compatible profile has been found, checks if this profile has compatible
-            // rate and channels as well
-            audio_channel_mask_t updatedChannels;
-            uint32_t updatedRate;
-            if (profile->checkCompatibleChannelMask(channelMask, updatedChannels,
-                                                    portType, portRole) == NO_ERROR &&
-                    profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) {
-                // for inexact checks we take the first linear pcm format due to sorting.
-                format = formatToCompare;
-                channelMask = updatedChannels;
-                samplingRate = updatedRate;
-                return NO_ERROR;
-            }
-        }
-    }
-    return BAD_VALUE;
-}
-
-void AudioProfileVector::clearProfiles()
-{
-    for (size_t i = size(); i != 0; ) {
-        sp<AudioProfile> profile = itemAt(--i);
-        if (profile->isDynamicFormat() && profile->hasValidFormat()) {
-            removeAt(i);
-            continue;
-        }
-        profile->clear();
-    }
-}
-
-// Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
-// The result is ordered according to 'order'.
-template<typename T, typename Order>
-std::vector<typename T::value_type> intersectFilterAndOrder(
-        const T& input1, const T& input2, const Order& order)
-{
-    std::set<typename T::value_type> set1{input1.begin(), input1.end()};
-    std::set<typename T::value_type> set2{input2.begin(), input2.end()};
-    std::set<typename T::value_type> common;
-    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
-            std::inserter(common, common.begin()));
-    std::vector<typename T::value_type> result;
-    for (const auto& e : order) {
-        if (common.find(e) != common.end()) result.push_back(e);
-    }
-    return result;
-}
-
-// Intersect two possibly unsorted vectors, return common elements according to 'comp' ordering.
-// 'comp' is a comparator function.
-template<typename T, typename Compare>
-std::vector<typename T::value_type> intersectAndOrder(
-        const T& input1, const T& input2, Compare comp)
-{
-    std::set<typename T::value_type, Compare> set1{input1.begin(), input1.end(), comp};
-    std::set<typename T::value_type, Compare> set2{input2.begin(), input2.end(), comp};
-    std::vector<typename T::value_type> result;
-    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
-            std::back_inserter(result), comp);
-    return result;
-}
-
-status_t AudioProfileVector::findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
-            const std::vector<audio_format_t>& preferredFormats,
-            const std::vector<audio_channel_mask_t>& preferredOutputChannels,
-            bool preferHigherSamplingRates,
-            audio_config_base *bestOutputConfig) const
-{
-    auto formats = intersectFilterAndOrder(getSupportedFormats(),
-            outputProfiles.getSupportedFormats(), preferredFormats);
-    // Pick the best compatible profile.
-    for (const auto& f : formats) {
-        sp<AudioProfile> inputProfile = getFirstValidProfileFor(f);
-        sp<AudioProfile> outputProfile = outputProfiles.getFirstValidProfileFor(f);
-        if (inputProfile == nullptr || outputProfile == nullptr) {
-            continue;
-        }
-        auto channels = intersectFilterAndOrder(inputProfile->getChannels().asOutMask(),
-                outputProfile->getChannels(), preferredOutputChannels);
-        if (channels.empty()) {
-            continue;
-        }
-        auto sampleRates = preferHigherSamplingRates ?
-                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
-                        std::greater<typename SampleRateVector::value_type>()) :
-                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
-                        std::less<typename SampleRateVector::value_type>());
-        if (sampleRates.empty()) {
-            continue;
-        }
-        ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.",
-                __func__, *channels.begin(), *sampleRates.begin(), f);
-        bestOutputConfig->format = f;
-        bestOutputConfig->sample_rate = *sampleRates.begin();
-        bestOutputConfig->channel_mask = *channels.begin();
-        return NO_ERROR;
-    }
-    return BAD_VALUE;
-}
-
-sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
-{
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->isValid()) {
-            return itemAt(i);
-        }
-    }
-    return 0;
-}
-
-sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
-{
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->isValid() && itemAt(i)->getFormat() == format) {
-            return itemAt(i);
-        }
-    }
-    return 0;
-}
-
-FormatVector AudioProfileVector::getSupportedFormats() const
-{
-    FormatVector supportedFormats;
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->hasValidFormat()) {
-            supportedFormats.add(itemAt(i)->getFormat());
-        }
-    }
-    return supportedFormats;
-}
-
-bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
-{
-    for (size_t i = 0; i < size(); i++) {
-        sp<AudioProfile> profile = itemAt(i);
-        if (profile->getFormat() == format && profile->isDynamicChannels()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioProfileVector::hasDynamicProfile() const
-{
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->isDynamic()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
-{
-    for (size_t i = 0; i < size(); i++) {
-        sp<AudioProfile> profile = itemAt(i);
-        if (profile->getFormat() == format && profile->isDynamicRate()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-void AudioProfileVector::setFormats(const FormatVector &formats)
-{
-    // Only allow to change the format of dynamic profile
-    sp<AudioProfile> dynamicFormatProfile = getProfileFor(gDynamicFormat);
-    if (dynamicFormatProfile == 0) {
-        return;
-    }
-    for (size_t i = 0; i < formats.size(); i++) {
-        sp<AudioProfile> profile = new AudioProfile(formats[i],
-                dynamicFormatProfile->getChannels(),
-                dynamicFormatProfile->getSampleRates());
-        profile->setDynamicFormat(true);
-        profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
-        profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
-        add(profile);
-    }
-}
-
-void AudioProfileVector::dump(String8 *dst, int spaces) const
-{
-    dst->appendFormat("%*s- Profiles:\n", spaces, "");
-    for (size_t i = 0; i < size(); i++) {
-        dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i);
-        itemAt(i)->dump(dst, spaces + 8);
-    }
-}
-
-sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const
-{
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->getFormat() == format) {
-            return itemAt(i);
-        }
-    }
-    return 0;
-}
-
-void AudioProfileVector::setSampleRatesFor(
-        const SampleRateVector &sampleRates, audio_format_t format)
-{
-    for (size_t i = 0; i < size(); i++) {
-        sp<AudioProfile> profile = itemAt(i);
-        if (profile->getFormat() == format && profile->isDynamicRate()) {
-            if (profile->hasValidRates()) {
-                // Need to create a new profile with same format
-                sp<AudioProfile> profileToAdd = new AudioProfile(format, profile->getChannels(),
-                        sampleRates);
-                profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
-                add(profileToAdd);
-            } else {
-                profile->setSampleRates(sampleRates);
-            }
-            return;
-        }
-    }
-}
-
-void AudioProfileVector::setChannelsFor(const ChannelsVector &channelMasks, audio_format_t format)
-{
-    for (size_t i = 0; i < size(); i++) {
-        sp<AudioProfile> profile = itemAt(i);
-        if (profile->getFormat() == format && profile->isDynamicChannels()) {
-            if (profile->hasValidChannels()) {
-                // Need to create a new profile with same format
-                sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMasks,
-                        profile->getSampleRates());
-                profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
-                add(profileToAdd);
-            } else {
-                profile->setChannels(channelMasks);
-            }
-            return;
-        }
-    }
-}
-
-// static
-int AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1,
-                                       const sp<AudioProfile> *profile2)
-{
-    return AudioPort::compareFormats((*profile1)->getFormat(), (*profile2)->getFormat());
-}
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp
new file mode 100644
index 0000000..8ccb8b9
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2015 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 <algorithm>
+#include <set>
+#include <string>
+
+#define LOG_TAG "APM::AudioProfileVectorHelper"
+//#define LOG_NDEBUG 0
+
+#include <media/AudioContainers.h>
+#include <media/AudioResamplerPublic.h>
+#include <utils/Errors.h>
+
+#include "AudioProfileVectorHelper.h"
+#include "HwModule.h"
+#include "PolicyAudioPort.h"
+#include "policy.h"
+
+namespace android {
+
+void sortAudioProfiles(AudioProfileVector &audioProfileVector) {
+    std::sort(audioProfileVector.begin(), audioProfileVector.end(),
+            [](const sp<AudioProfile> & a, const sp<AudioProfile> & b)
+            {
+                return PolicyAudioPort::compareFormats(a->getFormat(), b->getFormat()) < 0;
+            });
+}
+
+ssize_t addAudioProfileAndSort(AudioProfileVector &audioProfileVector,
+                               const sp<AudioProfile> &profile)
+{
+    ssize_t ret = audioProfileVector.add(profile);
+    // we sort from worst to best, so that AUDIO_FORMAT_DEFAULT is always the first entry.
+    sortAudioProfiles(audioProfileVector);
+    return ret;
+}
+
+sp<AudioProfile> getAudioProfileForFormat(const AudioProfileVector &audioProfileVector,
+                                          audio_format_t format)
+{
+    for (const auto &profile : audioProfileVector) {
+        if (profile->getFormat() == format) {
+            return profile;
+        }
+    }
+    return nullptr;
+}
+
+void setSampleRatesForAudioProfiles(AudioProfileVector &audioProfileVector,
+                                    const SampleRateSet &sampleRateSet,
+                                    audio_format_t format)
+{
+    for (const auto &profile : audioProfileVector) {
+        if (profile->getFormat() == format && profile->isDynamicRate()) {
+            if (profile->hasValidRates()) {
+                // Need to create a new profile with same format
+                sp<AudioProfile> profileToAdd = new AudioProfile(
+                        format, profile->getChannels(), sampleRateSet);
+                profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
+                addAudioProfileAndSort(audioProfileVector, profileToAdd);
+            } else {
+                profile->setSampleRates(sampleRateSet);
+            }
+            return;
+        }
+    }
+}
+
+void setChannelsForAudioProfiles(AudioProfileVector &audioProfileVector,
+                                 const ChannelMaskSet &channelMaskSet,
+                                 audio_format_t format)
+{
+    for (const auto &profile : audioProfileVector) {
+        if (profile->getFormat() == format && profile->isDynamicChannels()) {
+            if (profile->hasValidChannels()) {
+                // Need to create a new profile with same format
+                sp<AudioProfile> profileToAdd = new AudioProfile(format, channelMaskSet,
+                        profile->getSampleRates());
+                profileToAdd->setDynamicFormat(true); // need to set to allow cleaning
+                addAudioProfileAndSort(audioProfileVector, profileToAdd);
+            } else {
+                profile->setChannels(channelMaskSet);
+            }
+            return;
+        }
+    }
+}
+
+void addProfilesForFormats(AudioProfileVector &audioProfileVector, const FormatVector &formatVector)
+{
+    // Only allow to change the format of dynamic profile
+    sp<AudioProfile> dynamicFormatProfile = getAudioProfileForFormat(
+            audioProfileVector, gDynamicFormat);
+    if (!dynamicFormatProfile) {
+        return;
+    }
+    for (const auto &format : formatVector) {
+        sp<AudioProfile> profile = new AudioProfile(format,
+                dynamicFormatProfile->getChannels(),
+                dynamicFormatProfile->getSampleRates());
+        profile->setDynamicFormat(true);
+        profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels());
+        profile->setDynamicRate(dynamicFormatProfile->isDynamicRate());
+        addAudioProfileAndSort(audioProfileVector, profile);
+    }
+}
+
+void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector,
+                                      const sp<AudioProfile> &profileToAdd)
+{
+    // Check valid profile to add:
+    if (!profileToAdd->hasValidFormat()) {
+        ALOGW("Adding dynamic audio profile without valid format");
+        return;
+    }
+    if (!profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
+        FormatVector formats;
+        formats.push_back(profileToAdd->getFormat());
+        addProfilesForFormats(audioProfileVector, FormatVector(formats));
+        return;
+    }
+    if (!profileToAdd->hasValidChannels() && profileToAdd->hasValidRates()) {
+        setSampleRatesForAudioProfiles(
+                audioProfileVector, profileToAdd->getSampleRates(), profileToAdd->getFormat());
+        return;
+    }
+    if (profileToAdd->hasValidChannels() && !profileToAdd->hasValidRates()) {
+        setChannelsForAudioProfiles(
+                audioProfileVector, profileToAdd->getChannels(), profileToAdd->getFormat());
+        return;
+    }
+    // Go through the list of profile to avoid duplicates
+    for (size_t profileIndex = 0; profileIndex < audioProfileVector.size(); profileIndex++) {
+        const sp<AudioProfile> &profile = audioProfileVector.at(profileIndex);
+        if (profile->isValid() && profile == profileToAdd) {
+            // Nothing to do
+            return;
+        }
+    }
+    profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal
+    addAudioProfileAndSort(audioProfileVector, profileToAdd);
+}
+
+void appendAudioProfiles(AudioProfileVector &audioProfileVector,
+                         const AudioProfileVector &audioProfileVectorToAppend)
+{
+    audioProfileVector.insert(audioProfileVector.end(),
+                              audioProfileVectorToAppend.begin(),
+                              audioProfileVectorToAppend.end());
+}
+
+status_t checkExact(const sp<AudioProfile> &audioProfile,
+                    uint32_t samplingRate,
+                    audio_channel_mask_t channelMask,
+                    audio_format_t format)
+{
+    if (audio_formats_match(format, audioProfile->getFormat()) &&
+            audioProfile->supportsChannels(channelMask) &&
+            audioProfile->supportsRate(samplingRate)) {
+        return NO_ERROR;
+    }
+    return BAD_VALUE;
+}
+
+status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
+                                     uint32_t samplingRate,
+                                     uint32_t &updatedSamplingRate)
+{
+    ALOG_ASSERT(samplingRate > 0);
+
+    const SampleRateSet sampleRates = audioProfile->getSampleRates();
+    if (sampleRates.empty()) {
+        updatedSamplingRate = samplingRate;
+        return NO_ERROR;
+    }
+
+    // Search for the closest supported sampling rate that is above (preferred)
+    // or below (acceptable) the desired sampling rate, within a permitted ratio.
+    // The sampling rates are sorted in ascending order.
+    auto desiredRate = sampleRates.lower_bound(samplingRate);
+
+    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
+    if (desiredRate != sampleRates.end()) {
+        if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
+            updatedSamplingRate = *desiredRate;
+            return NO_ERROR;
+        }
+    }
+    // But if we have to up-sample from a lower sampling rate, that's OK.
+    if (desiredRate != sampleRates.begin()) {
+        uint32_t candidate = *(--desiredRate);
+        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
+            updatedSamplingRate = candidate;
+            return NO_ERROR;
+        }
+    }
+    // leave updatedSamplingRate unmodified
+    return BAD_VALUE;
+}
+
+status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
+                                    audio_channel_mask_t channelMask,
+                                    audio_channel_mask_t &updatedChannelMask,
+                                    audio_port_type_t portType,
+                                    audio_port_role_t portRole)
+{
+    const ChannelMaskSet channelMasks = audioProfile->getChannels();
+    if (channelMasks.empty()) {
+        updatedChannelMask = channelMask;
+        return NO_ERROR;
+    }
+    const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK;
+    const bool isIndex = audio_channel_mask_get_representation(channelMask)
+            == AUDIO_CHANNEL_REPRESENTATION_INDEX;
+    const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
+    int bestMatch = 0;
+    for (const auto &supported : channelMasks) {
+        if (supported == channelMask) {
+            // Exact matches always taken.
+            updatedChannelMask = channelMask;
+            return NO_ERROR;
+        }
+
+        // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
+        if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
+            // Approximate (best) match:
+            // The match score measures how well the supported channel mask matches the
+            // desired mask, where increasing-is-better.
+            //
+            // TODO: Some tweaks may be needed.
+            // Should be a static function of the data processing library.
+            //
+            // In priority:
+            // match score = 1000 if legacy channel conversion equivalent (always prefer this)
+            // OR
+            // match score += 100 if the channel mask representations match
+            // match score += number of channels matched.
+            // match score += 100 if the channel mask representations DO NOT match
+            //   but the profile has positional channel mask and less than 2 channels.
+            //   This is for audio HAL convention to not list index masks for less than 2 channels
+            //
+            // If there are no matched channels, the mask may still be accepted
+            // but the playback or record will be silent.
+            const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
+                    == AUDIO_CHANNEL_REPRESENTATION_INDEX);
+            const uint32_t supportedChannelCount = audio_channel_count_from_in_mask(supported);
+            int match;
+            if (isIndex && isSupportedIndex) {
+                // index equivalence
+                match = 100 + __builtin_popcount(
+                        audio_channel_mask_get_bits(channelMask)
+                            & audio_channel_mask_get_bits(supported));
+            } else if (isIndex && !isSupportedIndex) {
+                const uint32_t equivalentBits = (1 << supportedChannelCount) - 1 ;
+                match = __builtin_popcount(
+                        audio_channel_mask_get_bits(channelMask) & equivalentBits);
+                if (supportedChannelCount <= FCC_2) {
+                    match += 100;
+                }
+            } else if (!isIndex && isSupportedIndex) {
+                const uint32_t equivalentBits = (1 << channelCount) - 1;
+                match = __builtin_popcount(
+                        equivalentBits & audio_channel_mask_get_bits(supported));
+            } else {
+                // positional equivalence
+                match = 100 + __builtin_popcount(
+                        audio_channel_mask_get_bits(channelMask)
+                            & audio_channel_mask_get_bits(supported));
+                switch (supported) {
+                case AUDIO_CHANNEL_IN_FRONT_BACK:
+                case AUDIO_CHANNEL_IN_STEREO:
+                    if (channelMask == AUDIO_CHANNEL_IN_MONO) {
+                        match = 1000;
+                    }
+                    break;
+                case AUDIO_CHANNEL_IN_MONO:
+                    if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
+                            || channelMask == AUDIO_CHANNEL_IN_STEREO) {
+                        match = 1000;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+            if (match > bestMatch) {
+                bestMatch = match;
+                updatedChannelMask = supported;
+            }
+        }
+    }
+    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
+}
+
+status_t checkExactProfile(const AudioProfileVector& audioProfileVector,
+                           const uint32_t samplingRate,
+                           audio_channel_mask_t channelMask,
+                           audio_format_t format)
+{
+    if (audioProfileVector.empty()) {
+        return NO_ERROR;
+    }
+
+    for (const auto& profile : audioProfileVector) {
+        if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
+            return NO_ERROR;
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t checkCompatibleProfile(const AudioProfileVector &audioProfileVector,
+                                uint32_t &samplingRate,
+                                audio_channel_mask_t &channelMask,
+                                audio_format_t &format,
+                                audio_port_type_t portType,
+                                audio_port_role_t portRole)
+{
+    if (audioProfileVector.empty()) {
+        return NO_ERROR;
+    }
+
+    const bool checkInexact = // when port is input and format is linear pcm
+            portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK
+            && audio_is_linear_pcm(format);
+
+    // iterate from best format to worst format (reverse order)
+    for (ssize_t i = audioProfileVector.size() - 1; i >= 0 ; --i) {
+        const sp<AudioProfile> profile = audioProfileVector.at(i);
+        audio_format_t formatToCompare = profile->getFormat();
+        if (formatToCompare == format ||
+                (checkInexact
+                        && formatToCompare != AUDIO_FORMAT_DEFAULT
+                        && audio_is_linear_pcm(formatToCompare))) {
+            // Compatible profile has been found, checks if this profile has compatible
+            // rate and channels as well
+            audio_channel_mask_t updatedChannels;
+            uint32_t updatedRate;
+            if (checkCompatibleChannelMask(profile, channelMask, updatedChannels,
+                                           portType, portRole) == NO_ERROR &&
+                    checkCompatibleSamplingRate(profile, samplingRate, updatedRate) == NO_ERROR) {
+                // for inexact checks we take the first linear pcm format due to sorting.
+                format = formatToCompare;
+                channelMask = updatedChannels;
+                samplingRate = updatedRate;
+                return NO_ERROR;
+            }
+        }
+    }
+    return BAD_VALUE;
+}
+
+// Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
+// The result is ordered according to 'order'.
+template<typename T, typename Order>
+std::vector<typename T::value_type> intersectFilterAndOrder(
+        const T& input1, const T& input2, const Order& order)
+{
+    std::set<typename T::value_type> set1{input1.begin(), input1.end()};
+    std::set<typename T::value_type> set2{input2.begin(), input2.end()};
+    std::set<typename T::value_type> common;
+    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
+            std::inserter(common, common.begin()));
+    std::vector<typename T::value_type> result;
+    for (const auto& e : order) {
+        if (common.find(e) != common.end()) result.push_back(e);
+    }
+    return result;
+}
+
+// Intersect two possibly unsorted vectors, return common elements according to 'comp' ordering.
+// 'comp' is a comparator function.
+template<typename T, typename Compare>
+std::vector<typename T::value_type> intersectAndOrder(
+        const T& input1, const T& input2, Compare comp)
+{
+    std::set<typename T::value_type, Compare> set1{input1.begin(), input1.end(), comp};
+    std::set<typename T::value_type, Compare> set2{input2.begin(), input2.end(), comp};
+    std::vector<typename T::value_type> result;
+    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
+            std::back_inserter(result), comp);
+    return result;
+}
+
+status_t findBestMatchingOutputConfig(
+        const AudioProfileVector &audioProfileVector,
+        const AudioProfileVector &outputProfileVector,
+        const std::vector<audio_format_t> &preferredFormatVector, // order: most pref -> least pref
+        const std::vector<audio_channel_mask_t> &preferredOutputChannelVector,
+        bool preferHigherSamplingRates,
+        audio_config_base &bestOutputConfig)
+{
+    auto formats = intersectFilterAndOrder(audioProfileVector.getSupportedFormats(),
+            outputProfileVector.getSupportedFormats(), preferredFormatVector);
+    // Pick the best compatible profile.
+    for (const auto& f : formats) {
+        sp<AudioProfile> inputProfile = audioProfileVector.getFirstValidProfileFor(f);
+        sp<AudioProfile> outputProfile = outputProfileVector.getFirstValidProfileFor(f);
+        if (inputProfile == nullptr || outputProfile == nullptr) {
+            continue;
+        }
+        auto channels = intersectFilterAndOrder(asOutMask(inputProfile->getChannels()),
+                outputProfile->getChannels(), preferredOutputChannelVector);
+        if (channels.empty()) {
+            continue;
+        }
+        auto sampleRates = preferHigherSamplingRates ?
+                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
+                        std::greater<typename SampleRateSet::value_type>()) :
+                intersectAndOrder(inputProfile->getSampleRates(), outputProfile->getSampleRates(),
+                        std::less<typename SampleRateSet::value_type>());
+        if (sampleRates.empty()) {
+            continue;
+        }
+        ALOGD("%s() found channel mask %#x and sample rate %d for format %#x.",
+                __func__, *channels.begin(), *sampleRates.begin(), f);
+        bestOutputConfig.format = f;
+        bestOutputConfig.sample_rate = *sampleRates.begin();
+        bestOutputConfig.channel_mask = *channels.begin();
+        return NO_ERROR;
+    }
+    return BAD_VALUE;
+}
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index 79f0919..2a18f19 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -19,7 +19,6 @@
 
 #include "AudioRoute.h"
 #include "HwModule.h"
-#include "AudioGain.h"
 
 namespace android
 {
@@ -27,25 +26,26 @@
 void AudioRoute::dump(String8 *dst, int spaces) const
 {
     dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix");
-    dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().string());
+    dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().c_str());
     if (mSources.size() != 0) {
         dst->appendFormat("%*s- Sources: \n", spaces, "");
         for (size_t i = 0; i < mSources.size(); i++) {
-            dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().string());
+            dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().c_str());
         }
     }
     dst->append("\n");
 }
 
-bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const
+bool AudioRoute::supportsPatch(const sp<PolicyAudioPort> &srcPort,
+                               const sp<PolicyAudioPort> &dstPort) const
 {
     if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
         return false;
     }
-    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
     for (const auto &sourcePort : mSources) {
         if (sourcePort == srcPort) {
-            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
             return true;
         }
     }
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index ad07ab1..afc4d01 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -21,9 +21,9 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <TypeConverter.h>
-#include "AudioGain.h"
 #include "AudioOutputDescriptor.h"
 #include "AudioPatch.h"
+#include "AudioPolicyMix.h"
 #include "ClientDescriptor.h"
 #include "DeviceDescriptor.h"
 #include "HwModule.h"
@@ -56,6 +56,12 @@
     ClientDescriptor::dump(dst, spaces, index);
     dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags);
     dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount);
+    dst->appendFormat("%*s- DAP Primary Mix: %p\n", spaces, "", mPrimaryMix.promote().get());
+    dst->appendFormat("%*s- DAP Secondary Outputs:\n", spaces, "");
+    for (auto desc : mSecondaryOutputs) {
+        dst->appendFormat("%*s  - %d\n", spaces, "",
+                desc.promote() == nullptr ? 0 : desc.promote()->mIoHandle);
+    }
 }
 
 std::string TrackClientDescriptor::toShortString() const
@@ -83,14 +89,13 @@
 }
 
 SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
-         audio_attributes_t attributes, const sp<AudioPatch>& patchDesc,
+         audio_attributes_t attributes, const struct audio_port_config &config,
          const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream,
          product_strategy_t strategy, VolumeSource volumeSource) :
     TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
-        AUDIO_CONFIG_BASE_INITIALIZER, AUDIO_PORT_HANDLE_NONE,
+        {config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE,
         stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
-        {} /* Sources do not support secondary outputs*/),
-        mPatchDesc(patchDesc), mSrcDevice(srcDevice)
+        {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice)
 {
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index ecd5b34..a29e60e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -17,57 +17,64 @@
 #define LOG_TAG "APM::Devices"
 //#define LOG_NDEBUG 0
 
-#include <audio_utils/string.h>
-#include <media/TypeConverter.h>
 #include <set>
+
+#include <AudioPolicyInterface.h>
+#include <audio_utils/string.h>
+#include <media/AudioParameter.h>
+#include <media/TypeConverter.h>
 #include "DeviceDescriptor.h"
 #include "TypeConverter.h"
-#include "AudioGain.h"
 #include "HwModule.h"
 
 namespace android {
 
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
-        DeviceDescriptor(type, FormatVector{}, tagName)
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type) :
+        DeviceDescriptor(type, "" /*tagName*/)
 {
 }
 
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
-        const String8 &tagName) :
-    AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
-              audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
-                                             AUDIO_PORT_ROLE_SOURCE),
-    mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
+                                   const std::string &tagName,
+                                   const FormatVector &encodedFormats) :
+        DeviceDescriptor(type, tagName, "" /*address*/, encodedFormats)
+{
+}
+
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
+                                   const std::string &tagName,
+                                   const std::string &address,
+                                   const FormatVector &encodedFormats) :
+        DeviceDescriptor(AudioDeviceTypeAddr(type, address), tagName, encodedFormats)
+{
+}
+
+DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
+                                   const std::string &tagName,
+                                   const FormatVector &encodedFormats) :
+        DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats)
 {
     mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
-    if (audio_is_remote_submix_device(type)) {
-        mAddress = String8("0");
-    }
     /* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
      * FIXME: APM should know the version of the HAL and don't add the formats for V5.0.
      * For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
      * something like 'encodedFormats="AUDIO_FORMAT_PCM_16_BIT"' on the HDMI devicePort.
      */
-    if (type == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.isEmpty()) {
-        mEncodedFormats.add(AUDIO_FORMAT_AC3);
-        mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
+    if (mDeviceTypeAddr.mType == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.empty()) {
+        mEncodedFormats.push_back(AUDIO_FORMAT_AC3);
+        mEncodedFormats.push_back(AUDIO_FORMAT_IEC61937);
     }
 }
 
-audio_port_handle_t DeviceDescriptor::getId() const
-{
-    return mId;
-}
-
 void DeviceDescriptor::attach(const sp<HwModule>& module)
 {
-    AudioPort::attach(module);
+    PolicyAudioPort::attach(module);
     mId = getNextUniqueId();
 }
 
 void DeviceDescriptor::detach() {
     mId = AUDIO_PORT_HANDLE_NONE;
-    AudioPort::detach();
+    PolicyAudioPort::detach();
 }
 
 template<typename T>
@@ -88,7 +95,7 @@
         return false;
     }
 
-    return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
+    return mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
            checkEqual(mEncodedFormats, other->mEncodedFormats);
 }
 
@@ -97,7 +104,7 @@
     if (!device_has_encoding_capability(type())) {
         return true;
     }
-    if (mEncodedFormats.isEmpty()) {
+    if (mEncodedFormats.empty()) {
         return true;
     }
 
@@ -106,7 +113,7 @@
 
 bool DeviceDescriptor::supportsFormat(audio_format_t format)
 {
-    if (mEncodedFormats.isEmpty()) {
+    if (mEncodedFormats.empty()) {
         return true;
     }
 
@@ -118,13 +125,92 @@
     return false;
 }
 
+status_t DeviceDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
+                                                audio_port_config *backupConfig)
+{
+    struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
+    status_t status = NO_ERROR;
+
+    toAudioPortConfig(&localBackupConfig);
+    if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
+        AudioPortConfig::applyAudioPortConfig(config, backupConfig);
+        applyPolicyAudioPortConfig(config);
+    }
+
+    if (backupConfig != NULL) {
+        *backupConfig = localBackupConfig;
+    }
+    return status;
+}
+
+void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                         const struct audio_port_config *srcConfig) const
+{
+    DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
+    toPolicyAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->ext.device.hw_module = getModuleHandle();
+}
+
+void DeviceDescriptor::toAudioPort(struct audio_port *port) const
+{
+    ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
+    DeviceDescriptorBase::toAudioPort(port);
+    port->ext.device.hw_module = getModuleHandle();
+}
+
+void DeviceDescriptor::importAudioPortAndPickAudioProfile(
+        const sp<PolicyAudioPort>& policyPort, bool force) {
+    if (!force && !policyPort->asAudioPort()->hasDynamicAudioProfile()) {
+        return;
+    }
+    AudioPort::importAudioPort(policyPort->asAudioPort());
+    policyPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
+}
+
+void DeviceDescriptor::setEncapsulationInfoFromHal(
+        AudioPolicyClientInterface *clientInterface) {
+    AudioParameter param(String8(mDeviceTypeAddr.getAddress()));
+    param.addInt(String8(AudioParameter::keyRouting), mDeviceTypeAddr.mType);
+    param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES));
+    param.addKey(String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES));
+    String8 reply = clientInterface->getParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+    AudioParameter repliedParameters(reply);
+    int value;
+    if (repliedParameters.getInt(
+            String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES), value) == NO_ERROR) {
+        if (setEncapsulationModes(value) != NO_ERROR) {
+            ALOGE("Failed to set encapsulation mode(%d)", value);
+        }
+    }
+    if (repliedParameters.getInt(
+            String8(AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_METADATA_TYPES), value) == NO_ERROR) {
+        if (setEncapsulationMetadataTypes(value) != NO_ERROR) {
+            ALOGE("Failed to set encapsulation metadata types(%d)", value);
+        }
+    }
+}
+
+void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
+{
+    String8 extraInfo;
+    if (!mTagName.empty()) {
+        extraInfo.appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
+    }
+
+    std::string descBaseDumpStr;
+    DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, index, extraInfo.string(), verbose);
+    dst->append(descBaseDumpStr.c_str());
+}
+
+
 void DeviceVector::refreshTypes()
 {
-    mDeviceTypes = AUDIO_DEVICE_NONE;
+    mDeviceTypes.clear();
     for (size_t i = 0; i < size(); i++) {
-        mDeviceTypes |= itemAt(i)->type();
+        mDeviceTypes.insert(itemAt(i)->type());
     }
-    ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
+    ALOGV("DeviceVector::refreshTypes() mDeviceTypes %s", dumpDeviceTypes(mDeviceTypes).c_str());
 }
 
 ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
@@ -199,17 +285,6 @@
     return devices;
 }
 
-audio_devices_t DeviceVector::getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const
-{
-    audio_devices_t deviceTypes = AUDIO_DEVICE_NONE;
-    for (const auto& device : *this) {
-        if (device->getModuleHandle() == moduleHandle) {
-            deviceTypes |= device->type();
-        }
-    }
-    return deviceTypes;
-}
-
 sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, const String8& address,
                                              audio_format_t format) const
 {
@@ -219,11 +294,11 @@
             // If format is specified, match it and ignore address
             // Otherwise if address is specified match it
             // Otherwise always match
-            if (((address == "" || itemAt(i)->address() == address) &&
+            if (((address == "" || (itemAt(i)->address().compare(address.c_str()) == 0)) &&
                  format == AUDIO_FORMAT_DEFAULT) ||
                 (itemAt(i)->supportsFormat(format) && format != AUDIO_FORMAT_DEFAULT)) {
                 device = itemAt(i);
-                if (itemAt(i)->address() == address) {
+                if (itemAt(i)->address().compare(address.c_str()) == 0) {
                     break;
                 }
             }
@@ -246,17 +321,15 @@
     return nullptr;
 }
 
-DeviceVector DeviceVector::getDevicesFromTypeMask(audio_devices_t type) const
+DeviceVector DeviceVector::getDevicesFromTypes(const DeviceTypeSet& types) const
 {
     DeviceVector devices;
-    bool isOutput = audio_is_output_devices(type);
-    type &= ~AUDIO_DEVICE_BIT_IN;
-    for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
-        bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
-        audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
-        if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
+    if (types.empty()) {
+        return devices;
+    }
+    for (size_t i = 0; i < size(); i++) {
+        if (types.count(itemAt(i)->type()) != 0) {
             devices.add(itemAt(i));
-            type &= ~curType;
             ALOGV("DeviceVector::%s() for type %08x found %p",
                     __func__, itemAt(i)->type(), itemAt(i).get());
         }
@@ -264,7 +337,7 @@
     return devices;
 }
 
-sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
+sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
 {
     for (const auto& device : *this) {
         if (device->getTagName() == tagName) {
@@ -274,6 +347,56 @@
     return nullptr;
 }
 
+DeviceVector DeviceVector::getFirstDevicesFromTypes(
+        std::vector<audio_devices_t> orderedTypes) const
+{
+    DeviceVector devices;
+    for (auto deviceType : orderedTypes) {
+        if (!(devices = getDevicesFromType(deviceType)).isEmpty()) {
+            break;
+        }
+    }
+    return devices;
+}
+
+sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
+        std::vector<audio_devices_t> orderedTypes) const {
+    sp<DeviceDescriptor> device;
+    for (auto deviceType : orderedTypes) {
+        if ((device = getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT)) != nullptr) {
+            break;
+        }
+    }
+    return device;
+}
+
+sp<DeviceDescriptor> DeviceVector::getDeviceForOpening() const
+{
+    if (isEmpty()) {
+        // Return nullptr if this collection is empty.
+        return nullptr;
+    } else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
+        // For input case, return the first one when there is only one device.
+        return size() > 1 ? nullptr : *begin();
+    } else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
+        // For output case, return the device descriptor according to apm strategy.
+        audio_devices_t deviceType = apm_extract_one_audio_device(types());
+        return deviceType == AUDIO_DEVICE_NONE ? nullptr :
+                getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT);
+    }
+    // Return null pointer if the devices are not all input/output device.
+    return nullptr;
+}
+
+void DeviceVector::replaceDevicesByType(
+        audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
+    DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
+    if (!devicesToRemove.isEmpty() && !devicesToAdd.isEmpty()) {
+        remove(devicesToRemove);
+        add(devicesToAdd);
+    }
+}
+
 void DeviceVector::dump(String8 *dst, const String8 &tag, int spaces, bool verbose) const
 {
     if (isEmpty()) {
@@ -285,84 +408,6 @@
     }
 }
 
-void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
-                                         const struct audio_port_config *srcConfig) const
-{
-    dstConfig->config_mask = AUDIO_PORT_CONFIG_GAIN;
-    if (mSamplingRate != 0) {
-        dstConfig->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
-    }
-    if (mChannelMask != AUDIO_CHANNEL_NONE) {
-        dstConfig->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
-    }
-    if (mFormat != AUDIO_FORMAT_INVALID) {
-        dstConfig->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
-    }
-
-    if (srcConfig != NULL) {
-        dstConfig->config_mask |= srcConfig->config_mask;
-    }
-
-    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
-    dstConfig->id = mId;
-    dstConfig->role = audio_is_output_device(mDeviceType) ?
-                        AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
-    dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
-    dstConfig->ext.device.type = mDeviceType;
-
-    //TODO Understand why this test is necessary. i.e. why at boot time does it crash
-    // without the test?
-    // This has been demonstrated to NOT be true (at start up)
-    // ALOG_ASSERT(mModule != NULL);
-    dstConfig->ext.device.hw_module = getModuleHandle();
-    (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
-}
-
-void DeviceDescriptor::toAudioPort(struct audio_port *port) const
-{
-    ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
-    AudioPort::toAudioPort(port);
-    port->id = mId;
-    toAudioPortConfig(&port->active_config);
-    port->ext.device.type = mDeviceType;
-    port->ext.device.hw_module = getModuleHandle();
-    (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
-}
-
-void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
-    if (!force && !port->hasDynamicAudioProfile()) {
-        return;
-    }
-    AudioPort::importAudioPort(port);
-    port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
-}
-
-void DeviceDescriptor::dump(String8 *dst, int spaces, int index, bool verbose) const
-{
-    dst->appendFormat("%*sDevice %d:\n", spaces, "", index + 1);
-    if (mId != 0) {
-        dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
-    }
-    if (!mTagName.isEmpty()) {
-        dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
-    }
-
-    dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
-
-    if (mAddress.size() != 0) {
-        dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
-    }
-    AudioPort::dump(dst, spaces, verbose);
-}
-
-std::string DeviceDescriptor::toString() const
-{
-    std::stringstream sstream;
-    sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
-    return sstream.str();
-}
-
 std::string DeviceVector::toString() const
 {
     if (isEmpty()) {
@@ -411,13 +456,4 @@
     return filteredDevices;
 }
 
-void DeviceDescriptor::log() const
-{
-    ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId,  mDeviceType,
-          ::android::toString(mDeviceType).c_str(),
-          mAddress.string());
-
-    AudioPort::log("  ");
-}
-
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 1f9b725..d31e443 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -19,7 +19,6 @@
 
 #include "HwModule.h"
 #include "IOProfile.h"
-#include "AudioGain.h"
 #include <policy.h>
 #include <system/audio.h>
 
@@ -42,7 +41,7 @@
     }
 }
 
-status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
                                     audio_devices_t device, const String8& address)
 {
     sp<IOProfile> profile = new OutputProfile(name);
@@ -50,8 +49,7 @@
     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
                                               config->sample_rate));
 
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->setAddress(address);
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
     addDynamicDevice(devDesc);
     // Reciprocally attach the device to the module
     devDesc->attach(this);
@@ -96,7 +94,7 @@
     }
 }
 
-status_t HwModule::removeOutputProfile(const String8& name)
+status_t HwModule::removeOutputProfile(const std::string& name)
 {
     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
         if (mOutputProfiles[i]->getName() == name) {
@@ -111,27 +109,26 @@
     return NO_ERROR;
 }
 
-status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
                                    audio_devices_t device, const String8& address)
 {
     sp<IOProfile> profile = new InputProfile(name);
     profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
                                               config->sample_rate));
 
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->setAddress(address);
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
     addDynamicDevice(devDesc);
     // Reciprocally attach the device to the module
     devDesc->attach(this);
     profile->addSupportedDevice(devDesc);
 
     ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
-          name.string(), config->sample_rate, config->channel_mask);
+          name.c_str(), config->sample_rate, config->channel_mask);
 
     return addInputProfile(profile);
 }
 
-status_t HwModule::removeInputProfile(const String8& name)
+status_t HwModule::removeInputProfile(const std::string& name)
 {
     for (size_t i = 0; i < mInputProfiles.size(); i++) {
         if (mInputProfiles[i]->getName() == name) {
@@ -157,7 +154,7 @@
 sp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const
 {
     sp<DeviceDescriptor> sinkDevice = 0;
-    if (route->getSink()->getType() == AUDIO_PORT_TYPE_DEVICE) {
+    if (route->getSink()->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
         sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName());
     }
     return sinkDevice;
@@ -167,7 +164,7 @@
 {
     DeviceVector sourceDevices;
     for (const auto& source : route->getSources()) {
-        if (source->getType() == AUDIO_PORT_TYPE_DEVICE) {
+        if (source->asAudioPort()->getType() == AUDIO_PORT_TYPE_DEVICE) {
             sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(source->getTagName()));
         }
     }
@@ -187,20 +184,20 @@
     for (const auto& stream : mInputProfiles) {
         DeviceVector sourceDevices;
         for (const auto& route : stream->getRoutes()) {
-            sp<AudioPort> sink = route->getSink();
+            sp<PolicyAudioPort> sink = route->getSink();
             if (sink == 0 || stream != sink) {
                 ALOGE("%s: Invalid route attached to input stream", __FUNCTION__);
                 continue;
             }
             DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route);
             if (sourceDevicesForRoute.isEmpty()) {
-                ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+                ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
                 continue;
             }
             sourceDevices.add(sourceDevicesForRoute);
         }
         if (sourceDevices.isEmpty()) {
-            ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+            ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
             continue;
         }
         stream->setSupportedDevices(sourceDevices);
@@ -208,14 +205,14 @@
     for (const auto& stream : mOutputProfiles) {
         DeviceVector sinkDevices;
         for (const auto& route : stream->getRoutes()) {
-            sp<AudioPort> source = route->getSources().findByTagName(stream->getTagName());
+            sp<PolicyAudioPort> source = findByTagName(route->getSources(), stream->getTagName());
             if (source == 0 || stream != source) {
                 ALOGE("%s: Invalid route attached to output stream", __FUNCTION__);
                 continue;
             }
             sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route);
             if (sinkDevice == 0) {
-                ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string());
+                ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str());
                 continue;
             }
             sinkDevices.add(sinkDevice);
@@ -230,7 +227,8 @@
     mHandle = handle;
 }
 
-bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const {
+bool HwModule::supportsPatch(const sp<PolicyAudioPort> &srcPort,
+                             const sp<PolicyAudioPort> &dstPort) const {
     for (const auto &route : mRoutes) {
         if (route->supportsPatch(srcPort, dstPort)) {
             return true;
@@ -260,7 +258,7 @@
     }
     mDeclaredDevices.dump(dst, String8("Declared"), 2, true);
     mDynamicDevices.dump(dst, String8("Dynamic"),  2, true);
-    mRoutes.dump(dst, 2);
+    dumpAudioRouteVector(mRoutes, dst, 2);
 }
 
 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
@@ -273,14 +271,14 @@
     return nullptr;
 }
 
-sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type,
-                                                          audio_format_t encodedFormat) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceType(audio_devices_t type,
+                                                         audio_format_t encodedFormat) const
 {
     for (const auto& module : *this) {
         const auto& profiles = audio_is_output_device(type) ?
                 module->getOutputProfiles() : module->getInputProfiles();
         for (const auto& profile : profiles) {
-            if (profile->supportsDeviceTypes(type)) {
+            if (profile->supportsDeviceTypes({type})) {
                 if (encodedFormat != AUDIO_FORMAT_DEFAULT) {
                     DeviceVector declaredDevices = module->getDeclaredDevices();
                     sp <DeviceDescriptor> deviceDesc =
@@ -300,7 +298,7 @@
 sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device,
                                                      audio_format_t encodedFormat) const
 {
-    return getModuleForDeviceTypes(device->type(), encodedFormat);
+    return getModuleForDeviceType(device->type(), encodedFormat);
 }
 
 DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
@@ -322,7 +320,7 @@
 {
     String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address);
     // handle legacy remote submix case where the address was not always specified
-    if (device_distinguishes_on_address(deviceType) && (devAddress.length() == 0)) {
+    if (audio_is_remote_submix_device(deviceType) && (devAddress.length() == 0)) {
         devAddress = String8("0");
     }
 
@@ -335,8 +333,8 @@
             }
             if (allowToCreate) {
                 moduleDevice->attach(hwModule);
-                moduleDevice->setAddress(devAddress);
-                moduleDevice->setName(String8(name));
+                moduleDevice->setAddress(devAddress.string());
+                moduleDevice->setName(name);
             }
             return moduleDevice;
         }
@@ -354,15 +352,15 @@
                                                       const char *name,
                                                       const audio_format_t encodedFormat) const
 {
-    sp<HwModule> hwModule = getModuleForDeviceTypes(type, encodedFormat);
+    sp<HwModule> hwModule = getModuleForDeviceType(type, encodedFormat);
     if (hwModule == 0) {
         ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
               address);
         return nullptr;
     }
-    sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name));
-    device->setName(String8(name));
-    device->setAddress(String8(address));
+
+    sp<DeviceDescriptor> device = new DeviceDescriptor(type, name, address);
+    device->setName(name);
     device->setEncodedFormat(encodedFormat);
 
   // Add the device to the list of dynamic devices
@@ -382,7 +380,7 @@
             // @todo quid of audio profile? import the profile from device of the same type?
             const auto &isoTypeDeviceForProfile =
                 profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT);
-            device->importAudioPort(isoTypeDeviceForProfile, true /* force */);
+            device->importAudioPortAndPickAudioProfile(isoTypeDeviceForProfile, true /* force */);
 
             ALOGV("%s: adding device %s to profile %s", __FUNCTION__,
                   device->toString().c_str(), profile->getTagName().c_str());
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index fe2eaee..bf1a0f7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -20,7 +20,6 @@
 #include <system/audio-base.h>
 #include "IOProfile.h"
 #include "HwModule.h"
-#include "AudioGain.h"
 #include "TypeConverter.h"
 
 namespace android {
@@ -79,7 +78,10 @@
         }
     }
 
-    if (isPlaybackThread && (getFlags() & flags) != flags) {
+    const uint32_t mustMatchOutputFlags =
+            AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+    if (isPlaybackThread && (((getFlags() ^ flags) & mustMatchOutputFlags)
+                    || (getFlags() & flags) != flags)) {
         return false;
     }
     // The only input flag that is allowed to be different is the fast flag.
@@ -105,7 +107,9 @@
 
 void IOProfile::dump(String8 *dst) const
 {
-    AudioPort::dump(dst, 4);
+    std::string portStr;
+    AudioPort::dump(&portStr, 4);
+    dst->append(portStr.c_str());
 
     dst->appendFormat("    - flags: 0x%04x", getFlags());
     std::string flagsLiteral;
diff --git a/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp
new file mode 100644
index 0000000..8c61b90
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2015 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_TAG "APM::PolicyAudioPort"
+//#define LOG_NDEBUG 0
+#include "TypeConverter.h"
+#include "PolicyAudioPort.h"
+#include "HwModule.h"
+#include <policy.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+namespace android {
+
+// --- PolicyAudioPort class implementation
+void PolicyAudioPort::attach(const sp<HwModule>& module)
+{
+    ALOGV("%s: attaching module %s to port %s",
+            __FUNCTION__, getModuleName(), asAudioPort()->getName().c_str());
+    mModule = module;
+}
+
+void PolicyAudioPort::detach()
+{
+    mModule = nullptr;
+}
+
+// Note that is a different namespace than AudioFlinger unique IDs
+audio_port_handle_t PolicyAudioPort::getNextUniqueId()
+{
+    return getNextHandle();
+}
+
+audio_module_handle_t PolicyAudioPort::getModuleHandle() const
+{
+    return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
+}
+
+uint32_t PolicyAudioPort::getModuleVersionMajor() const
+{
+    return mModule != 0 ? mModule->getHalVersionMajor() : 0;
+}
+
+const char *PolicyAudioPort::getModuleName() const
+{
+    return mModule != 0 ? mModule->getName() : "invalid module";
+}
+
+status_t PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
+{
+    status_t status = NO_ERROR;
+    auto config_mask = config->config_mask;
+    if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
+        config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
+        status = asAudioPort()->checkGain(&config->gain, config->gain.index);
+        if (status != NO_ERROR) {
+            return status;
+        }
+    }
+    if (config_mask != 0) {
+        // TODO should we check sample_rate / channel_mask / format separately?
+        status = checkExactProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
+                config->channel_mask, config->format);
+    }
+    return status;
+}
+
+void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
+                                       const SampleRateSet &samplingRates) const
+{
+    pickedRate = 0;
+    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
+    // channel count / sampling rate combination chosen will be supported by the connected
+    // sink
+    if (isDirectOutput()) {
+        uint32_t samplingRate = UINT_MAX;
+        for (const auto rate : samplingRates) {
+            if ((rate < samplingRate) && (rate > 0)) {
+                samplingRate = rate;
+            }
+        }
+        pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
+    } else {
+        uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
+
+        // For mixed output and inputs, use max mixer sampling rates. Do not
+        // limit sampling rate otherwise
+        // For inputs, also see checkCompatibleSamplingRate().
+        if (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) {
+            maxRate = UINT_MAX;
+        }
+        // TODO: should mSamplingRates[] be ordered in terms of our preference
+        // and we return the first (and hence most preferred) match?  This is of concern if
+        // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
+        for (const auto rate : samplingRates) {
+            if ((rate > pickedRate) && (rate <= maxRate)) {
+                pickedRate = rate;
+            }
+        }
+    }
+}
+
+void PolicyAudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
+                                      const ChannelMaskSet &channelMasks) const
+{
+    pickedChannelMask = AUDIO_CHANNEL_NONE;
+    // For direct outputs, pick minimum channel count: this helps ensuring that the
+    // channel count / sampling rate combination chosen will be supported by the connected
+    // sink
+    if (isDirectOutput()) {
+        uint32_t channelCount = UINT_MAX;
+        for (const auto channelMask : channelMasks) {
+            uint32_t cnlCount;
+            if (asAudioPort()->useInputChannelMask()) {
+                cnlCount = audio_channel_count_from_in_mask(channelMask);
+            } else {
+                cnlCount = audio_channel_count_from_out_mask(channelMask);
+            }
+            if ((cnlCount < channelCount) && (cnlCount > 0)) {
+                pickedChannelMask = channelMask;
+                channelCount = cnlCount;
+            }
+        }
+    } else {
+        uint32_t channelCount = 0;
+        uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
+
+        // For mixed output and inputs, use max mixer channel count. Do not
+        // limit channel count otherwise
+        if (asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) {
+            maxCount = UINT_MAX;
+        }
+        for (const auto channelMask : channelMasks) {
+            uint32_t cnlCount;
+            if (asAudioPort()->useInputChannelMask()) {
+                cnlCount = audio_channel_count_from_in_mask(channelMask);
+            } else {
+                cnlCount = audio_channel_count_from_out_mask(channelMask);
+            }
+            if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
+                pickedChannelMask = channelMask;
+                channelCount = cnlCount;
+            }
+        }
+    }
+}
+
+/* format in order of increasing preference */
+const audio_format_t PolicyAudioPort::sPcmFormatCompareTable[] = {
+        AUDIO_FORMAT_DEFAULT,
+        AUDIO_FORMAT_PCM_16_BIT,
+        AUDIO_FORMAT_PCM_8_24_BIT,
+        AUDIO_FORMAT_PCM_24_BIT_PACKED,
+        AUDIO_FORMAT_PCM_32_BIT,
+        AUDIO_FORMAT_PCM_FLOAT,
+};
+
+int PolicyAudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
+{
+    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
+    // compressed format and better than any PCM format. This is by design of pickFormat()
+    if (!audio_is_linear_pcm(format1)) {
+        if (!audio_is_linear_pcm(format2)) {
+            return 0;
+        }
+        return 1;
+    }
+    if (!audio_is_linear_pcm(format2)) {
+        return -1;
+    }
+
+    int index1 = -1, index2 = -1;
+    for (size_t i = 0;
+            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
+            i ++) {
+        if (sPcmFormatCompareTable[i] == format1) {
+            index1 = i;
+        }
+        if (sPcmFormatCompareTable[i] == format2) {
+            index2 = i;
+        }
+    }
+    // format1 not found => index1 < 0 => format2 > format1
+    // format2 not found => index2 < 0 => format2 < format1
+    return index1 - index2;
+}
+
+uint32_t PolicyAudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
+{
+    if (format1 == format2) {
+        return 0;
+    }
+    if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
+        return kFormatDistanceMax;
+    }
+    int diffBytes = (int)audio_bytes_per_sample(format1) -
+            audio_bytes_per_sample(format2);
+
+    return abs(diffBytes);
+}
+
+bool PolicyAudioPort::isBetterFormatMatch(audio_format_t newFormat,
+                                          audio_format_t currentFormat,
+                                          audio_format_t targetFormat)
+{
+    return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
+}
+
+void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
+                                       audio_channel_mask_t &channelMask,
+                                       audio_format_t &format) const
+{
+    format = AUDIO_FORMAT_DEFAULT;
+    samplingRate = 0;
+    channelMask = AUDIO_CHANNEL_NONE;
+
+    // special case for uninitialized dynamic profile
+    if (!asAudioPort()->hasValidAudioProfile()) {
+        return;
+    }
+    audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
+    // For mixed output and inputs, use best mixer output format.
+    // Do not limit format otherwise
+    if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
+        bestFormat = AUDIO_FORMAT_INVALID;
+    }
+
+    const AudioProfileVector& audioProfiles = asAudioPort()->getAudioProfiles();
+    for (size_t i = 0; i < audioProfiles.size(); i ++) {
+        if (!audioProfiles[i]->isValid()) {
+            continue;
+        }
+        audio_format_t formatToCompare = audioProfiles[i]->getFormat();
+        if ((compareFormats(formatToCompare, format) > 0) &&
+                (compareFormats(formatToCompare, bestFormat) <= 0)) {
+            uint32_t pickedSamplingRate = 0;
+            audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
+            pickChannelMask(pickedChannelMask, audioProfiles[i]->getChannels());
+            pickSamplingRate(pickedSamplingRate, audioProfiles[i]->getSampleRates());
+
+            if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
+                    && pickedSamplingRate != 0) {
+                format = formatToCompare;
+                channelMask = pickedChannelMask;
+                samplingRate = pickedSamplingRate;
+                // TODO: shall we return on the first one or still trying to pick a better Profile?
+            }
+        }
+    }
+    ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__,
+            asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
+}
+
+// --- PolicyAudioPortConfig class implementation
+
+status_t PolicyAudioPortConfig::validationBeforeApplyConfig(
+        const struct audio_port_config *config) const
+{
+    sp<PolicyAudioPort> policyAudioPort = getPolicyAudioPort();
+    return policyAudioPort ? policyAudioPort->checkExactAudioProfile(config) : NO_INIT;
+}
+
+void PolicyAudioPortConfig::toPolicyAudioPortConfig(struct audio_port_config *dstConfig,
+                                                    const struct audio_port_config *srcConfig) const
+{
+    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+        if ((srcConfig != nullptr) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS)) {
+            dstConfig->flags = srcConfig->flags;
+        } else {
+            dstConfig->flags = mFlags;
+        }
+    } else {
+        dstConfig->flags = { AUDIO_INPUT_FLAG_NONE };
+    }
+}
+
+
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 5f820c2..883e713 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -199,6 +199,8 @@
     struct Attributes
     {
         static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
+        static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
+        static constexpr const char *engineLibrarySuffix = "engine_library";
     };
 
     static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
@@ -406,8 +408,8 @@
             samplingRatesFromString(samplingRates, ","));
 
     profile->setDynamicFormat(profile->getFormat() == gDynamicFormat);
-    profile->setDynamicChannels(profile->getChannels().isEmpty());
-    profile->setDynamicRate(profile->getSampleRates().isEmpty());
+    profile->setDynamicChannels(profile->getChannels().empty());
+    profile->setDynamicRate(profile->getSampleRates().empty());
 
     return profile;
 }
@@ -430,16 +432,19 @@
     audio_port_role_t portRole = (role == Attributes::roleSource) ?
             AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
 
-    Element mixPort = new IOProfile(String8(name.c_str()), portRole);
+    Element mixPort = new IOProfile(name, portRole);
 
     AudioProfileTraits::Collection profiles;
     status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
     if (status != NO_ERROR) {
         return Status::fromStatusT(status);
     }
-    if (profiles.isEmpty()) {
-        profiles.add(AudioProfile::createFullDynamic());
+    if (profiles.empty()) {
+        profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
     }
+    // The audio profiles are in order of listed in audio policy configuration file.
+    // Sort audio profiles accroding to the format.
+    sortAudioProfiles(profiles);
     mixPort->setAudioProfiles(profiles);
 
     std::string flags = getXmlAttribute(child, Attributes::flags);
@@ -508,22 +513,20 @@
     if (!encodedFormatsLiteral.empty()) {
         encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
     }
-    Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str()));
-
     std::string address = getXmlAttribute(cur, Attributes::address);
-    if (!address.empty()) {
-        ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
-        deviceDesc->setAddress(String8(address.c_str()));
-    }
+    Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);
 
     AudioProfileTraits::Collection profiles;
     status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
     if (status != NO_ERROR) {
         return Status::fromStatusT(status);
     }
-    if (profiles.isEmpty()) {
-        profiles.add(AudioProfile::createFullDynamic());
+    if (profiles.empty()) {
+        profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
     }
+    // The audio profiles are in order of listed in audio policy configuration file.
+    // Sort audio profiles accroding to the format.
+    sortAudioProfiles(profiles);
     deviceDesc->setAudioProfiles(profiles);
 
     // Deserialize AudioGain children
@@ -532,7 +535,7 @@
         return Status::fromStatusT(status);
     }
     ALOGV("%s: adding device tag %s type %08x address %s", __func__,
-          deviceDesc->getName().string(), type, deviceDesc->address().string());
+          deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
     return deviceDesc;
 }
 
@@ -555,7 +558,7 @@
         return Status::fromStatusT(BAD_VALUE);
     }
     // Convert Sink name to port pointer
-    sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
+    sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
     if (sink == NULL) {
         ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
         return Status::fromStatusT(BAD_VALUE);
@@ -568,13 +571,13 @@
         return Status::fromStatusT(BAD_VALUE);
     }
     // Tokenize and Convert Sources name to port pointer
-    AudioPortVector sources;
+    PolicyAudioPortVector sources;
     std::unique_ptr<char[]> sourcesLiteral{strndup(
                 sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))};
     char *devTag = strtok(sourcesLiteral.get(), ",");
     while (devTag != NULL) {
         if (strlen(devTag) != 0) {
-            sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
+            sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
             if (source == NULL) {
                 ALOGE("%s: no source found with name=%s", __func__, devTag);
                 return Status::fromStatusT(BAD_VALUE);
@@ -586,7 +589,7 @@
 
     sink->addRoute(route);
     for (size_t i = 0; i < sources.size(); i++) {
-        sp<AudioPort> source = sources.itemAt(i);
+        sp<PolicyAudioPort> source = sources.itemAt(i);
         source->addRoute(route);
     }
     route->setSources(sources);
@@ -648,9 +651,9 @@
                         ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
                                 reinterpret_cast<const char*>(attachedDevice.get()));
                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
-                                getDeviceFromTagName(String8(reinterpret_cast<const char*>(
+                                getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
                                                         attachedDevice.get())));
-                        ctx->addAvailableDevice(device);
+                        ctx->addDevice(device);
                     }
                 }
             }
@@ -663,7 +666,7 @@
                 ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
                         reinterpret_cast<const char*>(defaultOutputDevice.get()));
                 sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
-                        String8(reinterpret_cast<const char*>(defaultOutputDevice.get())));
+                        std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
                 if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
                     ctx->setDefaultOutputDevice(device);
                     ALOGV("%s: default is %08x",
@@ -679,12 +682,20 @@
 {
     for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
-            std::string speakerDrcEnabled =
-                    getXmlAttribute(cur, Attributes::speakerDrcEnabled);
-            bool isSpeakerDrcEnabled;
-            if (!speakerDrcEnabled.empty() &&
-                    convertTo<std::string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
-                config->setSpeakerDrcEnabled(isSpeakerDrcEnabled);
+            bool value;
+            std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
+            if (!attr.empty() &&
+                    convertTo<std::string, bool>(attr, value)) {
+                config->setSpeakerDrcEnabled(value);
+            }
+            attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
+            if (!attr.empty() &&
+                    convertTo<std::string, bool>(attr, value)) {
+                config->setCallScreenModeSupported(value);
+            }
+            std::string engineLibrarySuffix = getXmlAttribute(cur, Attributes::engineLibrarySuffix);
+            if (!engineLibrarySuffix.empty()) {
+                config->setEngineLibraryNameSuffix(engineLibrarySuffix);
             }
             return NO_ERROR;
         }
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 2b5455e..c5b3546 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -55,9 +55,11 @@
     MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_USAGE),
     MAKE_STRING_FROM_ENUM(RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET),
     MAKE_STRING_FROM_ENUM(RULE_MATCH_UID),
+    MAKE_STRING_FROM_ENUM(RULE_MATCH_USERID),
     MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_ATTRIBUTE_USAGE),
     MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET),
     MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_UID),
+    MAKE_STRING_FROM_ENUM(RULE_EXCLUDE_USERID),
     TERMINATOR
 };
 
diff --git a/services/audiopolicy/config/Android.bp b/services/audiopolicy/config/Android.bp
new file mode 100644
index 0000000..f4610bb
--- /dev/null
+++ b/services/audiopolicy/config/Android.bp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+soong_namespace {
+}
+
+prebuilt_etc {
+    name: "a2dp_in_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":a2dp_in_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "a2dp_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":a2dp_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "audio_policy_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_configuration_generic",
+}
+prebuilt_etc {
+    name: "r_submix_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":r_submix_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "audio_policy_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_volumes",
+}
+prebuilt_etc {
+    name: "default_volume_tables.xml",
+    vendor: true,
+    src: ":default_volume_tables",
+}
+prebuilt_etc {
+    name: "surround_sound_configuration_5_0.xml",
+    vendor: true,
+    src: ":surround_sound_configuration_5_0",
+}
+prebuilt_etc {
+    name: "usb_audio_policy_configuration.xml",
+    vendor: true,
+    src: ":usb_audio_policy_configuration",
+}
+prebuilt_etc {
+    name: "primary_audio_policy_configuration.xml",
+    src: ":primary_audio_policy_configuration",
+    vendor: true,
+}
+
+filegroup {
+    name: "a2dp_in_audio_policy_configuration",
+    srcs: ["a2dp_in_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "a2dp_audio_policy_configuration",
+    srcs: ["a2dp_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "primary_audio_policy_configuration",
+    srcs: ["primary_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "surround_sound_configuration_5_0",
+    srcs: ["surround_sound_configuration_5_0.xml"],
+}
+filegroup {
+    name: "default_volume_tables",
+    srcs: ["default_volume_tables.xml"],
+}
+filegroup {
+    name: "audio_policy_volumes",
+    srcs: ["audio_policy_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_configuration_generic",
+    srcs: ["audio_policy_configuration_generic.xml"],
+}
+filegroup {
+    name: "audio_policy_configuration_generic_configurable",
+    srcs: ["audio_policy_configuration_generic_configurable.xml"],
+}
+filegroup {
+    name: "usb_audio_policy_configuration",
+    srcs: ["usb_audio_policy_configuration.xml"],
+}
+filegroup {
+    name: "r_submix_audio_policy_configuration",
+    srcs: ["r_submix_audio_policy_configuration.xml"],
+}
diff --git a/services/audiopolicy/config/audio_policy_configuration_generic_configurable.xml b/services/audiopolicy/config/audio_policy_configuration_generic_configurable.xml
new file mode 100644
index 0000000..fbe4f7f
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration_generic_configurable.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
+
+    <!-- Global configuration Decalaration -->
+    <globalConfiguration speaker_drc_enabled="false" engine_library="configurable"/>
+
+    <modules>
+        <!-- Primary Audio HAL -->
+        <xi:include href="primary_audio_policy_configuration.xml"/>
+
+        <!-- Remote Submix Audio HAL -->
+        <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+    </modules>
+    <!-- End of Modules section -->
+
+    <!-- Volume section:
+        IMPORTANT NOTE: Volume tables have been moved to engine configuration.
+                        Keep it here for legacy.
+                        Engine will fallback on these files if none are provided by engine.
+     -->
+
+    <xi:include href="audio_policy_volumes.xml"/>
+    <xi:include href="default_volume_tables.xml"/>
+
+    <!-- End of Volume section -->
+
+    <!-- Surround Sound configuration -->
+
+    <xi:include href="surround_sound_configuration_5_0.xml"/>
+
+    <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/audio_policy_volumes.xml b/services/audiopolicy/config/audio_policy_volumes.xml
index ec64a7c..1dec6f4 100644
--- a/services/audiopolicy/config/audio_policy_volumes.xml
+++ b/services/audiopolicy/config/audio_policy_volumes.xml
@@ -44,7 +44,7 @@
     <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
                                              ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
-                                             ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+                                             ref="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET">
         <point>1,-3000</point>
         <point>33,-2600</point>
@@ -181,6 +181,16 @@
                                                 ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
                                                 ref="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"/>
+    <volume stream="AUDIO_STREAM_ASSISTANT" deviceCategory="DEVICE_CATEGORY_HEADSET"
+                                                ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+    <volume stream="AUDIO_STREAM_ASSISTANT" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+                                                ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+    <volume stream="AUDIO_STREAM_ASSISTANT" deviceCategory="DEVICE_CATEGORY_EARPIECE"
+                                                ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+    <volume stream="AUDIO_STREAM_ASSISTANT" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
+                                                ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+    <volume stream="AUDIO_STREAM_ASSISTANT" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
+                                                ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_HEADSET"
                                             ref="FULL_SCALE_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_SPEAKER"
diff --git a/services/audiopolicy/config/msd_audio_policy_configuration.xml b/services/audiopolicy/config/msd_audio_policy_configuration.xml
index db17bc6..305cbe6 100644
--- a/services/audiopolicy/config/msd_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/msd_audio_policy_configuration.xml
@@ -40,7 +40,7 @@
                      channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
         </mixPort>
         <!-- The HW AV Sync flag is not required, but is recommended -->
-        <mixPort name="ms12 output" role="sink" flags="AUDIO_INPUT_FLAG_HW_AV_SYNC">
+        <mixPort name="ms12 output" role="sink" flags="AUDIO_INPUT_FLAG_HW_AV_SYNC|AUDIO_INPUT_FLAG_DIRECT">
             <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                      samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
             <profile name="" format="AUDIO_FORMAT_AC3"
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
old mode 100644
new mode 100755
index d0775ad..a1c69f2
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -25,6 +25,7 @@
         "src/ProductStrategy.cpp",
         "src/VolumeCurve.cpp",
         "src/VolumeGroup.cpp",
+        "src/LastRemovableMediaDevices.cpp",
     ],
     cflags: [
         "-Wall",
@@ -44,4 +45,7 @@
         "libaudiopolicycomponents",
         "libaudiopolicyengine_config",
     ],
+    shared_libs: [
+        "libaudiofoundation",
+    ],
 }
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
old mode 100644
new mode 100755
index cedc78f..7f339dc
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -17,18 +17,19 @@
 #pragma once
 
 #include <EngineConfig.h>
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <ProductStrategy.h>
 #include <VolumeGroup.h>
+#include <LastRemovableMediaDevices.h>
 
 namespace android {
 namespace audio_policy {
 
-class EngineBase : public AudioPolicyManagerInterface
+class EngineBase : public EngineInterface
 {
 public:
     ///
-    /// from AudioPolicyManagerInterface
+    /// from EngineInterface
     ///
     android::status_t initCheck() override;
 
@@ -49,10 +50,8 @@
         return mForceUse[usage];
     }
     android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> /*devDesc*/,
-                                               audio_policy_dev_state_t /*state*/) override
-    {
-        return NO_ERROR;
-    }
+                                               audio_policy_dev_state_t /*state*/) override;
+
     product_strategy_t getProductStrategyForAttributes(
             const audio_attributes_t &attr) const override;
 
@@ -86,8 +85,21 @@
 
     status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
 
+    std::vector<audio_devices_t> getLastRemovableMediaDevices(
+            device_out_group_t group = GROUP_NONE) const
+    {
+        return mLastRemovableMediaDevices.getLastRemovableMediaDevices(group);
+    }
+
     void dump(String8 *dst) const override;
 
+    status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+            const AudioDeviceTypeAddr &device) override;
+
+    status_t removePreferredDeviceForStrategy(product_strategy_t strategy) override;
+
+    status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device) const override;
 
     engineConfig::ParsingResult loadAudioPolicyEngineConfig();
 
@@ -115,11 +127,13 @@
 
     status_t restoreOriginVolumeCurve(audio_stream_type_t stream);
 
- private:
+private:
     AudioPolicyManagerObserver *mApmObserver = nullptr;
 
     ProductStrategyMap mProductStrategies;
+    ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
     VolumeGroupMap mVolumeGroups;
+    LastRemovableMediaDevices mLastRemovableMediaDevices;
     audio_mode_t mPhoneState = AUDIO_MODE_NORMAL;  /**< current phone state. */
 
     /** current forced use configuration. */
diff --git a/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
new file mode 100755
index 0000000..a3053a4
--- /dev/null
+++ b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
+#define ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
+
+#include <vector>
+#include <HwModule.h>
+#include <system/audio_policy.h>
+
+namespace android {
+
+typedef enum {
+    GROUP_NONE = -1,
+    GROUP_WIRED,
+    GROUP_BT_A2DP,
+    NUM_GROUP
+} device_out_group_t;
+
+class LastRemovableMediaDevices
+{
+public:
+    void setRemovableMediaDevices(sp<DeviceDescriptor> desc, audio_policy_dev_state_t state);
+    std::vector<audio_devices_t> getLastRemovableMediaDevices(
+            device_out_group_t group = GROUP_NONE) const;
+
+private:
+    struct DeviceGroupDescriptor {
+        sp<DeviceDescriptor> desc;
+        device_out_group_t group;
+    };
+    std::vector<DeviceGroupDescriptor> mMediaDevices;
+
+    device_out_group_t getDeviceOutGroup(audio_devices_t device) const;
+};
+
+} // namespace android
+
+#endif // ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 1a2a198..3ebe7d1 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -19,7 +19,6 @@
 #include "VolumeGroup.h"
 
 #include <system/audio.h>
-#include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
 #include <HandleGenerator.h>
 #include <string>
@@ -27,6 +26,9 @@
 #include <map>
 #include <utils/Errors.h>
 #include <utils/String8.h>
+#include <media/AudioAttributes.h>
+#include <media/AudioContainers.h>
+#include <media/AudioPolicy.h>
 
 namespace android {
 
@@ -77,12 +79,12 @@
 
     std::string getDeviceAddress() const { return mDeviceAddress; }
 
-    void setDeviceTypes(audio_devices_t devices)
+    void setDeviceTypes(const DeviceTypeSet& devices)
     {
         mApplicableDevices = devices;
     }
 
-    audio_devices_t getDeviceTypes() const { return mApplicableDevices; }
+    DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
 
     audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
     audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
@@ -109,7 +111,7 @@
     /**
      * Applicable device(s) type mask for this strategy.
      */
-    audio_devices_t mApplicableDevices = AUDIO_DEVICE_NONE;
+    DeviceTypeSet mApplicableDevices;
 };
 
 class ProductStrategyMap : public std::map<product_strategy_t, sp<ProductStrategy> >
@@ -144,7 +146,7 @@
      */
     audio_attributes_t getAttributesForProductStrategy(product_strategy_t strategy) const;
 
-    audio_devices_t getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
+    DeviceTypeSet getDeviceTypesForProductStrategy(product_strategy_t strategy) const;
 
     std::string getDeviceAddressForProductStrategy(product_strategy_t strategy) const;
 
@@ -162,4 +164,10 @@
     product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
 };
 
+class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t, AudioDeviceTypeAddr>
+{
+public:
+    void dump(String8 *dst, int spaces = 0) const;
+};
+
 } // namespace android
diff --git a/services/audiopolicy/engine/common/include/VolumeCurve.h b/services/audiopolicy/engine/common/include/VolumeCurve.h
index 54314e3..2e75ff1 100644
--- a/services/audiopolicy/engine/common/include/VolumeCurve.h
+++ b/services/audiopolicy/engine/common/include/VolumeCurve.h
@@ -18,7 +18,6 @@
 
 #include "IVolumeCurves.h"
 #include <policy.h>
-#include <AudioPolicyManagerInterface.h>
 #include <utils/RefBase.h>
 #include <HandleGenerator.h>
 #include <utils/String8.h>
@@ -92,9 +91,9 @@
         return valueFor(device);
     }
 
-    virtual int getVolumeIndex(audio_devices_t device) const
+    virtual int getVolumeIndex(const DeviceTypeSet& deviceTypes) const
     {
-        device = Volume::getDeviceForVolume(device);
+        audio_devices_t device = Volume::getDeviceForVolume(deviceTypes);
         // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
         if (mIndexCur.find(device) == end(mIndexCur)) {
             device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
@@ -115,7 +114,7 @@
 
     bool hasVolumeIndexForDevice(audio_devices_t device) const
     {
-        device = Volume::getDeviceForVolume(device);
+        device = Volume::getDeviceForVolume({device});
         return mIndexCur.find(device) != end(mIndexCur);
     }
 
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
index c34b406..5378f64 100644
--- a/services/audiopolicy/engine/common/include/VolumeGroup.h
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <AudioPolicyManagerInterface.h>
 #include <VolumeCurve.h>
 #include <system/audio.h>
 #include <utils/RefBase.h>
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 07a7e65..1bc7fe3 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -39,7 +39,7 @@
 {
     ALOGV("setPhoneState() state %d", state);
 
-    if (state < 0 || state >= AUDIO_MODE_CNT) {
+    if (state < 0 || uint32_t(state) >= AUDIO_MODE_CNT) {
         ALOGW("setPhoneState() invalid state %d", state);
         return BAD_VALUE;
     }
@@ -63,6 +63,17 @@
     return NO_ERROR;
 }
 
+status_t EngineBase::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                              audio_policy_dev_state_t state)
+{
+    audio_devices_t deviceType = devDesc->type();
+    if ((deviceType != AUDIO_DEVICE_NONE) && audio_is_output_device(deviceType)) {
+        mLastRemovableMediaDevices.setRemovableMediaDevices(devDesc, state);
+    }
+
+    return NO_ERROR;
+}
+
 product_strategy_t EngineBase::getProductStrategyForAttributes(const audio_attributes_t &attr) const
 {
     return mProductStrategies.getProductStrategyForAttributes(attr);
@@ -95,48 +106,48 @@
 
 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
 {
-    auto loadProductStrategies =
-            [](auto& strategyConfigs, auto& productStrategies, auto& volumeGroups) {
-        for (auto& strategyConfig : strategyConfigs) {
-            sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
-            for (const auto &group : strategyConfig.attributesGroups) {
-                const auto &iter = std::find_if(begin(volumeGroups), end(volumeGroups),
-                                         [&group](const auto &volumeGroup) {
-                        return group.volumeGroup == volumeGroup.second->getName(); });
-                ALOG_ASSERT(iter != end(volumeGroups), "Invalid Volume Group Name %s",
-                            group.volumeGroup.c_str());
-                if (group.stream != AUDIO_STREAM_DEFAULT) {
-                    iter->second->addSupportedStream(group.stream);
-                }
-                for (const auto &attr : group.attributesVect) {
-                    strategy->addAttributes({group.stream, iter->second->getId(), attr});
-                    iter->second->addSupportedAttributes(attr);
-                }
-            }
-            product_strategy_t strategyId = strategy->getId();
-            productStrategies[strategyId] = strategy;
-        }
-    };
-    auto loadVolumeGroups = [](auto &volumeConfigs, auto &volumeGroups) {
-        for (auto &volumeConfig : volumeConfigs) {
-            sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
-                                                          volumeConfig.indexMax);
-            volumeGroups[volumeGroup->getId()] = volumeGroup;
+    auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
+        // Ensure name unicity to prevent duplicate
+        LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
+                                     [&volumeConfig](const auto &volumeGroup) {
+                return volumeConfig.name == volumeGroup.second->getName(); }),
+                            "group name %s defined twice, review the configuration",
+                            volumeConfig.name.c_str());
 
-            for (auto &configCurve : volumeConfig.volumeCurves) {
-                device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
-                if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
-                    ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
-                    continue;
-                }
-                sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
-                for (auto &point : configCurve.curvePoints) {
-                    curve->add({point.index, point.attenuationInMb});
-                }
-                volumeGroup->add(curve);
+        sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
+                                                      volumeConfig.indexMax);
+        volumeGroups[volumeGroup->getId()] = volumeGroup;
+
+        for (auto &configCurve : volumeConfig.volumeCurves) {
+            device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
+            if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
+                ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
+                continue;
             }
+            sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
+            for (auto &point : configCurve.curvePoints) {
+                curve->add({point.index, point.attenuationInMb});
+            }
+            volumeGroup->add(curve);
+        }
+        return volumeGroup;
+    };
+    auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
+        for (const auto &attr : group.attributesVect) {
+            strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
+            volumeGroup->addSupportedAttributes(attr);
         }
     };
+    auto checkStreamForGroups = [](auto streamType, const auto &volumeGroups) {
+        const auto &iter = std::find_if(std::begin(volumeGroups), std::end(volumeGroups),
+                                     [&streamType](const auto &volumeGroup) {
+            const auto& streams = volumeGroup.second->getStreamTypes();
+            return std::find(std::begin(streams), std::end(streams), streamType) !=
+                    std::end(streams);
+        });
+        return iter != end(volumeGroups);
+    };
+
     auto result = engineConfig::parse();
     if (result.parsedConfig == nullptr) {
         ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
@@ -144,11 +155,67 @@
         android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
         result = {std::make_unique<engineConfig::Config>(config),
                   static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
+    } else {
+        // Append for internal use only volume groups (e.g. rerouting/patch)
+        result.parsedConfig->volumeGroups.insert(
+                    std::end(result.parsedConfig->volumeGroups),
+                    std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
     }
+    // Append for internal use only strategies (e.g. rerouting/patch)
+    result.parsedConfig->productStrategies.insert(
+                std::end(result.parsedConfig->productStrategies),
+                std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
+
+
     ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-    loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
-    loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies,
-                          mVolumeGroups);
+
+    engineConfig::VolumeGroup defaultVolumeConfig;
+    engineConfig::VolumeGroup defaultSystemVolumeConfig;
+    for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
+        // save default volume config for streams not defined in configuration
+        if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
+            defaultVolumeConfig = volumeConfig;
+        }
+        if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
+            defaultSystemVolumeConfig = volumeConfig;
+        }
+        loadVolumeConfig(mVolumeGroups, volumeConfig);
+    }
+    for (auto& strategyConfig : result.parsedConfig->productStrategies) {
+        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
+        for (const auto &group : strategyConfig.attributesGroups) {
+            const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
+                                         [&group](const auto &volumeGroup) {
+                    return group.volumeGroup == volumeGroup.second->getName(); });
+            sp<VolumeGroup> volumeGroup = nullptr;
+            // If no volume group provided for this strategy, creates a new one using
+            // Music Volume Group configuration (considered as the default)
+            if (iter == end(mVolumeGroups)) {
+                engineConfig::VolumeGroup volumeConfig;
+                if (group.stream >= AUDIO_STREAM_PUBLIC_CNT) {
+                    volumeConfig = defaultSystemVolumeConfig;
+                } else {
+                    volumeConfig = defaultVolumeConfig;
+                }
+                ALOGW("%s: No configuration of %s found, using default volume configuration"
+                        , __FUNCTION__, group.volumeGroup.c_str());
+                volumeConfig.name = group.volumeGroup;
+                volumeGroup = loadVolumeConfig(mVolumeGroups, volumeConfig);
+            } else {
+                volumeGroup = iter->second;
+            }
+            if (group.stream != AUDIO_STREAM_DEFAULT) {
+                // A legacy stream can be assigned once to a volume group
+                LOG_ALWAYS_FATAL_IF(checkStreamForGroups(group.stream, mVolumeGroups),
+                                    "stream %s already assigned to a volume group, "
+                                    "review the configuration", toString(group.stream).c_str());
+                volumeGroup->addSupportedStream(group.stream);
+            }
+            addSupportedAttributesToGroup(group, volumeGroup, strategy);
+        }
+        product_strategy_t strategyId = strategy->getId();
+        mProductStrategies[strategyId] = strategy;
+    }
     mProductStrategies.initialize();
     return result;
 }
@@ -272,9 +339,57 @@
     return NO_ERROR;
 }
 
+status_t EngineBase::setPreferredDeviceForStrategy(product_strategy_t strategy,
+            const AudioDeviceTypeAddr &device)
+{
+    // verify strategy exists
+    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
+        ALOGE("%s invalid strategy %u", __func__, strategy);
+        return BAD_VALUE;
+    }
+
+    mProductStrategyPreferredDevices[strategy] = device;
+    return NO_ERROR;
+}
+
+status_t EngineBase::removePreferredDeviceForStrategy(product_strategy_t strategy)
+{
+    // verify strategy exists
+    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
+        ALOGE("%s invalid strategy %u", __func__, strategy);
+        return BAD_VALUE;
+    }
+
+    if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
+        // no preferred device was set
+        return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+status_t EngineBase::getPreferredDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device) const
+{
+    // verify strategy exists
+    if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
+        ALOGE("%s unknown strategy %u", __func__, strategy);
+        return BAD_VALUE;
+    }
+    // preferred device for this strategy?
+    auto devIt = mProductStrategyPreferredDevices.find(strategy);
+    if (devIt == mProductStrategyPreferredDevices.end()) {
+        ALOGV("%s no preferred device for strategy %u", __func__, strategy);
+        return NAME_NOT_FOUND;
+    }
+
+    device = devIt->second;
+    return NO_ERROR;
+}
+
 void EngineBase::dump(String8 *dst) const
 {
     mProductStrategies.dump(dst, 2);
+    mProductStrategyPreferredDevices.dump(dst, 2);
     mVolumeGroups.dump(dst, 2);
 }
 
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index fede0d9..981582e 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -81,6 +81,10 @@
     },
     {"STRATEGY_MEDIA",
      {
+         {"assistant", AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
+          {{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
+            AUDIO_SOURCE_DEFAULT, 0, ""}}
+         },
          {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, 0, ""},
@@ -107,6 +111,13 @@
          }
      },
     },
+    {"STRATEGY_CALL_ASSISTANT",
+     {
+         {"", AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""}}
+         }
+     },
+    },
     {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
      {
          {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
@@ -114,15 +125,22 @@
             AUDIO_FLAG_BEACON, ""}}
          }
      },
-    },
-    {"STRATEGY_REROUTING",
+    }
+};
+
+/**
+ * For Internal use of respectively audio policy and audioflinger
+ * For compatibility reason why apm volume config file, volume group name is the stream type.
+ */
+const engineConfig::ProductStrategies gOrderedSystemStrategies = {
+    {"rerouting",
      {
          {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
          }
      },
     },
-    {"STRATEGY_PATCH",
+    {"patch",
      {
          {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, 0, ""}}
@@ -130,6 +148,28 @@
      },
     }
 };
+const engineConfig::VolumeGroups gSystemVolumeGroups = {
+    {"AUDIO_STREAM_REROUTING", 0, 1,
+     {
+         {"DEVICE_CATEGORY_SPEAKER", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_HEADSET", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_EARPIECE", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_EXT_MEDIA", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_HEARING_AID", {{0,0}, {100, 0}}},
+
+     }
+    },
+    {"AUDIO_STREAM_PATCH", 0, 1,
+     {
+         {"DEVICE_CATEGORY_SPEAKER", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_HEADSET", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_EARPIECE", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_EXT_MEDIA", {{0,0}, {100, 0}}},
+         {"DEVICE_CATEGORY_HEARING_AID", {{0,0}, {100, 0}}},
+
+     }
+    }
+};
 
 const engineConfig::Config gDefaultEngineConfig = {
     1.0,
diff --git a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
new file mode 100755
index 0000000..87b6aaf
--- /dev/null
+++ b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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_TAG "APM::AudioPolicyEngine/LastRemovableMediaDevices"
+//#define LOG_NDEBUG 0
+
+#include "LastRemovableMediaDevices.h"
+#include <log/log.h>
+
+namespace android {
+
+void LastRemovableMediaDevices::setRemovableMediaDevices(sp<DeviceDescriptor> desc,
+                                                         audio_policy_dev_state_t state)
+{
+    if (desc == nullptr) {
+        return;
+    } else {
+        if ((state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) &&
+                (getDeviceOutGroup(desc->type()) != GROUP_NONE)) {
+            setRemovableMediaDevices(desc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+            mMediaDevices.insert(mMediaDevices.begin(), {desc, getDeviceOutGroup(desc->type())});
+        } else if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+            for (auto iter = mMediaDevices.begin(); iter != mMediaDevices.end(); ++iter) {
+                if ((iter->desc)->equals(desc)) {
+                    mMediaDevices.erase(iter);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+std::vector<audio_devices_t> LastRemovableMediaDevices::getLastRemovableMediaDevices(
+        device_out_group_t group) const
+{
+    std::vector<audio_devices_t> ret;
+    for (auto iter = mMediaDevices.begin(); iter != mMediaDevices.end(); ++iter) {
+        if ((group == GROUP_NONE) || (group == getDeviceOutGroup((iter->desc)->type()))) {
+            ret.push_back((iter->desc)->type());
+        }
+    }
+    return ret;
+}
+
+device_out_group_t LastRemovableMediaDevices::getDeviceOutGroup(audio_devices_t device) const
+{
+    switch (device) {
+    case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+    case AUDIO_DEVICE_OUT_LINE:
+    case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+    case AUDIO_DEVICE_OUT_USB_HEADSET:
+    case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+    case AUDIO_DEVICE_OUT_USB_DEVICE:
+    case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
+        return GROUP_WIRED;
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+        return GROUP_BT_A2DP;
+    default:
+        return GROUP_NONE;
+    }
+}
+
+} // namespace android
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index f74f190..151c7bb 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -19,6 +19,7 @@
 
 #include "ProductStrategy.h"
 
+#include <media/AudioProductStrategy.h>
 #include <media/TypeConverter.h>
 #include <utils/String8.h>
 #include <cstdint>
@@ -72,10 +73,18 @@
 audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
         const audio_attributes_t &attr) const
 {
-    const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
+    const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
                                    [&attr](const auto &supportedAttr) {
         return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
-    return iter != end(mAttributesVector) ? iter->mStream : AUDIO_STREAM_DEFAULT;
+    if (iter == end(mAttributesVector)) {
+        return AUDIO_STREAM_DEFAULT;
+    }
+    audio_stream_type_t streamType = iter->mStream;
+    ALOGW_IF(streamType == AUDIO_STREAM_DEFAULT,
+             "%s: Strategy %s supporting attributes %s has not stream type associated"
+             "fallback on MUSIC. Do not use stream volume API", __func__, mName.c_str(),
+             toString(attr).c_str());
+    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
 }
 
 audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
@@ -142,8 +151,9 @@
 {
     dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
     std::string deviceLiteral;
-    if (!OutputDeviceConverter::toString(mApplicableDevices, deviceLiteral)) {
-        ALOGE("%s: failed to convert device %d", __FUNCTION__, mApplicableDevices);
+    if (!deviceTypesToString(mApplicableDevices, deviceLiteral)) {
+        ALOGE("%s: failed to convert device %s",
+              __FUNCTION__, dumpDeviceTypes(mApplicableDevices).c_str());
     }
     dst->appendFormat("%*sSelected Device: {type:%s, @:%s}\n", spaces + 2, "",
                        deviceLiteral.c_str(), mDeviceAddress.c_str());
@@ -235,14 +245,14 @@
 }
 
 
-audio_devices_t ProductStrategyMap::getDeviceTypesForProductStrategy(
+DeviceTypeSet ProductStrategyMap::getDeviceTypesForProductStrategy(
         product_strategy_t strategy) const
 {
     if (find(strategy) == end()) {
         ALOGE("Invalid %d strategy requested, returning device for default strategy", strategy);
         product_strategy_t defaultStrategy = getDefault();
         if (defaultStrategy == PRODUCT_STRATEGY_NONE) {
-            return AUDIO_DEVICE_NONE;
+            return {AUDIO_DEVICE_NONE};
         }
         return at(getDefault())->getDeviceTypes();
     }
@@ -308,5 +318,15 @@
     }
 }
 
+void ProductStrategyPreferredRoutingMap::dump(android::String8* dst, int spaces) const {
+    dst->appendFormat("\n%*sPreferred devices per product strategy dump:", spaces, "");
+    for (const auto& iter : *this) {
+        dst->appendFormat("\n%*sStrategy %u dev:%08x addr:%s",
+                          spaces + 2, "",
+                          (uint32_t) iter.first,
+                          iter.second.mType, iter.second.mAddress.c_str());
+    }
+    dst->appendFormat("\n");
+}
 }
 
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 6e72f2a..ff840f9 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -1,9 +1,8 @@
-cc_library_static {
+cc_library {
     name: "libaudiopolicyengine_config",
     export_include_dirs: ["include"],
     include_dirs: [
         "external/libxml2/include",
-        "external/icu/icu4c/source/common",
     ],
     srcs: [
         "src/EngineConfig.cpp",
@@ -15,17 +14,14 @@
     ],
     shared_libs: [
         "libmedia_helper",
-        "libandroidicu",
         "libxml2",
         "libutils",
         "liblog",
         "libcutils",
     ],
-    static_libs: [
-        "libaudiopolicycomponents",
-    ],
     header_libs: [
         "libaudio_system_headers",
-        "libaudiopolicycommon",
+        "libmedia_headers",
+        "libaudioclient_headers",
     ],
 }
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 7f5ed5e..5d22c24 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -31,9 +31,6 @@
 /** Default path of audio policy usages configuration file. */
 constexpr char DEFAULT_PATH[] = "/vendor/etc/audio_policy_engine_configuration.xml";
 
-/** Directories where the effect libraries will be search for. */
-constexpr const char* POLICY_USAGE_LIBRARY_PATH[] = {"/odm/etc/", "/vendor/etc/", "/system/etc/"};
-
 using AttributesVector = std::vector<audio_attributes_t>;
 using StreamVector = std::vector<audio_stream_type_t>;
 
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 1ad7739..4842cb2 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -18,10 +18,10 @@
 //#define LOG_NDEBUG 0
 
 #include "EngineConfig.h"
-#include <policy.h>
 #include <cutils/properties.h>
 #include <media/TypeConverter.h>
 #include <media/convert.h>
+#include <system/audio_config.h>
 #include <utils/Log.h>
 #include <libxml/parser.h>
 #include <libxml/xinclude.h>
@@ -32,9 +32,9 @@
 #include <istream>
 
 #include <cstdint>
+#include <stdarg.h>
 #include <string>
 
-
 namespace android {
 
 using utilities::convertTo;
@@ -603,7 +603,39 @@
     return NO_ERROR;
 }
 
+namespace {
+
+class XmlErrorHandler {
+public:
+    XmlErrorHandler() {
+        xmlSetGenericErrorFunc(this, &xmlErrorHandler);
+    }
+    XmlErrorHandler(const XmlErrorHandler&) = delete;
+    XmlErrorHandler(XmlErrorHandler&&) = delete;
+    XmlErrorHandler& operator=(const XmlErrorHandler&) = delete;
+    XmlErrorHandler& operator=(XmlErrorHandler&&) = delete;
+    ~XmlErrorHandler() {
+        xmlSetGenericErrorFunc(NULL, NULL);
+        if (!mErrorMessage.empty()) {
+            ALOG(LOG_ERROR, "libxml2", "%s", mErrorMessage.c_str());
+        }
+    }
+    static void xmlErrorHandler(void* ctx, const char* msg, ...) {
+        char buffer[256];
+        va_list args;
+        va_start(args, msg);
+        vsnprintf(buffer, sizeof(buffer), msg, args);
+        va_end(args);
+        static_cast<XmlErrorHandler*>(ctx)->mErrorMessage += buffer;
+    }
+private:
+    std::string mErrorMessage;
+};
+
+}  // namespace
+
 ParsingResult parse(const char* path) {
+    XmlErrorHandler errorHandler;
     xmlDocPtr doc;
     doc = xmlParseFile(path);
     if (doc == NULL) {
@@ -641,6 +673,7 @@
 }
 
 android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups) {
+    XmlErrorHandler errorHandler;
     xmlDocPtr doc;
     doc = xmlParseFile(path);
     if (doc == NULL) {
@@ -661,9 +694,6 @@
     return deserializeLegacyVolumeCollection(doc, cur, volumeGroups, nbSkippedElements);
 }
 
-static const char *kConfigLocationList[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
-static const int kConfigLocationListSize =
-        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
 static const int gApmXmlConfigFilePathMaxLength = 128;
 
 static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml";
@@ -683,9 +713,9 @@
     fileNames.push_back(apmXmlConfigFileName);
 
     for (const char* fileName : fileNames) {
-        for (int i = 0; i < kConfigLocationListSize; i++) {
+        for (const auto& path : audio_get_configuration_paths()) {
             snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
-                     "%s/%s", kConfigLocationList[i], fileName);
+                     "%s/%s", path.c_str(), fileName);
             ret = parseLegacyVolumeFile(audioPolicyXmlConfigFile, volumeGroups);
             if (ret == NO_ERROR) {
                 return ret;
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
deleted file mode 100644
index b7fd031..0000000
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-#include <AudioPolicyManagerObserver.h>
-#include <media/AudioProductStrategy.h>
-#include <media/AudioVolumeGroup.h>
-#include <IVolumeCurves.h>
-#include <policy.h>
-#include <Volume.h>
-#include <HwModule.h>
-#include <DeviceDescriptor.h>
-#include <system/audio.h>
-#include <system/audio_policy.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
-using StrategyVector = std::vector<product_strategy_t>;
-using VolumeGroupVector = std::vector<volume_group_t>;
-
-/**
- * This interface is dedicated to the policy manager that a Policy Engine shall implement.
- */
-class AudioPolicyManagerInterface
-{
-public:
-    /**
-     * Checks if the engine was correctly initialized.
-     *
-     * @return NO_ERROR if initialization has been done correctly, error code otherwise..
-     */
-    virtual status_t initCheck() = 0;
-
-    /**
-     * Sets the Manager observer that allows the engine to retrieve information on collection
-     * of devices, streams, HwModules, ...
-     *
-     * @param[in] observer handle on the manager.
-     */
-    virtual void setObserver(AudioPolicyManagerObserver *observer) = 0;
-
-    /**
-     * Set the Telephony Mode.
-     *
-     * @param[in] mode: Android Phone state (normal, ringtone, csv, in communication)
-     *
-     * @return NO_ERROR if Telephony Mode set correctly, error code otherwise.
-     */
-    virtual status_t setPhoneState(audio_mode_t mode) = 0;
-
-    /**
-     * Get the telephony Mode
-     *
-     * @return the current telephony mode
-     */
-    virtual audio_mode_t getPhoneState() const = 0;
-
-    /**
-     * Set Force Use config for a given usage.
-     *
-     * @param[in] usage for which a configuration shall be forced.
-     * @param[in] config wished to be forced for the given usage.
-     *
-     * @return NO_ERROR if the Force Use config was set correctly, error code otherwise (e.g. config
-     * not allowed a given usage...)
-     */
-    virtual status_t setForceUse(audio_policy_force_use_t usage,
-                                 audio_policy_forced_cfg_t config) = 0;
-
-    /**
-     * Get Force Use config for a given usage.
-     *
-     * @param[in] usage for which a configuration shall be forced.
-     *
-     * @return config wished to be forced for the given usage.
-     */
-    virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const = 0;
-
-    /**
-     * Set the connection state of device(s).
-     *
-     * @param[in] devDesc for which the state has changed.
-     * @param[in] state of availability of this(these) device(s).
-     *
-     * @return NO_ERROR if devices criterion updated correctly, error code otherwise.
-     */
-    virtual status_t setDeviceConnectionState(const android::sp<android::DeviceDescriptor> devDesc,
-                                              audio_policy_dev_state_t state) = 0;
-
-    /**
-     * Get the strategy selected for a given audio attributes.
-     *
-     * @param[in] audio attributes to get the selected @product_strategy_t followed by.
-     *
-     * @return @product_strategy_t to be followed.
-     */
-    virtual product_strategy_t getProductStrategyForAttributes(
-            const audio_attributes_t &attr) const = 0;
-
-    /**
-     * @brief getOutputDevicesForAttributes retrieves the devices to be used for given
-     * audio attributes.
-     * @param attributes of the output requesting Device(s) selection
-     * @param preferedDevice valid reference if a prefered device is requested, nullptr otherwise.
-     * @param fromCache if true, the device is returned from internal cache,
-     *                  otherwise it is determined by current state (device connected,phone state,
-     *                  force use, a2dp output...)
-     * @return vector of selected device descriptors.
-     *         Appropriate device for streams handled by the specified audio attributes according
-     *         to current phone state, forced states, connected devices...
-     *         if fromCache is true, the device is returned from internal cache,
-     *         otherwise it is determined by current state (device connected,phone state, force use,
-     *         a2dp output...)
-     * This allows to:
-     *      1 speed up process when the state is stable (when starting or stopping an output)
-     *      2 access to either current device selection (fromCache == true) or
-     *      "future" device selection (fromCache == false) when called from a context
-     *      where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
-     *      before manager updates its outputs.
-     */
-    virtual DeviceVector getOutputDevicesForAttributes(
-            const audio_attributes_t &attributes,
-            const sp<DeviceDescriptor> &preferedDevice = nullptr,
-            bool fromCache = false) const = 0;
-
-    /**
-     * @brief getOutputDevicesForStream Legacy function retrieving devices from a stream type.
-     * @param stream type of the output requesting Device(s) selection
-     * @param fromCache if true, the device is returned from internal cache,
-     *                  otherwise it is determined by current state (device connected,phone state,
-     *                  force use, a2dp output...)
-     * @return appropriate device for streams handled by the specified audio attributes according
-     *         to current phone state, forced states, connected devices...
-     *         if fromCache is true, the device is returned from internal cache,
-     *         otherwise it is determined by current state (device connected,phone state, force use,
-     *         a2dp output...)
-     * This allows to:
-     *      1 speed up process when the state is stable (when starting or stopping an output)
-     *      2 access to either current device selection (fromCache == true) or
-     *      "future" device selection (fromCache == false) when called from a context
-     *      where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
-     *      before manager updates its outputs.
-     */
-    virtual DeviceVector getOutputDevicesForStream(audio_stream_type_t stream,
-                                                   bool fromCache = false) const = 0;
-
-    /**
-     * Get the input device selected for given audio attributes.
-     *
-     * @param[in] attr audio attributes to consider
-     * @param[out] mix to be used if a mix has been installed for the given audio attributes.
-     * @return selected input device for the audio attributes, may be null if error.
-     */
-    virtual sp<DeviceDescriptor> getInputDeviceForAttributes(
-            const audio_attributes_t &attr, sp<AudioPolicyMix> *mix = nullptr) const = 0;
-
-    /**
-     * Get the legacy stream type for a given audio attributes.
-     *
-     * @param[in] audio attributes to get the associated audio_stream_type_t.
-     *
-     * @return audio_stream_type_t associated to the attributes.
-     */
-    virtual audio_stream_type_t getStreamTypeForAttributes(
-            const audio_attributes_t &attr) const = 0;
-
-    /**
-     * @brief getAttributesForStream get the audio attributes from legacy stream type
-     * Attributes returned might only be used to check upon routing decision, not volume decisions.
-     * @param stream to consider
-     * @return audio attributes matching the legacy stream type
-     */
-    virtual audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const = 0;
-
-    /**
-     * @brief getStreamTypesForProductStrategy retrieves the list of legacy stream type following
-     * the given product strategy
-     * @param ps product strategy to consider
-     * @return associated legacy Stream Types vector of the given product strategy
-     */
-    virtual StreamTypeVector getStreamTypesForProductStrategy(product_strategy_t ps) const = 0;
-
-    /**
-     * @brief getAllAttributesForProductStrategy retrieves all the attributes following the given
-     * product strategy. Any attributes that "matches" with this one will follow the product
-     * strategy.
-     * "matching" means the usage shall match if reference attributes has a defined usage, AND
-     * content type shall match if reference attributes has a defined content type AND
-     * flags shall match if reference attributes has defined flags AND
-     * tags shall match if reference attributes has defined tags.
-     * @param ps product strategy to consider
-     * @return vector of product strategy ids, empty if unknown strategy.
-     */
-    virtual AttributesVector getAllAttributesForProductStrategy(product_strategy_t ps) const = 0;
-
-    /**
-     * @brief getOrderedAudioProductStrategies
-     * @return priority ordered product strategies to help the AudioPolicyManager evaluating the
-     * device selection per output according to the prioritized strategies.
-     */
-    virtual StrategyVector getOrderedProductStrategies() const = 0;
-
-    /**
-     * @brief updateDeviceSelectionCache. Device selection for AudioAttribute / Streams is cached
-     * in the engine in order to speed up process when the audio system is stable.
-     * When a device is connected, the android mode is changed, engine is notified and can update
-     * the cache.
-     * When starting / stopping an output with a stream that can affect notification, the engine
-     * needs to update the cache upon this function call.
-     */
-    virtual void updateDeviceSelectionCache() = 0;
-
-    /**
-     * @brief listAudioProductStrategies. Introspection API to retrieve a collection of
-     * AudioProductStrategyVector that allows to build AudioAttributes according to a
-     * product_strategy which is just an index. It has also a human readable name to help the
-     * Car/Oem/AudioManager identiying the use case.
-     * @param strategies collection.
-     * @return OK if the list has been retrieved, error code otherwise
-     */
-    virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const = 0;
-
-    /**
-     * @brief getVolumeCurvesForAttributes retrieves the Volume Curves interface for the
-     *        requested Audio Attributes.
-     * @param attr to be considered
-     * @return IVolumeCurves interface pointer if found, nullptr otherwise
-     */
-    virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const = 0;
-
-    /**
-     * @brief getVolumeCurvesForStreamType retrieves the Volume Curves interface for the stream
-     * @param stream to be considered
-     * @return IVolumeCurves interface pointer if found, nullptr otherwise
-     */
-    virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const = 0;
-
-    /**
-     * @brief getVolumeCurvesForVolumeGroup retrieves the Volume Curves interface for volume group
-     * @param group to be considered
-     * @return IVolumeCurves interface pointer if found, nullptr otherwise
-     */
-    virtual IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const = 0;
-
-    /**
-     * @brief getVolumeGroups retrieves the collection of volume groups.
-     * @return vector of volume groups
-     */
-    virtual VolumeGroupVector getVolumeGroups() const = 0;
-
-    /**
-     * @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
-     * Audio Attributes.
-     * @param attr to be considered
-     * @return volume group associated to the given audio attributes, default group if none
-     * applicable, VOLUME_GROUP_NONE if no default group defined.
-     */
-    virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
-
-    /**
-     * @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
-     * legacy stream type
-     * @param stream type to be considered
-     * @return volume group associated to the given stream type, default group if none applicable,
-     * VOLUME_GROUP_NONE if no default group defined.
-     */
-    virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
-
-    /**
-     * @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
-     * former stream aliases in Audio Service, defining volume curves attached to one or more
-     * Audio Attributes.
-     * @param groups
-     * @return NO_ERROR if the volume groups were retrieved successfully, error code otherwise
-     */
-    virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
-
-    virtual void dump(String8 *dst) const = 0;
-
-protected:
-    virtual ~AudioPolicyManagerInterface() {}
-};
-
-} // namespace android
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
index ebd82a7..349f969 100644
--- a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
@@ -16,8 +16,7 @@
 
 #pragma once
 
-#include <AudioGain.h>
-#include <AudioPort.h>
+#include <PolicyAudioPort.h>
 #include <AudioPatch.h>
 #include <IOProfile.h>
 #include <DeviceDescriptor.h>
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
new file mode 100644
index 0000000..dfb20b5
--- /dev/null
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include <AudioPolicyManagerObserver.h>
+#include <media/AudioProductStrategy.h>
+#include <media/AudioVolumeGroup.h>
+#include <IVolumeCurves.h>
+#include <policy.h>
+#include <Volume.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+using DeviceStrategyMap = std::map<product_strategy_t, DeviceVector>;
+using StrategyVector = std::vector<product_strategy_t>;
+using VolumeGroupVector = std::vector<volume_group_t>;
+
+/**
+ * This interface is dedicated to the policy manager that a Policy Engine shall implement.
+ */
+class EngineInterface
+{
+public:
+    /**
+     * Checks if the engine was correctly initialized.
+     *
+     * @return NO_ERROR if initialization has been done correctly, error code otherwise..
+     */
+    virtual status_t initCheck() = 0;
+
+    /**
+     * Sets the Manager observer that allows the engine to retrieve information on collection
+     * of devices, streams, HwModules, ...
+     *
+     * @param[in] observer handle on the manager.
+     */
+    virtual void setObserver(AudioPolicyManagerObserver *observer) = 0;
+
+    /**
+     * Set the Telephony Mode.
+     *
+     * @param[in] mode: Android Phone state (normal, ringtone, csv, in communication)
+     *
+     * @return NO_ERROR if Telephony Mode set correctly, error code otherwise.
+     */
+    virtual status_t setPhoneState(audio_mode_t mode) = 0;
+
+    /**
+     * Get the telephony Mode
+     *
+     * @return the current telephony mode
+     */
+    virtual audio_mode_t getPhoneState() const = 0;
+
+    /**
+     * Set Force Use config for a given usage.
+     *
+     * @param[in] usage for which a configuration shall be forced.
+     * @param[in] config wished to be forced for the given usage.
+     *
+     * @return NO_ERROR if the Force Use config was set correctly, error code otherwise (e.g. config
+     * not allowed a given usage...)
+     */
+    virtual status_t setForceUse(audio_policy_force_use_t usage,
+                                 audio_policy_forced_cfg_t config) = 0;
+
+    /**
+     * Get Force Use config for a given usage.
+     *
+     * @param[in] usage for which a configuration shall be forced.
+     *
+     * @return config wished to be forced for the given usage.
+     */
+    virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const = 0;
+
+    /**
+     * Set the connection state of device(s).
+     *
+     * @param[in] devDesc for which the state has changed.
+     * @param[in] state of availability of this(these) device(s).
+     *
+     * @return NO_ERROR if devices criterion updated correctly, error code otherwise.
+     */
+    virtual status_t setDeviceConnectionState(const android::sp<android::DeviceDescriptor> devDesc,
+                                              audio_policy_dev_state_t state) = 0;
+
+    /**
+     * Get the strategy selected for a given audio attributes.
+     *
+     * @param[in] audio attributes to get the selected @product_strategy_t followed by.
+     *
+     * @return @product_strategy_t to be followed.
+     */
+    virtual product_strategy_t getProductStrategyForAttributes(
+            const audio_attributes_t &attr) const = 0;
+
+    /**
+     * @brief getOutputDevicesForAttributes retrieves the devices to be used for given
+     * audio attributes.
+     * @param attributes of the output requesting Device(s) selection
+     * @param preferedDevice valid reference if a prefered device is requested, nullptr otherwise.
+     * @param fromCache if true, the device is returned from internal cache,
+     *                  otherwise it is determined by current state (device connected,phone state,
+     *                  force use, a2dp output...)
+     * @return vector of selected device descriptors.
+     *         Appropriate device for streams handled by the specified audio attributes according
+     *         to current phone state, forced states, connected devices...
+     *         if fromCache is true, the device is returned from internal cache,
+     *         otherwise it is determined by current state (device connected,phone state, force use,
+     *         a2dp output...)
+     * This allows to:
+     *      1 speed up process when the state is stable (when starting or stopping an output)
+     *      2 access to either current device selection (fromCache == true) or
+     *      "future" device selection (fromCache == false) when called from a context
+     *      where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
+     *      before manager updates its outputs.
+     */
+    virtual DeviceVector getOutputDevicesForAttributes(
+            const audio_attributes_t &attributes,
+            const sp<DeviceDescriptor> &preferedDevice = nullptr,
+            bool fromCache = false) const = 0;
+
+    /**
+     * @brief getOutputDevicesForStream Legacy function retrieving devices from a stream type.
+     * @param stream type of the output requesting Device(s) selection
+     * @param fromCache if true, the device is returned from internal cache,
+     *                  otherwise it is determined by current state (device connected,phone state,
+     *                  force use, a2dp output...)
+     * @return appropriate device for streams handled by the specified audio attributes according
+     *         to current phone state, forced states, connected devices...
+     *         if fromCache is true, the device is returned from internal cache,
+     *         otherwise it is determined by current state (device connected,phone state, force use,
+     *         a2dp output...)
+     * This allows to:
+     *      1 speed up process when the state is stable (when starting or stopping an output)
+     *      2 access to either current device selection (fromCache == true) or
+     *      "future" device selection (fromCache == false) when called from a context
+     *      where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
+     *      before manager updates its outputs.
+     */
+    virtual DeviceVector getOutputDevicesForStream(audio_stream_type_t stream,
+                                                   bool fromCache = false) const = 0;
+
+    /**
+     * Get the input device selected for given audio attributes.
+     *
+     * @param[in] attr audio attributes to consider
+     * @param[out] mix to be used if a mix has been installed for the given audio attributes.
+     * @return selected input device for the audio attributes, may be null if error.
+     */
+    virtual sp<DeviceDescriptor> getInputDeviceForAttributes(
+            const audio_attributes_t &attr, sp<AudioPolicyMix> *mix = nullptr) const = 0;
+
+    /**
+     * Get the legacy stream type for a given audio attributes.
+     *
+     * @param[in] audio attributes to get the associated audio_stream_type_t.
+     *
+     * @return audio_stream_type_t associated to the attributes.
+     */
+    virtual audio_stream_type_t getStreamTypeForAttributes(
+            const audio_attributes_t &attr) const = 0;
+
+    /**
+     * @brief getAttributesForStream get the audio attributes from legacy stream type
+     * Attributes returned might only be used to check upon routing decision, not volume decisions.
+     * @param stream to consider
+     * @return audio attributes matching the legacy stream type
+     */
+    virtual audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const = 0;
+
+    /**
+     * @brief getStreamTypesForProductStrategy retrieves the list of legacy stream type following
+     * the given product strategy
+     * @param ps product strategy to consider
+     * @return associated legacy Stream Types vector of the given product strategy
+     */
+    virtual StreamTypeVector getStreamTypesForProductStrategy(product_strategy_t ps) const = 0;
+
+    /**
+     * @brief getAllAttributesForProductStrategy retrieves all the attributes following the given
+     * product strategy. Any attributes that "matches" with this one will follow the product
+     * strategy.
+     * "matching" means the usage shall match if reference attributes has a defined usage, AND
+     * content type shall match if reference attributes has a defined content type AND
+     * flags shall match if reference attributes has defined flags AND
+     * tags shall match if reference attributes has defined tags.
+     * @param ps product strategy to consider
+     * @return vector of product strategy ids, empty if unknown strategy.
+     */
+    virtual AttributesVector getAllAttributesForProductStrategy(product_strategy_t ps) const = 0;
+
+    /**
+     * @brief getOrderedAudioProductStrategies
+     * @return priority ordered product strategies to help the AudioPolicyManager evaluating the
+     * device selection per output according to the prioritized strategies.
+     */
+    virtual StrategyVector getOrderedProductStrategies() const = 0;
+
+    /**
+     * @brief updateDeviceSelectionCache. Device selection for AudioAttribute / Streams is cached
+     * in the engine in order to speed up process when the audio system is stable.
+     * When a device is connected, the android mode is changed, engine is notified and can update
+     * the cache.
+     * When starting / stopping an output with a stream that can affect notification, the engine
+     * needs to update the cache upon this function call.
+     */
+    virtual void updateDeviceSelectionCache() = 0;
+
+    /**
+     * @brief listAudioProductStrategies. Introspection API to retrieve a collection of
+     * AudioProductStrategyVector that allows to build AudioAttributes according to a
+     * product_strategy which is just an index. It has also a human readable name to help the
+     * Car/Oem/AudioManager identiying the use case.
+     * @param strategies collection.
+     * @return OK if the list has been retrieved, error code otherwise
+     */
+    virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) const = 0;
+
+    /**
+     * @brief getVolumeCurvesForAttributes retrieves the Volume Curves interface for the
+     *        requested Audio Attributes.
+     * @param attr to be considered
+     * @return IVolumeCurves interface pointer if found, nullptr otherwise
+     */
+    virtual IVolumeCurves *getVolumeCurvesForAttributes(const audio_attributes_t &attr) const = 0;
+
+    /**
+     * @brief getVolumeCurvesForStreamType retrieves the Volume Curves interface for the stream
+     * @param stream to be considered
+     * @return IVolumeCurves interface pointer if found, nullptr otherwise
+     */
+    virtual IVolumeCurves *getVolumeCurvesForStreamType(audio_stream_type_t stream) const = 0;
+
+    /**
+     * @brief getVolumeCurvesForVolumeGroup retrieves the Volume Curves interface for volume group
+     * @param group to be considered
+     * @return IVolumeCurves interface pointer if found, nullptr otherwise
+     */
+    virtual IVolumeCurves *getVolumeCurvesForVolumeGroup(volume_group_t group) const = 0;
+
+    /**
+     * @brief getVolumeGroups retrieves the collection of volume groups.
+     * @return vector of volume groups
+     */
+    virtual VolumeGroupVector getVolumeGroups() const = 0;
+
+    /**
+     * @brief getVolumeGroupForAttributes gets the appropriate volume group to be used for a given
+     * Audio Attributes.
+     * @param attr to be considered
+     * @return volume group associated to the given audio attributes, default group if none
+     * applicable, VOLUME_GROUP_NONE if no default group defined.
+     */
+    virtual volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const = 0;
+
+    /**
+     * @brief getVolumeGroupForStreamType gets the appropriate volume group to be used for a given
+     * legacy stream type
+     * @param stream type to be considered
+     * @return volume group associated to the given stream type, default group if none applicable,
+     * VOLUME_GROUP_NONE if no default group defined.
+     */
+    virtual volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const = 0;
+
+    /**
+     * @brief listAudioVolumeGroups introspection API to get the Audio Volume Groups, aka
+     * former stream aliases in Audio Service, defining volume curves attached to one or more
+     * Audio Attributes.
+     * @param groups
+     * @return NO_ERROR if the volume groups were retrieved successfully, error code otherwise
+     */
+    virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const = 0;
+
+    /**
+     * @brief setPreferredDeviceForStrategy sets the default device to be used for a
+     * strategy when available
+     * @param strategy the audio strategy whose routing will be affected
+     * @param device the audio device to route to when available
+     * @return BAD_VALUE if the strategy is invalid,
+     *     or NO_ERROR if the preferred device was set
+     */
+    virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+            const AudioDeviceTypeAddr &device) = 0;
+
+    /**
+     * @brief removePreferredDeviceForStrategy removes the preferred device previously set
+     * for the given strategy
+     * @param strategy the audio strategy whose routing will be affected
+     * @return BAD_VALUE if the strategy is invalid,
+     *     or NO_ERROR if the preferred device was removed
+     */
+    virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy) = 0;
+
+    /**
+     * @brief getPreferredDeviceForStrategy queries which device is set as the
+     * preferred device for the given strategy
+     * @param strategy the strategy to query
+     * @param device returns configured as the preferred device if one was set
+     * @return BAD_VALUE if the strategy is invalid,
+     *     or NAME_NOT_FOUND if no preferred device was set
+     *     or NO_ERROR if the device parameter was initialized to the preferred device
+     */
+    virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+            AudioDeviceTypeAddr &device) const = 0;
+
+
+    virtual void dump(String8 *dst) const = 0;
+
+protected:
+    virtual ~EngineInterface() {}
+};
+
+__attribute__((visibility("default")))
+extern "C" EngineInterface* createEngineInstance();
+
+__attribute__((visibility("default")))
+extern "C" void destroyEngineInstance(EngineInterface *engine);
+
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index c27dc88..8f522f0 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -33,6 +33,7 @@
 
     ],
     shared_libs: [
+        "libaudiofoundation",
         "liblog",
         "libcutils",
         "libutils",
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
new file mode 100644
index 0000000..fe3eae0
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Root soong_namespace for common components
+
+prebuilt_etc {
+    name: "audio_policy_engine_criteria.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criteria",
+}
+filegroup {
+    name: "audio_policy_engine_criterion_types_template",
+    srcs: ["example/common/audio_policy_engine_criterion_types.xml.in"],
+}
+filegroup {
+    name: "audio_policy_engine_criteria",
+    srcs: ["example/common/audio_policy_engine_criteria.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/Android.mk b/services/audiopolicy/engineconfigurable/config/example/Android.mk
deleted file mode 100644
index a0f1a90..0000000
--- a/services/audiopolicy/engineconfigurable/config/example/Android.mk
+++ /dev/null
@@ -1,151 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
-
-##################################################################
-# CONFIGURATION TOP FILE
-##################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml  \
-    audio_policy_engine_stream_volumes.xml \
-    audio_policy_engine_default_stream_volumes.xml \
-    audio_policy_engine_criteria.xml \
-    audio_policy_engine_criterion_types.xml
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_default_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
-
-##################################################################
-# AUTOMOTIVE CONFIGURATION TOP FILE
-##################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml \
-    audio_policy_engine_criteria.xml \
-    audio_policy_engine_criterion_types.xml \
-    audio_policy_engine_volumes.xml
-
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),automotive_configurable caremu_configurable))
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := automotive/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := caremu/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_criteria.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := common/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_criterion_types.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_VENDOR_ETC)/primary_audio_policy_configuration.xml
-ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
-AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
-CRITERION_TYPES_FILE := $(LOCAL_PATH)/common/$(LOCAL_MODULE).in
-
-include $(PROVISION_CRITERION_TYPES)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-endif #ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
new file mode 100644
index 0000000..f913a14
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/Android.bp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Automotive configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        ":audio_policy_engine_criterion_types.xml",
+        ":audio_policy_engine_criteria.xml",
+        ":audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration",
+    srcs: ["audio_policy_engine_configuration.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_volumes",
+    srcs: ["audio_policy_engine_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index 0ee83a2..f598cf2 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -84,7 +84,7 @@
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="voice_command">
-        <AttributesGroup volumeGroup="speech">
+        <AttributesGroup volumeGroup="speech" streamType="AUDIO_STREAM_ASSISTANT">
             <Attributes>
                 <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
                 <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
@@ -147,10 +147,6 @@
     <ProductStrategy name="notification">
         <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="system">
@@ -167,19 +163,5 @@
         </AttributesGroup>
     </ProductStrategy>
 
-    <!-- Routing Strategy rerouting may be removed as following media??? -->
-    <ProductStrategy name="rerouting">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
-    <ProductStrategy name="patch">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
index 6e72dc5..97a25a8 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -189,25 +189,5 @@
         </volume>
     </volumeGroup>
 
-    <volumeGroup>
-        <name>rerouting</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
-            <point>0,0</point>
-            <point>100,0</point>
-        </volume>
-    </volumeGroup>
-
-    <volumeGroup>
-        <name>patch</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
-            <point>0,0</point>
-            <point>100,0</point>
-        </volume>
-    </volumeGroup>
-
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
new file mode 100644
index 0000000..fae6b7b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/Android.bp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Car Emulator configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/automotive",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        "audio_policy_engine_criterion_types.xml",
+        "audio_policy_engine_criteria.xml",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
index adcbd83..f598cf2 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
@@ -84,7 +84,7 @@
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="voice_command">
-        <AttributesGroup volumeGroup="speech">
+        <AttributesGroup volumeGroup="speech" streamType="AUDIO_STREAM_ASSISTANT">
             <Attributes>
                 <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
                 <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
@@ -147,10 +147,6 @@
     <ProductStrategy name="notification">
         <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="ring">
             <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/> </Attributes>
-            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
         </AttributesGroup>
     </ProductStrategy>
     <ProductStrategy name="system">
@@ -167,18 +163,5 @@
         </AttributesGroup>
     </ProductStrategy>
 
-    <!-- Routing Strategy rerouting may be removed as following media??? -->
-    <ProductStrategy name="rerouting">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-    <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
-    <ProductStrategy name="patch">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
index 6e72dc5..97a25a8 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
@@ -189,25 +189,5 @@
         </volume>
     </volumeGroup>
 
-    <volumeGroup>
-        <name>rerouting</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
-            <point>0,0</point>
-            <point>100,0</point>
-        </volume>
-    </volumeGroup>
-
-    <volumeGroup>
-        <name>patch</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
-            <point>0,0</point>
-            <point>100,0</point>
-        </volume>
-    </volumeGroup>
-
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types.xml.in b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types.xml.in
index fe17369..e134c42 100644
--- a/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types.xml.in
+++ b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types.xml.in
@@ -22,7 +22,12 @@
             <value literal="0" numerical="1"/>
         </values>
     </criterion_type>
-    <criterion_type name="InputDevicesAddressesType" type="inclusive"/>
+    <criterion_type name="InputDevicesAddressesType" type="inclusive">
+        <values>
+            <!-- legacy remote submix -->
+            <value literal="0" numerical="1"/>
+        </values>
+    </criterion_type>
     <criterion_type name="AndroidModeType" type="exclusive"/>
     <criterion_type name="BooleanType" type="exclusive">
         <values>
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
new file mode 100644
index 0000000..94d33bd
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/Android.bp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: ":audio_policy_engine_configuration",
+    required: [
+        ":audio_policy_engine_criterion_types.xml",
+        ":audio_policy_engine_criteria.xml",
+        ":audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_volumes.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_stream_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_stream_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_default_stream_volumes.xml",
+    vendor: true,
+    src: ":audio_policy_engine_default_stream_volumes",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_criterion_types.xml",
+    vendor: true,
+    src: ":audio_policy_engine_criterion_types",
+}
+
+//
+// Generate audio_policy_engine criterion type file => provides device addresses criterion type
+//
+genrule {
+    name: "audio_policy_engine_criterion_types",
+    defaults: ["buildpolicycriteriontypesrule"],
+    srcs: [
+        ":audio_policy_configuration_top_file",
+        ":audio_policy_configuration_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_configuration_files",
+    srcs: [
+        ":r_submix_audio_policy_configuration",
+        ":default_volume_tables",
+        ":audio_policy_volumes",
+        ":surround_sound_configuration_5_0",
+        ":primary_audio_policy_configuration",
+    ],
+}
+filegroup {
+    name : "audio_policy_configuration_top_file",
+    srcs: [":audio_policy_configuration_generic"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration",
+    srcs: ["audio_policy_engine_configuration.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_stream_volumes",
+    srcs: ["audio_policy_engine_stream_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_default_stream_volumes",
+    srcs: ["audio_policy_engine_default_stream_volumes.xml"],
+}
+filegroup {
+    name: "audio_policy_engine_configuration_files",
+    srcs: [
+        ":audio_policy_engine_configuration",
+        "audio_policy_engine_product_strategies.xml",
+        ":audio_policy_engine_stream_volumes",
+        ":audio_policy_engine_default_stream_volumes",
+        ":audio_policy_engine_criterion_types",
+        ":audio_policy_engine_criteria",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
index 9398743..a7388da 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -72,6 +72,12 @@
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
             <Attributes></Attributes>
         </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant">
+            <Attributes>
+                <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+                <Usage value="AUDIO_USAGE_ASSISTANT"/>
+            </Attributes>
+        </AttributesGroup>
         <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
         </AttributesGroup>
@@ -91,20 +97,5 @@
         </AttributesGroup>
     </ProductStrategy>
 
-    <!-- Routing Strategy rerouting may be removed as following media??? -->
-    <ProductStrategy name="STRATEGY_REROUTING">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-    <!-- Default product strategy has empty attributes -->
-    <ProductStrategy name="STRATEGY_PATCH">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-
 </ProductStrategies>
 
diff --git a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
index 707a184..8aa71ca 100644
--- a/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -205,27 +205,16 @@
         <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
         <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"/>
     </volumeGroup>
-
     <volumeGroup>
-        <name>rerouting</name>
+        <name>assistant</name>
         <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     </volumeGroup>
 
-    <volumeGroup>
-        <name>patch</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
-    </volumeGroup>
 </volumeGroups>
 
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index efc69da..f52de21 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-class AudioPolicyManagerInterface;
+class EngineInterface;
 class AudioPolicyPluginInterface;
 
 namespace android {
@@ -69,7 +69,7 @@
  * Compile time error will claim if invalid interface is requested.
  */
 template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
+EngineInterface *EngineInstance::queryInterface() const;
 
 template <>
 AudioPolicyPluginInterface *EngineInstance::queryInterface() const;
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
new file mode 100644
index 0000000..90ebffd
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Root soong_namespace for common components
+
+prebuilt_etc {
+    name: "PolicyClass.xml",
+    vendor: true,
+    src: ":PolicyClass",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+prebuilt_etc {
+    name: "PolicySubsystem-CommonTypes.xml",
+    vendor: true,
+    src: ":buildcommontypesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+genrule {
+    name: "buildcommontypesstructure_gen",
+    defaults: ["buildcommontypesstructurerule"],
+}
+
+filegroup {
+    name: "product_strategies_structure_template",
+    srcs: ["examples/common/Structure/ProductStrategies.xml.in"],
+}
+filegroup {
+    name: "PolicySubsystem",
+    srcs: ["examples/common/Structure/PolicySubsystem.xml"],
+}
+filegroup {
+    name: "PolicySubsystem-no-strategy",
+    srcs: ["examples/common/Structure/PolicySubsystem-no-strategy.xml"],
+}
+filegroup {
+    name: "common_types_structure_template",
+    srcs: ["examples/common/Structure/PolicySubsystem-CommonTypes.xml.in"],
+}
+filegroup {
+    name: "PolicyClass",
+    srcs: ["examples/common/Structure/PolicyClass.xml"],
+}
+filegroup {
+    name: "volumes.pfw",
+    srcs: ["examples/Settings/volumes.pfw"],
+}
+filegroup {
+    name: "device_for_input_source.pfw",
+    srcs: ["examples/Settings/device_for_input_source.pfw"],
+}
+filegroup {
+    name: "ParameterFrameworkConfigurationPolicy.userdebug.xml",
+    srcs: ["examples/ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "ParameterFrameworkConfigurationPolicy.user.xml",
+    srcs: ["examples/ParameterFrameworkConfigurationPolicy.user.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
deleted file mode 100644
index 19f93b3..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ /dev/null
@@ -1,187 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-LOCAL_PATH := $(call my-dir)
-
-ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable no-output_configurable no-input_configurable))
-
-PFW_CORE := external/parameter-framework
-#@TODO: upstream new domain generator
-#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-PROVISION_STRATEGIES_STRUCTURE := $(TOOLS)/provision_strategies_structure.mk
-
-endif
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-######### Policy PFW top level file #########
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework
-LOCAL_SRC_FILES := $(LOCAL_MODULE).in
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem.xml \
-    PolicyClass.xml
-
-# external/parameter-framework prevents from using debug interface
-AUDIO_PATTERN = @TUNING_ALLOWED@
-ifeq ($(TARGET_BUILD_VARIANT),user)
-AUDIO_VALUE = false
-else
-AUDIO_VALUE = true
-endif
-
-LOCAL_POST_INSTALL_CMD := $(hide) sed -i -e 's|$(AUDIO_PATTERN)|$(AUDIO_VALUE)|g' $(TARGET_OUT_VENDOR_ETC)/$(LOCAL_MODULE_RELATIVE_PATH)/$(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-########## Policy PFW Common Structures #########
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem-CommonTypes.xml \
-    ProductStrategies.xml
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicyClass.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ProductStrategies.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-
-AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := \
-    $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_configuration.xml
-STRATEGIES_STRUCTURE_FILE := $(LOCAL_PATH)/common/Structure/$(LOCAL_MODULE).in
-
-include $(PROVISION_STRATEGIES_STRUCTURE)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),phone_configurable automotive_configurable caremu_configurable))
-
-########## Policy PFW Example Structures #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := PolicySubsystem.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := PolicySubsystem-CommonTypes.xml
-
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Structure/Policy
-LOCAL_SRC_FILES := common/Structure/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ParameterFrameworkConfigurationPolicy-no-strategy.xml
-LOCAL_MODULE_STEM := ParameterFrameworkConfigurationPolicy.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework
-LOCAL_SRC_FILES := $(LOCAL_MODULE).in
-LOCAL_REQUIRED_MODULES := \
-    PolicySubsystem.xml \
-    PolicyClass.xml
-AUDIO_VALUE = false
-LOCAL_POST_INSTALL_CMD := $(hide) sed -i -e 's|$(AUDIO_PATTERN)|$(AUDIO_VALUE)|g' $(TARGET_OUT_VENDOR_ETC)/$(LOCAL_MODULE_RELATIVE_PATH)/$(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),$(filter $(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable no-input_configurable))
-
-######### Policy PFW Settings - No Output #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
-        $(LOCAL_PATH)/Settings/device_for_input_source.pfw \
-        $(LOCAL_PATH)/Settings/volumes.pfw        
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-include $(BUILD_PFW_SETTINGS)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-output_configurable)
-######### Policy PFW Settings - No Input #########
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-input_configurable)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/SettingsNoInput/device_for_input_source.pfw \
-        $(LOCAL_PATH)/Settings/volumes.pfw
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION),no-input_configurable)
-#######################################################################
-# Recursive call sub-folder Android.mk
-#######################################################################
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-endif #ifdef BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION
-
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
new file mode 100644
index 0000000..82b1b6d
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Automotive configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/automotive",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategies.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":buildcommontypesstructure_gen",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
deleted file mode 100644
index 7304ec2..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-    $(LOCAL_PATH)/Settings/device_for_product_strategies.pfw \
-    $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-    $(LOCAL_PATH)/../Settings/volumes.pfw
-
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), automotive_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
index 57ad592..ddae356 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Settings/device_for_product_strategies.pfw
@@ -14,7 +14,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -59,7 +59,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -106,7 +106,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -152,7 +152,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -205,7 +205,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -251,7 +251,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -304,7 +304,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -357,7 +357,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -411,7 +411,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -464,7 +464,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -517,7 +517,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -570,7 +570,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -623,7 +623,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -676,7 +676,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -729,7 +729,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
new file mode 100644
index 0000000..e4605b2
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Car Emulator configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/caremu",
+        "frameworks/av/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategies.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":buildcommontypesstructure_gen",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
deleted file mode 100644
index f5eb7d1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.mk
+++ /dev/null
@@ -1,46 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-    $(LOCAL_PATH)/Settings/device_for_product_strategies.pfw \
-    $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-    $(LOCAL_PATH)/../Settings/volumes.pfw
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), caremu_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw
index ca3464f..cc778df 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Settings/device_for_product_strategies.pfw
@@ -14,7 +14,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -59,7 +59,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -106,7 +106,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -153,7 +153,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -198,7 +198,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -245,7 +245,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -291,7 +291,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -337,7 +337,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -384,7 +384,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -430,7 +430,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -476,7 +476,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -522,7 +522,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -568,7 +568,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -614,7 +614,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -659,7 +659,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml
new file mode 100644
index 0000000..c5960cb
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.user.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    SystemClassName="Policy" TuningAllowed="false">
+
+    <SubsystemPlugins>
+        <Location Folder="">
+            <Plugin Name="libpolicy-subsystem.so"/>
+        </Location>
+    </SubsystemPlugins>
+    <StructureDescriptionFileLocation Path="Structure/Policy/PolicyClass.xml"/>
+    <SettingsConfiguration>
+        <ConfigurableDomainsFileLocation Path="Settings/Policy/PolicyConfigurableDomains.xml"/>
+    </SettingsConfiguration>
+</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml
new file mode 100644
index 0000000..1b7d7d8
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.userdebug.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    SystemClassName="Policy" ServerPort="unix:///dev/socket/audioserver/policy_debug"
+    TuningAllowed="true">
+
+    <SubsystemPlugins>
+        <Location Folder="">
+            <Plugin Name="libpolicy-subsystem.so"/>
+        </Location>
+    </SubsystemPlugins>
+    <StructureDescriptionFileLocation Path="Structure/Policy/PolicyClass.xml"/>
+    <SettingsConfiguration>
+        <ConfigurableDomainsFileLocation Path="Settings/Policy/PolicyConfigurableDomains.xml"/>
+    </SettingsConfiguration>
+</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
deleted file mode 100644
index 1be67dd..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    SystemClassName="Policy" ServerPort="unix:///dev/socket/audioserver/policy_debug"
-    TuningAllowed="@TUNING_ALLOWED@">
-
-    <SubsystemPlugins>
-        <Location Folder="">
-            <Plugin Name="libpolicy-subsystem.so"/>
-        </Location>
-    </SubsystemPlugins>
-    <StructureDescriptionFileLocation Path="Structure/Policy/PolicyClass.xml"/>
-    <SettingsConfiguration>
-        <ConfigurableDomainsFileLocation Path="Settings/Policy/PolicyConfigurableDomains.xml"/>
-    </SettingsConfiguration>
-</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
new file mode 100644
index 0000000..61b54cf
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Product Strategies Structure file from template
+//
+prebuilt_etc {
+    name: "ProductStrategies.xml",
+    vendor: true,
+    src: ":buildstrategiesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+    required: ["libpolicy-subsystem"],
+}
+genrule {
+    name: "buildstrategiesstructure_gen",
+    defaults: ["buildstrategiesstructurerule"],
+    srcs: [
+        ":audio_policy_engine_configuration_files",
+    ],
+}
+
+//
+// Generate Audio Policy Parameter Framework Configurable Domains
+//
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "ProductStrategies.xml",
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        ":device_for_input_source.pfw",
+        ":volumes.pfw",
+        "Settings/device_for_product_strategy_media.pfw",
+        "Settings/device_for_product_strategy_accessibility.pfw",
+        "Settings/device_for_product_strategy_dtmf.pfw",
+        "Settings/device_for_product_strategy_enforced_audible.pfw",
+        "Settings/device_for_product_strategy_phone.pfw",
+        "Settings/device_for_product_strategy_sonification.pfw",
+        "Settings/device_for_product_strategy_sonification_respectful.pfw",
+        "Settings/device_for_product_strategy_transmitted_through_speaker.pfw",
+        "Settings/device_for_product_strategy_rerouting.pfw",
+        "Settings/device_for_product_strategy_patch.pfw",
+    ],
+}
+// This is for Settings generation, must use socket port, so userdebug version is required
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":buildcommontypesstructure_gen",
+        ":buildstrategiesstructure_gen",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
deleted file mode 100644
index 0b20781..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Engine configurable example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
-
-LOCAL_PATH := $(call my-dir)
-
-PFW_CORE := external/parameter-framework
-PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
-BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
-
-##################################################################
-# CONFIGURATION FILES
-##################################################################
-########## Policy PFW Structures #########
-######### Policy PFW Settings #########
-include $(CLEAR_VARS)
-LOCAL_MODULE := parameter-framework.policy
-LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_REQUIRED_MODULES := libpolicy-subsystem
-
-PFW_EDD_FILES := \
-        $(LOCAL_PATH)/../Settings/device_for_input_source.pfw \
-        $(LOCAL_PATH)/../Settings/volumes.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_media.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_accessibility.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_dtmf.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_enforced_audible.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_phone.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_sonification.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_sonification_respectful.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_transmitted_through_speaker.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_rerouting.pfw \
-        $(LOCAL_PATH)/Settings/device_for_product_strategy_patch.pfw
-PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criterion_types.xml
-PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_engine_criteria.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
-
-include $(BUILD_PFW_SETTINGS)
-
-endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_configurable)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_accessibility.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_accessibility.pfw
index 53e93de..d16a904 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_accessibility.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_accessibility.pfw
@@ -45,7 +45,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -73,7 +73,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -101,7 +101,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -129,7 +129,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -157,7 +157,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -186,7 +186,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -215,7 +215,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -244,7 +244,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -281,7 +281,7 @@
 					wired_headset = 0
 					wired_headphone = 1
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -317,7 +317,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -354,7 +354,7 @@
 					wired_headset = 1
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -394,7 +394,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -425,7 +425,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 1
 					usb_device = 0
@@ -455,7 +455,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -485,7 +485,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -517,7 +517,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -546,7 +546,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -568,7 +568,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -588,7 +588,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_dtmf.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_dtmf.pfw
index b8426c6..414445d 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_dtmf.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_dtmf.pfw
@@ -34,7 +34,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -62,7 +62,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -90,7 +90,7 @@
 					bluetooth_a2dp_headphones = 1
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -118,7 +118,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 1
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -147,7 +147,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -176,7 +176,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -205,7 +205,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -242,7 +242,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -281,7 +281,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -318,7 +318,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -358,7 +358,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -389,7 +389,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 1
 					usb_device = 0
@@ -419,7 +419,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -449,7 +449,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -481,7 +481,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -510,7 +510,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -548,7 +548,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -568,7 +568,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_enforced_audible.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_enforced_audible.pfw
index 2daa9ac..36b8f3c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_enforced_audible.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_enforced_audible.pfw
@@ -77,7 +77,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -100,7 +100,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -123,7 +123,7 @@
 					bluetooth_a2dp_headphones = 1
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -146,7 +146,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 1
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -169,7 +169,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -192,7 +192,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -215,7 +215,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -238,7 +238,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 1
 					usb_device = 0
@@ -261,7 +261,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -284,7 +284,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -307,7 +307,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -331,7 +331,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -351,7 +351,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_media.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_media.pfw
index d6d355c..6210a57 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_media.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_media.pfw
@@ -26,7 +26,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -46,7 +46,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -66,7 +66,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -86,7 +86,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -109,7 +109,7 @@
 					speaker = 1
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -127,7 +127,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -145,7 +145,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -163,7 +163,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 1
@@ -181,7 +181,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 1
 					wired_headset = 0
@@ -199,7 +199,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 1
 					usb_accessory = 0
 					wired_headset = 0
@@ -217,7 +217,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -235,7 +235,7 @@
 					speaker = 0
 					hdmi = 1
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -254,7 +254,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -277,7 +277,7 @@
 					speaker = 1
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
@@ -293,7 +293,7 @@
 					speaker = 0
 					hdmi = 0
 					dgtl_dock_headset = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					usb_device = 0
 					usb_accessory = 0
 					wired_headset = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
index d2cc090..feeeec6 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_patch.pfw
@@ -14,7 +14,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_phone.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_phone.pfw
index 5693d4e..da2fc9b 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_phone.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_phone.pfw
@@ -32,7 +32,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -55,7 +55,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -78,7 +78,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -108,7 +108,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -138,7 +138,7 @@
 					bluetooth_a2dp_headphones = 1
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -168,7 +168,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 1
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -195,7 +195,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -222,7 +222,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -245,7 +245,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -283,7 +283,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -311,7 +311,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -339,7 +339,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -367,7 +367,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -395,7 +395,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -422,7 +422,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -449,7 +449,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -472,7 +472,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
index 10f8814..3275cdf 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_rerouting.pfw
@@ -14,7 +14,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification.pfw
index c4edeeb..a60445b 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification.pfw
@@ -69,7 +69,7 @@
 					bluetooth_a2dp = 1
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -95,7 +95,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 1
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -121,7 +121,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -148,7 +148,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -175,7 +175,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -202,7 +202,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -238,7 +238,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -276,7 +276,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -312,7 +312,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -349,7 +349,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -378,7 +378,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 1
 					usb_device = 0
@@ -407,7 +407,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -437,7 +437,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -464,7 +464,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -482,7 +482,7 @@
 					bluetooth_a2dp = 0
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification_respectful.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification_respectful.pfw
index 0a3dd5f..6b11e23 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification_respectful.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_sonification_respectful.pfw
@@ -92,7 +92,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -119,7 +119,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -146,7 +146,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -173,7 +173,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -200,7 +200,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -227,7 +227,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -264,7 +264,7 @@
 					wired_headset = 0
 					wired_headphone = 1
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -305,7 +305,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 1
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -342,7 +342,7 @@
 					wired_headset = 1
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -380,7 +380,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 1
@@ -410,7 +410,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 1
 					usb_device = 0
@@ -440,7 +440,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 1
 					usb_accessory = 0
 					usb_device = 0
@@ -470,7 +470,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -501,7 +501,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 1
+					anlg_dock_headset = 1
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
@@ -528,7 +528,7 @@
 					wired_headset = 0
 					wired_headphone = 0
 					line = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_transmitted_through_speaker.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_transmitted_through_speaker.pfw
index 3fc7670..418f3cc 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_transmitted_through_speaker.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Settings/device_for_product_strategy_transmitted_through_speaker.pfw
@@ -19,7 +19,7 @@
 					bluetooth_a2dp_headphones = 0
 					bluetooth_a2dp_speaker = 0
 					hdmi = 0
-					angl_dock_headset = 0
+					anlg_dock_headset = 0
 					dgtl_dock_headset = 0
 					usb_accessory = 0
 					usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index 0710441..baffa81 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -145,7 +145,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/speaker"/>
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/hdmi"/>
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device"/>
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/wired_headset"/>
@@ -167,8 +167,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -208,8 +208,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -249,8 +249,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -290,8 +290,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -331,8 +331,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -372,8 +372,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -413,8 +413,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -454,8 +454,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -495,8 +495,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -536,8 +536,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">1</BitParameter>
@@ -577,8 +577,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -618,8 +618,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -659,8 +659,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -700,8 +700,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -741,8 +741,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/media/selected_output_devices/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -1039,7 +1039,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/bluetooth_a2dp_headphones"/>
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/bluetooth_a2dp_speaker"/>
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/usb_device"/>
@@ -1079,8 +1079,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1132,8 +1132,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1185,8 +1185,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1238,8 +1238,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1291,8 +1291,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1344,8 +1344,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1397,8 +1397,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1450,8 +1450,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1503,8 +1503,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1556,8 +1556,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1609,8 +1609,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1662,8 +1662,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -1715,8 +1715,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1768,8 +1768,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1821,8 +1821,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1874,8 +1874,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -1927,8 +1927,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2228,7 +2228,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_headphones"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/usb_device"/>
@@ -2264,8 +2264,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2311,8 +2311,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2358,8 +2358,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2405,8 +2405,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2452,8 +2452,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2499,8 +2499,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2546,8 +2546,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2593,8 +2593,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2640,8 +2640,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2687,8 +2687,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2734,8 +2734,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2781,8 +2781,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -2828,8 +2828,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2875,8 +2875,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -2922,8 +2922,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/bluetooth_a2dp_speaker">
           <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3246,7 +3246,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/wired_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/wired_headphone"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/usb_device"/>
@@ -3284,8 +3284,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3331,8 +3331,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3378,8 +3378,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3425,8 +3425,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3472,8 +3472,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3519,8 +3519,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3566,8 +3566,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3613,8 +3613,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3660,8 +3660,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3707,8 +3707,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3754,8 +3754,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3801,8 +3801,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -3848,8 +3848,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3895,8 +3895,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -3942,8 +3942,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/sonification_respectful/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4207,7 +4207,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/bluetooth_a2dp_headphones"/>
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/bluetooth_a2dp_speaker"/>
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/usb_device"/>
@@ -4247,8 +4247,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4300,8 +4300,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4353,8 +4353,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4406,8 +4406,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4459,8 +4459,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4512,8 +4512,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4565,8 +4565,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4618,8 +4618,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4671,8 +4671,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4724,8 +4724,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4777,8 +4777,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4830,8 +4830,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4883,8 +4883,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -4936,8 +4936,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -4989,8 +4989,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5042,8 +5042,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5095,8 +5095,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5148,8 +5148,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/dtmf/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5448,7 +5448,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/bluetooth_a2dp_headphones"/>
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/bluetooth_a2dp_speaker"/>
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/usb_device"/>
@@ -5490,8 +5490,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5543,8 +5543,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5596,8 +5596,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5649,8 +5649,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5702,8 +5702,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5755,8 +5755,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5808,8 +5808,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5861,8 +5861,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5914,8 +5914,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -5967,8 +5967,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -6020,8 +6020,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6073,8 +6073,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6126,8 +6126,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/enforced_audible/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6170,7 +6170,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/bluetooth_a2dp_headphones"/>
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/bluetooth_a2dp_speaker"/>
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/hdmi"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/usb_device"/>
@@ -6230,8 +6230,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/transmitted_through_speaker/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6539,7 +6539,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/wired_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/wired_headphone"/>
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/usb_device"/>
@@ -6583,8 +6583,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6636,8 +6636,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6689,8 +6689,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6742,8 +6742,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6795,8 +6795,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6848,8 +6848,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6901,8 +6901,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -6954,8 +6954,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7007,8 +7007,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7060,8 +7060,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7113,8 +7113,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7166,8 +7166,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7219,8 +7219,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7272,8 +7272,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -7325,8 +7325,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7378,8 +7378,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7431,8 +7431,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7484,8 +7484,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7537,8 +7537,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/accessibility/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7710,7 +7710,7 @@
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/wired_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/wired_headphone"/>
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line"/>
-      <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset"/>
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/usb_accessory"/>
       <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/usb_device"/>
@@ -7742,8 +7742,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7783,8 +7783,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7824,8 +7824,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7865,8 +7865,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7906,8 +7906,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7947,8 +7947,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -7988,8 +7988,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">1</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8029,8 +8029,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8070,8 +8070,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8111,8 +8111,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8152,8 +8152,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">1</BitParameter>
@@ -8193,8 +8193,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8234,8 +8234,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">1</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8275,8 +8275,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
@@ -8316,8 +8316,8 @@
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/line">
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
-        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/angl_dock_headset">
-          <BitParameter Name="angl_dock_headset">0</BitParameter>
+        <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/rerouting/selected_output_devices/mask/dgtl_dock_headset">
           <BitParameter Name="dgtl_dock_headset">0</BitParameter>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
index a990879..9e0957c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/device_for_input_source.pfw
@@ -18,7 +18,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/mic/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -36,7 +35,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_downlink/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -58,7 +56,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_call/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -80,7 +77,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_uplink/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -102,7 +98,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -123,7 +118,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_recognition/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -142,7 +136,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/voice_communication/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -160,7 +153,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -182,7 +174,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/hotword/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -201,7 +192,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/unprocessed/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -220,7 +210,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				communication = 0
 				ambient = 0
@@ -242,7 +231,6 @@
 				loopback = 0
 				ip = 0
 				bus = 0
-				stub = 0
 
 	domain: DefaultAndMic
 		conf: A2dp
@@ -255,12 +243,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: Sco
 			AvailableInputDevices Includes BluetoothScoHeadset
@@ -273,12 +263,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 1
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 1
+					stub = 0
 
 		conf: WiredHeadset
 			AvailableInputDevices Includes WiredHeadset
@@ -290,12 +282,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: UsbDevice
 			AvailableInputDevices Includes UsbDevice
@@ -307,12 +301,14 @@
 					usb_device = 1
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -324,12 +320,33 @@
 					usb_device = 0
 					builtin_mic = 1
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
 					bluetooth_sco_headset = 0
+					stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				component: default/applicable_input_device/mask/
+					bluetooth_a2dp = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					bluetooth_sco_headset = 0
+					stub = 1
+				component: mic/applicable_input_device/mask/
+					bluetooth_a2dp = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					bluetooth_sco_headset = 0
+					stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources
@@ -339,12 +356,14 @@
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 0
+					stub = 0
 
 	domain: VoiceUplinkAndVoiceDownlinkAndVoiceCall
 		conf: VoiceCall
@@ -354,12 +373,29 @@
 				voice_downlink/applicable_input_device/mask/telephony_rx = 1
 				voice_call/applicable_input_device/mask/telephony_rx = 1
 				voice_uplink/applicable_input_device/mask/telephony_rx = 1
+				voice_downlink/applicable_input_device/mask/stub = 0
+				voice_call/applicable_input_device/mask/stub = 0
+				voice_uplink/applicable_input_device/mask/stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				voice_downlink/applicable_input_device/mask/telephony_rx = 0
+				voice_call/applicable_input_device/mask/telephony_rx = 0
+				voice_uplink/applicable_input_device/mask/telephony_rx = 0
+				voice_downlink/applicable_input_device/mask/stub = 1
+				voice_call/applicable_input_device/mask/stub = 1
+				voice_uplink/applicable_input_device/mask/stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources
 				voice_downlink/applicable_input_device/mask/telephony_rx = 0
 				voice_call/applicable_input_device/mask/telephony_rx = 0
 				voice_uplink/applicable_input_device/mask/telephony_rx = 0
+				voice_downlink/applicable_input_device/mask/stub = 0
+				voice_call/applicable_input_device/mask/stub = 0
+				voice_uplink/applicable_input_device/mask/stub = 0
 
 	domain: Camcorder
 		conf: BackMic
@@ -368,6 +404,7 @@
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 1
 				builtin_mic = 0
+				stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -375,11 +412,21 @@
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 0
 				builtin_mic = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
+				back_mic = 0
+				builtin_mic = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/camcorder/applicable_input_device/mask
 				back_mic = 0
 				builtin_mic = 0
+				stub = 0
 
 	domain: VoiceRecognitionAndUnprocessedAndHotword
 		conf: ScoHeadset
@@ -392,16 +439,19 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 1
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 		conf: WiredHeadset
 			AvailableInputDevices Includes WiredHeadset
@@ -411,17 +461,20 @@
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
+					stub = 0
 					builtin_mic = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 1
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 		conf: UsbDevice
 			AvailableInputDevices Includes UsbDevice
@@ -432,16 +485,19 @@
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 1
 					builtin_mic = 0
+					stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -452,17 +508,42 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 1
+					stub = 0
 
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources
+				component: voice_recognition/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
+				component: unprocessed/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
+				component: hotword/applicable_input_device/mask
+					bluetooth_sco_headset = 0
+					wired_headset = 0
+					usb_device = 0
+					builtin_mic = 0
+					stub = 1
 		conf: Default
 			component: /Policy/policy/input_sources
 				component: voice_recognition/applicable_input_device/mask
@@ -470,16 +551,19 @@
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: unprocessed/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 				component: hotword/applicable_input_device/mask
 					bluetooth_sco_headset = 0
 					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
+					stub = 0
 
 	domain: VoiceCommunication
 		conf: ScoHeadset
@@ -495,6 +579,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: WiredHeadset
 			ForceUseForCommunication Is ForceNone
@@ -506,6 +591,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: UsbDevice
 			ForceUseForCommunication Is ForceNone
@@ -517,6 +603,7 @@
 				usb_device = 1
 				builtin_mic = 0
 				back_mic = 0
+				stub = 0
 
 		conf: BuiltinMic
 			AvailableInputDevices Includes BuiltinMic
@@ -532,6 +619,7 @@
 				usb_device = 0
 				builtin_mic = 1
 				back_mic = 0
+				stub = 0
 
 		conf: BackMic
 			ForceUseForCommunication Is ForceSpeaker
@@ -543,6 +631,7 @@
 				usb_device = 0
 				builtin_mic = 0
 				back_mic = 1
+				stub = 0
 
 		conf: Default
 			#
@@ -554,6 +643,7 @@
 				usb_device = 0
 				builtin_mic = 1
 				back_mic = 0
+				stub = 0
 
 	domain: RemoteSubmix
 		conf: RemoteSubmix
@@ -561,10 +651,19 @@
 
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				remote_submix = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
+				remote_submix = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/remote_submix/applicable_input_device/mask
 				remote_submix = 0
+				stub = 0
 
 	domain: FmTuner
 		conf: FmTuner
@@ -572,8 +671,29 @@
 
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				fm_tuner = 1
+				stub = 0
+
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
+				fm_tuner = 0
+				stub = 1
 
 		conf: Default
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				fm_tuner = 0
+				stub = 0
+
+	domain: Voice
+		conf: Stub
+			AvailableInputDevices Includes Default
+
+			/Policy/policy/input_sources/echo_reference/applicable_input_device/mask/stub = 1
+			/Policy/policy/input_sources/voice_performance/applicable_input_device/mask/stub = 1
+
+		conf: Default
+			/Policy/policy/input_sources/echo_reference/applicable_input_device/mask/stub = 0
+			/Policy/policy/input_sources/voice_performance/applicable_input_device/mask/stub = 0
+
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/volumes.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/volumes.pfw
index 7db4537..cf1857e 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/volumes.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/volumes.pfw
@@ -11,6 +11,7 @@
 			/Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile = enforced_audible
 			/Policy/policy/streams/tts/applicable_volume_profile/volume_profile = tts
 			/Policy/policy/streams/accessibility/applicable_volume_profile/volume_profile = accessibility
+			/Policy/policy/streams/assistant/applicable_volume_profile/volume_profile = assistant
 			/Policy/policy/streams/rerouting/applicable_volume_profile/volume_profile = rerouting
 			/Policy/policy/streams/patch/applicable_volume_profile/volume_profile = patch
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
new file mode 100644
index 0000000..9abcb70
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP No Input configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":buildcommontypesstructure_gen",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        "device_for_input_source.pfw",
+        ":volumes.pfw",
+    ],
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem-no-strategy",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
new file mode 100644
index 0000000..27172a4
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP No output configuration example
+
+soong_namespace {
+    imports: [
+        "frameworks/av/services/audiopolicy/engineconfigurable/config/example/phone",
+        "frameworks/av/services/audiopolicy/config",
+    ],
+}
+
+prebuilt_etc {
+    name: "parameter-framework.policy",
+    filename_from_src: true,
+    vendor: true,
+    src: ":domaingeneratorpolicyrule_gen",
+    sub_dir: "parameter-framework/Settings/Policy",
+    required: [
+        "PolicyClass.xml",
+        "PolicySubsystem.xml",
+        "PolicySubsystem-CommonTypes.xml",
+    ],
+}
+genrule {
+    name: "domaingeneratorpolicyrule_gen",
+    defaults: ["domaingeneratorpolicyrule"],
+    srcs: [
+        ":audio_policy_pfw_toplevel",
+        ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criterion_types",
+        ":edd_files",
+    ],
+}
+filegroup {
+    name: "audio_policy_pfw_toplevel",
+    srcs: [":ParameterFrameworkConfigurationPolicy.userdebug.xml"],
+}
+filegroup {
+    name: "audio_policy_pfw_structure_files",
+    srcs: [
+        ":PolicyClass",
+        ":PolicySubsystem",
+        ":buildcommontypesstructure_gen",
+    ],
+}
+filegroup {
+    name: "edd_files",
+    srcs: [
+        "device_for_strategies.pfw",
+        ":volumes.pfw",
+        ":device_for_input_source.pfw",
+    ],
+}
+prebuilt_etc {
+    name: "PolicySubsystem.xml",
+    vendor: true,
+    src: ":PolicySubsystem-no-strategy",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
index f923610..e259c00 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
@@ -13,7 +13,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -41,7 +41,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -69,7 +69,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -97,7 +97,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -125,7 +125,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -153,7 +153,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -181,7 +181,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -209,7 +209,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
@@ -237,7 +237,7 @@
 				bluetooth_a2dp_headphones = 0
 				bluetooth_a2dp_speaker = 0
 				hdmi = 0
-				angl_dock_headset = 0
+				anlg_dock_headset = 0
 				dgtl_dock_headset = 0
 				usb_accessory = 0
 				usb_device = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml
deleted file mode 100644
index d17c021..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml
+++ /dev/null
@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-              xmlns:xi="http://www.w3.org/2001/XInclude"
-              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
-    <!-- Output devices definition as a bitfield for the supported devices per output
-    profile. It must match with the output device enum parameter.
-    -->
-     <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
-
-     <!--#################### GLOBAL COMPONENTS END ####################-->
-
-    <ComponentType Name="OutputDevicesMask" Description="32th bit is not allowed as dedicated
-                                                     for input devices detection">
-        <BitParameterBlock Name="mask" Size="32">
-            <BitParameter Name="earpiece" Size="1" Pos="0"/>
-            <BitParameter Name="speaker" Size="1" Pos="1"/>
-            <BitParameter Name="wired_headset" Size="1" Pos="2"/>
-            <BitParameter Name="wired_headphone" Size="1" Pos="3"/>
-            <BitParameter Name="bluetooth_sco" Size="1" Pos="4"/>
-            <BitParameter Name="bluetooth_sco_headset" Size="1" Pos="5"/>
-            <BitParameter Name="bluetooth_sco_carkit" Size="1" Pos="6"/>
-            <BitParameter Name="bluetooth_a2dp" Size="1" Pos="7"/>
-            <BitParameter Name="bluetooth_a2dp_headphones" Size="1" Pos="8"/>
-            <BitParameter Name="bluetooth_a2dp_speaker" Size="1" Pos="9"/>
-            <BitParameter Name="hdmi" Size="1" Pos="10"/>
-            <BitParameter Name="angl_dock_headset" Size="1" Pos="11"/>
-            <BitParameter Name="dgtl_dock_headset" Size="1" Pos="12"/>
-            <BitParameter Name="usb_accessory" Size="1" Pos="13"/>
-            <BitParameter Name="usb_device" Size="1" Pos="14"/>
-            <BitParameter Name="remote_submix" Size="1" Pos="15"/>
-            <BitParameter Name="telephony_tx" Size="1" Pos="16"/>
-            <BitParameter Name="line" Size="1" Pos="17"/>
-            <BitParameter Name="hdmi_arc" Size="1" Pos="18"/>
-            <BitParameter Name="spdif" Size="1" Pos="19"/>
-            <BitParameter Name="fm" Size="1" Pos="20"/>
-            <BitParameter Name="aux_line" Size="1" Pos="21"/>
-            <BitParameter Name="speaker_safe" Size="1" Pos="22"/>
-            <BitParameter Name="ip" Size="1" Pos="23"/>
-            <BitParameter Name="bus" Size="1" Pos="24"/>
-            <BitParameter Name="proxy" Size="1" Pos="25"/>
-            <BitParameter Name="usb_headset" Size="1" Pos="26"/>
-            <BitParameter Name="hearing_aid" Size="1" Pos="27"/>
-            <BitParameter Name="echo_canceller" Size="1" Pos="28"/>
-            <BitParameter Name="stub" Size="1" Pos="30"/>
-        </BitParameterBlock>
-    </ComponentType>
-
-    <!-- Input devices definition as a bitfield for the supported devices per Input
-    profile. It must match with the Input device enum parameter.
-    -->
-    <ComponentType Name="InputDevicesMask">
-        <BitParameterBlock Name="mask" Size="32">
-            <BitParameter Name="communication" Size="1" Pos="0"/>
-            <BitParameter Name="ambient" Size="1" Pos="1"/>
-            <BitParameter Name="builtin_mic" Size="1" Pos="2"/>
-            <BitParameter Name="bluetooth_sco_headset" Size="1" Pos="3"/>
-            <BitParameter Name="wired_headset" Size="1" Pos="4"/>
-            <BitParameter Name="hdmi" Size="1" Pos="5"/>
-            <BitParameter Name="telephony_rx" Size="1" Pos="6"/>
-            <BitParameter Name="back_mic" Size="1" Pos="7"/>
-            <BitParameter Name="remote_submix" Size="1" Pos="8"/>
-            <BitParameter Name="anlg_dock_headset" Size="1" Pos="9"/>
-            <BitParameter Name="dgtl_dock_headset" Size="1" Pos="10"/>
-            <BitParameter Name="usb_accessory" Size="1" Pos="11"/>
-            <BitParameter Name="usb_device" Size="1" Pos="12"/>
-            <BitParameter Name="fm_tuner" Size="1" Pos="13"/>
-            <BitParameter Name="tv_tuner" Size="1" Pos="14"/>
-            <BitParameter Name="line" Size="1" Pos="15"/>
-            <BitParameter Name="spdif" Size="1" Pos="16"/>
-            <BitParameter Name="bluetooth_a2dp" Size="1" Pos="17"/>
-            <BitParameter Name="loopback" Size="1" Pos="18"/>
-            <BitParameter Name="ip" Size="1" Pos="19"/>
-            <BitParameter Name="bus" Size="1" Pos="20"/>
-            <BitParameter Name="proxy" Size="1" Pos="21"/>
-            <BitParameter Name="usb_headset" Size="1" Pos="22"/>
-            <BitParameter Name="bluetooth_ble" Size="1" Pos="23"/>
-            <BitParameter Name="hdmi_arc" Size="1" Pos="24"/>
-            <BitParameter Name="echo_reference" Size="1" Pos="25"/>
-            <BitParameter Name="stub" Size="1" Pos="30"/>
-        </BitParameterBlock>
-    </ComponentType>
-
-    <ComponentType Name="OutputFlags"
-                   Description="the audio output flags serve two purposes:
-                    - when an AudioTrack is created they indicate a wish to be connected to an
-                      output stream with attributes corresponding to the specified flags.
-                    - when present in an output profile descriptor listed for a particular audio
-                      hardware module, they indicate that an output stream can be opened that
-                      supports the attributes indicated by the flags.
-                    The audio policy manager will try to match the flags in the request
-                    (when getOuput() is called) to an available output stream.">
-        <BitParameterBlock Name="mask" Size="32">
-            <BitParameter Name="direct" Size="1" Pos="0"/>
-            <BitParameter Name="primary" Size="1" Pos="1"/>
-            <BitParameter Name="fast" Size="1" Pos="2"/>
-            <BitParameter Name="deep_buffer" Size="1" Pos="3"/>
-            <BitParameter Name="compress_offload" Size="1" Pos="4"/>
-            <BitParameter Name="non_blocking" Size="1" Pos="5"/>
-            <BitParameter Name="hw_av_sync" Size="1" Pos="6"/>
-            <BitParameter Name="tts" Size="1" Pos="7"/>
-            <BitParameter Name="raw" Size="1" Pos="8"/>
-            <BitParameter Name="sync" Size="1" Pos="9"/>
-            <BitParameter Name="iec958_nonaudio" Size="1" Pos="10"/>
-        </BitParameterBlock>
-    </ComponentType>
-
-    <ComponentType Name="InputFlags"
-                   Description="The audio input flags are analogous to audio output flags.
-                                Currently they are used only when an AudioRecord is created,
-                                to indicate a preference to be connected to an input stream with
-                                attributes corresponding to the specified flags.">
-        <BitParameterBlock Name="mask" Size="32">
-            <BitParameter Name="fast" Size="1" Pos="0"/>
-            <BitParameter Name="hw_hotword" Size="1" Pos="2"/>
-            <BitParameter Name="raw" Size="1" Pos="3"/>
-            <BitParameter Name="sync" Size="1" Pos="4"/>
-        </BitParameterBlock>
-    </ComponentType>
-
-    <ComponentType Name="InputSourcesMask" Description="The audio input source is also known
-                                                        as the use case.">
-        <BitParameterBlock Name="mask" Size="32">
-            <BitParameter Name="default" Size="1" Pos="0"/>
-            <BitParameter Name="mic" Size="1" Pos="1"/>
-            <BitParameter Name="voice_uplink" Size="1" Pos="2"/>
-            <BitParameter Name="voice_downlink" Size="1" Pos="3"/>
-            <BitParameter Name="voice_call" Size="1" Pos="4"/>
-            <BitParameter Name="camcorder" Size="1" Pos="5"/>
-            <BitParameter Name="voice_recognition" Size="1" Pos="6"/>
-            <BitParameter Name="voice_communication" Size="1" Pos="7"/>
-            <BitParameter Name="remote_submix" Size="1" Pos="8"/>
-            <BitParameter Name="unprocessed" Size="1" Pos="9"/>
-            <BitParameter Name="voice_performance" Size="1" Pos="10"/>
-            <BitParameter Name="echo_reference" Size="1" Pos="11"/>
-            <BitParameter Name="fm_tuner" Size="1" Pos="12"/>
-            <BitParameter Name="hotword" Size="1" Pos="13"/>
-        </BitParameterBlock>
-    </ComponentType>
-
-    <!--#################### STREAM COMMON TYPES BEGIN ####################-->
-
-    <ComponentType Name="VolumeProfileType">
-        <EnumParameter Name="volume_profile" Size="32">
-            <ValuePair Literal="voice_call" Numerical="0"/>
-            <ValuePair Literal="system" Numerical="1"/>
-            <ValuePair Literal="ring" Numerical="2"/>
-            <ValuePair Literal="music" Numerical="3"/>
-            <ValuePair Literal="alarm" Numerical="4"/>
-            <ValuePair Literal="notification" Numerical="5"/>
-            <ValuePair Literal="bluetooth_sco" Numerical="6"/>
-            <ValuePair Literal="enforced_audible" Numerical="7"/>
-            <ValuePair Literal="dtmf" Numerical="8"/>
-            <ValuePair Literal="tts" Numerical="9"/>
-            <ValuePair Literal="accessibility" Numerical="10"/>
-            <ValuePair Literal="rerouting" Numerical="11"/>
-            <ValuePair Literal="patch" Numerical="12"/>
-        </EnumParameter>
-    </ComponentType>
-
-    <ComponentType Name="Stream"  Mapping="Stream">
-        <Component Name="applicable_volume_profile" Type="VolumeProfileType"
-                   Description="Volume profile followed by a given stream type."/>
-    </ComponentType>
-
-    <!--#################### STREAM COMMON TYPES END ####################-->
-
-    <!--#################### INPUT SOURCE COMMON TYPES BEGIN ####################-->
-
-    <ComponentType Name="InputSource">
-        <Component Name="applicable_input_device" Type="InputDevicesMask"
-                   Mapping="InputSource" Description="Selected Input device"/>
-    </ComponentType>
-
-    <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
-
-    <!--#################### PRODUCT STRATEGY COMMON TYPES BEGIN ####################-->
-
-    <ComponentType Name="ProductStrategy" Mapping="ProductStrategy">
-        <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
-        <StringParameter Name="device_address" MaxLength="256"
-                         Description="if any, device address associated"/>
-    </ComponentType>
-
-    <!--#################### PRODUCT STRATEGY COMMON TYPES END ####################-->
-
-</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml.in
new file mode 100644
index 0000000..2e9f37e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-CommonTypes.xml.in
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+    <!-- Output devices definition as a bitfield for the supported devices per output
+    profile. It must match with the output device enum parameter.
+    -->
+     <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+
+     <!--#################### GLOBAL COMPONENTS END ####################-->
+
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="OutputDevicesMask" Description="32th bit is not allowed as dedicated for input devices detection">
+        <BitParameterBlock Name="mask" Size="32">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!-- Input devices definition as a bitfield for the supported devices per Input
+    profile. It must match with the Input device enum parameter.
+    -->
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="InputDevicesMask">
+        <BitParameterBlock Name="mask" Size="32">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES BEGIN ####################-->
+    <!-- Automatically filled from audio-base.h file. VolumeProfileType is associated to stream type -->
+    <ComponentType Name="VolumeProfileType">
+        <EnumParameter Name="volume_profile" Size="32">
+        </EnumParameter>
+    </ComponentType>
+
+    <ComponentType Name="Stream"  Mapping="Stream">
+        <Component Name="applicable_volume_profile" Type="VolumeProfileType"
+                   Description="Volume profile followed by a given stream type."/>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES END ####################-->
+
+    <!--#################### INPUT SOURCE COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="InputSource">
+        <Component Name="applicable_input_device" Type="InputDevicesMask"
+                   Mapping="InputSource" Description="Selected Input device"/>
+    </ComponentType>
+
+    <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="ProductStrategy" Mapping="ProductStrategy">
+        <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
+        <StringParameter Name="device_address" MaxLength="256"
+                         Description="if any, device address associated"/>
+    </ComponentType>
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES END ####################-->
+
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml
index a4e7537..ed349c8 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem-no-strategy.xml
@@ -28,6 +28,8 @@
                              Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
             <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
                              Description="For accessibility talk back prompts"/>
+            <Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
+                             Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
             <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
                              Description="For dynamic policy output mixes"/>
             <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
index b55ce2c..7bbb57a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/common/Structure/PolicySubsystem.xml
@@ -44,6 +44,8 @@
                              Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
             <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
                              Description="For accessibility talk back prompts"/>
+            <Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
+                             Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
             <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
                              Description="For dynamic policy output mixes"/>
             <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
@@ -73,10 +75,13 @@
                                             Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
             <Component Name="unprocessed" Type="InputSource"
                                             Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <Component Name="voice_performance" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <Component Name="echo_reference" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
             <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
             <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
         </ComponentType>
-
         <!--#################### INPUT SOURCE END ####################-->
     </ComponentLibrary>
 
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index cb45fcf..6d42fcf 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -32,6 +32,9 @@
 #include <policy.h>
 #include <AudioIODescriptorInterface.h>
 #include <ParameterManagerWrapper.h>
+#include <media/AudioContainers.h>
+
+#include <media/TypeConverter.h>
 
 using std::string;
 using std::map;
@@ -77,8 +80,9 @@
 
 status_t Engine::initCheck()
 {
-    if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start() != NO_ERROR) {
-        ALOGE("%s: could not start Policy PFW", __FUNCTION__);
+    std::string error;
+    if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
+        ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
         return NO_INIT;
     }
     return EngineBase::initCheck();
@@ -125,7 +129,7 @@
     Element<Key> *element = getFromCollection<Key>(key);
     if (element == NULL) {
         ALOGE("%s: Element not found within collection", __FUNCTION__);
-        return BAD_VALUE;
+        return false;
     }
     return element->template set<Property>(property) == NO_ERROR;
 }
@@ -159,19 +163,21 @@
     return mPolicyParameterMgr->getForceUse(usage);
 }
 
-status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> device,
                                           audio_policy_dev_state_t state)
 {
-    mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
-
-    if (audio_is_output_device(devDesc->type())) {
+    mPolicyParameterMgr->setDeviceConnectionState(
+                device->type(), device->address().c_str(), state);
+    if (audio_is_output_device(device->type())) {
+        // FIXME: Use DeviceTypeSet when the interface is ready
         return mPolicyParameterMgr->setAvailableOutputDevices(
-                    getApmObserver()->getAvailableOutputDevices().types());
-    } else if (audio_is_input_device(devDesc->type())) {
+                    deviceTypesToBitMask(getApmObserver()->getAvailableOutputDevices().types()));
+    } else if (audio_is_input_device(device->type())) {
+        // FIXME: Use DeviceTypeSet when the interface is ready
         return mPolicyParameterMgr->setAvailableInputDevices(
-                    getApmObserver()->getAvailableInputDevices().types());
+                    deviceTypesToBitMask(getApmObserver()->getAvailableInputDevices().types()));
     }
-    return BAD_TYPE;
+    return EngineBase::setDeviceConnectionState(device, state);
 }
 
 status_t Engine::loadAudioPolicyEngineConfig()
@@ -209,7 +215,7 @@
     }
     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
-    uint32_t availableOutputDevicesType = availableOutputDevices.types();
+    DeviceTypeSet availableOutputDevicesTypes = availableOutputDevices.types();
 
     /** This is the only case handled programmatically because the PFW is unable to know the
      * activity of streams.
@@ -221,7 +227,7 @@
      *
      * -When media is not playing anymore, fall back on the sonification behavior
      */
-    audio_devices_t devices = AUDIO_DEVICE_NONE;
+    DeviceTypeSet deviceTypes;
     if (ps == getProductStrategyForStream(AUDIO_STREAM_NOTIFICATION) &&
             !is_state_in_call(getPhoneState()) &&
             !outputs.isActiveRemotely(toVolumeSource(AUDIO_STREAM_MUSIC),
@@ -230,7 +236,7 @@
                              SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
         product_strategy_t strategyForMedia =
                 getProductStrategyForStream(AUDIO_STREAM_MUSIC);
-        devices = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
+        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyForMedia);
     } else if (ps == getProductStrategyForStream(AUDIO_STREAM_ACCESSIBILITY) &&
         (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
          outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM)))) {
@@ -238,28 +244,37 @@
             // compressed format as they would likely not be mixed and dropped.
             // Device For Sonification conf file has HDMI, SPDIF and HDMI ARC unreacheable.
         product_strategy_t strategyNotification = getProductStrategyForStream(AUDIO_STREAM_RING);
-        devices = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
+        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(strategyNotification);
     } else {
-        devices = productStrategies.getDeviceTypesForProductStrategy(ps);
+        deviceTypes = productStrategies.getDeviceTypesForProductStrategy(ps);
     }
-    if (devices == AUDIO_DEVICE_NONE ||
-            (devices & availableOutputDevicesType) == AUDIO_DEVICE_NONE) {
-        devices = getApmObserver()->getDefaultOutputDevice()->type();
-        ALOGE_IF(devices == AUDIO_DEVICE_NONE, "%s: no valid default device defined", __FUNCTION__);
-        return DeviceVector(getApmObserver()->getDefaultOutputDevice());
+    if (deviceTypes.empty() ||
+            Intersection(deviceTypes, availableOutputDevicesTypes).empty()) {
+        auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
+        ALOG_ASSERT(defaultDevice != nullptr, "no valid default device defined");
+        return DeviceVector(defaultDevice);
     }
-    if (/*device_distinguishes_on_address(devices)*/ devices == AUDIO_DEVICE_OUT_BUS) {
+    if (/*device_distinguishes_on_address(*deviceTypes.begin())*/ isSingleDeviceType(
+            deviceTypes, AUDIO_DEVICE_OUT_BUS)) {
         // We do expect only one device for these types of devices
         // Criterion device address garantee this one is available
         // If this criterion is not wished, need to ensure this device is available
         const String8 address(productStrategies.getDeviceAddressForProductStrategy(ps).c_str());
-        ALOGV("%s:device 0x%x %s %d", __FUNCTION__, devices, address.c_str(), ps);
-        return DeviceVector(availableOutputDevices.getDevice(devices,
-                                                             address,
-                                                             AUDIO_FORMAT_DEFAULT));
+        ALOGV("%s:device %s %s %d",
+                __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), address.c_str(), ps);
+        auto busDevice = availableOutputDevices.getDevice(
+                *deviceTypes.begin(), address, AUDIO_FORMAT_DEFAULT);
+        if (busDevice == nullptr) {
+            ALOGE("%s:unavailable device %s %s, fallback on default", __func__,
+                  dumpDeviceTypes(deviceTypes).c_str(), address.c_str());
+            auto defaultDevice = getApmObserver()->getDefaultOutputDevice();
+            ALOG_ASSERT(defaultDevice != nullptr, "Default Output Device NOT available");
+            return DeviceVector(defaultDevice);
+        }
+        return DeviceVector(busDevice);
     }
-    ALOGV("%s:device 0x%x %d", __FUNCTION__, devices, ps);
-    return availableOutputDevices.getDevicesFromTypeMask(devices);
+    ALOGV("%s:device %s %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), ps);
+    return availableOutputDevices.getDevicesFromTypes(deviceTypes);
 }
 
 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@@ -356,12 +371,13 @@
         ALOGE("%s: set device %d on invalid strategy %d", __FUNCTION__, devices, strategy);
         return false;
     }
-    getProductStrategies().at(strategy)->setDeviceTypes(devices);
+    // FIXME: stop using deviceTypesFromBitMask when the interface is ready
+    getProductStrategies().at(strategy)->setDeviceTypes(deviceTypesFromBitMask(devices));
     return true;
 }
 
 template <>
-AudioPolicyManagerInterface *Engine::queryInterface()
+EngineInterface *Engine::queryInterface()
 {
     return this;
 }
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4662e7e..3b371d8 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -17,7 +17,7 @@
 #pragma once
 
 #include "EngineBase.h"
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
 
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 2442590..b127796 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <AudioPolicyManagerInterface.h>
+#include <EngineInterface.h>
 #include <AudioPolicyPluginInterface.h>
 #include "AudioPolicyEngineInstance.h"
 #include "Engine.h"
@@ -45,9 +45,9 @@
 }
 
 template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const
+EngineInterface *EngineInstance::queryInterface() const
 {
-    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
+    return getEngine()->queryInterface<EngineInterface>();
 }
 
 template <>
@@ -57,5 +57,16 @@
 }
 
 } // namespace audio_policy
+
+extern "C" EngineInterface* createEngineInstance()
+{
+    return audio_policy::EngineInstance::getInstance()->queryInterface<EngineInterface>();
+}
+
+extern "C" void destroyEngineInstance(EngineInterface*)
+{
+    // The engine is a singleton.
+}
+
 } // namespace android
 
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index d252d3f..aa06ae3 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -30,7 +30,7 @@
         return BAD_VALUE;
     }
     mIdentifier = identifier;
-    ALOGD("%s: InputSource %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
+    ALOGV("%s: InputSource %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
     return NO_ERROR;
 }
 
@@ -46,15 +46,18 @@
 template <>
 status_t Element<audio_source_t>::set(audio_devices_t devices)
 {
-    if (devices != AUDIO_DEVICE_NONE) {
-        devices |= AUDIO_DEVICE_BIT_IN;
+    if (devices == AUDIO_DEVICE_NONE) {
+        // Reset
+        mApplicableDevices = devices;
+        return NO_ERROR;
     }
+    devices |= AUDIO_DEVICE_BIT_IN;
     if (!audio_is_input_device(devices)) {
         ALOGE("%s: trying to set an invalid device 0x%X for input source %s",
               __FUNCTION__, devices, getName().c_str());
         return BAD_VALUE;
     }
-    ALOGD("%s: 0x%X for input source %s", __FUNCTION__, devices, getName().c_str());
+    ALOGV("%s: 0x%X for input source %s", __FUNCTION__, devices, getName().c_str());
     mApplicableDevices = devices;
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h
index e1865cc..d64a60a 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.h
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.h
@@ -73,10 +73,11 @@
     Element(const Element &object);
     Element &operator=(const Element &object);
 
-    std::string mName; /**< Unique literal Identifier of a policy base element*/
-    audio_source_t mIdentifier; /**< Unique numerical Identifier of a policy base element*/
-
-    audio_devices_t mApplicableDevices; /**< Applicable input device for this input source. */
+    const std::string mName; /**< Unique literal Identifier of a policy base element*/
+    /** Unique numerical Identifier of a policy base element */
+    audio_source_t mIdentifier = AUDIO_SOURCE_DEFAULT;
+    /** Applicable input device for this input source. */
+    audio_devices_t mApplicableDevices = AUDIO_DEVICE_NONE;
 };
 
 typedef Element<audio_source_t> InputSource;
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 297eb02..e64ba4b 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -30,7 +30,7 @@
         return BAD_VALUE;
     }
     mIdentifier = identifier;
-    ALOGD("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
+    ALOGV("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
     return NO_ERROR;
 }
 
@@ -41,7 +41,7 @@
         return BAD_VALUE;
     }
     mVolumeProfile = volumeProfile;
-    ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, mVolumeProfile, getName().c_str());
+    ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mVolumeProfile, getName().c_str());
     return NO_ERROR;
 }
 
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 8c16972..3e47324 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -16,14 +16,17 @@
     name: "tools_default",
     version: {
         py2: {
-            enabled: true,
+            enabled: false,
         },
         py3: {
-            enabled: false,
+            enabled: true,
         },
     },
 }
 
+//##################################################################################################
+// Tools for audio policy engine criterion type configuration file
+//
 python_binary_host {
     name: "buildPolicyCriterionTypes.py",
     main: "buildPolicyCriterionTypes.py",
@@ -33,6 +36,30 @@
     defaults: ["tools_default"],
 }
 
+genrule_defaults {
+    name: "buildpolicycriteriontypesrule",
+    tools: ["buildPolicyCriterionTypes.py"],
+    cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
+         "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
+         "$(location buildPolicyCriterionTypes.py) " +
+         // @todo update if 1428659 is merged "--androidaudiobaseheader $(location :android_audio_base_header_file) " +
+         " --androidaudiobaseheader system/media/audio/include/system/audio-base.h " +
+         "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
+         "--criteriontypes $(location :audio_policy_engine_criterion_types_template) " +
+         "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // @todo uncomment if 1428659 is merged":android_audio_base_header_file",
+        ":audio_policy_engine_criterion_types_template",
+        // ":audio_policy_configuration_top_file",
+        // ":audio_policy_configuration_files",
+    ],
+    out: ["audio_policy_engine_criterion_types.xml"],
+}
+
+//##################################################################################################
+// Tools for audio policy engine parameter framework configurable domains
+//
 python_binary_host {
     name: "domainGeneratorPolicy.py",
     main: "domainGeneratorPolicy.py",
@@ -50,6 +77,38 @@
     ],
 }
 
+genrule_defaults {
+    name: "domaingeneratorpolicyrule",
+    tools: [
+        "domainGeneratorPolicy.py",
+        "domainGeneratorConnector",
+    ],
+    cmd: "mkdir -p $(genDir)/Structure/Policy && " +
+         "cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
+         "cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
+         "$(location domainGeneratorPolicy.py) " +
+         "--validate " +
+         "--domain-generator-tool $(location domainGeneratorConnector) " +
+         "--toplevel-config $(genDir)/top_level " +
+         "--criteria $(location :audio_policy_engine_criteria) " +
+         "--criteriontypes $(location :audio_policy_engine_criterion_types) " +
+         "--add-edds $(locations :edd_files) " +
+         "--schemas-dir external/parameter-framework/upstream/schemas " +
+         " > $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // ":audio_policy_pfw_toplevel",
+        // ":audio_policy_pfw_structure_files",
+        ":audio_policy_engine_criteria",
+        // ":audio_policy_engine_criterion_types",
+        // ":edd_files",
+    ],
+    out: ["PolicyConfigurableDomains.xml"],
+}
+
+//##################################################################################################
+// Tools for policy parameter-framework product strategies structure file generation
+//
 python_binary_host {
     name: "buildStrategiesStructureFile.py",
     main: "buildStrategiesStructureFile.py",
@@ -58,3 +117,45 @@
     ],
     defaults: ["tools_default"],
 }
+
+genrule_defaults {
+    name: "buildstrategiesstructurerule",
+    tools: ["buildStrategiesStructureFile.py"],
+    cmd: "cp $(locations :audio_policy_engine_configuration_files) $(genDir) && ls -l $(genDir) &&"+
+         "$(location buildStrategiesStructureFile.py) " +
+         "--audiopolicyengineconfigurationfile $(genDir)/audio_policy_engine_configuration.xml "+
+         "--productstrategiesstructurefile $(location :product_strategies_structure_template) " +
+         "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // ":audio_policy_engine_configuration_files",
+        ":product_strategies_structure_template",
+    ],
+    out: ["ProductStrategies.xml"],
+}
+
+//##################################################################################################
+// Tools for policy parameter-framework common type structure file generation
+//
+python_binary_host {
+    name: "buildCommonTypesStructureFile.py",
+    main: "buildCommonTypesStructureFile.py",
+    srcs: [
+        "buildCommonTypesStructureFile.py",
+    ],
+    defaults: ["tools_default"],
+}
+
+genrule_defaults {
+    name: "buildcommontypesstructurerule",
+    tools: ["buildCommonTypesStructureFile.py"],
+    cmd: "$(location buildCommonTypesStructureFile.py) " +
+         "--androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+         "--commontypesstructure $(location :common_types_structure_template) " +
+         "--outputfile $(out)",
+    srcs: [
+        ":common_types_structure_template",
+        ":libaudio_system_audio_base",
+    ],
+    out: ["PolicySubsystem-CommonTypes.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
new file mode 100755
index 0000000..9a7fa8f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
@@ -0,0 +1,184 @@
+#! /usr/bin/python3
+#
+# pylint: disable=line-too-long, missing-docstring, logging-format-interpolation, invalid-name
+
+#
+# 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.
+
+import argparse
+import re
+import sys
+import os
+import logging
+import xml.etree.ElementTree as ET
+from collections import OrderedDict
+import xml.dom.minidom as MINIDOM
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+        structure file generator.\n\
+        Exit with the number of (recoverable or not) error that occured.")
+    argparser.add_argument('--androidaudiobaseheader',
+                           help="Android Audio Base C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--commontypesstructure',
+                           help="Structure XML base file. Mandatory.",
+                           metavar="STRUCTURE_FILE_IN",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--outputfile',
+                           help="Structure XML file. Mandatory.",
+                           metavar="STRUCTURE_FILE_OUT",
+                           type=argparse.FileType('w'),
+                           required=True)
+    argparser.add_argument('--verbose',
+                           action='store_true')
+
+    return argparser.parse_args()
+
+
+def findBitPos(decimal):
+    pos = 0
+    i = 1
+    while i != decimal:
+        i = i << 1
+        pos = pos + 1
+        if pos == 32:
+            return -1
+    return pos
+
+
+def generateXmlStructureFile(componentTypeDict, structureTypesFile, outputFile):
+
+    logging.info("Importing structureTypesFile {}".format(structureTypesFile))
+    component_types_in_tree = ET.parse(structureTypesFile)
+
+    component_types_root = component_types_in_tree.getroot()
+
+    for component_types_name, values_dict in componentTypeDict.items():
+        for component_type in component_types_root.findall('ComponentType'):
+            if component_type.get('Name') == component_types_name:
+                bitparameters_node = component_type.find("BitParameterBlock")
+                if bitparameters_node is not None:
+                    ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                    for key, value in ordered_values.items():
+                        value_node = ET.SubElement(bitparameters_node, "BitParameter")
+                        value_node.set('Name', key)
+                        value_node.set('Size', "1")
+                        value_node.set('Pos', str(findBitPos(value)))
+
+                enum_parameter_node = component_type.find("EnumParameter")
+                if enum_parameter_node is not None:
+                    ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                    for key, value in ordered_values.items():
+                        value_node = ET.SubElement(enum_parameter_node, "ValuePair")
+                        value_node.set('Literal', key)
+                        value_node.set('Numerical', str(value))
+
+    xmlstr = ET.tostring(component_types_root, encoding='utf8', method='xml')
+    reparsed = MINIDOM.parseString(xmlstr)
+    prettyXmlStr = reparsed.toprettyxml(indent="    ", newl='\n')
+    prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+    outputFile.write(prettyXmlStr)
+
+
+def capitalizeLine(line):
+    return ' '.join((w.capitalize() for w in line.split(' ')))
+
+def parseAndroidAudioFile(androidaudiobaseheaderFile):
+    #
+    # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+    #
+    component_type_mapping_table = {
+        'AUDIO_STREAM' : "VolumeProfileType",
+        'AUDIO_DEVICE_OUT' : "OutputDevicesMask",
+        'AUDIO_DEVICE_IN' : "InputDevicesMask"}
+
+    all_component_types = {
+        'VolumeProfileType' : {},
+        'OutputDevicesMask' : {},
+        'InputDevicesMask' : {}
+    }
+
+    #
+    # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+    #
+    ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
+
+    criteria_pattern = re.compile(
+        r"\s*(?P<type>(?:"+'|'.join(component_type_mapping_table.keys()) + "))_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+        r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+
+    logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+    for line_number, line in enumerate(androidaudiobaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiobaseheaderFile.name, line_number, line))
+
+            component_type_name = component_type_mapping_table[match.groupdict()['type']]
+            component_type_literal = match.groupdict()['literal'].lower()
+
+            component_type_numerical_value = match.groupdict()['values']
+
+            # for AUDIO_DEVICE_IN: need to remove sign bit / rename default to stub
+            if component_type_name == "InputDevicesMask":
+                component_type_numerical_value = str(int(component_type_numerical_value, 0) & ~2147483648)
+                if component_type_literal == "default":
+                    component_type_literal = "stub"
+
+            if component_type_name == "OutputDevicesMask":
+                if component_type_literal == "default":
+                    component_type_literal = "stub"
+
+            # Remove duplicated numerical values
+            if int(component_type_numerical_value, 0) in all_component_types[component_type_name].values():
+                logging.info("The value {}:{} is duplicated for criterion {}, KEEPING LATEST".format(component_type_numerical_value, component_type_literal, component_type_name))
+                for key in list(all_component_types[component_type_name]):
+                    if all_component_types[component_type_name][key] == int(component_type_numerical_value, 0):
+                        del all_component_types[component_type_name][key]
+
+            all_component_types[component_type_name][component_type_literal] = int(component_type_numerical_value, 0)
+
+            logging.debug("type:{}, literal:{}, values:{}.".format(component_type_name, component_type_literal, component_type_numerical_value))
+
+    # Transform input source in inclusive criterion
+    shift = len(all_component_types['OutputDevicesMask'])
+    if shift > 32:
+        logging.critical("OutputDevicesMask incompatible with criterion representation on 32 bits")
+        logging.info("EXIT ON FAILURE")
+        exit(1)
+
+    for component_types in all_component_types:
+        values = ','.join('{}:{}'.format(value, key) for key, value in all_component_types[component_types].items())
+        logging.info("{}: <{}>".format(component_types, values))
+
+    return all_component_types
+
+
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+    route_criteria = 0
+
+    all_component_types = parseAndroidAudioFile(args.androidaudiobaseheader)
+
+    generateXmlStructureFile(all_component_types, args.commontypesstructure, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
index a63c858..b8b60c1 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2018, The Android Open Source Project
@@ -19,10 +19,8 @@
 import argparse
 import re
 import sys
-import tempfile
 import os
 import logging
-import subprocess
 import xml.etree.ElementTree as ET
 import xml.etree.ElementInclude as EI
 import xml.dom.minidom as MINIDOM
@@ -49,33 +47,35 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        audio criterion type file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        audio criterion type file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
     argparser.add_argument('--androidaudiobaseheader',
-            help="Android Audio Base C header file, Mandatory.",
-            metavar="ANDROID_AUDIO_BASE_HEADER",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Base C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--audiopolicyconfigurationfile',
-            help="Android Audio Policy Configuration file, Mandatory.",
-            metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Policy Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--criteriontypes',
-            help="Criterion types XML base file, in \
-            '<criterion_types> \
-                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/>' \
-        format. Mandatory.",
-            metavar="CRITERION_TYPE_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Criterion types XML base file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                               values=<value1,value2,...>/>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--outputfile',
-            help="Criterion types outputfile file. Mandatory.",
-            metavar="CRITERION_TYPE_OUTPUT_FILE",
-            type=argparse.FileType('w'),
-            required=True)
+                           help="Criterion types outputfile file. Mandatory.",
+                           metavar="CRITERION_TYPE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
@@ -120,7 +120,7 @@
     reparsed = MINIDOM.parseString(xmlstr)
     prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
     prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
-    outputFile.write(prettyXmlStr.encode('utf-8'))
+    outputFile.write(prettyXmlStr)
 
 def capitalizeLine(line):
     return ' '.join((w.capitalize() for w in line.split(' ')))
@@ -137,30 +137,30 @@
     #
     address_criteria_mapping_table = {
         'sink' : "OutputDevicesAddressesType",
-        'source' : "InputDevicesAddressesType" }
+        'source' : "InputDevicesAddressesType"}
 
     address_criteria = {
         'OutputDevicesAddressesType' : [],
-        'InputDevicesAddressesType' : [] }
+        'InputDevicesAddressesType' : []}
 
-    oldWorkingDir = os.getcwd()
-    print "Current working directory %s" % oldWorkingDir
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
 
-    newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+    new_dir = os.path.join(old_working_dir, audiopolicyconfigurationfile.name)
 
     policy_in_tree = ET.parse(audiopolicyconfigurationfile)
-    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
 
-    print "new working directory %s" % os.getcwd()
+    print("new working directory %s" % os.getcwd())
 
     policy_root = policy_in_tree.getroot()
     EI.include(policy_root)
 
-    os.chdir(oldWorkingDir)
+    os.chdir(old_working_dir)
 
     for device in policy_root.iter('devicePort'):
         for key in address_criteria_mapping_table.keys():
-            if device.get('role') == key and device.get('address') :
+            if device.get('role') == key and device.get('address'):
                 logging.info("{}: <{}>".format(key, device.get('address')))
                 address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
 
@@ -188,15 +188,15 @@
     all_criteria = {
         'AndroidModeType' : {},
         'OutputDevicesMaskType' : {},
-        'InputDevicesMaskType' : {} }
+        'InputDevicesMaskType' : {}}
 
     #
     # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
     #
-    ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+    ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
 
     criteria_pattern = re.compile(
-        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))\_" \
+        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
         r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
         r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
 
@@ -221,7 +221,7 @@
                 logging.info("criterion {} duplicated values:".format(criterion_name))
                 logging.info("{}:{}".format(numerical_value, literal))
                 logging.info("KEEPING LATEST")
-                for key in all_criteria[criterion_name].keys():
+                for key in list(all_criteria[criterion_name]):
                     if all_criteria[criterion_name][key] == int(numerical_value, 0):
                         del all_criteria[criterion_name][key]
 
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
index af40602..f69d346 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2019, The Android Open Source Project
@@ -17,16 +17,12 @@
 #
 
 import argparse
-import re
 import sys
-import tempfile
 import os
 import logging
-import subprocess
 import xml.etree.ElementTree as ET
 import xml.etree.ElementInclude as EI
 import xml.dom.minidom as MINIDOM
-from collections import OrderedDict
 
 #
 # Helper script that helps to feed at build time the XML Product Strategies Structure file file used
@@ -46,33 +42,34 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        product strategies structure file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        product strategies structure file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
     argparser.add_argument('--audiopolicyengineconfigurationfile',
-            help="Android Audio Policy Engine Configuration file, Mandatory.",
-            metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Android Audio Policy Engine Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--productstrategiesstructurefile',
-            help="Product Strategies Structure XML base file, Mandatory.",
-            metavar="STRATEGIES_STRUCTURE_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Product Strategies Structure XML base file, Mandatory.",
+                           metavar="STRATEGIES_STRUCTURE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--outputfile',
-            help="Product Strategies Structure output file, Mandatory.",
-            metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE",
-            type=argparse.FileType('w'),
-            required=True)
+                           help="Product Strategies Structure output file, Mandatory.",
+                           metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
 
-def generateXmlStructureFile(strategies, strategyStructureInFile, outputFile):
+def generateXmlStructureFile(strategies, strategy_structure_in_file, output_file):
 
-    logging.info("Importing strategyStructureInFile {}".format(strategyStructureInFile))
-    strategies_in_tree = ET.parse(strategyStructureInFile)
+    logging.info("Importing strategy_structure_in_file {}".format(strategy_structure_in_file))
+    strategies_in_tree = ET.parse(strategy_structure_in_file)
 
     strategies_root = strategies_in_tree.getroot()
     strategy_components = strategies_root.find('ComponentType')
@@ -80,13 +77,15 @@
     for strategy_name in strategies:
         context_mapping = "".join(map(str, ["Name:", strategy_name]))
         strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
-        strategy_component_node = ET.SubElement(strategy_components, "Component", Name=strategy_pfw_name, Type="ProductStrategy", Mapping=context_mapping)
+        ET.SubElement(strategy_components, "Component",
+                      Name=strategy_pfw_name, Type="ProductStrategy",
+                      Mapping=context_mapping)
 
     xmlstr = ET.tostring(strategies_root, encoding='utf8', method='xml')
     reparsed = MINIDOM.parseString(xmlstr)
     prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
     prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
-    outputFile.write(prettyXmlStr.encode('utf-8'))
+    output_file.write(prettyXmlStr)
 
 def capitalizeLine(line):
     return ' '.join((w.capitalize() for w in line.split(' ')))
@@ -97,26 +96,27 @@
 #
 def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile):
 
-    logging.info("Checking Audio Policy Engine Configuration file {}".format(audiopolicyengineconfigurationfile))
+    logging.info("Checking Audio Policy Engine Configuration file {}".format(
+        audiopolicyengineconfigurationfile))
     #
     # extract all product strategies name from audio policy engine configuration file
     #
     strategy_names = []
 
-    oldWorkingDir = os.getcwd()
-    print "Current working directory %s" % oldWorkingDir
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
 
-    newDir = os.path.join(oldWorkingDir , audiopolicyengineconfigurationfile.name)
+    new_dir = os.path.join(old_working_dir, audiopolicyengineconfigurationfile.name)
 
     policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile)
-    os.chdir(os.path.dirname(os.path.normpath(newDir)))
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
 
-    print "new working directory %s" % os.getcwd()
+    print("new working directory %s" % os.getcwd())
 
     policy_engine_root = policy_engine_in_tree.getroot()
     EI.include(policy_engine_root)
 
-    os.chdir(oldWorkingDir)
+    os.chdir(old_working_dir)
 
     for strategy in policy_engine_root.iter('ProductStrategy'):
         strategy_names.append(strategy.get('name'))
@@ -128,7 +128,8 @@
     logging.root.setLevel(logging.INFO)
     args = parseArgs()
 
-    strategies = parseAndroidAudioPolicyEngineConfigurationFile(args.audiopolicyengineconfigurationfile)
+    strategies = parseAndroidAudioPolicyEngineConfigurationFile(
+        args.audiopolicyengineconfigurationfile)
 
     product_strategies_structure = args.productstrategiesstructurefile
 
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
deleted file mode 100644
index ac60ef7..0000000
--- a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/domainGeneratorPolicy.py \
-    $(PFW_TOPLEVEL_FILE) $(PFW_CRITERIA_FILE) $(PFW_CRITERION_TYPES_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): MY_TOOL := $(HOST_OUT_EXECUTABLES)/domainGeneratorPolicy.py
-$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
-$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
-$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
-$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
-$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
-$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_TOOL)" --validate \
-		--toplevel-config "$(MY_TOPLEVEL_FILE)" \
-		--criteria "$(MY_CRITERIA_FILE)" \
-		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
-		--initial-settings $(MY_TUNING_FILE) \
-		--add-edds $(MY_EDD_FILES) \
-		--add-domains $(MY_DOMAIN_FILES) \
-		--schemas-dir $(MY_SCHEMAS_DIR) > "$@"
-
-
-# Clear variables for further use
-PFW_TOPLEVEL_FILE :=
-PFW_STRUCTURE_FILES :=
-PFW_CRITERIA_FILE :=
-PFW_CRITERION_TYPES_FILE :=
-PFW_TUNING_FILE :=
-PFW_EDD_FILES :=
-PFW_DOMAIN_FILES :=
-PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
index 4dec9a2..b0c4b66 100755
--- a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 #
 # Copyright 2018, The Android Open Source Project
@@ -16,12 +16,7 @@
 # limitations under the License.
 #
 
-import EddParser
-from PFWScriptGenerator import PfwScriptTranslator
-import hostConfig
-
 import argparse
-import re
 import sys
 import tempfile
 import os
@@ -29,6 +24,10 @@
 import subprocess
 import xml.etree.ElementTree as ET
 
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
 #
 # In order to build the XML Settings file at build time, an instance of the parameter-framework
 # shall be started and fed with all the criterion types/criteria that will be used by
@@ -39,61 +38,67 @@
 
 def parseArgs():
     argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
-        Settings file generator.\n\
-        Exit with the number of (recoverable or not) error that occured.")
+                                        Settings file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occured.")
+    argparser.add_argument('--domain-generator-tool',
+                           help="ParameterFramework domain generator tool. Mandatory.",
+                           metavar="PFW_DOMAIN_GENERATOR_TOOL",
+                           required=True)
     argparser.add_argument('--toplevel-config',
-            help="Top-level parameter-framework configuration file. Mandatory.",
-            metavar="TOPLEVEL_CONFIG_FILE",
-            required=True)
+                           help="Top-level parameter-framework configuration file. Mandatory.",
+                           metavar="TOPLEVEL_CONFIG_FILE",
+                           required=True)
     argparser.add_argument('--criteria',
-            help="Criteria file, in XML format: \
-                  in '<criteria> \
-                          <criterion name="" type=""/> \
-                      </criteria>' \
-        format. Mandatory.",
-            metavar="CRITERIA_FILE",
-            type=argparse.FileType('r'),
-            required=True)
+                           help="Criteria file, in XML format: \
+                                 in '<criteria> \
+                                         <criterion name="" type=""/> \
+                                     </criteria>' \
+                           format. Mandatory.",
+                           metavar="CRITERIA_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
     argparser.add_argument('--criteriontypes',
-            help="Criterion types XML file, in \
-            '<criterion_types> \
-                <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
-             </criterion_types>' \
-        format. Mandatory.",
-            metavar="CRITERION_TYPE_FILE",
-            type=argparse.FileType('r'),
-            required=False)
+                           help="Criterion types XML file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                                               values=<value1,value2,...>/> \
+                            </criterion_types>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=False)
     argparser.add_argument('--initial-settings',
-            help="Initial XML settings file (containing a \
-        <ConfigurableDomains>  tag",
-            nargs='?',
-            default=None,
-            metavar="XML_SETTINGS_FILE")
+                           help="Initial XML settings file (containing a \
+                           <ConfigurableDomains>  tag",
+                           nargs='?',
+                           default=None,
+                           metavar="XML_SETTINGS_FILE")
     argparser.add_argument('--add-domains',
-            help="List of single domain files (each containing a single \
-        <ConfigurableDomain> tag",
-            metavar="XML_DOMAIN_FILE",
-            nargs='*',
-            dest='xml_domain_files',
-            default=[])
+                           help="List of single domain files (each containing a single \
+                           <ConfigurableDomain> tag",
+                           metavar="XML_DOMAIN_FILE",
+                           nargs='*',
+                           dest='xml_domain_files',
+                           default=[])
     argparser.add_argument('--add-edds',
-            help="List of files in EDD syntax (aka \".pfw\" files)",
-            metavar="EDD_FILE",
-            type=argparse.FileType('r'),
-            nargs='*',
-            default=[],
-            dest='edd_files')
+                           help="List of files in EDD syntax (aka \".pfw\" files)",
+                           metavar="EDD_FILE",
+                           type=argparse.FileType('r'),
+                           nargs='*',
+                           default=[],
+                           dest='edd_files')
     argparser.add_argument('--schemas-dir',
-            help="Directory of parameter-framework XML Schemas for generation \
-        validation",
-            default=None)
+                           help="Directory of parameter-framework XML Schemas for generation \
+                           validation",
+                           default=None)
     argparser.add_argument('--target-schemas-dir',
-            help="Ignored. Kept for retro-compatibility")
+                           help="Ignored. Kept for retro-compatibility")
     argparser.add_argument('--validate',
-            help="Validate the settings against XML schemas",
-            action='store_true')
+                           help="Validate the settings against XML schemas",
+                           action='store_true')
     argparser.add_argument('--verbose',
-            action='store_true')
+                           action='store_true')
 
     return argparser.parse_args()
 
@@ -112,7 +117,6 @@
     logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
 
     criteria_root = criteria_tree.getroot()
-    criterion_types_root = criterion_types_tree.getroot()
 
     all_criteria = []
     for criterion in criteria_root.findall('criterion'):
@@ -165,7 +169,7 @@
 
         try:
             root.propagate()
-        except EddParser.MyPropagationError, ex :
+        except EddParser.MyPropagationError as ex:
             logging.critical(str(ex))
             logging.info("EXIT ON FAILURE")
             exit(1)
@@ -179,32 +183,32 @@
 # It takes as input the collection of criteria, the domains and the simplified settings read from
 # pfw.
 #
-def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
-        # create and inject all the criteria
-        logging.info("Creating all criteria")
-        for criterion in all_criteria:
-            yield ["createSelectionCriterion", criterion['inclusive'],
-                   criterion['name']] + criterion['values']
+def generateDomainCommands(logger, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+    # create and inject all the criteria
+    logger.info("Creating all criteria")
+    for criterion in all_criteria:
+        yield ["createSelectionCriterion", criterion['inclusive'],
+               criterion['name']] + criterion['values']
 
-        yield ["start"]
+    yield ["start"]
 
-        # Import initial settings file
-        if initial_settings:
-            logging.info("Importing initial settings file {}".format(initial_settings))
-            yield ["importDomainsWithSettingsXML", initial_settings]
+    # Import initial settings file
+    if initial_settings:
+        logger.info("Importing initial settings file {}".format(initial_settings))
+        yield ["importDomainsWithSettingsXML", initial_settings]
 
-        # Import each standalone domain files
-        for domain_file in xml_domain_files:
-            logging.info("Importing single domain file {}".format(domain_file))
-            yield ["importDomainWithSettingsXML", domain_file]
+    # Import each standalone domain files
+    for domain_file in xml_domain_files:
+        logger.info("Importing single domain file {}".format(domain_file))
+        yield ["importDomainWithSettingsXML", domain_file]
 
-        # Generate the script for each EDD file
-        for filename, parsed_edd in parsed_edds:
-            logging.info("Translating and injecting EDD file {}".format(filename))
-            translator = PfwScriptTranslator()
-            parsed_edd.translate(translator)
-            for command in translator.getScript():
-                yield command
+    # Generate the script for each EDD file
+    for filename, parsed_edd in parsed_edds:
+        logger.info("Translating and injecting EDD file {}".format(filename))
+        translator = PfwScriptTranslator()
+        parsed_edd.translate(translator)
+        for command in translator.getScript():
+            yield command
 
 #
 # Entry point of the domain generator.
@@ -232,30 +236,29 @@
                                                        prefix="TMPdomainGeneratorPFConfig_")
 
     install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
-    hostConfig.configure(
-            infile=args.toplevel_config,
-            outfile=fake_toplevel_config,
-            structPath=install_path)
+    hostConfig.configure(infile=args.toplevel_config,
+                         outfile=fake_toplevel_config,
+                         structPath=install_path)
     fake_toplevel_config.close()
 
     # Create the connector. Pipe its input to us in order to write commands;
     # connect its output to stdout in order to have it dump the domains
     # there; connect its error output to stderr.
-    connector = subprocess.Popen(["domainGeneratorConnector",
-                            fake_toplevel_config.name,
-                            'verbose' if args.verbose else 'no-verbose',
-                            'validate' if args.validate else 'no-validate',
-                            args.schemas_dir],
-                           stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+    connector = subprocess.Popen([args.domain_generator_tool,
+                                  fake_toplevel_config.name,
+                                  'verbose' if args.verbose else 'no-verbose',
+                                  'validate' if args.validate else 'no-validate',
+                                  args.schemas_dir],
+                                 stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
 
     initial_settings = None
     if args.initial_settings:
         initial_settings = os.path.realpath(args.initial_settings)
 
     for command in generateDomainCommands(logging, all_criteria, initial_settings,
-                                       args.xml_domain_files, parsed_edds):
-        connector.stdin.write('\0'.join(command))
-        connector.stdin.write("\n")
+                                          args.xml_domain_files, parsed_edds):
+        connector.stdin.write('\0'.join(command).encode('utf-8'))
+        connector.stdin.write("\n".encode('utf-8'))
 
     # Closing the connector's input triggers the domain generation
     connector.stdin.close()
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
deleted file mode 100644
index dab5a0f..0000000
--- a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/buildPolicyCriterionTypes.py \
-    $(CRITERION_TYPES_FILE) $(AUDIO_POLICY_CONFIGURATION_FILE) \
-    $(ANDROID_AUDIO_BASE_HEADER_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(CRITERION_TYPES_FILE)
-$(LOCAL_BUILT_MODULE): MY_ANDROID_AUDIO_BASE_HEADER_FILE := $(ANDROID_AUDIO_BASE_HEADER_FILE)
-$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_CONFIGURATION_FILE := $(AUDIO_POLICY_CONFIGURATION_FILE)
-$(LOCAL_BUILT_MODULE): MY_CRITERION_TOOL := $(HOST_OUT_EXECUTABLES)/buildPolicyCriterionTypes.py
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_CRITERION_TOOL)" \
-		--androidaudiobaseheader "$(MY_ANDROID_AUDIO_BASE_HEADER_FILE)" \
-		--audiopolicyconfigurationfile "$(MY_AUDIO_POLICY_CONFIGURATION_FILE)" \
-		--criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
-		--outputfile "$(@)"
-
-# Clear variables for further use
-CRITERION_TYPES_FILE :=
-ANDROID_AUDIO_BASE_HEADER_FILE :=
-AUDIO_POLICY_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk b/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
deleted file mode 100644
index f2b1a19..0000000
--- a/services/audiopolicy/engineconfigurable/tools/provision_strategies_structure.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES += \
-    $(HOST_OUT_EXECUTABLES)/buildStrategiesStructureFile.py \
-    $(STRATEGIES_STRUCTURE_FILE) $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): MY_STRATEGIES_STRUCTURE_FILE := $(STRATEGIES_STRUCTURE_FILE)
-$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE := $(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)
-$(LOCAL_BUILT_MODULE): MY_PROVISION_TOOL := $(HOST_OUT_EXECUTABLES)/buildStrategiesStructureFile.py
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-
-	"$(MY_PROVISION_TOOL)" \
-		--audiopolicyengineconfigurationfile "$(MY_AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)" \
-		--productstrategiesstructurefile "$(MY_STRATEGIES_STRUCTURE_FILE)" \
-		--outputfile "$(@)"
-
-# Clear variables for further use
-STRATEGIES_STRUCTURE_FILE :=
-AUDIO_POLICY_ENGINE_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.bp b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
index 6f59487..301ecc0 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.bp
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
@@ -11,7 +11,6 @@
         "libbase_headers",
         "libaudiopolicycommon",
     ],
-    static_libs: ["libaudiopolicycomponents"],
     shared_libs: [
         "liblog",
         "libutils",
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 4b57444..63990ac 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -92,7 +92,8 @@
 template <>
 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionTypeInterface> {};
 
-ParameterManagerWrapper::ParameterManagerWrapper()
+ParameterManagerWrapper::ParameterManagerWrapper(bool enableSchemaVerification,
+                                                 const std::string &schemaUri)
     : mPfwConnectorLogger(new ParameterMgrPlatformConnectorLogger)
 {
     // Connector
@@ -104,6 +105,15 @@
 
     // Logger
     mPfwConnector->setLogger(mPfwConnectorLogger);
+
+    // Schema validation
+    std::string error;
+    bool ret = mPfwConnector->setValidateSchemasOnStart(enableSchemaVerification, error);
+    ALOGE_IF(!ret, "Failed to activate schema validation: %s", error.c_str());
+    if (enableSchemaVerification && ret && !schemaUri.empty()) {
+        ALOGE("Schema verification activated with schema URI: %s", schemaUri.c_str());
+        mPfwConnector->setSchemaUri(schemaUri);
+    }
 }
 
 status_t ParameterManagerWrapper::addCriterion(const std::string &name, bool isInclusive,
@@ -145,11 +155,10 @@
     delete mPfwConnector;
 }
 
-status_t ParameterManagerWrapper::start()
+status_t ParameterManagerWrapper::start(std::string &error)
 {
     ALOGD("%s: in", __FUNCTION__);
     /// Start PFW
-    std::string error;
     if (!mPfwConnector->start(error)) {
         ALOGE("%s: Policy PFW start error: %s", __FUNCTION__, error.c_str());
         return NO_INIT;
@@ -253,13 +262,13 @@
     return interface->getLiteralValue(valueToCheck, literalValue);
 }
 
-status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
-                                                           audio_policy_dev_state_t state)
+status_t ParameterManagerWrapper::setDeviceConnectionState(
+        audio_devices_t type, const std::string address, audio_policy_dev_state_t state)
 {
-    std::string criterionName = audio_is_output_device(devDesc->type()) ?
+    std::string criterionName = audio_is_output_device(type) ?
                 gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
 
-    ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->address().string(),
+    ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
           state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
     ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
@@ -271,8 +280,9 @@
 
     auto criterionType = criterion->getCriterionType();
     int deviceAddressId;
-    if (not criterionType->getNumericalValue(devDesc->address().string(), deviceAddressId)) {
-        ALOGW("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->address().c_str());
+    if (not criterionType->getNumericalValue(address.c_str(), deviceAddressId)) {
+        ALOGW("%s: unknown device address reported (%s) for criterion %s", __FUNCTION__,
+              address.c_str(), criterionName.c_str());
         return BAD_TYPE;
     }
     int currentValueMask = criterion->getCriterionState();
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index 5bfad29..62b129a 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,10 +16,6 @@
 
 #pragma once
 
-#include <AudioGain.h>
-#include <AudioPort.h>
-#include <HwModule.h>
-#include <DeviceDescriptor.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <utils/Errors.h>
@@ -48,16 +44,18 @@
     using Criteria = std::map<std::string, ISelectionCriterionInterface *>;
 
 public:
-    ParameterManagerWrapper();
+    ParameterManagerWrapper(bool enableSchemaVerification = false,
+                            const std::string &schemaUri = {});
     ~ParameterManagerWrapper();
 
     /**
      * Starts the platform state service.
      * It starts the parameter framework policy instance.
+     * @param[out] contains human readable error if starts failed
      *
-     * @return NO_ERROR if success, error code otherwise.
+     * @return NO_ERROR if success, error code otherwise, and error is set to human readable string.
      */
-    status_t start();
+    status_t start(std::string &error);
 
     /**
      * The following API wrap policy action to criteria
@@ -118,7 +116,15 @@
      */
     status_t setAvailableOutputDevices(audio_devices_t outputDevices);
 
-    status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+    /**
+     * @brief setDeviceConnectionState propagates a state event on a given device(s)
+     * @param type bit mask of the device whose state has changed
+     * @param address of the device whose state has changed
+     * @param state new state of the given device
+     * @return NO_ERROR if new state corretly propagated to Engine Parameter-Framework, error
+     * code otherwise.
+     */
+    status_t setDeviceConnectionState(audio_devices_t type, const std::string address,
                                       audio_policy_dev_state_t state);
 
     /**
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 7b42c6a..aaf4158 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -1,16 +1,15 @@
 cc_library_shared {
     name: "libaudiopolicyenginedefault",
-    export_include_dirs: ["include"],
     srcs: [
         "src/Engine.cpp",
         "src/EngineInstance.cpp",
     ],
     cflags: [
+        "-fvisibility=hidden",
         "-Wall",
         "-Werror",
         "-Wextra",
     ],
-    local_include_dirs: ["include"],
     header_libs: [
         "libbase_headers",
         "libaudiopolicycommon",
@@ -22,6 +21,7 @@
         "libaudiopolicyengine_config",
     ],
     shared_libs: [
+        "libaudiofoundation",
         "liblog",
         "libcutils",
         "libutils",
diff --git a/services/audiopolicy/enginedefault/config/example/Android.bp b/services/audiopolicy/enginedefault/config/example/Android.bp
new file mode 100644
index 0000000..0bfcaa1
--- /dev/null
+++ b/services/audiopolicy/enginedefault/config/example/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Import this namespace in order to use AOSP Phone with Default Engine configuration example
+
+soong_namespace {
+}
+
+prebuilt_etc {
+    name: "audio_policy_engine_configuration.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_configuration.xml",
+    required: [
+        ":audio_policy_engine_stream_volumes.xml",
+        ":audio_policy_engine_default_stream_volumes.xml",
+        ":audio_policy_engine_product_strategies.xml",
+    ],
+}
+prebuilt_etc {
+    name: "audio_policy_engine_product_strategies.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_product_strategies.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_stream_volumes.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_stream_volumes.xml",
+}
+prebuilt_etc {
+    name: "audio_policy_engine_default_stream_volumes.xml",
+    vendor: true,
+    src: "phone/audio_policy_engine_default_stream_volumes.xml",
+}
diff --git a/services/audiopolicy/enginedefault/config/example/Android.mk b/services/audiopolicy/enginedefault/config/example/Android.mk
deleted file mode 100644
index 0badac8..0000000
--- a/services/audiopolicy/enginedefault/config/example/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# CONFIGURATION TOP FILE
-##################################################################
-
-ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_default)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_configuration.xml
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-
-LOCAL_REQUIRED_MODULES := \
-    audio_policy_engine_product_strategies.xml \
-    audio_policy_engine_stream_volumes.xml \
-    audio_policy_engine_default_stream_volumes.xml
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_product_strategies.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_engine_default_stream_volumes.xml
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := ETC
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := phone/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), phone_default)
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
index 9398743..a7388da 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_product_strategies.xml
@@ -72,6 +72,12 @@
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
             <Attributes></Attributes>
         </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant">
+            <Attributes>
+                <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+                <Usage value="AUDIO_USAGE_ASSISTANT"/>
+            </Attributes>
+        </AttributesGroup>
         <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
             <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
         </AttributesGroup>
@@ -91,20 +97,5 @@
         </AttributesGroup>
     </ProductStrategy>
 
-    <!-- Routing Strategy rerouting may be removed as following media??? -->
-    <ProductStrategy name="STRATEGY_REROUTING">
-        <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-    <!-- Default product strategy has empty attributes -->
-    <ProductStrategy name="STRATEGY_PATCH">
-        <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
-            <Attributes></Attributes>
-        </AttributesGroup>
-    </ProductStrategy>
-
-
 </ProductStrategies>
 
diff --git a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
index 707a184..d5c3896 100644
--- a/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
+++ b/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_stream_volumes.xml
@@ -207,25 +207,15 @@
     </volumeGroup>
 
     <volumeGroup>
-        <name>rerouting</name>
+        <name>assistant</name>
         <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     </volumeGroup>
 
-    <volumeGroup>
-        <name>patch</name>
-        <indexMin>0</indexMin>
-        <indexMax>1</indexMax>
-        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
-        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="FULL_SCALE_VOLUME_CURVE"/>
-    </volumeGroup>
 </volumeGroups>
 
diff --git a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
deleted file mode 100644
index 1e329f0..0000000
--- a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#pragma once
-
-class AudioPolicyManagerInterface;
-
-namespace android
-{
-namespace audio_policy
-{
-
-class Engine;
-
-class EngineInstance
-{
-protected:
-    EngineInstance();
-
-public:
-    virtual ~EngineInstance();
-
-    /**
-     * Get Audio Policy Engine instance.
-     *
-     * @return pointer to Route Manager Instance object.
-     */
-    static EngineInstance *getInstance();
-
-    /**
-     * Interface query.
-     * The first client of an interface of the policy engine will start the singleton.
-     *
-     * @tparam RequestedInterface: interface that the client is wishing to retrieve.
-     *
-     * @return interface handle.
-     */
-    template <class RequestedInterface>
-    RequestedInterface *queryInterface() const;
-
-protected:
-    /**
-     * Get Audio Policy Engine instance.
-     *
-     * @return Audio Policy Engine singleton.
-     */
-    Engine *getEngine() const;
-
-private:
-    /* Copy facilities are put private to disable copy. */
-    EngineInstance(const EngineInstance &object);
-    EngineInstance &operator=(const EngineInstance &object);
-};
-
-/**
- * Limit template instantation to supported type interfaces.
- * Compile time error will claim if invalid interface is requested.
- */
-template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
-
-} // namespace audio_policy
-} // namespace android
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
old mode 100644
new mode 100755
index 04170ac..b14d2bb
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -27,10 +27,11 @@
 #include "Engine.h"
 #include <android-base/macros.h>
 #include <AudioPolicyManagerObserver.h>
-#include <AudioPort.h>
+#include <PolicyAudioPort.h>
 #include <IOProfile.h>
 #include <AudioIODescriptorInterface.h>
 #include <policy.h>
+#include <media/AudioContainers.h>
 #include <utils/String8.h>
 #include <utils/Log.h>
 
@@ -40,19 +41,23 @@
 {
 
 struct legacy_strategy_map { const char *name; legacy_strategy id; };
-static const std::vector<legacy_strategy_map> gLegacyStrategy = {
-    { "STRATEGY_NONE", STRATEGY_NONE },
-    { "STRATEGY_MEDIA", STRATEGY_MEDIA },
-    { "STRATEGY_PHONE", STRATEGY_PHONE },
-    { "STRATEGY_SONIFICATION", STRATEGY_SONIFICATION },
-    { "STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL },
-    { "STRATEGY_DTMF", STRATEGY_DTMF },
-    { "STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE },
-    { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
-    { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
-    { "STRATEGY_REROUTING", STRATEGY_REROUTING },
-    { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
-};
+static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
+    static const std::vector<legacy_strategy_map> legacyStrategy = {
+        { "STRATEGY_NONE", STRATEGY_NONE },
+        { "STRATEGY_MEDIA", STRATEGY_MEDIA },
+        { "STRATEGY_PHONE", STRATEGY_PHONE },
+        { "STRATEGY_SONIFICATION", STRATEGY_SONIFICATION },
+        { "STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL },
+        { "STRATEGY_DTMF", STRATEGY_DTMF },
+        { "STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE },
+        { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
+        { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
+        { "STRATEGY_REROUTING", STRATEGY_REROUTING },
+        { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+        { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
+    };
+    return legacyStrategy;
+}
 
 Engine::Engine()
 {
@@ -61,7 +66,8 @@
              "Policy Engine configuration is partially invalid, skipped %zu elements",
              result.nbSkippedElement);
 
-    for (const auto &strategy : gLegacyStrategy) {
+    auto legacyStrategy = getLegacyStrategy();
+    for (const auto &strategy : legacyStrategy) {
         mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
     }
 }
@@ -136,27 +142,23 @@
     return EngineBase::setForceUse(usage, config);
 }
 
-audio_devices_t Engine::getDeviceForStrategyInt(legacy_strategy strategy,
-                                                DeviceVector availableOutputDevices,
-                                                DeviceVector availableInputDevices,
-                                                const SwAudioOutputCollection &outputs,
-                                                uint32_t outputDeviceTypesToIgnore) const
+DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
+                                              DeviceVector availableOutputDevices,
+                                              DeviceVector availableInputDevices,
+                                              const SwAudioOutputCollection &outputs) const
 {
-    uint32_t device = AUDIO_DEVICE_NONE;
-    uint32_t availableOutputDevicesType =
-            availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
+    DeviceVector devices;
 
     switch (strategy) {
 
     case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
-        device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
         break;
 
     case STRATEGY_SONIFICATION_RESPECTFUL:
         if (isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
         } else {
             bool media_active_locally =
                     outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
@@ -165,17 +167,18 @@
                         toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
                         SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
             // routing is same as media without the "remote" device
-            device = getDeviceForStrategyInt(STRATEGY_MEDIA,
+            availableOutputDevices.remove(availableOutputDevices.getDevicesFromType(
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
+            devices = getDevicesForStrategyInt(STRATEGY_MEDIA,
                     availableOutputDevices,
-                    availableInputDevices, outputs,
-                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
+                    availableInputDevices, outputs);
             // if no media is playing on the device, check for mandatory use of "safe" speaker
             // when media would have played on speaker, and the safe speaker path is available
-            if (!media_active_locally
-                    && (device & AUDIO_DEVICE_OUT_SPEAKER)
-                    && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-                device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-                device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+            if (!media_active_locally) {
+                devices.replaceDevicesByType(
+                        AUDIO_DEVICE_OUT_SPEAKER,
+                        availableOutputDevices.getDevicesFromType(
+                                AUDIO_DEVICE_OUT_SPEAKER_SAFE));
             }
         }
         break;
@@ -183,9 +186,8 @@
     case STRATEGY_DTMF:
         if (!isInCall()) {
             // when off call, DTMF strategy follows the same rules as MEDIA strategy
-            device = getDeviceForStrategyInt(
-                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         // when in call, DTMF and PHONE strategies follow the same rules
@@ -197,24 +199,28 @@
         //   - 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 = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+            audio_devices_t txDevice = getDeviceForInputSource(
+                    AUDIO_SOURCE_VOICE_COMMUNICATION)->type();
             sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
-            audio_devices_t availPrimaryInputDevices =
-                 availableInputDevices.getDeviceTypesFromHwModule(primaryOutput->getModuleHandle());
+            LOG_ALWAYS_FATAL_IF(primaryOutput == nullptr, "Primary output not found");
+            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
-            audio_devices_t availPrimaryOutputDevices =
-                (primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) &
-                availableOutputDevices.types();
+            DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
+                    primaryOutput->supportedDevices().types());
+            availPrimaryOutputDevices.add(
+                    availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
 
-            if (((availableInputDevices.types() &
-                    AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
-                    (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
-                         (primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
-                availableOutputDevicesType = 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;
             }
         }
         // for phone strategy, we first consider the forced use and then the available devices by
@@ -222,49 +228,40 @@
         switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
         case AUDIO_POLICY_FORCE_BT_SCO:
             if (!isInCall() || strategy != STRATEGY_DTMF) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-                if (device) break;
+                devices = availableOutputDevices.getDevicesFromType(
+                        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
-            if (device) break;
+            devices = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
+            if (!devices.isEmpty()) break;
             // if SCO device is requested but no SCO device is available, fall back to default case
             FALLTHROUGH_INTENDED;
 
         default:    // FORCE_NONE
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
-            if (device) break;
+            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
+            if (!devices.isEmpty()) break;
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
             if (!isInCall() &&
                     (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                      outputs.isA2dpSupported()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
-            if (device) break;
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-            if (device) break;
+            devices = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                    AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
+                    AUDIO_DEVICE_OUT_USB_DEVICE});
+            if (!devices.isEmpty()) break;
             if (!isInCall()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+                        AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
+            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_EARPIECE);
             break;
 
         case AUDIO_POLICY_FORCE_SPEAKER:
@@ -273,22 +270,18 @@
             if (!isInCall() &&
                     (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                      outputs.isA2dpSupported()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-                if (device) break;
+                devices = availableOutputDevices.getDevicesFromType(
+                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+                if (!devices.isEmpty()) break;
             }
             if (!isInCall()) {
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
-                if (device) break;
-                device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
-                if (device) break;
+                devices = availableOutputDevices.getFirstDevicesFromTypes({
+                        AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
+                        AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_AUX_DIGITAL,
+                        AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET});
+                if (!devices.isEmpty()) break;
             }
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
             break;
         }
     break;
@@ -298,9 +291,8 @@
         // If incall, just select the STRATEGY_PHONE device
         if (isInCall() ||
                 outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         FALLTHROUGH_INTENDED;
@@ -313,41 +305,37 @@
 
         if ((strategy == STRATEGY_SONIFICATION) ||
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
-            device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
         }
 
         // if SCO headset is connected and we are told to use it, play ringtone over
         // speaker and BT SCO
-        if ((availableOutputDevicesType & AUDIO_DEVICE_OUT_ALL_SCO) != 0) {
-            uint32_t device2 = AUDIO_DEVICE_NONE;
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-            }
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
-            }
+        if (!availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllScoSet()).isEmpty()) {
+            DeviceVector devices2;
+            devices2 = availableOutputDevices.getFirstDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
             // Use ONLY Bluetooth SCO output when ringing in vibration mode
             if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
                     && (strategy == STRATEGY_ENFORCED_AUDIBLE))) {
                 if (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
                         == AUDIO_POLICY_FORCE_BT_SCO) {
-                    if (device2 != AUDIO_DEVICE_NONE) {
-                        device = device2;
+                    if (!devices2.isEmpty()) {
+                        devices = devices2;
                         break;
                     }
                 }
             }
             // Use both Bluetooth SCO and phone default output when ringing in normal mode
             if (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) {
-                if ((strategy == STRATEGY_SONIFICATION) &&
-                        (device & AUDIO_DEVICE_OUT_SPEAKER) &&
-                        (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-                    device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-                    device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+                if (strategy == STRATEGY_SONIFICATION) {
+                    devices.replaceDevicesByType(
+                            AUDIO_DEVICE_OUT_SPEAKER,
+                            availableOutputDevices.getDevicesFromType(
+                                    AUDIO_DEVICE_OUT_SPEAKER_SAFE));
                 }
-                if (device2 != AUDIO_DEVICE_NONE) {
-                    device |= device2;
+                if (!devices2.isEmpty()) {
+                    devices.add(devices2);
                     break;
                 }
             }
@@ -361,25 +349,20 @@
             // compressed format as they would likely not be mixed and dropped.
             for (size_t i = 0; i < outputs.size(); i++) {
                 sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
-                audio_devices_t devices = desc->devices().types() &
-                    (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
-                if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
-                        devices != AUDIO_DEVICE_NONE) {
-                    availableOutputDevicesType = availableOutputDevices.types() & ~devices;
+                if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
+                    availableOutputDevices.remove(desc->devices().getDevicesFromTypes({
+                            AUDIO_DEVICE_OUT_HDMI, AUDIO_DEVICE_OUT_SPDIF,
+                            AUDIO_DEVICE_OUT_HDMI_ARC}));
                 }
             }
-            availableOutputDevices =
-                    availableOutputDevices.getDevicesFromTypeMask(availableOutputDevicesType);
             if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
                     outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
-                return getDeviceForStrategyInt(
-                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+                return getDevicesForStrategyInt(
+                    STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs);
             }
             if (isInCall()) {
-                return getDeviceForStrategyInt(
-                        STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                        outputDeviceTypesToIgnore);
+                return getDevicesForStrategyInt(
+                        STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             }
         }
         // For other cases, STRATEGY_ACCESSIBILITY behaves like STRATEGY_MEDIA
@@ -388,128 +371,118 @@
     // FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
     case STRATEGY_REROUTING:
     case STRATEGY_MEDIA: {
-        uint32_t device2 = AUDIO_DEVICE_NONE;
+        DeviceVector devices2;
         if (strategy != STRATEGY_SONIFICATION) {
             // no sonification on remote submix (e.g. WFD)
-            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                                                 String8("0"), AUDIO_FORMAT_DEFAULT) != 0) {
-                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+            sp<DeviceDescriptor> remoteSubmix;
+            if ((remoteSubmix = availableOutputDevices.getDevice(
+                    AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
+                    AUDIO_FORMAT_DEFAULT)) != nullptr) {
+                devices2.add(remoteSubmix);
             }
         }
         if (isInCall() && (strategy == STRATEGY_MEDIA)) {
-            device = getDeviceForStrategyInt(
-                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
-                    outputDeviceTypesToIgnore);
+            devices = getDevicesForStrategyInt(
+                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
             break;
         }
         // FIXME: Find a better solution to prevent routing to BT hearing aid(b/122931261).
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
+            devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
         }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
-                (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                 outputs.isA2dpSupported()) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-            }
-            if (device2 == AUDIO_DEVICE_NONE) {
-                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-            }
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
             (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+            devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+        if (devices2.isEmpty() && (getLastRemovableMediaDevices().size() > 0)) {
+            if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+                    outputs.isA2dpSupported()) {
+                // Get the last connected device of wired and bluetooth a2dp
+                devices2 = availableOutputDevices.getFirstDevicesFromTypes(
+                        getLastRemovableMediaDevices());
+            } else {
+                // Get the last connected device of wired except bluetooth a2dp
+                devices2 = availableOutputDevices.getFirstDevicesFromTypes(
+                        getLastRemovableMediaDevices(GROUP_WIRED));
+            }
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
-        }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
-        }
-        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
+        if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
             // no sonification on aux digital (e.g. HDMI)
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+            devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_AUX_DIGITAL);
         }
-        if ((device2 == AUDIO_DEVICE_NONE) &&
+        if ((devices2.isEmpty()) &&
                 (getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+            devices2 = availableOutputDevices.getDevicesFromType(
+                    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
         }
-        if (device2 == AUDIO_DEVICE_NONE) {
-            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+        if (devices2.isEmpty()) {
+            devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
         }
-        int device3 = AUDIO_DEVICE_NONE;
+        DeviceVector devices3;
         if (strategy == STRATEGY_MEDIA) {
             // ARC, SPDIF and AUX_LINE can co-exist with others.
-            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
-            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
-            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
+            devices3 = availableOutputDevices.getDevicesFromTypes({
+                    AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_SPDIF, AUDIO_DEVICE_OUT_AUX_LINE});
         }
 
-        device2 |= device3;
+        devices2.add(devices3);
         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
-        device |= device2;
+        devices.add(devices2);
 
         // If hdmi system audio mode is on, remove speaker out of output list.
         if ((strategy == STRATEGY_MEDIA) &&
             (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
-            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+            devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
         }
 
         // for STRATEGY_SONIFICATION:
         // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
-        if ((strategy == STRATEGY_SONIFICATION) &&
-                (device & AUDIO_DEVICE_OUT_SPEAKER) &&
-                (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
-            device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
-            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+        if (strategy == STRATEGY_SONIFICATION) {
+            devices.replaceDevicesByType(
+                    AUDIO_DEVICE_OUT_SPEAKER,
+                    availableOutputDevices.getDevicesFromType(
+                            AUDIO_DEVICE_OUT_SPEAKER_SAFE));
         }
         } break;
 
+    case STRATEGY_CALL_ASSISTANT:
+        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_TELEPHONY_TX);
+        break;
+
     default:
-        ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
+        ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
         break;
     }
 
-    if (device == AUDIO_DEVICE_NONE) {
-        ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
-        device = getApmObserver()->getDefaultOutputDevice()->type();
-        ALOGE_IF(device == AUDIO_DEVICE_NONE,
-                 "getDeviceForStrategy() no default device defined");
+    if (devices.isEmpty()) {
+        ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
+        sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
+        if (defaultOutputDevice != nullptr) {
+            devices.add(defaultOutputDevice);
+        }
+        ALOGE_IF(devices.isEmpty(),
+                 "getDevicesForStrategy() no default device defined");
     }
-    ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
-    return device;
+
+    ALOGVV("getDevices ForStrategy() strategy %d, device %s",
+           strategy, dumpDeviceTypes(devices.types()).c_str());
+    return devices;
 }
 
 
-audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
+sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
 {
     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
     const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
-    audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+    DeviceVector availableDevices = availableInputDevices;
     sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
-    audio_devices_t availablePrimaryDeviceTypes = availableInputDevices.getDeviceTypesFromHwModule(
-        primaryOutput->getModuleHandle()) & ~AUDIO_DEVICE_BIT_IN;
-    uint32_t device = AUDIO_DEVICE_NONE;
+    DeviceVector availablePrimaryDevices = primaryOutput == nullptr ? DeviceVector()
+            : availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
+    sp<DeviceDescriptor> device;
 
     // when a call is active, force device selection to match source VOICE_COMMUNICATION
     // for most other input sources to avoid rerouting call TX audio
@@ -532,57 +505,48 @@
     switch (inputSource) {
     case AUDIO_SOURCE_DEFAULT:
     case AUDIO_SOURCE_MIC:
-    if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
-    } else if ((getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) &&
-        (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
-        device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-        device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-        device = AUDIO_DEVICE_IN_USB_HEADSET;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-        device = AUDIO_DEVICE_IN_USB_DEVICE;
-    } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-        device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-    }
-    break;
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
+        if (device != nullptr) break;
+        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) break;
+        }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
+        break;
 
     case AUDIO_SOURCE_VOICE_COMMUNICATION:
         // Allow only use of devices on primary input if in call and HAL does not support routing
         // to voice call path.
         if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
-                (availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
-            availableDeviceTypes = availablePrimaryDeviceTypes;
+                (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
+                        String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
+            LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
+            availableDevices = availablePrimaryDevices;
         }
 
         switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
         case AUDIO_POLICY_FORCE_BT_SCO:
             // if SCO device is requested but no SCO device is available, fall back to default case
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-                device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) {
                 break;
             }
             FALLTHROUGH_INTENDED;
 
         default:    // FORCE_NONE
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-                device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-                device = AUDIO_DEVICE_IN_USB_HEADSET;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-                device = AUDIO_DEVICE_IN_USB_DEVICE;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
+            device = availableDevices.getFirstExistingDevice({
+                    AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
             break;
 
         case AUDIO_POLICY_FORCE_SPEAKER:
-            if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-                device = AUDIO_DEVICE_IN_BACK_MIC;
-            } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-            }
+            device = availableDevices.getFirstExistingDevice({
+                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
             break;
         }
         break;
@@ -591,84 +555,70 @@
     case AUDIO_SOURCE_UNPROCESSED:
     case AUDIO_SOURCE_HOTWORD:
         if (inputSource == AUDIO_SOURCE_HOTWORD) {
-            availableDeviceTypes = availablePrimaryDeviceTypes;
+            // 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 (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO &&
-                availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
-            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-            device = AUDIO_DEVICE_IN_USB_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
+            device = availableDevices.getDevice(
+                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+            if (device != nullptr) break;
         }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
     case AUDIO_SOURCE_CAMCORDER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
-            device = AUDIO_DEVICE_IN_BACK_MIC;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            // This is specifically for a device without built-in mic
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        }
+        // For a device without built-in mic, adding usb device
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
+                AUDIO_DEVICE_IN_USB_DEVICE});
         break;
     case AUDIO_SOURCE_VOICE_DOWNLINK:
     case AUDIO_SOURCE_VOICE_CALL:
     case AUDIO_SOURCE_VOICE_UPLINK:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
-            device = AUDIO_DEVICE_IN_VOICE_CALL;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_VOICE_PERFORMANCE:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
-            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
-            device = AUDIO_DEVICE_IN_USB_HEADSET;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
-            device = AUDIO_DEVICE_IN_USB_DEVICE;
-        } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
-            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
-        }
+        device = availableDevices.getFirstExistingDevice({
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
         break;
     case AUDIO_SOURCE_REMOTE_SUBMIX:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
-            device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_FM_TUNER:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
-            device = AUDIO_DEVICE_IN_FM_TUNER;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     case AUDIO_SOURCE_ECHO_REFERENCE:
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) {
-            device = AUDIO_DEVICE_IN_ECHO_REFERENCE;
-        }
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
         break;
     default:
         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
         break;
     }
-    if (device == AUDIO_DEVICE_NONE) {
+    if (device == nullptr) {
         ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
-        if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
-            device = AUDIO_DEVICE_IN_STUB;
-        }
-        ALOGE_IF(device == AUDIO_DEVICE_NONE,
+        device = availableDevices.getDevice(
+                AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
+        ALOGE_IF(device == nullptr,
                  "getDeviceForInputSource() no default device defined");
     }
-    ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
+    ALOGV_IF(device != nullptr,
+             "getDeviceForInputSource()input source %d, device %08x",
+             inputSource, device->type());
     return device;
 }
 
 void Engine::updateDeviceSelectionCache()
 {
     for (const auto &iter : getProductStrategies()) {
-        const auto &strategy = iter.second;
+        const auto& strategy = iter.second;
         auto devices = getDevicesForProductStrategy(strategy->getId());
         mDevicesForStrategies[strategy->getId()] = devices;
         strategy->setDeviceTypes(devices.types());
@@ -676,19 +626,34 @@
     }
 }
 
-DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const
-{
+DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
-    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
-    const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
 
+    // check if this strategy has a preferred device that is available,
+    // if yes, give priority to it
+    AudioDeviceTypeAddr preferredStrategyDevice;
+    const status_t status = getPreferredDeviceForStrategy(strategy, preferredStrategyDevice);
+    if (status == NO_ERROR) {
+        // there is a preferred device, is it available?
+        sp<DeviceDescriptor> preferredAvailableDevDescr = availableOutputDevices.getDevice(
+                preferredStrategyDevice.mType,
+                String8(preferredStrategyDevice.mAddress.c_str()),
+                AUDIO_FORMAT_DEFAULT);
+        if (preferredAvailableDevDescr != nullptr) {
+            ALOGVV("%s using pref device 0x%08x/%s for strategy %u",
+                   __func__, preferredStrategyDevice.mType,
+                   preferredStrategyDevice.mAddress.c_str(), strategy);
+            return DeviceVector(preferredAvailableDevDescr);
+        }
+    }
+
+    DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
+    const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
     auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
-                mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
-    audio_devices_t devices = getDeviceForStrategyInt(legacyStrategy,
-                                                      availableOutputDevices,
-                                                      availableInputDevices, outputs,
-                                                      (uint32_t)AUDIO_DEVICE_NONE);
-    return availableOutputDevices.getDevicesFromTypeMask(devices);
+                          mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
+    return getDevicesForStrategyInt(legacyStrategy,
+                                    availableOutputDevices,
+                                    availableInputDevices, outputs);
 }
 
 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
@@ -747,27 +712,25 @@
     if (device != nullptr) {
         return device;
     }
-    audio_devices_t deviceType = getDeviceForInputSource(attr.source);
 
-    if (audio_is_remote_submix_device(deviceType)) {
-        address = "0";
-        std::size_t pos;
-        std::string tags { attr.tags };
-        if ((pos = tags.find("addr=")) != std::string::npos) {
-            address = tags.substr(pos + std::strlen("addr="));
-        }
+    device = getDeviceForInputSource(attr.source);
+    if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
+        // Return immediately if the device is null or it is not a remote submix device.
+        return device;
     }
-    return availableInputDevices.getDevice(deviceType,
+
+    // For remote submix device, try to find the device by address.
+    address = "0";
+    std::size_t pos;
+    std::string tags { attr.tags };
+    if ((pos = tags.find("addr=")) != std::string::npos) {
+        address = tags.substr(pos + std::strlen("addr="));
+    }
+    return availableInputDevices.getDevice(device->type(),
                                            String8(address.c_str()),
                                            AUDIO_FORMAT_DEFAULT);
 }
 
-template <>
-AudioPolicyManagerInterface *Engine::queryInterface()
-{
-    return this;
-}
-
 } // namespace audio_policy
 } // namespace android
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index d5dfacc..bb9e2df 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -17,8 +17,7 @@
 #pragma once
 
 #include "EngineBase.h"
-#include "AudioPolicyManagerInterface.h"
-#include <AudioGain.h>
+#include "EngineInterface.h"
 #include <policy.h>
 
 namespace android
@@ -40,6 +39,7 @@
     STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
     STRATEGY_ACCESSIBILITY,
     STRATEGY_REROUTING,
+    STRATEGY_CALL_ASSISTANT,
 };
 
 class Engine : public EngineBase
@@ -48,12 +48,9 @@
     Engine();
     virtual ~Engine() = default;
 
-    template <class RequestedInterface>
-    RequestedInterface *queryInterface();
-
 private:
     ///
-    /// from EngineBase, so from AudioPolicyManagerInterface
+    /// from EngineBase, so from EngineInterface
     ///
     status_t setForceUse(audio_policy_force_use_t usage,
                          audio_policy_forced_cfg_t config) override;
@@ -77,15 +74,14 @@
 
     status_t setDefaultDevice(audio_devices_t device);
 
-    audio_devices_t getDeviceForStrategyInt(legacy_strategy strategy,
-                                            DeviceVector availableOutputDevices,
-                                            DeviceVector availableInputDevices,
-                                            const SwAudioOutputCollection &outputs,
-                                            uint32_t outputDeviceTypesToIgnore) const;
+    DeviceVector getDevicesForStrategyInt(legacy_strategy strategy,
+                                          DeviceVector availableOutputDevices,
+                                          DeviceVector availableInputDevices,
+                                          const SwAudioOutputCollection &outputs) const;
 
     DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
 
-    audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
+    sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
 
     DeviceStrategyMap mDevicesForStrategies;
 
diff --git a/services/audiopolicy/enginedefault/src/EngineInstance.cpp b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
index 17e9832..eeb3758 100644
--- a/services/audiopolicy/enginedefault/src/EngineInstance.cpp
+++ b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
@@ -14,41 +14,21 @@
  * limitations under the License.
  */
 
-#include <AudioPolicyManagerInterface.h>
-#include "AudioPolicyEngineInstance.h"
+#include <EngineInterface.h>
 #include "Engine.h"
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
 
-EngineInstance::EngineInstance()
+extern "C" EngineInterface* createEngineInstance()
 {
+    return new (std::nothrow) Engine();
 }
 
-EngineInstance *EngineInstance::getInstance()
+extern "C" void destroyEngineInstance(EngineInterface *engine)
 {
-    static EngineInstance instance;
-    return &instance;
-}
-
-EngineInstance::~EngineInstance()
-{
-}
-
-Engine *EngineInstance::getEngine() const
-{
-    static Engine engine;
-    return &engine;
-}
-
-template <>
-AudioPolicyManagerInterface *EngineInstance::queryInterface() const
-{
-    return getEngine()->queryInterface<AudioPolicyManagerInterface>();
+    delete static_cast<Engine*>(engine);
 }
 
 } // namespace audio_policy
 } // namespace android
-
diff --git a/services/audiopolicy/manager/Android.mk b/services/audiopolicy/manager/Android.mk
index d6ca2f2..cae6cfa 100644
--- a/services/audiopolicy/manager/Android.mk
+++ b/services/audiopolicy/manager/Android.mk
@@ -23,8 +23,6 @@
 
 LOCAL_CFLAGS := -Wall -Werror
 
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
 LOCAL_MODULE:= libaudiopolicymanager
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/manager/AudioPolicyFactory.cpp b/services/audiopolicy/manager/AudioPolicyFactory.cpp
index 7aff6a9..476a1ec 100644
--- a/services/audiopolicy/manager/AudioPolicyFactory.cpp
+++ b/services/audiopolicy/manager/AudioPolicyFactory.cpp
@@ -21,7 +21,13 @@
 extern "C" AudioPolicyInterface* createAudioPolicyManager(
         AudioPolicyClientInterface *clientInterface)
 {
-    return new AudioPolicyManager(clientInterface);
+    AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
+    status_t status = apm->initialize();
+    if (status != NO_ERROR) {
+        delete apm;
+        apm = nullptr;
+    }
+    return apm;
 }
 
 extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
new file mode 100644
index 0000000..577b42f
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -0,0 +1,43 @@
+cc_library_shared {
+    name: "libaudiopolicymanagerdefault",
+
+    srcs: [
+        "AudioPolicyManager.cpp",
+        "EngineLibrary.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    shared_libs: [
+        "libaudiofoundation",
+        "libcutils",
+        "libdl",
+        "libutils",
+        "liblog",
+        "libaudiopolicy",
+        "libmedia_helper",
+        "libmediametrics",
+        "libbinder",
+        "libhidlbase",
+        "libxml2",
+        // The default audio policy engine is always present in the system image.
+        // libaudiopolicyengineconfigurable can be built in addition by specifying
+        // a dependency on it in the device makefile. There will be no build time
+        // conflict with libaudiopolicyenginedefault.
+        "libaudiopolicyenginedefault",
+    ],
+
+    header_libs: [
+        "libaudiopolicycommon",
+        "libaudiopolicyengine_interface_headers",
+        "libaudiopolicymanager_interface_headers",
+    ],
+
+    static_libs: ["libaudiopolicycomponents"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+}
diff --git a/services/audiopolicy/managerdefault/Android.mk b/services/audiopolicy/managerdefault/Android.mk
deleted file mode 100644
index 684fc9f..0000000
--- a/services/audiopolicy/managerdefault/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= AudioPolicyManager.cpp
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libutils \
-    liblog \
-    libaudiopolicy \
-    libsoundtrigger
-
-ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
-
-ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-$(error Configurable policy does not support legacy conf file)
-endif #ifneq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-
-LOCAL_SHARED_LIBRARIES += libaudiopolicyengineconfigurable
-
-else
-
-LOCAL_SHARED_LIBRARIES += libaudiopolicyenginedefault
-
-endif # ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
-
-LOCAL_C_INCLUDES += \
-    $(call include-path-for, audio-utils)
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudiopolicycommon \
-    libaudiopolicyengine_interface_headers \
-    libaudiopolicymanager_interface_headers
-
-LOCAL_STATIC_LIBRARIES := \
-    libaudiopolicycomponents
-
-LOCAL_SHARED_LIBRARIES += libmedia_helper
-LOCAL_SHARED_LIBRARIES += libmediametrics
-
-LOCAL_SHARED_LIBRARIES += libbinder libhidlbase libxml2
-
-ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
-endif #ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
-
-LOCAL_CFLAGS += -Wall -Werror
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE:= libaudiopolicymanagerdefault
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a984b10..c5c13e9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -42,15 +42,12 @@
 #include <set>
 #include <unordered_set>
 #include <vector>
-#include <AudioPolicyManagerInterface.h>
-#include <AudioPolicyEngineInstance.h>
 #include <cutils/properties.h>
 #include <utils/Log.h>
 #include <media/AudioParameter.h>
 #include <private/android_filesystem_config.h>
-#include <soundtrigger/SoundTrigger.h>
 #include <system/audio.h>
-#include <audio_policy_conf.h>
+#include <system/audio_config.h>
 #include "AudioPolicyManager.h"
 #include <Serializer.h>
 #include "TypeConverter.h"
@@ -76,6 +73,26 @@
         AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
         AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
 
+template <typename T>
+bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
+{
+    if (left.size() != right.size()) {
+        return false;
+    }
+    for (size_t index = 0; index < right.size(); index++) {
+        if (left[index] != right[index]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+template <typename T>
+bool operator!= (const SortedVector<T> &left, const SortedVector<T> &right)
+{
+    return !(left == right);
+}
+
 // ----------------------------------------------------------------------------
 // AudioPolicyInterface implementation
 // ----------------------------------------------------------------------------
@@ -95,9 +112,9 @@
 void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
                                                         audio_policy_dev_state_t state)
 {
-    AudioParameter param(device->address());
+    AudioParameter param(String8(device->address().c_str()));
     const String8 key(state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE ?
-                AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect);
+                AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect);
     param.addInt(key, device->type());
     mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 }
@@ -117,12 +134,14 @@
     sp<DeviceDescriptor> device =
             mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
                                            state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
-    if (device == 0) {
-        return INVALID_OPERATION;
-    }
+    return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
+}
 
+status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+                                                         audio_policy_dev_state_t state)
+{
     // handle output devices
-    if (audio_is_output_device(deviceType)) {
+    if (audio_is_output_device(device->type())) {
         SortedVector <audio_io_handle_t> outputs;
 
         ssize_t index = mAvailableOutputDevices.indexOf(device);
@@ -139,7 +158,7 @@
                 return INVALID_OPERATION;
             }
             ALOGV("%s() connecting device %s format %x",
-                    __func__, device->toString().c_str(), encodedFormat);
+                    __func__, device->toString().c_str(), device->getEncodedFormat());
 
             // register new device as available
             if (mAvailableOutputDevices.add(device) < 0) {
@@ -159,6 +178,9 @@
                 return INVALID_OPERATION;
             }
 
+            // Populate encapsulation information when a output device is connected.
+            device->setEncapsulationInfoFromHal(mpClientInterface);
+
             // outputs should never be empty here
             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
                     "checkOutputsForDevice() returned no outputs but status OK");
@@ -201,16 +223,13 @@
         // output device used by a dynamic policy of type recorder as no
         // playback use case is affected.
         bool doCheckForDeviceAndOutputChanges = true;
-        if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-                && strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
+        if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX && device->address() != "0") {
             for (audio_io_handle_t output : outputs) {
                 sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
                 sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
                 if (policyMix != nullptr
                         && policyMix->mMixType == MIX_TYPE_RECORDERS
-                        && strncmp(device_address,
-                                   policyMix->mDeviceAddress.string(),
-                                   AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+                        && device->address() == policyMix->mDeviceAddress.string()) {
                     doCheckForDeviceAndOutputChanges = false;
                     break;
                 }
@@ -256,7 +275,7 @@
                 // a valid device selection on those outputs.
                 bool force = (msdOutDevices.isEmpty() || msdOutDevices != desc->devices())
                         && !desc->isDuplicated()
-                        && (!device_distinguishes_on_address(deviceType)
+                        && (!device_distinguishes_on_address(device->type())
                                 // always force when disconnecting (a non-duplicated device)
                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
                 setOutputDevices(desc, newDevices, force, 0);
@@ -272,7 +291,7 @@
     }  // end if is output device
 
     // handle input devices
-    if (audio_is_input_device(deviceType)) {
+    if (audio_is_input_device(device->type())) {
         ssize_t index = mAvailableInputDevices.indexOf(device);
         switch (state)
         {
@@ -408,7 +427,7 @@
     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
 
     // Check if the device is currently connected
-    DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromTypeMask(device);
+    DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromType(device);
     if (deviceList.empty()) {
         // Nothing to do: device is not connected
         return NO_ERROR;
@@ -422,8 +441,8 @@
     // Case 1: A2DP active device switches from primary to primary
     // module
     // Case 2: A2DP device config changes on primary module.
-    if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
-        sp<HwModule> module = mHwModules.getModuleForDeviceTypes(device, encodedFormat);
+    if (audio_is_a2dp_out_device(device)) {
+        sp<HwModule> module = mHwModules.getModuleForDeviceType(device, encodedFormat);
         audio_module_handle_t primaryHandle = mPrimaryOutput->getModuleHandle();
         if (availablePrimaryOutputDevices().contains(devDesc) &&
            (module != 0 && module->getHandle() == primaryHandle)) {
@@ -475,8 +494,12 @@
     std::unordered_set<audio_format_t> formatSet;
     sp<HwModule> primaryModule =
             mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
-    DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
-            AUDIO_DEVICE_OUT_ALL_A2DP);
+    if (primaryModule == nullptr) {
+        ALOGE("%s() unable to get primary module", __func__);
+        return NO_INIT;
+    }
+    DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypes(
+            getAudioDeviceOutAllA2dpSet());
     for (const auto& device : declaredDevices) {
         formatSet.insert(device->encodedFormats().begin(), device->encodedFormats().end());
     }
@@ -490,7 +513,8 @@
     bool createRxPatch = false;
     uint32_t muteWaitMs = 0;
 
-    if(!hasPrimaryOutput() || mPrimaryOutput->devices().types() == AUDIO_DEVICE_OUT_STUB) {
+    if(!hasPrimaryOutput() ||
+            mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
         return muteWaitMs;
     }
     ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device");
@@ -504,19 +528,19 @@
 
     // release existing RX patch if any
     if (mCallRxPatch != 0) {
-        mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0);
+        releaseAudioPatchInternal(mCallRxPatch->getHandle());
         mCallRxPatch.clear();
     }
     // release TX patch if any
     if (mCallTxPatch != 0) {
-        mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0);
+        releaseAudioPatchInternal(mCallTxPatch->getHandle());
         mCallTxPatch.clear();
     }
 
     auto telephonyRxModule =
-        mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
+        mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
     auto telephonyTxModule =
-        mHwModules.getModuleForDeviceTypes(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
+        mHwModules.getModuleForDeviceType(AUDIO_DEVICE_OUT_TELEPHONY_TX, AUDIO_FORMAT_DEFAULT);
     // retrieve Rx Source and Tx Sink device descriptors
     sp<DeviceDescriptor> rxSourceDevice =
         mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
@@ -535,11 +559,9 @@
             ALOGE("updateCallRouting() no telephony Tx and/or RX device");
             return muteWaitMs;
         }
-        // do not create a patch (aka Sw Bridging) if Primary HW module has declared supporting a
-        // route between telephony RX to Sink device and Source device to telephony TX
-        const auto &primaryModule = telephonyRxModule;
-        createRxPatch = !primaryModule->supportsPatch(rxSourceDevice, rxDevices.itemAt(0));
-        createTxPatch = !primaryModule->supportsPatch(txSourceDevice, txSinkDevice);
+        // createAudioPatchInternal now supports both HW / SW bridging
+        createRxPatch = true;
+        createTxPatch = true;
     } else {
         // If the RX device is on the primary HW module, then use legacy routing method for
         // voice calls via setOutputDevice() on primary output.
@@ -563,6 +585,15 @@
         // assuming the device uses audio HAL V5.0 and above
     }
     if (createTxPatch) { // create TX path audio patch
+        // terminate active capture if on the same HW module as the call TX source device
+        // FIXME: would be better to refine to only inputs whose profile connects to the
+        // call TX device but this information is not in the audio patch and logic here must be
+        // symmetric to the one in startInput()
+        for (const auto& activeDesc : mInputs.getActiveInputs()) {
+            if (activeDesc->hasSameHwModuleAs(txSourceDevice)) {
+                closeActiveClients(activeDesc);
+            }
+        }
         mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs);
     }
 
@@ -576,6 +607,8 @@
     if (device == nullptr) {
         return nullptr;
     }
+
+    // @TODO: still ignoring the address, or not dealing platform with multiple telephony devices
     if (isRx) {
         patchBuilder.addSink(device).
                 addSource(mAvailableInputDevices.getDevice(
@@ -586,59 +619,15 @@
                     AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT));
     }
 
-    // @TODO: still ignoring the address, or not dealing platform with mutliple telephonydevices
-    const sp<DeviceDescriptor> outputDevice = isRx ?
-                device : mAvailableOutputDevices.getDevice(
-                    AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT);
-    SortedVector<audio_io_handle_t> outputs =
-            getOutputsForDevices(DeviceVector(outputDevice), mOutputs);
-    const audio_io_handle_t output = selectOutput(outputs);
-    // request to reuse existing output stream if one is already opened to reach the target device
-    if (output != AUDIO_IO_HANDLE_NONE) {
-        sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-        ALOG_ASSERT(!outputDesc->isDuplicated(), "%s() %s device output %d is duplicated", __func__,
-                    outputDevice->toString().c_str(), output);
-        patchBuilder.addSource(outputDesc, { .stream = AUDIO_STREAM_PATCH });
+    audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
+    status_t status =
+            createAudioPatchInternal(patchBuilder.patch(), &patchHandle, mUidCached, delayMs);
+    ssize_t index = mAudioPatches.indexOfKey(patchHandle);
+    if (status != NO_ERROR || index < 0) {
+        ALOGW("%s() error %d creating %s audio patch", __func__, status, isRx ? "RX" : "TX");
+        return nullptr;
     }
-
-    if (!isRx) {
-        // terminate active capture if on the same HW module as the call TX source device
-        // FIXME: would be better to refine to only inputs whose profile connects to the
-        // call TX device but this information is not in the audio patch and logic here must be
-        // symmetric to the one in startInput()
-        for (const auto& activeDesc : mInputs.getActiveInputs()) {
-            if (activeDesc->hasSameHwModuleAs(device)) {
-                closeActiveClients(activeDesc);
-            }
-        }
-    }
-
-    audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-    status_t status = mpClientInterface->createAudioPatch(
-            patchBuilder.patch(), &afPatchHandle, delayMs);
-    ALOGW_IF(status != NO_ERROR,
-            "%s() error %d creating %s audio patch", __func__, status, isRx ? "RX" : "TX");
-    sp<AudioPatch> audioPatch;
-    if (status == NO_ERROR) {
-        audioPatch = new AudioPatch(patchBuilder.patch(), mUidCached);
-        audioPatch->mAfPatchHandle = afPatchHandle;
-        audioPatch->mUid = mUidCached;
-    }
-    return audioPatch;
-}
-
-sp<DeviceDescriptor> AudioPolicyManager::findDevice(
-        const DeviceVector& devices, audio_devices_t device) const {
-    DeviceVector deviceList = devices.getDevicesFromTypeMask(device);
-    ALOG_ASSERT(!deviceList.isEmpty(),
-            "%s() selected device type %#x is not in devices list", __func__, device);
-    return deviceList.itemAt(0);
-}
-
-audio_devices_t AudioPolicyManager::getModuleDeviceTypes(
-        const DeviceVector& devices, const char *moduleId) const {
-    sp<HwModule> mod = mHwModules.getModuleFromName(moduleId);
-    return mod != 0 ? devices.getDeviceTypesFromHwModule(mod->getHandle()) : AUDIO_DEVICE_NONE;
+    return mAudioPatches.valueAt(index);
 }
 
 bool AudioPolicyManager::isDeviceOfModule(
@@ -674,8 +663,8 @@
      * Switching to or from incall state or switching between telephony and VoIP lead to force
      * routing command.
      */
-    bool force = ((is_state_in_call(oldState) != is_state_in_call(state))
-                  || (is_state_in_call(state) && (state != oldState)));
+    bool force = ((isStateInCall(oldState) != isStateInCall(state))
+                  || (isStateInCall(state) && (state != oldState)));
 
     // check for device and output changes triggered by new phone state
     checkForDeviceAndOutputChanges();
@@ -721,11 +710,11 @@
             updateCallRouting(rxDevices, delayMs);
         } else if (oldState == AUDIO_MODE_IN_CALL) {
             if (mCallRxPatch != 0) {
-                mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0);
+                releaseAudioPatchInternal(mCallRxPatch->getHandle());
                 mCallRxPatch.clear();
             }
             if (mCallTxPatch != 0) {
-                mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0);
+                releaseAudioPatchInternal(mCallTxPatch->getHandle());
                 mCallTxPatch.clear();
             }
             setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
@@ -786,27 +775,11 @@
     //FIXME: workaround for truncated touch sounds
     // to be removed when the problem is handled by system UI
     uint32_t delayMs = 0;
-    uint32_t waitMs = 0;
     if (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) {
         delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
     }
-    if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
-        DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
-        waitMs = updateCallRouting(newDevices, delayMs);
-    }
-    for (size_t i = 0; i < mOutputs.size(); i++) {
-        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
-        DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
-        if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
-            // As done in setDeviceConnectionState, we could also fix default device issue by
-            // preventing the force re-routing in case of default dev that distinguishes on address.
-            // Let's give back to engine full device choice decision however.
-            waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
-        }
-        if (forceVolumeReeval && !newDevices.isEmpty()) {
-            applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
-        }
-    }
+
+    updateCallAndOutputRouting(forceVolumeReeval, delayMs);
 
     for (const auto& activeDesc : mInputs.getActiveInputs()) {
         auto newDevice = getNewInputDevice(activeDesc);
@@ -839,7 +812,7 @@
         // if explicitly requested
         static const uint32_t kRelevantFlags =
                 (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
-                 AUDIO_OUTPUT_FLAG_VOIP_RX);
+                 AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
         flags =
             (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
     }
@@ -860,7 +833,7 @@
                 continue;
             }
             // reject profiles if connected device does not support codec
-            if (!curProfile->deviceSupportsEncodedFormats(devices.types())) {
+            if (!curProfile->devicesSupportEncodedFormats(devices.types())) {
                 continue;
             }
             if (!directOnly) return curProfile;
@@ -937,7 +910,8 @@
         audio_output_flags_t *flags,
         audio_port_handle_t *selectedDeviceId,
         bool *isRequestedDeviceForExclusiveUse,
-        std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
+        std::vector<sp<AudioPolicyMix>> *secondaryMixes,
+        output_type_t *outputType)
 {
     DeviceVector outputDevices;
     const audio_port_handle_t requestedPortId = *selectedDeviceId;
@@ -945,6 +919,7 @@
     const sp<DeviceDescriptor> requestedDevice =
         mAvailableOutputDevices.getDeviceFromId(requestedPortId);
 
+    *outputType = API_OUTPUT_INVALID;
     status_t status = getAudioAttributes(resultAttr, attr, *stream);
     if (status != NO_ERROR) {
         return status;
@@ -960,31 +935,55 @@
     // The primary output is the explicit routing (eg. setPreferredDevice) if specified,
     //       otherwise, fallback to the dynamic policies, if none match, query the engine.
     // Secondary outputs are always found by dynamic policies as the engine do not support them
-    sp<SwAudioOutputDescriptor> policyDesc;
-    status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, policyDesc, secondaryDescs);
+    sp<AudioPolicyMix> primaryMix;
+    status = mPolicyMixes.getOutputForAttr(*resultAttr, uid, *flags, primaryMix, secondaryMixes);
     if (status != OK) {
         return status;
     }
 
     // Explicit routing is higher priority then any dynamic policy primary output
-    bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && policyDesc != nullptr;
+    bool usePrimaryOutputFromPolicyMixes = requestedDevice == nullptr && primaryMix != nullptr;
 
     // FIXME: in case of RENDER policy, the output capabilities should be checked
-    if ((usePrimaryOutputFromPolicyMixes || !secondaryDescs->empty())
+    if ((usePrimaryOutputFromPolicyMixes
+            || (secondaryMixes != nullptr && !secondaryMixes->empty()))
         && !audio_is_linear_pcm(config->format)) {
         ALOGD("%s: rejecting request as dynamic audio policy only support pcm", __func__);
         return BAD_VALUE;
     }
     if (usePrimaryOutputFromPolicyMixes) {
-        *output = policyDesc->mIoHandle;
-        sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
         sp<DeviceDescriptor> deviceDesc =
-                mAvailableOutputDevices.getDevice(mix->mDeviceType,
-                                                  mix->mDeviceAddress,
+                mAvailableOutputDevices.getDevice(primaryMix->mDeviceType,
+                                                  primaryMix->mDeviceAddress,
                                                   AUDIO_FORMAT_DEFAULT);
-        *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
-        ALOGV("getOutputForAttr() returns output %d", *output);
-        return NO_ERROR;
+        sp<SwAudioOutputDescriptor> policyDesc = primaryMix->getOutput();
+        if (deviceDesc != nullptr
+                && (policyDesc == nullptr || (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT))) {
+            audio_io_handle_t newOutput;
+            status = openDirectOutput(
+                    *stream, session, config,
+                    (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT),
+                    DeviceVector(deviceDesc), &newOutput);
+            if (status != NO_ERROR) {
+                policyDesc = nullptr;
+            } else {
+                policyDesc = mOutputs.valueFor(newOutput);
+                primaryMix->setOutput(policyDesc);
+            }
+        }
+        if (policyDesc != nullptr) {
+            policyDesc->mPolicyMix = primaryMix;
+            *output = policyDesc->mIoHandle;
+            *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
+
+            ALOGV("getOutputForAttr() returns output %d", *output);
+            if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+                *outputType = API_OUT_MIX_PLAYBACK;
+            } else {
+                *outputType = API_OUTPUT_LEGACY;
+            }
+            return NO_ERROR;
+        }
     }
     // Virtual sources must always be dynamicaly or explicitly routed
     if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
@@ -1004,10 +1003,10 @@
     // FIXME: provide a more generic approach which is not device specific and move this back
     // to getOutputForDevice.
     // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
-    if (outputDevices.types() == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+    if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX) &&
         (*stream == AUDIO_STREAM_MUSIC  || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
         audio_is_linear_pcm(config->format) &&
-        isInCall()) {
+        isCallAudioAccessible()) {
         if (requestedPortId != AUDIO_PORT_HANDLE_NONE) {
             *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
             *isRequestedDeviceForExclusiveUse = true;
@@ -1040,6 +1039,12 @@
 
     *selectedDeviceId = getFirstDeviceId(outputDevices);
 
+    if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+        *outputType = API_OUTPUT_TELEPHONY_TX;
+    } else {
+        *outputType = API_OUTPUT_LEGACY;
+    }
+
     ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
 
     return NO_ERROR;
@@ -1054,7 +1059,8 @@
                                               audio_output_flags_t *flags,
                                               audio_port_handle_t *selectedDeviceId,
                                               audio_port_handle_t *portId,
-                                              std::vector<audio_io_handle_t> *secondaryOutputs)
+                                              std::vector<audio_io_handle_t> *secondaryOutputs,
+                                              output_type_t *outputType)
 {
     // The supplied portId must be AUDIO_PORT_HANDLE_NONE
     if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1063,7 +1069,7 @@
     const audio_port_handle_t requestedPortId = *selectedDeviceId;
     audio_attributes_t resultAttr;
     bool isRequestedDeviceForExclusiveUse = false;
-    std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputDescs;
+    std::vector<sp<AudioPolicyMix>> secondaryMixes;
     const sp<DeviceDescriptor> requestedDevice =
       mAvailableOutputDevices.getDeviceFromId(requestedPortId);
 
@@ -1074,29 +1080,37 @@
 
     status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
             config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
-            &secondaryOutputDescs);
+            secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType);
     if (status != NO_ERROR) {
         return status;
     }
     std::vector<wp<SwAudioOutputDescriptor>> weakSecondaryOutputDescs;
-    for (auto& secondaryDesc : secondaryOutputDescs) {
-        secondaryOutputs->push_back(secondaryDesc->mIoHandle);
-        weakSecondaryOutputDescs.push_back(secondaryDesc);
+    if (secondaryOutputs != nullptr) {
+        for (auto &secondaryMix : secondaryMixes) {
+            sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
+            if (outputDesc != nullptr &&
+                outputDesc->mIoHandle != AUDIO_IO_HANDLE_NONE) {
+                secondaryOutputs->push_back(outputDesc->mIoHandle);
+                weakSecondaryOutputDescs.push_back(outputDesc);
+            }
+        }
     }
 
     audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
+        .channel_mask = config->channel_mask,
         .format = config->format,
-        .channel_mask = config->channel_mask };
-    *portId = AudioPort::getNextUniqueId();
+    };
+    *portId = PolicyAudioPort::getNextUniqueId();
 
+    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
     sp<TrackClientDescriptor> clientDesc =
         new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
                                   sanitizedRequestedPortId, *stream,
                                   mEngine->getProductStrategyForAttributes(resultAttr),
                                   toVolumeSource(resultAttr),
                                   *flags, isRequestedDeviceForExclusiveUse,
-                                  std::move(weakSecondaryOutputDescs));
-    sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
+                                  std::move(weakSecondaryOutputDescs),
+                                  outputDesc->mPolicyMix);
     outputDesc->addClient(clientDesc);
 
     ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
@@ -1105,6 +1119,118 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyManager::openDirectOutput(audio_stream_type_t stream,
+                                              audio_session_t session,
+                                              const audio_config_t *config,
+                                              audio_output_flags_t flags,
+                                              const DeviceVector &devices,
+                                              audio_io_handle_t *output) {
+
+    *output = AUDIO_IO_HANDLE_NONE;
+
+    // skip direct output selection if the request can obviously be attached to a mixed output
+    // and not explicitly requested
+    if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+            audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
+            audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
+        return NAME_NOT_FOUND;
+    }
+
+    // Do not allow offloading if one non offloadable effect is enabled or MasterMono is enabled.
+    // This prevents creating an offloaded track and tearing it down immediately after start
+    // when audioflinger detects there is an active non offloadable effect.
+    // FIXME: We should check the audio session here but we do not have it in this context.
+    // This may prevent offloading in rare situations where effects are left active by apps
+    // in the background.
+    sp<IOProfile> profile;
+    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
+            !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
+        profile = getProfileForOutput(
+                devices, config->sample_rate, config->format, config->channel_mask,
+                flags, true /* directOnly */);
+    }
+
+    if (profile == nullptr) {
+        return NAME_NOT_FOUND;
+    }
+
+    // exclusive outputs for MMAP and Offload are enforced by different session ids.
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+        if (!desc->isDuplicated() && (profile == desc->mProfile)) {
+            // reuse direct output if currently open by the same client
+            // and configured with same parameters
+            if ((config->sample_rate == desc->getSamplingRate()) &&
+                (config->format == desc->getFormat()) &&
+                (config->channel_mask == desc->getChannelMask()) &&
+                (session == desc->mDirectClientSession)) {
+                desc->mDirectOpenCount++;
+                ALOGI("%s reusing direct output %d for session %d", __func__,
+                    mOutputs.keyAt(i), session);
+                *output = mOutputs.keyAt(i);
+                return NO_ERROR;
+            }
+        }
+    }
+
+    if (!profile->canOpenNewIo()) {
+        return NAME_NOT_FOUND;
+    }
+
+    sp<SwAudioOutputDescriptor> outputDesc =
+            new SwAudioOutputDescriptor(profile, mpClientInterface);
+
+    String8 address = getFirstDeviceAddress(devices);
+
+    // MSD patch may be using the only output stream that can service this request. Release
+    // MSD patch to prioritize this request over any active output on MSD.
+    AudioPatchCollection msdPatches = getMsdPatches();
+    for (size_t i = 0; i < msdPatches.size(); i++) {
+        const auto& patch = msdPatches[i];
+        for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
+            const struct audio_port_config *sink = &patch->mPatch.sinks[j];
+            if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
+                    devices.containsDeviceWithType(sink->ext.device.type) &&
+                    (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
+                            AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
+                releaseAudioPatch(patch->getHandle(), mUidCached);
+                break;
+            }
+        }
+    }
+
+    status_t status = outputDesc->open(config, devices, stream, flags, output);
+
+    // only accept an output with the requested parameters
+    if (status != NO_ERROR ||
+        (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
+        (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
+        (config->channel_mask != 0 && config->channel_mask != outputDesc->getChannelMask())) {
+        ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
+                "format %d %d, channel mask %04x %04x", __func__, *output, config->sample_rate,
+                outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
+                config->channel_mask, outputDesc->getChannelMask());
+        if (*output != AUDIO_IO_HANDLE_NONE) {
+            outputDesc->close();
+        }
+        // fall back to mixer output if possible when the direct output could not be open
+        if (audio_is_linear_pcm(config->format) &&
+                config->sample_rate  <= SAMPLE_RATE_HZ_MAX) {
+            return NAME_NOT_FOUND;
+        }
+        *output = AUDIO_IO_HANDLE_NONE;
+        return BAD_VALUE;
+    }
+    outputDesc->mDirectOpenCount = 1;
+    outputDesc->mDirectClientSession = session;
+
+    addOutput(*output, outputDesc);
+    mPreviousOutputs = mOutputs;
+    ALOGV("%s returns new direct output %d", __func__, *output);
+    mpClientInterface->onAudioPortListUpdate();
+    return NO_ERROR;
+}
+
 audio_io_handle_t AudioPolicyManager::getOutputForDevices(
         const DeviceVector &devices,
         audio_session_t session,
@@ -1114,7 +1240,6 @@
         bool forceMutingHaptic)
 {
     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-    status_t status;
 
     // Discard haptic channel mask when forcing muting haptic channels.
     audio_channel_mask_t channelMask = forceMutingHaptic
@@ -1149,112 +1274,13 @@
         ALOGV("Set VoIP and Direct output flags for PCM format");
     }
 
-
-    sp<IOProfile> profile;
-
-    // skip direct output selection if the request can obviously be attached to a mixed output
-    // and not explicitly requested
-    if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
-            audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
-            audio_channel_count_from_out_mask(channelMask) <= 2) {
-        goto non_direct_output;
-    }
-
-    // Do not allow offloading if one non offloadable effect is enabled or MasterMono is enabled.
-    // This prevents creating an offloaded track and tearing it down immediately after start
-    // when audioflinger detects there is an active non offloadable effect.
-    // FIXME: We should check the audio session here but we do not have it in this context.
-    // This may prevent offloading in rare situations where effects are left active by apps
-    // in the background.
-
-    if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
-            !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
-        profile = getProfileForOutput(devices,
-                                   config->sample_rate,
-                                   config->format,
-                                   channelMask,
-                                   (audio_output_flags_t)*flags,
-                                   true /* directOnly */);
-    }
-
-    if (profile != 0) {
-        // exclusive outputs for MMAP and Offload are enforced by different session ids.
-        for (size_t i = 0; i < mOutputs.size(); i++) {
-            sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-            if (!desc->isDuplicated() && (profile == desc->mProfile)) {
-                // reuse direct output if currently open by the same client
-                // and configured with same parameters
-                if ((config->sample_rate == desc->mSamplingRate) &&
-                    (config->format == desc->mFormat) &&
-                    (channelMask == desc->mChannelMask) &&
-                    (session == desc->mDirectClientSession)) {
-                    desc->mDirectOpenCount++;
-                    ALOGI("%s reusing direct output %d for session %d", __func__, 
-                        mOutputs.keyAt(i), session);
-                    return mOutputs.keyAt(i);
-                }
-            }
-        }
-
-        if (!profile->canOpenNewIo()) {
-            goto non_direct_output;
-        }
-
-        sp<SwAudioOutputDescriptor> outputDesc =
-                new SwAudioOutputDescriptor(profile, mpClientInterface);
-
-        String8 address = getFirstDeviceAddress(devices);
-
-        // MSD patch may be using the only output stream that can service this request. Release
-        // MSD patch to prioritize this request over any active output on MSD.
-        AudioPatchCollection msdPatches = getMsdPatches();
-        for (size_t i = 0; i < msdPatches.size(); i++) {
-            const auto& patch = msdPatches[i];
-            for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
-                const struct audio_port_config *sink = &patch->mPatch.sinks[j];
-                if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
-                        (sink->ext.device.type & devices.types()) != AUDIO_DEVICE_NONE &&
-                        (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
-                                AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
-                    releaseAudioPatch(patch->mHandle, mUidCached);
-                    break;
-                }
-            }
-        }
-
-        status = outputDesc->open(config, devices, stream, *flags, &output);
-
-        // only accept an output with the requested parameters
-        if (status != NO_ERROR ||
-            (config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
-            (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) ||
-            (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
-            ALOGV("%s failed opening direct output: output %d sample rate %d %d," 
-                    "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
-                    outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
-                    channelMask, outputDesc->mChannelMask);
-            if (output != AUDIO_IO_HANDLE_NONE) {
-                outputDesc->close();
-            }
-            // fall back to mixer output if possible when the direct output could not be open
-            if (audio_is_linear_pcm(config->format) &&
-                    config->sample_rate  <= SAMPLE_RATE_HZ_MAX) {
-                goto non_direct_output;
-            }
-            return AUDIO_IO_HANDLE_NONE;
-        }
-        outputDesc->mDirectOpenCount = 1;
-        outputDesc->mDirectClientSession = session;
-
-        addOutput(output, outputDesc);
-        mPreviousOutputs = mOutputs;
-        ALOGV("%s returns new direct output %d", __func__, output);
-        mpClientInterface->onAudioPortListUpdate();
+    audio_config_t directConfig = *config;
+    directConfig.channel_mask = channelMask;
+    status_t status = openDirectOutput(stream, session, &directConfig, *flags, devices, &output);
+    if (status != NAME_NOT_FOUND) {
         return output;
     }
 
-non_direct_output:
-
     // A request for HW A/V sync cannot fallback to a mixed output because time
     // stamps are embedded in audio data
     if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
@@ -1303,7 +1329,7 @@
                 const struct audio_port_config *source = &patch->mPatch.sources[j];
                 if (source->type == AUDIO_PORT_TYPE_DEVICE &&
                         source->ext.device.hw_module == msdModule->getHandle()) {
-                    msdPatches.addAudioPatch(patch->mHandle, patch);
+                    msdPatches.addAudioPatch(patch->getHandle(), patch);
                 }
             }
         }
@@ -1338,19 +1364,19 @@
     // Each IOProfile represents a MixPort from audio_policy_configuration.xml
     for (const auto &inProfile : inputProfiles) {
         if (hwAvSync == ((inProfile->getFlags() & AUDIO_INPUT_FLAG_HW_AV_SYNC) != 0)) {
-            msdProfiles.appendVector(inProfile->getAudioProfiles());
+            appendAudioProfiles(msdProfiles, inProfile->getAudioProfiles());
         }
     }
     AudioProfileVector deviceProfiles;
     for (const auto &outProfile : outputProfiles) {
         if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
-            deviceProfiles.appendVector(outProfile->getAudioProfiles());
+            appendAudioProfiles(deviceProfiles, outProfile->getAudioProfiles());
         }
     }
     struct audio_config_base bestSinkConfig;
-    status_t result = msdProfiles.findBestMatchingOutputConfig(deviceProfiles,
+    status_t result = findBestMatchingOutputConfig(msdProfiles, deviceProfiles,
             compressedFormatsOrder, surroundChannelMasksOrder, true /*preferHigherSamplingRates*/,
-            &bestSinkConfig);
+            bestSinkConfig);
     if (result != NO_ERROR) {
         ALOGD("%s() no matching profiles found for device: %s, hwAvSync: %d",
                 __func__, outputDevice->toString().c_str(), hwAvSync);
@@ -1362,6 +1388,14 @@
     // For encoded streams force direct flag to prevent downstream mixing.
     sinkConfig->flags.output = static_cast<audio_output_flags_t>(
             sinkConfig->flags.output | AUDIO_OUTPUT_FLAG_DIRECT);
+    if (audio_is_iec61937_compatible(sinkConfig->format)) {
+        // For formats compatible with IEC61937 encapsulation, assume that
+        // the record thread input from MSD is IEC61937 framed (for proportional buffer sizing).
+        // Add the AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO flag so downstream HAL can distinguish between
+        // raw and IEC61937 framed streams.
+        sinkConfig->flags.output = static_cast<audio_output_flags_t>(
+                sinkConfig->flags.output | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO);
+    }
     sourceConfig->sample_rate = bestSinkConfig.sample_rate;
     // Specify exact channel mask to prevent guessing by bit count in PatchPanel.
     sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
@@ -1425,7 +1459,7 @@
         if (audio_patches_are_equal(&currentPatch->mPatch, patch)) {
             return NO_ERROR;
         }
-        releaseAudioPatch(currentPatch->mHandle, mUidCached);
+        releaseAudioPatch(currentPatch->getHandle(), mUidCached);
     }
     status_t status = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
             patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
@@ -1503,13 +1537,13 @@
         // If haptic channel is specified, use the haptic output if present.
         // When using haptic output, same audio format and sample rate are required.
         const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
-            outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+            outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
         if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
             continue;
         }
         if (outputHapticChannelCount >= hapticChannelCount
-            && format == outputDesc->mFormat
-            && samplingRate == outputDesc->mSamplingRate) {
+            && format == outputDesc->getFormat()
+            && samplingRate == outputDesc->getSamplingRate()) {
                 currentMatchCriteria[0] = outputHapticChannelCount;
         }
 
@@ -1517,12 +1551,13 @@
         currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);
 
         // channel mask and channel count match
-        uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask);
+        uint32_t outputChannelCount = audio_channel_count_from_out_mask(
+                outputDesc->getChannelMask());
         if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
             channelCount <= outputChannelCount) {
             if ((audio_channel_mask_get_representation(channelMask) ==
-                    audio_channel_mask_get_representation(outputDesc->mChannelMask)) &&
-                    ((channelMask & outputDesc->mChannelMask) == channelMask)) {
+                    audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
+                    ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
                 currentMatchCriteria[2] = outputChannelCount;
             }
             currentMatchCriteria[3] = outputChannelCount;
@@ -1530,8 +1565,8 @@
 
         // sampling rate match
         if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
-                samplingRate <= outputDesc->mSamplingRate) {
-            currentMatchCriteria[4] = outputDesc->mSamplingRate;
+                samplingRate <= outputDesc->getSamplingRate()) {
+            currentMatchCriteria[4] = outputDesc->getSamplingRate();
         }
 
         // performance flags match
@@ -1540,8 +1575,8 @@
         // format match
         if (format != AUDIO_FORMAT_INVALID) {
             currentMatchCriteria[6] =
-                AudioPort::kFormatDistanceMax -
-                AudioPort::formatDistance(format, outputDesc->mFormat);
+                PolicyAudioPort::kFormatDistanceMax -
+                PolicyAudioPort::formatDistance(format, outputDesc->getFormat());
         }
 
         // primary output match
@@ -1630,7 +1665,7 @@
     DeviceVector devices;
     sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
     const char *address = NULL;
-    if (policyMix != NULL) {
+    if (policyMix != nullptr) {
         audio_devices_t newDeviceType;
         address = policyMix->mDeviceAddress.string();
         if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
@@ -1755,14 +1790,15 @@
     }
 
     if (stream == AUDIO_STREAM_ENFORCED_AUDIBLE &&
-            mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+            mEngine->getForceUse(
+                    AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
         setStrategyMute(streamToStrategy(AUDIO_STREAM_ALARM), true, outputDesc);
     }
 
     // Automatically enable the remote submix input when output is started on a re routing mix
     // of type MIX_TYPE_RECORDERS
-    if (audio_is_remote_submix_device(devices.types()) && policyMix != NULL &&
-        policyMix->mMixType == MIX_TYPE_RECORDERS) {
+    if (isSingleDeviceType(devices.types(), &audio_is_remote_submix_device) &&
+        policyMix != NULL && policyMix->mMixType == MIX_TYPE_RECORDERS) {
         setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
                                     address,
@@ -1809,8 +1845,9 @@
             // Automatically disable the remote submix input when output is stopped on a
             // re routing mix of type MIX_TYPE_RECORDERS
             sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
-            if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
-                policyMix != NULL &&
+            if (isSingleDeviceType(
+                    outputDesc->devices().types(), &audio_is_remote_submix_device) &&
+                policyMix != nullptr &&
                 policyMix->mMixType == MIX_TYPE_RECORDERS) {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                             AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -2065,7 +2102,7 @@
 
     isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
         mSoundTriggerSessions.indexOfKey(session) >= 0;
-    *portId = AudioPort::getNextUniqueId();
+    *portId = PolicyAudioPort::getNextUniqueId();
 
     clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config,
                                             requestedDeviceId, attributes.source, flags,
@@ -2147,7 +2184,7 @@
 
     if (!profile->canOpenNewIo()) {
         for (size_t i = 0; i < mInputs.size(); ) {
-            sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
+            sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
             if (desc->mProfile != profile) {
                 i++;
                 continue;
@@ -2239,19 +2276,25 @@
         return status;
     }
 
-  // increment activity count before calling getNewInputDevice() below as only active sessions
+    // increment activity count before calling getNewInputDevice() below as only active sessions
     // are considered for device selection
     inputDesc->setClientActive(client, true);
 
     // indicate active capture to sound trigger service if starting capture from a mic on
     // primary HW module
     sp<DeviceDescriptor> device = getNewInputDevice(inputDesc);
-    setInputDevice(input, device, true /* force */);
+    if (device != nullptr) {
+        status = setInputDevice(input, device, true /* force */);
+    } else {
+        ALOGW("%s no new input device can be found for descriptor %d",
+                __FUNCTION__, inputDesc->getId());
+        status = BAD_VALUE;
+    }
 
-    if (inputDesc->activeCount()  == 1) {
+    if (status == NO_ERROR && inputDesc->activeCount() == 1) {
         sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
         // if input maps to a dynamic policy with an activity listener, notify of state change
-        if ((policyMix != NULL)
+        if ((policyMix != nullptr)
                 && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
             mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
                     MIX_STATE_MIXING);
@@ -2260,7 +2303,7 @@
         DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
         if (primaryInputDevices.contains(device) &&
                 mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
-            SoundTrigger::setCaptureState(true);
+            mpClientInterface->setSoundTriggerCaptureState(true);
         }
 
         // automatically enable the remote submix output when input is started if not
@@ -2268,7 +2311,7 @@
         // For remote submix (a virtual device), we open only one input per capture request.
         if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
             String8 address = String8("");
-            if (policyMix == NULL) {
+            if (policyMix == nullptr) {
                 address = String8("0");
             } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
                 address = policyMix->mDeviceAddress;
@@ -2279,11 +2322,16 @@
                         address, "remote-submix", AUDIO_FORMAT_DEFAULT);
             }
         }
+    } else if (status != NO_ERROR) {
+        // Restore client activity state.
+        inputDesc->setClientActive(client, false);
+        inputDesc->stop();
     }
 
-    ALOGV("%s input %d source = %d exit", __FUNCTION__, input, client->source());
+    ALOGV("%s input %d source = %d status = %d exit",
+            __FUNCTION__, input, client->source(), status);
 
-    return NO_ERROR;
+    return status;
 }
 
 status_t AudioPolicyManager::stopInput(audio_port_handle_t portId)
@@ -2310,7 +2358,7 @@
     } else {
         sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
         // if input maps to a dynamic policy with an activity listener, notify of state change
-        if ((policyMix != NULL)
+        if ((policyMix != nullptr)
                 && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
             mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
                     MIX_STATE_IDLE);
@@ -2320,7 +2368,7 @@
         // used by a policy mix of type MIX_TYPE_RECORDERS
         if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
             String8 address = String8("");
-            if (policyMix == NULL) {
+            if (policyMix == nullptr) {
                 address = String8("0");
             } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
                 address = policyMix->mDeviceAddress;
@@ -2338,7 +2386,7 @@
         DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
         if (primaryInputDevices.contains(inputDesc->getDevice()) &&
                 mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
-            SoundTrigger::setCaptureState(false);
+            mpClientInterface->setSoundTriggerCaptureState(false);
         }
         inputDesc->clearPreemptedSessions();
     }
@@ -2396,8 +2444,7 @@
     for (size_t i = 0; i < mInputs.size(); i++) {
         const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
         if (input->clientsList().size() == 0
-                || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())
-                || (input->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
+                || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
             inputsToClose.push_back(mInputs.keyAt(i));
         } else {
             bool close = false;
@@ -2446,6 +2493,10 @@
                                                   audio_devices_t device)
 {
     auto attributes = mEngine->getAttributesForStreamType(stream);
+    if (attributes == AUDIO_ATTRIBUTES_INITIALIZER) {
+        ALOGW("%s: no group for stream %s, bailing out", __func__, toString(stream).c_str());
+        return NO_ERROR;
+    }
     ALOGV("%s: stream %s attributes=%s", __func__,
           toString(stream).c_str(), toString(attributes).c_str());
     return setVolumeIndexForAttributes(attributes, index, device);
@@ -2457,10 +2508,12 @@
 {
     // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
     // stream by the engine.
+    DeviceTypeSet deviceTypes = {device};
     if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
-        device = mEngine->getOutputDevicesForStream(stream, true /*fromCache*/).types();
+        deviceTypes = mEngine->getOutputDevicesForStream(
+                stream, true /*fromCache*/).types();
     }
-    return getVolumeIndex(getVolumeCurves(stream), *index, device);
+    return getVolumeIndex(getVolumeCurves(stream), *index, deviceTypes);
 }
 
 status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attributes,
@@ -2485,19 +2538,20 @@
         return status;
     }
 
-    audio_devices_t curSrcDevice;
+    DeviceTypeSet curSrcDevices;
     auto curCurvAttrs = curves.getAttributes();
     if (!curCurvAttrs.empty() && curCurvAttrs.front() != defaultAttr) {
         auto attr = curCurvAttrs.front();
-        curSrcDevice = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
+        curSrcDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false).types();
     } else if (!curves.getStreamTypes().empty()) {
         auto stream = curves.getStreamTypes().front();
-        curSrcDevice = mEngine->getOutputDevicesForStream(stream, false).types();
+        curSrcDevices = mEngine->getOutputDevicesForStream(stream, false).types();
     } else {
         ALOGE("%s: Invalid src %d: no valid attributes nor stream",__func__, vs);
         return BAD_VALUE;
     }
-    curSrcDevice = Volume::getDeviceForVolume(curSrcDevice);
+    audio_devices_t curSrcDevice = Volume::getDeviceForVolume(curSrcDevices);
+    resetDeviceTypes(curSrcDevices, curSrcDevice);
 
     // update volume on all outputs and streams matching the following:
     // - The requested stream (or a stream matching for volume control) is active on the output
@@ -2509,21 +2563,34 @@
     // no specific device volume value exists for currently selected device.
     for (size_t i = 0; i < mOutputs.size(); i++) {
         sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-        audio_devices_t curDevice = desc->devices().types();
+        DeviceTypeSet curDevices = desc->devices().types();
 
-        if (curDevice & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
-            curDevice |= AUDIO_DEVICE_OUT_SPEAKER;
-            curDevice &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+        if (curDevices.erase(AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
+            curDevices.insert(AUDIO_DEVICE_OUT_SPEAKER);
         }
-
+        if (!(desc->isActive(vs) || isInCall())) {
+            continue;
+        }
+        if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME &&
+                curDevices.find(device) == curDevices.end()) {
+            continue;
+        }
+        bool applyVolume = false;
+        if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
+            curSrcDevices.insert(device);
+            applyVolume = (curSrcDevices.find(
+                    Volume::getDeviceForVolume(curDevices)) != curSrcDevices.end());
+        } else {
+            applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
+        }
+        if (!applyVolume) {
+            continue; // next output
+        }
         // Inter / intra volume group priority management: Loop on strategies arranged by priority
         // If a higher priority strategy is active, and the output is routed to a device with a
         // HW Gain management, do not change the volume
-        bool applyVolume = false;
         if (desc->useHwGain()) {
-            if (!(desc->isActive(toVolumeSource(group)) || isInCall())) {
-                continue;
-            }
+            applyVolume = false;
             for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
                 auto activeClients = desc->clientsList(true /*activeOnly*/, productStrategy,
                                                        false /*preferredDevice*/);
@@ -2557,37 +2624,16 @@
             if (!applyVolume) {
                 continue; // next output
             }
-            status_t volStatus = checkAndSetVolume(curves, vs, index, desc, curDevice,
-                                                   (vs == toVolumeSource(AUDIO_STREAM_SYSTEM)?
-                                                        TOUCH_SOUND_FIXED_DELAY_MS : 0));
-            if (volStatus != NO_ERROR) {
-                status = volStatus;
-            }
-            continue;
         }
-        if (!(desc->isActive(vs) || isInCall())) {
-            continue;
-        }
-        if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) && ((curDevice & device) == 0)) {
-            continue;
-        }
-        if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
-            curSrcDevice |= device;
-            applyVolume = (Volume::getDeviceForVolume(curDevice) & curSrcDevice) != 0;
-        } else {
-            applyVolume = !curves.hasVolumeIndexForDevice(curSrcDevice);
-        }
-        if (applyVolume) {
-            //FIXME: workaround for truncated touch sounds
-            // delayed volume change for system stream to be removed when the problem is
-            // handled by system UI
-            status_t volStatus = checkAndSetVolume(
-                        curves, vs, index, desc, curDevice,
-                        ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
-                             TOUCH_SOUND_FIXED_DELAY_MS : 0));
-            if (volStatus != NO_ERROR) {
-                status = volStatus;
-            }
+        //FIXME: workaround for truncated touch sounds
+        // delayed volume change for system stream to be removed when the problem is
+        // handled by system UI
+        status_t volStatus = checkAndSetVolume(
+                    curves, vs, index, desc, curDevices,
+                    ((vs == toVolumeSource(AUDIO_STREAM_SYSTEM))?
+                         TOUCH_SOUND_FIXED_DELAY_MS : 0));
+        if (volStatus != NO_ERROR) {
+            status = volStatus;
         }
     }
     mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/);
@@ -2625,22 +2671,23 @@
 {
     // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this
     // stream by the engine.
+    DeviceTypeSet deviceTypes = {device};
     if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
-        device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types();
+        DeviceTypeSet deviceTypes = mEngine->getOutputDevicesForAttributes(
+                attr, nullptr, true /*fromCache*/).types();
     }
-    return getVolumeIndex(getVolumeCurves(attr), index, device);
+    return getVolumeIndex(getVolumeCurves(attr), index, deviceTypes);
 }
 
 status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves,
                                             int &index,
-                                            audio_devices_t device) const
+                                            const DeviceTypeSet& deviceTypes) const
 {
-    if (!audio_is_output_device(device)) {
+    if (isSingleDeviceType(deviceTypes, audio_is_output_device)) {
         return BAD_VALUE;
     }
-    device = Volume::getDeviceForVolume(device);
-    index = curves.getVolumeIndex(device);
-    ALOGV("%s: device %08x index %d", __FUNCTION__, device, index);
+    index = curves.getVolumeIndex(deviceTypes);
+    ALOGV("%s: device %s index %d", __FUNCTION__, dumpDeviceTypes(deviceTypes).c_str(), index);
     return NO_ERROR;
 }
 
@@ -2735,12 +2782,14 @@
                                 int session,
                                 int id)
 {
-    ssize_t index = mOutputs.indexOfKey(io);
-    if (index < 0) {
-        index = mInputs.indexOfKey(io);
+    if (session != AUDIO_SESSION_DEVICE) {
+        ssize_t index = mOutputs.indexOfKey(io);
         if (index < 0) {
-            ALOGW("registerEffect() unknown io %d", io);
-            return INVALID_OPERATION;
+            index = mInputs.indexOfKey(io);
+            if (index < 0) {
+                ALOGW("registerEffect() unknown io %d", io);
+                return INVALID_OPERATION;
+            }
         }
     }
     return mEffects.registerEffect(desc, io, session, id,
@@ -2760,16 +2809,6 @@
     return mEffects.unregisterEffect(id);
 }
 
-void AudioPolicyManager::cleanUpEffectsForIo(audio_io_handle_t io)
-{
-    EffectDescriptorCollection effects = mEffects.getEffectsForIo(io);
-    for (size_t i = 0; i < effects.size(); i++) {
-        ALOGW("%s removing stale effect %s, id %d on closed IO %d",
-              __func__, effects.valueAt(i)->mDesc.name, effects.keyAt(i), io);
-        unregisterEffect(effects.keyAt(i));
-    }
-}
-
 status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
 {
     sp<EffectDescriptor> effect = mEffects.getEffect(id);
@@ -2839,7 +2878,7 @@
 {
     ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
     status_t res = NO_ERROR;
-
+    bool checkOutputs = false;
     sp<HwModule> rSubmixModule;
     // examine each mix's route type
     for (size_t i = 0; i < mixes.size(); i++) {
@@ -2885,13 +2924,13 @@
             }
             audio_config_t outputConfig = mix.mFormat;
             audio_config_t inputConfig = mix.mFormat;
-            // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
-            // stereo and let audio flinger do the channel conversion if needed.
+            // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL
+            // in stereo and let audio flinger do the channel conversion if needed.
             outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
             inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
-            rSubmixModule->addOutputProfile(address, &outputConfig,
+            rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
                     AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
-            rSubmixModule->addInputProfile(address, &inputConfig,
+            rSubmixModule->addInputProfile(address.c_str(), &inputConfig,
                     AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
 
             if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
@@ -2916,10 +2955,11 @@
             }
 
             bool foundOutput = false;
-            for (size_t j = 0 ; j < mOutputs.size() ; j++) {
+            // First try to find an already opened output supporting the device
+            for (size_t j = 0 ; j < mOutputs.size() && !foundOutput && res == NO_ERROR; j++) {
                 sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
 
-                if (desc->supportedDevices().contains(device)) {
+                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());
@@ -2927,10 +2967,26 @@
                     } else {
                         foundOutput = true;
                     }
-                    break;
                 }
             }
-
+            // If no output found, try to find a direct output profile supporting the device
+            for (size_t i = 0; i < mHwModules.size() && !foundOutput && res == NO_ERROR; i++) {
+                sp<HwModule> module = mHwModules[i];
+                for (size_t j = 0;
+                        j < module->getOutputProfiles().size() && !foundOutput && res == NO_ERROR;
+                        j++) {
+                    sp<IOProfile> profile = module->getOutputProfiles()[j];
+                    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());
+                            res = INVALID_OPERATION;
+                        } else {
+                            foundOutput = true;
+                        }
+                    }
+                }
+            }
             if (res != NO_ERROR) {
                 ALOGE(" Error registering mix %zu for device 0x%X addr %s",
                         i, type, address.string());
@@ -2941,11 +2997,16 @@
                         i, type, address.string());
                 res = INVALID_OPERATION;
                 break;
+            } else {
+                checkOutputs = true;
             }
         }
     }
     if (res != NO_ERROR) {
         unregisterPolicyMixes(mixes);
+    } else if (checkOutputs) {
+        checkForDeviceAndOutputChanges();
+        updateCallAndOutputRouting();
     }
     return res;
 }
@@ -2954,6 +3015,7 @@
 {
     ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
     status_t res = NO_ERROR;
+    bool checkOutputs = false;
     sp<HwModule> rSubmixModule;
     // examine each mix's route type
     for (const auto& mix : mixes) {
@@ -2987,16 +3049,22 @@
                     }
                 }
             }
-            rSubmixModule->removeOutputProfile(address);
-            rSubmixModule->removeInputProfile(address);
+            rSubmixModule->removeOutputProfile(address.c_str());
+            rSubmixModule->removeInputProfile(address.c_str());
 
         } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
             if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
                 res = INVALID_OPERATION;
                 continue;
+            } else {
+                checkOutputs = true;
             }
         }
     }
+    if (res == NO_ERROR && checkOutputs) {
+        checkForDeviceAndOutputChanges();
+        updateCallAndOutputRouting();
+    }
     return res;
 }
 
@@ -3013,48 +3081,159 @@
     }
 }
 
+// Returns true if all devices types match the predicate and are supported by one HW module
+bool  AudioPolicyManager::areAllDevicesSupported(
+        const Vector<AudioDeviceTypeAddr>& devices,
+        std::function<bool(audio_devices_t)> predicate,
+        const char *context) {
+    for (size_t i = 0; i < devices.size(); i++) {
+        sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+                devices[i].mType, devices[i].mAddress.c_str(), String8(),
+                AUDIO_FORMAT_DEFAULT, false /*allowToCreate*/, true /*matchAddress*/);
+        if (devDesc == nullptr || (predicate != nullptr && !predicate(devices[i].mType))) {
+            ALOGE("%s: device type %#x address %s not supported or not an output device",
+                    context, devices[i].mType, devices[i].mAddress.c_str());
+            return false;
+        }
+    }
+    return true;
+}
+
 status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
         const Vector<AudioDeviceTypeAddr>& devices) {
     ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
-    // uid/device affinity is only for output devices
-    for (size_t i = 0; i < devices.size(); i++) {
-        if (!audio_is_output_device(devices[i].mType)) {
-            ALOGE("setUidDeviceAffinities() device=%08x is NOT an output device",
-                    devices[i].mType);
-            return BAD_VALUE;
-        }
+    if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
+        return BAD_VALUE;
     }
     status_t res =  mPolicyMixes.setUidDeviceAffinities(uid, devices);
-    if (res == NO_ERROR) {
-        // reevaluate outputs for all given devices
-        for (size_t i = 0; i < devices.size(); i++) {
-            sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
-                            devices[i].mType, devices[i].mAddress, String8(),
-                            AUDIO_FORMAT_DEFAULT);
-            SortedVector<audio_io_handle_t> outputs;
-            if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                    outputs) != NO_ERROR) {
-                ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
-                        " addr=%s", devices[i].mType, devices[i].mAddress.string());
-                return INVALID_OPERATION;
-            }
-        }
+    if (res != NO_ERROR) {
+        ALOGE("%s() Could not set all device affinities for uid = %d", __FUNCTION__, uid);
+        return res;
     }
-    return res;
+
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
+    return NO_ERROR;
 }
 
 status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
     ALOGV("%s() uid=%d", __FUNCTION__, uid);
     status_t res = mPolicyMixes.removeUidDeviceAffinities(uid);
     if (res != NO_ERROR) {
-        ALOGE("%s() Could not remove all device affinities fo uid = %d",
+        ALOGE("%s() Could not remove all device affinities for uid = %d",
             __FUNCTION__, uid);
         return INVALID_OPERATION;
     }
 
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
     return res;
 }
 
+status_t AudioPolicyManager::setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device) {
+    ALOGV("%s() strategy=%d device=%08x addr=%s", __FUNCTION__,
+            strategy, device.mType, device.mAddress.c_str());
+
+    Vector<AudioDeviceTypeAddr> devices;
+    devices.add(device);
+    if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
+        return BAD_VALUE;
+    }
+    status_t status = mEngine->setPreferredDeviceForStrategy(strategy, device);
+    if (status != NO_ERROR) {
+        ALOGW("Engine could not set preferred device %08x %s for strategy %d",
+                device.mType, device.mAddress.c_str(), strategy);
+        return status;
+    }
+
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
+    return NO_ERROR;
+}
+
+void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs)
+{
+    uint32_t waitMs = 0;
+    if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+        DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
+        waitMs = updateCallRouting(newDevices, delayMs);
+    }
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
+        DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
+        if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
+            // As done in setDeviceConnectionState, we could also fix default device issue by
+            // preventing the force re-routing in case of default dev that distinguishes on address.
+            // Let's give back to engine full device choice decision however.
+            waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
+        }
+        if (forceVolumeReeval && !newDevices.isEmpty()) {
+            applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
+        }
+    }
+}
+
+status_t AudioPolicyManager::removePreferredDeviceForStrategy(product_strategy_t strategy)
+{
+    ALOGI("%s() strategy=%d", __FUNCTION__, strategy);
+
+    status_t status = mEngine->removePreferredDeviceForStrategy(strategy);
+    if (status != NO_ERROR) {
+        ALOGW("Engine could not remove preferred device for strategy %d", strategy);
+        return status;
+    }
+
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device) {
+    return mEngine->getPreferredDeviceForStrategy(strategy, device);
+}
+
+status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    ALOGI("%s() userId=%d num devices %zu", __FUNCTION__, userId, devices.size());\
+    if (!areAllDevicesSupported(devices, audio_is_output_device, __func__)) {
+        return BAD_VALUE;
+    }
+    status_t status =  mPolicyMixes.setUserIdDeviceAffinities(userId, devices);
+    if (status != NO_ERROR) {
+        ALOGE("%s() could not set device affinity for userId %d",
+            __FUNCTION__, userId);
+        return status;
+    }
+
+    // reevaluate outputs for all devices
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) {
+    ALOGI("%s() userId=%d", __FUNCTION__, userId);
+    status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId);
+    if (status != NO_ERROR) {
+        ALOGE("%s() Could not remove all device affinities fo userId = %d",
+            __FUNCTION__, userId);
+        return status;
+    }
+
+    // reevaluate outputs for all devices
+    checkForDeviceAndOutputChanges();
+    updateCallAndOutputRouting();
+
+    return NO_ERROR;
+}
+
 void AudioPolicyManager::dump(String8 *dst) const
 {
     dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@@ -3200,7 +3379,7 @@
     ALOGV("%s() profile %sfound with name: %s, "
         "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
         __FUNCTION__, profile != 0 ? "" : "NOT ",
-        (profile != 0 ? profile->getTagName().string() : "null"),
+        (profile != 0 ? profile->getTagName().c_str() : "null"),
         config.sample_rate, config.format, config.channel_mask, output_flags);
     return (profile != 0);
 }
@@ -3302,16 +3481,16 @@
     return BAD_VALUE;
 }
 
-status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
-                                               audio_patch_handle_t *handle,
-                                               uid_t uid)
+status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *patch,
+                                                      audio_patch_handle_t *handle,
+                                                      uid_t uid, uint32_t delayMs,
+                                                      const sp<SourceClientDescriptor>& sourceDesc)
 {
-    ALOGV("createAudioPatch()");
-
+    ALOGV("%s", __func__);
     if (handle == NULL || patch == NULL) {
         return BAD_VALUE;
     }
-    ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks);
+    ALOGV("%s num sources %d num sinks %d", __func__, patch->num_sources, patch->num_sinks);
 
     if (!audio_patch_is_valid(patch)) {
         return BAD_VALUE;
@@ -3333,22 +3512,22 @@
     sp<AudioPatch> patchDesc;
     ssize_t index = mAudioPatches.indexOfKey(*handle);
 
-    ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id,
-                                                           patch->sources[0].role,
-                                                           patch->sources[0].type);
+    ALOGV("%s source id %d role %d type %d", __func__, patch->sources[0].id,
+                                                       patch->sources[0].role,
+                                                       patch->sources[0].type);
 #if LOG_NDEBUG == 0
     for (size_t i = 0; i < patch->num_sinks; i++) {
-        ALOGV("createAudioPatch sink %zu: id %d role %d type %d", i, patch->sinks[i].id,
-                                                             patch->sinks[i].role,
-                                                             patch->sinks[i].type);
+        ALOGV("%s sink %zu: id %d role %d type %d", __func__ ,i, patch->sinks[i].id,
+                                                                 patch->sinks[i].role,
+                                                                 patch->sinks[i].type);
     }
 #endif
 
     if (index >= 0) {
         patchDesc = mAudioPatches.valueAt(index);
-        ALOGV("createAudioPatch() mUidCached %d patchDesc->mUid %d uid %d",
-                                                                  mUidCached, patchDesc->mUid, uid);
-        if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) {
+        ALOGV("%s mUidCached %d patchDesc->mUid %d uid %d",
+              __func__, mUidCached, patchDesc->getUid(), uid);
+        if (patchDesc->getUid() != mUidCached && uid != patchDesc->getUid()) {
             return INVALID_OPERATION;
         }
     } else {
@@ -3358,15 +3537,15 @@
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
         sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
-            ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id);
+            ALOGV("%s output not found for id %d", __func__, patch->sources[0].id);
             return BAD_VALUE;
         }
         ALOG_ASSERT(!outputDesc->isDuplicated(),"duplicated output %d in source in ports",
                                                 outputDesc->mIoHandle);
         if (patchDesc != 0) {
             if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) {
-                ALOGV("createAudioPatch() source id differs for patch current id %d new id %d",
-                                          patchDesc->mPatch.sources[0].id, patch->sources[0].id);
+                ALOGV("%s source id differs for patch current id %d new id %d",
+                      __func__, patchDesc->mPatch.sources[0].id, patch->sources[0].id);
                 return BAD_VALUE;
             }
         }
@@ -3375,13 +3554,13 @@
             // Only support mix to devices connection
             // TODO add support for mix to mix connection
             if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
-                ALOGV("createAudioPatch() source mix but sink is not a device");
+                ALOGV("%s source mix but sink is not a device", __func__);
                 return INVALID_OPERATION;
             }
             sp<DeviceDescriptor> devDesc =
                     mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id);
             if (devDesc == 0) {
-                ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[i].id);
+                ALOGV("%s out device not found for id %d", __func__, patch->sinks[i].id);
                 return BAD_VALUE;
             }
 
@@ -3393,8 +3572,7 @@
                                                            patch->sources[0].channel_mask,
                                                            NULL,  // updatedChannelMask
                                                            AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
-                ALOGV("createAudioPatch() profile not supported for device %08x",
-                        devDesc->type());
+                ALOGV("%s profile not supported for device %08x", __func__, devDesc->type());
                 return INVALID_OPERATION;
             }
             devices.add(devDesc);
@@ -3404,19 +3582,19 @@
         }
 
         // TODO: reconfigure output format and channels here
-        ALOGV("createAudioPatch() setting device %08x on output %d",
-              devices.types(), outputDesc->mIoHandle);
+        ALOGV("%s setting device %s on output %d",
+              __func__, dumpDeviceTypes(devices.types()).c_str(), outputDesc->mIoHandle);
         setOutputDevices(outputDesc, devices, true, 0, handle);
         index = mAudioPatches.indexOfKey(*handle);
         if (index >= 0) {
             if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
-                ALOGW("createAudioPatch() setOutputDevice() did not reuse the patch provided");
+                ALOGW("%s setOutputDevice() did not reuse the patch provided", __func__);
             }
             patchDesc = mAudioPatches.valueAt(index);
-            patchDesc->mUid = uid;
-            ALOGV("createAudioPatch() success");
+            patchDesc->setUid(uid);
+            ALOGV("%s success", __func__);
         } else {
-            ALOGW("createAudioPatch() setOutputDevice() failed to create a patch");
+            ALOGW("%s setOutputDevice() failed to create a patch", __func__);
             return INVALID_OPERATION;
         }
     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
@@ -3455,19 +3633,19 @@
                 return INVALID_OPERATION;
             }
             // TODO: reconfigure output format and channels here
-            ALOGV("%s() setting device %s on output %d", __func__,
+            ALOGV("%s setting device %s on output %d", __func__,
                   device->toString().c_str(), inputDesc->mIoHandle);
             setInputDevice(inputDesc->mIoHandle, device, true, handle);
             index = mAudioPatches.indexOfKey(*handle);
             if (index >= 0) {
                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
-                    ALOGW("createAudioPatch() setInputDevice() did not reuse the patch provided");
+                    ALOGW("%s setInputDevice() did not reuse the patch provided", __func__);
                 }
                 patchDesc = mAudioPatches.valueAt(index);
-                patchDesc->mUid = uid;
-                ALOGV("createAudioPatch() success");
+                patchDesc->setUid(uid);
+                ALOGV("%s success", __func__);
             } else {
-                ALOGW("createAudioPatch() setInputDevice() failed to create a patch");
+                ALOGW("%s setInputDevice() failed to create a patch", __func__);
                 return INVALID_OPERATION;
             }
         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) {
@@ -3485,55 +3663,96 @@
 
             //update source and sink with our own data as the data passed in the patch may
             // be incomplete.
-            struct audio_patch newPatch = *patch;
-            srcDevice->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]);
+            PatchBuilder patchBuilder;
+            audio_port_config sourcePortConfig = {};
+            srcDevice->toAudioPortConfig(&sourcePortConfig, &patch->sources[0]);
+            patchBuilder.addSource(sourcePortConfig);
 
             for (size_t i = 0; i < patch->num_sinks; i++) {
                 if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
-                    ALOGV("createAudioPatch() source device but one sink is not a device");
+                    ALOGV("%s source device but one sink is not a device", __func__);
                     return INVALID_OPERATION;
                 }
-
                 sp<DeviceDescriptor> sinkDevice =
                         mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id);
                 if (sinkDevice == 0) {
                     return BAD_VALUE;
                 }
-                sinkDevice->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);
+                audio_port_config sinkPortConfig = {};
+                sinkDevice->toAudioPortConfig(&sinkPortConfig, &patch->sinks[i]);
+                patchBuilder.addSink(sinkPortConfig);
 
                 // create a software bridge in PatchPanel if:
                 // - source and sink devices are on different HW modules OR
                 // - audio HAL version is < 3.0
                 // - audio HAL version is >= 3.0 but no route has been declared between devices
+                // - called from startAudioSource (aka sourceDesc != nullptr) and source device does
+                //   not have a gain controller
                 if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
                         (srcDevice->getModuleVersionMajor() < 3) ||
-                        !srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice)) {
+                        !srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice) ||
+                        (sourceDesc != nullptr &&
+                         srcDevice->getAudioPort()->getGains().size() == 0)) {
                     // support only one sink device for now to simplify output selection logic
                     if (patch->num_sinks > 1) {
                         return INVALID_OPERATION;
                     }
-                    SortedVector<audio_io_handle_t> outputs =
-                            getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
-                    // if the sink device is reachable via an opened output stream, request to go via
-                    // this output stream by adding a second source to the patch description
-                    const audio_io_handle_t output = selectOutput(outputs);
-                    if (output != AUDIO_IO_HANDLE_NONE) {
-                        sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-                        if (outputDesc->isDuplicated()) {
+                    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+                    if (sourceDesc != nullptr) {
+                        // take care of dynamic routing for SwOutput selection,
+                        audio_attributes_t attributes = sourceDesc->attributes();
+                        audio_stream_type_t stream = sourceDesc->stream();
+                        audio_attributes_t resultAttr;
+                        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+                        config.sample_rate = sourceDesc->config().sample_rate;
+                        config.channel_mask = sourceDesc->config().channel_mask;
+                        config.format = sourceDesc->config().format;
+                        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+                        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+                        bool isRequestedDeviceForExclusiveUse = false;
+                        output_type_t outputType;
+                        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
+                                            &stream, sourceDesc->uid(), &config, &flags,
+                                            &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
+                                            nullptr, &outputType);
+                        if (output == AUDIO_IO_HANDLE_NONE) {
+                            ALOGV("%s no output for device %s",
+                                  __FUNCTION__, sinkDevice->toString().c_str());
                             return INVALID_OPERATION;
                         }
-                        outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]);
-                        newPatch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
-                        newPatch.num_sources = 2;
+                    } else {
+                        SortedVector<audio_io_handle_t> outputs =
+                                getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
+                        // if the sink device is reachable via an opened output stream, request to
+                        // go via this output stream by adding a second source to the patch
+                        // description
+                        output = selectOutput(outputs);
+                    }
+                    if (output != AUDIO_IO_HANDLE_NONE) {
+                        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
+                        if (outputDesc->isDuplicated()) {
+                            ALOGV("%s output for device %s is duplicated",
+                                  __FUNCTION__, sinkDevice->toString().c_str());
+                            return INVALID_OPERATION;
+                        }
+                        audio_port_config srcMixPortConfig = {};
+                        outputDesc->toAudioPortConfig(&srcMixPortConfig, &patch->sources[0]);
+                        if (sourceDesc != nullptr) {
+                            sourceDesc->setSwOutput(outputDesc);
+                        }
+                        // for volume control, we may need a valid stream
+                        srcMixPortConfig.ext.mix.usecase.stream = sourceDesc != nullptr ?
+                                    sourceDesc->stream() : AUDIO_STREAM_PATCH;
+                        patchBuilder.addSource(srcMixPortConfig);
                     }
                 }
             }
             // TODO: check from routing capabilities in config file and other conflicting patches
 
-            status_t status = installPatch(__func__, index, handle, &newPatch, 0, uid, &patchDesc);
+            status_t status = installPatch(
+                        __func__, index, handle, patchBuilder.patch(), delayMs, uid, &patchDesc);
             if (status != NO_ERROR) {
-                ALOGW("createAudioPatch() patch panel could not connect device patch, error %d",
-                status);
+                ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
                 return INVALID_OPERATION;
             }
         } else {
@@ -3556,18 +3775,29 @@
         return BAD_VALUE;
     }
     sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-    ALOGV("releaseAudioPatch() mUidCached %d patchDesc->mUid %d uid %d",
-          mUidCached, patchDesc->mUid, uid);
-    if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) {
+    ALOGV("%s() mUidCached %d patchDesc->mUid %d uid %d",
+          __func__, mUidCached, patchDesc->getUid(), uid);
+    if (patchDesc->getUid() != mUidCached && uid != patchDesc->getUid()) {
         return INVALID_OPERATION;
     }
+    return releaseAudioPatchInternal(handle);
+}
 
+status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t handle,
+                                                       uint32_t delayMs)
+{
+    ALOGV("%s patch %d", __func__, handle);
+    if (mAudioPatches.indexOfKey(handle) < 0) {
+        ALOGE("%s: no patch found with handle=%d", __func__, handle);
+        return BAD_VALUE;
+    }
+    sp<AudioPatch> patchDesc = mAudioPatches.valueFor(handle);
     struct audio_patch *patch = &patchDesc->mPatch;
-    patchDesc->mUid = mUidCached;
+    patchDesc->setUid(mUidCached);
     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
         sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
         if (outputDesc == NULL) {
-            ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id);
+            ALOGV("%s output not found for id %d", __func__, patch->sources[0].id);
             return BAD_VALUE;
         }
 
@@ -3580,7 +3810,7 @@
         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
             sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
             if (inputDesc == NULL) {
-                ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id);
+                ALOGV("%s input not found for id %d", __func__, patch->sinks[0].id);
                 return BAD_VALUE;
             }
             setInputDevice(inputDesc->mIoHandle,
@@ -3588,12 +3818,33 @@
                            true,
                            NULL);
         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) {
-            status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
-            ALOGV("releaseAudioPatch() patch panel returned %d patchHandle %d",
-                                                              status, patchDesc->mAfPatchHandle);
-            removeAudioPatch(patchDesc->mHandle);
+            status_t status =
+                    mpClientInterface->releaseAudioPatch(patchDesc->getAfHandle(), delayMs);
+            ALOGV("%s patch panel returned %d patchHandle %d",
+                  __func__, status, patchDesc->getAfHandle());
+            removeAudioPatch(patchDesc->getHandle());
             nextAudioPortGeneration();
             mpClientInterface->onAudioPatchListUpdate();
+            // SW Bridge
+            if (patch->num_sources > 1 && patch->sources[1].type == AUDIO_PORT_TYPE_MIX) {
+                sp<SwAudioOutputDescriptor> outputDesc =
+                        mOutputs.getOutputFromId(patch->sources[1].id);
+                if (outputDesc == NULL) {
+                    ALOGE("%s output not found for id %d", __func__, patch->sources[0].id);
+                    return BAD_VALUE;
+                }
+                if (patchDesc->getHandle() != outputDesc->getPatchHandle()) {
+                    // force SwOutput patch removal as AF counter part patch has already gone.
+                    ALOGV("%s reset patch handle on Output as different from SWBridge", __func__);
+                    removeAudioPatch(outputDesc->getPatchHandle());
+                }
+                outputDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
+                setOutputDevices(outputDesc,
+                                 getNewOutputDevices(outputDesc, true /*fromCache*/),
+                                 true, /*force*/
+                                 0,
+                                 NULL);
+            }
         } else {
             return BAD_VALUE;
         }
@@ -3689,7 +3940,7 @@
 {
     for (ssize_t i = (ssize_t)mAudioPatches.size() - 1; i >= 0; i--)  {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(i);
-        if (patchDesc->mUid == uid) {
+        if (patchDesc->getUid() == uid) {
             releaseAudioPatch(mAudioPatches.keyAt(i), uid);
         }
     }
@@ -3823,13 +4074,10 @@
         return BAD_VALUE;
     }
 
-    *portId = AudioPort::getNextUniqueId();
-
-    struct audio_patch dummyPatch = {};
-    sp<AudioPatch> patchDesc = new AudioPatch(&dummyPatch, uid);
+    *portId = PolicyAudioPort::getNextUniqueId();
 
     sp<SourceClientDescriptor> sourceDesc =
-        new SourceClientDescriptor(*portId, uid, *attributes, patchDesc, srcDevice,
+        new SourceClientDescriptor(*portId, uid, *attributes, *source, srcDevice,
                                    mEngine->getStreamTypeForAttributes(*attributes),
                                    mEngine->getProductStrategyForAttributes(*attributes),
                                    toVolumeSource(*attributes));
@@ -3849,7 +4097,6 @@
     disconnectAudioSource(sourceDesc);
 
     audio_attributes_t attributes = sourceDesc->attributes();
-    audio_stream_type_t stream = sourceDesc->stream();
     sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
 
     DeviceVector sinkDevices =
@@ -3859,89 +4106,55 @@
     ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
                 __FUNCTION__, sinkDevice->toString().c_str());
 
-    audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-
-    if (srcDevice->hasSameHwModuleAs(sinkDevice) &&
-            srcDevice->getModuleVersionMajor() >= 3 &&
-            sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) &&
-            srcDevice->getAudioPort()->mGains.size() > 0) {
-        ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
-        // TODO: may explicitly specify whether we should use HW or SW patch
-        //   create patch between src device and output device
-        //   create Hwoutput and add to mHwOutputs
-    } else {
-        audio_attributes_t resultAttr;
-        audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
-        config.sample_rate = sourceDesc->config().sample_rate;
-        config.channel_mask = sourceDesc->config().channel_mask;
-        config.format = sourceDesc->config().format;
-        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
-        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-        bool isRequestedDeviceForExclusiveUse = false;
-        std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputs;
-        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
-                &attributes, &stream, sourceDesc->uid(), &config, &flags,
-                &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
-                &secondaryOutputs);
-        if (output == AUDIO_IO_HANDLE_NONE) {
-            ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevices.types());
-            return INVALID_OPERATION;
-        }
-        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
-        if (outputDesc->isDuplicated()) {
-            ALOGV("%s output for device %08x is duplicated", __FUNCTION__, sinkDevices.types());
-            return INVALID_OPERATION;
-        }
-        status_t status = outputDesc->start();
+    PatchBuilder patchBuilder;
+    patchBuilder.addSink(sinkDevice).addSource(srcDevice);
+    audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
+    status_t status =
+            createAudioPatchInternal(patchBuilder.patch(), &handle, mUidCached, 0, sourceDesc);
+    if (status != NO_ERROR || mAudioPatches.indexOfKey(handle) < 0) {
+        ALOGW("%s patch panel could not connect device patch, error %d", __func__, status);
+        return INVALID_OPERATION;
+    }
+    sourceDesc->setPatchHandle(handle);
+    // SW Bridge? (@todo: HW bridge, keep track of HwOutput for device selection "reconsideration")
+    sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
+    if (swOutput != 0) {
+        status = swOutput->start();
         if (status != NO_ERROR) {
-            return status;
+            goto FailureSourceAdded;
         }
-
-        // create a special patch with no sink and two sources:
-        // - the second source indicates to PatchPanel through which output mix this patch should
-        // be connected as well as the stream type for volume control
-        // - the sink is defined by whatever output device is currently selected for the output
-        // though which this patch is routed.
-        PatchBuilder patchBuilder;
-        patchBuilder.addSource(srcDevice).addSource(outputDesc, { .stream = stream });
-        status = mpClientInterface->createAudioPatch(patchBuilder.patch(),
-                                                              &afPatchHandle,
-                                                              0);
-        ALOGV("%s patch panel returned %d patchHandle %d", __FUNCTION__,
-                                                              status, afPatchHandle);
-        sourceDesc->patchDesc()->mPatch = *patchBuilder.patch();
-        if (status != NO_ERROR) {
-            ALOGW("%s patch panel could not connect device patch, error %d",
-                  __FUNCTION__, status);
-            return INVALID_OPERATION;
-        }
-
-        if (outputDesc->getClient(sourceDesc->portId()) != nullptr) {
+        if (swOutput->getClient(sourceDesc->portId()) != nullptr) {
             ALOGW("%s source portId has already been attached to outputDesc", __func__);
-            return INVALID_OPERATION;
+            goto FailureReleasePatch;
         }
-        outputDesc->addClient(sourceDesc);
-
+        swOutput->addClient(sourceDesc);
         uint32_t delayMs = 0;
-        status = startSource(outputDesc, sourceDesc, &delayMs);
-
+        status = startSource(swOutput, sourceDesc, &delayMs);
         if (status != NO_ERROR) {
-            mpClientInterface->releaseAudioPatch(sourceDesc->patchDesc()->mAfPatchHandle, 0);
-            outputDesc->removeClient(sourceDesc->portId());
-            outputDesc->stop();
-            return status;
+            ALOGW("%s failed to start source, error %d", __FUNCTION__, status);
+            goto FailureSourceActive;
         }
-        sourceDesc->setSwOutput(outputDesc);
         if (delayMs != 0) {
             usleep(delayMs * 1000);
         }
+    } else {
+        sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
+        if (hwOutputDesc != 0) {
+          //   create Hwoutput and add to mHwOutputs
+        } else {
+            ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
+        }
     }
-
-    sourceDesc->patchDesc()->mAfPatchHandle = afPatchHandle;
-    addAudioPatch(sourceDesc->patchDesc()->mHandle, sourceDesc->patchDesc());
-
     return NO_ERROR;
+
+FailureSourceActive:
+    swOutput->stop();
+    releaseOutput(sourceDesc->portId());
+FailureSourceAdded:
+    sourceDesc->setSwOutput(nullptr);
+FailureReleasePatch:
+    releaseAudioPatchInternal(handle);
+    return INVALID_OPERATION;
 }
 
 status_t AudioPolicyManager::stopAudioSource(audio_port_handle_t portId)
@@ -3999,7 +4212,7 @@
 float AudioPolicyManager::getStreamVolumeDB(
         audio_stream_type_t stream, int index, audio_devices_t device)
 {
-    return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, device);
+    return computeVolume(getVolumeCurves(stream), toVolumeSource(stream), index, {device});
 }
 
 status_t AudioPolicyManager::getSurroundFormats(unsigned int *numSurroundFormats,
@@ -4099,12 +4312,12 @@
 
     sp<SwAudioOutputDescriptor> outputDesc;
     bool profileUpdated = false;
-    DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(
-            AUDIO_DEVICE_OUT_HDMI);
+    DeviceVector hdmiOutputDevices = mAvailableOutputDevices.getDevicesFromType(
+        AUDIO_DEVICE_OUT_HDMI);
     for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiOutputDevices[i]->address();
-        String8 name = hdmiOutputDevices[i]->getName();
+        String8 address = String8(hdmiOutputDevices[i]->address().c_str());
+        std::string name = hdmiOutputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                                       address.c_str(),
@@ -4121,12 +4334,12 @@
         profileUpdated |= (status == NO_ERROR);
     }
     // FIXME: Why doing this for input HDMI devices if we don't augment their reported formats?
-    DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromTypeMask(
+    DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromType(
                 AUDIO_DEVICE_IN_HDMI);
     for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiInputDevices[i]->address();
-        String8 name = hdmiInputDevices[i]->getName();
+        String8 address = String8(hdmiInputDevices[i]->address().c_str());
+        std::string name = hdmiInputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                                       address.c_str(),
@@ -4151,11 +4364,11 @@
     return profileUpdated ? NO_ERROR : INVALID_OPERATION;
 }
 
-void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
+void AudioPolicyManager::setAppState(audio_port_handle_t portId, app_state_t state)
 {
-    ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
+    ALOGV("%s(portId:%d, state:%d)", __func__, portId, state);
     for (size_t i = 0; i < mInputs.size(); i++) {
-        mInputs.valueAt(i)->setAppState(uid, state);
+        mInputs.valueAt(i)->setAppState(portId, state);
     }
 }
 
@@ -4176,36 +4389,31 @@
     return false;
 }
 
+bool AudioPolicyManager::isCallScreenModeSupported()
+{
+    return getConfig().isCallScreenModeSupported();
+}
+
+
 status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
 {
     ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
-
-    sp<AudioPatch> patchDesc = mAudioPatches.valueFor(sourceDesc->patchDesc()->mHandle);
-    if (patchDesc == 0) {
-        ALOGW("%s source has no patch with handle %d", __FUNCTION__,
-              sourceDesc->patchDesc()->mHandle);
-        return BAD_VALUE;
-    }
-    removeAudioPatch(sourceDesc->patchDesc()->mHandle);
-
-    sp<SwAudioOutputDescriptor> swOutputDesc = sourceDesc->swOutput().promote();
-    if (swOutputDesc != 0) {
-        status_t status = stopSource(swOutputDesc, sourceDesc);
+    sp<SwAudioOutputDescriptor> swOutput = sourceDesc->swOutput().promote();
+    if (swOutput != 0) {
+        status_t status = stopSource(swOutput, sourceDesc);
         if (status == NO_ERROR) {
-            swOutputDesc->stop();
+            swOutput->stop();
         }
-        swOutputDesc->removeClient(sourceDesc->portId());
-        mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
+        releaseOutput(sourceDesc->portId());
     } else {
         sp<HwAudioOutputDescriptor> hwOutputDesc = sourceDesc->hwOutput().promote();
         if (hwOutputDesc != 0) {
-          //   release patch between src device and output device
           //   close Hwoutput and remove from mHwOutputs
         } else {
             ALOGW("%s source has neither SW nor HW output", __FUNCTION__);
         }
     }
-    return NO_ERROR;
+    return releaseAudioPatchInternal(sourceDesc->getPatchHandle());
 }
 
 sp<SourceClientDescriptor> AudioPolicyManager::getSourceForAttributesOnOutput(
@@ -4232,12 +4440,6 @@
     return mAudioPortGeneration++;
 }
 
-// Treblized audio policy xml config will be located in /odm/etc or /vendor/etc.
-static const char *kConfigLocationList[] =
-        {"/odm/etc", "/vendor/etc", "/system/etc"};
-static const int kConfigLocationListSize =
-        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));
-
 static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
     char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
     std::vector<const char*> fileNames;
@@ -4259,9 +4461,9 @@
     fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
 
     for (const char* fileName : fileNames) {
-        for (int i = 0; i < kConfigLocationListSize; i++) {
+        for (const auto& path : audio_get_configuration_paths()) {
             snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
-                     "%s/%s", kConfigLocationList[i], fileName);
+                     "%s/%s", path.c_str(), fileName);
             ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile, &config);
             if (ret == NO_ERROR) {
                 config.setSource(audioPolicyXmlConfigFile);
@@ -4279,7 +4481,7 @@
     mpClientInterface(clientInterface),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mA2dpSuspended(false),
-    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice),
+    mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -4294,17 +4496,8 @@
         : AudioPolicyManager(clientInterface, false /*forTesting*/)
 {
     loadConfig();
-    initialize();
 }
 
-//  This check is to catch any legacy platform updating to Q without having
-//  switched to XML since its deprecation on O.
-// TODO: after Q release, remove this check and flag as XML is now the only
-//        option and all legacy platform should have transitioned to XML.
-#ifndef USE_XML_AUDIO_POLICY_CONF
-#error Audio policy no longer supports legacy .conf configuration format
-#endif
-
 void AudioPolicyManager::loadConfig() {
     if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
         ALOGE("could not load audio policy configuration file, setting defaults");
@@ -4313,17 +4506,18 @@
 }
 
 status_t AudioPolicyManager::initialize() {
-    // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
-    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
-    if (!engineInstance) {
-        ALOGE("%s:  Could not get an instance of policy engine", __FUNCTION__);
-        return NO_INIT;
-    }
-    // Retrieve the Policy Manager Interface
-    mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
-    if (mEngine == NULL) {
-        ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
-        return NO_INIT;
+    {
+        auto engLib = EngineLibrary::load(
+                        "libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
+        if (!engLib) {
+            ALOGE("%s: Failed to load the engine library", __FUNCTION__);
+            return NO_INIT;
+        }
+        mEngine = engLib->createEngine();
+        if (mEngine == nullptr) {
+            ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
+            return NO_INIT;
+        }
     }
     mEngine->setObserver(this);
     status_t status = mEngine->initCheck();
@@ -4332,141 +4526,9 @@
         return status;
     }
 
-    // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
+    // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
     // open all output streams needed to access attached devices
-    for (const auto& hwModule : mHwModulesAll) {
-        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
-        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
-            ALOGW("could not open HW module %s", hwModule->getName());
-            continue;
-        }
-        mHwModules.push_back(hwModule);
-        // open all output streams needed to access attached devices
-        // except for direct output streams that are only opened when they are actually
-        // required by an app.
-        // This also validates mAvailableOutputDevices list
-        for (const auto& outProfile : hwModule->getOutputProfiles()) {
-            if (!outProfile->canOpenNewIo()) {
-                ALOGE("Invalid Output profile max open count %u for profile %s",
-                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
-                continue;
-            }
-            if (!outProfile->hasSupportedDevices()) {
-                ALOGW("Output profile contains no device on module %s", hwModule->getName());
-                continue;
-            }
-            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
-                mTtsOutputAvailable = true;
-            }
-
-            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
-                continue;
-            }
-            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mAvailableOutputDevices);
-            sp<DeviceDescriptor> supportedDevice = 0;
-            if (supportedDevices.contains(mDefaultOutputDevice)) {
-                supportedDevice = mDefaultOutputDevice;
-            } else {
-                // choose first device present in profile's SupportedDevices also part of
-                // mAvailableOutputDevices.
-                if (availProfileDevices.isEmpty()) {
-                    continue;
-                }
-                supportedDevice = availProfileDevices.itemAt(0);
-            }
-            if (!mAvailableOutputDevices.contains(supportedDevice)) {
-                continue;
-            }
-            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
-                                                                                 mpClientInterface);
-            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-            status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
-                                               AUDIO_STREAM_DEFAULT,
-                                               AUDIO_OUTPUT_FLAG_NONE, &output);
-            if (status != NO_ERROR) {
-                ALOGW("Cannot open output stream for devices %s on hw module %s",
-                      supportedDevice->toString().c_str(), hwModule->getName());
-                continue;
-            }
-            for (const auto &device : availProfileDevices) {
-                // give a valid ID to an attached device once confirmed it is reachable
-                if (!device->isAttached()) {
-                    device->attach(hwModule);
-                }
-            }
-            if (mPrimaryOutput == 0 &&
-                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
-                mPrimaryOutput = outputDesc;
-            }
-            addOutput(output, outputDesc);
-            setOutputDevices(outputDesc,
-                             DeviceVector(supportedDevice),
-                             true,
-                             0,
-                             NULL);
-        }
-        // open input streams needed to access attached devices to validate
-        // mAvailableInputDevices list
-        for (const auto& inProfile : hwModule->getInputProfiles()) {
-            if (!inProfile->canOpenNewIo()) {
-                ALOGE("Invalid Input profile max open count %u for profile %s",
-                      inProfile->maxOpenCount, inProfile->getTagName().c_str());
-                continue;
-            }
-            if (!inProfile->hasSupportedDevices()) {
-                ALOGW("Input profile contains no device on module %s", hwModule->getName());
-                continue;
-            }
-            // chose first device present in profile's SupportedDevices also part of
-            // available input devices
-            const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mAvailableInputDevices);
-            if (availProfileDevices.isEmpty()) {
-                ALOGE("%s: Input device list is empty!", __FUNCTION__);
-                continue;
-            }
-            sp<AudioInputDescriptor> inputDesc =
-                    new AudioInputDescriptor(inProfile, mpClientInterface);
-
-            audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
-            status_t status = inputDesc->open(nullptr,
-                                              availProfileDevices.itemAt(0),
-                                              AUDIO_SOURCE_MIC,
-                                              AUDIO_INPUT_FLAG_NONE,
-                                              &input);
-            if (status != NO_ERROR) {
-                ALOGW("Cannot open input stream for device %s on hw module %s",
-                      availProfileDevices.toString().c_str(),
-                      hwModule->getName());
-                continue;
-            }
-            for (const auto &device : availProfileDevices) {
-                // give a valid ID to an attached device once confirmed it is reachable
-                if (!device->isAttached()) {
-                    device->attach(hwModule);
-                    device->importAudioPort(inProfile, true);
-                }
-            }
-            inputDesc->close();
-        }
-    }
-    // make sure all attached devices have been allocated a unique ID
-    auto checkAndSetAvailable = [this](auto& devices) {
-        for (size_t i = 0; i < devices.size();) {
-            const auto &device = devices[i];
-            if (!device->isAttached()) {
-                ALOGW("device %s is unreachable", device->toString().c_str());
-                devices.remove(device);
-                continue;
-            }
-            // Device is now validated and can be appended to the available devices of the engine
-            setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
-            i++;
-        }
-    };
-    checkAndSetAvailable(mAvailableOutputDevices);
-    checkAndSetAvailable(mAvailableInputDevices);
+    onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
 
     // make sure default device is reachable
     if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
@@ -4476,11 +4538,11 @@
     }
     // If microphones address is empty, set it according to device type
     for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->address().isEmpty()) {
+        if (mAvailableInputDevices[i]->address().empty()) {
             if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
+                mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
             } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mAvailableInputDevices[i]->setAddress(String8(AUDIO_BACK_MICROPHONE_ADDRESS));
+                mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
             }
         }
     }
@@ -4521,11 +4583,153 @@
 
 // ---
 
+void AudioPolicyManager::onNewAudioModulesAvailable()
+{
+    DeviceVector newDevices;
+    onNewAudioModulesAvailableInt(&newDevices);
+    if (!newDevices.empty()) {
+        nextAudioPortGeneration();
+        mpClientInterface->onAudioPortListUpdate();
+    }
+}
+
+void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
+{
+    for (const auto& hwModule : mHwModulesAll) {
+        if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
+            continue;
+        }
+        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
+        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
+            ALOGW("could not open HW module %s", hwModule->getName());
+            continue;
+        }
+        mHwModules.push_back(hwModule);
+        // open all output streams needed to access attached devices
+        // except for direct output streams that are only opened when they are actually
+        // required by an app.
+        // This also validates mAvailableOutputDevices list
+        for (const auto& outProfile : hwModule->getOutputProfiles()) {
+            if (!outProfile->canOpenNewIo()) {
+                ALOGE("Invalid Output profile max open count %u for profile %s",
+                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
+                continue;
+            }
+            if (!outProfile->hasSupportedDevices()) {
+                ALOGW("Output profile contains no device on module %s", hwModule->getName());
+                continue;
+            }
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+                mTtsOutputAvailable = true;
+            }
+
+            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
+            DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
+            sp<DeviceDescriptor> supportedDevice = 0;
+            if (supportedDevices.contains(mDefaultOutputDevice)) {
+                supportedDevice = mDefaultOutputDevice;
+            } else {
+                // choose first device present in profile's SupportedDevices also part of
+                // mAvailableOutputDevices.
+                if (availProfileDevices.isEmpty()) {
+                    continue;
+                }
+                supportedDevice = availProfileDevices.itemAt(0);
+            }
+            if (!mOutputDevicesAll.contains(supportedDevice)) {
+                continue;
+            }
+            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
+                                                                                 mpClientInterface);
+            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+            status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
+                                               AUDIO_STREAM_DEFAULT,
+                                               AUDIO_OUTPUT_FLAG_NONE, &output);
+            if (status != NO_ERROR) {
+                ALOGW("Cannot open output stream for devices %s on hw module %s",
+                      supportedDevice->toString().c_str(), hwModule->getName());
+                continue;
+            }
+            for (const auto &device : availProfileDevices) {
+                // give a valid ID to an attached device once confirmed it is reachable
+                if (!device->isAttached()) {
+                    device->attach(hwModule);
+                    mAvailableOutputDevices.add(device);
+                    device->setEncapsulationInfoFromHal(mpClientInterface);
+                    if (newDevices) newDevices->add(device);
+                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+                }
+            }
+            if (mPrimaryOutput == 0 &&
+                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
+                mPrimaryOutput = outputDesc;
+            }
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
+                outputDesc->close();
+            } else {
+                addOutput(output, outputDesc);
+                setOutputDevices(outputDesc,
+                                 DeviceVector(supportedDevice),
+                                 true,
+                                 0,
+                                 NULL);
+            }
+        }
+        // open input streams needed to access attached devices to validate
+        // mAvailableInputDevices list
+        for (const auto& inProfile : hwModule->getInputProfiles()) {
+            if (!inProfile->canOpenNewIo()) {
+                ALOGE("Invalid Input profile max open count %u for profile %s",
+                      inProfile->maxOpenCount, inProfile->getTagName().c_str());
+                continue;
+            }
+            if (!inProfile->hasSupportedDevices()) {
+                ALOGW("Input profile contains no device on module %s", hwModule->getName());
+                continue;
+            }
+            // chose first device present in profile's SupportedDevices also part of
+            // available input devices
+            const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
+            DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
+            if (availProfileDevices.isEmpty()) {
+                ALOGE("%s: Input device list is empty!", __FUNCTION__);
+                continue;
+            }
+            sp<AudioInputDescriptor> inputDesc =
+                    new AudioInputDescriptor(inProfile, mpClientInterface);
+
+            audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+            status_t status = inputDesc->open(nullptr,
+                                              availProfileDevices.itemAt(0),
+                                              AUDIO_SOURCE_MIC,
+                                              AUDIO_INPUT_FLAG_NONE,
+                                              &input);
+            if (status != NO_ERROR) {
+                ALOGW("Cannot open input stream for device %s on hw module %s",
+                      availProfileDevices.toString().c_str(),
+                      hwModule->getName());
+                continue;
+            }
+            for (const auto &device : availProfileDevices) {
+                // give a valid ID to an attached device once confirmed it is reachable
+                if (!device->isAttached()) {
+                    device->attach(hwModule);
+                    device->importAudioPortAndPickAudioProfile(inProfile, true);
+                    mAvailableInputDevices.add(device);
+                    if (newDevices) newDevices->add(device);
+                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+                }
+            }
+            inputDesc->close();
+        }
+    }
+}
+
 void AudioPolicyManager::addOutput(audio_io_handle_t output,
                                    const sp<SwAudioOutputDescriptor>& outputDesc)
 {
     mOutputs.add(output, outputDesc);
-    applyStreamVolumes(outputDesc, AUDIO_DEVICE_NONE, 0 /* delayMs */, true /* force */);
+    applyStreamVolumes(outputDesc, DeviceTypeSet(), 0 /* delayMs */, true /* force */);
     updateMono(output); // update mono status when adding to output list
     selectOutputForMusicEffects();
     nextAudioPortGeneration();
@@ -4549,7 +4753,7 @@
                                                    SortedVector<audio_io_handle_t>& outputs)
 {
     audio_devices_t deviceType = device->type();
-    const String8 &address = device->address();
+    const String8 &address = String8(device->address().c_str());
     sp<SwAudioOutputDescriptor> desc;
 
     if (audio_device_is_digital(deviceType)) {
@@ -4562,7 +4766,7 @@
         for (size_t i = 0; i < mOutputs.size(); i++) {
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated() && desc->supportsDevice(device)
-                    && desc->deviceSupportsEncodedFormats(deviceType)) {
+                    && desc->devicesSupportEncodedFormats({deviceType})) {
                 ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
                       mOutputs.keyAt(i), device->toString().c_str());
                 outputs.add(mOutputs.keyAt(i));
@@ -4601,7 +4805,7 @@
                     // matching profile: save the sample rates, format and channel masks supported
                     // by the profile in our device descriptor
                     if (audio_device_is_digital(deviceType)) {
-                        device->importAudioPort(profile);
+                        device->importAudioPortAndPickAudioProfile(profile);
                     }
                     break;
                 }
@@ -4617,7 +4821,7 @@
             }
 
             ALOGV("opening output for device %08x with params %s profile %p name %s",
-                  deviceType, address.string(), profile.get(), profile->getName().string());
+                  deviceType, address.string(), profile.get(), profile->getName().c_str());
             desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
             status_t status = desc->open(nullptr, DeviceVector(device),
@@ -4655,7 +4859,7 @@
 
                 if (output != AUDIO_IO_HANDLE_NONE) {
                     addOutput(output, desc);
-                    if (device_distinguishes_on_address(deviceType) && address != "0") {
+                    if (audio_is_remote_submix_device(deviceType) && address != "0") {
                         sp<AudioPolicyMix> policyMix;
                         if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
                                 == NO_ERROR) {
@@ -4703,7 +4907,7 @@
                 outputs.add(output);
                 // Load digital format info only for digital devices
                 if (audio_device_is_digital(deviceType)) {
-                    device->importAudioPort(profile);
+                    device->importAudioPortAndPickAudioProfile(profile);
                 }
 
                 if (device_distinguishes_on_address(deviceType)) {
@@ -4727,7 +4931,7 @@
             if (!desc->isDuplicated()) {
                 // exact match on device
                 if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
-                        && desc->deviceSupportsEncodedFormats(deviceType)) {
+                        && desc->devicesSupportEncodedFormats({deviceType})) {
                     outputs.add(mOutputs.keyAt(i));
                 } else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -4797,7 +5001,7 @@
                 desc = mInputs.valueAt(input_index);
                 if (desc->mProfile == profile) {
                     if (audio_device_is_digital(device->type())) {
-                        device->importAudioPort(profile);
+                        device->importAudioPortAndPickAudioProfile(profile);
                     }
                     break;
                 }
@@ -4821,7 +5025,7 @@
                                          &input);
 
             if (status == NO_ERROR) {
-                const String8& address = device->address();
+                const String8& address = String8(device->address().c_str());
                 if (!address.isEmpty()) {
                     char *param = audio_device_address_to_parameter(device->type(), address);
                     mpClientInterface->setParameters(input, String8(param));
@@ -4846,7 +5050,7 @@
                 profile_index--;
             } else {
                 if (audio_device_is_digital(device->type())) {
-                    device->importAudioPort(profile);
+                    device->importAudioPortAndPickAudioProfile(profile);
                 }
                 ALOGV("checkInputsForDevice(): adding input %d", input);
             }
@@ -4921,7 +5125,8 @@
     ssize_t index = mAudioPatches.indexOfKey(closingOutput->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-        (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
+        (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(
+                    patchDesc->getAfHandle(), 0);
         mAudioPatches.removeItemsAt(index);
         mpClientInterface->onAudioPatchListUpdate();
     }
@@ -4949,8 +5154,6 @@
             setMsdPatch();
         }
     }
-
-    cleanUpEffectsForIo(output);
 }
 
 void AudioPolicyManager::closeInput(audio_io_handle_t input)
@@ -4969,7 +5172,8 @@
     ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-        (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
+        (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(
+                    patchDesc->getAfHandle(), 0);
         mAudioPatches.removeItemsAt(index);
         mpClientInterface->onAudioPatchListUpdate();
     }
@@ -4980,10 +5184,8 @@
     DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
     if (primaryInputDevices.contains(device) &&
             mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
-        SoundTrigger::setCaptureState(false);
+        mpClientInterface->setSoundTriggerCaptureState(false);
     }
-
-    cleanUpEffectsForIo(input);
 }
 
 SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
@@ -4998,7 +5200,7 @@
                 i, openOutputs.valueAt(i)->isDuplicated(),
                 openOutputs.valueAt(i)->supportedDevices().toString().c_str());
         if (openOutputs.valueAt(i)->supportsAllDevices(devices)
-                && openOutputs.valueAt(i)->deviceSupportsEncodedFormats(devices.types())) {
+                && openOutputs.valueAt(i)->devicesSupportEncodedFormats(devices.types())) {
             ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
             outputs.add(openOutputs.keyAt(i));
         }
@@ -5033,37 +5235,80 @@
 
     DeviceVector oldDevices = mEngine->getOutputDevicesForAttributes(attr, 0, true /*fromCache*/);
     DeviceVector newDevices = mEngine->getOutputDevicesForAttributes(attr, 0, false /*fromCache*/);
+
     SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);
 
-    // also take into account external policy-related changes: add all outputs which are
-    // associated with policies in the "before" and "after" output vectors
-    ALOGVV("%s(): policy related outputs", __func__);
-    for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
-        const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
-        if (desc != 0 && desc->mPolicyMix != NULL) {
-            srcOutputs.add(desc->mIoHandle);
-            ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
+    uint32_t maxLatency = 0;
+    bool invalidate = false;
+    // take into account dynamic audio policies related changes: if a client is now associated
+    // to a different policy mix than at creation time, invalidate corresponding stream
+    for (size_t i = 0; i < mPreviousOutputs.size() && !invalidate; i++) {
+        const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i);
+        if (desc->isDuplicated()) {
+            continue;
         }
-    }
-    for (size_t i = 0 ; i < mOutputs.size() ; i++) {
-        const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-        if (desc != 0 && desc->mPolicyMix != NULL) {
-            dstOutputs.add(desc->mIoHandle);
-            ALOGVV(" new outputs: adding %d", desc->mIoHandle);
+        for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
+            if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) {
+                continue;
+            }
+            sp<AudioPolicyMix> primaryMix;
+            status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
+                    client->flags(), primaryMix, nullptr);
+            if (status != OK) {
+                continue;
+            }
+            if (client->getPrimaryMix() != primaryMix) {
+                invalidate = true;
+                if (desc->isStrategyActive(psId)) {
+                    maxLatency = desc->latency();
+                }
+                break;
+            }
         }
     }
 
-    if (srcOutputs != dstOutputs) {
+    if (srcOutputs != dstOutputs || invalidate) {
         // get maximum latency of all source outputs to determine the minimum mute time guaranteeing
         // audio from invalidated tracks will be rendered when unmuting
-        uint32_t maxLatency = 0;
         for (audio_io_handle_t srcOut : srcOutputs) {
             sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
-            if (desc != 0 && maxLatency < desc->latency()) {
+            if (desc == nullptr) continue;
+
+            if (desc->isStrategyActive(psId) && maxLatency < desc->latency()) {
                 maxLatency = desc->latency();
             }
+
+            if (invalidate) continue;
+
+            for (auto client : desc->clientsList(false /*activeOnly*/)) {
+                if (desc->isDuplicated() || !desc->mProfile->isDirectOutput()) {
+                    // a client on a non direct outputs has necessarily a linear PCM format
+                    // so we can call selectOutput() safely
+                    const audio_io_handle_t newOutput = selectOutput(dstOutputs,
+                                                                     client->flags(),
+                                                                     client->config().format,
+                                                                     client->config().channel_mask,
+                                                                     client->config().sample_rate);
+                    if (newOutput != srcOut) {
+                        invalidate = true;
+                        break;
+                    }
+                } else {
+                    sp<IOProfile> profile = getProfileForOutput(newDevices,
+                                   client->config().sample_rate,
+                                   client->config().format,
+                                   client->config().channel_mask,
+                                   client->flags(),
+                                   true /* directOnly */);
+                    if (profile != desc->mProfile) {
+                        invalidate = true;
+                        break;
+                    }
+                }
+            }
         }
+
         ALOGV_IF(!(srcOutputs.isEmpty() || dstOutputs.isEmpty()),
               "%s: strategy %d, moving from output %s to output %s", __func__, psId,
               std::to_string(srcOutputs[0]).c_str(),
@@ -5071,7 +5316,9 @@
         // mute strategy while moving tracks from one output to another
         for (audio_io_handle_t srcOut : srcOutputs) {
             sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
-            if (desc != 0 && desc->isStrategyActive(psId)) {
+            if (desc == nullptr) continue;
+
+            if (desc->isStrategyActive(psId)) {
                 setStrategyMute(psId, true, desc);
                 setStrategyMute(psId, false, desc, maxLatency * LATENCY_MUTE_FACTOR,
                                 newDevices.types());
@@ -5087,8 +5334,10 @@
             selectOutputForMusicEffects();
         }
         // Move tracks associated to this stream (and linked) from previous output to new output
-        for (auto stream :  mEngine->getStreamTypesForProductStrategy(psId)) {
-            mpClientInterface->invalidateStream(stream);
+        if (invalidate) {
+            for (auto stream :  mEngine->getStreamTypesForProductStrategy(psId)) {
+                mpClientInterface->invalidateStream(stream);
+            }
         }
     }
 }
@@ -5106,10 +5355,19 @@
     for (size_t i = 0; i < mOutputs.size(); i++) {
         const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
         for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
-            sp<SwAudioOutputDescriptor> desc;
-            std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
+            sp<AudioPolicyMix> primaryMix;
+            std::vector<sp<AudioPolicyMix>> secondaryMixes;
             status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
-                                                            client->flags(), desc, &secondaryDescs);
+                    client->flags(), primaryMix, &secondaryMixes);
+            std::vector<sp<SwAudioOutputDescriptor>> secondaryDescs;
+            for (auto &secondaryMix : secondaryMixes) {
+                sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
+                if (outputDesc != nullptr &&
+                    outputDesc->mIoHandle != AUDIO_IO_HANDLE_NONE) {
+                    secondaryDescs.push_back(outputDesc);
+                }
+            }
+
             if (status != OK ||
                 !std::equal(client->getSecondaryOutputs().begin(),
                             client->getSecondaryOutputs().end(),
@@ -5133,9 +5391,8 @@
     }
 
     bool isScoConnected =
-            ((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
-                    ~AUDIO_DEVICE_BIT_IN) != 0) ||
-            ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0);
+            (mAvailableInputDevices.types().count(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0 ||
+             !Intersection(mAvailableOutputDevices.types(), getAudioDeviceOutAllScoSet()).empty());
 
     // if suspended, restore A2DP output if:
     //      ((SCO device is NOT connected) ||
@@ -5182,7 +5439,7 @@
     ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-        if (patchDesc->mUid != mUidCached) {
+        if (patchDesc->getUid() != mUidCached) {
             ALOGV("%s device %s forced by patch %d", __func__,
                   outputDesc->devices().toString().c_str(), outputDesc->getPatchHandle());
             return  outputDesc->devices();
@@ -5210,7 +5467,8 @@
         auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
 
         if ((hasVoiceStream(streams) &&
-             (isInCall() || mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) ||
+             (isInCall() || mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc)) &&
+             !isStreamActive(AUDIO_STREAM_ENFORCED_AUDIBLE, 0)) ||
              ((hasStream(streams, AUDIO_STREAM_ALARM) || hasStream(streams, AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
                 mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc)) ||
                 outputDesc->isStrategyActive(productStrategy)) {
@@ -5232,7 +5490,7 @@
     ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-        if (patchDesc->mUid != mUidCached) {
+        if (patchDesc->getUid() != mUidCached) {
             ALOGV("getNewInputDevice() device %s forced by patch %d",
                   inputDesc->getDevice()->toString().c_str(), inputDesc->getPatchHandle());
             return inputDesc->getDevice();
@@ -5297,12 +5555,38 @@
     }
     /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
       and doesn't really need to.*/
-    DeviceVector speakerSafeDevices = devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
+    DeviceVector speakerSafeDevices = devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
     if (!speakerSafeDevices.isEmpty()) {
-        devices.merge(mAvailableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
+        devices.merge(mAvailableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
         devices.remove(speakerSafeDevices);
     }
-    return devices.types();
+    // FIXME: use DeviceTypeSet when Java layer is ready for it.
+    return deviceTypesToBitMask(devices.types());
+}
+
+status_t AudioPolicyManager::getDevicesForAttributes(
+        const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices) {
+    if (devices == nullptr) {
+        return BAD_VALUE;
+    }
+    // check dynamic policies but only for primary descriptors (secondary not used for audible
+    // audio routing, only used for duplication for playback capture)
+    sp<AudioPolicyMix> policyMix;
+    status_t status = mPolicyMixes.getOutputForAttr(attr, 0 /*uid unknown here*/,
+            AUDIO_OUTPUT_FLAG_NONE, policyMix, nullptr);
+    if (status != OK) {
+        return status;
+    }
+    if (policyMix != nullptr && policyMix->getOutput() != nullptr) {
+        AudioDeviceTypeAddr device(policyMix->mDeviceType, policyMix->mDeviceAddress.c_str());
+        devices->push_back(device);
+        return NO_ERROR;
+    }
+    DeviceVector curDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false);
+    for (const auto& device : curDevices) {
+        devices->push_back(device->getDeviceTypeAddr());
+    }
+    return NO_ERROR;
 }
 
 void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@@ -5362,7 +5646,7 @@
         auto ttsVolumeSource = toVolumeSource(AUDIO_STREAM_TTS);
         for (size_t i = 0; i < mOutputs.size(); i++) {
             sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-            setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, AUDIO_DEVICE_NONE);
+            setVolumeSourceMute(ttsVolumeSource, mute/*on*/, desc, 0 /*delay*/, DeviceTypeSet());
             const uint32_t latency = desc->latency() * 2;
             if (latency > maxLatency) {
                 maxLatency = latency;
@@ -5486,15 +5770,6 @@
     DeviceVector filteredDevices = outputDesc->filterSupportedDevices(devices);
     DeviceVector prevDevices = outputDesc->devices();
 
-    // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
-    // output profile or if new device is not supported AND previous device(s) is(are) still
-    // available (otherwise reset device must be done on the output)
-    if (!devices.isEmpty() && filteredDevices.isEmpty() &&
-            !mAvailableOutputDevices.filter(prevDevices).empty()) {
-        ALOGV("%s: unsupported device %s for output", __func__, devices.toString().c_str());
-        return 0;
-    }
-
     ALOGV("setOutputDevices() prevDevice %s", prevDevices.toString().c_str());
 
     if (!filteredDevices.isEmpty()) {
@@ -5509,6 +5784,17 @@
         muteWaitMs = 0;
     }
 
+    // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
+    // output profile or if new device is not supported AND previous device(s) is(are) still
+    // available (otherwise reset device must be done on the output)
+    if (!devices.isEmpty() && filteredDevices.isEmpty() &&
+            !mAvailableOutputDevices.filter(prevDevices).empty()) {
+        ALOGV("%s: unsupported device %s for output", __func__, devices.toString().c_str());
+        // restore previous device after evaluating strategy mute state
+        outputDesc->setDevices(prevDevices);
+        return muteWaitMs;
+    }
+
     // Do not change the routing if:
     //      the requested device is AUDIO_DEVICE_NONE
     //      OR the requested device is the same as current device
@@ -5561,10 +5847,10 @@
         return INVALID_OPERATION;
     }
     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-    status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs);
+    status_t status = mpClientInterface->releaseAudioPatch(patchDesc->getAfHandle(), delayMs);
     ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status);
     outputDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
-    removeAudioPatch(patchDesc->mHandle);
+    removeAudioPatch(patchDesc->getHandle());
     nextAudioPortGeneration();
     mpClientInterface->onAudioPatchListUpdate();
     return status;
@@ -5614,10 +5900,10 @@
         return INVALID_OPERATION;
     }
     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
-    status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
+    status_t status = mpClientInterface->releaseAudioPatch(patchDesc->getAfHandle(), 0);
     ALOGV("resetInputDevice() releaseAudioPatch returned %d", status);
     inputDesc->setPatchHandle(AUDIO_PATCH_HANDLE_NONE);
-    removeAudioPatch(patchDesc->mHandle);
+    removeAudioPatch(patchDesc->getHandle());
     nextAudioPortGeneration();
     mpClientInterface->onAudioPatchListUpdate();
     return status;
@@ -5681,9 +5967,9 @@
 float AudioPolicyManager::computeVolume(IVolumeCurves &curves,
                                         VolumeSource volumeSource,
                                         int index,
-                                        audio_devices_t device)
+                                        const DeviceTypeSet& deviceTypes)
 {
-    float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
+    float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(deviceTypes), index);
 
     // handle the case of accessibility active while a ringtone is playing: if the ringtone is much
     // louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
@@ -5699,7 +5985,7 @@
             && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
             mOutputs.isActive(ringVolumeSrc, 0)) {
         auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
-        const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, device);
+        const float ringVolumeDb = computeVolume(ringCurves, ringVolumeSrc, index, deviceTypes);
         return ringVolumeDb - 4 > volumeDb ? ringVolumeDb - 4 : volumeDb;
     }
 
@@ -5714,9 +6000,9 @@
              volumeSource == toVolumeSource(AUDIO_STREAM_DTMF) ||
              volumeSource == a11yVolumeSrc)) {
         auto &voiceCurves = getVolumeCurves(callVolumeSrc);
-        int voiceVolumeIndex = voiceCurves.getVolumeIndex(device);
+        int voiceVolumeIndex = voiceCurves.getVolumeIndex(deviceTypes);
         const float maxVoiceVolDb =
-                computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, device)
+                computeVolume(voiceCurves, callVolumeSrc, voiceVolumeIndex, deviceTypes)
                 + IN_CALL_EARPIECE_HEADROOM_DB;
         // FIXME: Workaround for call screening applications until a proper audio mode is defined
         // to support this scenario : Exempt the RING stream from the audio cap if the audio was
@@ -5742,9 +6028,10 @@
     // speaker is part of the select devices
     // - if music is playing, always limit the volume to current music volume,
     // with a minimum threshold at -36dB so that notification is always perceived.
-    if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                   AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
-                   AUDIO_DEVICE_OUT_USB_HEADSET | AUDIO_DEVICE_OUT_HEARING_AID)) &&
+    if (!Intersection(deviceTypes,
+            {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+             AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+             AUDIO_DEVICE_OUT_USB_HEADSET, AUDIO_DEVICE_OUT_HEARING_AID}).empty() &&
             ((volumeSource == alarmVolumeSrc ||
               volumeSource == ringVolumeSrc) ||
              (volumeSource == toVolumeSource(AUDIO_STREAM_NOTIFICATION)) ||
@@ -5759,31 +6046,33 @@
         if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
                 mLimitRingtoneVolume) {
             volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
-            audio_devices_t musicDevice =
+            DeviceTypeSet musicDevice =
                     mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
                                                            nullptr, true /*fromCache*/).types();
             auto &musicCurves = getVolumeCurves(AUDIO_STREAM_MUSIC);
-            float musicVolDb = computeVolume(musicCurves, musicVolumeSrc,
-                                             musicCurves.getVolumeIndex(musicDevice), musicDevice);
+            float musicVolDb = computeVolume(musicCurves,
+                                             musicVolumeSrc,
+                                             musicCurves.getVolumeIndex(musicDevice),
+                                             musicDevice);
             float minVolDb = (musicVolDb > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
                         musicVolDb : SONIFICATION_HEADSET_VOLUME_MIN_DB;
             if (volumeDb > minVolDb) {
                 volumeDb = minVolDb;
                 ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDb, musicVolDb);
             }
-            if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
-                          AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
+            if (!Intersection(deviceTypes, {AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}).empty()) {
                 // on A2DP, also ensure notification volume is not too low compared to media when
                 // intended to be played
                 if ((volumeDb > -96.0f) &&
                         (musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
-                    ALOGV("%s increasing volume for volume source=%d device=0x%X from %f to %f",
-                          __func__, volumeSource, device, volumeDb,
+                    ALOGV("%s increasing volume for volume source=%d device=%s from %f to %f",
+                          __func__, volumeSource, dumpDeviceTypes(deviceTypes).c_str(), volumeDb,
                           musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
                     volumeDb = musicVolDb - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
                 }
             }
-        } else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
+        } else if ((Volume::getDeviceForVolume(deviceTypes) != AUDIO_DEVICE_OUT_SPEAKER) ||
                    (!(volumeSource == alarmVolumeSrc || volumeSource == ringVolumeSrc))) {
             volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
         }
@@ -5822,7 +6111,7 @@
                                                VolumeSource volumeSource,
                                                int index,
                                                const sp<AudioOutputDescriptor>& outputDesc,
-                                               audio_devices_t device,
+                                               DeviceTypeSet deviceTypes,
                                                int delayMs,
                                                bool force)
 {
@@ -5848,17 +6137,20 @@
              volumeSource, forceUseForComm);
         return INVALID_OPERATION;
     }
-    if (device == AUDIO_DEVICE_NONE) {
-        device = outputDesc->devices().types();
+    if (deviceTypes.empty()) {
+        deviceTypes = outputDesc->devices().types();
     }
 
-    float volumeDb = computeVolume(curves, volumeSource, index, device);
-    if (outputDesc->isFixedVolume(device) ||
+    float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
+    if (outputDesc->isFixedVolume(deviceTypes) ||
             // Force VoIP volume to max for bluetooth SCO
-            ((isVoiceVolSrc || isBtScoVolSrc) && (device & AUDIO_DEVICE_OUT_ALL_SCO) != 0)) {
+
+            ((isVoiceVolSrc || isBtScoVolSrc) &&
+                    isSingleDeviceType(deviceTypes, audio_is_bluetooth_out_sco_device))) {
         volumeDb = 0.0f;
     }
-    outputDesc->setVolume(volumeDb, volumeSource, curves.getStreamTypes(), device, delayMs, force);
+    outputDesc->setVolume(
+            volumeDb, volumeSource, curves.getStreamTypes(), deviceTypes, delayMs, force);
 
     if (isVoiceVolSrc || isBtScoVolSrc) {
         float voiceVolume;
@@ -5877,15 +6169,16 @@
 }
 
 void AudioPolicyManager::applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
-                                                audio_devices_t device,
-                                                int delayMs,
-                                                bool force)
+                                            const DeviceTypeSet& deviceTypes,
+                                            int delayMs,
+                                            bool force)
 {
-    ALOGVV("applyStreamVolumes() for device %08x", device);
+    ALOGVV("applyStreamVolumes() for device %s", dumpDeviceTypes(deviceTypes).c_str());
     for (const auto &volumeGroup : mEngine->getVolumeGroups()) {
         auto &curves = getVolumeCurves(toVolumeSource(volumeGroup));
         checkAndSetVolume(curves, toVolumeSource(volumeGroup),
-                          curves.getVolumeIndex(device), outputDesc, device, delayMs, force);
+                          curves.getVolumeIndex(deviceTypes),
+                          outputDesc, deviceTypes, delayMs, force);
     }
 }
 
@@ -5893,7 +6186,7 @@
                                          bool on,
                                          const sp<AudioOutputDescriptor>& outputDesc,
                                          int delayMs,
-                                         audio_devices_t device)
+                                         DeviceTypeSet deviceTypes)
 {
     std::vector<VolumeSource> sourcesToMute;
     for (auto attributes: mEngine->getAllAttributesForProductStrategy(strategy)) {
@@ -5905,7 +6198,7 @@
         }
     }
     for (auto source : sourcesToMute) {
-        setVolumeSourceMute(source, on, outputDesc, delayMs, device);
+        setVolumeSourceMute(source, on, outputDesc, delayMs, deviceTypes);
     }
 
 }
@@ -5914,10 +6207,10 @@
                                              bool on,
                                              const sp<AudioOutputDescriptor>& outputDesc,
                                              int delayMs,
-                                             audio_devices_t device)
+                                             DeviceTypeSet deviceTypes)
 {
-    if (device == AUDIO_DEVICE_NONE) {
-        device = outputDesc->devices().types();
+    if (deviceTypes.empty()) {
+        deviceTypes = outputDesc->devices().types();
     }
     auto &curves = getVolumeCurves(volumeSource);
     if (on) {
@@ -5926,7 +6219,7 @@
                     (volumeSource != toVolumeSource(AUDIO_STREAM_ENFORCED_AUDIBLE) ||
                      (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) ==
                       AUDIO_POLICY_FORCE_NONE))) {
-                checkAndSetVolume(curves, volumeSource, 0, outputDesc, device, delayMs);
+                checkAndSetVolume(curves, volumeSource, 0, outputDesc, deviceTypes, delayMs);
             }
         }
         // increment mMuteCount after calling checkAndSetVolume() so that volume change is not
@@ -5939,9 +6232,9 @@
         }
         if (outputDesc->decMuteCount(volumeSource) == 0) {
             checkAndSetVolume(curves, volumeSource,
-                              curves.getVolumeIndex(device),
+                              curves.getVolumeIndex(deviceTypes),
                               outputDesc,
-                              device,
+                              deviceTypes,
                               delayMs);
         }
     }
@@ -5973,6 +6266,11 @@
     case AUDIO_USAGE_GAME:
     case AUDIO_USAGE_VIRTUAL_SOURCE:
     case AUDIO_USAGE_ASSISTANT:
+    case AUDIO_USAGE_CALL_ASSISTANT:
+    case AUDIO_USAGE_EMERGENCY:
+    case AUDIO_USAGE_SAFETY:
+    case AUDIO_USAGE_VEHICLE_STATUS:
+    case AUDIO_USAGE_ANNOUNCEMENT:
         break;
     default:
         return false;
@@ -5995,6 +6293,14 @@
     return is_state_in_call(state);
 }
 
+bool AudioPolicyManager::isCallAudioAccessible()
+{
+    audio_mode_t mode = mEngine->getPhoneState();
+    return (mode == AUDIO_MODE_IN_CALL)
+            || (mode == AUDIO_MODE_IN_COMMUNICATION)
+            || (mode == AUDIO_MODE_CALL_SCREEN);
+}
+
 void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc)
 {
     for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--)  {
@@ -6023,8 +6329,8 @@
             }
         }
         if (release) {
-            ALOGV("%s releasing patch %u", __FUNCTION__, patchDesc->mHandle);
-            releaseAudioPatch(patchDesc->mHandle, patchDesc->mUid);
+            ALOGV("%s releasing patch %u", __FUNCTION__, patchDesc->getHandle());
+            releaseAudioPatch(patchDesc->getHandle(), patchDesc->getUid());
         }
     }
 
@@ -6083,24 +6389,24 @@
         formatSet.insert(enforcedSurround.begin(), enforcedSurround.end());
     }
     for (const auto& format : formatSet) {
-        formatsPtr->push(format);
+        formatsPtr->push_back(format);
     }
 }
 
-void AudioPolicyManager::modifySurroundChannelMasks(ChannelsVector *channelMasksPtr) {
-    ChannelsVector &channelMasks = *channelMasksPtr;
+void AudioPolicyManager::modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr) {
+    ChannelMaskSet &channelMasks = *channelMasksPtr;
     audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
             AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
 
     // If NEVER, then remove support for channelMasks > stereo.
     if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
-        for (size_t maskIndex = 0; maskIndex < channelMasks.size(); ) {
-            audio_channel_mask_t channelMask = channelMasks[maskIndex];
+        for (auto it = channelMasks.begin(); it != channelMasks.end();) {
+            audio_channel_mask_t channelMask = *it;
             if (channelMask & ~AUDIO_CHANNEL_OUT_STEREO) {
                 ALOGI("%s: force NEVER, so remove channelMask 0x%08x", __FUNCTION__, channelMask);
-                channelMasks.removeAt(maskIndex);
+                it = channelMasks.erase(it);
             } else {
-                maskIndex++;
+                ++it;
             }
         }
     // If ALWAYS or MANUAL, then make sure we at least support 5.1
@@ -6116,7 +6422,7 @@
         }
         // If not then add 5.1 support.
         if (!supports5dot1) {
-            channelMasks.add(AUDIO_CHANNEL_OUT_5POINT1);
+            channelMasks.insert(AUDIO_CHANNEL_OUT_5POINT1);
             ALOGI("%s: force MANUAL or ALWAYS, so adding channelMask for 5.1 surround", __func__);
         }
     }
@@ -6145,12 +6451,12 @@
                 || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
             modifySurroundFormats(devDesc, &formats);
         }
-        profiles.setFormats(formats);
+        addProfilesForFormats(profiles, formats);
     }
 
     for (audio_format_t format : profiles.getSupportedFormats()) {
-        ChannelsVector channelMasks;
-        SampleRateVector samplingRates;
+        ChannelMaskSet channelMasks;
+        SampleRateSet samplingRates;
         AudioParameter requestedParameters;
         requestedParameters.addInt(String8(AudioParameter::keyFormat), format);
 
@@ -6181,7 +6487,8 @@
                 }
             }
         }
-        profiles.addProfileFromHal(new AudioProfile(format, channelMasks, samplingRates));
+        addDynamicAudioProfileAndSort(
+                profiles, new AudioProfile(format, channelMasks, samplingRates));
     }
 }
 
@@ -6198,7 +6505,7 @@
     status_t status = installPatch(
             caller, index, patchHandle, patch, delayMs, mUidCached, &patchDesc);
     if (status == NO_ERROR) {
-        ioDescriptor->setPatchHandle(patchDesc->mHandle);
+        ioDescriptor->setPatchHandle(patchDesc->getHandle());
     }
     return status;
 }
@@ -6215,7 +6522,7 @@
     audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
     if (index >= 0) {
         patchDesc = mAudioPatches.valueAt(index);
-        afPatchHandle = patchDesc->mAfPatchHandle;
+        afPatchHandle = patchDesc->getAfHandle();
     }
 
     status_t status = mpClientInterface->createAudioPatch(patch, &afPatchHandle, delayMs);
@@ -6224,13 +6531,13 @@
     if (status == NO_ERROR) {
         if (index < 0) {
             patchDesc = new AudioPatch(patch, uid);
-            addAudioPatch(patchDesc->mHandle, patchDesc);
+            addAudioPatch(patchDesc->getHandle(), patchDesc);
         } else {
             patchDesc->mPatch = *patch;
         }
-        patchDesc->mAfPatchHandle = afPatchHandle;
+        patchDesc->setAfHandle(afPatchHandle);
         if (patchHandle) {
-            *patchHandle = patchDesc->mHandle;
+            *patchHandle = patchDesc->getHandle();
         }
         nextAudioPortGeneration();
         mpClientInterface->onAudioPatchListUpdate();
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index dc548d6..b588f89 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -31,16 +31,14 @@
 #include <utils/SortedVector.h>
 #include <media/AudioParameter.h>
 #include <media/AudioPolicy.h>
+#include <media/AudioProfile.h>
 #include <media/PatchBuilder.h>
 #include "AudioPolicyInterface.h"
 
-#include <AudioPolicyManagerInterface.h>
 #include <AudioPolicyManagerObserver.h>
-#include <AudioGain.h>
 #include <AudioPolicyConfig.h>
-#include <AudioPort.h>
+#include <PolicyAudioPort.h>
 #include <AudioPatch.h>
-#include <AudioProfile.h>
 #include <DeviceDescriptor.h>
 #include <IOProfile.h>
 #include <HwModule.h>
@@ -49,6 +47,7 @@
 #include <AudioPolicyMix.h>
 #include <EffectDescriptor.h>
 #include <SoundTriggerSession.h>
+#include "EngineLibrary.h"
 #include "TypeConverter.h"
 
 namespace android {
@@ -122,7 +121,8 @@
                                   audio_output_flags_t *flags,
                                   audio_port_handle_t *selectedDeviceId,
                                   audio_port_handle_t *portId,
-                                  std::vector<audio_io_handle_t> *secondaryOutputs) override;
+                                  std::vector<audio_io_handle_t> *secondaryOutputs,
+                                  output_type_t *outputType) override;
         virtual status_t startOutput(audio_port_handle_t portId);
         virtual status_t stopOutput(audio_port_handle_t portId);
         virtual void releaseOutput(audio_port_handle_t portId);
@@ -177,7 +177,7 @@
                                      IVolumeCurves &volumeCurves);
 
         status_t getVolumeIndex(const IVolumeCurves &curves, int &index,
-                                audio_devices_t device) const;
+                                const DeviceTypeSet& deviceTypes) const;
 
         // return the strategy corresponding to a given stream type
         virtual uint32_t getStrategyForStream(audio_stream_type_t stream)
@@ -193,6 +193,10 @@
         // return the enabled output devices for the given stream type
         virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
 
+        virtual status_t getDevicesForAttributes(
+                const audio_attributes_t &attributes,
+                AudioDeviceTypeAddrVector *devices);
+
         virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc = NULL);
         virtual status_t registerEffect(const effect_descriptor_t *desc,
                                         audio_io_handle_t io,
@@ -234,7 +238,10 @@
         virtual status_t getAudioPort(struct audio_port *port);
         virtual status_t createAudioPatch(const struct audio_patch *patch,
                                            audio_patch_handle_t *handle,
-                                           uid_t uid);
+                                           uid_t uid) {
+            return createAudioPatchInternal(patch, handle, uid);
+        }
+
         virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
                                               uid_t uid);
         virtual status_t listAudioPatches(unsigned int *num_patches,
@@ -258,6 +265,15 @@
         virtual status_t setUidDeviceAffinities(uid_t uid,
                 const Vector<AudioDeviceTypeAddr>& devices);
         virtual status_t removeUidDeviceAffinities(uid_t uid);
+        virtual status_t setUserIdDeviceAffinities(int userId,
+                const Vector<AudioDeviceTypeAddr>& devices);
+        virtual status_t removeUserIdDeviceAffinities(int userId);
+
+        virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device);
+        virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
+        virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device);
 
         virtual status_t startAudioSource(const struct audio_port_config *source,
                                           const audio_attributes_t *attributes,
@@ -279,7 +295,7 @@
         virtual status_t getHwOffloadEncodingFormatsSupportedForA2DP(
                     std::vector<audio_format_t> *formats);
 
-        virtual void setAppState(uid_t uid, app_state_t state);
+        virtual void setAppState(audio_port_handle_t portId, app_state_t state);
 
         virtual bool isHapticPlaybackSupported();
 
@@ -307,6 +323,12 @@
             return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
         }
 
+        bool isCallScreenModeSupported() override;
+
+        void onNewAudioModulesAvailable() override;
+
+        status_t initialize();
+
 protected:
         // A constructor that allows more fine-grained control over initialization process,
         // used in automatic tests.
@@ -321,7 +343,6 @@
         //   - initialize.
         AudioPolicyConfig& getConfig() { return mConfig; }
         void loadConfig();
-        status_t initialize();
 
         // From AudioPolicyManagerObserver
         virtual const AudioPatchCollection &getAudioPatches() const
@@ -422,7 +443,7 @@
         virtual float computeVolume(IVolumeCurves &curves,
                                     VolumeSource volumeSource,
                                     int index,
-                                    audio_devices_t device);
+                                    const DeviceTypeSet& deviceTypes);
 
         // rescale volume index from srcStream within range of dstStream
         int rescaleVolumeIndex(int srcIndex,
@@ -432,12 +453,13 @@
         virtual status_t checkAndSetVolume(IVolumeCurves &curves,
                                            VolumeSource volumeSource, int index,
                                            const sp<AudioOutputDescriptor>& outputDesc,
-                                           audio_devices_t device,
+                                           DeviceTypeSet deviceTypes,
                                            int delayMs = 0, bool force = false);
 
         // apply all stream volumes to the specified output and device
         void applyStreamVolumes(const sp<AudioOutputDescriptor>& outputDesc,
-                                audio_devices_t device, int delayMs = 0, bool force = false);
+                                const DeviceTypeSet& deviceTypes,
+                                int delayMs = 0, bool force = false);
 
         /**
          * @brief setStrategyMute Mute or unmute all active clients on the considered output
@@ -452,7 +474,7 @@
                              bool on,
                              const sp<AudioOutputDescriptor>& outputDesc,
                              int delayMs = 0,
-                             audio_devices_t device = AUDIO_DEVICE_NONE);
+                             DeviceTypeSet deviceTypes = DeviceTypeSet());
 
         /**
          * @brief setVolumeSourceMute Mute or unmute the volume source on the specified output
@@ -467,7 +489,7 @@
                                  bool on,
                                  const sp<AudioOutputDescriptor>& outputDesc,
                                  int delayMs = 0,
-                                 audio_devices_t device = AUDIO_DEVICE_NONE);
+                                 DeviceTypeSet deviceTypes = DeviceTypeSet());
 
         audio_mode_t getPhoneState();
 
@@ -475,6 +497,8 @@
         virtual bool isInCall();
         // true if given state represents a device in a telephony or VoIP call
         virtual bool isStateInCall(int state);
+        // true if playback to call TX or capture from call RX is possible
+        bool isCallAudioAccessible();
 
         // when a device is connected, checks if an open output can be routed
         // to this device. If none is open, tries to open one of the available outputs.
@@ -495,13 +519,19 @@
         // close an input.
         void closeInput(audio_io_handle_t input);
 
-        // runs all the checks required for accomodating changes in devices and outputs
+        // runs all the checks required for accommodating changes in devices and outputs
         // if 'onOutputsChecked' callback is provided, it is executed after the outputs
         // check via 'checkOutputForAllStrategies'. If the callback returns 'true',
         // A2DP suspend status is rechecked.
         void checkForDeviceAndOutputChanges(std::function<bool()> onOutputsChecked = nullptr);
 
         /**
+         * @brief updates routing for all outputs (including call if call in progress).
+         * @param delayMs delay for unmuting if required
+         */
+        void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0);
+
+        /**
          * @brief checkOutputForAttributes checks and if necessary changes outputs used for the
          * given audio attributes.
          * must be called every time a condition that affects the output choice for a given
@@ -646,16 +676,13 @@
         }
         String8 getFirstDeviceAddress(const DeviceVector &devices) const
         {
-            return (devices.size() > 0) ? devices.itemAt(0)->address() : String8("");
+            return (devices.size() > 0) ?
+                    String8(devices.itemAt(0)->address().c_str()) : String8("");
         }
 
         uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);
         sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device,
                                             uint32_t delayMs);
-        sp<DeviceDescriptor> findDevice(
-                const DeviceVector& devices, audio_devices_t device) const;
-        audio_devices_t getModuleDeviceTypes(
-                const DeviceVector& devices, const char *moduleId) const;
         bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
 
         status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
@@ -704,6 +731,8 @@
         SwAudioOutputCollection mPreviousOutputs;
         AudioInputCollection mInputs;     // list of input descriptors
 
+        DeviceVector  mOutputDevicesAll; // all output devices from the config
+        DeviceVector  mInputDevicesAll;  // all input devices from the config
         DeviceVector  mAvailableOutputDevices; // all available output devices
         DeviceVector  mAvailableInputDevices;  // all available input devices
 
@@ -714,9 +743,8 @@
 
         EffectDescriptorCollection mEffects;  // list of registered audio effects
         sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
-        HwModuleCollection mHwModules; // contains only modules that have been loaded successfully
-        HwModuleCollection mHwModulesAll; // normally not needed, used during construction and for
-                                          // dumps
+        HwModuleCollection mHwModules; // contains modules that have been loaded successfully
+        HwModuleCollection mHwModulesAll; // contains all modules declared in the config
 
         AudioPolicyConfig mConfig;
 
@@ -752,7 +780,7 @@
         uint32_t nextAudioPortGeneration();
 
         // Audio Policy Engine Interface.
-        AudioPolicyManagerInterface *mEngine;
+        EngineInstance mEngine;
 
         // Surround formats that are enabled manually. Taken into account when
         // "encoded surround" is forced into "manual" mode.
@@ -760,9 +788,11 @@
 
         std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
 private:
+        void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
+
         // Add or remove AC3 DTS encodings based on user preferences.
         void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
-        void modifySurroundChannelMasks(ChannelsVector *channelMasksPtr);
+        void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
 
         // Support for Multi-Stream Decoder (MSD) module
         sp<DeviceDescriptor> getMsdAudioInDevice() const;
@@ -807,7 +837,8 @@
                 audio_output_flags_t *flags,
                 audio_port_handle_t *selectedDeviceId,
                 bool *isRequestedDeviceForExclusiveUse,
-                std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
+                std::vector<sp<AudioPolicyMix>> *secondaryMixes,
+                output_type_t *outputType);
         // internal method to return the output handle for the given device and format
         audio_io_handle_t getOutputForDevices(
                 const DeviceVector &devices,
@@ -817,6 +848,16 @@
                 audio_output_flags_t *flags,
                 bool forceMutingHaptic = false);
 
+        // Internal method checking if a direct output can be opened matching the requested
+        // attributes, flags, config and devices.
+        // If NAME_NOT_FOUND is returned, an attempt can be made to open a mixed output.
+        status_t openDirectOutput(
+                audio_stream_type_t stream,
+                audio_session_t session,
+                const audio_config_t *config,
+                audio_output_flags_t flags,
+                const DeviceVector &devices,
+                audio_io_handle_t *output);
         /**
          * @brief getInputForDevice selects an input handle for a given input device and
          * requester context
@@ -849,6 +890,8 @@
                                              const char *device_address,
                                              const char *device_name,
                                              audio_format_t encodedFormat);
+        status_t setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+                                             audio_policy_dev_state_t state);
 
         void setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
                                       audio_policy_dev_state_t state);
@@ -858,6 +901,29 @@
             param.addInt(String8(AudioParameter::keyMonoOutput), (int)mMasterMono);
             mpClientInterface->setParameters(output, param.toString());
         }
+
+        /**
+         * @brief createAudioPatchInternal internal function to manage audio patch creation
+         * @param[in] patch structure containing sink and source ports configuration
+         * @param[out] handle patch handle to be provided if patch installed correctly
+         * @param[in] uid of the client
+         * @param[in] delayMs if required
+         * @param[in] sourceDesc [optional] in case of external source, source client to be
+         * configured by the patch, i.e. assigning an Output (HW or SW)
+         * @return NO_ERROR if patch installed correctly, error code otherwise.
+         */
+        status_t createAudioPatchInternal(const struct audio_patch *patch,
+                                          audio_patch_handle_t *handle,
+                                          uid_t uid, uint32_t delayMs = 0,
+                                          const sp<SourceClientDescriptor>& sourceDesc = nullptr);
+        /**
+         * @brief releaseAudioPatchInternal internal function to remove an audio patch
+         * @param[in] handle of the patch to be removed
+         * @param[in] delayMs if required
+         * @return NO_ERROR if patch removed correctly, error code otherwise.
+         */
+        status_t releaseAudioPatchInternal(audio_patch_handle_t handle, uint32_t delayMs = 0);
+
         status_t installPatch(const char *caller,
                 audio_patch_handle_t *patchHandle,
                 AudioIODescriptorInterface *ioDescriptor,
@@ -871,7 +937,11 @@
                 uid_t uid,
                 sp<AudioPatch> *patchDescPtr);
 
-        void cleanUpEffectsForIo(audio_io_handle_t io);
+        bool areAllDevicesSupported(
+                const Vector<AudioDeviceTypeAddr>& devices,
+                std::function<bool(audio_devices_t)> predicate,
+                const char* context);
+
 };
 
 };
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
new file mode 100644
index 0000000..ef699aa
--- /dev/null
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 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_TAG "APM_EngineLoader"
+
+#include <dlfcn.h>
+#include <utils/Log.h>
+
+#include "EngineLibrary.h"
+
+namespace android {
+
+// static
+std::shared_ptr<EngineLibrary> EngineLibrary::load(std::string libraryPath)
+{
+    std::shared_ptr<EngineLibrary> engLib(new EngineLibrary());
+    return engLib->init(std::move(libraryPath)) ? engLib : nullptr;
+}
+
+EngineLibrary::~EngineLibrary()
+{
+    close();
+}
+
+bool EngineLibrary::init(std::string libraryPath)
+{
+    mLibraryHandle = dlopen(libraryPath.c_str(), 0);
+    if (mLibraryHandle == nullptr) {
+        ALOGE("Could not dlopen %s: %s", libraryPath.c_str(), dlerror());
+        return false;
+    }
+    mCreateEngineInstance = (EngineInterface* (*)())dlsym(mLibraryHandle, "createEngineInstance");
+    mDestroyEngineInstance = (void (*)(EngineInterface*))dlsym(
+            mLibraryHandle, "destroyEngineInstance");
+    if (mCreateEngineInstance == nullptr || mDestroyEngineInstance == nullptr) {
+        ALOGE("Could not find engine interface functions in %s", libraryPath.c_str());
+        close();
+        return false;
+    }
+    ALOGD("Loaded engine from %s", libraryPath.c_str());
+    return true;
+}
+
+EngineInstance EngineLibrary::createEngine()
+{
+    if (mCreateEngineInstance == nullptr || mDestroyEngineInstance == nullptr) {
+        return EngineInstance();
+    }
+    return EngineInstance(mCreateEngineInstance(),
+            [lib = shared_from_this(), destroy = mDestroyEngineInstance] (EngineInterface* e) {
+                destroy(e);
+            });
+}
+
+void EngineLibrary::close()
+{
+    if (mLibraryHandle != nullptr) {
+        dlclose(mLibraryHandle);
+    }
+    mLibraryHandle = nullptr;
+    mCreateEngineInstance = nullptr;
+    mDestroyEngineInstance = nullptr;
+}
+
+}  // namespace android
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
new file mode 100644
index 0000000..f143916
--- /dev/null
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <EngineInterface.h>
+
+namespace android {
+
+using EngineInstance = std::unique_ptr<EngineInterface, std::function<void (EngineInterface*)>>;
+
+class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
+public:
+    static std::shared_ptr<EngineLibrary> load(std::string libraryPath);
+    ~EngineLibrary();
+
+    EngineLibrary(const EngineLibrary&) = delete;
+    EngineLibrary(EngineLibrary&&) = delete;
+    EngineLibrary& operator=(const EngineLibrary&) = delete;
+    EngineLibrary& operator=(EngineLibrary&&) = delete;
+
+    EngineInstance createEngine();
+
+private:
+    EngineLibrary() = default;
+    bool init(std::string libraryPath);
+    void close();
+
+    void *mLibraryHandle = nullptr;
+    EngineInterface* (*mCreateEngineInstance)() = nullptr;
+    void (*mDestroyEngineInstance)(EngineInterface*) = nullptr;
+};
+
+}  // namespace android
diff --git a/services/audiopolicy/service/Android.mk b/services/audiopolicy/service/Android.mk
index c4f4c56..680b077 100644
--- a/services/audiopolicy/service/Android.mk
+++ b/services/audiopolicy/service/Android.mk
@@ -6,7 +6,8 @@
     AudioPolicyService.cpp \
     AudioPolicyEffects.cpp \
     AudioPolicyInterfaceImpl.cpp \
-    AudioPolicyClientImpl.cpp
+    AudioPolicyClientImpl.cpp \
+    CaptureStateNotifier.cpp
 
 LOCAL_C_INCLUDES := \
     frameworks/av/services/audioflinger \
@@ -24,13 +25,15 @@
     libbinder \
     libaudioclient \
     libaudioutils \
+    libaudiofoundation \
     libhardware_legacy \
     libaudiopolicymanager \
     libmedia_helper \
     libmediametrics \
     libmediautils \
     libeffectsconfig \
-    libsensorprivacy
+    libsensorprivacy \
+    capture_state_listener-aidl-cpp
 
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
     libsensorprivacy
@@ -38,12 +41,10 @@
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents
 
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
 LOCAL_MODULE:= libaudiopolicyservice
 
 LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -Wall -Werror -Wthread-safety
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index d51cc6e..9fa7a53 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -17,10 +17,12 @@
 #define LOG_TAG "AudioPolicyClientImpl"
 //#define LOG_NDEBUG 0
 
-#include <soundtrigger/SoundTrigger.h>
-#include <utils/Log.h>
 #include "AudioPolicyService.h"
 
+#include <utils/Log.h>
+
+#include "BinderProxy.h"
+
 namespace android {
 
 /* implementation of the client interface from the policy manager */
@@ -39,8 +41,7 @@
 status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
                                                            audio_io_handle_t *output,
                                                            audio_config_t *config,
-                                                           audio_devices_t *devices,
-                                                           const String8& address,
+                                                           const sp<DeviceDescriptorBase>& device,
                                                            uint32_t *latencyMs,
                                                            audio_output_flags_t flags)
 {
@@ -49,7 +50,7 @@
         ALOGW("%s: could not get AudioFlinger", __func__);
         return PERMISSION_DENIED;
     }
-    return af->openOutput(module, output, config, devices, address, latencyMs, flags);
+    return af->openOutput(module, output, config, device, latencyMs, flags);
 }
 
 audio_io_handle_t AudioPolicyService::AudioPolicyClient::openDuplicateOutput(
@@ -240,4 +241,9 @@
     return AudioSystem::newAudioUniqueId(use);
 }
 
+void AudioPolicyService::AudioPolicyClient::setSoundTriggerCaptureState(bool active)
+{
+    mAudioPolicyService->mCaptureStateNotifier.setCaptureState(active);
+}
+
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 4947714..1ec0c5e 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -42,7 +42,10 @@
 AudioPolicyEffects::AudioPolicyEffects()
 {
     status_t loadResult = loadAudioEffectXmlConfig();
-    if (loadResult < 0) {
+    if (loadResult == NO_ERROR) {
+        mDefaultDeviceEffectFuture = std::async(
+                    std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
+    } else if (loadResult < 0) {
         ALOGW("Failed to load XML effect configuration, fallback to .conf");
         // load automatic audio effect modules
         if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
@@ -562,7 +565,8 @@
     AUDIO_STREAM_BLUETOOTH_SCO_TAG,
     AUDIO_STREAM_ENFORCED_AUDIBLE_TAG,
     AUDIO_STREAM_DTMF_TAG,
-    AUDIO_STREAM_TTS_TAG
+    AUDIO_STREAM_TTS_TAG,
+    AUDIO_STREAM_ASSISTANT_TAG
 };
 
 // returns the audio_stream_t enum corresponding to the output stream name or
@@ -907,8 +911,27 @@
             streams.add(stream.type, effectDescs.release());
         }
     };
+
+    auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
+        for (auto& deviceProcess : processingChain) {
+
+            auto effectDescs = std::make_unique<EffectDescVector>();
+            for (auto& effect : deviceProcess.effects) {
+                effectDescs->mEffects.add(
+                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+            }
+            auto deviceEffects = std::make_unique<DeviceEffects>(
+                        std::move(effectDescs), deviceProcess.type, deviceProcess.address);
+            devicesEffects.emplace(deviceProcess.address, std::move(deviceEffects));
+        }
+    };
+
     loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
     loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+    {
+        Mutex::Autolock _l(mLock);
+        loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
+    }
     // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
     return result.nbSkippedElement;
 }
@@ -941,5 +964,32 @@
     return NO_ERROR;
 }
 
+void AudioPolicyEffects::initDefaultDeviceEffects()
+{
+    Mutex::Autolock _l(mLock);
+    for (const auto& deviceEffectsIter : mDeviceEffects) {
+        const auto& deviceEffects =  deviceEffectsIter.second;
+        for (const auto& effectDesc : deviceEffects->mEffectDescriptors->mEffects) {
+            auto fx = std::make_unique<AudioEffect>(
+                        EFFECT_UUID_NULL, String16("android"), &effectDesc->mUuid, 0, nullptr,
+                        nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
+                        AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
+                                            deviceEffects->getDeviceAddress()});
+            status_t status = fx->initCheck();
+            if (status != NO_ERROR && status != ALREADY_EXISTS) {
+                ALOGE("%s(): failed to create Fx %s on port type=%d address=%s", __func__,
+                      effectDesc->mName, deviceEffects->getDeviceType(),
+                      deviceEffects->getDeviceAddress().c_str());
+                // fx goes out of scope and strong ref on AudioEffect is released
+                continue;
+            }
+            fx->setEnabled(true);
+            ALOGV("%s(): create Fx %s added on port type=%d address=%s", __func__,
+                  effectDesc->mName, deviceEffects->getDeviceType(),
+                  deviceEffects->getDeviceAddress().c_str());
+            deviceEffects->mEffects.push_back(std::move(fx));
+        }
+    }
+}
 
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index dcf093b..81c728d 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -25,6 +25,9 @@
 #include <system/audio.h>
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
+#include <android-base/thread_annotations.h>
+
+#include <future>
 
 namespace android {
 
@@ -104,6 +107,7 @@
     status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
 private:
+    void initDefaultDeviceEffects();
 
     // class to store the description of an effects and its parameters
     // as defined in audio_effects.conf
@@ -192,6 +196,28 @@
         Vector< sp<AudioEffect> >mEffects;
     };
 
+    /**
+     * @brief The DeviceEffects class stores the effects associated to a given Device Port.
+     */
+    class DeviceEffects {
+    public:
+        DeviceEffects(std::unique_ptr<EffectDescVector> effectDescriptors,
+                               audio_devices_t device, const std::string& address) :
+            mEffectDescriptors(std::move(effectDescriptors)),
+            mDeviceType(device), mDeviceAddress(address) {}
+        /*virtual*/ ~DeviceEffects() = default;
+
+        std::vector<std::unique_ptr<AudioEffect>> mEffects;
+        audio_devices_t getDeviceType() const { return mDeviceType; }
+        std::string getDeviceAddress() const { return mDeviceAddress; }
+        const std::unique_ptr<EffectDescVector> mEffectDescriptors;
+
+    private:
+        const audio_devices_t mDeviceType;
+        const std::string mDeviceAddress;
+
+    };
+
 
     static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
     static audio_source_t inputSourceNameToEnum(const char *name);
@@ -237,6 +263,19 @@
     KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
     // Automatic output effects are unique for audiosession ID
     KeyedVector< audio_session_t, EffectVector* > mOutputSessions;
+
+    /**
+     * @brief mDeviceEffects map of device effects indexed by the device address
+     */
+    std::map<std::string, std::unique_ptr<DeviceEffects>> mDeviceEffects GUARDED_BY(mLock);
+
+    /**
+     * Device Effect initialization must be asynchronous: the audio_policy service parses and init
+     * effect on first reference. AudioFlinger will handle effect creation and register these
+     * effect on audio_policy service.
+     * We must store the reference of the furture garantee real asynchronous operation.
+     */
+    std::future<void> mDefaultDeviceEffectFuture;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 20e1c9e..34d07b6 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -19,15 +19,61 @@
 
 #include "AudioPolicyService.h"
 #include "TypeConverter.h"
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetricsItem.h>
 #include <media/AudioPolicy.h>
 #include <utils/Log.h>
 
 namespace android {
 
+const std::vector<audio_usage_t>& SYSTEM_USAGES = {
+    AUDIO_USAGE_CALL_ASSISTANT,
+    AUDIO_USAGE_EMERGENCY,
+    AUDIO_USAGE_SAFETY,
+    AUDIO_USAGE_VEHICLE_STATUS,
+    AUDIO_USAGE_ANNOUNCEMENT
+};
+
+bool isSystemUsage(audio_usage_t usage) {
+    return std::find(std::begin(SYSTEM_USAGES), std::end(SYSTEM_USAGES), usage)
+        != std::end(SYSTEM_USAGES);
+}
+
+bool AudioPolicyService::isSupportedSystemUsage(audio_usage_t usage) {
+    return std::find(std::begin(mSupportedSystemUsages), std::end(mSupportedSystemUsages), usage)
+        != std::end(mSupportedSystemUsages);
+}
+
+status_t AudioPolicyService::validateUsage(audio_usage_t usage) {
+     return validateUsage(usage, IPCThreadState::self()->getCallingPid(),
+        IPCThreadState::self()->getCallingUid());
+}
+
+status_t AudioPolicyService::validateUsage(audio_usage_t usage, pid_t pid, uid_t uid) {
+    if (isSystemUsage(usage)) {
+        if (isSupportedSystemUsage(usage)) {
+            if (!modifyAudioRoutingAllowed(pid, uid)) {
+                ALOGE("permission denied: modify audio routing not allowed for uid %d", uid);
+                return PERMISSION_DENIED;
+            }
+        } else {
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
+
 
 // ----------------------------------------------------------------------------
 
+void AudioPolicyService::doOnNewAudioModulesAvailable()
+{
+    if (mAudioPolicyManager == NULL) return;
+    Mutex::Autolock _l(mLock);
+    AutoCallerClear acc;
+    mAudioPolicyManager->onNewAudioModulesAvailable();
+}
+
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
                                                   const char *device_address,
@@ -83,7 +129,7 @@
                                                          device_name, encodedFormat);
 }
 
-status_t AudioPolicyService::setPhoneState(audio_mode_t state)
+status_t AudioPolicyService::setPhoneState(audio_mode_t state, uid_t uid)
 {
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
@@ -107,6 +153,7 @@
     AutoCallerClear acc;
     mAudioPolicyManager->setPhoneState(state);
     mPhoneState = state;
+    mPhoneStateOwnerUid = uid;
     return NO_ERROR;
 }
 
@@ -181,13 +228,19 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
-    ALOGV("getOutputForAttr()");
+
+    status_t result = validateUsage(attr->usage, pid, uid);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    ALOGV("%s()", __func__);
     Mutex::Autolock _l(mLock);
 
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     if (!isAudioServerOrMediaServerUid(callingUid) || uid == (uid_t)-1) {
         ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
-                "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
+                "%s uid %d tried to pass itself off as %d", __func__, callingUid, uid);
         uid = callingUid;
     }
     if (!mPackageManager.allowPlaybackCapture(uid)) {
@@ -197,32 +250,44 @@
             && !bypassInterruptionPolicyAllowed(pid, uid)) {
         attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
     }
-    audio_output_flags_t originalFlags = flags;
     AutoCallerClear acc;
-    status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+    AudioPolicyInterface::output_type_t outputType;
+    result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
                                                  config,
                                                  &flags, selectedDeviceId, portId,
-                                                 secondaryOutputs);
+                                                 secondaryOutputs,
+                                                 &outputType);
 
     // FIXME: Introduce a way to check for the the telephony device before opening the output
-    if ((result == NO_ERROR) &&
-        (flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) &&
-        !modifyPhoneStateAllowed(pid, uid)) {
-        // If the app tries to play music through the telephony device and doesn't have permission
-        // the fallback to the default output device.
-        mAudioPolicyManager->releaseOutput(*portId);
-        flags = originalFlags;
-        *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-        *portId = AUDIO_PORT_HANDLE_NONE;
-        secondaryOutputs->clear();
-        result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, config,
-                                                       &flags, selectedDeviceId, portId,
-                                                       secondaryOutputs);
+    if (result == NO_ERROR) {
+        // enforce permission (if any) required for each type of input
+        switch (outputType) {
+        case AudioPolicyInterface::API_OUTPUT_LEGACY:
+            break;
+        case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
+            if (!modifyPhoneStateAllowed(pid, uid)) {
+                ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
+                    __func__, uid);
+                result = PERMISSION_DENIED;
+            }
+            break;
+        case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
+            if (!modifyAudioRoutingAllowed(pid, uid)) {
+                ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
+                    __func__, uid);
+                result = PERMISSION_DENIED;
+            }
+            break;
+        case AudioPolicyInterface::API_OUTPUT_INVALID:
+        default:
+            LOG_ALWAYS_FATAL("%s() encountered an invalid output type %d",
+                __func__, (int)outputType);
+        }
     }
 
     if (result == NO_ERROR) {
         sp <AudioPlaybackClient> client =
-            new AudioPlaybackClient(*attr, *output, uid, pid, session, *selectedDeviceId, *stream);
+            new AudioPlaybackClient(*attr, *output, uid, pid, session, *portId, *selectedDeviceId, *stream);
         mAudioPlaybackClients.add(*portId, client);
     }
     return result;
@@ -351,12 +416,22 @@
         return NO_INIT;
     }
 
+    status_t result = validateUsage(attr->usage, pid, uid);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    audio_source_t inputSource = attr->source;
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
+    }
+
     // already checked by client, but double-check in case the client wrapper is bypassed
-    if ((attr->source < AUDIO_SOURCE_DEFAULT)
-            || (attr->source >= AUDIO_SOURCE_CNT
-                && attr->source != AUDIO_SOURCE_HOTWORD
-                && attr->source != AUDIO_SOURCE_FM_TUNER
-                && attr->source != AUDIO_SOURCE_ECHO_REFERENCE)) {
+    if ((inputSource < AUDIO_SOURCE_DEFAULT)
+            || (inputSource >= AUDIO_SOURCE_CNT
+                && inputSource != AUDIO_SOURCE_HOTWORD
+                && inputSource != AUDIO_SOURCE_FM_TUNER
+                && inputSource != AUDIO_SOURCE_ECHO_REFERENCE)) {
         return BAD_VALUE;
     }
 
@@ -377,24 +452,27 @@
         pid = callingPid;
     }
 
-    // check calling permissions
-    if (!recordingAllowed(opPackageName, pid, uid)) {
+    // check calling permissions.
+    // Capturing from FM_TUNER source is controlled by captureAudioOutputAllowed() only as this
+    // does not affect users privacy as does capturing from an actual microphone.
+    if (!(recordingAllowed(opPackageName, pid, uid) || attr->source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, uid, pid);
         return PERMISSION_DENIED;
     }
 
     bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
-    if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
-        attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
-        attr->source == AUDIO_SOURCE_VOICE_CALL ||
-        attr->source == AUDIO_SOURCE_ECHO_REFERENCE) &&
+    if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
+        inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
+        inputSource == AUDIO_SOURCE_VOICE_CALL ||
+        inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
+        inputSource == AUDIO_SOURCE_FM_TUNER) &&
         !canCaptureOutput) {
         return PERMISSION_DENIED;
     }
 
     bool canCaptureHotword = captureHotwordAllowed(opPackageName, pid, uid);
-    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
+    if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
         return BAD_VALUE;
     }
 
@@ -431,7 +509,7 @@
                 }
                 break;
             case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
-                if (!modifyAudioRoutingAllowed()) {
+                if (!modifyAudioRoutingAllowed(pid, uid)) {
                     ALOGE("getInputForAttr() permission denied: modify audio routing not allowed");
                     status = PERMISSION_DENIED;
                 }
@@ -451,7 +529,7 @@
             return status;
         }
 
-        sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session,
+        sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session, *portId,
                                                              *selectedDeviceId, opPackageName,
                                                              canCaptureOutput, canCaptureHotword);
         mAudioRecordClients.add(*portId, client);
@@ -459,7 +537,7 @@
 
     if (audioPolicyEffects != 0) {
         // create audio pre processors according to input source
-        status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
+        status_t status = audioPolicyEffects->addInputEffects(*input, inputSource, session);
         if (status != NO_ERROR && status != ALREADY_EXISTS) {
             ALOGW("Failed to add effects on input %d", *input);
         }
@@ -494,7 +572,8 @@
     }
 
     // check calling permissions
-    if (!startRecording(client->opPackageName, client->pid, client->uid)) {
+    if (!(startRecording(client->opPackageName, client->pid, client->uid)
+            || client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
         ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
                 __func__, client->uid, client->pid);
         return PERMISSION_DENIED;
@@ -514,7 +593,7 @@
     }
 
     // including successes gets very verbose
-    // but once we cut over to westworld, log them all.
+    // but once we cut over to statsd, log them all.
     if (status != NO_ERROR) {
 
         static constexpr char kAudioPolicy[] = "audiopolicy";
@@ -532,7 +611,7 @@
         static constexpr char kAudioPolicyActiveDevice[] =
                 "android.media.audiopolicy.active.device";
 
-        MediaAnalyticsItem *item = MediaAnalyticsItem::create(kAudioPolicy);
+        mediametrics::Item *item = mediametrics::Item::create(kAudioPolicy);
         if (item != NULL) {
 
             item->setInt32(kAudioPolicyStatus, status);
@@ -785,6 +864,17 @@
     return mAudioPolicyManager->getDevicesForStream(stream);
 }
 
+status_t AudioPolicyService::getDevicesForAttributes(const AudioAttributes &aa,
+                                                     AudioDeviceTypeAddrVector *devices) const
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    AutoCallerClear acc;
+    return mAudioPolicyManager->getDevicesForAttributes(aa.getAttributes(), devices);
+}
+
 audio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor_t *desc)
 {
     // FIXME change return type to status_t, and return NO_INIT here
@@ -970,6 +1060,22 @@
     return audioPolicyEffects->removeStreamDefaultEffect(id);
 }
 
+status_t AudioPolicyService::setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages) {
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    bool areAllSystemUsages = std::all_of(begin(systemUsages), end(systemUsages),
+        [](audio_usage_t usage) { return isSystemUsage(usage); });
+    if (!areAllSystemUsages) {
+        return BAD_VALUE;
+    }
+
+    mSupportedSystemUsages = systemUsages;
+    return NO_ERROR;
+}
+
 status_t AudioPolicyService::setAllowedCapturePolicy(uid_t uid, audio_flags_mask_t capturePolicy) {
     Mutex::Autolock _l(mLock);
     if (mAudioPolicyManager == NULL) {
@@ -996,6 +1102,12 @@
         ALOGV("mAudioPolicyManager == NULL");
         return false;
     }
+
+    status_t result = validateUsage(attributes.usage);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
     Mutex::Autolock _l(mLock);
     return mAudioPolicyManager->isDirectOutputSupported(config, attributes);
 }
@@ -1112,14 +1224,27 @@
         return PERMISSION_DENIED;
     }
 
+    // If one of the mixes has needCaptureVoiceCommunicationOutput set to true, then we
+    // need to verify that the caller still has CAPTURE_VOICE_COMMUNICATION_OUTPUT
+    bool needCaptureVoiceCommunicationOutput =
+        std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
+            return mix.mVoiceCommunicationCaptureAllowed; });
+
     bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
             return mix.mAllowPrivilegedPlaybackCapture; });
+
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+
     if (needCaptureMediaOutput && !captureMediaOutputAllowed(callingPid, callingUid)) {
         return PERMISSION_DENIED;
     }
 
+    if (needCaptureVoiceCommunicationOutput &&
+        !captureVoiceCommunicationOutputAllowed(callingPid, callingUid)) {
+        return PERMISSION_DENIED;
+    }
+
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
@@ -1156,6 +1281,31 @@
     return mAudioPolicyManager->removeUidDeviceAffinities(uid);
 }
 
+status_t AudioPolicyService::setUserIdDeviceAffinities(int userId,
+        const Vector<AudioDeviceTypeAddr>& devices) {
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    AutoCallerClear acc;
+    return mAudioPolicyManager->setUserIdDeviceAffinities(userId, devices);
+}
+
+status_t AudioPolicyService::removeUserIdDeviceAffinities(int userId) {
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    AutoCallerClear acc;
+    return mAudioPolicyManager->removeUserIdDeviceAffinities(userId);
+}
+
 status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
                                               const audio_attributes_t *attributes,
                                               audio_port_handle_t *portId)
@@ -1164,6 +1314,12 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
+
+    status_t result = validateUsage(attributes->usage);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
     // startAudioSource should be created as the calling uid
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     AutoCallerClear acc;
@@ -1264,6 +1420,13 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyService::setCurrentImeUid(uid_t uid)
+{
+    Mutex::Autolock _l(mLock);
+    mUidPolicy->setCurrentImeUid(uid);
+    return NO_ERROR;
+}
+
 bool AudioPolicyService::isHapticPlaybackSupported()
 {
     if (mAudioPolicyManager == NULL) {
@@ -1320,4 +1483,52 @@
     return NO_ERROR;
 }
 
+bool AudioPolicyService::isCallScreenModeSupported()
+{
+    if (mAudioPolicyManager == NULL) {
+        ALOGW("%s, mAudioPolicyManager == NULL", __func__);
+        return false;
+    }
+    Mutex::Autolock _l(mLock);
+    AutoCallerClear acc;
+    return mAudioPolicyManager->isCallScreenModeSupported();
+}
+
+status_t AudioPolicyService::setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->setPreferredDeviceForStrategy(strategy, device);
+}
+
+status_t AudioPolicyService::removePreferredDeviceForStrategy(product_strategy_t strategy)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->removePreferredDeviceForStrategy(strategy);
+}
+
+status_t AudioPolicyService::getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->getPreferredDeviceForStrategy(strategy, device);
+}
+
+status_t AudioPolicyService::registerSoundTriggerCaptureStateListener(
+    const sp<media::ICaptureStateListener>& listener,
+    bool* result)
+{
+    *result = mCaptureStateNotifier.RegisterListener(listener);
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6cda20..e847f9f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -29,7 +29,6 @@
 #include <utils/Log.h>
 #include <cutils/properties.h>
 #include <binder/IPCThreadState.h>
-#include <binder/ActivityManager.h>
 #include <binder/PermissionController.h>
 #include <binder/IResultReceiver.h>
 #include <utils/String16.h>
@@ -58,9 +57,11 @@
 // ----------------------------------------------------------------------------
 
 AudioPolicyService::AudioPolicyService()
-    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
-      mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
-{
+    : BnAudioPolicyService(),
+      mAudioPolicyManager(NULL),
+      mAudioPolicyClient(NULL),
+      mPhoneState(AUDIO_MODE_INVALID),
+      mCaptureStateNotifier(false) {
 }
 
 void AudioPolicyService::onFirstRef()
@@ -77,17 +78,17 @@
         mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
     }
     // load audio processing modules
-    sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
+    sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
+    sp<UidPolicy> uidPolicy = new UidPolicy(this);
+    sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
     {
         Mutex::Autolock _l(mLock);
         mAudioPolicyEffects = audioPolicyEffects;
+        mUidPolicy = uidPolicy;
+        mSensorPrivacyPolicy = sensorPrivacyPolicy;
     }
-
-    mUidPolicy = new UidPolicy(this);
-    mUidPolicy->registerSelf();
-
-    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
-    mSensorPrivacyPolicy->registerSelf();
+    uidPolicy->registerSelf();
+    sensorPrivacyPolicy->registerSelf();
 }
 
 AudioPolicyService::~AudioPolicyService()
@@ -102,9 +103,9 @@
     mAudioPolicyEffects.clear();
 
     mUidPolicy->unregisterSelf();
-    mUidPolicy.clear();
-
     mSensorPrivacyPolicy->unregisterSelf();
+
+    mUidPolicy.clear();
     mSensorPrivacyPolicy.clear();
 }
 
@@ -167,20 +168,20 @@
 // removeNotificationClient() is called when the client process dies.
 void AudioPolicyService::removeNotificationClient(uid_t uid, pid_t pid)
 {
+    bool hasSameUid = false;
     {
         Mutex::Autolock _l(mNotificationClientsLock);
         int64_t token = ((int64_t)uid<<32) | pid;
         mNotificationClients.removeItem(token);
-    }
-    {
-        Mutex::Autolock _l(mLock);
-        bool hasSameUid = false;
         for (size_t i = 0; i < mNotificationClients.size(); i++) {
             if (mNotificationClients.valueAt(i)->uid() == uid) {
                 hasSameUid = true;
                 break;
             }
         }
+    }
+    {
+        Mutex::Autolock _l(mLock);
         if (mAudioPolicyManager && !hasSameUid) {
             // called from binder death notification: no need to clear caller identity
             mAudioPolicyManager->releaseResourcesForUid(uid);
@@ -376,10 +377,14 @@
             IPCThreadState::self()->getCallingPid());
 }
 
-static bool dumpTryLock(Mutex& mutex)
+static bool dumpTryLock(Mutex& mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
 {
-    status_t err = mutex.timedLock(kDumpLockTimeoutNs);
-    return err == NO_ERROR;
+    return mutex.timedLock(kDumpLockTimeoutNs) == NO_ERROR;
+}
+
+static void dumpReleaseLock(Mutex& mutex, bool locked) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
+{
+    if (locked) mutex.unlock();
 }
 
 status_t AudioPolicyService::dumpInternals(int fd)
@@ -393,6 +398,14 @@
     snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
     result.append(buffer);
 
+    snprintf(buffer, SIZE, "Supported System Usages:\n");
+    result.append(buffer);
+    for (std::vector<audio_usage_t>::iterator it = mSupportedSystemUsages.begin();
+        it != mSupportedSystemUsages.end(); ++it) {
+        snprintf(buffer, SIZE, "\t%d\n", *it);
+        result.append(buffer);
+    }
+
     write(fd, result.string(), result.size());
     return NO_ERROR;
 }
@@ -407,8 +420,7 @@
 {
 //    Go over all active clients and allow capture (does not force silence) in the
 //    following cases:
-//    Another client in the same UID has already been allowed to capture
-//    OR The client is the assistant
+//    The client is the assistant
 //        AND an accessibility service is on TOP or a RTT call is active
 //                AND the source is VOICE_RECOGNITION or HOTWORD
 //            OR uses VOICE_RECOGNITION AND is on TOP
@@ -424,26 +436,37 @@
 //        AND is on TOP
 //        AND the source is VOICE_RECOGNITION or HOTWORD
 //    OR the client source is virtual (remote submix, call audio TX or RX...)
+//    OR the client source is HOTWORD
+//        AND is on TOP
+//            OR all active clients are using HOTWORD source
+//        AND no call is active
+//            OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//    OR the client is the current InputMethodService
+//        AND a RTT call is active AND the source is VOICE_RECOGNITION
 //    OR Any client
 //        AND The assistant is not on TOP
 //        AND is on TOP or latest started
 //        AND there is no active privacy sensitive capture or call
 //            OR client has CAPTURE_AUDIO_OUTPUT privileged permission
 
+
     sp<AudioRecordClient> topActive;
     sp<AudioRecordClient> latestActive;
+    sp<AudioRecordClient> topSensitiveActive;
     sp<AudioRecordClient> latestSensitiveActive;
 
     nsecs_t topStartNs = 0;
     nsecs_t latestStartNs = 0;
+    nsecs_t topSensitiveStartNs = 0;
     nsecs_t latestSensitiveStartNs = 0;
     bool isA11yOnTop = mUidPolicy->isA11yOnTop();
     bool isAssistantOnTop = false;
     bool isSensitiveActive = false;
     bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
-    bool rttCallActive =
-            (mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
+    bool isInCommunication = mPhoneState == AUDIO_MODE_IN_COMMUNICATION;
+    bool rttCallActive = (isInCall || isInCommunication)
             && mUidPolicy->isRttEnabled();
+    bool onlyHotwordActive = true;
 
     // if Sensor Privacy is enabled then all recordings should be silenced.
     if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -464,42 +487,71 @@
             continue;
         }
 
-        bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
         bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
-        if (appState == APP_STATE_TOP && !isAccessibility) {
-            if (current->startTimeNs > topStartNs) {
-                topActive = current;
-                topStartNs = current->startTimeNs;
+        // Clients capturing for Accessibility services are not considered
+        // for top or latest active to avoid masking regular clients started before
+        if (!isAccessibility) {
+            bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
+            bool isPrivacySensitive =
+                    (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
+            if (appState == APP_STATE_TOP) {
+                if (isPrivacySensitive) {
+                    if (current->startTimeNs > topSensitiveStartNs) {
+                        topSensitiveActive = current;
+                        topSensitiveStartNs = current->startTimeNs;
+                    }
+                } else {
+                    if (current->startTimeNs > topStartNs) {
+                        topActive = current;
+                        topStartNs = current->startTimeNs;
+                    }
+                }
+                if (isAssistant) {
+                    isAssistantOnTop = true;
+                }
             }
-            if (isAssistant) {
-                isAssistantOnTop = true;
+            // Clients capturing for HOTWORD are not considered
+            // for latest active to avoid masking regular clients started before
+            if (!(current->attributes.source == AUDIO_SOURCE_HOTWORD
+                    || ((isA11yOnTop || rttCallActive) && isAssistant))) {
+                if (isPrivacySensitive) {
+                    if (current->startTimeNs > latestSensitiveStartNs) {
+                        latestSensitiveActive = current;
+                        latestSensitiveStartNs = current->startTimeNs;
+                    }
+                    isSensitiveActive = true;
+                } else {
+                    if (current->startTimeNs > latestStartNs) {
+                        latestActive = current;
+                        latestStartNs = current->startTimeNs;
+                    }
+                }
             }
         }
-        // Assistant capturing for HOTWORD or Accessibility services not considered
-        // for latest active to avoid masking regular clients started before
-        if (current->startTimeNs > latestStartNs
-                && !((current->attributes.source == AUDIO_SOURCE_HOTWORD
-                        || isA11yOnTop || rttCallActive)
-                    && isAssistant)
-                && !isAccessibility) {
-            latestActive = current;
-            latestStartNs = current->startTimeNs;
-        }
-        if (isPrivacySensitiveSource(current->attributes.source)) {
-            if (current->startTimeNs > latestSensitiveStartNs) {
-                latestSensitiveActive = current;
-                latestSensitiveStartNs = current->startTimeNs;
-            }
-            isSensitiveActive = true;
+        if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
+            onlyHotwordActive = false;
         }
     }
 
     // if no active client with UI on Top, consider latest active as top
     if (topActive == nullptr) {
         topActive = latestActive;
+        topStartNs = latestStartNs;
+    }
+    if (topSensitiveActive == nullptr) {
+        topSensitiveActive = latestSensitiveActive;
+        topSensitiveStartNs = latestSensitiveStartNs;
     }
 
-    std::vector<uid_t> enabledUids;
+    // If both privacy sensitive and regular capture are active:
+    //  if the regular capture is privileged
+    //    allow concurrency
+    //  else
+    //    favor the privacy sensitive case
+    if (topActive != nullptr && topSensitiveActive != nullptr
+            && !topActive->canCaptureOutput) {
+        topActive = nullptr;
+    }
 
     for (size_t i =0; i < mAudioRecordClients.size(); i++) {
         sp<AudioRecordClient> current = mAudioRecordClients[i];
@@ -507,17 +559,21 @@
             continue;
         }
 
-        // keep capture allowed if another client with the same UID has already
-        // been allowed to capture
-        if (std::find(enabledUids.begin(), enabledUids.end(), current->uid)
-                != enabledUids.end()) {
-            continue;
-        }
-
         audio_source_t source = current->attributes.source;
         bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
-        bool isLatestSensitive = latestSensitiveActive == nullptr ?
-                                 false : current->uid == latestSensitiveActive->uid;
+        bool isTopOrLatestSensitive = topSensitiveActive == nullptr ?
+                                 false : current->uid == topSensitiveActive->uid;
+
+        auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
+            bool canCaptureCall = recordClient->canCaptureOutput;
+            return !(isInCall && !canCaptureCall);
+//TODO(b/160260850): restore restriction to mode owner once fix for misbehaving apps is merged
+//            bool canCaptureCommunication = recordClient->canCaptureOutput
+//                || recordClient->uid == mPhoneStateOwnerUid
+//                || isServiceUid(mPhoneStateOwnerUid);
+//            return !(isInCall && !canCaptureCall)
+//                && !(isInCommunication && !canCaptureCommunication);
+        };
 
         // By default allow capture if:
         //     The assistant is not on TOP
@@ -525,9 +581,10 @@
         //     AND there is no active privacy sensitive capture or call
         //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
         bool allowCapture = !isAssistantOnTop
-                && ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
-                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
-                && !(isInCall && !current->canCaptureOutput);
+                && (isTopOrLatestActive || isTopOrLatestSensitive)
+                && !(isSensitiveActive
+                    && !(isTopOrLatestSensitive || current->canCaptureOutput))
+                && canCaptureIfInCallOrCommunication(current);
 
         if (isVirtualSource(source)) {
             // Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -546,36 +603,48 @@
                 }
             } else {
                 if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
-                        source == AUDIO_SOURCE_HOTWORD) &&
-                        (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+                        source == AUDIO_SOURCE_HOTWORD)
+                        && !(isSensitiveActive && !current->canCaptureOutput)
+                        && canCaptureIfInCallOrCommunication(current)) {
                     allowCapture = true;
                 }
             }
         } else if (mUidPolicy->isA11yUid(current->uid)) {
             // For accessibility service allow capture if:
-            //     Is on TOP
-            //          AND the source is VOICE_RECOGNITION or HOTWORD
-            //     Or
-            //          The assistant is not on TOP
-            //          AND there is no active privacy sensitive capture or call
+            //     The assistant is not on TOP
+            //         AND there is no active privacy sensitive capture or call
             //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //     OR
+            //         Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
+            if (!isAssistantOnTop
+                    && !(isSensitiveActive && !current->canCaptureOutput)
+                    && canCaptureIfInCallOrCommunication(current)) {
+                allowCapture = true;
+            }
             if (isA11yOnTop) {
                 if (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD) {
                     allowCapture = true;
                 }
-            } else {
-                if (!isAssistantOnTop
-                        && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
-                    allowCapture = true;
-                }
+            }
+        } else if (source == AUDIO_SOURCE_HOTWORD) {
+            // For HOTWORD source allow capture when not on TOP if:
+            //     All active clients are using HOTWORD source
+            //     AND no call is active
+            //         OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            if (onlyHotwordActive
+                    && canCaptureIfInCallOrCommunication(current)) {
+                allowCapture = true;
+            }
+        } else if (mUidPolicy->isCurrentImeUid(current->uid)) {
+            // For current InputMethodService allow capture if:
+            //     A RTT call is active AND the source is VOICE_RECOGNITION
+            if (rttCallActive && source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+                allowCapture = true;
             }
         }
-        setAppState_l(current->uid,
+        setAppState_l(current->portId,
                       allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(current->uid)) :
                                 APP_STATE_IDLE);
-        if (allowCapture) {
-            enabledUids.push_back(current->uid);
-        }
     }
 }
 
@@ -583,7 +652,7 @@
     for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
         sp<AudioRecordClient> current = mAudioRecordClients[i];
         if (!isVirtualSource(current->attributes.source)) {
-            setAppState_l(current->uid, APP_STATE_IDLE);
+            setAppState_l(current->portId, APP_STATE_IDLE);
         }
     }
 }
@@ -601,19 +670,6 @@
 }
 
 /* static */
-bool AudioPolicyService::isPrivacySensitiveSource(audio_source_t source)
-{
-    switch (source) {
-        case AUDIO_SOURCE_CAMCORDER:
-        case AUDIO_SOURCE_VOICE_COMMUNICATION:
-            return true;
-        default:
-            break;
-    }
-    return false;
-}
-
-/* static */
 bool AudioPolicyService::isVirtualSource(audio_source_t source)
 {
     switch (source) {
@@ -622,6 +678,7 @@
         case AUDIO_SOURCE_VOICE_CALL:
         case AUDIO_SOURCE_REMOTE_SUBMIX:
         case AUDIO_SOURCE_FM_TUNER:
+        case AUDIO_SOURCE_ECHO_REFERENCE:
             return true;
         default:
             break;
@@ -629,17 +686,17 @@
     return false;
 }
 
-void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
+void AudioPolicyService::setAppState_l(audio_port_handle_t portId, app_state_t state)
 {
     AutoCallerClear acc;
 
     if (mAudioPolicyManager) {
-        mAudioPolicyManager->setAppState(uid, state);
+        mAudioPolicyManager->setAppState(portId, state);
     }
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
     if (af) {
         bool silenced = state == APP_STATE_IDLE;
-        af->setRecordSilenced(uid, silenced);
+        af->setRecordSilenced(portId, silenced);
     }
 }
 
@@ -648,7 +705,7 @@
     if (!dumpAllowed()) {
         dumpPermissionDenial(fd);
     } else {
-        bool locked = dumpTryLock(mLock);
+        const bool locked = dumpTryLock(mLock);
         if (!locked) {
             String8 result(kDeadlockedString);
             write(fd, result.string(), result.size());
@@ -665,7 +722,7 @@
 
         mPackageManager.dump(fd);
 
-        if (locked) mLock.unlock();
+        dumpReleaseLock(mLock, locked);
     }
     return NO_ERROR;
 }
@@ -784,8 +841,16 @@
         return BAD_VALUE;
     }
 
-    mUidPolicy->addOverrideUid(uid, active);
-    return NO_ERROR;
+    sp<UidPolicy> uidPolicy;
+    {
+        Mutex::Autolock _l(mLock);
+        uidPolicy = mUidPolicy;
+    }
+    if (uidPolicy) {
+        uidPolicy->addOverrideUid(uid, active);
+        return NO_ERROR;
+    }
+    return NO_INIT;
 }
 
 status_t AudioPolicyService::handleResetUidState(Vector<String16>& args, int err) {
@@ -805,8 +870,16 @@
         return BAD_VALUE;
     }
 
-    mUidPolicy->removeOverrideUid(uid);
-    return NO_ERROR;
+    sp<UidPolicy> uidPolicy;
+    {
+        Mutex::Autolock _l(mLock);
+        uidPolicy = mUidPolicy;
+    }
+    if (uidPolicy) {
+        uidPolicy->removeOverrideUid(uid);
+        return NO_ERROR;
+    }
+    return NO_INIT;
 }
 
 status_t AudioPolicyService::handleGetUidState(Vector<String16>& args, int out, int err) {
@@ -826,11 +899,15 @@
         return BAD_VALUE;
     }
 
-    if (mUidPolicy->isUidActive(uid)) {
-        return dprintf(out, "active\n");
-    } else {
-        return dprintf(out, "idle\n");
+    sp<UidPolicy> uidPolicy;
+    {
+        Mutex::Autolock _l(mLock);
+        uidPolicy = mUidPolicy;
     }
+    if (uidPolicy) {
+        return dprintf(out, uidPolicy->isUidActive(uid) ? "active\n" : "idle\n");
+    }
+    return NO_INIT;
 }
 
 status_t AudioPolicyService::printHelp(int out) {
@@ -844,28 +921,26 @@
 // -----------  AudioPolicyService::UidPolicy implementation ----------
 
 void AudioPolicyService::UidPolicy::registerSelf() {
-    ActivityManager am;
-    am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+    status_t res = mAm.linkToDeath(this);
+    mAm.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
             | ActivityManager::UID_OBSERVER_IDLE
             | ActivityManager::UID_OBSERVER_ACTIVE
             | ActivityManager::UID_OBSERVER_PROCSTATE,
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("audioserver"));
-    status_t res = am.linkToDeath(this);
     if (!res) {
         Mutex::Autolock _l(mLock);
         mObserverRegistered = true;
     } else {
         ALOGE("UidPolicy::registerSelf linkToDeath failed: %d", res);
 
-        am.unregisterUidObserver(this);
+        mAm.unregisterUidObserver(this);
     }
 }
 
 void AudioPolicyService::UidPolicy::unregisterSelf() {
-    ActivityManager am;
-    am.unlinkToDeath(this);
-    am.unregisterUidObserver(this);
+    mAm.unlinkToDeath(this);
+    mAm.unregisterUidObserver(this);
     Mutex::Autolock _l(mLock);
     mObserverRegistered = false;
 }
@@ -978,7 +1053,8 @@
 
 void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
                                                       int32_t procState,
-                                                      int64_t procStateSeq __unused) {
+                                                      int64_t procStateSeq __unused,
+                                                      int32_t capability __unused) {
     if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) {
         updateUid(&mCachedUids, uid, true, procState, true);
     }
@@ -1043,8 +1119,7 @@
 
 bool AudioPolicyService::UidPolicy::isA11yOnTop() {
     for (const auto &uid : mCachedUids) {
-        std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid.first);
-        if (it == mA11yUids.end()) {
+        if (!isA11yUid(uid.first)) {
             continue;
         }
         if (uid.second.second >= ActivityManager::PROCESS_STATE_TOP
@@ -1281,6 +1356,16 @@
                         mLock.lock();
                     }
                     } break;
+                case AUDIO_MODULES_UPDATE: {
+                    ALOGV("AudioCommandThread() processing audio modules update");
+                    svc = mService.promote();
+                    if (svc == 0) {
+                        break;
+                    }
+                    mLock.unlock();
+                    svc->doOnNewAudioModulesAvailable();
+                    mLock.lock();
+                    } break;
 
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -1339,7 +1424,7 @@
     result.append(buffer);
     write(fd, result.string(), result.size());
 
-    bool locked = dumpTryLock(mLock);
+    const bool locked = dumpTryLock(mLock);
     if (!locked) {
         String8 result2(kCmdDeadlockedString);
         write(fd, result2.string(), result2.size());
@@ -1362,7 +1447,7 @@
 
     write(fd, result.string(), result.size());
 
-    if (locked) mLock.unlock();
+    dumpReleaseLock(mLock, locked);
 
     return NO_ERROR;
 }
@@ -1570,6 +1655,13 @@
     sendCommand(command);
 }
 
+void AudioPolicyService::AudioCommandThread::audioModulesUpdateCommand()
+{
+    sp<AudioCommand> command = new AudioCommand();
+    command->mCommand = AUDIO_MODULES_UPDATE;
+    sendCommand(command);
+}
+
 status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
 {
     {
@@ -1817,6 +1909,11 @@
     mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
 }
 
+void AudioPolicyService::onNewAudioModulesAvailable()
+{
+    mOutputCommandThread->audioModulesUpdateCommand();
+}
+
 
 extern "C" {
 audio_module_handle_t aps_load_hw_module(void *service __unused,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e467f70..869a963 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -17,12 +17,14 @@
 #ifndef ANDROID_AUDIOPOLICYSERVICE_H
 #define ANDROID_AUDIOPOLICYSERVICE_H
 
+#include <android-base/thread_annotations.h>
 #include <cutils/misc.h>
 #include <cutils/config_utils.h>
 #include <cutils/compiler.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
+#include <binder/ActivityManager.h>
 #include <binder/BinderService.h>
 #include <binder/IUidObserver.h>
 #include <system/audio.h>
@@ -33,6 +35,7 @@
 #include <media/AudioPolicy.h>
 #include <mediautils/ServiceUtilities.h>
 #include "AudioPolicyEffects.h"
+#include "CaptureStateNotifier.h"
 #include <AudioPolicyInterface.h>
 #include <android/hardware/BnSensorPrivacyListener.h>
 
@@ -59,6 +62,7 @@
     // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
     //
 
+    void onNewAudioModulesAvailable() override;
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
                                               const char *device_address,
@@ -71,7 +75,7 @@
                                               const char *device_address,
                                               const char *device_name,
                                               audio_format_t encodedFormat);
-    virtual status_t setPhoneState(audio_mode_t state);
+    virtual status_t setPhoneState(audio_mode_t state, uid_t uid);
     virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
     virtual audio_io_handle_t getOutput(audio_stream_type_t stream);
@@ -126,6 +130,8 @@
 
     virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
     virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
+    virtual status_t getDevicesForAttributes(const AudioAttributes &aa,
+                                             AudioDeviceTypeAddrVector *devices) const;
 
     virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc);
     virtual status_t registerEffect(const effect_descriptor_t *desc,
@@ -184,6 +190,7 @@
                                      audio_io_handle_t output,
                                      int delayMs = 0);
     virtual status_t setVoiceVolume(float volume, int delayMs = 0);
+    status_t setSupportedSystemUsages(const std::vector<audio_usage_t>& systemUsages);
     status_t setAllowedCapturePolicy(uint_t uid, audio_flags_mask_t capturePolicy) override;
     virtual bool isOffloadSupported(const audio_offload_info_t &config);
     virtual bool isDirectOutputSupported(const audio_config_base_t& config,
@@ -223,6 +230,18 @@
 
     virtual status_t removeUidDeviceAffinities(uid_t uid);
 
+    virtual status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   const AudioDeviceTypeAddr &device);
+
+    virtual status_t removePreferredDeviceForStrategy(product_strategy_t strategy);
+
+
+    virtual status_t getPreferredDeviceForStrategy(product_strategy_t strategy,
+                                                   AudioDeviceTypeAddr &device);
+    virtual status_t setUserIdDeviceAffinities(int userId, const Vector<AudioDeviceTypeAddr>& devices);
+
+    virtual status_t removeUserIdDeviceAffinities(int userId);
+
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId);
@@ -244,6 +263,7 @@
 
     virtual status_t setAssistantUid(uid_t uid);
     virtual status_t setA11yServicesUids(const std::vector<uid_t>& uids);
+    virtual status_t setCurrentImeUid(uid_t uid);
 
     virtual bool     isHapticPlaybackSupported();
 
@@ -256,8 +276,15 @@
     virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
                                                        volume_group_t &volumeGroup);
 
+    status_t registerSoundTriggerCaptureStateListener(
+        const sp<media::ICaptureStateListener>& listener,
+        bool* result) override;
+
     virtual status_t setRttEnabled(bool enabled);
 
+            bool isCallScreenModeSupported() override;
+
+            void doOnNewAudioModulesAvailable();
             status_t doStopOutput(audio_port_handle_t portId);
             void doReleaseOutput(audio_port_handle_t portId);
 
@@ -304,13 +331,13 @@
                         AudioPolicyService() ANDROID_API;
     virtual             ~AudioPolicyService();
 
-            status_t dumpInternals(int fd);
+            status_t dumpInternals(int fd) REQUIRES(mLock);
 
     // Handles binder shell commands
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
     // Sets whether the given UID records only silence
-    virtual void setAppState_l(uid_t uid, app_state_t state);
+    virtual void setAppState_l(audio_port_handle_t portId, app_state_t state) REQUIRES(mLock);
 
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(Vector<String16>& args, int err);
@@ -330,12 +357,15 @@
 
     app_state_t apmStatFromAmState(int amState);
 
+    bool isSupportedSystemUsage(audio_usage_t usage);
+    status_t validateUsage(audio_usage_t usage);
+    status_t validateUsage(audio_usage_t usage, pid_t pid, uid_t uid);
+
     void updateUidStates();
-    void updateUidStates_l();
+    void updateUidStates_l() REQUIRES(mLock);
 
-    void silenceAllRecordings_l();
+    void silenceAllRecordings_l() REQUIRES(mLock);
 
-    static bool isPrivacySensitiveSource(audio_source_t source);
     static bool isVirtualSource(audio_source_t source);
 
     // If recording we need to make sure the UID is allowed to do that. If the UID is idle
@@ -348,7 +378,7 @@
     public:
         explicit UidPolicy(wp<AudioPolicyService> service)
                 : mService(service), mObserverRegistered(false),
-                  mAssistantUid(0), mRttEnabled(false) {}
+                  mAssistantUid(0), mCurrentImeUid(0), mRttEnabled(false) {}
 
         void registerSelf();
         void unregisterSelf();
@@ -363,6 +393,8 @@
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
         bool isA11yUid(uid_t uid);
         bool isA11yOnTop();
+        void setCurrentImeUid(uid_t uid) { mCurrentImeUid = uid; }
+        bool isCurrentImeUid(uid_t uid) { return uid == mCurrentImeUid; }
         void setRttEnabled(bool enabled) { mRttEnabled = enabled; }
         bool isRttEnabled() { return mRttEnabled; }
 
@@ -370,7 +402,8 @@
         void onUidActive(uid_t uid) override;
         void onUidGone(uid_t uid, bool disabled) override;
         void onUidIdle(uid_t uid, bool disabled) override;
-        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq);
+        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
+                int32_t capability);
 
         void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
         void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
@@ -387,12 +420,14 @@
 
         wp<AudioPolicyService> mService;
         Mutex mLock;
-        bool mObserverRegistered;
+        ActivityManager mAm;
+        bool mObserverRegistered = false;
         std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
         std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
-        uid_t mAssistantUid;
+        uid_t mAssistantUid = -1;
         std::vector<uid_t> mA11yUids;
-        bool mRttEnabled;
+        uid_t mCurrentImeUid = -1;
+        bool mRttEnabled = false;
     };
 
     // If sensor privacy is enabled then all apps, including those that are active, should be
@@ -413,7 +448,7 @@
 
         private:
             wp<AudioPolicyService> mService;
-            std::atomic_bool mSensorPrivacyEnabled;
+            std::atomic_bool mSensorPrivacyEnabled = false;
     };
 
     // Thread used to send audio config commands to audio flinger
@@ -439,6 +474,7 @@
             DYN_POLICY_MIX_STATE_UPDATE,
             RECORDING_CONFIGURATION_UPDATE,
             SET_EFFECT_SUSPENDED,
+            AUDIO_MODULES_UPDATE,
         };
 
         AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -484,6 +520,7 @@
                     void        setEffectSuspendedCommand(int effectId,
                                                           audio_session_t sessionId,
                                                           bool suspended);
+                    void        audioModulesUpdateCommand();
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
     private:
         class AudioCommandData;
@@ -620,8 +657,7 @@
         virtual status_t openOutput(audio_module_handle_t module,
                                     audio_io_handle_t *output,
                                     audio_config_t *config,
-                                    audio_devices_t *devices,
-                                    const String8& address,
+                                    const sp<DeviceDescriptorBase>& device,
                                     uint32_t *latencyMs,
                                     audio_output_flags_t flags);
         // creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by
@@ -705,6 +741,8 @@
 
         virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
 
+        void setSoundTriggerCaptureState(bool active) override;
+
      private:
         AudioPolicyService *mAudioPolicyService;
     };
@@ -757,9 +795,10 @@
     public:
                 AudioClient(const audio_attributes_t attributes,
                             const audio_io_handle_t io, uid_t uid, pid_t pid,
-                            const audio_session_t session, const audio_port_handle_t deviceId) :
+                            const audio_session_t session,  audio_port_handle_t portId,
+                            const audio_port_handle_t deviceId) :
                                 attributes(attributes), io(io), uid(uid), pid(pid),
-                                session(session), deviceId(deviceId), active(false) {}
+                                session(session), portId(portId), deviceId(deviceId), active(false) {}
                 ~AudioClient() override = default;
 
 
@@ -768,6 +807,7 @@
         const uid_t uid;                     // client UID
         const pid_t pid;                     // client PID
         const audio_session_t session;       // audio session ID
+        const audio_port_handle_t portId;
         const audio_port_handle_t deviceId;  // selected input device port ID
               bool active;                   // Playback/Capture is active or inactive
     };
@@ -779,10 +819,10 @@
     public:
                 AudioRecordClient(const audio_attributes_t attributes,
                           const audio_io_handle_t io, uid_t uid, pid_t pid,
-                          const audio_session_t session, const audio_port_handle_t deviceId,
-                          const String16& opPackageName,
+                          const audio_session_t session, audio_port_handle_t portId,
+                          const audio_port_handle_t deviceId, const String16& opPackageName,
                           bool canCaptureOutput, bool canCaptureHotword) :
-                    AudioClient(attributes, io, uid, pid, session, deviceId),
+                    AudioClient(attributes, io, uid, pid, session, portId, deviceId),
                     opPackageName(opPackageName), startTimeNs(0),
                     canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
                 ~AudioRecordClient() override = default;
@@ -800,9 +840,9 @@
     public:
                 AudioPlaybackClient(const audio_attributes_t attributes,
                       const audio_io_handle_t io, uid_t uid, pid_t pid,
-                            const audio_session_t session, audio_port_handle_t deviceId,
-                            audio_stream_type_t stream) :
-                    AudioClient(attributes, io, uid, pid, session, deviceId), stream(stream) {}
+                            const audio_session_t session, audio_port_handle_t portId,
+                            audio_port_handle_t deviceId, audio_stream_type_t stream) :
+                    AudioClient(attributes, io, uid, pid, session, portId, deviceId), stream(stream) {}
                 ~AudioPlaybackClient() override = default;
 
         const audio_stream_type_t stream;
@@ -841,26 +881,31 @@
     // and possibly back in to audio policy service and acquire mEffectsLock.
     sp<AudioCommandThread> mAudioCommandThread;     // audio commands thread
     sp<AudioCommandThread> mOutputCommandThread;    // process stop and release output
-    struct audio_policy_device *mpAudioPolicyDev;
-    struct audio_policy *mpAudioPolicy;
     AudioPolicyInterface *mAudioPolicyManager;
     AudioPolicyClient *mAudioPolicyClient;
+    std::vector<audio_usage_t> mSupportedSystemUsages;
 
-    DefaultKeyedVector< int64_t, sp<NotificationClient> >    mNotificationClients;
-    Mutex mNotificationClientsLock;  // protects mNotificationClients
+    Mutex mNotificationClientsLock;
+    DefaultKeyedVector<int64_t, sp<NotificationClient>> mNotificationClients
+        GUARDED_BY(mNotificationClientsLock);
     // Manage all effects configured in audio_effects.conf
     // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
     // those can call back into AudioPolicyService methods and try to acquire the mutex
-    sp<AudioPolicyEffects> mAudioPolicyEffects;
-    audio_mode_t mPhoneState;
+    sp<AudioPolicyEffects> mAudioPolicyEffects GUARDED_BY(mLock);
+    audio_mode_t mPhoneState GUARDED_BY(mLock);
+    uid_t mPhoneStateOwnerUid GUARDED_BY(mLock);
 
-    sp<UidPolicy> mUidPolicy;
-    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+    sp<UidPolicy> mUidPolicy GUARDED_BY(mLock);
+    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy GUARDED_BY(mLock);
 
-    DefaultKeyedVector< audio_port_handle_t, sp<AudioRecordClient> >   mAudioRecordClients;
-    DefaultKeyedVector< audio_port_handle_t, sp<AudioPlaybackClient> >   mAudioPlaybackClients;
+    DefaultKeyedVector<audio_port_handle_t, sp<AudioRecordClient>> mAudioRecordClients
+        GUARDED_BY(mLock);
+    DefaultKeyedVector<audio_port_handle_t, sp<AudioPlaybackClient>> mAudioPlaybackClients
+        GUARDED_BY(mLock);
 
     MediaPackageManager mPackageManager; // To check allowPlaybackCapture
+
+    CaptureStateNotifier mCaptureStateNotifier;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/service/BinderProxy.h b/services/audiopolicy/service/BinderProxy.h
new file mode 100644
index 0000000..516e84d
--- /dev/null
+++ b/services/audiopolicy/service/BinderProxy.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <type_traits>
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// A simple utility that caches a proxy for a service and handles death notification.
+// Typically, intended to be used as a static-lifetime object.
+//
+// Example usage:
+// static BinderProxy<IMyInterface> myInterface("my_interface_svc");
+// ...
+// myInterface.waitServiceOrDie()->doSomething();
+//
+// If the service is unavailable, will wait until it becomes available.
+// Will die if the service doesn't implement the requested interface, or cannot be used for
+// permission reasons.
+template<typename ServiceType>
+class BinderProxy {
+public:
+    static_assert(std::is_base_of_v<IInterface, ServiceType>,
+                  "Service type must be a sub-type of IInterface.");
+
+    explicit BinderProxy(std::string_view serviceName)
+            : mServiceName(serviceName), mDeathRecipient(new DeathRecipient(this)) {}
+
+    ~BinderProxy() {
+        if (mDelegate != nullptr) {
+            sp<IBinder> binder = IInterface::asBinder(mDelegate);
+            if (binder != nullptr) {
+                binder->unlinkToDeath(mDeathRecipient);
+            }
+        }
+    }
+
+    sp<ServiceType> waitServiceOrDie() {
+        std::lock_guard<std::mutex> _l(mDelegateMutex);
+        if (mDelegate == nullptr) {
+            mDelegate = waitForService<ServiceType>(String16(mServiceName.c_str()));
+            LOG_ALWAYS_FATAL_IF(mDelegate == nullptr,
+                                "Service %s doesn't implement the required interface.",
+                                mServiceName.c_str());
+            sp<IBinder> binder = IInterface::asBinder(mDelegate);
+            if (binder != nullptr) {
+                binder->linkToDeath(mDeathRecipient);
+            }
+        }
+        return mDelegate;
+    }
+
+private:
+    sp<ServiceType> mDelegate;
+    std::mutex mDelegateMutex;
+    const std::string mServiceName;
+    sp<IBinder::DeathRecipient> mDeathRecipient;
+
+    class DeathRecipient : public IBinder::DeathRecipient {
+    public:
+        DeathRecipient(BinderProxy* proxy) : mProxy(proxy) {}
+
+        void binderDied(const wp<IBinder>&) override {
+            mProxy->binderDied();
+        }
+
+    private:
+        BinderProxy* const mProxy;
+    };
+
+    void binderDied() {
+        std::lock_guard<std::mutex> _l(mDelegateMutex);
+        mDelegate.clear();
+        ALOGW("Binder died: %s", mServiceName.c_str());
+    }
+};
+
+}  // namespace android
diff --git a/services/audiopolicy/service/CaptureStateNotifier.cpp b/services/audiopolicy/service/CaptureStateNotifier.cpp
new file mode 100644
index 0000000..135e0a2
--- /dev/null
+++ b/services/audiopolicy/service/CaptureStateNotifier.cpp
@@ -0,0 +1,67 @@
+#define LOG_TAG "CaptureStateNotifier"
+
+#include "CaptureStateNotifier.h"
+
+#include <android/media/ICaptureStateListener.h>
+#include <binder/IBinder.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using media::ICaptureStateListener;
+
+class CaptureStateNotifier::DeathRecipient : public IBinder::DeathRecipient {
+public:
+    DeathRecipient(CaptureStateNotifier* notifier) : mNotifier(notifier) {}
+
+    void binderDied(const wp<IBinder>&) override {
+        mNotifier->binderDied();
+    }
+
+private:
+    CaptureStateNotifier* const mNotifier;
+};
+
+CaptureStateNotifier::CaptureStateNotifier(bool initialActive)
+    : mDeathRecipient(new DeathRecipient(this)), mActive(
+    initialActive) {}
+
+CaptureStateNotifier::~CaptureStateNotifier() {
+    LOG_ALWAYS_FATAL_IF(mListener != nullptr);
+}
+
+bool CaptureStateNotifier::RegisterListener(const sp<ICaptureStateListener>& listener) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    LOG_ALWAYS_FATAL_IF(mListener != nullptr);
+    LOG_ALWAYS_FATAL_IF(listener == nullptr);
+
+    ALOGI("Registering a listener");
+    sp<IBinder> binder = IInterface::asBinder(listener);
+    if (binder != nullptr) {
+        status_t status = binder->linkToDeath(mDeathRecipient);
+        if (status == NO_ERROR) {
+            mListener = listener;
+        } else {
+            ALOGE("Failed to register death listener: %u", status);
+        }
+    } else {
+        ALOGE("Listener failed to cast to a binder.");
+    }
+    return mActive;
+}
+
+void CaptureStateNotifier::setCaptureState(bool active) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    mActive = active;
+    if (mListener) {
+        mListener->setCaptureState(active);
+    }
+}
+
+void CaptureStateNotifier::binderDied() {
+    std::lock_guard<std::mutex> _l(mMutex);
+    mListener.clear();
+    ALOGI("Listener binder died");
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/service/CaptureStateNotifier.h b/services/audiopolicy/service/CaptureStateNotifier.h
new file mode 100644
index 0000000..166de2a
--- /dev/null
+++ b/services/audiopolicy/service/CaptureStateNotifier.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <binder/IBinder.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace media {
+// Must be pre-declared, or else there isn't a good way to generate a header
+// library.
+class ICaptureStateListener;
+}
+
+// A utility for managing capture state change notifications.
+//
+// We are making some strong assumptions, for the sake of simplicity:
+// - There is no way to explicitly unregister listeners. The only way for a
+//   listener to unregister is by dying.
+// - There's only at most one listener at a given time. Attempting to register
+//   a second listener will cause a crash.
+// - This class isn't really meant to ever be destroyed. We expose a destructor
+//   because it is convenient to use this class as a global instance or a member
+//   of another class, but it will crash if destroyed while a listener is
+//   registered.
+//
+// All of these assumptions can be lifted if there is ever a need.
+//
+// This class is thread-safe.
+class CaptureStateNotifier {
+public:
+    // Ctor.
+    // Accepts the initial active state.
+    explicit CaptureStateNotifier(bool initialActive);
+
+    // Register a listener to be notified of state changes.
+    // The current state is returned and from that point on any change will be
+    // notified of.
+    bool RegisterListener(const sp<media::ICaptureStateListener>& listener);
+
+    // Change the current capture state.
+    // Active means "actively capturing".
+    void setCaptureState(bool active);
+
+    // Dtor. Do not actually call at runtime. Will cause a crash if a listener
+    // is registered.
+    ~CaptureStateNotifier();
+
+private:
+    std::mutex mMutex;
+    sp<media::ICaptureStateListener> mListener;
+    sp<IBinder::DeathRecipient> mDeathRecipient;
+    bool mActive;
+
+    class DeathRecipient;
+
+    void binderDied();
+};
+
+}  // namespace android
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
new file mode 100644
index 0000000..efdb241
--- /dev/null
+++ b/services/audiopolicy/tests/Android.bp
@@ -0,0 +1,71 @@
+cc_test {
+    name: "audiopolicy_tests",
+
+    include_dirs: [
+        "frameworks/av/services/audiopolicy",
+    ],
+
+    shared_libs: [
+        "libaudioclient",
+        "libaudiofoundation",
+        "libaudiopolicy",
+        "libaudiopolicymanagerdefault",
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+        "libxml2",
+    ],
+
+    static_libs: ["libaudiopolicycomponents"],
+
+    header_libs: [
+        "libaudiopolicycommon",
+        "libaudiopolicyengine_interface_headers",
+        "libaudiopolicymanager_interface_headers",
+    ],
+
+    srcs: ["audiopolicymanager_tests.cpp"],
+
+    data: [":audiopolicytest_configuration_files",],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    test_suites: ["device-tests"],
+
+}
+
+
+cc_test {
+    name: "audio_health_tests",
+
+    shared_libs: [
+        "libaudiofoundation",
+        "libaudioclient",
+        "libaudiopolicymanagerdefault",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+    ],
+
+    static_libs: ["libaudiopolicycomponents"],
+
+    header_libs: [
+        "libaudiopolicyengine_interface_headers",
+        "libaudiopolicymanager_interface_headers",
+    ],
+
+    srcs: ["audio_health_tests.cpp"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    test_suites: ["device-tests"],
+
+}
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
deleted file mode 100644
index ab9f78b..0000000
--- a/services/audiopolicy/tests/Android.mk
+++ /dev/null
@@ -1,65 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := \
-  frameworks/av/services/audiopolicy \
-  $(call include-path-for, audio-utils) \
-
-LOCAL_SHARED_LIBRARIES := \
-  libaudiopolicymanagerdefault \
-  libbase \
-  liblog \
-  libmedia_helper \
-  libutils \
-
-LOCAL_STATIC_LIBRARIES := \
-  libaudiopolicycomponents \
-
-LOCAL_HEADER_LIBRARIES := \
-    libaudiopolicycommon \
-    libaudiopolicyengine_interface_headers \
-    libaudiopolicymanager_interface_headers
-
-LOCAL_SRC_FILES := \
-  audiopolicymanager_tests.cpp \
-
-LOCAL_MODULE := audiopolicy_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_NATIVE_TEST)
-
-# system/audio.h utilities test
-
-include $(CLEAR_VARS)
-
-LOCAL_SHARED_LIBRARIES := \
-  libbase \
-  liblog \
-  libmedia_helper \
-  libutils
-
-LOCAL_HEADER_LIBRARIES := \
-  libmedia_headers
-
-LOCAL_SRC_FILES := \
-  systemaudio_tests.cpp \
-
-LOCAL_MODULE := systemaudio_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_NATIVE_TEST)
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
new file mode 100644
index 0000000..e1721ea
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 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 <map>
+#include <set>
+
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "AudioPolicyTestClient.h"
+
+namespace android {
+
+class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
+public:
+    // AudioPolicyClientInterface implementation
+    audio_module_handle_t loadHwModule(const char* name) override {
+        if (!mAllowedModuleNames.empty() && !mAllowedModuleNames.count(name)) {
+            return AUDIO_MODULE_HANDLE_NONE;
+        }
+        return mNextModuleHandle++;
+    }
+
+    status_t openOutput(audio_module_handle_t module,
+                        audio_io_handle_t *output,
+                        audio_config_t * /*config*/,
+                        const sp<DeviceDescriptorBase>& /*device*/,
+                        uint32_t * /*latencyMs*/,
+                        audio_output_flags_t /*flags*/) override {
+        if (module >= mNextModuleHandle) {
+            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+                  __func__, module, mNextModuleHandle);
+            return BAD_VALUE;
+        }
+        *output = mNextIoHandle++;
+        return NO_ERROR;
+    }
+
+    audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
+                                          audio_io_handle_t /*output2*/) override {
+        audio_io_handle_t id = mNextIoHandle++;
+        return id;
+    }
+
+    status_t openInput(audio_module_handle_t module,
+                       audio_io_handle_t *input,
+                       audio_config_t * /*config*/,
+                       audio_devices_t * /*device*/,
+                       const String8 & /*address*/,
+                       audio_source_t /*source*/,
+                       audio_input_flags_t /*flags*/) override {
+        if (module >= mNextModuleHandle) {
+            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+                  __func__, module, mNextModuleHandle);
+            return BAD_VALUE;
+        }
+        *input = mNextIoHandle++;
+        return NO_ERROR;
+    }
+
+    status_t createAudioPatch(const struct audio_patch *patch,
+                              audio_patch_handle_t *handle,
+                              int /*delayMs*/) override {
+        *handle = mNextPatchHandle++;
+        mActivePatches.insert(std::make_pair(*handle, *patch));
+        return NO_ERROR;
+    }
+
+    status_t releaseAudioPatch(audio_patch_handle_t handle,
+                               int /*delayMs*/) override {
+        if (mActivePatches.erase(handle) != 1) {
+            if (handle >= mNextPatchHandle) {
+                ALOGE("%s: Patch handle %d has not been allocated yet (next is %d)",
+                      __func__, handle, mNextPatchHandle);
+            } else {
+                ALOGE("%s: Attempt to release patch %d twice", __func__, handle);
+            }
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+
+    void onAudioPortListUpdate() override {
+        ++mAudioPortListUpdateCount;
+    }
+
+    // Helper methods for tests
+    size_t getActivePatchesCount() const { return mActivePatches.size(); }
+
+    const struct audio_patch *getLastAddedPatch() const {
+        if (mActivePatches.empty()) {
+            return nullptr;
+        }
+        auto it = --mActivePatches.end();
+        return &it->second;
+    };
+
+    audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }
+
+    void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
+        mAllowedModuleNames.swap(names);
+    }
+
+    size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
+
+private:
+    audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
+    audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
+    audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
+    std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
+    std::set<std::string> mAllowedModuleNames;
+    size_t mAudioPortListUpdateCount = 0;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index e4c64e5..c628e70 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -31,8 +31,7 @@
     status_t openOutput(audio_module_handle_t /*module*/,
                         audio_io_handle_t* /*output*/,
                         audio_config_t* /*config*/,
-                        audio_devices_t* /*devices*/,
-                        const String8& /*address*/,
+                        const sp<DeviceDescriptorBase>& /*device*/,
                         uint32_t* /*latencyMs*/,
                         audio_output_flags_t /*flags*/) override { return NO_INIT; }
     audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
@@ -87,6 +86,7 @@
     void setEffectSuspended(int effectId __unused,
                             audio_session_t sessionId __unused,
                             bool suspended __unused) {}
+    void setSoundTriggerCaptureState(bool active __unused) override {};
 };
 
 } // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index fe543a6..8bab020 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -24,7 +24,12 @@
     explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
             : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
     using AudioPolicyManager::getConfig;
+    using AudioPolicyManager::loadConfig;
     using AudioPolicyManager::initialize;
+    using AudioPolicyManager::getOutputs;
+    using AudioPolicyManager::getAvailableOutputDevices;
+    using AudioPolicyManager::getAvailableInputDevices;
+    uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
 };
 
 }  // namespace android
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
new file mode 100644
index 0000000..b5c67a1
--- /dev/null
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 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_TAG "AudioPolicy_Boot_Test"
+
+#include <unordered_set>
+
+#include <gtest/gtest.h>
+
+#include <media/AudioSystem.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "AudioPolicyManagerTestClient.h"
+#include "AudioPolicyTestManager.h"
+
+using namespace android;
+
+TEST(AudioHealthTest, AttachedDeviceFound) {
+    unsigned int numPorts;
+    unsigned int generation1;
+    unsigned int generation;
+    struct audio_port *audioPorts = NULL;
+    int attempts = 10;
+    do {
+        if (attempts-- < 0) {
+            free(audioPorts);
+            GTEST_FAIL() << "Query audio ports time out";
+        }
+        numPorts = 0;
+        ASSERT_EQ(NO_ERROR, AudioSystem::listAudioPorts(
+                AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, NULL, &generation1));
+        if (numPorts == 0) {
+            free(audioPorts);
+            GTEST_FAIL() << "Number of audio ports should not be zero";
+        }
+
+        audioPorts = (struct audio_port *)realloc(audioPorts, numPorts * sizeof(struct audio_port));
+        status_t status = AudioSystem::listAudioPorts(
+                AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_DEVICE, &numPorts, audioPorts, &generation);
+        if (status != NO_ERROR) {
+            free(audioPorts);
+            GTEST_FAIL() << "Query audio ports failed";
+        }
+    } while (generation1 != generation);
+    std::unordered_set<audio_devices_t> attachedDevices;
+    for (int i = 0 ; i < numPorts; i++) {
+        attachedDevices.insert(audioPorts[i].ext.device.type);
+    }
+    free(audioPorts);
+
+    AudioPolicyManagerTestClient client;
+    AudioPolicyTestManager manager(&client);
+    manager.loadConfig();
+    ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
+
+    for (auto desc : manager.getConfig().getInputDevices()) {
+        ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+    }
+    for (auto desc : manager.getConfig().getOutputDevices()) {
+        ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
+    }
+}
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index de5670c..a0074bc 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -15,22 +15,38 @@
  */
 
 #include <memory>
-#include <set>
+#include <string>
 #include <sys/wait.h>
 #include <unistd.h>
 
 #include <gtest/gtest.h>
 
 #define LOG_TAG "APM_Test"
-#include <log/log.h>
+#include <Serializer.h>
+#include <android-base/file.h>
+#include <media/AudioPolicy.h>
 #include <media/PatchBuilder.h>
+#include <media/RecordingActivityTracker.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
 
+#include "AudioPolicyInterface.h"
+#include "AudioPolicyManagerTestClient.h"
 #include "AudioPolicyTestClient.h"
 #include "AudioPolicyTestManager.h"
 
 using namespace android;
 
-TEST(AudioPolicyManagerTestInit, Failure) {
+TEST(AudioPolicyManagerTestInit, EngineFailure) {
+    AudioPolicyTestClient client;
+    AudioPolicyTestManager manager(&client);
+    manager.getConfig().setDefault();
+    manager.getConfig().setEngineLibraryNameSuffix("non-existent");
+    ASSERT_EQ(NO_INIT, manager.initialize());
+    ASSERT_EQ(NO_INIT, manager.initCheck());
+}
+
+TEST(AudioPolicyManagerTestInit, ClientFailure) {
     AudioPolicyTestClient client;
     AudioPolicyTestManager manager(&client);
     manager.getConfig().setDefault();
@@ -41,77 +57,6 @@
 }
 
 
-class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
-  public:
-    // AudioPolicyClientInterface implementation
-    audio_module_handle_t loadHwModule(const char* /*name*/) override {
-        return mNextModuleHandle++;
-    }
-
-    status_t openOutput(audio_module_handle_t module,
-                        audio_io_handle_t* output,
-                        audio_config_t* /*config*/,
-                        audio_devices_t* /*devices*/,
-                        const String8& /*address*/,
-                        uint32_t* /*latencyMs*/,
-                        audio_output_flags_t /*flags*/) override {
-        if (module >= mNextModuleHandle) {
-            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
-                    __func__, module, mNextModuleHandle);
-            return BAD_VALUE;
-        }
-        *output = mNextIoHandle++;
-        return NO_ERROR;
-    }
-
-    status_t openInput(audio_module_handle_t module,
-                       audio_io_handle_t* input,
-                       audio_config_t* /*config*/,
-                       audio_devices_t* /*device*/,
-                       const String8& /*address*/,
-                       audio_source_t /*source*/,
-                       audio_input_flags_t /*flags*/) override {
-        if (module >= mNextModuleHandle) {
-            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
-                    __func__, module, mNextModuleHandle);
-            return BAD_VALUE;
-        }
-        *input = mNextIoHandle++;
-        return NO_ERROR;
-    }
-
-    status_t createAudioPatch(const struct audio_patch* /*patch*/,
-                              audio_patch_handle_t* handle,
-                              int /*delayMs*/) override {
-        *handle = mNextPatchHandle++;
-        mActivePatches.insert(*handle);
-        return NO_ERROR;
-    }
-
-    status_t releaseAudioPatch(audio_patch_handle_t handle,
-                               int /*delayMs*/) override {
-        if (mActivePatches.erase(handle) != 1) {
-            if (handle >= mNextPatchHandle) {
-                ALOGE("%s: Patch handle %d has not been allocated yet (next is %d)",
-                        __func__, handle, mNextPatchHandle);
-            } else {
-                ALOGE("%s: Attempt to release patch %d twice", __func__, handle);
-            }
-            return BAD_VALUE;
-        }
-        return NO_ERROR;
-    }
-
-    // Helper methods for tests
-    size_t getActivePatchesCount() const { return mActivePatches.size(); }
-
-  private:
-    audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
-    audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
-    audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
-    std::set<audio_patch_handle_t> mActivePatches;
-};
-
 class PatchCountCheck {
   public:
     explicit PatchCountCheck(AudioPolicyManagerTestClient *client)
@@ -134,18 +79,37 @@
   protected:
     void SetUp() override;
     void TearDown() override;
-    virtual void SetUpConfig(AudioPolicyConfig *config) { (void)config; }
+    virtual void SetUpManagerConfig();
 
     void dumpToLog();
+    // When explicit routing is needed, selectedDeviceId needs to be set as the wanted port
+    // id. Otherwise, selectedDeviceId needs to be initialized as AUDIO_PORT_HANDLE_NONE.
     void getOutputForAttr(
             audio_port_handle_t *selectedDeviceId,
             audio_format_t format,
             int channelMask,
             int sampleRate,
             audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+            audio_io_handle_t *output = nullptr,
+            audio_port_handle_t *portId = nullptr,
+            audio_attributes_t attr = {});
+    void getInputForAttr(
+            const audio_attributes_t &attr,
+            audio_unique_id_t riid,
+            audio_port_handle_t *selectedDeviceId,
+            audio_format_t format,
+            int channelMask,
+            int sampleRate,
+            audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
             audio_port_handle_t *portId = nullptr);
     PatchCountCheck snapshotPatchCount() { return PatchCountCheck(mClient.get()); }
 
+    // Tries to find a device port. If 'foundPort' isn't nullptr,
+    // will generate a failure if the port hasn't been found.
+    bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
+            const std::string &address, audio_port *foundPort);
+    static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
+
     std::unique_ptr<AudioPolicyManagerTestClient> mClient;
     std::unique_ptr<AudioPolicyTestManager> mManager;
 };
@@ -153,8 +117,7 @@
 void AudioPolicyManagerTest::SetUp() {
     mClient.reset(new AudioPolicyManagerTestClient);
     mManager.reset(new AudioPolicyTestManager(mClient.get()));
-    mManager->getConfig().setDefault();
-    SetUpConfig(&mManager->getConfig());  // Subclasses may want to customize the config.
+    SetUpManagerConfig();  // Subclasses may want to customize the config.
     ASSERT_EQ(NO_ERROR, mManager->initialize());
     ASSERT_EQ(NO_ERROR, mManager->initCheck());
 }
@@ -164,6 +127,10 @@
     mClient.reset();
 }
 
+void AudioPolicyManagerTest::SetUpManagerConfig() {
+    mManager->getConfig().setDefault();
+}
+
 void AudioPolicyManagerTest::dumpToLog() {
     int pipefd[2];
     ASSERT_NE(-1, pipe(pipefd));
@@ -200,22 +167,97 @@
         int channelMask,
         int sampleRate,
         audio_output_flags_t flags,
-        audio_port_handle_t *portId) {
-    audio_attributes_t attr = {};
-    audio_io_handle_t output = AUDIO_PORT_HANDLE_NONE;
+        audio_io_handle_t *output,
+        audio_port_handle_t *portId,
+        audio_attributes_t attr) {
+    audio_io_handle_t localOutput;
+    if (!output) output = &localOutput;
+    *output = AUDIO_IO_HANDLE_NONE;
     audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
     config.sample_rate = sampleRate;
     config.channel_mask = channelMask;
     config.format = format;
-    *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_port_handle_t localPortId;
     if (!portId) portId = &localPortId;
     *portId = AUDIO_PORT_HANDLE_NONE;
+    AudioPolicyInterface::output_type_t outputType;
     ASSERT_EQ(OK, mManager->getOutputForAttr(
-                    &attr, &output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
-                    selectedDeviceId, portId, {}));
+                    &attr, output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
+                    selectedDeviceId, portId, {}, &outputType));
     ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+    ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
+}
+
+void AudioPolicyManagerTest::getInputForAttr(
+        const audio_attributes_t &attr,
+        audio_unique_id_t riid,
+        audio_port_handle_t *selectedDeviceId,
+        audio_format_t format,
+        int channelMask,
+        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;
+    config.format = format;
+    audio_port_handle_t localPortId;
+    if (!portId) portId = &localPortId;
+    *portId = AUDIO_PORT_HANDLE_NONE;
+    AudioPolicyInterface::input_type_t inputType;
+    ASSERT_EQ(OK, mManager->getInputForAttr(
+            &attr, &input, riid, AUDIO_SESSION_NONE, 0 /*uid*/, &config, flags,
+            selectedDeviceId, &inputType, portId));
+    ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+}
+
+bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
+        audio_devices_t deviceType, const std::string &address, audio_port *foundPort) {
+    uint32_t numPorts = 0;
+    uint32_t generation1;
+    status_t ret;
+
+    ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    if (HasFailure()) return false;
+
+    uint32_t generation2;
+    struct audio_port ports[numPorts];
+    ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
+    if (HasFailure()) return false;
+
+    for (const auto &port : ports) {
+        if (port.role == role && port.ext.device.type == deviceType &&
+                (strncmp(port.ext.device.address, address.c_str(),
+                         AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
+            if (foundPort) *foundPort = port;
+            return true;
+        }
+    }
+    if (foundPort) {
+        ADD_FAILURE() << "Device port with role " << role << " and address "
+                      << address << " not found";
+    }
+    return false;
+}
+
+audio_port_handle_t AudioPolicyManagerTest::getDeviceIdFromPatch(
+        const struct audio_patch* patch) {
+    // The logic here is the same as the one in AudioIoDescriptor.
+    // Note this function is aim to get routed device id for test.
+    // In that case, device to device patch is not expected here.
+    if (patch->num_sources != 0 && patch->num_sinks != 0) {
+        if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
+            return patch->sinks[0].id;
+        } else {
+            return patch->sources[0].id;
+        }
+    }
+    return AUDIO_PORT_HANDLE_NONE;
 }
 
 
@@ -264,9 +306,9 @@
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
     uid_t uid = 42;
     const PatchCountCheck patchCount = snapshotPatchCount();
-    ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
+    ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
     PatchBuilder patchBuilder;
-    patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
+    patchBuilder.addSource(mManager->getAvailableInputDevices()[0]).
             addSink(mManager->getConfig().getDefaultOutputDevice());
     ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
     ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
@@ -277,15 +319,17 @@
 
 class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
   protected:
-    void SetUpConfig(AudioPolicyConfig *config) override;
+    void SetUpManagerConfig() override;
     void TearDown() override;
 
     sp<DeviceDescriptor> mMsdOutputDevice;
     sp<DeviceDescriptor> mMsdInputDevice;
 };
 
-void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
+void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
     // TODO: Consider using Serializer to load part of the config from a string.
+    AudioPolicyManagerTest::SetUpManagerConfig();
+    AudioPolicyConfig& config = mManager->getConfig();
     mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
     sp<AudioProfile> pcmOutputProfile = new AudioProfile(
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
@@ -298,22 +342,19 @@
     sp<AudioProfile> pcmInputProfile = new AudioProfile(
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
     mMsdInputDevice->addAudioProfile(pcmInputProfile);
-    config->addAvailableDevice(mMsdOutputDevice);
-    config->addAvailableDevice(mMsdInputDevice);
+    config.addDevice(mMsdOutputDevice);
+    config.addDevice(mMsdInputDevice);
 
     sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
-    HwModuleCollection modules = config->getHwModules();
+    HwModuleCollection modules = config.getHwModules();
     modules.add(msdModule);
-    config->setHwModules(modules);
-    mMsdOutputDevice->attach(msdModule);
-    mMsdInputDevice->attach(msdModule);
+    config.setHwModules(modules);
 
-    sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input"));
+    sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
     msdOutputProfile->addAudioProfile(pcmOutputProfile);
     msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
     msdModule->addOutputProfile(msdOutputProfile);
-    sp<OutputProfile> msdCompressedOutputProfile =
-            new OutputProfile(String8("msd compressed input"));
+    sp<OutputProfile> msdCompressedOutputProfile = new OutputProfile("msd compressed input");
     msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
     msdCompressedOutputProfile->setFlags(
             AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
@@ -321,7 +362,7 @@
     msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
     msdModule->addOutputProfile(msdCompressedOutputProfile);
 
-    sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output"));
+    sp<InputProfile> msdInputProfile = new InputProfile("msd output");
     msdInputProfile->addAudioProfile(pcmInputProfile);
     msdInputProfile->addSupportedDevice(mMsdInputDevice);
     msdModule->addInputProfile(msdInputProfile);
@@ -330,12 +371,12 @@
     // of streams that are not supported by MSD.
     sp<AudioProfile> dtsOutputProfile = new AudioProfile(
             AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
-    config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
-    sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile(String8("encoded"));
+    config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+    sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
     primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
     primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
-    primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());
-    config->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+    primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
+    config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
             addOutputProfile(primaryEncodedOutputProfile);
 }
 
@@ -363,7 +404,7 @@
 
 TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
     const PatchCountCheck patchCount = snapshotPatchCount();
-    audio_port_handle_t selectedDeviceId;
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
     ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -372,7 +413,7 @@
 
 TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
     const PatchCountCheck patchCount = snapshotPatchCount();
-    audio_port_handle_t selectedDeviceId;
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
     ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -381,7 +422,7 @@
 
 TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
     const PatchCountCheck patchCount = snapshotPatchCount();
-    audio_port_handle_t selectedDeviceId;
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
     ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -394,7 +435,7 @@
 
 TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
     const PatchCountCheck patchCount = snapshotPatchCount();
-    audio_port_handle_t selectedDeviceId;
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     getOutputForAttr(&selectedDeviceId,
             AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
     ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
@@ -405,10 +446,11 @@
     // Switch between formats that are supported and not supported by MSD.
     {
         const PatchCountCheck patchCount = snapshotPatchCount();
-        audio_port_handle_t selectedDeviceId, portId;
+        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t portId;
         getOutputForAttr(&selectedDeviceId,
                 AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
-                &portId);
+                nullptr /*output*/, &portId);
         ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
         ASSERT_EQ(1, patchCount.deltaFromSnapshot());
         mManager->releaseOutput(portId);
@@ -416,10 +458,11 @@
     }
     {
         const PatchCountCheck patchCount = snapshotPatchCount();
-        audio_port_handle_t selectedDeviceId, portId;
+        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+        audio_port_handle_t portId;
         getOutputForAttr(&selectedDeviceId,
                 AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
-                &portId);
+                nullptr /*output*/, &portId);
         ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
         ASSERT_EQ(-1, patchCount.deltaFromSnapshot());
         mManager->releaseOutput(portId);
@@ -427,10 +470,721 @@
     }
     {
         const PatchCountCheck patchCount = snapshotPatchCount();
-        audio_port_handle_t selectedDeviceId;
+        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
         getOutputForAttr(&selectedDeviceId,
                 AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
         ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
         ASSERT_EQ(0, patchCount.deltaFromSnapshot());
     }
 }
+
+class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest {
+protected:
+    void SetUpManagerConfig() override;
+    virtual std::string getConfigFile() { return sDefaultConfig; }
+
+    static const std::string sExecutableDir;
+    static const std::string sDefaultConfig;
+};
+
+const std::string AudioPolicyManagerTestWithConfigurationFile::sExecutableDir =
+        base::GetExecutableDirectory() + "/";
+
+const std::string AudioPolicyManagerTestWithConfigurationFile::sDefaultConfig =
+        sExecutableDir + "test_audio_policy_configuration.xml";
+
+void AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig() {
+    status_t status = deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
+    ASSERT_EQ(NO_ERROR, status);
+}
+
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, Dump) {
+    dumpToLog();
+}
+
+using PolicyMixTuple = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+
+class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+    void TearDown() override;
+
+    status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType,
+            std::string mixAddress, const audio_config_t& audioConfig,
+            const std::vector<PolicyMixTuple>& rules);
+    void clearPolicyMix();
+
+    Vector<AudioMix> mAudioMixes;
+    const std::string mMixAddress = "remote_submix_media";
+};
+
+void AudioPolicyManagerTestDynamicPolicy::TearDown() {
+    mManager->unregisterPolicyMixes(mAudioMixes);
+    AudioPolicyManagerTestWithConfigurationFile::TearDown();
+}
+
+status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixFlag,
+        audio_devices_t deviceType, std::string mixAddress, const audio_config_t& audioConfig,
+        const std::vector<PolicyMixTuple>& rules) {
+    Vector<AudioMixMatchCriterion> myMixMatchCriteria;
+
+    for(const auto &rule: rules) {
+        myMixMatchCriteria.add(AudioMixMatchCriterion(
+                std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
+    }
+
+    AudioMix myAudioMix(myMixMatchCriteria, mixType, audioConfig, mixFlag,
+            String8(mixAddress.c_str()), 0);
+    myAudioMix.mDeviceType = deviceType;
+    // Clear mAudioMix before add new one to make sure we don't add already exist mixes.
+    mAudioMixes.clear();
+    mAudioMixes.add(myAudioMix);
+
+    // As the policy mixes registration may fail at some case,
+    // caller need to check the returned status.
+    status_t ret = mManager->registerPolicyMixes(mAudioMixes);
+    return ret;
+}
+
+void AudioPolicyManagerTestDynamicPolicy::clearPolicyMix() {
+    if (mManager != nullptr) {
+        mManager->unregisterPolicyMixes(mAudioMixes);
+    }
+    mAudioMixes.clear();
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, InitSuccess) {
+    // SetUp must finish with no assertions
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, Dump) {
+    dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyMixes) {
+    status_t ret;
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+
+    // Only capture of playback is allowed in LOOP_BACK &RENDER mode
+    ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    // Fail due to the device is already connected.
+    clearPolicyMix();
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    // The first time to register policy mixes with valid parameter should succeed.
+    clearPolicyMix();
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = 48000;
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+            std::vector<PolicyMixTuple>());
+    ASSERT_EQ(NO_ERROR, ret);
+    // Registering the same policy mixes should fail.
+    ret = mManager->registerPolicyMixes(mAudioMixes);
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    // Registration should fail due to device not found.
+    // Note that earpiece is not present in the test configuration file.
+    // This will need to be updated if earpiece is added in the test configuration file.
+    clearPolicyMix();
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+            AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    // Registration should fail due to output not found.
+    clearPolicyMix();
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    // The first time to register valid policy mixes should succeed.
+    clearPolicyMix();
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+            AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(NO_ERROR, ret);
+    // Registering the same policy mixes should fail.
+    ret = mManager->registerPolicyMixes(mAudioMixes);
+    ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, UnregisterPolicyMixes) {
+    status_t ret;
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = 48000;
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+            std::vector<PolicyMixTuple>());
+    ASSERT_EQ(NO_ERROR, ret);
+
+    // After successfully registering policy mixes, it should be able to unregister.
+    ret = mManager->unregisterPolicyMixes(mAudioMixes);
+    ASSERT_EQ(NO_ERROR, ret);
+
+    // After unregistering policy mixes successfully, it should fail unregistering
+    // the same policy mixes as they are not registered.
+    ret = mManager->unregisterPolicyMixes(mAudioMixes);
+    ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+class AudioPolicyManagerTestDPNoRemoteSubmixModule : public AudioPolicyManagerTestDynamicPolicy {
+protected:
+    std::string getConfigFile() override { return sPrimaryOnlyConfig; }
+
+    static const std::string sPrimaryOnlyConfig;
+};
+
+const std::string AudioPolicyManagerTestDPNoRemoteSubmixModule::sPrimaryOnlyConfig =
+        sExecutableDir + "test_audio_policy_primary_only_configuration.xml";
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, Dump) {
+    dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, RegistrationFailure) {
+    // Registration/Unregistration should fail due to module for remote submix not found.
+    status_t ret;
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = 48000;
+    ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+    ASSERT_EQ(INVALID_OPERATION, ret);
+
+    ret = mManager->unregisterPolicyMixes(mAudioMixes);
+    ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+class AudioPolicyManagerTestDPPlaybackReRouting : public AudioPolicyManagerTestDynamicPolicy,
+        public testing::WithParamInterface<audio_attributes_t> {
+protected:
+    void SetUp() override;
+    void TearDown() override;
+
+    std::unique_ptr<RecordingActivityTracker> mTracker;
+
+    std::vector<PolicyMixTuple> mUsageRules = {
+            {AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE},
+            {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
+    };
+
+    struct audio_port mInjectionPort;
+    audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
+};
+
+void AudioPolicyManagerTestDPPlaybackReRouting::SetUp() {
+    AudioPolicyManagerTestDynamicPolicy::SetUp();
+
+    mTracker.reset(new RecordingActivityTracker());
+
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = 48000;
+    status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, mUsageRules);
+    ASSERT_EQ(NO_ERROR, ret);
+
+    struct audio_port extractionPort;
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                    mMixAddress, &extractionPort));
+
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
+    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, 0, ""};
+    std::string tags = "addr=" + mMixAddress;
+    strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+    getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+            AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &mPortId);
+    ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
+    ASSERT_EQ(extractionPort.id, selectedDeviceId);
+
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                    mMixAddress, &mInjectionPort));
+}
+
+void AudioPolicyManagerTestDPPlaybackReRouting::TearDown() {
+    mManager->stopInput(mPortId);
+    AudioPolicyManagerTestDynamicPolicy::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestDPPlaybackReRouting, InitSuccess) {
+    // SetUp must finish with no assertions
+}
+
+TEST_F(AudioPolicyManagerTestDPPlaybackReRouting, Dump) {
+    dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDPPlaybackReRouting, PlaybackReRouting) {
+    const audio_attributes_t attr = GetParam();
+    const audio_usage_t usage = attr.usage;
+
+    audio_port_handle_t playbackRoutedPortId = AUDIO_PORT_HANDLE_NONE;
+    getOutputForAttr(&playbackRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE,
+            nullptr /*output*/, nullptr /*portId*/, attr);
+    if (std::find_if(begin(mUsageRules), end(mUsageRules), [&usage](const auto &usageRule) {
+            return (std::get<0>(usageRule) == usage) &&
+            (std::get<2>(usageRule) == RULE_MATCH_ATTRIBUTE_USAGE);}) != end(mUsageRules) ||
+            (strncmp(attr.tags, "addr=", strlen("addr=")) == 0 &&
+                    strncmp(attr.tags + strlen("addr="), mMixAddress.c_str(),
+                    AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0)) {
+        EXPECT_EQ(mInjectionPort.id, playbackRoutedPortId);
+    } else {
+        EXPECT_NE(mInjectionPort.id, playbackRoutedPortId);
+    }
+}
+
+INSTANTIATE_TEST_CASE_P(
+        PlaybackReroutingUsageMatch,
+        AudioPolicyManagerTestDPPlaybackReRouting,
+        testing::Values(
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""}
+                )
+        );
+
+INSTANTIATE_TEST_CASE_P(
+        PlaybackReroutingAddressPriorityMatch,
+        AudioPolicyManagerTestDPPlaybackReRouting,
+        testing::Values(
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VIRTUAL_SOURCE,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"}
+                )
+        );
+
+INSTANTIATE_TEST_CASE_P(
+        PlaybackReroutingUnHandledUsages,
+        AudioPolicyManagerTestDPPlaybackReRouting,
+        testing::Values(
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+                                     AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
+                                     AUDIO_SOURCE_DEFAULT, 0, ""}
+                )
+        );
+
+class AudioPolicyManagerTestDPMixRecordInjection : public AudioPolicyManagerTestDynamicPolicy,
+        public testing::WithParamInterface<audio_attributes_t> {
+protected:
+    void SetUp() override;
+    void TearDown() override;
+
+    std::unique_ptr<RecordingActivityTracker> mTracker;
+
+    std::vector<PolicyMixTuple> mSourceRules = {
+        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_CAMCORDER, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
+        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_MIC, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
+        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
+    };
+
+    struct audio_port mExtractionPort;
+    audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
+};
+
+void AudioPolicyManagerTestDPMixRecordInjection::SetUp() {
+    AudioPolicyManagerTestDynamicPolicy::SetUp();
+
+    mTracker.reset(new RecordingActivityTracker());
+
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+    audioConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = 48000;
+    status_t ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK,
+            AUDIO_DEVICE_IN_REMOTE_SUBMIX, mMixAddress, audioConfig, mSourceRules);
+    ASSERT_EQ(NO_ERROR, ret);
+
+    struct audio_port injectionPort;
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                    mMixAddress, &injectionPort));
+
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
+    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, 0, ""};
+    std::string tags = std::string("addr=") + mMixAddress;
+    strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, &mPortId, attr);
+    ASSERT_EQ(NO_ERROR, mManager->startOutput(mPortId));
+    ASSERT_EQ(injectionPort.id, getDeviceIdFromPatch(mClient->getLastAddedPatch()));
+
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                    mMixAddress, &mExtractionPort));
+}
+
+void AudioPolicyManagerTestDPMixRecordInjection::TearDown() {
+    mManager->stopOutput(mPortId);
+    AudioPolicyManagerTestDynamicPolicy::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestDPMixRecordInjection, InitSuccess) {
+    // SetUp mush finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDPMixRecordInjection, Dump) {
+    dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDPMixRecordInjection, RecordingInjection) {
+    const audio_attributes_t attr = GetParam();
+    const audio_source_t source = attr.source;
+
+    audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE;
+    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+    getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT,
+            AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &portId);
+    if (std::find_if(begin(mSourceRules), end(mSourceRules), [&source](const auto &sourceRule) {
+            return (std::get<1>(sourceRule) == source) &&
+            (std::get<2>(sourceRule) == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET);})
+            != end(mSourceRules)) {
+        EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
+    } else {
+        EXPECT_NE(mExtractionPort.id, captureRoutedPortId);
+    }
+}
+
+// No address priority rule for remote recording, address is a "don't care"
+INSTANTIATE_TEST_CASE_P(
+        RecordInjectionSourceMatch,
+        AudioPolicyManagerTestDPMixRecordInjection,
+        testing::Values(
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_CAMCORDER, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_CAMCORDER, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_MIC, 0, "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_MIC, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_VOICE_COMMUNICATION, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_VOICE_COMMUNICATION, 0,
+                                     "addr=remote_submix_media"}
+                )
+        );
+
+// No address priority rule for remote recording
+INSTANTIATE_TEST_CASE_P(
+        RecordInjectionSourceNotMatch,
+        AudioPolicyManagerTestDPMixRecordInjection,
+        testing::Values(
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_VOICE_RECOGNITION, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_HOTWORD, 0, ""},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_VOICE_RECOGNITION, 0,
+                                     "addr=remote_submix_media"},
+                (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+                                     AUDIO_SOURCE_HOTWORD, 0, "addr=remote_submix_media"}
+                )
+        );
+
+using DeviceConnectionTestParams =
+        std::tuple<audio_devices_t /*type*/, std::string /*name*/, std::string /*address*/>;
+
+class AudioPolicyManagerTestDeviceConnection : public AudioPolicyManagerTestWithConfigurationFile,
+        public testing::WithParamInterface<DeviceConnectionTestParams> {
+};
+
+TEST_F(AudioPolicyManagerTestDeviceConnection, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDeviceConnection, Dump) {
+    dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, SetDeviceConnectionState) {
+    const audio_devices_t type = std::get<0>(GetParam());
+    const std::string name = std::get<1>(GetParam());
+    const std::string address = std::get<2>(GetParam());
+
+    if (type == AUDIO_DEVICE_OUT_HDMI) {
+        // Set device connection state failed due to no device descriptor found
+        // For HDMI case, it is easier to simulate device descriptor not found error
+        // by using a undeclared encoded format.
+        ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+                type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                address.c_str(), name.c_str(), AUDIO_FORMAT_MAT_2_1));
+    }
+    // Connect with valid parameters should succeed
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+    // Try to connect with the same device again should fail
+    ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+    // Disconnect the connected device should succeed
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+    // Disconnect device that is not connected should fail
+    ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+    // Try to set device connection state  with a invalid connection state should fail
+    ASSERT_EQ(BAD_VALUE, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_CNT,
+            "", "", AUDIO_FORMAT_DEFAULT));
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, ExplicitlyRoutingAfterConnection) {
+    const audio_devices_t type = std::get<0>(GetParam());
+    const std::string name = std::get<1>(GetParam());
+    const std::string address = std::get<2>(GetParam());
+
+    // Connect device to do explicitly routing test
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+
+    audio_port devicePort;
+    const audio_port_role_t role = audio_is_output_device(type)
+            ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
+    ASSERT_TRUE(findDevicePort(role, type, address, &devicePort));
+
+    audio_port_handle_t routedPortId = devicePort.id;
+    // Try start input or output according to the device type
+    if (audio_is_output_devices(type)) {
+        getOutputForAttr(&routedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+                48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE);
+    } else if (audio_is_input_device(type)) {
+        RecordingActivityTracker tracker;
+        getInputForAttr({}, tracker.getRiid(), &routedPortId, AUDIO_FORMAT_PCM_16_BIT,
+                AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE);
+    }
+    ASSERT_EQ(devicePort.id, routedPortId);
+
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+}
+
+INSTANTIATE_TEST_CASE_P(
+        DeviceConnectionState,
+        AudioPolicyManagerTestDeviceConnection,
+        testing::Values(
+                DeviceConnectionTestParams({AUDIO_DEVICE_IN_HDMI, "test_in_hdmi",
+                                            "audio_policy_test_in_hdmi"}),
+                DeviceConnectionTestParams({AUDIO_DEVICE_OUT_HDMI, "test_out_hdmi",
+                                            "audio_policy_test_out_hdmi"}),
+                DeviceConnectionTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "bt_hfp_in",
+                                            "hfp_client_in"}),
+                DeviceConnectionTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "bt_hfp_out",
+                                            "hfp_client_out"})
+                )
+        );
+
+class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+    std::string getConfigFile() override { return sTvConfig; }
+    void testHDMIPortSelection(audio_output_flags_t flags, const char* expectedMixPortName);
+
+    static const std::string sTvConfig;
+};
+
+const std::string AudioPolicyManagerTVTest::sTvConfig =
+        AudioPolicyManagerTVTest::sExecutableDir + "test_tv_apm_configuration.xml";
+
+// SwAudioOutputDescriptor doesn't populate flags so check against the port name.
+void AudioPolicyManagerTVTest::testHDMIPortSelection(
+        audio_output_flags_t flags, const char* expectedMixPortName) {
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+            "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT));
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    audio_io_handle_t output;
+    audio_port_handle_t portId;
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000,
+            flags, &output, &portId);
+    sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
+    ASSERT_NE(nullptr, outDesc.get());
+    audio_port port = {};
+    outDesc->toAudioPort(&port);
+    mManager->releaseOutput(portId);
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+            AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+            "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT));
+    ASSERT_EQ(AUDIO_PORT_TYPE_MIX, port.type);
+    ASSERT_EQ(AUDIO_PORT_ROLE_SOURCE, port.role);
+    ASSERT_STREQ(expectedMixPortName, port.name);
+}
+
+TEST_F(AudioPolicyManagerTVTest, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTVTest, Dump) {
+    dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchNoFlags) {
+    testHDMIPortSelection(AUDIO_OUTPUT_FLAG_NONE, "primary output");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectNoHwAvSync) {
+    // b/140447125: The selected port must not have HW AV Sync flag (see the config file).
+    testHDMIPortSelection(AUDIO_OUTPUT_FLAG_DIRECT, "direct");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectHwAvSync) {
+    testHDMIPortSelection(static_cast<audio_output_flags_t>(
+                    AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
+            "tunnel");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectMMapNoIrq) {
+    testHDMIPortSelection(static_cast<audio_output_flags_t>(
+                    AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
+            "low latency");
+}
+
+class AudioPolicyManagerDynamicHwModulesTest : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+    void SetUpManagerConfig() override;
+};
+
+void AudioPolicyManagerDynamicHwModulesTest::SetUpManagerConfig() {
+    AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig();
+    // Only allow successful opening of "primary" hw module during APM initialization.
+    mClient->swapAllowedModuleNames({"primary"});
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, DynamicAddition) {
+    const auto handleBefore = mClient->peekNextModuleHandle();
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(handleBefore, mClient->peekNextModuleHandle());
+    // Reset module loading restrictions.
+    mClient->swapAllowedModuleNames();
+    mManager->onNewAudioModulesAvailable();
+    const auto handleAfter = mClient->peekNextModuleHandle();
+    ASSERT_GT(handleAfter, handleBefore);
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(handleAfter, mClient->peekNextModuleHandle());
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, AddedDeviceAvailable) {
+    ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, mManager->getDeviceConnectionState(
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ListAddedAudioPorts) {
+    ASSERT_FALSE(
+            findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", nullptr));
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    struct audio_port port;
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", &port));
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ClientIsUpdated) {
+    const size_t prevAudioPortListUpdateCount = mClient->getAudioPortListUpdateCount();
+    const uint32_t prevAudioPortGeneration = mManager->getAudioPortGeneration();
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    EXPECT_GT(mClient->getAudioPortListUpdateCount(), prevAudioPortListUpdateCount);
+    EXPECT_GT(mManager->getAudioPortGeneration(), prevAudioPortGeneration);
+}
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
new file mode 100644
index 0000000..d9476d9
--- /dev/null
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -0,0 +1,8 @@
+filegroup {
+    name: "audiopolicytest_configuration_files",
+    srcs: [
+        "test_audio_policy_configuration.xml",
+        "test_audio_policy_primary_only_configuration.xml",
+        "test_tv_apm_configuration.xml",
+    ],
+}
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
new file mode 100644
index 0000000..87f0ab9
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <globalConfiguration speaker_drc_enabled="true"/>
+
+    <modules>
+        <!-- Primary module -->
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="primary input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000"
+                             channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+                <mixPort name="mixport_bt_hfp_output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="mixport_bt_hfp_input" role="sink">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="8000,11025,16000,44100,48000"
+                             channelMasks="AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_MONO"/>
+                </mixPort>
+            </mixPorts>
+            <devicePorts>
+                <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
+                </devicePort>
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                </devicePort>
+                <devicePort tagName="Hdmi" type="AUDIO_DEVICE_OUT_HDMI" role="sink">
+                </devicePort>
+                <devicePort tagName="Hdmi-In Mic" type="AUDIO_DEVICE_IN_HDMI" role="source">
+                </devicePort>
+                <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"
+                            role="sink" address="hfp_client_out">
+                </devicePort>
+                <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"
+                            role="source" address="hfp_client_in">
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="Speaker"
+                       sources="primary output"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic,Hdmi-In Mic"/>
+                <route type="mix" sink="Hdmi"
+                       sources="primary output"/>
+                <route type="mix" sink="BT SCO"
+                       sources="mixport_bt_hfp_output"/>
+                <route type="mix" sink="mixport_bt_hfp_input"
+                       sources="BT SCO Headset Mic"/>
+            </routes>
+        </module>
+
+        <!-- Remote Submix module -->
+        <module name="r_submix" halVersion="2.0">
+            <attachedDevices>
+                <item>Remote Submix In</item>
+            </attachedDevices>
+            <mixPorts>
+                <mixPort name="r_submix output" role="source">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="r_submix input" role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </mixPort>
+           </mixPorts>
+           <devicePorts>
+               <devicePort tagName="Remote Submix Out" type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"  role="sink">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+               </devicePort>
+               <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX"  role="source">
+                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="Remote Submix Out"
+                       sources="r_submix output"/>
+                <route type="mix" sink="r_submix input"
+                       sources="Remote Submix In"/>
+            </routes>
+        </module>
+    </modules>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml
new file mode 100644
index 0000000..edc0adb
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <globalConfiguration speaker_drc_enabled="true"/>
+
+    <modules>
+        <!-- Primary module -->
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Speaker</item>
+                <item>Built-In Mic</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="primary 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">
+                </devicePort>
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                </devicePort>
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="Speaker"
+                       sources="primary output"/>
+                <route type="mix" sink="primary input"
+                       sources="Built-In Mic"/>
+            </routes>
+        </module>
+    </modules>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml b/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml
new file mode 100644
index 0000000..f1638f3
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <globalConfiguration speaker_drc_enabled="false"/>
+    <modules>
+        <module name="primary" halVersion="2.0">
+            <attachedDevices>
+                <item>Speaker</item>
+            </attachedDevices>
+            <defaultOutputDevice>Speaker</defaultOutputDevice>
+            <mixPorts>
+                <!-- Profiles on the HDMI port are explicit for simplicity. In reality they are dynamic -->
+                <!-- Note: ports are intentionally arranged from more specific to less
+                     specific in order to test b/140447125 for HW AV Sync, and similar "explicit matches" -->
+                <mixPort name="tunnel" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="low latency" role="source"
+                         flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="direct" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+                </mixPort>
+           </mixPorts>
+           <devicePorts>
+                <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink" />
+                <devicePort tagName="Out Aux Digital" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink" />
+            </devicePorts>
+            <routes>
+                <route type="mix" sink="Speaker" sources="primary output"/>
+                <route type="mix" sink="Out Aux Digital" sources="primary output,tunnel,direct,low latency"/>
+            </routes>
+        </module>
+    </modules>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/tests/systemaudio_tests.cpp b/services/audiopolicy/tests/systemaudio_tests.cpp
deleted file mode 100644
index abaae52..0000000
--- a/services/audiopolicy/tests/systemaudio_tests.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <gtest/gtest.h>
-
-#define LOG_TAG "SysAudio_Test"
-#include <log/log.h>
-#include <media/PatchBuilder.h>
-#include <system/audio.h>
-
-using namespace android;
-
-TEST(SystemAudioTest, PatchInvalid) {
-    audio_patch patch{};
-    ASSERT_FALSE(audio_patch_is_valid(&patch));
-    patch.num_sources = AUDIO_PATCH_PORTS_MAX + 1;
-    patch.num_sinks = 1;
-    ASSERT_FALSE(audio_patch_is_valid(&patch));
-    patch.num_sources = 1;
-    patch.num_sinks = AUDIO_PATCH_PORTS_MAX + 1;
-    ASSERT_FALSE(audio_patch_is_valid(&patch));
-    patch.num_sources = 0;
-    patch.num_sinks = 1;
-    ASSERT_FALSE(audio_patch_is_valid(&patch));
-}
-
-TEST(SystemAudioTest, PatchValid) {
-    const audio_port_config src = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE };
-    // It's OK not to have sinks.
-    ASSERT_TRUE(audio_patch_is_valid((PatchBuilder{}).addSource(src).patch()));
-    const audio_port_config sink = {
-        .id = 2, .role = AUDIO_PORT_ROLE_SINK, .type = AUDIO_PORT_TYPE_DEVICE };
-    ASSERT_TRUE(audio_patch_is_valid((PatchBuilder{}).addSource(src).addSink(sink).patch()));
-    ASSERT_TRUE(audio_patch_is_valid(
-                    (PatchBuilder{}).addSource(src).addSource(src).addSink(sink).patch()));
-    ASSERT_TRUE(audio_patch_is_valid(
-                    (PatchBuilder{}).addSource(src).addSink(sink).addSink(sink).patch()));
-    ASSERT_TRUE(audio_patch_is_valid(
-                    (PatchBuilder{}).addSource(src).addSource(src).
-                    addSink(sink).addSink(sink).patch()));
-}
-
-TEST(SystemAudioTest, PatchHwAvSync) {
-    audio_port_config device_src_cfg = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE };
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&device_src_cfg));
-    device_src_cfg.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&device_src_cfg));
-    device_src_cfg.flags.input = AUDIO_INPUT_FLAG_HW_AV_SYNC;
-    ASSERT_TRUE(audio_port_config_has_hw_av_sync(&device_src_cfg));
-
-    audio_port_config device_sink_cfg = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SINK, .type = AUDIO_PORT_TYPE_DEVICE };
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&device_sink_cfg));
-    device_sink_cfg.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&device_sink_cfg));
-    device_sink_cfg.flags.output = AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-    ASSERT_TRUE(audio_port_config_has_hw_av_sync(&device_sink_cfg));
-
-    audio_port_config mix_sink_cfg = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SINK, .type = AUDIO_PORT_TYPE_MIX };
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&mix_sink_cfg));
-    mix_sink_cfg.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&mix_sink_cfg));
-    mix_sink_cfg.flags.input = AUDIO_INPUT_FLAG_HW_AV_SYNC;
-    ASSERT_TRUE(audio_port_config_has_hw_av_sync(&mix_sink_cfg));
-
-    audio_port_config mix_src_cfg = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_MIX };
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&mix_src_cfg));
-    mix_src_cfg.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    ASSERT_FALSE(audio_port_config_has_hw_av_sync(&mix_src_cfg));
-    mix_src_cfg.flags.output = AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-    ASSERT_TRUE(audio_port_config_has_hw_av_sync(&mix_src_cfg));
-}
-
-TEST(SystemAudioTest, PatchEqual) {
-    const audio_patch patch1{}, patch2{};
-    // Invalid patches are not equal.
-    ASSERT_FALSE(audio_patches_are_equal(&patch1, &patch2));
-    const audio_port_config src = {
-        .id = 1, .role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE };
-    const audio_port_config sink = {
-        .id = 2, .role = AUDIO_PORT_ROLE_SINK, .type = AUDIO_PORT_TYPE_DEVICE };
-    ASSERT_FALSE(audio_patches_are_equal(
-                    (PatchBuilder{}).addSource(src).patch(),
-                    (PatchBuilder{}).addSource(src).addSink(sink).patch()));
-    ASSERT_TRUE(audio_patches_are_equal(
-                    (PatchBuilder{}).addSource(src).addSink(sink).patch(),
-                    (PatchBuilder{}).addSource(src).addSink(sink).patch()));
-    ASSERT_FALSE(audio_patches_are_equal(
-                    (PatchBuilder{}).addSource(src).addSink(sink).patch(),
-                    (PatchBuilder{}).addSource(src).addSource(src).addSink(sink).patch()));
-    audio_port_config sink_hw_av_sync = sink;
-    sink_hw_av_sync.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    sink_hw_av_sync.flags.output = AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-    ASSERT_FALSE(audio_patches_are_equal(
-                    (PatchBuilder{}).addSource(src).addSink(sink).patch(),
-                    (PatchBuilder{}).addSource(src).addSink(sink_hw_av_sync).patch()));
-    ASSERT_TRUE(audio_patches_are_equal(
-                    (PatchBuilder{}).addSource(src).addSink(sink_hw_av_sync).patch(),
-                    (PatchBuilder{}).addSource(src).addSink(sink_hw_av_sync).patch()));
-}
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1c1f5e6..501d922 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -26,7 +26,9 @@
         "CameraFlashlight.cpp",
         "common/Camera2ClientBase.cpp",
         "common/CameraDeviceBase.cpp",
+        "common/CameraOfflineSessionBase.cpp",
         "common/CameraProviderManager.cpp",
+        "common/DepthPhotoProcessor.cpp",
         "common/FrameProcessorBase.cpp",
         "api1/CameraClient.cpp",
         "api1/Camera2Client.cpp",
@@ -39,12 +41,15 @@
         "api1/client2/CaptureSequencer.cpp",
         "api1/client2/ZslProcessor.cpp",
         "api2/CameraDeviceClient.cpp",
+        "api2/CameraOfflineSessionClient.cpp",
         "api2/CompositeStream.cpp",
         "api2/DepthCompositeStream.cpp",
         "api2/HeicEncoderInfoManager.cpp",
         "api2/HeicCompositeStream.cpp",
         "device1/CameraHardwareInterface.cpp",
+        "device3/BufferUtils.cpp",
         "device3/Camera3Device.cpp",
+        "device3/Camera3OfflineSession.cpp",
         "device3/Camera3Stream.cpp",
         "device3/Camera3IOStreamBase.cpp",
         "device3/Camera3InputStream.cpp",
@@ -54,21 +59,32 @@
         "device3/StatusTracker.cpp",
         "device3/Camera3BufferManager.cpp",
         "device3/Camera3StreamSplitter.cpp",
+        "device3/CoordinateMapper.cpp",
         "device3/DistortionMapper.cpp",
+        "device3/ZoomRatioMapper.cpp",
+        "device3/RotateAndCropMapper.cpp",
+        "device3/Camera3OutputStreamInterface.cpp",
+        "device3/Camera3OutputUtils.cpp",
         "gui/RingBufferConsumer.cpp",
-        "utils/CameraThreadState.cpp",
         "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
         "hidl/Convert.cpp",
         "hidl/HidlCameraDeviceUser.cpp",
         "hidl/HidlCameraService.cpp",
+        "utils/CameraThreadState.cpp",
         "utils/CameraTraces.cpp",
         "utils/AutoConditionLock.cpp",
         "utils/ExifUtils.cpp",
+        "utils/SessionConfigurationUtils.cpp",
         "utils/TagMonitor.cpp",
         "utils/LatencyHistogram.cpp",
     ],
 
+    header_libs: [
+        "libmediadrm_headers",
+        "libmediametrics_headers",
+    ],
+
     shared_libs: [
         "libbase",
         "libdl",
@@ -83,30 +99,39 @@
         "libmediautils",
         "libcamera_client",
         "libcamera_metadata",
+        "libdynamic_depth",
         "libfmq",
         "libgui",
         "libhardware",
-        "libhwbinder",
         "libhidlbase",
-        "libhidltransport",
+        "libimage_io",
         "libjpeg",
+        "libmedia_codeclist",
         "libmedia_omx",
         "libmemunreachable",
         "libsensorprivacy",
         "libstagefright",
         "libstagefright_foundation",
+        "libxml2",
         "libyuv",
         "android.frameworks.cameraservice.common@2.0",
         "android.frameworks.cameraservice.service@2.0",
+        "android.frameworks.cameraservice.service@2.1",
         "android.frameworks.cameraservice.device@2.0",
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.6",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
         "android.hardware.camera.device@3.5",
+        "android.hardware.camera.device@3.6"
+    ],
+
+    static_libs: [
+        "libbinderthreadstateutils",
     ],
 
     export_shared_lib_headers: [
@@ -135,40 +160,3 @@
 
 }
 
-cc_library_shared {
-    name: "libdepthphoto",
-
-    srcs: [
-        "utils/ExifUtils.cpp",
-        "common/DepthPhotoProcessor.cpp",
-    ],
-
-    shared_libs: [
-        "libimage_io",
-        "libdynamic_depth",
-        "libxml2",
-        "liblog",
-        "libutilscallstack",
-        "libutils",
-        "libcutils",
-        "libjpeg",
-        "libmemunreachable",
-        "libexif",
-        "libcamera_client",
-    ],
-
-    include_dirs: [
-        "external/dynamic_depth/includes",
-        "external/dynamic_depth/internal",
-    ],
-
-    export_include_dirs: ["."],
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wno-ignored-qualifiers",
-    ],
-
-}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 670e026..af1e01d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -43,6 +43,7 @@
 #include <binder/PermissionController.h>
 #include <binder/ProcessInfoService.h>
 #include <binder/IResultReceiver.h>
+#include <binderthreadstate/CallerUtils.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 #include <cutils/misc.h>
@@ -56,12 +57,12 @@
 #include <media/IMediaHTTPService.h>
 #include <media/mediaplayer.h>
 #include <mediautils/BatteryNotifier.h>
-#include <sensorprivacy/SensorPrivacyManager.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
 #include <utils/SystemClock.h>
 #include <utils/Trace.h>
+#include <utils/CallStack.h>
 #include <private/android_filesystem_config.h>
 #include <system/camera_vendor_tags.h>
 #include <system/camera_metadata.h>
@@ -91,6 +92,8 @@
 using hardware::ICameraServiceListener;
 using hardware::camera::common::V1_0::CameraDeviceStatus;
 using hardware::camera::common::V1_0::TorchModeStatus;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera2::utils::ConcurrentCameraIdCombination;
 
 // ----------------------------------------------------------------------------
 // Logging support -- this is for debugging only
@@ -117,7 +120,12 @@
 
 // ----------------------------------------------------------------------------
 
+static const String16 sDumpPermission("android.permission.DUMP");
 static const String16 sManageCameraPermission("android.permission.MANAGE_CAMERA");
+static const String16 sCameraPermission("android.permission.CAMERA");
+static const String16 sSystemCameraPermission("android.permission.SYSTEM_CAMERA");
+static const String16
+        sCameraSendSystemEventsPermission("android.permission.CAMERA_SEND_SYSTEM_EVENTS");
 static const String16 sCameraOpenCloseListenerPermission(
         "android.permission.CAMERA_OPEN_CLOSE_LISTENER");
 
@@ -125,6 +133,7 @@
 static constexpr int32_t kVendorClientScore = 200;
 // Matches with PROCESS_STATE_PERSISTENT_UI in ActivityManager.java
 static constexpr int32_t kVendorClientState = 1;
+const String8 CameraService::kOfflineDevice("offline-");
 
 Mutex CameraService::sProxyMutex;
 sp<hardware::ICameraServiceProxy> CameraService::sCameraServiceProxy;
@@ -132,7 +141,9 @@
 CameraService::CameraService() :
         mEventLog(DEFAULT_EVENT_LOG_LENGTH),
         mNumberOfCameras(0),
-        mSoundRef(0), mInitialized(false) {
+        mNumberOfCamerasWithoutSystemCamera(0),
+        mSoundRef(0), mInitialized(false),
+        mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
     ALOGI("CameraService started (pid=%d)", getpid());
     mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
 }
@@ -159,6 +170,7 @@
     mUidPolicy->registerSelf();
     mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
     mSensorPrivacyPolicy->registerSelf();
+    mAppOps.setCameraAudioRestriction(mAudioRestriction);
     sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
     if (hcs->registerAsService() != android::OK) {
         ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -244,7 +256,7 @@
     Mutex::Autolock lock(mStatusListenerLock);
 
     for (auto& i : mListenerList) {
-        i.second->getListener()->onTorchStatusChanged(mapToInterface(status), String16{cameraId});
+        i->getListener()->onTorchStatusChanged(mapToInterface(status), String16{cameraId});
     }
 }
 
@@ -258,32 +270,62 @@
     enumerateProviders();
 }
 
-bool CameraService::isPublicallyHiddenSecureCamera(const String8& cameraId) {
+void CameraService::filterAPI1SystemCameraLocked(
+        const std::vector<std::string> &normalDeviceIds) {
+    mNormalDeviceIdsWithoutSystemCamera.clear();
+    for (auto &deviceId : normalDeviceIds) {
+        SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+        if (getSystemCameraKind(String8(deviceId.c_str()), &deviceKind) != OK) {
+            ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
+            continue;
+        }
+        if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+            // All system camera ids will necessarily come after public camera
+            // device ids as per the HAL interface contract.
+            break;
+        }
+        mNormalDeviceIdsWithoutSystemCamera.push_back(deviceId);
+    }
+    ALOGV("%s: number of API1 compatible public cameras is %zu", __FUNCTION__,
+              mNormalDeviceIdsWithoutSystemCamera.size());
+}
+
+status_t CameraService::getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const {
     auto state = getCameraState(cameraId);
     if (state != nullptr) {
-        return state->isPublicallyHiddenSecureCamera();
+        *kind = state->getSystemCameraKind();
+        return OK;
     }
     // Hidden physical camera ids won't have CameraState
-    return mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str());
+    return mCameraProviderManager->getSystemCameraKind(cameraId.c_str(), kind);
 }
 
 void CameraService::updateCameraNumAndIds() {
     Mutex::Autolock l(mServiceLock);
-    mNumberOfCameras = mCameraProviderManager->getCameraCount();
+    std::pair<int, int> systemAndNonSystemCameras = mCameraProviderManager->getCameraCount();
+    // Excludes hidden secure cameras
+    mNumberOfCameras =
+            systemAndNonSystemCameras.first + systemAndNonSystemCameras.second;
+    mNumberOfCamerasWithoutSystemCamera = systemAndNonSystemCameras.second;
     mNormalDeviceIds =
             mCameraProviderManager->getAPI1CompatibleCameraDeviceIds();
+    filterAPI1SystemCameraLocked(mNormalDeviceIds);
 }
 
 void CameraService::addStates(const String8 id) {
     std::string cameraId(id.c_str());
     hardware::camera::common::V1_0::CameraResourceCost cost;
     status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
+    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
     if (res != OK) {
         ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
         return;
     }
-    bool isPublicallyHiddenSecureCamera =
-            mCameraProviderManager->isPublicallyHiddenSecureCamera(id.string());
+    res = mCameraProviderManager->getSystemCameraKind(cameraId, &deviceKind);
+    if (res != OK) {
+        ALOGE("Failed to query device kind: %s (%d)", strerror(-res), res);
+        return;
+    }
     std::set<String8> conflicting;
     for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
         conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
@@ -292,8 +334,7 @@
     {
         Mutex::Autolock lock(mCameraStatesLock);
         mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
-                                                                conflicting,
-                                                                isPublicallyHiddenSecureCamera));
+                                                                conflicting, deviceKind));
     }
 
     if (mFlashlight->hasFlashUnit(id)) {
@@ -359,7 +400,7 @@
         // to this device until the status changes
         updateStatus(StatusInternal::NOT_PRESENT, id);
 
-        sp<BasicClient> clientToDisconnect;
+        sp<BasicClient> clientToDisconnectOnline, clientToDisconnectOffline;
         {
             // Don't do this in updateStatus to avoid deadlock over mServiceLock
             Mutex::Autolock lock(mServiceLock);
@@ -367,23 +408,14 @@
             // Remove cached shim parameters
             state->setShimParams(CameraParameters());
 
-            // Remove the client from the list of active clients, if there is one
-            clientToDisconnect = removeClientLocked(id);
+            // Remove online as well as offline client from the list of active clients,
+            // if they are present
+            clientToDisconnectOnline = removeClientLocked(id);
+            clientToDisconnectOffline = removeClientLocked(kOfflineDevice + id);
         }
 
-        // Disconnect client
-        if (clientToDisconnect.get() != nullptr) {
-            ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL",
-                    __FUNCTION__, id.string());
-            // Notify the client of disconnection
-            clientToDisconnect->notifyError(
-                    hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
-                    CaptureResultExtras{});
-            // Ensure not in binder RPC so client disconnect PID checks work correctly
-            LOG_ALWAYS_FATAL_IF(CameraThreadState::getCallingPid() != getpid(),
-                    "onDeviceStatusChanged must be called from the camera service process!");
-            clientToDisconnect->disconnect();
-        }
+        disconnectClient(id, clientToDisconnectOnline);
+        disconnectClient(kOfflineDevice + id, clientToDisconnectOffline);
 
         removeStates(id);
     } else {
@@ -393,7 +425,79 @@
         }
         updateStatus(newStatus, id);
     }
+}
 
+void CameraService::onDeviceStatusChanged(const String8& id,
+        const String8& physicalId,
+        CameraDeviceStatus newHalStatus) {
+    ALOGI("%s: Status changed for cameraId=%s, physicalCameraId=%s, newStatus=%d",
+            __FUNCTION__, id.string(), physicalId.string(), newHalStatus);
+
+    StatusInternal newStatus = mapToInternal(newHalStatus);
+
+    std::shared_ptr<CameraState> state = getCameraState(id);
+
+    if (state == nullptr) {
+        ALOGE("%s: Physical camera id %s status change on a non-present ID %s",
+                __FUNCTION__, id.string(), physicalId.string());
+        return;
+    }
+
+    StatusInternal logicalCameraStatus = state->getStatus();
+    if (logicalCameraStatus != StatusInternal::PRESENT &&
+            logicalCameraStatus != StatusInternal::NOT_AVAILABLE) {
+        ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
+                __FUNCTION__, physicalId.string(), newHalStatus, logicalCameraStatus);
+        return;
+    }
+
+    bool updated = false;
+    if (newStatus == StatusInternal::PRESENT) {
+        updated = state->removeUnavailablePhysicalId(physicalId);
+    } else {
+        updated = state->addUnavailablePhysicalId(physicalId);
+    }
+
+    if (updated) {
+        String8 idCombo = id + " : " + physicalId;
+        if (newStatus == StatusInternal::PRESENT) {
+            logDeviceAdded(idCombo,
+                    String8::format("Device status changed to %d", newStatus));
+        } else {
+            logDeviceRemoved(idCombo,
+                    String8::format("Device status changed to %d", newStatus));
+        }
+        // Avoid calling getSystemCameraKind() with mStatusListenerLock held (b/141756275)
+        SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+        if (getSystemCameraKind(id, &deviceKind) != OK) {
+            ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, id.string());
+            return;
+        }
+        String16 id16(id), physicalId16(physicalId);
+        Mutex::Autolock lock(mStatusListenerLock);
+        for (auto& listener : mListenerList) {
+            if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
+                    listener->getListenerPid(), listener->getListenerUid())) {
+                ALOGV("Skipping discovery callback for system-only camera device %s",
+                        id.c_str());
+                continue;
+            }
+            listener->getListener()->onPhysicalCameraStatusChanged(mapToInterface(newStatus),
+                    id16, physicalId16);
+        }
+    }
+}
+
+void CameraService::disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect) {
+    if (clientToDisconnect.get() != nullptr) {
+        ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL",
+                __FUNCTION__, id.string());
+        // Notify the client of disconnection
+        clientToDisconnect->notifyError(
+                hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
+                CaptureResultExtras{});
+        clientToDisconnect->disconnect();
+    }
 }
 
 void CameraService::onTorchStatusChanged(const String8& cameraId,
@@ -456,15 +560,31 @@
     broadcastTorchModeStatus(cameraId, newStatus);
 }
 
+static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+    return checkPermission(sSystemCameraPermission, callingPid, callingUid) &&
+            checkPermission(sCameraPermission, callingPid, callingUid);
+}
+
 Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
+    bool hasSystemCameraPermissions =
+            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+                    CameraThreadState::getCallingUid());
     switch (type) {
         case CAMERA_TYPE_BACKWARD_COMPATIBLE:
-            *numCameras = static_cast<int>(mNormalDeviceIds.size());
+            if (hasSystemCameraPermissions) {
+                *numCameras = static_cast<int>(mNormalDeviceIds.size());
+            } else {
+                *numCameras = static_cast<int>(mNormalDeviceIdsWithoutSystemCamera.size());
+            }
             break;
         case CAMERA_TYPE_ALL:
-            *numCameras = mNumberOfCameras;
+            if (hasSystemCameraPermissions) {
+                *numCameras = mNumberOfCameras;
+            } else {
+                *numCameras = mNumberOfCamerasWithoutSystemCamera;
+            }
             break;
         default:
             ALOGW("%s: Unknown camera type %d",
@@ -479,20 +599,31 @@
         CameraInfo* cameraInfo) {
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
+    std::string cameraIdStr = cameraIdIntToStrLocked(cameraId);
+    if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
+                "characteristics for system only device %s: ", cameraIdStr.c_str());
+    }
 
     if (!mInitialized) {
         return STATUS_ERROR(ERROR_DISCONNECTED,
                 "Camera subsystem is not available");
     }
-
-    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+    bool hasSystemCameraPermissions =
+            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+                    CameraThreadState::getCallingUid());
+    int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
+    if (hasSystemCameraPermissions) {
+        cameraIdBound = mNumberOfCameras;
+    }
+    if (cameraId < 0 || cameraId >= cameraIdBound) {
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
                 "CameraId is not valid");
     }
 
     Status ret = Status::ok();
     status_t err = mCameraProviderManager->getCameraInfo(
-            cameraIdIntToStrLocked(cameraId), cameraInfo);
+            cameraIdStr.c_str(), cameraInfo);
     if (err != OK) {
         ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                 "Error retrieving camera info from device %d: %s (%d)", cameraId,
@@ -503,13 +634,20 @@
 }
 
 std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
-    if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
+    const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
+    auto callingPid = CameraThreadState::getCallingPid();
+    auto callingUid = CameraThreadState::getCallingUid();
+    if (checkPermission(sSystemCameraPermission, callingPid, callingUid) ||
+            getpid() == callingPid) {
+        deviceIds = &mNormalDeviceIds;
+    }
+    if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(deviceIds->size())) {
         ALOGE("%s: input id %d invalid: valid range  (0, %zu)",
-                __FUNCTION__, cameraIdInt, mNormalDeviceIds.size());
+                __FUNCTION__, cameraIdInt, deviceIds->size());
         return std::string{};
     }
 
-    return mNormalDeviceIds[cameraIdInt];
+    return (*deviceIds)[cameraIdInt];
 }
 
 String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
@@ -531,16 +669,13 @@
                 "Camera subsystem is not available");;
     }
 
-    if (shouldRejectHiddenCameraConnection(String8(cameraId))) {
-        ALOGW("Attempting to retrieve characteristics for system-only camera id %s, rejected",
-              String8(cameraId).string());
-        return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
-                                "No camera device with ID \"%s\" currently available",
-                                String8(cameraId).string());
-
+    if (shouldRejectSystemCameraConnection(String8(cameraId))) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
+                "characteristics for system only device %s: ", String8(cameraId).string());
     }
 
     Status ret{};
+
     status_t res = mCameraProviderManager->getCameraCharacteristics(
             String8(cameraId).string(), cameraInfo);
     if (res != OK) {
@@ -548,13 +683,21 @@
                 "characteristics for device %s: %s (%d)", String8(cameraId).string(),
                 strerror(-res), res);
     }
-
+    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+    if (getSystemCameraKind(String8(cameraId), &deviceKind) != OK) {
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, String8(cameraId).string());
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
+                "for device %s", String8(cameraId).string());
+    }
     int callingPid = CameraThreadState::getCallingPid();
     int callingUid = CameraThreadState::getCallingUid();
     std::vector<int32_t> tagsRemoved;
-    // If it's not calling from cameraserver, check the permission.
+    // If it's not calling from cameraserver, check the permission only if
+    // android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
+    // it would've already been checked in shouldRejectSystemCameraConnection.
     if ((callingPid != getpid()) &&
-            !checkPermission(String16("android.permission.CAMERA"), callingPid, callingUid)) {
+            (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
+            !checkPermission(sCameraPermission, callingPid, callingUid)) {
         res = cameraInfo->removePermissionEntries(
                 mCameraProviderManager->getProviderTagIdLocked(String8(cameraId).string()),
                 &tagsRemoved);
@@ -658,9 +801,10 @@
 }
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
-        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-        int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
-        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+        const sp<IInterface>& cameraCb, const String16& packageName,
+        const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+        int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+        int deviceVersion, apiLevel effectiveApiLevel,
         /*out*/sp<BasicClient>* client) {
 
     if (halVersion < 0 || halVersion == deviceVersion) {
@@ -670,7 +814,7 @@
           case CAMERA_DEVICE_API_VERSION_1_0:
             if (effectiveApiLevel == API_1) {  // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new CameraClient(cameraService, tmp, packageName,
+                *client = new CameraClient(cameraService, tmp, packageName, featureId,
                         api1CameraId, facing, clientPid, clientUid,
                         getpid());
             } else { // Camera2 API route
@@ -686,17 +830,18 @@
           case CAMERA_DEVICE_API_VERSION_3_3:
           case CAMERA_DEVICE_API_VERSION_3_4:
           case CAMERA_DEVICE_API_VERSION_3_5:
+          case CAMERA_DEVICE_API_VERSION_3_6:
             if (effectiveApiLevel == API_1) { // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-                *client = new Camera2Client(cameraService, tmp, packageName,
+                *client = new Camera2Client(cameraService, tmp, packageName, featureId,
                         cameraId, api1CameraId,
                         facing, clientPid, clientUid,
                         servicePid);
             } else { // Camera2 API route
                 sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                         static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
-                *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
-                        facing, clientPid, clientUid, servicePid);
+                *client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
+                        cameraId, facing, clientPid, clientUid, servicePid);
             }
             break;
           default:
@@ -713,7 +858,7 @@
             halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
             // Only support higher HAL version device opened as HAL1.0 device.
             sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
-            *client = new CameraClient(cameraService, tmp, packageName,
+            *client = new CameraClient(cameraService, tmp, packageName, featureId,
                     api1CameraId, facing, clientPid, clientUid,
                     servicePid);
         } else {
@@ -813,7 +958,7 @@
     if (!(ret = connectHelper<ICameraClient,Client>(
             sp<ICameraClient>{nullptr}, id, cameraId,
             static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
-            internalPackageName, uid, USE_CALLING_PID,
+            internalPackageName, std::unique_ptr<String16>(), uid, USE_CALLING_PID,
             API_1, /*shimUpdateOnly*/ true, /*out*/ tmp)
             ).isOk()) {
         ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
@@ -994,9 +1139,26 @@
                 clientName8.string(), clientUid, clientPid);
     }
 
-    // If it's not calling from cameraserver, check the permission.
+    if (shouldRejectSystemCameraConnection(cameraId)) {
+        ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
+                cameraId.c_str());
+        return STATUS_ERROR_FMT(ERROR_DISCONNECTED, "No camera device with ID \"%s\" is"
+                                "available", cameraId.string());
+    }
+    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+    if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
+        return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "No camera device with ID \"%s\""
+                "found while trying to query device kind", cameraId.string());
+
+    }
+
+    // If it's not calling from cameraserver, check the permission if the
+    // device isn't a system only camera (shouldRejectSystemCameraConnection already checks for
+    // android.permission.SYSTEM_CAMERA for system only camera devices).
     if (callingPid != getpid() &&
-            !checkPermission(String16("android.permission.CAMERA"), clientPid, clientUid)) {
+                (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
+                !checkPermission(sCameraPermission, clientPid, clientUid)) {
         ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
         return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                 "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" without camera permission",
@@ -1032,7 +1194,7 @@
 
     // Only allow clients who are being used by the current foreground device user, unless calling
     // from our own process OR the caller is using the cameraserver's HIDL interface.
-    if (!hardware::IPCThreadState::self()->isServingCall() && callingPid != getpid() &&
+    if (getCurrentServingCall() != BinderCallType::HWBINDER && callingPid != getpid() &&
             (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
         ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
                 "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
@@ -1212,7 +1374,12 @@
             Mutex::Autolock l(mLogLock);
             mEventLog.add(msg);
 
-            return -EBUSY;
+            auto current = mActiveClientManager.get(cameraId);
+            if (current != nullptr) {
+                return -EBUSY; // CAMERA_IN_USE
+            } else {
+                return -EUSERS; // MAX_CAMERAS_IN_USE
+            }
         }
 
         for (auto& i : evicted) {
@@ -1309,8 +1476,8 @@
     String8 id = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
-            /*shimUpdateOnly*/ false, /*out*/client);
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, std::unique_ptr<String16>(),
+            clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
         logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1336,8 +1503,8 @@
     Status ret = Status::ok();
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
-            clientPackageName, clientUid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ false,
-            /*out*/client);
+            clientPackageName, std::unique_ptr<String16>(), clientUid, USE_CALLING_PID, API_1,
+            /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
         logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1349,22 +1516,69 @@
     return ret;
 }
 
-bool CameraService::shouldRejectHiddenCameraConnection(const String8 & cameraId) {
-    // If the thread serving this call is not a hwbinder thread and the caller
-    // isn't the cameraserver itself, and the camera id being requested is to be
-    // publically hidden, we should reject the connection.
-    if (!hardware::IPCThreadState::self()->isServingCall() &&
-            CameraThreadState::getCallingPid() != getpid() &&
-            isPublicallyHiddenSecureCamera(cameraId)) {
+bool CameraService::shouldSkipStatusUpdates(SystemCameraKind systemCameraKind,
+        bool isVendorListener, int clientPid, int clientUid) {
+    // If the client is not a vendor client, don't add listener if
+    //   a) the camera is a publicly hidden secure camera OR
+    //   b) the camera is a system only camera and the client doesn't
+    //      have android.permission.SYSTEM_CAMERA permissions.
+    if (!isVendorListener && (systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA ||
+            (systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
+            !hasPermissionsForSystemCamera(clientPid, clientUid)))) {
         return true;
     }
     return false;
 }
 
+bool CameraService::shouldRejectSystemCameraConnection(const String8& cameraId) const {
+    // Rules for rejection:
+    // 1) If cameraserver tries to access this camera device, accept the
+    //    connection.
+    // 2) The camera device is a publicly hidden secure camera device AND some
+    //    component is trying to access it on a non-hwbinder thread (generally a non HAL client),
+    //    reject it.
+    // 3) if the camera device is advertised by the camera HAL as SYSTEM_ONLY
+    //    and the serving thread is a non hwbinder thread, the client must have
+    //    android.permission.SYSTEM_CAMERA permissions to connect.
+
+    int cPid = CameraThreadState::getCallingPid();
+    int cUid = CameraThreadState::getCallingUid();
+    SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+    if (getSystemCameraKind(cameraId, &systemCameraKind) != OK) {
+        ALOGE("%s: Invalid camera id %s, ", __FUNCTION__, cameraId.c_str());
+        return true;
+    }
+
+    // (1) Cameraserver trying to connect, accept.
+    if (CameraThreadState::getCallingPid() == getpid()) {
+        return false;
+    }
+    // (2)
+    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
+            systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
+        ALOGW("Rejecting access to secure hidden camera %s", cameraId.c_str());
+        return true;
+    }
+    // (3) Here we only check for permissions if it is a system only camera device. This is since
+    //     getCameraCharacteristics() allows for calls to succeed (albeit after hiding some
+    //     characteristics) even if clients don't have android.permission.CAMERA. We do not want the
+    //     same behavior for system camera devices.
+    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
+            systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
+            !hasPermissionsForSystemCamera(cPid, cUid)) {
+        ALOGW("Rejecting access to system only camera %s, inadequete permissions",
+                cameraId.c_str());
+        return true;
+    }
+
+    return false;
+}
+
 Status CameraService::connectDevice(
         const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
         const String16& cameraId,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         int clientUid,
         /*out*/
         sp<hardware::camera2::ICameraDeviceUser>* device) {
@@ -1374,14 +1588,15 @@
     String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
     String16 clientPackageNameAdj = clientPackageName;
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         std::string vendorClient =
                 StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
         clientPackageNameAdj = String16(vendorClient.c_str());
     }
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
             /*api1CameraId*/-1,
-            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj, clientFeatureId,
             clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
 
     if(!ret.isOk()) {
@@ -1396,8 +1611,9 @@
 
 template<class CALLBACK, class CLIENT>
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-        int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
-        int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
+        int api1CameraId, int halVersion, const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+        apiLevel effectiveApiLevel, bool shimUpdateOnly,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
@@ -1410,14 +1626,6 @@
             (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
             static_cast<int>(effectiveApiLevel));
 
-    if (shouldRejectHiddenCameraConnection(cameraId)) {
-        ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
-              cameraId.c_str());
-        return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
-                                "No camera device with ID \"%s\" currently available",
-                                cameraId.string());
-
-    }
     sp<CLIENT> client = nullptr;
     {
         // Acquire mServiceLock and prevent other clients from connecting
@@ -1432,7 +1640,7 @@
                     cameraId.string(), clientName8.string(), clientPid);
         }
 
-        // Enforce client permissions and do basic sanity checks
+        // Enforce client permissions and do basic validity checks
         if(!(ret = validateConnectLocked(cameraId, clientName8,
                 /*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
             return ret;
@@ -1463,6 +1671,10 @@
                     return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                             "Higher-priority client using camera, ID \"%s\" currently unavailable",
                             cameraId.string());
+                case -EUSERS:
+                    return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
+                            "Too many cameras already open, cannot open camera \"%s\"",
+                            cameraId.string());
                 default:
                     return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                             "Unexpected error %s (%d) opening camera \"%s\"",
@@ -1488,7 +1700,7 @@
         }
 
         sp<BasicClient> tmp = nullptr;
-        if(!(ret = makeClient(this, cameraCb, clientPackageName,
+        if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
                 cameraId, api1CameraId, facing,
                 clientPid, clientUid, getpid(),
                 halVersion, deviceVersion, effectiveApiLevel,
@@ -1545,6 +1757,11 @@
             }
         }
 
+        // Set rotate-and-crop override behavior
+        if (mOverrideRotateAndCropMode != ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
+            client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
+        }
+
         if (shimUpdateOnly) {
             // If only updating legacy shim parameters, immediately disconnect client
             mServiceLock.unlock();
@@ -1562,6 +1779,77 @@
     return ret;
 }
 
+status_t CameraService::addOfflineClient(String8 cameraId, sp<BasicClient> offlineClient) {
+    if (offlineClient.get() == nullptr) {
+        return BAD_VALUE;
+    }
+
+    {
+        // Acquire mServiceLock and prevent other clients from connecting
+        std::unique_ptr<AutoConditionLock> lock =
+                AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
+
+        if (lock == nullptr) {
+            ALOGE("%s: (PID %d) rejected (too many other clients connecting)."
+                    , __FUNCTION__, offlineClient->getClientPid());
+            return TIMED_OUT;
+        }
+
+        auto onlineClientDesc = mActiveClientManager.get(cameraId);
+        if (onlineClientDesc.get() == nullptr) {
+            ALOGE("%s: No active online client using camera id: %s", __FUNCTION__,
+                    cameraId.c_str());
+            return BAD_VALUE;
+        }
+
+        // Offline clients do not evict or conflict with other online devices. Resource sharing
+        // conflicts are handled by the camera provider which will either succeed or fail before
+        // reaching this method.
+        const auto& onlinePriority = onlineClientDesc->getPriority();
+        auto offlineClientDesc = CameraClientManager::makeClientDescriptor(
+                kOfflineDevice + onlineClientDesc->getKey(), offlineClient, /*cost*/ 0,
+                /*conflictingKeys*/ std::set<String8>(), onlinePriority.getScore(),
+                onlineClientDesc->getOwnerId(), onlinePriority.getState());
+
+        // Allow only one offline device per camera
+        auto incompatibleClients = mActiveClientManager.getIncompatibleClients(offlineClientDesc);
+        if (!incompatibleClients.empty()) {
+            ALOGE("%s: Incompatible offline clients present!", __FUNCTION__);
+            return BAD_VALUE;
+        }
+
+        auto err = offlineClient->initialize(mCameraProviderManager, mMonitorTags);
+        if (err != OK) {
+            ALOGE("%s: Could not initialize offline client.", __FUNCTION__);
+            return err;
+        }
+
+        auto evicted = mActiveClientManager.addAndEvict(offlineClientDesc);
+        if (evicted.size() > 0) {
+            for (auto& i : evicted) {
+                ALOGE("%s: Invalid state: Offline client for camera %s was not removed ",
+                        __FUNCTION__, i->getKey().string());
+            }
+
+            LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, offline clients not evicted "
+                    "properly", __FUNCTION__);
+
+            return BAD_VALUE;
+        }
+
+        logConnectedOffline(offlineClientDesc->getKey(),
+                static_cast<int>(offlineClientDesc->getOwnerId()),
+                String8(offlineClient->getPackageName()));
+
+        sp<IBinder> remoteCallback = offlineClient->getRemote();
+        if (remoteCallback != nullptr) {
+            remoteCallback->linkToDeath(this);
+        }
+    } // lock is destroyed, allow further connect calls
+
+    return OK;
+}
+
 Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
         const sp<IBinder>& clientBinder) {
     Mutex::Autolock lock(mServiceLock);
@@ -1693,8 +1981,7 @@
     if (pid != selfPid) {
         // Ensure we're being called by system_server, or similar process with
         // permissions to notify the camera service about system events
-        if (!checkCallingPermission(
-                String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
+        if (!checkCallingPermission(sCameraSendSystemEventsPermission)) {
             const int uid = CameraThreadState::getCallingUid();
             ALOGE("Permission Denial: cannot send updates to camera service about system"
                     " events from pid=%d, uid=%d", pid, uid);
@@ -1729,7 +2016,7 @@
     Mutex::Autolock lock(mStatusListenerLock);
 
     for (const auto& it : mListenerList) {
-        auto ret = it.second->getListener()->onCameraAccessPrioritiesChanged();
+        auto ret = it->getListener()->onCameraAccessPrioritiesChanged();
         if (!ret.isOk()) {
             ALOGE("%s: Failed to trigger permission callback: %d", __FUNCTION__,
                     ret.exceptionCode());
@@ -1745,8 +2032,7 @@
     if (pid != selfPid) {
         // Ensure we're being called by system_server, or similar process with
         // permissions to notify the camera service about system events
-        if (!checkCallingPermission(
-                String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
+        if (!checkCallingPermission(sCameraSendSystemEventsPermission)) {
             const int uid = CameraThreadState::getCallingUid();
             ALOGE("Permission Denial: cannot send updates to camera service about device"
                     " state changes from pid=%d, uid=%d", pid, uid);
@@ -1780,6 +2066,83 @@
     return Status::ok();
 }
 
+ Status CameraService::getConcurrentCameraIds(
+        std::vector<ConcurrentCameraIdCombination>* concurrentCameraIds) {
+    ATRACE_CALL();
+    if (!concurrentCameraIds) {
+        ALOGE("%s: concurrentCameraIds is NULL", __FUNCTION__);
+        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "concurrentCameraIds is NULL");
+    }
+
+    if (!mInitialized) {
+        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+        return STATUS_ERROR(ERROR_DISCONNECTED,
+                "Camera subsystem is not available");
+    }
+    // First call into the provider and get the set of concurrent camera
+    // combinations
+    std::vector<std::unordered_set<std::string>> concurrentCameraCombinations =
+            mCameraProviderManager->getConcurrentCameraIds();
+    for (auto &combination : concurrentCameraCombinations) {
+        std::vector<std::string> validCombination;
+        for (auto &cameraId : combination) {
+            // if the camera state is not present, skip
+            String8 cameraIdStr(cameraId.c_str());
+            auto state = getCameraState(cameraIdStr);
+            if (state == nullptr) {
+                ALOGW("%s: camera id %s does not exist", __FUNCTION__, cameraId.c_str());
+                continue;
+            }
+            StatusInternal status = state->getStatus();
+            if (status == StatusInternal::NOT_PRESENT || status == StatusInternal::ENUMERATING) {
+                continue;
+            }
+            if (shouldRejectSystemCameraConnection(cameraIdStr)) {
+                continue;
+            }
+            validCombination.push_back(cameraId);
+        }
+        if (validCombination.size() != 0) {
+            concurrentCameraIds->push_back(std::move(validCombination));
+        }
+    }
+    return Status::ok();
+}
+
+Status CameraService::isConcurrentSessionConfigurationSupported(
+        const std::vector<CameraIdAndSessionConfiguration>& cameraIdsAndSessionConfigurations,
+        /*out*/bool* isSupported) {
+    if (!isSupported) {
+        ALOGE("%s: isSupported is NULL", __FUNCTION__);
+        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "isSupported is NULL");
+    }
+
+    if (!mInitialized) {
+        ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
+        return STATUS_ERROR(ERROR_DISCONNECTED,
+                "Camera subsystem is not available");
+    }
+
+    // Check for camera permissions
+    int callingPid = CameraThreadState::getCallingPid();
+    int callingUid = CameraThreadState::getCallingUid();
+    if ((callingPid != getpid()) && !checkPermission(sCameraPermission, callingPid, callingUid)) {
+        ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
+        return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+                "android.permission.CAMERA needed to call"
+                "isConcurrentSessionConfigurationSupported");
+    }
+
+    status_t res =
+            mCameraProviderManager->isConcurrentSessionConfigurationSupported(
+                    cameraIdsAndSessionConfigurations, isSupported);
+    if (res != OK) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to query session configuration "
+                "support %s (%d)", strerror(-res), res);
+    }
+    return Status::ok();
+}
+
 Status CameraService::addListener(const sp<ICameraServiceListener>& listener,
         /*out*/
         std::vector<hardware::CameraStatus> *cameraStatuses) {
@@ -1800,24 +2163,26 @@
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Null listener given to addListener");
     }
 
+    auto clientUid = CameraThreadState::getCallingUid();
+    auto clientPid = CameraThreadState::getCallingPid();
+    bool openCloseCallbackAllowed = checkPermission(sCameraOpenCloseListenerPermission,
+            clientPid, clientUid);
+
     Mutex::Autolock lock(mServiceLock);
 
     {
         Mutex::Autolock lock(mStatusListenerLock);
         for (const auto &it : mListenerList) {
-            if (IInterface::asBinder(it.second->getListener()) == IInterface::asBinder(listener)) {
+            if (IInterface::asBinder(it->getListener()) == IInterface::asBinder(listener)) {
                 ALOGW("%s: Tried to add listener %p which was already subscribed",
                       __FUNCTION__, listener.get());
                 return STATUS_ERROR(ERROR_ALREADY_EXISTS, "Listener already registered");
             }
         }
 
-        auto clientUid = CameraThreadState::getCallingUid();
-        auto clientPid = CameraThreadState::getCallingPid();
-        bool openCloseCallbackAllowed = checkPermission(sCameraOpenCloseListenerPermission,
-                clientPid, clientUid);
-        sp<ServiceListener> serviceListener = new ServiceListener(this, listener,
-                clientUid, clientPid, openCloseCallbackAllowed);
+        sp<ServiceListener> serviceListener =
+                new ServiceListener(this, listener, clientUid, clientPid, isVendorListener,
+                        openCloseCallbackAllowed);
         auto ret = serviceListener->initialize();
         if (ret != NO_ERROR) {
             String8 msg = String8::format("Failed to initialize service listener: %s (%d)",
@@ -1825,7 +2190,10 @@
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
         }
-        mListenerList.emplace_back(isVendorListener, serviceListener);
+        // The listener still needs to be added to the list of listeners, regardless of what
+        // permissions the listener process has / whether it is a vendor listener. Since it might be
+        // eligible to listen to other camera ids.
+        mListenerList.emplace_back(serviceListener);
         mUidPolicy->registerMonitorUid(clientUid);
     }
 
@@ -1833,24 +2201,25 @@
     {
         Mutex::Autolock lock(mCameraStatesLock);
         for (auto& i : mCameraStates) {
-            cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus()));
+            cameraStatuses->emplace_back(i.first,
+                    mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds());
         }
     }
-
     // Remove the camera statuses that should be hidden from the client, we do
     // this after collecting the states in order to avoid holding
-    // mCameraStatesLock and mInterfaceLock (held in
-    // isPublicallyHiddenSecureCamera()) at the same time.
+    // mCameraStatesLock and mInterfaceLock (held in getSystemCameraKind()) at
+    // the same time.
     cameraStatuses->erase(std::remove_if(cameraStatuses->begin(), cameraStatuses->end(),
-                [this, &isVendorListener](const hardware::CameraStatus& s) {
-                    bool ret = !isVendorListener && isPublicallyHiddenSecureCamera(s.cameraId);
-                    if (ret) {
-                        ALOGV("Cannot add public listener for hidden system-only %s for pid %d",
-                                s.cameraId.c_str(), CameraThreadState::getCallingPid());
+                [this, &isVendorListener, &clientPid, &clientUid](const hardware::CameraStatus& s) {
+                    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+                    if (getSystemCameraKind(s.cameraId, &deviceKind) != OK) {
+                        ALOGE("%s: Invalid camera id %s, skipping status update",
+                                __FUNCTION__, s.cameraId.c_str());
+                        return true;
                     }
-                    return ret;
-                }),
-                cameraStatuses->end());
+                    return shouldSkipStatusUpdates(deviceKind, isVendorListener, clientPid,
+                            clientUid);}), cameraStatuses->end());
+
 
     /*
      * Immediately signal current torch status to this listener only
@@ -1882,9 +2251,9 @@
     {
         Mutex::Autolock lock(mStatusListenerLock);
         for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) {
-            if (IInterface::asBinder(it->second->getListener()) == IInterface::asBinder(listener)) {
-                mUidPolicy->unregisterMonitorUid(it->second->getListenerUid());
-                IInterface::asBinder(listener)->unlinkToDeath(it->second);
+            if (IInterface::asBinder((*it)->getListener()) == IInterface::asBinder(listener)) {
+                mUidPolicy->unregisterMonitorUid((*it)->getListenerUid());
+                IInterface::asBinder(listener)->unlinkToDeath(*it);
                 mListenerList.erase(it);
                 return Status::ok();
             }
@@ -1960,6 +2329,7 @@
         case CAMERA_DEVICE_API_VERSION_3_3:
         case CAMERA_DEVICE_API_VERSION_3_4:
         case CAMERA_DEVICE_API_VERSION_3_5:
+        case CAMERA_DEVICE_API_VERSION_3_6:
             ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",
                     __FUNCTION__, id.string());
             *isSupported = true;
@@ -2000,6 +2370,7 @@
             mActiveClientManager.remove(i);
         }
     }
+    updateAudioRestrictionLocked();
 }
 
 bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
@@ -2164,6 +2535,13 @@
             clientPackage, clientPid));
 }
 
+void CameraService::logDisconnectedOffline(const char* cameraId, int clientPid,
+        const char* clientPackage) {
+    // Log the clients evicted
+    logEvent(String8::format("DISCONNECT offline device %s client for package %s (PID %d)",
+                cameraId, clientPackage, clientPid));
+}
+
 void CameraService::logConnected(const char* cameraId, int clientPid,
         const char* clientPackage) {
     // Log the clients evicted
@@ -2171,6 +2549,13 @@
             clientPackage, clientPid));
 }
 
+void CameraService::logConnectedOffline(const char* cameraId, int clientPid,
+        const char* clientPackage) {
+    // Log the clients evicted
+    logEvent(String8::format("CONNECT offline device %s client for package %s (PID %d)", cameraId,
+            clientPackage, clientPid));
+}
+
 void CameraService::logRejected(const char* cameraId, int clientPid,
         const char* clientPackage, const char* reason) {
     // Log the client rejected
@@ -2329,13 +2714,14 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraIdStr,
         int api1CameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid) :
         CameraService::BasicClient(cameraService,
                 IInterface::asBinder(cameraClient),
-                clientPackageName,
+                clientPackageName, clientFeatureId,
                 cameraIdStr, cameraFacing,
                 clientPid, clientUid,
                 servicePid),
@@ -2365,16 +2751,24 @@
 
 CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
         const sp<IBinder>& remoteCallback,
-        const String16& clientPackageName,
+        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraIdStr, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid):
         mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
-        mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
+        mClientPackageName(clientPackageName),
+        mClientPid(clientPid), mClientUid(clientUid),
         mServicePid(servicePid),
-        mDisconnected(false),
+        mDisconnected(false), mUidIsTrusted(false),
+        mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
         mRemoteBinder(remoteCallback)
 {
+    if (clientFeatureId) {
+        mClientFeatureId = std::unique_ptr<String16>(new String16(*clientFeatureId));
+    } else {
+        mClientFeatureId = std::unique_ptr<String16>();
+    }
+
     if (sCameraService == nullptr) {
         sCameraService = cameraService;
     }
@@ -2411,9 +2805,11 @@
         }
         mClientPackageName = packages[0];
     }
-    if (!hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() != BinderCallType::HWBINDER) {
         mAppOpsManager = std::make_unique<AppOpsManager>();
     }
+
+    mUidIsTrusted = isTrustedCallingUid(mClientUid);
 }
 
 CameraService::BasicClient::~BasicClient() {
@@ -2476,6 +2872,35 @@
     return level == API_2;
 }
 
+status_t CameraService::BasicClient::setAudioRestriction(int32_t mode) {
+    {
+        Mutex::Autolock l(mAudioRestrictionLock);
+        mAudioRestriction = mode;
+    }
+    sCameraService->updateAudioRestriction();
+    return OK;
+}
+
+int32_t CameraService::BasicClient::getServiceAudioRestriction() const {
+    return sCameraService->updateAudioRestriction();
+}
+
+int32_t CameraService::BasicClient::getAudioRestriction() const {
+    Mutex::Autolock l(mAudioRestrictionLock);
+    return mAudioRestriction;
+}
+
+bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) {
+    switch (mode) {
+        case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE:
+        case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION:
+        case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION_SOUND:
+            return true;
+        default:
+            return false;
+    }
+}
+
 status_t CameraService::BasicClient::startCameraOps() {
     ATRACE_CALL();
 
@@ -2489,8 +2914,9 @@
         int32_t res;
         mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
                 mClientPackageName, mOpsCallback);
-        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
-                mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
+                mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
+                String16("start camera ") + String16(mCameraIdStr));
 
         if (res == AppOpsManager::MODE_ERRORED) {
             ALOGI("Camera %s: Access for \"%s\" has been revoked",
@@ -2498,7 +2924,9 @@
             return PERMISSION_DENIED;
         }
 
-        if (res == AppOpsManager::MODE_IGNORED) {
+        // If the calling Uid is trusted (a native service), the AppOpsManager could
+        // return MODE_IGNORED. Do not treat such case as error.
+        if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
             ALOGI("Camera %s: Access for \"%s\" has been restricted",
                     mCameraIdStr.string(), String8(mClientPackageName).string());
             // Return the same error as for device policy manager rejection
@@ -2535,7 +2963,7 @@
         // Notify app ops that the camera is available again
         if (mAppOpsManager != nullptr) {
             mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
-                    mClientPackageName);
+                    mClientPackageName, mClientFeatureId);
             mOpsActive = false;
         }
         // This function is called when a client disconnects. This should
@@ -2575,6 +3003,7 @@
     if (mAppOpsManager == nullptr) {
         return;
     }
+    // TODO : add offline camera session case
     if (op != AppOpsManager::OP_CAMERA) {
         ALOGW("Unexpected app ops notification received: %d", op);
         return;
@@ -2652,14 +3081,13 @@
 void CameraService::UidPolicy::registerSelf() {
     Mutex::Autolock _l(mUidLock);
 
-    ActivityManager am;
     if (mRegistered) return;
-    am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+    status_t res = mAm.linkToDeath(this);
+    mAm.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
             | ActivityManager::UID_OBSERVER_IDLE
             | ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("cameraserver"));
-    status_t res = am.linkToDeath(this);
     if (res == OK) {
         mRegistered = true;
         ALOGV("UidPolicy: Registered with ActivityManager");
@@ -2669,9 +3097,8 @@
 void CameraService::UidPolicy::unregisterSelf() {
     Mutex::Autolock _l(mUidLock);
 
-    ActivityManager am;
-    am.unregisterUidObserver(this);
-    am.unlinkToDeath(this);
+    mAm.unregisterUidObserver(this);
+    mAm.unlinkToDeath(this);
     mRegistered = false;
     mActiveUids.clear();
     ALOGV("UidPolicy: Unregistered with ActivityManager");
@@ -2703,7 +3130,7 @@
 }
 
 void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
-        int64_t /*procStateSeq*/) {
+        int64_t procStateSeq __unused, int32_t capability __unused) {
     bool procStateChange = false;
     {
         Mutex::Autolock _l(mUidLock);
@@ -2867,10 +3294,9 @@
     if (mRegistered) {
         return;
     }
-    SensorPrivacyManager spm;
-    spm.addSensorPrivacyListener(this);
-    mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
-    status_t res = spm.linkToDeath(this);
+    mSpm.addSensorPrivacyListener(this);
+    mSensorPrivacyEnabled = mSpm.isSensorPrivacyEnabled();
+    status_t res = mSpm.linkToDeath(this);
     if (res == OK) {
         mRegistered = true;
         ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
@@ -2879,9 +3305,8 @@
 
 void CameraService::SensorPrivacyPolicy::unregisterSelf() {
     Mutex::Autolock _l(mSensorPrivacyLock);
-    SensorPrivacyManager spm;
-    spm.removeSensorPrivacyListener(this);
-    spm.unlinkToDeath(this);
+    mSpm.removeSensorPrivacyListener(this);
+    mSpm.unlinkToDeath(this);
     mRegistered = false;
     ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager");
 }
@@ -2917,9 +3342,9 @@
 // ----------------------------------------------------------------------------
 
 CameraService::CameraState::CameraState(const String8& id, int cost,
-        const std::set<String8>& conflicting, bool isHidden) : mId(id),
+        const std::set<String8>& conflicting, SystemCameraKind systemCameraKind) : mId(id),
         mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting),
-        mIsPublicallyHiddenSecureCamera(isHidden) {}
+        mSystemCameraKind(systemCameraKind) {}
 
 CameraService::CameraState::~CameraState() {}
 
@@ -2928,6 +3353,12 @@
     return mStatus;
 }
 
+std::vector<String8> CameraService::CameraState::getUnavailablePhysicalIds() const {
+    Mutex::Autolock lock(mStatusLock);
+    std::vector<String8> res(mUnavailablePhysicalIds.begin(), mUnavailablePhysicalIds.end());
+    return res;
+}
+
 CameraParameters CameraService::CameraState::getShimParams() const {
     return mShimParams;
 }
@@ -2948,8 +3379,20 @@
     return mId;
 }
 
-bool CameraService::CameraState::isPublicallyHiddenSecureCamera() const {
-    return mIsPublicallyHiddenSecureCamera;
+SystemCameraKind CameraService::CameraState::getSystemCameraKind() const {
+    return mSystemCameraKind;
+}
+
+bool CameraService::CameraState::addUnavailablePhysicalId(const String8& physicalId) {
+    Mutex::Autolock lock(mStatusLock);
+    auto result = mUnavailablePhysicalIds.insert(physicalId);
+    return result.second;
+}
+
+bool CameraService::CameraState::removeUnavailablePhysicalId(const String8& physicalId) {
+    Mutex::Autolock lock(mStatusLock);
+    auto count = mUnavailablePhysicalIds.erase(physicalId);
+    return count > 0;
 }
 
 // ----------------------------------------------------------------------------
@@ -3044,7 +3487,7 @@
         const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
         int32_t state) {
 
-    bool isVendorClient = hardware::IPCThreadState::self()->isServingCall();
+    bool isVendorClient = getCurrentServingCall() == BinderCallType::HWBINDER;
     int32_t score_adj = isVendorClient ? kVendorClientScore : score;
     int32_t state_adj = isVendorClient ? kVendorClientState: state;
 
@@ -3080,7 +3523,7 @@
 status_t CameraService::dump(int fd, const Vector<String16>& args) {
     ATRACE_CALL();
 
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+    if (checkCallingPermission(sDumpPermission) == false) {
         dprintf(fd, "Permission Denial: can't dump CameraService from pid=%d, uid=%d\n",
                 CameraThreadState::getCallingPid(),
                 CameraThreadState::getCallingUid());
@@ -3104,6 +3547,8 @@
     dprintf(fd, "\n== Service global info: ==\n\n");
     dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras);
     dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size());
+    dprintf(fd, "Number of public camera devices visible to API1: %zu\n",
+            mNormalDeviceIdsWithoutSystemCamera.size());
     for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
         dprintf(fd, "    Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
     }
@@ -3287,10 +3732,28 @@
                 cameraId.string());
         return;
     }
-    bool isHidden = isPublicallyHiddenSecureCamera(cameraId);
+
+    // Avoid calling getSystemCameraKind() with mStatusListenerLock held (b/141756275)
+    SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+    if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
+        return;
+    }
+    bool supportsHAL3 = false;
+    // supportsCameraApi also holds mInterfaceMutex, we can't call it in the
+    // HIDL onStatusChanged wrapper call (we'll hold mStatusListenerLock and
+    // mInterfaceMutex together, which can lead to deadlocks)
+    binder::Status sRet =
+            supportsCameraApi(String16(cameraId), hardware::ICameraService::API_VERSION_2,
+                    &supportsHAL3);
+    if (!sRet.isOk()) {
+        ALOGW("%s: Failed to determine if device supports HAL3 %s, supportsCameraApi call failed",
+                __FUNCTION__, cameraId.string());
+        return;
+    }
     // Update the status for this camera state, then send the onStatusChangedCallbacks to each
-    // of the listeners with both the mStatusStatus and mStatusListenerLock held
-    state->updateStatus(status, cameraId, rejectSourceStates, [this,&isHidden]
+    // of the listeners with both the mStatusLock and mStatusListenerLock held
+    state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &supportsHAL3]
             (const String8& cameraId, StatusInternal status) {
 
             if (status != StatusInternal::ENUMERATING) {
@@ -3311,13 +3774,18 @@
 
             Mutex::Autolock lock(mStatusListenerLock);
 
+            notifyPhysicalCameraStatusLocked(mapToInterface(status), cameraId, deviceKind);
+
             for (auto& listener : mListenerList) {
-                if (!listener.first &&  isHidden) {
-                    ALOGV("Skipping camera discovery callback for system-only camera %s",
-                          cameraId.c_str());
+                bool isVendorListener = listener->isVendorListener();
+                if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
+                        listener->getListenerPid(), listener->getListenerUid()) ||
+                        (isVendorListener && !supportsHAL3)) {
+                    ALOGV("Skipping discovery callback for system-only camera/HAL1 device %s",
+                            cameraId.c_str());
                     continue;
                 }
-                listener.second->getListener()->onStatusChanged(mapToInterface(status),
+                listener->getListener()->onStatusChanged(mapToInterface(status),
                         String16(cameraId));
             }
         });
@@ -3328,16 +3796,16 @@
     Mutex::Autolock lock(mStatusListenerLock);
 
     for (const auto& it : mListenerList) {
-        if (!it.second->isOpenCloseCallbackAllowed()) {
+        if (!it->isOpenCloseCallbackAllowed()) {
             continue;
         }
 
         binder::Status ret;
         String16 cameraId64(cameraId);
         if (open) {
-            ret = it.second->getListener()->onCameraOpened(cameraId64, clientPackageName);
+            ret = it->getListener()->onCameraOpened(cameraId64, clientPackageName);
         } else {
-            ret = it.second->getListener()->onCameraClosed(cameraId64);
+            ret = it->getListener()->onCameraClosed(cameraId64);
         }
         if (!ret.isOk()) {
             ALOGE("%s: Failed to trigger onCameraOpened/onCameraClosed callback: %d", __FUNCTION__,
@@ -3424,6 +3892,35 @@
     return OK;
 }
 
+void CameraService::notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId,
+        SystemCameraKind deviceKind) {
+    Mutex::Autolock lock(mCameraStatesLock);
+    for (const auto& state : mCameraStates) {
+        std::vector<std::string> physicalCameraIds;
+        if (!mCameraProviderManager->isLogicalCamera(state.first.c_str(), &physicalCameraIds)) {
+            // This is not a logical multi-camera.
+            continue;
+        }
+        if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(), cameraId.c_str())
+                == physicalCameraIds.end()) {
+            // cameraId is not a physical camera of this logical multi-camera.
+            continue;
+        }
+
+        String16 id16(state.first), physicalId16(cameraId);
+        for (auto& listener : mListenerList) {
+            if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
+                    listener->getListenerPid(), listener->getListenerUid())) {
+                ALOGV("Skipping discovery callback for system-only camera device %s",
+                        cameraId.c_str());
+                continue;
+            }
+            listener->getListener()->onPhysicalCameraStatusChanged(status,
+                    id16, physicalId16);
+        }
+    }
+}
+
 void CameraService::blockClientsForUid(uid_t uid) {
     const auto clients = mActiveClientManager.getAll();
     for (auto& current : clients) {
@@ -3462,6 +3959,10 @@
         return handleResetUidState(args, err);
     } else if (args.size() >= 2 && args[0] == String16("get-uid-state")) {
         return handleGetUidState(args, out, err);
+    } else if (args.size() >= 2 && args[0] == String16("set-rotate-and-crop")) {
+        return handleSetRotateAndCrop(args);
+    } else if (args.size() >= 1 && args[0] == String16("get-rotate-and-crop")) {
+        return handleGetRotateAndCrop(out);
     } else if (args.size() == 1 && args[0] == String16("help")) {
         printHelp(out);
         return NO_ERROR;
@@ -3532,12 +4033,65 @@
     }
 }
 
+status_t CameraService::handleSetRotateAndCrop(const Vector<String16>& args) {
+    int rotateValue = atoi(String8(args[1]));
+    if (rotateValue < ANDROID_SCALER_ROTATE_AND_CROP_NONE ||
+            rotateValue > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
+    Mutex::Autolock lock(mServiceLock);
+
+    mOverrideRotateAndCropMode = rotateValue;
+
+    if (rotateValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return OK;
+
+    const auto clients = mActiveClientManager.getAll();
+    for (auto& current : clients) {
+        if (current != nullptr) {
+            const auto basicClient = current->getValue();
+            if (basicClient.get() != nullptr) {
+                basicClient->setRotateAndCropOverride(rotateValue);
+            }
+        }
+    }
+
+    return OK;
+}
+
+status_t CameraService::handleGetRotateAndCrop(int out) {
+    Mutex::Autolock lock(mServiceLock);
+
+    return dprintf(out, "rotateAndCrop override: %d\n", mOverrideRotateAndCropMode);
+}
+
 status_t CameraService::printHelp(int out) {
     return dprintf(out, "Camera service commands:\n"
         "  get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
         "  set-uid-state <PACKAGE> <active|idle> [--user USER_ID] overrides the uid state\n"
         "  reset-uid-state <PACKAGE> [--user USER_ID] clears the uid state override\n"
+        "  set-rotate-and-crop <ROTATION> overrides the rotate-and-crop value for AUTO backcompat\n"
+        "      Valid values 0=0 deg, 1=90 deg, 2=180 deg, 3=270 deg, 4=No override\n"
+        "  get-rotate-and-crop returns the current override rotate-and-crop value\n"
         "  help print this message\n");
 }
 
+int32_t CameraService::updateAudioRestriction() {
+    Mutex::Autolock lock(mServiceLock);
+    return updateAudioRestrictionLocked();
+}
+
+int32_t CameraService::updateAudioRestrictionLocked() {
+    int32_t mode = 0;
+    // iterate through all active client
+    for (const auto& i : mActiveClientManager.getAll()) {
+        const auto clientSp = i->getValue();
+        mode |= clientSp->getAudioRestriction();
+    }
+
+    bool modeChanged = (mAudioRestriction != mode);
+    mAudioRestriction = mode;
+    if (modeChanged) {
+        mAppOps.setCameraAudioRestriction(mode);
+    }
+    return mode;
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index bcaca9f..4321201 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -25,17 +25,20 @@
 #include <cutils/multiuser.h>
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
+#include <binder/ActivityManager.h>
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IAppOpsCallback.h>
 #include <binder/IUidObserver.h>
 #include <hardware/camera.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
 
 #include <android/hardware/camera/common/1.0/types.h>
 
 #include <camera/VendorTagDescriptor.h>
 #include <camera/CaptureResult.h>
 #include <camera/CameraParameters.h>
+#include <camera/camera2/ConcurrentCamera.h>
 
 #include "CameraFlashlight.h"
 
@@ -67,9 +70,11 @@
 {
     friend class BinderService<CameraService>;
     friend class CameraClient;
+    friend class CameraOfflineSessionClient;
 public:
     class Client;
     class BasicClient;
+    class OfflineClient;
 
     // The effective API level.  The Camera2 API running in LEGACY mode counts as API_1.
     enum apiLevel {
@@ -100,6 +105,9 @@
 
     virtual void        onDeviceStatusChanged(const String8 &cameraId,
             hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+    virtual void        onDeviceStatusChanged(const String8 &cameraId,
+            const String8 &physicalCameraId,
+            hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
     virtual void        onTorchStatusChanged(const String8& cameraId,
             hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
     virtual void        onNewProviderRegistered() override;
@@ -133,7 +141,8 @@
 
     virtual binder::Status     connectDevice(
             const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
-            const String16& clientPackageName, int32_t clientUid,
+            const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+            int32_t clientUid,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
 
@@ -143,6 +152,14 @@
     virtual binder::Status    removeListener(
             const sp<hardware::ICameraServiceListener>& listener);
 
+    virtual binder::Status getConcurrentCameraIds(
+        /*out*/
+        std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination>* concurrentCameraIds);
+
+    virtual binder::Status isConcurrentSessionConfigurationSupported(
+        const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>& sessions,
+        /*out*/bool* supported);
+
     virtual binder::Status    getLegacyParameters(
             int32_t cameraId,
             /*out*/
@@ -182,6 +199,9 @@
     // Monitored UIDs availability notification
     void                notifyMonitoredUids();
 
+    // Register an offline client for a given active camera id
+    status_t addOfflineClient(String8 cameraId, sp<BasicClient> offlineClient);
+
     /////////////////////////////////////////////////////////////////////
     // Client functionality
 
@@ -257,10 +277,28 @@
 
         // Block the client form using the camera
         virtual void block();
+
+        // set audio restriction from client
+        // Will call into camera service and hold mServiceLock
+        virtual status_t setAudioRestriction(int32_t mode);
+
+        // Get current global audio restriction setting
+        // Will call into camera service and hold mServiceLock
+        virtual int32_t getServiceAudioRestriction() const;
+
+        // Get current audio restriction setting for this client
+        virtual int32_t getAudioRestriction() const;
+
+        static bool isValidAudioRestriction(int32_t mode);
+
+        // Override rotate-and-crop AUTO behavior
+        virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) = 0;
+
     protected:
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
                 const String16& clientPackageName,
+                const std::unique_ptr<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int cameraFacing,
                 int clientPid,
@@ -280,19 +318,23 @@
         const String8                   mCameraIdStr;
         const int                       mCameraFacing;
         String16                        mClientPackageName;
+        std::unique_ptr<String16>       mClientFeatureId;
         pid_t                           mClientPid;
         const uid_t                     mClientUid;
         const pid_t                     mServicePid;
         bool                            mDisconnected;
+        bool                            mUidIsTrusted;
+
+        mutable Mutex                   mAudioRestrictionLock;
+        int32_t                         mAudioRestriction;
 
         // - The app-side Binder interface to receive callbacks from us
         sp<IBinder>                     mRemoteBinder;   // immutable after constructor
 
         // permissions management
-        status_t                        startCameraOps();
-        status_t                        finishCameraOps();
+        virtual status_t                startCameraOps();
+        virtual status_t                finishCameraOps();
 
-    private:
         std::unique_ptr<AppOpsManager>  mAppOpsManager = nullptr;
 
         class OpsCallback : public BnAppOpsCallback {
@@ -348,6 +390,7 @@
         Client(const sp<CameraService>& cameraService,
                 const sp<hardware::ICameraClient>& cameraClient,
                 const String16& clientPackageName,
+                const std::unique_ptr<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int api1CameraId,
                 int cameraFacing,
@@ -438,6 +481,9 @@
 
     }; // class CameraClientManager
 
+    int32_t updateAudioRestriction();
+    int32_t updateAudioRestrictionLocked();
+
 private:
 
     typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus;
@@ -471,7 +517,7 @@
          * returned in the HAL's camera_info struct for each device.
          */
         CameraState(const String8& id, int cost, const std::set<String8>& conflicting,
-                bool isHidden);
+                SystemCameraKind deviceKind);
         virtual ~CameraState();
 
         /**
@@ -524,18 +570,31 @@
         String8 getId() const;
 
         /**
-         * Return if the camera device is a publically hidden secure camera
+         * Return the kind (SystemCameraKind) of this camera device.
          */
-        bool isPublicallyHiddenSecureCamera() const;
+        SystemCameraKind getSystemCameraKind() const;
 
+        /**
+         * Add/Remove the unavailable physical camera ID.
+         */
+        bool addUnavailablePhysicalId(const String8& physicalId);
+        bool removeUnavailablePhysicalId(const String8& physicalId);
+
+        /**
+         * Return the unavailable physical ids for this device.
+         *
+         * This method acquires mStatusLock.
+         */
+        std::vector<String8> getUnavailablePhysicalIds() const;
     private:
         const String8 mId;
         StatusInternal mStatus; // protected by mStatusLock
         const int mCost;
         std::set<String8> mConflicting;
+        std::set<String8> mUnavailablePhysicalIds;
         mutable Mutex mStatusLock;
         CameraParameters mShimParams;
-        const bool mIsPublicallyHiddenSecureCamera;
+        const SystemCameraKind mSystemCameraKind;
     }; // class CameraState
 
     // Observer for UID lifecycle enforcing that UIDs in idle
@@ -554,7 +613,8 @@
         void onUidGone(uid_t uid, bool disabled);
         void onUidActive(uid_t uid);
         void onUidIdle(uid_t uid, bool disabled);
-        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq);
+        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
+                int32_t capability);
 
         void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
         void removeOverrideUid(uid_t uid, String16 callingPackage);
@@ -571,6 +631,7 @@
 
         Mutex mUidLock;
         bool mRegistered;
+        ActivityManager mAm;
         wp<CameraService> mService;
         std::unordered_set<uid_t> mActiveUids;
         // Monitored uid map to cached procState and refCount pair
@@ -597,6 +658,7 @@
             virtual void binderDied(const wp<IBinder> &who);
 
         private:
+            SensorPrivacyManager mSpm;
             wp<CameraService> mService;
             Mutex mSensorPrivacyLock;
             bool mSensorPrivacyEnabled;
@@ -638,18 +700,36 @@
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial);
 
-    // Should an operation attempt on a cameraId be rejected, if the camera id is
-    // advertised as a publically hidden secure camera, by the camera HAL ?
-    bool shouldRejectHiddenCameraConnection(const String8& cameraId);
+    // Should an operation attempt on a cameraId be rejected ? (this can happen
+    // under various conditions. For example if a camera device is advertised as
+    // system only or hidden secure camera, amongst possible others.
+    bool shouldRejectSystemCameraConnection(const String8 & cameraId) const;
 
-    bool isPublicallyHiddenSecureCamera(const String8& cameraId);
+    // Should a device status update be skipped for a particular camera device ? (this can happen
+    // under various conditions. For example if a camera device is advertised as
+    // system only or hidden secure camera, amongst possible others.
+    static bool shouldSkipStatusUpdates(SystemCameraKind systemCameraKind, bool isVendorListener,
+            int clientPid, int clientUid);
+
+    // Gets the kind of camera device (i.e public, hidden secure or system only)
+    // getSystemCameraKind() needs mInterfaceMutex which might lead to deadlocks
+    // if held along with mStatusListenerLock (depending on lock ordering, b/141756275), it is
+    // recommended that we don't call this function with mStatusListenerLock held.
+    status_t getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const;
+
+    // Update the set of API1Compatible camera devices without including system
+    // cameras and secure cameras. This is used for hiding system only cameras
+    // from clients using camera1 api and not having android.permission.SYSTEM_CAMERA.
+    // This function expects @param normalDeviceIds, to have normalDeviceIds
+    // sorted in alpha-numeric order.
+    void filterAPI1SystemCameraLocked(const std::vector<std::string> &normalDeviceIds);
 
     // Single implementation shared between the various connect calls
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
             int api1CameraId, int halVersion, const String16& clientPackageName,
-            int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
-            /*out*/sp<CLIENT>& device);
+            const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+            apiLevel effectiveApiLevel, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
 
     // Lock guarding camera service state
     Mutex               mServiceLock;
@@ -746,6 +826,17 @@
     void logDisconnected(const char* cameraId, int clientPid, const char* clientPackage);
 
     /**
+     * Add an event log message that a client has been disconnected from offline device.
+     */
+    void logDisconnectedOffline(const char* cameraId, int clientPid, const char* clientPackage);
+
+    /**
+     * Add an event log message that an offline client has been connected.
+     */
+    void logConnectedOffline(const char* cameraId, int clientPid,
+            const char* clientPackage);
+
+    /**
      * Add an event log message that a client has been connected.
      */
     void logConnected(const char* cameraId, int clientPid, const char* clientPackage);
@@ -798,9 +889,14 @@
      */
     void updateCameraNumAndIds();
 
+    // Number of camera devices (excluding hidden secure cameras)
     int                 mNumberOfCameras;
+    // Number of camera devices (excluding hidden secure cameras and
+    // system cameras)
+    int                 mNumberOfCamerasWithoutSystemCamera;
 
     std::vector<std::string> mNormalDeviceIds;
+    std::vector<std::string> mNormalDeviceIdsWithoutSystemCamera;
 
     // sounds
     sp<MediaPlayer>     newMediaPlayer(const char *file);
@@ -817,9 +913,10 @@
     class ServiceListener : public virtual IBinder::DeathRecipient {
         public:
             ServiceListener(sp<CameraService> parent, sp<hardware::ICameraServiceListener> listener,
-                    int uid, int pid, bool openCloseCallbackAllowed) : mParent(parent),
-                    mListener(listener), mListenerUid(uid), mListenerPid(pid),
-                    mOpenCloseCallbackAllowed(openCloseCallbackAllowed) {}
+                    int uid, int pid, bool isVendorClient, bool openCloseCallbackAllowed)
+                    : mParent(parent), mListener(listener), mListenerUid(uid), mListenerPid(pid),
+                      mIsVendorListener(isVendorClient),
+                      mOpenCloseCallbackAllowed(openCloseCallbackAllowed) { }
 
             status_t initialize() {
                 return IInterface::asBinder(mListener)->linkToDeath(this);
@@ -835,18 +932,20 @@
             int getListenerUid() { return mListenerUid; }
             int getListenerPid() { return mListenerPid; }
             sp<hardware::ICameraServiceListener> getListener() { return mListener; }
+            bool isVendorListener() { return mIsVendorListener; }
             bool isOpenCloseCallbackAllowed() { return mOpenCloseCallbackAllowed; }
 
         private:
             wp<CameraService> mParent;
             sp<hardware::ICameraServiceListener> mListener;
-            int mListenerUid;
-            int mListenerPid;
+            int mListenerUid = -1;
+            int mListenerPid = -1;
+            bool mIsVendorListener = false;
             bool mOpenCloseCallbackAllowed = false;
     };
 
     // Guarded by mStatusListenerMutex
-    std::vector<std::pair<bool, sp<ServiceListener>>> mListenerList;
+    std::vector<sp<ServiceListener>> mListenerList;
 
     Mutex       mStatusListenerLock;
 
@@ -905,6 +1004,10 @@
     status_t setTorchStatusLocked(const String8 &cameraId,
             hardware::camera::common::V1_0::TorchModeStatus status);
 
+    // notify physical camera status when the physical camera is public.
+    void notifyPhysicalCameraStatusLocked(int32_t status, const String8& cameraId,
+            SystemCameraKind deviceKind);
+
     // IBinder::DeathRecipient implementation
     virtual void        binderDied(const wp<IBinder> &who);
 
@@ -938,6 +1041,12 @@
     // Gets the UID state
     status_t handleGetUidState(const Vector<String16>& args, int out, int err);
 
+    // Set the rotate-and-crop AUTO override behavior
+    status_t handleSetRotateAndCrop(const Vector<String16>& args);
+
+    // Get the rotate-and-crop AUTO override behavior
+    status_t handleGetRotateAndCrop(int out);
+
     // Prints the shell command help
     status_t printHelp(int out);
 
@@ -947,9 +1056,10 @@
     static String8 getFormattedCurrentTime();
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
-            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
-            int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
-            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+            const sp<IInterface>& cameraCb, const String16& packageName,
+            const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+            int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+            int deviceVersion, apiLevel effectiveApiLevel,
             /*out*/sp<BasicClient>* client);
 
     status_t checkCameraAccess(const String16& opPackageName);
@@ -969,6 +1079,22 @@
 
     void broadcastTorchModeStatus(const String8& cameraId,
             hardware::camera::common::V1_0::TorchModeStatus status);
+
+    void disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect);
+
+    // Regular online and offline devices must not be in conflict at camera service layer.
+    // Use separate keys for offline devices.
+    static const String8 kOfflineDevice;
+
+    // TODO: right now each BasicClient holds one AppOpsManager instance.
+    // We can refactor the code so all of clients share this instance
+    AppOpsManager mAppOps;
+
+    // Aggreated audio restriction mode for all camera clients
+    int32_t mAudioRestriction;
+
+    // Current override rotate-and-crop mode
+    uint8_t mOverrideRotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_AUTO;
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 162b50f..b043c0b 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -50,13 +50,14 @@
 Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraDeviceId,
         int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid):
-        Camera2ClientBase(cameraService, cameraClient, clientPackageName,
+        Camera2ClientBase(cameraService, cameraClient, clientPackageName, clientFeatureId,
                 cameraDeviceId, api1CameraId, cameraFacing,
                 clientPid, clientUid, servicePid),
         mParameters(api1CameraId, cameraFacing)
@@ -732,6 +733,10 @@
 
     ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
 
+    if (params.state == Parameters::DISCONNECTED) {
+        ALOGE("%s: Camera %d has been disconnected.", __FUNCTION__, mCameraId);
+        return INVALID_OPERATION;
+    }
     if ( (params.state == Parameters::PREVIEW ||
                     params.state == Parameters::RECORD ||
                     params.state == Parameters::VIDEO_SNAPSHOT)
@@ -959,6 +964,11 @@
         case Parameters::RECORD:
         case Parameters::PREVIEW:
             syncWithDevice();
+            // Due to flush a camera device sync is not a sufficient
+            // guarantee that the current client parameters are
+            // correctly applied. To resolve this wait for the current
+            // request id to return in the results.
+            waitUntilCurrentRequestIdLocked();
             res = stopStream();
             if (res != OK) {
                 ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
@@ -1767,6 +1777,14 @@
         case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
             ALOGW("%s: Received recoverable error %d from HAL - ignoring, requestId %" PRId32,
                     __FUNCTION__, errorCode, resultExtras.requestId);
+
+            if ((hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST == errorCode) ||
+                    (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT == errorCode)) {
+                Mutex::Autolock al(mLatestRequestMutex);
+
+                mLatestFailedRequestId = resultExtras.requestId;
+                mLatestRequestSignal.signal();
+            }
             mCaptureSequencer->notifyError(errorCode, resultExtras);
             return;
         default:
@@ -2253,6 +2271,65 @@
     return OK;
 }
 
+status_t Camera2Client::setAudioRestriction(int /*mode*/) {
+    // Empty implementation. setAudioRestriction is hidden interface and not
+    // supported by android.hardware.Camera API
+    return INVALID_OPERATION;
+}
+
+int32_t Camera2Client::getGlobalAudioRestriction() {
+    // Empty implementation. getAudioRestriction is hidden interface and not
+    // supported by android.hardware.Camera API
+    return INVALID_OPERATION;
+}
+
+status_t Camera2Client::setRotateAndCropOverride(uint8_t rotateAndCrop) {
+    if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
+
+    return mDevice->setRotateAndCropAutoBehavior(
+        static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
+}
+
+status_t Camera2Client::waitUntilCurrentRequestIdLocked() {
+    int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
+    if (activeRequestId != 0) {
+        auto res = waitUntilRequestIdApplied(activeRequestId,
+                mDevice->getExpectedInFlightDuration());
+        if (res == TIMED_OUT) {
+            ALOGE("%s: Camera %d: Timed out waiting for current request id to return in results!",
+                    __FUNCTION__, mCameraId);
+            return res;
+        } else if (res != OK) {
+            ALOGE("%s: Camera %d: Error while waiting for current request id to return in results!",
+                    __FUNCTION__, mCameraId);
+            return res;
+        }
+    }
+
+    return OK;
+}
+
+status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout) {
+    Mutex::Autolock l(mLatestRequestMutex);
+    while ((mLatestRequestId != requestId) && (mLatestFailedRequestId != requestId)) {
+        nsecs_t startTime = systemTime();
+
+        auto res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
+        if (res != OK) return res;
+
+        timeout -= (systemTime() - startTime);
+    }
+
+    return (mLatestRequestId == requestId) ? OK : DEAD_OBJECT;
+}
+
+void Camera2Client::notifyRequestId(int32_t requestId) {
+    Mutex::Autolock al(mLatestRequestMutex);
+
+    mLatestRequestId = requestId;
+    mLatestRequestSignal.signal();
+}
+
 const char* Camera2Client::kAutofocusLabel = "autofocus";
 const char* Camera2Client::kTakepictureLabel = "take_picture";
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index a9ea271..03ca44a 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -83,6 +83,9 @@
     virtual void            notifyError(int32_t errorCode,
                                         const CaptureResultExtras& resultExtras);
     virtual status_t        setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+    virtual status_t        setAudioRestriction(int mode);
+    virtual int32_t         getGlobalAudioRestriction();
+    virtual status_t        setRotateAndCropOverride(uint8_t rotateAndCrop);
 
     /**
      * Interface used by CameraService
@@ -91,6 +94,7 @@
     Camera2Client(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraDeviceId,
             int api1CameraId,
             int cameraFacing,
@@ -122,6 +126,8 @@
 
     camera2::SharedParameters& getParameters();
 
+    void notifyRequestId(int32_t requestId);
+
     int getPreviewStreamId() const;
     int getCaptureStreamId() const;
     int getCallbackStreamId() const;
@@ -227,6 +233,13 @@
     status_t initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
 
     bool isZslEnabledInStillTemplate();
+
+    mutable Mutex mLatestRequestMutex;
+    Condition mLatestRequestSignal;
+    int32_t mLatestRequestId = -1;
+    int32_t mLatestFailedRequestId = -1;
+    status_t waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout);
+    status_t waitUntilCurrentRequestIdLocked();
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index d65ac7b..892996c 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -34,11 +34,11 @@
 
 CameraClient::CameraClient(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
-        const String16& clientPackageName,
+        const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
         int cameraId, int cameraFacing,
         int clientPid, int clientUid,
         int servicePid):
-        Client(cameraService, cameraClient, clientPackageName,
+        Client(cameraService, cameraClient, clientPackageName, clientFeatureId,
                 String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
                 clientUid, servicePid)
 {
@@ -534,7 +534,7 @@
     }
 
     if (mHardware != nullptr) {
-        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->unsecurePointer());
         metadata->eType = kMetadataBufferTypeNativeHandleSource;
         metadata->pHandle = handle;
         mHardware->releaseRecordingFrame(dataPtr);
@@ -573,7 +573,7 @@
         }
 
         if (!disconnected) {
-            VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+            VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->unsecurePointer());
             metadata->eType = kMetadataBufferTypeNativeHandleSource;
             metadata->pHandle = handle;
             frames.push_back(dataPtr);
@@ -916,8 +916,12 @@
                 ALOGE("%s: dataPtr does not contain VideoNativeHandleMetadata!", __FUNCTION__);
                 return;
             }
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
             VideoNativeHandleMetadata *metadata =
-                (VideoNativeHandleMetadata*)(msg.dataPtr->pointer());
+                (VideoNativeHandleMetadata*)(msg.dataPtr->unsecurePointer());
             if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
                 handle = metadata->pHandle;
             }
@@ -1073,8 +1077,12 @@
 
         // Check if dataPtr contains a VideoNativeHandleMetadata.
         if (dataPtr->size() == sizeof(VideoNativeHandleMetadata)) {
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
             VideoNativeHandleMetadata *metadata =
-                (VideoNativeHandleMetadata*)(dataPtr->pointer());
+                (VideoNativeHandleMetadata*)(dataPtr->unsecurePointer());
             if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
                 handle = metadata->pHandle;
             }
@@ -1171,4 +1179,30 @@
     return INVALID_OPERATION;
 }
 
+status_t CameraClient::setAudioRestriction(int mode) {
+    if (!isValidAudioRestriction(mode)) {
+        ALOGE("%s: invalid audio restriction mode %d", __FUNCTION__, mode);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+    return BasicClient::setAudioRestriction(mode);
+}
+
+int32_t CameraClient::getGlobalAudioRestriction() {
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+    return BasicClient::getServiceAudioRestriction();
+}
+
+// API1->Device1 does not support this feature
+status_t CameraClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
+    return OK;
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 9530b6c..a7eb960 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -59,11 +59,16 @@
     virtual String8         getParameters() const;
     virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
     virtual status_t        setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+    virtual status_t        setAudioRestriction(int mode);
+    virtual int32_t         getGlobalAudioRestriction();
+
+    virtual status_t        setRotateAndCropOverride(uint8_t override);
 
     // Interface used by CameraService
     CameraClient(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             int cameraId,
             int cameraFacing,
             int clientPid,
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index 88799f9..0c01a91 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -265,7 +265,7 @@
     Mutex::Autolock l(mInputMutex);
     while (!mStartCapture) {
         res = mStartCaptureSignal.waitRelative(mInputMutex,
-                kWaitDuration);
+                kIdleWaitDuration);
         if (res == TIMED_OUT) break;
     }
     if (mStartCapture) {
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
index 727dd53..9475a39 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
@@ -111,6 +111,7 @@
      * Internal to CaptureSequencer
      */
     static const nsecs_t kWaitDuration = 100000000; // 100 ms
+    static const nsecs_t kIdleWaitDuration = 10000000; // 10 ms
     static const int kMaxTimeoutsForPrecaptureStart = 10; // 1 sec
     static const int kMaxTimeoutsForPrecaptureEnd = 20;  // 2 sec
     static const int kMaxTimeoutsForCaptureEnd    = 40;  // 4 sec
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index 683e84d..2daacd1 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -66,7 +66,7 @@
 }
 
 bool FrameProcessor::processSingleFrame(CaptureResult &frame,
-                                        const sp<CameraDeviceBase> &device) {
+                                        const sp<FrameProducer> &device) {
 
     sp<Camera2Client> client = mClient.promote();
     if (!client.get()) {
@@ -86,6 +86,12 @@
         process3aState(frame, client);
     }
 
+    if (mCurrentRequestId != frame.mResultExtras.requestId) {
+        mCurrentRequestId = frame.mResultExtras.requestId;
+
+        client->notifyRequestId(mCurrentRequestId);
+    }
+
     return FrameProcessorBase::processSingleFrame(frame, device);
 }
 
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.h b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
index 8183c12..bb985f6 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
@@ -24,6 +24,7 @@
 #include <utils/List.h>
 #include <camera/CameraMetadata.h>
 
+#include "common/CameraDeviceBase.h"
 #include "common/FrameProcessorBase.h"
 
 struct camera_frame_metadata;
@@ -54,7 +55,7 @@
     void processNewFrames(const sp<Camera2Client> &client);
 
     virtual bool processSingleFrame(CaptureResult &frame,
-                                    const sp<CameraDeviceBase> &device);
+                                    const sp<FrameProducer> &device);
 
     status_t processFaceDetect(const CameraMetadata &frame,
             const sp<Camera2Client> &client);
@@ -94,6 +95,7 @@
     };
 
     AlgState m3aState;
+    int32_t mCurrentRequestId = -1;
 
     // frame number -> pending 3A states that not all data are received yet.
     KeyedVector<int32_t, AlgState> mPending3AStates;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 18addb5..dbc863b 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -230,7 +230,7 @@
     previewFpsRange[1] = fastInfo.bestStillCaptureFpsRange[1];
 
     // PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but
-    // still have to do something sane for them
+    // still have to do something reasonable for them
 
     // NOTE: Not scaled like FPS range values are.
     int previewFps = fpsFromRange(previewFpsRange[0], previewFpsRange[1]);
@@ -2454,12 +2454,9 @@
 
     camera_metadata_ro_entry_t availableFocalLengths =
         staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, 0, 0, /*required*/false);
-    if (!availableFocalLengths.count && !fastInfo.isExternalCamera) return NO_INIT;
 
     // Find focal length in PREVIEW template to use as default focal length.
-    if (fastInfo.isExternalCamera) {
-        fastInfo.defaultFocalLength = -1.0;
-    } else {
+    if (availableFocalLengths.count) {
         // Find smallest (widest-angle) focal length to use as basis of still
         // picture FOV reporting.
         fastInfo.defaultFocalLength = availableFocalLengths.data.f[0];
@@ -2481,6 +2478,10 @@
         if (entry.count != 0) {
             fastInfo.defaultFocalLength = entry.data.f[0];
         }
+    } else if (fastInfo.isExternalCamera) {
+        fastInfo.defaultFocalLength = -1.0;
+    } else {
+        return NO_INIT;
     }
     return OK;
 }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 3587db3..e35b436 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -54,6 +54,7 @@
         const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
@@ -63,6 +64,7 @@
     BasicClient(cameraService,
             IInterface::asBinder(remoteCallback),
             clientPackageName,
+            clientFeatureId,
             cameraId,
             cameraFacing,
             clientPid,
@@ -78,12 +80,13 @@
 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid) :
-    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
+    Camera2ClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
                 cameraId, /*API1 camera ID*/ -1,
                 cameraFacing, clientPid, clientUid, servicePid),
     mInputStream(),
@@ -114,8 +117,8 @@
     threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
     mFrameProcessor->run(threadName.string());
 
-    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
-                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
+    mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+                                      camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
                                       /*listener*/this,
                                       /*sendPartials*/true);
 
@@ -467,7 +470,8 @@
 }
 
 binder::Status CameraDeviceClient::endConfigure(int operatingMode,
-        const hardware::camera2::impl::CameraMetadataNative& sessionParams) {
+        const hardware::camera2::impl::CameraMetadataNative& sessionParams,
+        std::vector<int>* offlineStreamIds /*out*/) {
     ATRACE_CALL();
     ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
             __FUNCTION__, mInputStream.configured ? 1 : 0,
@@ -476,13 +480,19 @@
     binder::Status res;
     if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
 
+    if (offlineStreamIds == nullptr) {
+        String8 msg = String8::format("Invalid offline stream ids");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
     Mutex::Autolock icl(mBinderSerializationLock);
 
     if (!mDevice.get()) {
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    res = checkOperatingModeLocked(operatingMode);
+    res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
     if (!res.isOk()) {
         return res;
     }
@@ -499,23 +509,49 @@
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     } else {
+        offlineStreamIds->clear();
+        mDevice->getOfflineStreamIds(offlineStreamIds);
+
         for (size_t i = 0; i < mCompositeStreamMap.size(); ++i) {
             err = mCompositeStreamMap.valueAt(i)->configureStream();
-            if (err != OK ) {
+            if (err != OK) {
                 String8 msg = String8::format("Camera %s: Error configuring composite "
                         "streams: %s (%d)", mCameraIdStr.string(), strerror(-err), err);
                 ALOGE("%s: %s", __FUNCTION__, msg.string());
                 res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
                 break;
             }
+
+            // Composite streams can only support offline mode in case all individual internal
+            // streams are also supported.
+            std::vector<int> internalStreams;
+            mCompositeStreamMap.valueAt(i)->insertCompositeStreamIds(&internalStreams);
+            offlineStreamIds->erase(
+                    std::remove_if(offlineStreamIds->begin(), offlineStreamIds->end(),
+                    [&internalStreams] (int streamId) {
+                        auto it = std::find(internalStreams.begin(), internalStreams.end(),
+                                streamId);
+                        if (it != internalStreams.end()) {
+                            internalStreams.erase(it);
+                            return true;
+                        }
+
+                        return false;}), offlineStreamIds->end());
+            if (internalStreams.empty()) {
+                offlineStreamIds->push_back(mCompositeStreamMap.valueAt(i)->getStreamId());
+            }
+        }
+
+        for (const auto& offlineStreamId : *offlineStreamIds) {
+            mStreamInfoMap[offlineStreamId].supportsOffline = true;
         }
     }
 
     return res;
 }
 
-binder::Status CameraDeviceClient::checkSurfaceTypeLocked(size_t numBufferProducers,
-        bool deferredConsumer, int surfaceType) const {
+binder::Status CameraDeviceClient::checkSurfaceType(size_t numBufferProducers,
+        bool deferredConsumer, int surfaceType)  {
     if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
         ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
                 __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
@@ -536,28 +572,27 @@
     return binder::Status::ok();
 }
 
-binder::Status CameraDeviceClient::checkPhysicalCameraIdLocked(String8 physicalCameraId) {
-    if (physicalCameraId.size() > 0) {
-        std::vector<std::string> physicalCameraIds;
-        bool logicalCamera =
-            mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
-        if (!logicalCamera ||
-                std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
-                    physicalCameraId.string()) == physicalCameraIds.end()) {
-            String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
-                    mCameraIdStr.string(), physicalCameraId.string());
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-        }
+binder::Status CameraDeviceClient::checkPhysicalCameraId(
+        const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
+        const String8 &logicalCameraId) {
+    if (physicalCameraId.size() == 0) {
+        return binder::Status::ok();
     }
-
+    if (std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
+        physicalCameraId.string()) == physicalCameraIds.end()) {
+        String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+                logicalCameraId.string(), physicalCameraId.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
     return binder::Status::ok();
 }
 
-binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) const {
+binder::Status CameraDeviceClient::checkOperatingMode(int operatingMode,
+        const CameraMetadata &staticInfo, const String8 &cameraId) {
     if (operatingMode < 0) {
         String8 msg = String8::format(
-            "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
+            "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 msg.string());
@@ -565,8 +600,7 @@
 
     bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
     if (isConstrainedHighSpeed) {
-        CameraMetadata staticInfo = mDevice->info();
-        camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+        camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
         bool isConstrainedHighSpeedSupported = false;
         for(size_t i = 0; i < entry.count; ++i) {
             uint8_t capability = entry.data.u8[i];
@@ -578,7 +612,7 @@
         if (!isConstrainedHighSpeedSupported) {
             String8 msg = String8::format(
                 "Camera %s: Try to create a constrained high speed configuration on a device"
-                " that doesn't support it.", mCameraIdStr.string());
+                " that doesn't support it.", cameraId.string());
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     msg.string());
@@ -609,39 +643,31 @@
     stream->bufferSize = 0;
 }
 
-binder::Status CameraDeviceClient::isSessionConfigurationSupported(
-        const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
-    ATRACE_CALL();
-
-    binder::Status res;
-    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
-
-    Mutex::Autolock icl(mBinderSerializationLock);
-
-    if (!mDevice.get()) {
-        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
-    }
-
+binder::Status
+CameraDeviceClient::convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+        hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+        bool *unsupported) {
     auto operatingMode = sessionConfiguration.getOperatingMode();
-    res = checkOperatingModeLocked(operatingMode);
+    binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
     if (!res.isOk()) {
         return res;
     }
 
-    if (status == nullptr) {
-        String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+    if (unsupported == nullptr) {
+        String8 msg("unsupported nullptr");
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
-
-    hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+    *unsupported = false;
     auto ret = Camera3Device::mapToStreamConfigurationMode(
             static_cast<camera3_stream_configuration_mode_t> (operatingMode),
             /*out*/ &streamConfiguration.operationMode);
     if (ret != OK) {
         String8 msg = String8::format(
-            "Camera %s: Failed mapping operating mode %d requested: %s (%d)", mCameraIdStr.string(),
-            operatingMode, strerror(-ret), ret);
+            "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
+            logicalCameraId.string(), operatingMode, strerror(-ret), ret);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 msg.string());
@@ -675,12 +701,12 @@
         bool isStreamInfoValid = false;
         OutputStreamInfo streamInfo;
 
-        res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer, it.getSurfaceType());
+        res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
         if (!res.isOk()) {
             return res;
         }
-
-        res = checkPhysicalCameraIdLocked(physicalCameraId);
+        res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
+                logicalCameraId);
         if (!res.isOk()) {
             return res;
         }
@@ -706,8 +732,10 @@
 
         for (auto& bufferProducer : bufferProducers) {
             sp<Surface> surface;
+            const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
             res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
-                    physicalCameraId);
+                    logicalCameraId,
+                    physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo );
 
             if (!res.isOk())
                 return res;
@@ -723,15 +751,15 @@
                     std::vector<OutputStreamInfo> compositeStreams;
                     if (isDepthCompositeStream) {
                         ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
-                                mDevice->info(), &compositeStreams);
+                                deviceInfo, &compositeStreams);
                     } else {
                         ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
-                            mDevice->info(), &compositeStreams);
+                            deviceInfo, &compositeStreams);
                     }
                     if (ret != OK) {
                         String8 msg = String8::format(
                                 "Camera %s: Failed adding composite streams: %s (%d)",
-                                mCameraIdStr.string(), strerror(-ret), ret);
+                                logicalCameraId.string(), strerror(-ret), ret);
                         ALOGE("%s: %s", __FUNCTION__, msg.string());
                         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
                     }
@@ -739,7 +767,7 @@
                     if (compositeStreams.size() == 0) {
                         // No internal streams means composite stream not
                         // supported.
-                        *status = false;
+                        *unsupported = true;
                         return binder::Status::ok();
                     } else if (compositeStreams.size() > 1) {
                         streamCount += compositeStreams.size() - 1;
@@ -760,6 +788,49 @@
             }
         }
     }
+    return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::isSessionConfigurationSupported(
+        const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    status_t ret = OK;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    auto operatingMode = sessionConfiguration.getOperatingMode();
+    res = checkOperatingMode(operatingMode, mDevice->info(), mCameraIdStr);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (status == nullptr) {
+        String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+    hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+    bool earlyExit = false;
+    metadataGetter getMetadata = [this](const String8 &id) {return mDevice->infoPhysical(id);};
+    std::vector<std::string> physicalCameraIds;
+    mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+    res = convertToHALStreamCombination(sessionConfiguration, mCameraIdStr,
+            mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration, &earlyExit);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (earlyExit) {
+        *status = false;
+        return binder::Status::ok();
+    }
 
     *status = false;
     ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
@@ -899,7 +970,7 @@
     String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
     bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
 
-    res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer,
+    res = checkSurfaceType(numBufferProducers, deferredConsumer,
             outputConfiguration.getSurfaceType());
     if (!res.isOk()) {
         return res;
@@ -908,8 +979,9 @@
     if (!mDevice.get()) {
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
-
-    res = checkPhysicalCameraIdLocked(physicalCameraId);
+    std::vector<std::string> physicalCameraIds;
+    mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+    res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId, mCameraIdStr);
     if (!res.isOk()) {
         return res;
     }
@@ -938,7 +1010,7 @@
 
         sp<Surface> surface;
         res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
-                physicalCameraId);
+                mCameraIdStr, mDevice->infoPhysical(physicalCameraId));
 
         if (!res.isOk())
             return res;
@@ -1242,7 +1314,7 @@
         OutputStreamInfo outInfo;
         sp<Surface> surface;
         res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
-                newOutputsMap.valueAt(i), physicalCameraId);
+                newOutputsMap.valueAt(i), mCameraIdStr, mDevice->infoPhysical(physicalCameraId));
         if (!res.isOk())
             return res;
 
@@ -1322,11 +1394,11 @@
 binder::Status CameraDeviceClient::createSurfaceFromGbp(
         OutputStreamInfo& streamInfo, bool isStreamInfoValid,
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
-        const String8& physicalId) {
+        const String8 &cameraId, const CameraMetadata &physicalCameraMetadata) {
 
     // bufferProducer must be non-null
     if (gbp == nullptr) {
-        String8 msg = String8::format("Camera %s: Surface is NULL", mCameraIdStr.string());
+        String8 msg = String8::format("Camera %s: Surface is NULL", cameraId.string());
         ALOGW("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
@@ -1338,13 +1410,13 @@
     status_t err;
     if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
         ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for stream",
-                __FUNCTION__, mCameraIdStr.string(), consumerUsage);
+                __FUNCTION__, cameraId.string(), consumerUsage);
         useAsync = true;
     }
 
@@ -1363,26 +1435,26 @@
     android_dataspace dataSpace;
     if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface width: %s (%d)",
-                 mCameraIdStr.string(), strerror(-err), err);
+                 cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE,
             reinterpret_cast<int*>(&dataSpace))) != OK) {
         String8 msg = String8::format("Camera %s: Failed to query Surface dataspace: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                cameraId.string(), strerror(-err), err);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
     }
@@ -1393,16 +1465,16 @@
             ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
              ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
         ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
-                __FUNCTION__, mCameraIdStr.string(), format);
+                __FUNCTION__, cameraId.string(), format);
         format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     }
     // Round dimensions to the nearest dimensions available for this format
     if (flexibleConsumer && isPublicFormat(format) &&
             !CameraDeviceClient::roundBufferDimensionNearest(width, height,
-            format, dataSpace, mDevice->info(physicalId), /*out*/&width, /*out*/&height)) {
+            format, dataSpace, physicalCameraMetadata, /*out*/&width, /*out*/&height)) {
         String8 msg = String8::format("Camera %s: No supported stream configurations with "
                 "format %#x defined, failed to create output stream",
-                mCameraIdStr.string(), format);
+                cameraId.string(), format);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
@@ -1417,26 +1489,26 @@
     }
     if (width != streamInfo.width) {
         String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
-                mCameraIdStr.string(), width, streamInfo.width);
+                cameraId.string(), width, streamInfo.width);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (height != streamInfo.height) {
         String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
-                 mCameraIdStr.string(), height, streamInfo.height);
+                 cameraId.string(), height, streamInfo.height);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (format != streamInfo.format) {
         String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
-                 mCameraIdStr.string(), format, streamInfo.format);
+                 cameraId.string(), format, streamInfo.format);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
     if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
         if (dataSpace != streamInfo.dataSpace) {
             String8 msg = String8::format("Camera %s:Surface dataSpace doesn't match: %d vs %d",
-                    mCameraIdStr.string(), dataSpace, streamInfo.dataSpace);
+                    cameraId.string(), dataSpace, streamInfo.dataSpace);
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
         }
@@ -1445,7 +1517,7 @@
         if (consumerUsage != streamInfo.consumerUsage) {
             String8 msg = String8::format(
                     "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
-                    mCameraIdStr.string(), consumerUsage, streamInfo.consumerUsage);
+                    cameraId.string(), consumerUsage, streamInfo.consumerUsage);
             ALOGE("%s: %s", __FUNCTION__, msg.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
         }
@@ -1825,7 +1897,7 @@
 
         sp<Surface> surface;
         res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
-                surface, bufferProducer, physicalId);
+                surface, bufferProducer, mCameraIdStr, mDevice->infoPhysical(physicalId));
 
         if (!res.isOk())
             return res;
@@ -1870,6 +1942,159 @@
     return res;
 }
 
+binder::Status CameraDeviceClient::setCameraAudioRestriction(int32_t mode) {
+    ATRACE_CALL();
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    if (!isValidAudioRestriction(mode)) {
+        String8 msg = String8::format("Camera %s: invalid audio restriction mode %d",
+                mCameraIdStr.string(), mode);
+        ALOGW("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+    BasicClient::setAudioRestriction(mode);
+    return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::getGlobalAudioRestriction(/*out*/ int32_t* outMode) {
+    ATRACE_CALL();
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+    Mutex::Autolock icl(mBinderSerializationLock);
+    if (outMode != nullptr) {
+        *outMode = BasicClient::getServiceAudioRestriction();
+    }
+    return binder::Status::ok();
+}
+
+status_t CameraDeviceClient::setRotateAndCropOverride(uint8_t rotateAndCrop) {
+    if (rotateAndCrop > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
+
+    return mDevice->setRotateAndCropAutoBehavior(
+        static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
+}
+
+binder::Status CameraDeviceClient::switchToOffline(
+        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+        const std::vector<int>& offlineOutputIds,
+        /*out*/
+        sp<hardware::camera2::ICameraOfflineSession>* session) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    if (offlineOutputIds.empty()) {
+        String8 msg = String8::format("Offline surfaces must not be empty");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    if (session == nullptr) {
+        String8 msg = String8::format("Invalid offline session");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    std::vector<int32_t> offlineStreamIds;
+    offlineStreamIds.reserve(offlineOutputIds.size());
+    KeyedVector<sp<IBinder>, sp<CompositeStream>> offlineCompositeStreamMap;
+    for (const auto& streamId : offlineOutputIds) {
+        ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
+        if (index == NAME_NOT_FOUND) {
+            String8 msg = String8::format("Offline surface with id: %d is not registered",
+                    streamId);
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+
+        if (!mStreamInfoMap[streamId].supportsOffline) {
+            String8 msg = String8::format("Offline surface with id: %d doesn't support "
+                    "offline mode", streamId);
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+
+        bool isCompositeStream = false;
+        for (const auto& gbp : mConfiguredOutputs[streamId].getGraphicBufferProducers()) {
+            sp<Surface> s = new Surface(gbp, false /*controlledByApp*/);
+            isCompositeStream = camera3::DepthCompositeStream::isDepthCompositeStream(s) |
+                camera3::HeicCompositeStream::isHeicCompositeStream(s);
+            if (isCompositeStream) {
+                auto compositeIdx = mCompositeStreamMap.indexOfKey(IInterface::asBinder(gbp));
+                if (compositeIdx == NAME_NOT_FOUND) {
+                    ALOGE("%s: Unknown composite stream", __FUNCTION__);
+                    return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                            "Unknown composite stream");
+                }
+
+                mCompositeStreamMap.valueAt(compositeIdx)->insertCompositeStreamIds(
+                        &offlineStreamIds);
+                offlineCompositeStreamMap.add(mCompositeStreamMap.keyAt(compositeIdx),
+                        mCompositeStreamMap.valueAt(compositeIdx));
+                break;
+            }
+        }
+
+        if (!isCompositeStream) {
+            offlineStreamIds.push_back(streamId);
+        }
+    }
+
+    sp<CameraOfflineSessionBase> offlineSession;
+    auto ret = mDevice->switchToOffline(offlineStreamIds, &offlineSession);
+    if (ret != OK) {
+        return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Error switching to offline mode: %s (%d)",
+                mCameraIdStr.string(), strerror(ret), ret);
+    }
+
+    sp<CameraOfflineSessionClient> offlineClient;
+    if (offlineSession.get() != nullptr) {
+        offlineClient = new CameraOfflineSessionClient(sCameraService,
+                offlineSession, offlineCompositeStreamMap, cameraCb, mClientPackageName,
+                mClientFeatureId, mCameraIdStr, mCameraFacing, mClientPid, mClientUid, mServicePid);
+        ret = sCameraService->addOfflineClient(mCameraIdStr, offlineClient);
+    }
+
+    if (ret == OK) {
+        // A successful offline session switch must reset the current camera client
+        // and release any resources occupied by previously configured streams.
+        mStreamMap.clear();
+        mConfiguredOutputs.clear();
+        mDeferredStreams.clear();
+        mStreamInfoMap.clear();
+        mCompositeStreamMap.clear();
+        mInputStream = {false, 0, 0, 0, 0};
+    } else {
+        switch(ret) {
+            case BAD_VALUE:
+                return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Illegal argument to HAL module for camera \"%s\"", mCameraIdStr.c_str());
+            case TIMED_OUT:
+                return STATUS_ERROR_FMT(CameraService::ERROR_CAMERA_IN_USE,
+                        "Camera \"%s\" is already open", mCameraIdStr.c_str());
+            default:
+                return STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
+                        "Failed to initialize camera \"%s\": %s (%d)", mCameraIdStr.c_str(),
+                        strerror(-ret), ret);
+        }
+    }
+
+    *session = offlineClient;
+
+    return binder::Status::ok();
+}
+
 status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
     return BasicClient::dump(fd, args);
 }
@@ -1982,8 +2207,8 @@
 
     ALOGV("Camera %s: Stopping processors", mCameraIdStr.string());
 
-    mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
-                                    FRAME_PROCESSOR_LISTENER_MAX_ID,
+    mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+                                    camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
                                     /*listener*/this);
     mFrameProcessor->requestExit();
     ALOGV("Camera %s: Waiting for threads", mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1c5abb0..9d3874f 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -23,6 +23,7 @@
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
 
+#include "CameraOfflineSessionClient.h"
 #include "CameraService.h"
 #include "common/FrameProcessorBase.h"
 #include "common/Camera2ClientBase.h"
@@ -33,6 +34,8 @@
 
 namespace android {
 
+typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
+
 struct CameraDeviceClientBase :
          public CameraService::BasicClient,
          public hardware::camera2::BnCameraDeviceUser
@@ -47,6 +50,7 @@
     CameraDeviceClientBase(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraId,
             int api1CameraId,
             int cameraFacing,
@@ -90,7 +94,9 @@
     virtual binder::Status beginConfigure() override;
 
     virtual binder::Status endConfigure(int operatingMode,
-            const hardware::camera2::impl::CameraMetadataNative& sessionParams) override;
+            const hardware::camera2::impl::CameraMetadataNative& sessionParams,
+            /*out*/
+            std::vector<int>* offlineStreamIds) override;
 
     // Verify specific session configuration.
     virtual binder::Status isSessionConfigurationSupported(
@@ -152,6 +158,16 @@
     virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
             const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
 
+    virtual binder::Status setCameraAudioRestriction(int32_t mode) override;
+
+    virtual binder::Status getGlobalAudioRestriction(/*out*/int32_t* outMode) override;
+
+    virtual binder::Status switchToOffline(
+            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+            const std::vector<int>& offlineOutputIds,
+            /*out*/
+            sp<hardware::camera2::ICameraOfflineSession>* session) override;
+
     /**
      * Interface used by CameraService
      */
@@ -159,6 +175,7 @@
     CameraDeviceClient(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
             const String8& cameraId,
             int cameraFacing,
             int clientPid,
@@ -169,6 +186,8 @@
     virtual status_t      initialize(sp<CameraProviderManager> manager,
             const String8& monitorTags) override;
 
+    virtual status_t      setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
@@ -185,6 +204,16 @@
     virtual void notifyRequestQueueEmpty();
     virtual void notifyRepeatingRequestError(long lastFrameNumber);
 
+    // utility function to convert AIDL SessionConfiguration to HIDL
+    // streamConfiguration. Also checks for validity of SessionConfiguration and
+    // returns a non-ok binder::Status if the passed in session configuration
+    // isn't valid.
+    static binder::Status
+    convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+            const String8 &cameraId, const CameraMetadata &deviceInfo,
+            metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+            hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+            bool *earlyExit);
     /**
      * Interface used by independent components of CameraDeviceClient.
      */
@@ -229,8 +258,6 @@
 
     /** Preview callback related members */
     sp<camera2::FrameProcessorBase> mFrameProcessor;
-    static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
-    static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
 
     std::vector<int32_t> mSupportedPhysicalRequestKeys;
 
@@ -239,10 +266,10 @@
 
     /** Utility members */
     binder::Status checkPidStatus(const char* checkLocation);
-    binder::Status checkOperatingModeLocked(int operatingMode) const;
-    binder::Status checkPhysicalCameraIdLocked(String8 physicalCameraId);
-    binder::Status checkSurfaceTypeLocked(size_t numBufferProducers, bool deferredConsumer,
-            int surfaceType) const;
+    static binder::Status checkOperatingMode(int operatingMode, const CameraMetadata &staticInfo,
+            const String8 &cameraId);
+    static binder::Status checkSurfaceType(size_t numBufferProducers, bool deferredConsumer,
+            int surfaceType);
     static void mapStreamInfo(const OutputStreamInfo &streamInfo,
             camera3_stream_rotation_t rotation, String8 physicalId,
             hardware::camera::device::V3_4::Stream *stream /*out*/);
@@ -273,9 +300,9 @@
 
     // Create a Surface from an IGraphicBufferProducer. Returns error if
     // IGraphicBufferProducer's property doesn't match with streamInfo
-    binder::Status createSurfaceFromGbp(OutputStreamInfo& streamInfo, bool isStreamInfoValid,
-            sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
-            const String8& physicalCameraId);
+    static binder::Status createSurfaceFromGbp(OutputStreamInfo& streamInfo, bool isStreamInfoValid,
+            sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp, const String8 &cameraId,
+            const CameraMetadata &physicalCameraMetadata);
 
 
     // Utility method to insert the surface into SurfaceMap
@@ -285,7 +312,8 @@
 
     // Check that the physicalCameraId passed in is spported by the camera
     // device.
-    bool checkPhysicalCameraId(const String8& physicalCameraId);
+    static binder::Status checkPhysicalCameraId(const std::vector<std::string> &physicalCameraIds,
+            const String8 &physicalCameraId, const String8 &logicalCameraId);
 
     // IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
     KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
new file mode 100644
index 0000000..237c24b
--- /dev/null
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2019 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_TAG "CameraOfflineClient"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include "CameraOfflineSessionClient.h"
+#include "utils/CameraThreadState.h"
+#include <utils/Trace.h>
+
+namespace android {
+
+using binder::Status;
+
+status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
+    ATRACE_CALL();
+
+    // Verify ops permissions
+    auto res = startCameraOps();
+    if (res != OK) {
+        return res;
+    }
+
+    if (mOfflineSession.get() == nullptr) {
+        ALOGE("%s: Camera %s: No valid offline session",
+                __FUNCTION__, mCameraIdStr.string());
+        return NO_INIT;
+    }
+
+    String8 threadName;
+    mFrameProcessor = new camera2::FrameProcessorBase(mOfflineSession);
+    threadName = String8::format("Offline-%s-FrameProc", mCameraIdStr.string());
+    mFrameProcessor->run(threadName.string());
+
+    mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+                                      camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
+                                      /*listener*/this,
+                                      /*sendPartials*/true);
+
+    wp<NotificationListener> weakThis(this);
+    res = mOfflineSession->initialize(weakThis);
+    if (res != OK) {
+        ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
+                __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
+        return res;
+    }
+
+    for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+        mCompositeStreamMap.valueAt(i)->switchToOffline();
+    }
+
+    return OK;
+}
+
+status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
+    // Since we're not submitting more capture requests, changes to rotateAndCrop override
+    // make no difference.
+    return OK;
+}
+
+status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
+    return BasicClient::dump(fd, args);
+}
+
+status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
+    String8 result;
+
+    result = "  Offline session dump:\n";
+    write(fd, result.string(), result.size());
+
+    if (mOfflineSession.get() == nullptr) {
+        result = "  *** Offline session is detached\n";
+        write(fd, result.string(), result.size());
+        return NO_ERROR;
+    }
+
+    mFrameProcessor->dump(fd, args);
+
+    auto res = mOfflineSession->dump(fd);
+    if (res != OK) {
+        result = String8::format("   Error dumping offline session: %s (%d)",
+                strerror(-res), res);
+        write(fd, result.string(), result.size());
+    }
+
+    return OK;
+}
+
+binder::Status CameraOfflineSessionClient::disconnect() {
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    binder::Status res = Status::ok();
+    if (mDisconnected) {
+        return res;
+    }
+    // Allow both client and the media server to disconnect at all times
+    int callingPid = CameraThreadState::getCallingPid();
+    if (callingPid != mClientPid &&
+            callingPid != mServicePid) {
+        return res;
+    }
+
+    mDisconnected = true;
+
+    sCameraService->removeByClient(this);
+    sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
+
+    sp<IBinder> remote = getRemote();
+    if (remote != nullptr) {
+        remote->unlinkToDeath(sCameraService);
+    }
+
+    mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+                                    camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
+                                    /*listener*/this);
+    mFrameProcessor->requestExit();
+    mFrameProcessor->join();
+
+    finishCameraOps();
+    ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
+            mCameraIdStr.string(), mClientPid);
+
+    // client shouldn't be able to call into us anymore
+    mClientPid = 0;
+
+    if (mOfflineSession.get() != nullptr) {
+        auto ret = mOfflineSession->disconnect();
+        if (ret != OK) {
+            ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
+                    strerror(-ret), ret);
+        }
+        mOfflineSession = nullptr;
+    }
+
+    for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+        auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
+        if (ret != OK) {
+            ALOGE("%s: Failed removing composite stream  %s (%d)", __FUNCTION__,
+                    strerror(-ret), ret);
+        }
+    }
+    mCompositeStreamMap.clear();
+
+    return res;
+}
+
+void CameraOfflineSessionClient::notifyError(int32_t errorCode,
+        const CaptureResultExtras& resultExtras) {
+    // Thread safe. Don't bother locking.
+    // Composites can have multiple internal streams. Error notifications coming from such internal
+    // streams may need to remain within camera service.
+    bool skipClientNotification = false;
+    for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+        skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
+    }
+
+    if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
+        mRemoteCallback->onDeviceError(errorCode, resultExtras);
+    }
+}
+
+status_t CameraOfflineSessionClient::startCameraOps() {
+    ATRACE_CALL();
+    {
+        ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
+              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+    }
+
+    if (mAppOpsManager != nullptr) {
+        // Notify app ops that the camera is not available
+        mOpsCallback = new OpsCallback(this);
+        int32_t res;
+        // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
+        mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
+                mClientPackageName, mOpsCallback);
+        // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
+        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
+                mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+
+        if (res == AppOpsManager::MODE_ERRORED) {
+            ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
+                    mCameraIdStr.string(), String8(mClientPackageName).string());
+            return PERMISSION_DENIED;
+        }
+
+        // If the calling Uid is trusted (a native service), the AppOpsManager could
+        // return MODE_IGNORED. Do not treat such case as error.
+        if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
+            ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
+                    mCameraIdStr.string(), String8(mClientPackageName).string());
+            // Return the same error as for device policy manager rejection
+            return -EACCES;
+        }
+    }
+
+    mOpsActive = true;
+
+    // Transition device state to OPEN
+    sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
+
+    return OK;
+}
+
+status_t CameraOfflineSessionClient::finishCameraOps() {
+    ATRACE_CALL();
+
+    // Check if startCameraOps succeeded, and if so, finish the camera op
+    if (mOpsActive) {
+        // Notify app ops that the camera is available again
+        if (mAppOpsManager != nullptr) {
+        // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
+            mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
+                    mClientPackageName);
+            mOpsActive = false;
+        }
+    }
+    // Always stop watching, even if no camera op is active
+    if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
+        mAppOpsManager->stopWatchingMode(mOpsCallback);
+    }
+    mOpsCallback.clear();
+
+    sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
+
+    return OK;
+}
+
+void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
+    ATRACE_CALL();
+    ALOGV("%s", __FUNCTION__);
+
+    if (mRemoteCallback.get() != NULL) {
+        mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
+                result.mPhysicalMetadatas);
+    }
+
+    for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+        mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
+    }
+}
+
+void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
+        nsecs_t timestamp) {
+
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
+    }
+
+    for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+        mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
+    }
+}
+
+void CameraOfflineSessionClient::notifyIdle() {
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onDeviceIdle();
+    }
+}
+
+void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autofocus state now %d, last trigger %d",
+          __FUNCTION__, newState, triggerId);
+}
+
+void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autoexposure state now %d, last trigger %d",
+            __FUNCTION__, newState, triggerId);
+}
+
+void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
+            triggerId);
+}
+
+void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
+    ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
+    notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                CaptureResultExtras());
+}
+
+void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onRequestQueueEmpty();
+    }
+}
+
+void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
+    ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
+    notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                CaptureResultExtras());
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
new file mode 100644
index 0000000..b67fcb3
--- /dev/null
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+#define ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+
+#include <android/hardware/camera2/BnCameraOfflineSession.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include "common/FrameProcessorBase.h"
+#include "common/CameraDeviceBase.h"
+#include "CameraService.h"
+#include "CompositeStream.h"
+
+namespace android {
+
+using android::hardware::camera2::ICameraDeviceCallbacks;
+using camera3::CompositeStream;
+
+// Client for offline session. Note that offline session client does not affect camera service's
+// client arbitration logic. It is camera HAL's decision to decide whether a normal camera
+// client is conflicting with existing offline client(s).
+// The other distinctive difference between offline clients and normal clients is that normal
+// clients are created through ICameraService binder calls, while the offline session client
+// is created through ICameraDeviceUser::switchToOffline call.
+class CameraOfflineSessionClient :
+        public CameraService::BasicClient,
+        public hardware::camera2::BnCameraOfflineSession,
+        public camera2::FrameProcessorBase::FilteredListener,
+        public NotificationListener
+{
+public:
+    CameraOfflineSessionClient(
+            const sp<CameraService>& cameraService,
+            sp<CameraOfflineSessionBase> session,
+            const KeyedVector<sp<IBinder>, sp<CompositeStream>>& offlineCompositeStreamMap,
+            const sp<ICameraDeviceCallbacks>& remoteCallback,
+            const String16& clientPackageName,
+            const std::unique_ptr<String16>& clientFeatureId,
+            const String8& cameraIdStr, int cameraFacing,
+            int clientPid, uid_t clientUid, int servicePid) :
+            CameraService::BasicClient(
+                    cameraService,
+                    IInterface::asBinder(remoteCallback),
+                    clientPackageName, clientFeatureId,
+                    cameraIdStr, cameraFacing, clientPid, clientUid, servicePid),
+            mRemoteCallback(remoteCallback), mOfflineSession(session),
+            mCompositeStreamMap(offlineCompositeStreamMap) {}
+
+    virtual ~CameraOfflineSessionClient() {}
+
+    sp<IBinder> asBinderWrapper() override {
+        return IInterface::asBinder(this);
+    }
+
+    binder::Status disconnect() override;
+
+    status_t dump(int /*fd*/, const Vector<String16>& /*args*/) override;
+
+    status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
+
+    status_t initialize(sp<CameraProviderManager> /*manager*/,
+            const String8& /*monitorTags*/) override;
+
+    status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
+
+    // permissions management
+    status_t startCameraOps() override;
+    status_t finishCameraOps() override;
+
+    // FilteredResultListener API
+    void onResultAvailable(const CaptureResult& result) override;
+
+    // NotificationListener API
+    void notifyError(int32_t errorCode, const CaptureResultExtras& resultExtras) override;
+    void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
+    void notifyIdle() override;
+    void notifyAutoFocus(uint8_t newState, int triggerId) override;
+    void notifyAutoExposure(uint8_t newState, int triggerId) override;
+    void notifyAutoWhitebalance(uint8_t newState, int triggerId) override;
+    void notifyPrepared(int streamId) override;
+    void notifyRequestQueueEmpty() override;
+    void notifyRepeatingRequestError(long lastFrameNumber) override;
+
+private:
+    mutable Mutex mBinderSerializationLock;
+
+    sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
+
+    sp<CameraOfflineSessionBase> mOfflineSession;
+
+    sp<camera2::FrameProcessorBase> mFrameProcessor;
+
+    // Offline composite stream map, output surface -> composite stream
+    KeyedVector<sp<IBinder>, sp<CompositeStream>> mCompositeStreamMap;
+};
+
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
diff --git a/services/camera/libcameraservice/api2/CompositeStream.cpp b/services/camera/libcameraservice/api2/CompositeStream.cpp
index 354eaf9..a61dac7 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/CompositeStream.cpp
@@ -28,19 +28,19 @@
 namespace android {
 namespace camera3 {
 
-CompositeStream::CompositeStream(wp<CameraDeviceBase> device,
+CompositeStream::CompositeStream(sp<CameraDeviceBase> device,
         wp<hardware::camera2::ICameraDeviceCallbacks> cb) :
         mDevice(device),
         mRemoteCallback(cb),
         mNumPartialResults(1),
         mErrorState(false) {
-    sp<CameraDeviceBase> cameraDevice = device.promote();
-    if (cameraDevice.get() != nullptr) {
-        CameraMetadata staticInfo = cameraDevice->info();
+    if (device != nullptr) {
+        CameraMetadata staticInfo = device->info();
         camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
         if (entry.count > 0) {
             mNumPartialResults = entry.data.i32[0];
         }
+        mStatusTracker = device->getStatusTracker();
     }
 }
 
@@ -174,7 +174,7 @@
             ret = onStreamBufferError(resultExtras);
             break;
         case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
-            // Invalid request, this shouldn't affect composite streams.
+            onRequestError(resultExtras);
             break;
         default:
             ALOGE("%s: Unrecoverable error: %d detected!", __FUNCTION__, errorCode);
@@ -186,7 +186,7 @@
     return ret;
 }
 
-void CompositeStream::notifyError(int64_t frameNumber) {
+void CompositeStream::notifyError(int64_t frameNumber, int32_t requestId) {
     sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb =
         mRemoteCallback.promote();
 
@@ -194,11 +194,17 @@
         CaptureResultExtras extras;
         extras.errorStreamId = getStreamId();
         extras.frameNumber = frameNumber;
+        extras.requestId = requestId;
         remoteCb->onDeviceError(
                 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
                 extras);
     }
 }
 
+void CompositeStream::switchToOffline() {
+    Mutex::Autolock l(mMutex);
+    mDevice.clear();
+}
+
 }; // namespace camera3
 }; // namespace android
diff --git a/services/camera/libcameraservice/api2/CompositeStream.h b/services/camera/libcameraservice/api2/CompositeStream.h
index a401a82..5f62d47 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.h
+++ b/services/camera/libcameraservice/api2/CompositeStream.h
@@ -38,7 +38,7 @@
 class CompositeStream : public camera3::Camera3StreamBufferListener {
 
 public:
-    CompositeStream(wp<CameraDeviceBase> device, wp<hardware::camera2::ICameraDeviceCallbacks> cb);
+    CompositeStream(sp<CameraDeviceBase> device, wp<hardware::camera2::ICameraDeviceCallbacks> cb);
     virtual ~CompositeStream() {}
 
     status_t createStream(const std::vector<sp<Surface>>& consumers,
@@ -48,6 +48,9 @@
 
     status_t deleteStream();
 
+    // Switch to offline mode and release any online resources.
+    void switchToOffline();
+
     // Create and register all internal camera streams.
     virtual status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -64,6 +67,10 @@
     virtual status_t insertGbp(SurfaceMap* /*out*/outSurfaceMap,
             Vector<int32_t>* /*out*/outputStreamIds, int32_t* /*out*/currentStreamId) = 0;
 
+    // Attach the internal composite stream ids.
+    virtual status_t insertCompositeStreamIds(
+            std::vector<int32_t>* compositeStreamIds /*out*/) = 0;
+
     // Return composite stream id.
     virtual int getStreamId() = 0;
 
@@ -88,7 +95,7 @@
     status_t registerCompositeStreamListener(int32_t streamId);
     void eraseResult(int64_t frameNumber);
     void flagAnErrorFrameNumber(int64_t frameNumber);
-    void notifyError(int64_t frameNumber);
+    void notifyError(int64_t frameNumber, int32_t requestId);
 
     // Subclasses should check for buffer errors from internal streams and return 'true' in
     // case the error notification should remain within camera service.
@@ -98,11 +105,16 @@
     // internal processing needs result data.
     virtual void onResultError(const CaptureResultExtras& resultExtras) = 0;
 
+    // Subclasses can decide how to handle request errors depending on whether
+    // or not the internal processing needs clean up.
+    virtual void onRequestError(const CaptureResultExtras& /*resultExtras*/) {}
+
     // Device and/or service is in unrecoverable error state.
     // Composite streams should behave accordingly.
     void enableErrorState();
 
     wp<CameraDeviceBase>   mDevice;
+    wp<camera3::StatusTracker> mStatusTracker;
     wp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
 
     mutable Mutex          mMutex;
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index 0b91016..c6859be 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -20,7 +20,6 @@
 
 #include "api1/client2/JpegProcessor.h"
 #include "common/CameraProviderManager.h"
-#include "dlfcn.h"
 #include <gui/Surface.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
@@ -30,7 +29,7 @@
 namespace android {
 namespace camera3 {
 
-DepthCompositeStream::DepthCompositeStream(wp<CameraDeviceBase> device,
+DepthCompositeStream::DepthCompositeStream(sp<CameraDeviceBase> device,
         wp<hardware::camera2::ICameraDeviceCallbacks> cb) :
         CompositeStream(device, cb),
         mBlobStreamId(-1),
@@ -43,12 +42,9 @@
         mBlobBufferAcquired(false),
         mProducerListener(new ProducerListener()),
         mMaxJpegSize(-1),
-        mIsLogicalCamera(false),
-        mDepthPhotoLibHandle(nullptr),
-        mDepthPhotoProcess(nullptr) {
-    sp<CameraDeviceBase> cameraDevice = device.promote();
-    if (cameraDevice.get() != nullptr) {
-        CameraMetadata staticInfo = cameraDevice->info();
+        mIsLogicalCamera(false) {
+    if (device != nullptr) {
+        CameraMetadata staticInfo = device->info();
         auto entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
         if (entry.count > 0) {
             mMaxJpegSize = entry.data.i32[0];
@@ -83,19 +79,6 @@
         }
 
         getSupportedDepthSizes(staticInfo, &mSupportedDepthSizes);
-
-        mDepthPhotoLibHandle = dlopen(camera3::kDepthPhotoLibrary, RTLD_NOW | RTLD_LOCAL);
-        if (mDepthPhotoLibHandle != nullptr) {
-            mDepthPhotoProcess = reinterpret_cast<camera3::process_depth_photo_frame> (
-                    dlsym(mDepthPhotoLibHandle, camera3::kDepthPhotoProcessFunction));
-            if (mDepthPhotoProcess == nullptr) {
-                ALOGE("%s: Failed to link to depth photo process function: %s", __FUNCTION__,
-                        dlerror());
-            }
-        } else {
-            ALOGE("%s: Failed to link to depth photo library: %s", __FUNCTION__, dlerror());
-        }
-
     }
 }
 
@@ -108,11 +91,6 @@
     mDepthSurface.clear();
     mDepthConsumer = nullptr;
     mDepthSurface = nullptr;
-    if (mDepthPhotoLibHandle != nullptr) {
-        dlclose(mDepthPhotoLibHandle);
-        mDepthPhotoLibHandle = nullptr;
-    }
-    mDepthPhotoProcess = nullptr;
 }
 
 void DepthCompositeStream::compilePendingInputLocked() {
@@ -356,7 +334,7 @@
     }
 
     size_t actualJpegSize = 0;
-    res = mDepthPhotoProcess(depthPhoto, finalJpegBufferSize, dstBuffer, &actualJpegSize);
+    res = processDepthPhotoFrame(depthPhoto, finalJpegBufferSize, dstBuffer, &actualJpegSize);
     if (res != 0) {
         ALOGE("%s: Depth photo processing failed: %s (%d)", __FUNCTION__, strerror(-res), res);
         outputANW->cancelBuffer(mOutputSurface.get(), anb, /*fence*/ -1);
@@ -406,7 +384,8 @@
     }
 
     if ((inputFrame->error || mErrorState) && !inputFrame->errorNotified) {
-        notifyError(inputFrame->frameNumber);
+        //TODO: Figure out correct requestId
+        notifyError(inputFrame->frameNumber, -1 /*requestId*/);
         inputFrame->errorNotified = true;
     }
 }
@@ -583,11 +562,6 @@
         return NO_ERROR;
     }
 
-    if ((mDepthPhotoLibHandle == nullptr) || (mDepthPhotoProcess == nullptr)) {
-        ALOGE("%s: Depth photo library is not present!", __FUNCTION__);
-        return NO_INIT;
-    }
-
     if (mOutputSurface.get() == nullptr) {
         ALOGE("%s: No valid output surface set!", __FUNCTION__);
         return NO_INIT;
@@ -645,14 +619,15 @@
                 strerror(-ret), ret);
     }
 
-    sp<CameraDeviceBase> device = mDevice.promote();
-    if (!device.get()) {
-        ALOGE("%s: Invalid camera device!", __FUNCTION__);
-        return NO_INIT;
-    }
-
     if (mDepthStreamId >= 0) {
-        ret = device->deleteStream(mDepthStreamId);
+        // Camera devices may not be valid after switching to offline mode.
+        // In this case, all offline streams including internal composite streams
+        // are managed and released by the offline session.
+        sp<CameraDeviceBase> device = mDevice.promote();
+        if (device.get() != nullptr) {
+            ret = device->deleteStream(mDepthStreamId);
+        }
+
         mDepthStreamId = -1;
     }
 
@@ -709,6 +684,18 @@
     return NO_ERROR;
 }
 
+status_t DepthCompositeStream::insertCompositeStreamIds(
+        std::vector<int32_t>* compositeStreamIds /*out*/) {
+    if (compositeStreamIds == nullptr) {
+        return BAD_VALUE;
+    }
+
+    compositeStreamIds->push_back(mDepthStreamId);
+    compositeStreamIds->push_back(mBlobStreamId);
+
+    return OK;
+}
+
 void DepthCompositeStream::onResultError(const CaptureResultExtras& resultExtras) {
     // Processing can continue even in case of result errors.
     // At the moment depth composite stream processing relies mainly on static camera
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index 28a7826..cab52b6 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -41,7 +41,7 @@
         public CpuConsumer::FrameAvailableListener {
 
 public:
-    DepthCompositeStream(wp<CameraDeviceBase> device,
+    DepthCompositeStream(sp<CameraDeviceBase> device,
             wp<hardware::camera2::ICameraDeviceCallbacks> cb);
     ~DepthCompositeStream() override;
 
@@ -56,6 +56,7 @@
     status_t configureStream() override;
     status_t insertGbp(SurfaceMap* /*out*/outSurfaceMap, Vector<int32_t>* /*out*/outputStreamIds,
             int32_t* /*out*/currentStreamId) override;
+    status_t insertCompositeStreamIds(std::vector<int32_t>* compositeStreamIds /*out*/) override;
     int getStreamId() override { return mBlobStreamId; }
 
     // CpuConsumer listener implementation
@@ -79,8 +80,9 @@
         bool                      error;
         bool                      errorNotified;
         int64_t                   frameNumber;
+        int32_t                   requestId;
 
-        InputFrame() : error(false), errorNotified(false), frameNumber(-1) { }
+        InputFrame() : error(false), errorNotified(false), frameNumber(-1), requestId(-1) { }
     };
 
     // Helper methods
@@ -126,8 +128,6 @@
     std::vector<std::tuple<size_t, size_t>> mSupportedDepthSizes;
     std::vector<float>   mIntrinsicCalibration, mLensDistortion;
     bool                 mIsLogicalCamera;
-    void*                mDepthPhotoLibHandle;
-    process_depth_photo_frame mDepthPhotoProcess;
 
     // Keep all incoming Depth buffer timestamps pending further processing.
     std::vector<int64_t> mInputDepthBuffers;
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 9f15be0..a63f402 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -28,7 +28,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <media/ICrypto.h>
+#include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/MediaDefs.h>
@@ -45,7 +45,7 @@
 namespace android {
 namespace camera3 {
 
-HeicCompositeStream::HeicCompositeStream(wp<CameraDeviceBase> device,
+HeicCompositeStream::HeicCompositeStream(sp<CameraDeviceBase> device,
         wp<hardware::camera2::ICameraDeviceCallbacks> cb) :
         CompositeStream(device, cb),
         mUseHeic(false),
@@ -67,7 +67,9 @@
         mDequeuedOutputBufferCnt(0),
         mLockedAppSegmentBufferCnt(0),
         mCodecOutputCounter(0),
-        mGridTimestampUs(0) {
+        mQuality(-1),
+        mGridTimestampUs(0),
+        mStatusId(StatusTracker::NO_STATUS_ID) {
 }
 
 HeicCompositeStream::~HeicCompositeStream() {
@@ -187,9 +189,17 @@
     }
 
     mOutputSurface = consumers[0];
-    res = registerCompositeStreamListener(getStreamId());
+    res = registerCompositeStreamListener(mMainImageStreamId);
     if (res != OK) {
-        ALOGE("%s: Failed to register HAL main image stream", __FUNCTION__);
+        ALOGE("%s: Failed to register HAL main image stream: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+        return res;
+    }
+
+    res = registerCompositeStreamListener(mAppSegmentStreamId);
+    if (res != OK) {
+        ALOGE("%s: Failed to register HAL app segment stream: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
         return res;
     }
 
@@ -208,13 +218,14 @@
     deinitCodec();
 
     if (mAppSegmentStreamId >= 0) {
+        // Camera devices may not be valid after switching to offline mode.
+        // In this case, all offline streams including internal composite streams
+        // are managed and released by the offline session.
         sp<CameraDeviceBase> device = mDevice.promote();
-        if (!device.get()) {
-            ALOGE("%s: Invalid camera device!", __FUNCTION__);
-            return NO_INIT;
+        if (device.get() != nullptr) {
+            res = device->deleteStream(mAppSegmentStreamId);
         }
 
-        res = device->deleteStream(mAppSegmentStreamId);
         mAppSegmentStreamId = -1;
     }
 
@@ -222,6 +233,19 @@
         mOutputSurface->disconnect(NATIVE_WINDOW_API_CAMERA);
         mOutputSurface.clear();
     }
+
+    sp<StatusTracker> statusTracker = mStatusTracker.promote();
+    if (statusTracker != nullptr && mStatusId != StatusTracker::NO_STATUS_ID) {
+        statusTracker->removeComponent(mStatusId);
+        mStatusId = StatusTracker::NO_STATUS_ID;
+    }
+
+    if (mPendingInputFrames.size() > 0) {
+        ALOGW("%s: mPendingInputFrames has %zu stale entries",
+                __FUNCTION__, mPendingInputFrames.size());
+        mPendingInputFrames.clear();
+    }
+
     return res;
 }
 
@@ -230,9 +254,16 @@
 
     if (bufferInfo.mError) return;
 
-    mCodecOutputBufferTimestamps.push(bufferInfo.mTimestamp);
-    ALOGV("%s: [%" PRId64 "]: Adding codecOutputBufferTimestamp (%zu timestamps in total)",
-            __FUNCTION__, bufferInfo.mTimestamp, mCodecOutputBufferTimestamps.size());
+    if (bufferInfo.mStreamId == mMainImageStreamId) {
+        mMainImageFrameNumbers.push(bufferInfo.mFrameNumber);
+        mCodecOutputBufferFrameNumbers.push(bufferInfo.mFrameNumber);
+        ALOGV("%s: [%" PRId64 "]: Adding main image frame number (%zu frame numbers in total)",
+                __FUNCTION__, bufferInfo.mFrameNumber, mMainImageFrameNumbers.size());
+    } else if (bufferInfo.mStreamId == mAppSegmentStreamId) {
+        mAppSegmentFrameNumbers.push(bufferInfo.mFrameNumber);
+        ALOGV("%s: [%" PRId64 "]: Adding app segment frame number (%zu frame numbers in total)",
+                __FUNCTION__, bufferInfo.mFrameNumber, mAppSegmentFrameNumbers.size());
+    }
 }
 
 // We need to get the settings early to handle the case where the codec output
@@ -262,7 +293,7 @@
         quality = entry.data.i32[0];
     }
 
-    mSettingsByFrameNumber[frameNumber] = std::make_pair(orientation, quality);
+    mSettingsByFrameNumber[frameNumber] = {orientation, quality};
 }
 
 void HeicCompositeStream::onFrameAvailable(const BufferItem& item) {
@@ -477,6 +508,11 @@
         return res;
     }
 
+    sp<camera3::StatusTracker> statusTracker = mStatusTracker.promote();
+    if (statusTracker != nullptr) {
+        mStatusId = statusTracker->addComponent();
+    }
+
     run("HeicCompositeStreamProc");
 
     return NO_ERROR;
@@ -503,6 +539,18 @@
     return NO_ERROR;
 }
 
+status_t HeicCompositeStream::insertCompositeStreamIds(
+        std::vector<int32_t>* compositeStreamIds /*out*/) {
+    if (compositeStreamIds == nullptr) {
+        return BAD_VALUE;
+    }
+
+    compositeStreamIds->push_back(mAppSegmentStreamId);
+    compositeStreamIds->push_back(mMainImageStreamId);
+
+    return OK;
+}
+
 void HeicCompositeStream::onShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) {
     Mutex::Autolock l(mMutex);
     if (mErrorState) {
@@ -510,24 +558,44 @@
     }
 
     if (mSettingsByFrameNumber.find(resultExtras.frameNumber) != mSettingsByFrameNumber.end()) {
-        ALOGV("%s: [%" PRId64 "]: frameNumber %" PRId64, __FUNCTION__,
-                timestamp, resultExtras.frameNumber);
-        mFrameNumberMap.emplace(resultExtras.frameNumber, timestamp);
-        mSettingsByTimestamp[timestamp] = mSettingsByFrameNumber[resultExtras.frameNumber];
-        mSettingsByFrameNumber.erase(resultExtras.frameNumber);
+        ALOGV("%s: [%" PRId64 "]: timestamp %" PRId64 ", requestId %d", __FUNCTION__,
+                resultExtras.frameNumber, timestamp, resultExtras.requestId);
+        mSettingsByFrameNumber[resultExtras.frameNumber].shutterNotified = true;
+        mSettingsByFrameNumber[resultExtras.frameNumber].timestamp = timestamp;
+        mSettingsByFrameNumber[resultExtras.frameNumber].requestId = resultExtras.requestId;
         mInputReadyCondition.signal();
     }
 }
 
 void HeicCompositeStream::compilePendingInputLocked() {
-    while (!mSettingsByTimestamp.empty()) {
-        auto it = mSettingsByTimestamp.begin();
-        mPendingInputFrames[it->first].orientation = it->second.first;
-        mPendingInputFrames[it->first].quality = it->second.second;
-        mSettingsByTimestamp.erase(it);
+    auto i = mSettingsByFrameNumber.begin();
+    while (i != mSettingsByFrameNumber.end()) {
+        if (i->second.shutterNotified) {
+            mPendingInputFrames[i->first].orientation = i->second.orientation;
+            mPendingInputFrames[i->first].quality = i->second.quality;
+            mPendingInputFrames[i->first].timestamp = i->second.timestamp;
+            mPendingInputFrames[i->first].requestId = i->second.requestId;
+            ALOGV("%s: [%" PRId64 "]: timestamp is %" PRId64, __FUNCTION__,
+                    i->first, i->second.timestamp);
+            i = mSettingsByFrameNumber.erase(i);
+
+            // Set encoder quality if no inflight encoding
+            if (mPendingInputFrames.size() == 1) {
+                sp<StatusTracker> statusTracker = mStatusTracker.promote();
+                if (statusTracker != nullptr) {
+                    statusTracker->markComponentActive(mStatusId);
+                    ALOGV("%s: Mark component as active", __FUNCTION__);
+                }
+
+                int32_t newQuality = mPendingInputFrames.begin()->second.quality;
+                updateCodecQualityLocked(newQuality);
+            }
+        } else {
+            i++;
+        }
     }
 
-    while (!mInputAppSegmentBuffers.empty()) {
+    while (!mInputAppSegmentBuffers.empty() && mAppSegmentFrameNumbers.size() > 0) {
         CpuConsumer::LockedBuffer imgBuffer;
         auto it = mInputAppSegmentBuffers.begin();
         auto res = mAppSegmentConsumer->lockNextBuffer(&imgBuffer);
@@ -549,17 +617,30 @@
             continue;
         }
 
-        if ((mPendingInputFrames.find(imgBuffer.timestamp) != mPendingInputFrames.end()) &&
-                (mPendingInputFrames[imgBuffer.timestamp].error)) {
+        if (mPendingInputFrames.find(mAppSegmentFrameNumbers.front()) == mPendingInputFrames.end()) {
+            ALOGE("%s: mPendingInputFrames doesn't contain frameNumber %" PRId64, __FUNCTION__,
+                    mAppSegmentFrameNumbers.front());
+            mInputAppSegmentBuffers.erase(it);
+            mAppSegmentFrameNumbers.pop();
+            continue;
+        }
+
+        int64_t frameNumber = mAppSegmentFrameNumbers.front();
+        // If mPendingInputFrames doesn't contain the expected frame number, the captured
+        // input app segment frame must have been dropped via a buffer error.  Simply
+        // return the buffer to the buffer queue.
+        if ((mPendingInputFrames.find(frameNumber) == mPendingInputFrames.end()) ||
+                (mPendingInputFrames[frameNumber].error)) {
             mAppSegmentConsumer->unlockBuffer(imgBuffer);
         } else {
-            mPendingInputFrames[imgBuffer.timestamp].appSegmentBuffer = imgBuffer;
+            mPendingInputFrames[frameNumber].appSegmentBuffer = imgBuffer;
             mLockedAppSegmentBufferCnt++;
         }
         mInputAppSegmentBuffers.erase(it);
+        mAppSegmentFrameNumbers.pop();
     }
 
-    while (!mInputYuvBuffers.empty() && !mYuvBufferAcquired) {
+    while (!mInputYuvBuffers.empty() && !mYuvBufferAcquired && mMainImageFrameNumbers.size() > 0) {
         CpuConsumer::LockedBuffer imgBuffer;
         auto it = mInputYuvBuffers.begin();
         auto res = mMainImageConsumer->lockNextBuffer(&imgBuffer);
@@ -580,59 +661,68 @@
             continue;
         }
 
-        if ((mPendingInputFrames.find(imgBuffer.timestamp) != mPendingInputFrames.end()) &&
-                (mPendingInputFrames[imgBuffer.timestamp].error)) {
+        if (mPendingInputFrames.find(mMainImageFrameNumbers.front()) == mPendingInputFrames.end()) {
+            ALOGE("%s: mPendingInputFrames doesn't contain frameNumber %" PRId64, __FUNCTION__,
+                    mMainImageFrameNumbers.front());
+            mInputYuvBuffers.erase(it);
+            mMainImageFrameNumbers.pop();
+            continue;
+        }
+
+        int64_t frameNumber = mMainImageFrameNumbers.front();
+        // If mPendingInputFrames doesn't contain the expected frame number, the captured
+        // input main image must have been dropped via a buffer error. Simply
+        // return the buffer to the buffer queue.
+        if ((mPendingInputFrames.find(frameNumber) == mPendingInputFrames.end()) ||
+                (mPendingInputFrames[frameNumber].error)) {
             mMainImageConsumer->unlockBuffer(imgBuffer);
         } else {
-            mPendingInputFrames[imgBuffer.timestamp].yuvBuffer = imgBuffer;
+            mPendingInputFrames[frameNumber].yuvBuffer = imgBuffer;
             mYuvBufferAcquired = true;
         }
         mInputYuvBuffers.erase(it);
+        mMainImageFrameNumbers.pop();
     }
 
     while (!mCodecOutputBuffers.empty()) {
         auto it = mCodecOutputBuffers.begin();
-        // Bitstream buffer timestamp doesn't necessarily directly correlate with input
-        // buffer timestamp. Assume encoder input to output is FIFO, use a queue
-        // to look up timestamp.
-        int64_t bufferTime = -1;
-        if (mCodecOutputBufferTimestamps.empty()) {
-            ALOGV("%s: Failed to find buffer timestamp for codec output buffer!", __FUNCTION__);
+        // Assume encoder input to output is FIFO, use a queue to look up
+        // frameNumber when handling codec outputs.
+        int64_t bufferFrameNumber = -1;
+        if (mCodecOutputBufferFrameNumbers.empty()) {
+            ALOGV("%s: Failed to find buffer frameNumber for codec output buffer!", __FUNCTION__);
             break;
         } else {
-            // Direct mapping between camera timestamp (in ns) and codec timestamp (in us).
-            bufferTime = mCodecOutputBufferTimestamps.front();
+            // Direct mapping between camera frame number and codec timestamp (in us).
+            bufferFrameNumber = mCodecOutputBufferFrameNumbers.front();
             mCodecOutputCounter++;
             if (mCodecOutputCounter == mNumOutputTiles) {
-                mCodecOutputBufferTimestamps.pop();
+                mCodecOutputBufferFrameNumbers.pop();
                 mCodecOutputCounter = 0;
             }
 
-            mPendingInputFrames[bufferTime].codecOutputBuffers.push_back(*it);
-            ALOGV("%s: [%" PRId64 "]: Pushing codecOutputBuffers (time %" PRId64 " us)",
-                    __FUNCTION__, bufferTime, it->timeUs);
+            mPendingInputFrames[bufferFrameNumber].codecOutputBuffers.push_back(*it);
+            ALOGV("%s: [%" PRId64 "]: Pushing codecOutputBuffers (frameNumber %" PRId64 ")",
+                    __FUNCTION__, bufferFrameNumber, it->timeUs);
         }
         mCodecOutputBuffers.erase(it);
     }
 
-    while (!mFrameNumberMap.empty()) {
-        auto it = mFrameNumberMap.begin();
-        mPendingInputFrames[it->second].frameNumber = it->first;
-        ALOGV("%s: [%" PRId64 "]: frameNumber is %" PRId64, __FUNCTION__, it->second, it->first);
-        mFrameNumberMap.erase(it);
-    }
-
     while (!mCaptureResults.empty()) {
         auto it = mCaptureResults.begin();
-        // Negative timestamp indicates that something went wrong during the capture result
+        // Negative frame number indicates that something went wrong during the capture result
         // collection process.
-        if (it->first >= 0) {
-            if (mPendingInputFrames[it->first].frameNumber == std::get<0>(it->second)) {
-                mPendingInputFrames[it->first].result =
+        int64_t frameNumber = std::get<0>(it->second);
+        if (it->first >= 0 &&
+                mPendingInputFrames.find(frameNumber) != mPendingInputFrames.end()) {
+            if (mPendingInputFrames[frameNumber].timestamp == it->first) {
+                mPendingInputFrames[frameNumber].result =
                         std::make_unique<CameraMetadata>(std::get<1>(it->second));
             } else {
                 ALOGE("%s: Capture result frameNumber/timestamp mapping changed between "
-                        "shutter and capture result!", __FUNCTION__);
+                        "shutter and capture result! before: %" PRId64 ", after: %" PRId64,
+                        __FUNCTION__, mPendingInputFrames[frameNumber].timestamp,
+                        it->first);
             }
         }
         mCaptureResults.erase(it);
@@ -641,22 +731,24 @@
     // mErrorFrameNumbers stores frame number of dropped buffers.
     auto it = mErrorFrameNumbers.begin();
     while (it != mErrorFrameNumbers.end()) {
-        bool frameFound = false;
-        for (auto &inputFrame : mPendingInputFrames) {
-            if (inputFrame.second.frameNumber == *it) {
-                inputFrame.second.error = true;
-                frameFound = true;
-                break;
-            }
-        }
-
-        if (frameFound) {
-            it = mErrorFrameNumbers.erase(it);
+        if (mPendingInputFrames.find(*it) != mPendingInputFrames.end()) {
+            mPendingInputFrames[*it].error = true;
         } else {
+            //Error callback is guaranteed to arrive after shutter notify, which
+            //results in mPendingInputFrames being populated.
             ALOGW("%s: Not able to find failing input with frame number: %" PRId64, __FUNCTION__,
                     *it);
-            it++;
         }
+        it = mErrorFrameNumbers.erase(it);
+    }
+
+    // mExifErrorFrameNumbers stores the frame number of dropped APP_SEGMENT buffers
+    it = mExifErrorFrameNumbers.begin();
+    while (it != mExifErrorFrameNumbers.end()) {
+        if (mPendingInputFrames.find(*it) != mPendingInputFrames.end()) {
+            mPendingInputFrames[*it].exifError = true;
+        }
+        it = mExifErrorFrameNumbers.erase(it);
     }
 
     // Distribute codec input buffers to be filled out from YUV output
@@ -681,8 +773,8 @@
     }
 }
 
-bool HeicCompositeStream::getNextReadyInputLocked(int64_t *currentTs /*out*/) {
-    if (currentTs == nullptr) {
+bool HeicCompositeStream::getNextReadyInputLocked(int64_t *frameNumber /*out*/) {
+    if (frameNumber == nullptr) {
         return false;
     }
 
@@ -695,7 +787,8 @@
         // This makes sure that muxer gets created only when an output tile is
         // generated, because right now we only handle 1 HEIC output buffer at a
         // time (max dequeued buffer count is 1).
-        bool appSegmentReady = (it.second.appSegmentBuffer.data != nullptr) &&
+        bool appSegmentReady =
+                (it.second.appSegmentBuffer.data != nullptr || it.second.exifError) &&
                 !it.second.appSegmentWritten && it.second.result != nullptr &&
                 it.second.muxer != nullptr;
         bool codecOutputReady = !it.second.codecOutputBuffers.empty();
@@ -704,9 +797,8 @@
         bool hasOutputBuffer = it.second.muxer != nullptr ||
                 (mDequeuedOutputBufferCnt < kMaxOutputSurfaceProducerCount);
         if ((!it.second.error) &&
-                (it.first < *currentTs) &&
                 (appSegmentReady || (codecOutputReady && hasOutputBuffer) || codecInputReady)) {
-            *currentTs = it.first;
+            *frameNumber = it.first;
             if (it.second.format == nullptr && mFormat != nullptr) {
                 it.second.format = mFormat->dup();
             }
@@ -718,16 +810,12 @@
     return newInputAvailable;
 }
 
-int64_t HeicCompositeStream::getNextFailingInputLocked(int64_t *currentTs /*out*/) {
+int64_t HeicCompositeStream::getNextFailingInputLocked() {
     int64_t res = -1;
-    if (currentTs == nullptr) {
-        return res;
-    }
 
     for (const auto& it : mPendingInputFrames) {
-        if (it.second.error && !it.second.errorNotified && (it.first < *currentTs)) {
-            *currentTs = it.first;
-            res = it.second.frameNumber;
+        if (it.second.error) {
+            res = it.first;
             break;
         }
     }
@@ -735,12 +823,13 @@
     return res;
 }
 
-status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp,
+status_t HeicCompositeStream::processInputFrame(int64_t frameNumber,
         InputFrame &inputFrame) {
     ATRACE_CALL();
     status_t res = OK;
 
-    bool appSegmentReady = inputFrame.appSegmentBuffer.data != nullptr &&
+    bool appSegmentReady =
+            (inputFrame.appSegmentBuffer.data != nullptr || inputFrame.exifError) &&
             !inputFrame.appSegmentWritten && inputFrame.result != nullptr &&
             inputFrame.muxer != nullptr;
     bool codecOutputReady = inputFrame.codecOutputBuffers.size() > 0;
@@ -750,8 +839,9 @@
             (mDequeuedOutputBufferCnt < kMaxOutputSurfaceProducerCount);
 
     ALOGV("%s: [%" PRId64 "]: appSegmentReady %d, codecOutputReady %d, codecInputReady %d,"
-            " dequeuedOutputBuffer %d", __FUNCTION__, timestamp, appSegmentReady,
-            codecOutputReady, codecInputReady, mDequeuedOutputBufferCnt);
+            " dequeuedOutputBuffer %d, timestamp %" PRId64, __FUNCTION__, frameNumber,
+            appSegmentReady, codecOutputReady, codecInputReady, mDequeuedOutputBufferCnt,
+            inputFrame.timestamp);
 
     // Handle inputs for Hevc tiling
     if (codecInputReady) {
@@ -771,7 +861,7 @@
     // codecOutputReady must be true. Otherwise, appSegmentReady is guaranteed
     // to be false, and the function must have returned early.
     if (inputFrame.muxer == nullptr) {
-        res = startMuxerForInputFrame(timestamp, inputFrame);
+        res = startMuxerForInputFrame(frameNumber, inputFrame);
         if (res != OK) {
             ALOGE("%s: Failed to create and start muxer: %s (%d)", __FUNCTION__,
                     strerror(-res), res);
@@ -781,7 +871,7 @@
 
     // Write JPEG APP segments data to the muxer.
     if (appSegmentReady) {
-        res = processAppSegment(timestamp, inputFrame);
+        res = processAppSegment(frameNumber, inputFrame);
         if (res != OK) {
             ALOGE("%s: Failed to process JPEG APP segments: %s (%d)", __FUNCTION__,
                     strerror(-res), res);
@@ -791,7 +881,7 @@
 
     // Write media codec bitstream buffers to muxer.
     while (!inputFrame.codecOutputBuffers.empty()) {
-        res = processOneCodecOutputFrame(timestamp, inputFrame);
+        res = processOneCodecOutputFrame(frameNumber, inputFrame);
         if (res != OK) {
             ALOGE("%s: Failed to process codec output frame: %s (%d)", __FUNCTION__,
                     strerror(-res), res);
@@ -801,7 +891,7 @@
 
     if (inputFrame.pendingOutputTiles == 0) {
         if (inputFrame.appSegmentWritten) {
-            res = processCompletedInputFrame(timestamp, inputFrame);
+            res = processCompletedInputFrame(frameNumber, inputFrame);
             if (res != OK) {
                 ALOGE("%s: Failed to process completed input frame: %s (%d)", __FUNCTION__,
                         strerror(-res), res);
@@ -817,7 +907,7 @@
     return res;
 }
 
-status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFrame &inputFrame) {
+status_t HeicCompositeStream::startMuxerForInputFrame(int64_t frameNumber, InputFrame &inputFrame) {
     sp<ANativeWindow> outputANW = mOutputSurface;
 
     auto res = outputANW->dequeueBuffer(mOutputSurface.get(), &inputFrame.anb, &inputFrame.fenceFd);
@@ -831,7 +921,7 @@
     // Combine current thread id, stream id and timestamp to uniquely identify image.
     std::ostringstream tempOutputFile;
     tempOutputFile << "HEIF-" << pthread_self() << "-"
-            << getStreamId() << "-" << timestamp;
+            << getStreamId() << "-" << frameNumber;
     inputFrame.fileFd = syscall(__NR_memfd_create, tempOutputFile.str().c_str(), MFD_CLOEXEC);
     if (inputFrame.fileFd < 0) {
         ALOGE("%s: Failed to create file %s. Error no is %d", __FUNCTION__,
@@ -851,17 +941,6 @@
                 strerror(-res), res);
         return res;
     }
-    // Set encoder quality
-    {
-        sp<AMessage> qualityParams = new AMessage;
-        qualityParams->setInt32(PARAMETER_KEY_VIDEO_BITRATE, inputFrame.quality);
-        res = mCodec->setParameters(qualityParams);
-        if (res != OK) {
-            ALOGE("%s: Failed to set codec quality: %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return res;
-        }
-    }
 
     ssize_t trackId = inputFrame.muxer->addTrack(inputFrame.format);
     if (trackId < 0) {
@@ -880,22 +959,27 @@
     }
 
     ALOGV("%s: [%" PRId64 "]: Muxer started for inputFrame", __FUNCTION__,
-            timestamp);
+            frameNumber);
     return OK;
 }
 
-status_t HeicCompositeStream::processAppSegment(nsecs_t timestamp, InputFrame &inputFrame) {
+status_t HeicCompositeStream::processAppSegment(int64_t frameNumber, InputFrame &inputFrame) {
     size_t app1Size = 0;
-    auto appSegmentSize = findAppSegmentsSize(inputFrame.appSegmentBuffer.data,
-            inputFrame.appSegmentBuffer.width * inputFrame.appSegmentBuffer.height,
-            &app1Size);
-    if (appSegmentSize == 0) {
-        ALOGE("%s: Failed to find JPEG APP segment size", __FUNCTION__);
-        return NO_INIT;
+    size_t appSegmentSize = 0;
+    if (!inputFrame.exifError) {
+        appSegmentSize = findAppSegmentsSize(inputFrame.appSegmentBuffer.data,
+                inputFrame.appSegmentBuffer.width * inputFrame.appSegmentBuffer.height,
+                &app1Size);
+        if (appSegmentSize == 0) {
+            ALOGE("%s: Failed to find JPEG APP segment size", __FUNCTION__);
+            return NO_INIT;
+        }
     }
 
     std::unique_ptr<ExifUtils> exifUtils(ExifUtils::create());
-    auto exifRes = exifUtils->initialize(inputFrame.appSegmentBuffer.data, app1Size);
+    auto exifRes = inputFrame.exifError ?
+            exifUtils->initializeEmpty() :
+            exifUtils->initialize(inputFrame.appSegmentBuffer.data, app1Size);
     if (!exifRes) {
         ALOGE("%s: Failed to initialize ExifUtils object!", __FUNCTION__);
         return BAD_VALUE;
@@ -936,7 +1020,7 @@
 
     sp<ABuffer> aBuffer = new ABuffer(appSegmentBuffer, appSegmentBufferSize);
     auto res = inputFrame.muxer->writeSampleData(aBuffer, inputFrame.trackIndex,
-            timestamp, MediaCodec::BUFFER_FLAG_MUXER_DATA);
+            inputFrame.timestamp, MediaCodec::BUFFER_FLAG_MUXER_DATA);
     delete[] appSegmentBuffer;
 
     if (res != OK) {
@@ -946,13 +1030,14 @@
     }
 
     ALOGV("%s: [%" PRId64 "]: appSegmentSize is %zu, width %d, height %d, app1Size %zu",
-          __FUNCTION__, timestamp, appSegmentSize, inputFrame.appSegmentBuffer.width,
+          __FUNCTION__, frameNumber, appSegmentSize, inputFrame.appSegmentBuffer.width,
           inputFrame.appSegmentBuffer.height, app1Size);
 
     inputFrame.appSegmentWritten = true;
     // Release the buffer now so any pending input app segments can be processed
     mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer);
     inputFrame.appSegmentBuffer.data = nullptr;
+    inputFrame.exifError = false;
     mLockedAppSegmentBufferCnt--;
 
     return OK;
@@ -1001,7 +1086,7 @@
     return OK;
 }
 
-status_t HeicCompositeStream::processOneCodecOutputFrame(nsecs_t timestamp,
+status_t HeicCompositeStream::processOneCodecOutputFrame(int64_t frameNumber,
         InputFrame &inputFrame) {
     auto it = inputFrame.codecOutputBuffers.begin();
     sp<MediaCodecBuffer> buffer;
@@ -1019,7 +1104,7 @@
 
     sp<ABuffer> aBuffer = new ABuffer(buffer->data(), buffer->size());
     res = inputFrame.muxer->writeSampleData(
-            aBuffer, inputFrame.trackIndex, timestamp, 0 /*flags*/);
+            aBuffer, inputFrame.trackIndex, inputFrame.timestamp, 0 /*flags*/);
     if (res != OK) {
         ALOGE("%s: Failed to write buffer index %d to muxer: %s (%d)",
                 __FUNCTION__, it->index, strerror(-res), res);
@@ -1036,11 +1121,11 @@
     inputFrame.codecOutputBuffers.erase(inputFrame.codecOutputBuffers.begin());
 
     ALOGV("%s: [%" PRId64 "]: Output buffer index %d",
-        __FUNCTION__, timestamp, it->index);
+        __FUNCTION__, frameNumber, it->index);
     return OK;
 }
 
-status_t HeicCompositeStream::processCompletedInputFrame(nsecs_t timestamp,
+status_t HeicCompositeStream::processCompletedInputFrame(int64_t frameNumber,
         InputFrame &inputFrame) {
     sp<ANativeWindow> outputANW = mOutputSurface;
     inputFrame.muxer->stop();
@@ -1079,7 +1164,7 @@
     blobHeader->blobId = static_cast<CameraBlobId>(0x00FE);
     blobHeader->blobSize = fSize;
 
-    res = native_window_set_buffers_timestamp(mOutputSurface.get(), timestamp);
+    res = native_window_set_buffers_timestamp(mOutputSurface.get(), inputFrame.timestamp);
     if (res != OK) {
         ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
                __FUNCTION__, getStreamId(), strerror(-res), res);
@@ -1095,13 +1180,14 @@
     inputFrame.anb = nullptr;
     mDequeuedOutputBufferCnt--;
 
-    ALOGV("%s: [%" PRId64 "]", __FUNCTION__, timestamp);
-    ATRACE_ASYNC_END("HEIC capture", inputFrame.frameNumber);
+    ALOGV("%s: [%" PRId64 "]", __FUNCTION__, frameNumber);
+    ATRACE_ASYNC_END("HEIC capture", frameNumber);
     return OK;
 }
 
 
-void HeicCompositeStream::releaseInputFrameLocked(InputFrame *inputFrame /*out*/) {
+void HeicCompositeStream::releaseInputFrameLocked(int64_t frameNumber,
+        InputFrame *inputFrame /*out*/) {
     if (inputFrame == nullptr) {
         return;
     }
@@ -1129,9 +1215,9 @@
         inputFrame->codecInputBuffers.erase(it);
     }
 
-    if ((inputFrame->error || mErrorState) && !inputFrame->errorNotified) {
-        notifyError(inputFrame->frameNumber);
-        inputFrame->errorNotified = true;
+    if (inputFrame->error || mErrorState) {
+        ALOGV("%s: notifyError called for frameNumber %" PRId64, __FUNCTION__, frameNumber);
+        notifyError(frameNumber, inputFrame->requestId);
     }
 
     if (inputFrame->fileFd >= 0) {
@@ -1143,21 +1229,39 @@
         sp<ANativeWindow> outputANW = mOutputSurface;
         outputANW->cancelBuffer(mOutputSurface.get(), inputFrame->anb, /*fence*/ -1);
         inputFrame->anb = nullptr;
+
+        mDequeuedOutputBufferCnt--;
     }
 }
 
 void HeicCompositeStream::releaseInputFramesLocked() {
     auto it = mPendingInputFrames.begin();
+    bool inputFrameDone = false;
     while (it != mPendingInputFrames.end()) {
         auto& inputFrame = it->second;
         if (inputFrame.error ||
-            (inputFrame.appSegmentWritten && inputFrame.pendingOutputTiles == 0)) {
-            releaseInputFrameLocked(&inputFrame);
+                (inputFrame.appSegmentWritten && inputFrame.pendingOutputTiles == 0)) {
+            releaseInputFrameLocked(it->first, &inputFrame);
             it = mPendingInputFrames.erase(it);
+            inputFrameDone = true;
         } else {
             it++;
         }
     }
+
+    // Update codec quality based on first upcoming input frame.
+    // Note that when encoding is in surface mode, currently there is  no
+    // way for camera service to synchronize quality setting on a per-frame
+    // basis: we don't get notification when codec is ready to consume a new
+    // input frame. So we update codec quality on a best-effort basis.
+    if (inputFrameDone) {
+        auto firstPendingFrame = mPendingInputFrames.begin();
+        if (firstPendingFrame != mPendingInputFrames.end()) {
+            updateCodecQualityLocked(firstPendingFrame->second.quality);
+        } else {
+            markTrackerIdle();
+        }
+    }
 }
 
 status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
@@ -1260,7 +1364,7 @@
     outputFormat->setInt32(KEY_I_FRAME_INTERVAL, 0);
     outputFormat->setInt32(KEY_COLOR_FORMAT,
             useGrid ? COLOR_FormatYUV420Flexible : COLOR_FormatSurface);
-    outputFormat->setInt32(KEY_FRAME_RATE, gridRows * gridCols);
+    outputFormat->setInt32(KEY_FRAME_RATE, useGrid ? gridRows * gridCols : kNoGridOpRate);
     // This only serves as a hint to encoder when encoding is not real-time.
     outputFormat->setInt32(KEY_OPERATING_RATE, useGrid ? kGridOpRate : kNoGridOpRate);
 
@@ -1374,20 +1478,6 @@
     return expectedSize;
 }
 
-int64_t HeicCompositeStream::findTimestampInNsLocked(int64_t timeInUs) {
-    for (const auto& fn : mFrameNumberMap) {
-        if (timeInUs == ns2us(fn.second)) {
-            return fn.second;
-        }
-    }
-    for (const auto& inputFrame : mPendingInputFrames) {
-        if (timeInUs == ns2us(inputFrame.first)) {
-            return inputFrame.first;
-        }
-    }
-    return -1;
-}
-
 status_t HeicCompositeStream::copyOneYuvTile(sp<MediaCodecBuffer>& codecBuffer,
         const CpuConsumer::LockedBuffer& yuvBuffer,
         size_t top, size_t left, size_t width, size_t height) {
@@ -1546,8 +1636,22 @@
     return maxAppsSegment * (2 + 0xFFFF) + sizeof(struct CameraBlob);
 }
 
+void HeicCompositeStream::updateCodecQualityLocked(int32_t quality) {
+    if (quality != mQuality) {
+        sp<AMessage> qualityParams = new AMessage;
+        qualityParams->setInt32(PARAMETER_KEY_VIDEO_BITRATE, quality);
+        status_t res = mCodec->setParameters(qualityParams);
+        if (res != OK) {
+            ALOGE("%s: Failed to set codec quality: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+        } else {
+            mQuality = quality;
+        }
+    }
+}
+
 bool HeicCompositeStream::threadLoop() {
-    int64_t currentTs = INT64_MAX;
+    int64_t frameNumber = -1;
     bool newInputAvailable = false;
 
     {
@@ -1563,19 +1667,25 @@
 
         while (!newInputAvailable) {
             compilePendingInputLocked();
-            newInputAvailable = getNextReadyInputLocked(&currentTs);
+            newInputAvailable = getNextReadyInputLocked(&frameNumber);
 
             if (!newInputAvailable) {
-                auto failingFrameNumber = getNextFailingInputLocked(&currentTs);
+                auto failingFrameNumber = getNextFailingInputLocked();
                 if (failingFrameNumber >= 0) {
-                    // We cannot erase 'mPendingInputFrames[currentTs]' at this point because it is
-                    // possible for two internal stream buffers to fail. In such scenario the
-                    // composite stream should notify the client about a stream buffer error only
-                    // once and this information is kept within 'errorNotified'.
-                    // Any present failed input frames will be removed on a subsequent call to
-                    // 'releaseInputFramesLocked()'.
-                    releaseInputFrameLocked(&mPendingInputFrames[currentTs]);
-                    currentTs = INT64_MAX;
+                    releaseInputFrameLocked(failingFrameNumber,
+                            &mPendingInputFrames[failingFrameNumber]);
+
+                    // It's okay to remove the entry from mPendingInputFrames
+                    // because:
+                    // 1. Only one internal stream (main input) is critical in
+                    // backing the output stream.
+                    // 2. If captureResult/appSegment arrives after the entry is
+                    // removed, they are simply skipped.
+                    mPendingInputFrames.erase(failingFrameNumber);
+                    if (mPendingInputFrames.size() == 0) {
+                        markTrackerIdle();
+                    }
+                    return true;
                 }
 
                 auto ret = mInputReadyCondition.waitRelative(mMutex, kWaitDuration);
@@ -1590,12 +1700,13 @@
         }
     }
 
-    auto res = processInputFrame(currentTs, mPendingInputFrames[currentTs]);
+    auto res = processInputFrame(frameNumber, mPendingInputFrames[frameNumber]);
     Mutex::Autolock l(mMutex);
     if (res != OK) {
-        ALOGE("%s: Failed processing frame with timestamp: %" PRIu64 ": %s (%d)",
-                __FUNCTION__, currentTs, strerror(-res), res);
-        mPendingInputFrames[currentTs].error = true;
+        ALOGE("%s: Failed processing frame with timestamp: %" PRIu64 ", frameNumber: %"
+                PRId64 ": %s (%d)", __FUNCTION__, mPendingInputFrames[frameNumber].timestamp,
+                frameNumber, strerror(-res), res);
+        mPendingInputFrames[frameNumber].error = true;
     }
 
     releaseInputFramesLocked();
@@ -1603,14 +1714,26 @@
     return true;
 }
 
+void HeicCompositeStream::flagAnExifErrorFrameNumber(int64_t frameNumber) {
+    Mutex::Autolock l(mMutex);
+    mExifErrorFrameNumbers.emplace(frameNumber);
+    mInputReadyCondition.signal();
+}
+
 bool HeicCompositeStream::onStreamBufferError(const CaptureResultExtras& resultExtras) {
     bool res = false;
+    int64_t frameNumber = resultExtras.frameNumber;
+
     // Buffer errors concerning internal composite streams should not be directly visible to
     // camera clients. They must only receive a single buffer error with the public composite
     // stream id.
-    if ((resultExtras.errorStreamId == mAppSegmentStreamId) ||
-            (resultExtras.errorStreamId == mMainImageStreamId)) {
-        flagAnErrorFrameNumber(resultExtras.frameNumber);
+    if (resultExtras.errorStreamId == mAppSegmentStreamId) {
+        ALOGV("%s: APP_SEGMENT frameNumber: %" PRId64, __FUNCTION__, frameNumber);
+        flagAnExifErrorFrameNumber(frameNumber);
+        res = true;
+    } else if (resultExtras.errorStreamId == mMainImageStreamId) {
+        ALOGV("%s: YUV frameNumber: %" PRId64, __FUNCTION__, frameNumber);
+        flagAnErrorFrameNumber(frameNumber);
         res = true;
     }
 
@@ -1623,16 +1746,16 @@
     Mutex::Autolock l(mMutex);
 
     int64_t timestamp = -1;
-    for (const auto& fn : mFrameNumberMap) {
+    for (const auto& fn : mSettingsByFrameNumber) {
         if (fn.first == resultExtras.frameNumber) {
-            timestamp = fn.second;
+            timestamp = fn.second.timestamp;
             break;
         }
     }
     if (timestamp == -1) {
         for (const auto& inputFrame : mPendingInputFrames) {
-            if (inputFrame.second.frameNumber == resultExtras.frameNumber) {
-                timestamp = inputFrame.first;
+            if (inputFrame.first == resultExtras.frameNumber) {
+                timestamp = inputFrame.second.timestamp;
                 break;
             }
         }
@@ -1644,9 +1767,33 @@
     }
 
     mCaptureResults.emplace(timestamp, std::make_tuple(resultExtras.frameNumber, CameraMetadata()));
+    ALOGV("%s: timestamp %" PRId64 ", frameNumber %" PRId64, __FUNCTION__,
+            timestamp, resultExtras.frameNumber);
     mInputReadyCondition.signal();
 }
 
+void HeicCompositeStream::onRequestError(const CaptureResultExtras& resultExtras) {
+    auto frameNumber = resultExtras.frameNumber;
+    ALOGV("%s: frameNumber: %" PRId64, __FUNCTION__, frameNumber);
+    Mutex::Autolock l(mMutex);
+    auto numRequests = mSettingsByFrameNumber.erase(frameNumber);
+    if (numRequests == 0) {
+        // Pending request has been populated into mPendingInputFrames
+        mErrorFrameNumbers.emplace(frameNumber);
+        mInputReadyCondition.signal();
+    } else {
+        // REQUEST_ERROR was received without onShutter.
+    }
+}
+
+void HeicCompositeStream::markTrackerIdle() {
+    sp<StatusTracker> statusTracker = mStatusTracker.promote();
+    if (statusTracker != nullptr) {
+        statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
+        ALOGV("%s: Mark component as idle", __FUNCTION__);
+    }
+}
+
 void HeicCompositeStream::CodecCallbackHandler::onMessageReceived(const sp<AMessage> &msg) {
     sp<HeicCompositeStream> parent = mParent.promote();
     if (parent == nullptr) return;
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 04e7b83..33ca69a 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -37,7 +37,7 @@
 class HeicCompositeStream : public CompositeStream, public Thread,
         public CpuConsumer::FrameAvailableListener {
 public:
-    HeicCompositeStream(wp<CameraDeviceBase> device,
+    HeicCompositeStream(sp<CameraDeviceBase> device,
             wp<hardware::camera2::ICameraDeviceCallbacks> cb);
     ~HeicCompositeStream() override;
 
@@ -55,6 +55,8 @@
     status_t insertGbp(SurfaceMap* /*out*/outSurfaceMap, Vector<int32_t>* /*out*/outputStreamIds,
             int32_t* /*out*/currentStreamId) override;
 
+    status_t insertCompositeStreamIds(std::vector<int32_t>* compositeStreamIds /*out*/) override;
+
     void onShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
 
     int getStreamId() override { return mMainImageStreamId; }
@@ -79,6 +81,7 @@
     bool threadLoop() override;
     bool onStreamBufferError(const CaptureResultExtras& resultExtras) override;
     void onResultError(const CaptureResultExtras& resultExtras) override;
+    void onRequestError(const CaptureResultExtras& resultExtras) override;
 
 private:
     //
@@ -154,9 +157,10 @@
         CpuConsumer::LockedBuffer          yuvBuffer;
         std::vector<CodecInputBufferInfo>  codecInputBuffers;
 
-        bool                      error;
-        bool                      errorNotified;
-        int64_t                   frameNumber;
+        bool                      error;     // Main input image buffer error
+        bool                      exifError; // Exif/APP_SEGMENT buffer error
+        int64_t                   timestamp;
+        int32_t                   requestId;
 
         sp<AMessage>              format;
         sp<MediaMuxer>            muxer;
@@ -170,35 +174,35 @@
         size_t                    codecInputCounter;
 
         InputFrame() : orientation(0), quality(kDefaultJpegQuality), error(false),
-                       errorNotified(false), frameNumber(-1), fenceFd(-1), fileFd(-1),
-                       trackIndex(-1), anb(nullptr), appSegmentWritten(false),
+                       exifError(false), timestamp(-1), requestId(-1), fenceFd(-1),
+                       fileFd(-1), trackIndex(-1), anb(nullptr), appSegmentWritten(false),
                        pendingOutputTiles(0), codecInputCounter(0) { }
     };
 
     void compilePendingInputLocked();
-    // Find first complete and valid frame with smallest timestamp
-    bool getNextReadyInputLocked(int64_t *currentTs /*out*/);
-    // Find next failing frame number with smallest timestamp and return respective frame number
-    int64_t getNextFailingInputLocked(int64_t *currentTs /*out*/);
+    // Find first complete and valid frame with smallest frame number
+    bool getNextReadyInputLocked(int64_t *frameNumber /*out*/);
+    // Find next failing frame number with smallest frame number and return respective frame number
+    int64_t getNextFailingInputLocked();
 
-    status_t processInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
+    status_t processInputFrame(int64_t frameNumber, InputFrame &inputFrame);
     status_t processCodecInputFrame(InputFrame &inputFrame);
-    status_t startMuxerForInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
-    status_t processAppSegment(nsecs_t timestamp, InputFrame &inputFrame);
-    status_t processOneCodecOutputFrame(nsecs_t timestamp, InputFrame &inputFrame);
-    status_t processCompletedInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
+    status_t startMuxerForInputFrame(int64_t frameNumber, InputFrame &inputFrame);
+    status_t processAppSegment(int64_t frameNumber, InputFrame &inputFrame);
+    status_t processOneCodecOutputFrame(int64_t frameNumber, InputFrame &inputFrame);
+    status_t processCompletedInputFrame(int64_t frameNumber, InputFrame &inputFrame);
 
-    void releaseInputFrameLocked(InputFrame *inputFrame /*out*/);
+    void releaseInputFrameLocked(int64_t frameNumber, InputFrame *inputFrame /*out*/);
     void releaseInputFramesLocked();
 
     size_t findAppSegmentsSize(const uint8_t* appSegmentBuffer, size_t maxSize,
             size_t* app1SegmentSize);
-    int64_t findTimestampInNsLocked(int64_t timeInUs);
     status_t copyOneYuvTile(sp<MediaCodecBuffer>& codecBuffer,
             const CpuConsumer::LockedBuffer& yuvBuffer,
             size_t top, size_t left, size_t width, size_t height);
     void initCopyRowFunction(int32_t width);
     static size_t calcAppSegmentMaxSize(const CameraMetadata& info);
+    void updateCodecQualityLocked(int32_t quality);
 
     static const nsecs_t kWaitDuration = 10000000; // 10 ms
     static const int32_t kDefaultJpegQuality = 99;
@@ -215,12 +219,14 @@
     sp<CpuConsumer>   mAppSegmentConsumer;
     sp<Surface>       mAppSegmentSurface;
     size_t            mAppSegmentMaxSize;
+    std::queue<int64_t> mAppSegmentFrameNumbers;
     CameraMetadata    mStaticInfo;
 
     int               mMainImageStreamId, mMainImageSurfaceId;
     sp<Surface>       mMainImageSurface;
     sp<CpuConsumer>   mMainImageConsumer; // Only applicable for HEVC codec.
     bool              mYuvBufferAcquired; // Only applicable to HEVC codec
+    std::queue<int64_t> mMainImageFrameNumbers;
 
     static const int32_t kMaxOutputSurfaceProducerCount = 1;
     sp<Surface>       mOutputSurface;
@@ -228,9 +234,22 @@
     int32_t           mDequeuedOutputBufferCnt;
 
     // Map from frame number to JPEG setting of orientation+quality
-    std::map<int64_t, std::pair<int32_t, int32_t>> mSettingsByFrameNumber;
-    // Map from timestamp to JPEG setting of orientation+quality
-    std::map<int64_t, std::pair<int32_t, int32_t>> mSettingsByTimestamp;
+    struct HeicSettings {
+        int32_t orientation;
+        int32_t quality;
+        int64_t timestamp;
+        int32_t requestId;
+        bool shutterNotified;
+
+        HeicSettings() : orientation(0), quality(95), timestamp(0),
+                requestId(-1), shutterNotified(false) {}
+        HeicSettings(int32_t _orientation, int32_t _quality) :
+                orientation(_orientation),
+                quality(_quality), timestamp(0),
+                requestId(-1), shutterNotified(false) {}
+
+    };
+    std::map<int64_t, HeicSettings> mSettingsByFrameNumber;
 
     // Keep all incoming APP segment Blob buffer pending further processing.
     std::vector<int64_t> mInputAppSegmentBuffers;
@@ -238,8 +257,9 @@
 
     // Keep all incoming HEIC blob buffer pending further processing.
     std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
-    std::queue<int64_t> mCodecOutputBufferTimestamps;
+    std::queue<int64_t> mCodecOutputBufferFrameNumbers;
     size_t mCodecOutputCounter;
+    int32_t mQuality;
 
     // Keep all incoming Yuv buffer pending tiling and encoding (for HEVC YUV tiling only)
     std::vector<int64_t> mInputYuvBuffers;
@@ -249,11 +269,19 @@
     // Artificial strictly incremental YUV grid timestamp to make encoder happy.
     int64_t mGridTimestampUs;
 
-    // In most common use case, entries are accessed in order.
+    // Indexed by frame number. In most common use case, entries are accessed in order.
     std::map<int64_t, InputFrame> mPendingInputFrames;
 
     // Function pointer of libyuv row copy.
     void (*mFnCopyRow)(const uint8_t* src, uint8_t* dst, int width);
+
+    // A set of APP_SEGMENT error frame numbers
+    std::set<int64_t> mExifErrorFrameNumbers;
+    void flagAnExifErrorFrameNumber(int64_t frameNumber);
+
+    // The status id for tracking the active/idle status of this composite stream
+    int mStatusId;
+    void markTrackerIdle();
 };
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
index d7cc2bf..d36ca3b 100644
--- a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
+++ b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
@@ -91,6 +91,8 @@
             // The "measured-frame-rate-WIDTHxHEIGHT-range" key is optional.
             // Hardcode to some default value (3.33ms * tile count) based on resolution.
             *stall = 3333333LL * width * height / (kGridWidth * kGridHeight);
+            *useHeic = chooseHeic;
+            *useGrid = enableGrid;
             return true;
         }
 
@@ -275,9 +277,13 @@
             ALOGE("%s: Failed to get codec info for %s", __FUNCTION__, mime);
             break;
         }
+        ALOGV("%s: [%s] codec found", __FUNCTION__,
+                info->getCodecName());
 
         // Filter out software ones as they may be too slow
         if (!(info->getAttributes() & MediaCodecInfo::kFlagIsHardwareAccelerated)) {
+            ALOGV("%s: [%s] Filter out software ones as they may be too slow", __FUNCTION__,
+                    info->getCodecName());
             continue;
         }
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 78feb3e..0a41776 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -44,13 +44,14 @@
         const sp<CameraService>& cameraService,
         const sp<TCamCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        const std::unique_ptr<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
         int servicePid):
-        TClientBase(cameraService, remoteCallback, clientPackageName,
+        TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
                 cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
         mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
@@ -110,7 +111,7 @@
         return res;
     }
 
-    wp<CameraDeviceBase::NotificationListener> weakThis(this);
+    wp<NotificationListener> weakThis(this);
     res = mDevice->setNotifyCallback(weakThis);
 
     return OK;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 6693847..042f5aa 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -29,7 +29,7 @@
 template <typename TClientBase>
 class Camera2ClientBase :
         public TClientBase,
-        public CameraDeviceBase::NotificationListener
+        public NotificationListener
 {
 public:
     typedef typename TClientBase::TCamCallbacks TCamCallbacks;
@@ -48,6 +48,7 @@
     Camera2ClientBase(const sp<CameraService>& cameraService,
                       const sp<TCamCallbacks>& remoteCallback,
                       const String16& clientPackageName,
+                      const std::unique_ptr<String16>& clientFeatureId,
                       const String8& cameraId,
                       int api1CameraId,
                       int cameraFacing,
@@ -60,7 +61,7 @@
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
 
     /**
-     * CameraDeviceBase::NotificationListener implementation
+     * NotificationListener implementation
      */
 
     virtual void          notifyError(int32_t errorCode,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.cpp b/services/camera/libcameraservice/common/CameraDeviceBase.cpp
index 6c4e87f..0efe4bc 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.cpp
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.cpp
@@ -24,7 +24,4 @@
 CameraDeviceBase::~CameraDeviceBase() {
 }
 
-CameraDeviceBase::NotificationListener::~NotificationListener() {
-}
-
 } // namespace android
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 98c1b5e..a537ef5 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -33,7 +33,11 @@
 #include "camera/CaptureResult.h"
 #include "gui/IGraphicBufferProducer.h"
 #include "device3/Camera3StreamInterface.h"
+#include "device3/StatusTracker.h"
 #include "binder/Status.h"
+#include "FrameProducer.h"
+
+#include "CameraOfflineSessionBase.h"
 
 namespace android {
 
@@ -46,16 +50,11 @@
  * Base interface for version >= 2 camera device classes, which interface to
  * camera HAL device versions >= 2.
  */
-class CameraDeviceBase : public virtual RefBase {
+class CameraDeviceBase : public virtual FrameProducer {
   public:
     virtual ~CameraDeviceBase();
 
     /**
-     * The device's camera ID
-     */
-    virtual const String8& getId() const = 0;
-
-    /**
      * The device vendor tag ID
      */
     virtual metadata_vendor_id_t getVendorTagId() const = 0;
@@ -66,13 +65,9 @@
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
 
     /**
-     * The device's static characteristics metadata buffer
-     */
-    virtual const CameraMetadata& info() const = 0;
-    /**
      * The physical camera device's static characteristics metadata buffer
      */
-    virtual const CameraMetadata& info(const String8& physicalId) const = 0;
+    virtual const CameraMetadata& infoPhysical(const String8& physicalId) const = 0;
 
     struct PhysicalCameraSettings {
         std::string cameraId;
@@ -232,6 +227,12 @@
     virtual status_t configureStreams(const CameraMetadata& sessionParams,
             int operatingMode = 0) = 0;
 
+    /**
+     * Retrieve a list of all stream ids that were advertised as capable of
+     * supporting offline processing mode by Hal after the last stream configuration.
+     */
+    virtual void getOfflineStreamIds(std::vector<int> *offlineStreamIds) = 0;
+
     // get the buffer producer of the input stream
     virtual status_t getInputBufferProducer(
             sp<IGraphicBufferProducer> *producer) = 0;
@@ -257,35 +258,6 @@
     virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const = 0;
 
     /**
-     * Abstract class for HAL notification listeners
-     */
-    class NotificationListener : public virtual RefBase {
-      public:
-        // The set of notifications is a merge of the notifications required for
-        // API1 and API2.
-
-        // Required for API 1 and 2
-        virtual void notifyError(int32_t errorCode,
-                                 const CaptureResultExtras &resultExtras) = 0;
-
-        // Required only for API2
-        virtual void notifyIdle() = 0;
-        virtual void notifyShutter(const CaptureResultExtras &resultExtras,
-                nsecs_t timestamp) = 0;
-        virtual void notifyPrepared(int streamId) = 0;
-        virtual void notifyRequestQueueEmpty() = 0;
-
-        // Required only for API1
-        virtual void notifyAutoFocus(uint8_t newState, int triggerId) = 0;
-        virtual void notifyAutoExposure(uint8_t newState, int triggerId) = 0;
-        virtual void notifyAutoWhitebalance(uint8_t newState,
-                int triggerId) = 0;
-        virtual void notifyRepeatingRequestError(long lastFrameNumber) = 0;
-      protected:
-        virtual ~NotificationListener();
-    };
-
-    /**
      * Connect HAL notifications to a listener. Overwrites previous
      * listener. Set to NULL to stop receiving notifications.
      */
@@ -299,21 +271,6 @@
     virtual bool     willNotify3A() = 0;
 
     /**
-     * Wait for a new frame to be produced, with timeout in nanoseconds.
-     * Returns TIMED_OUT when no frame produced within the specified duration
-     * May be called concurrently to most methods, except for getNextFrame
-     */
-    virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
-
-    /**
-     * Get next capture result frame from the result queue. Returns NOT_ENOUGH_DATA
-     * if the queue is empty; caller takes ownership of the metadata buffer inside
-     * the capture result object's metadata field.
-     * May be called concurrently to most methods, except for waitForNextFrame.
-     */
-    virtual status_t getNextResult(CaptureResult *frame) = 0;
-
-    /**
      * Trigger auto-focus. The latest ID used in a trigger autofocus or cancel
      * autofocus call will be returned by the HAL in all subsequent AF
      * notifications.
@@ -383,6 +340,33 @@
      * drop buffers for stream of streamId.
      */
     virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0;
+
+    /**
+     * Returns the maximum expected time it'll take for all currently in-flight
+     * requests to complete, based on their settings
+     */
+    virtual nsecs_t getExpectedInFlightDuration() = 0;
+
+    /**
+     * switch to offline session
+     */
+    virtual status_t switchToOffline(
+            const std::vector<int32_t>& streamsToKeep,
+            /*out*/ sp<CameraOfflineSessionBase>* session) = 0;
+
+    /**
+     * Set the current behavior for the ROTATE_AND_CROP control when in AUTO.
+     *
+     * The value must be one of the ROTATE_AND_CROP_* values besides AUTO,
+     * and defaults to NONE.
+     */
+    virtual status_t setRotateAndCropAutoBehavior(
+            camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) = 0;
+
+    /**
+     * Get the status tracker of the camera device
+     */
+    virtual wp<camera3::StatusTracker> getStatusTracker() = 0;
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp b/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp
new file mode 100644
index 0000000..ff673a9
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 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 "CameraOfflineSessionBase.h"
+
+namespace android {
+
+/**
+ * Base class destructors
+ */
+CameraOfflineSessionBase::~CameraOfflineSessionBase() {
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
new file mode 100644
index 0000000..1f835a9
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA_CAMERAOFFLINESESSIONBASE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAOFFLINESESSIONBASE_H
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "camera/CaptureResult.h"
+#include "FrameProducer.h"
+
+namespace android {
+
+/**
+ * Abstract class for HAL notification listeners
+ */
+class NotificationListener : public virtual RefBase {
+  public:
+    // The set of notifications is a merge of the notifications required for
+    // API1 and API2.
+
+    // Required for API 1 and 2
+    virtual void notifyError(int32_t errorCode,
+                             const CaptureResultExtras &resultExtras) = 0;
+
+    // Required only for API2
+    virtual void notifyIdle() = 0;
+    virtual void notifyShutter(const CaptureResultExtras &resultExtras,
+            nsecs_t timestamp) = 0;
+    virtual void notifyPrepared(int streamId) = 0;
+    virtual void notifyRequestQueueEmpty() = 0;
+
+    // Required only for API1
+    virtual void notifyAutoFocus(uint8_t newState, int triggerId) = 0;
+    virtual void notifyAutoExposure(uint8_t newState, int triggerId) = 0;
+    virtual void notifyAutoWhitebalance(uint8_t newState,
+            int triggerId) = 0;
+    virtual void notifyRepeatingRequestError(long lastFrameNumber) = 0;
+  protected:
+    virtual ~NotificationListener() {}
+};
+
+class CameraOfflineSessionBase : public virtual FrameProducer {
+  public:
+    virtual ~CameraOfflineSessionBase();
+
+    virtual status_t initialize(
+            wp<NotificationListener> listener) = 0;
+
+    virtual status_t disconnect() = 0;
+
+    virtual status_t dump(int fd) = 0;
+
+    // TODO: notification passing path
+}; // class CameraOfflineSessionBase
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index fdb5657..32d118d 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -37,15 +37,19 @@
 #include <android-base/logging.h>
 #include <cutils/properties.h>
 #include <hwbinder/IPCThreadState.h>
+#include <utils/SessionConfigurationUtils.h>
 #include <utils/Trace.h>
 
 #include "api2/HeicCompositeStream.h"
+#include "device3/ZoomRatioMapper.h"
 
 namespace android {
 
 using namespace ::android::hardware::camera;
 using namespace ::android::hardware::camera::common::V1_0;
 using std::literals::chrono_literals::operator""s;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
 
 namespace {
 const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
@@ -104,19 +108,30 @@
     return OK;
 }
 
-int CameraProviderManager::getCameraCount() const {
+std::pair<int, int> CameraProviderManager::getCameraCount() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    int count = 0;
+    int systemCameraCount = 0;
+    int publicCameraCount = 0;
     for (auto& provider : mProviders) {
-        for (auto& id : provider->mUniqueCameraIds) {
-            // Hidden secure camera ids are not to be exposed to camera1 api.
-            if (isPublicallyHiddenSecureCameraLocked(id)) {
+        for (auto &id : provider->mUniqueCameraIds) {
+            SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+            if (getSystemCameraKindLocked(id, &deviceKind) != OK) {
+                ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, id.c_str());
                 continue;
             }
-            count++;
+            switch(deviceKind) {
+                case SystemCameraKind::PUBLIC:
+                    publicCameraCount++;
+                    break;
+                case SystemCameraKind::SYSTEM_ONLY_CAMERA:
+                    systemCameraCount++;
+                    break;
+                default:
+                    break;
+            }
         }
     }
-    return count;
+    return std::make_pair(systemCameraCount, publicCameraCount);
 }
 
 std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
@@ -130,25 +145,47 @@
     return deviceIds;
 }
 
+void CameraProviderManager::collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+        std::vector<std::string>& publicDeviceIds,
+        std::vector<std::string>& systemDeviceIds) const {
+    for (auto &deviceId : deviceIds) {
+        SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+        if (getSystemCameraKindLocked(deviceId, &deviceKind) != OK) {
+            ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
+            continue;
+        }
+        if (deviceKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+            systemDeviceIds.push_back(deviceId);
+        } else {
+            publicDeviceIds.push_back(deviceId);
+        }
+    }
+}
+
 std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    std::vector<std::string> publicDeviceIds;
+    std::vector<std::string> systemDeviceIds;
     std::vector<std::string> deviceIds;
     for (auto& provider : mProviders) {
         std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
-
+        // Secure cameras should not be exposed through camera 1 api
+        providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
+                [this](const std::string& s) {
+                SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
+                if (getSystemCameraKindLocked(s, &deviceKind) != OK) {
+                    ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, s.c_str());
+                    return true;
+                }
+                return deviceKind == SystemCameraKind::HIDDEN_SECURE_CAMERA;}),
+                providerDeviceIds.end());
         // API1 app doesn't handle logical and physical camera devices well. So
         // for each camera facing, only take the first id advertised by HAL in
         // all [logical, physical1, physical2, ...] id combos, and filter out the rest.
         filterLogicalCameraIdsLocked(providerDeviceIds);
-        // Hidden secure camera ids are not to be exposed to camera1 api.
-        providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
-                [this](const std::string& s) {
-                    return this->isPublicallyHiddenSecureCameraLocked(s);}),
-                providerDeviceIds.end());
-        deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
+        collectDeviceIdsLocked(providerDeviceIds, publicDeviceIds, systemDeviceIds);
     }
-
-    std::sort(deviceIds.begin(), deviceIds.end(),
+    auto sortFunc =
             [](const std::string& a, const std::string& b) -> bool {
                 uint32_t aUint = 0, bUint = 0;
                 bool aIsUint = base::ParseUint(a, &aUint);
@@ -164,7 +201,13 @@
                 }
                 // Simple string compare if both id are not uint
                 return a < b;
-            });
+            };
+    // We put device ids for system cameras at the end since they will be pared
+    // off for processes not having system camera permissions.
+    std::sort(publicDeviceIds.begin(), publicDeviceIds.end(), sortFunc);
+    std::sort(systemDeviceIds.begin(), systemDeviceIds.end(), sortFunc);
+    deviceIds.insert(deviceIds.end(), publicDeviceIds.begin(), publicDeviceIds.end());
+    deviceIds.insert(deviceIds.end(), systemDeviceIds.begin(), systemDeviceIds.end());
     return deviceIds;
 }
 
@@ -193,6 +236,15 @@
     return deviceInfo->hasFlashUnit();
 }
 
+bool CameraProviderManager::supportNativeZoomRatio(const std::string &id) const {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo == nullptr) return false;
+
+    return deviceInfo->supportNativeZoomRatio();
+}
+
 status_t CameraProviderManager::getResourceCost(const std::string &id,
         CameraResourceCost* cost) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -218,7 +270,6 @@
         const hardware::camera::device::V3_4::StreamConfiguration &configuration,
         bool *status /*out*/) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) {
         return NAME_NOT_FOUND;
@@ -275,8 +326,11 @@
 
     // Pass the camera ID to start interface so that it will save it to the map of ICameraProviders
     // that are currently in use.
-    const sp<provider::V2_4::ICameraProvider> interface =
-            deviceInfo->mParentProvider->startProviderInterface();
+    sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    const sp<provider::V2_4::ICameraProvider> interface = parentProvider->startProviderInterface();
     if (interface == nullptr) {
         return DEAD_OBJECT;
     }
@@ -329,8 +383,11 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
-    const sp<provider::V2_4::ICameraProvider> provider =
-            deviceInfo->mParentProvider->startProviderInterface();
+    sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    const sp<provider::V2_4::ICameraProvider> provider = parentProvider->startProviderInterface();
     if (provider == nullptr) {
         return DEAD_OBJECT;
     }
@@ -372,8 +429,11 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
-    const sp<provider::V2_4::ICameraProvider> provider =
-            deviceInfo->mParentProvider->startProviderInterface();
+    sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    const sp<provider::V2_4::ICameraProvider> provider = parentProvider->startProviderInterface();
     if (provider == nullptr) {
         return DEAD_OBJECT;
     }
@@ -544,15 +604,23 @@
     }
 }
 
-bool CameraProviderManager::ProviderInfo::DeviceInfo3::isPublicallyHiddenSecureCamera() {
+SystemCameraKind CameraProviderManager::ProviderInfo::DeviceInfo3::getSystemCameraKind() {
     camera_metadata_entry_t entryCap;
     entryCap = mCameraCharacteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
-    if (entryCap.count != 1) {
-        // Do NOT hide this camera device if the capabilities specify anything more
-        // than ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA.
-        return false;
+    if (entryCap.count == 1 &&
+            entryCap.data.u8[0] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA) {
+        return SystemCameraKind::HIDDEN_SECURE_CAMERA;
     }
-    return entryCap.data.u8[0] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA;
+
+    // Go through the capabilities and check if it has
+    // ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA
+    for (size_t i = 0; i < entryCap.count; ++i) {
+        uint8_t capability = entryCap.data.u8[i];
+        if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA) {
+            return SystemCameraKind::SYSTEM_ONLY_CAMERA;
+        }
+    }
+    return SystemCameraKind::PUBLIC;
 }
 
 void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedSizes(
@@ -659,31 +727,6 @@
     }
 }
 
-bool CameraProviderManager::ProviderInfo::DeviceInfo3::isDepthPhotoLibraryPresent() {
-    static bool libraryPresent = false;
-    static bool initialized = false;
-    if (initialized) {
-        return libraryPresent;
-    } else {
-        initialized = true;
-    }
-
-    void* depthLibHandle = dlopen(camera3::kDepthPhotoLibrary, RTLD_NOW | RTLD_LOCAL);
-    if (depthLibHandle == nullptr) {
-        return false;
-    }
-
-    auto processFunc = dlsym(depthLibHandle, camera3::kDepthPhotoProcessFunction);
-    if (processFunc != nullptr) {
-        libraryPresent = true;
-    } else {
-        libraryPresent = false;
-    }
-    dlclose(depthLibHandle);
-
-    return libraryPresent;
-}
-
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addDynamicDepthTags() {
     uint32_t depthExclTag = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE;
     uint32_t depthSizesTag = ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS;
@@ -731,11 +774,6 @@
         return OK;
     }
 
-    if(!isDepthPhotoLibraryPresent()) {
-        // Depth photo processing library is not present, nothing more to do.
-        return OK;
-    }
-
     std::vector<int32_t> dynamicDepthEntries;
     for (const auto& it : supportedDynamicDepthSizes) {
         int32_t entry[4] = {HAL_PIXEL_FORMAT_BLOB, static_cast<int32_t> (std::get<0>(it)),
@@ -803,13 +841,6 @@
         itDuration++; itSize++;
     }
 
-    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
-            dynamicDepthEntries.data(), dynamicDepthEntries.size());
-    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
-            dynamicDepthMinDurationEntries.data(), dynamicDepthMinDurationEntries.size());
-    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
-            dynamicDepthStallDurationEntries.data(), dynamicDepthStallDurationEntries.size());
-
     std::vector<int32_t> supportedChTags;
     supportedChTags.reserve(chTags.count + 3);
     supportedChTags.insert(supportedChTags.end(), chTags.data.i32,
@@ -817,6 +848,12 @@
     supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
     supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS);
     supportedChTags.push_back(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS);
+    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
+            dynamicDepthEntries.data(), dynamicDepthEntries.size());
+    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS,
+            dynamicDepthMinDurationEntries.data(), dynamicDepthMinDurationEntries.size());
+    c.update(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS,
+            dynamicDepthStallDurationEntries.data(), dynamicDepthStallDurationEntries.size());
     c.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, supportedChTags.data(),
             supportedChTags.size());
 
@@ -899,6 +936,64 @@
     return res;
 }
 
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addRotateCropTags() {
+    status_t res = OK;
+    auto& c = mCameraCharacteristics;
+
+    auto availableRotateCropEntry = c.find(ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES);
+    if (availableRotateCropEntry.count == 0) {
+        uint8_t defaultAvailableRotateCropEntry = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+        res = c.update(ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES,
+                &defaultAvailableRotateCropEntry, 1);
+    }
+    return res;
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addPreCorrectionActiveArraySize() {
+    status_t res = OK;
+    auto& c = mCameraCharacteristics;
+
+    auto activeArraySize = c.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+    auto preCorrectionActiveArraySize = c.find(
+            ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+    if (activeArraySize.count == 4 && preCorrectionActiveArraySize.count == 0) {
+        std::vector<int32_t> preCorrectionArray(
+                activeArraySize.data.i32, activeArraySize.data.i32+4);
+        res = c.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+                preCorrectionArray.data(), 4);
+        if (res != OK) {
+            ALOGE("%s: Failed to add ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s(%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+    } else {
+        return res;
+    }
+
+    auto charTags = c.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+    bool hasPreCorrectionActiveArraySize = std::find(charTags.data.i32,
+            charTags.data.i32 + charTags.count,
+            ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE) !=
+            (charTags.data.i32 + charTags.count);
+    if (!hasPreCorrectionActiveArraySize) {
+        std::vector<int32_t> supportedCharTags;
+        supportedCharTags.reserve(charTags.count + 1);
+        supportedCharTags.insert(supportedCharTags.end(), charTags.data.i32,
+                charTags.data.i32 + charTags.count);
+        supportedCharTags.push_back(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+
+        res = c.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, supportedCharTags.data(),
+                supportedCharTags.size());
+        if (res != OK) {
+            ALOGE("%s: Failed to update ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS: %s(%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+    }
+
+    return res;
+}
+
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::removeAvailableKeys(
         CameraMetadata& c, const std::vector<uint32_t>& keys, uint32_t keyTag) {
     status_t res = OK;
@@ -957,7 +1052,8 @@
         if (sizeAvail) continue;
 
         int64_t stall = 0;
-        bool useHeic, useGrid;
+        bool useHeic = false;
+        bool useGrid = false;
         if (camera3::HeicCompositeStream::isSizeSupportedByHeifEncoder(
                 halStreamConfigs.data.i32[i+1], halStreamConfigs.data.i32[i+2],
                 &useHeic, &useGrid, &stall)) {
@@ -1043,10 +1139,8 @@
     return OK;
 }
 
-bool CameraProviderManager::isLogicalCamera(const std::string& id,
+bool CameraProviderManager::isLogicalCameraLocked(const std::string& id,
         std::vector<std::string>* physicalCameraIds) {
-    std::lock_guard<std::mutex> lock(mInterfaceMutex);
-
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) return false;
 
@@ -1056,15 +1150,24 @@
     return deviceInfo->mIsLogicalCamera;
 }
 
-bool CameraProviderManager::isPublicallyHiddenSecureCamera(const std::string& id) const {
+bool CameraProviderManager::isLogicalCamera(const std::string& id,
+        std::vector<std::string>* physicalCameraIds) {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    return isPublicallyHiddenSecureCameraLocked(id);
+    return isLogicalCameraLocked(id, physicalCameraIds);
 }
 
-bool CameraProviderManager::isPublicallyHiddenSecureCameraLocked(const std::string& id) const {
+status_t CameraProviderManager::getSystemCameraKind(const std::string& id,
+        SystemCameraKind *kind) const {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    return getSystemCameraKindLocked(id, kind);
+}
+
+status_t CameraProviderManager::getSystemCameraKindLocked(const std::string& id,
+        SystemCameraKind *kind) const {
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo != nullptr) {
-        return deviceInfo->mIsPublicallyHiddenSecureCamera;
+        *kind = deviceInfo->mSystemCameraKind;
+        return OK;
     }
     // If this is a hidden physical camera, we should return what kind of
     // camera the enclosing logical camera is.
@@ -1073,10 +1176,10 @@
         LOG_ALWAYS_FATAL_IF(id == isHiddenAndParent.second->mId,
                 "%s: hidden physical camera id %s and enclosing logical camera id %s are the same",
                 __FUNCTION__, id.c_str(), isHiddenAndParent.second->mId.c_str());
-        return isPublicallyHiddenSecureCameraLocked(isHiddenAndParent.second->mId);
+        return getSystemCameraKindLocked(isHiddenAndParent.second->mId, kind);
     }
-    // Invalid camera id
-    return true;
+    // Neither a hidden physical camera nor a logical camera
+    return NAME_NOT_FOUND;
 }
 
 bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) const {
@@ -1137,7 +1240,7 @@
     }
 
     sp<provider::V2_4::ICameraProvider> interface;
-    interface = mServiceProxy->getService(newProvider);
+    interface = mServiceProxy->tryGetService(newProvider);
 
     if (interface == nullptr) {
         ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
@@ -1218,25 +1321,27 @@
             mProviderName.c_str(), interface->isRemote());
 
     // Determine minor version
-    auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
-    if (castResult.isOk()) {
-        mMinorVersion = 5;
-    } else {
-        mMinorVersion = 4;
+    mMinorVersion = 4;
+    auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+    sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
+    if (cast2_6.isOk()) {
+        interface2_6 = cast2_6;
+        if (interface2_6 != nullptr) {
+            mMinorVersion = 6;
+        }
     }
-
-    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
-    // before setCallback returns
-    hardware::Return<Status> status = interface->setCallback(this);
-    if (!status.isOk()) {
-        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
-                __FUNCTION__, mProviderName.c_str(), status.description().c_str());
-        return DEAD_OBJECT;
-    }
-    if (status != Status::OK) {
-        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
-                __FUNCTION__, mProviderName.c_str());
-        return mapToStatusT(status);
+    // We need to check again since cast2_6.isOk() succeeds even if the provider
+    // version isn't actually 2.6.
+    if (interface2_6 == nullptr){
+        auto cast2_5 =
+                provider::V2_5::ICameraProvider::castFrom(interface);
+        sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
+        if (cast2_5.isOk()) {
+            interface2_5 = cast2_5;
+            if (interface != nullptr) {
+                mMinorVersion = 5;
+            }
+        }
     }
 
     hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
@@ -1267,6 +1372,7 @@
         return res;
     }
 
+    Status status;
     // Get initial list of camera devices, if any
     std::vector<std::string> devices;
     hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
@@ -1298,6 +1404,14 @@
         return mapToStatusT(status);
     }
 
+    // Get list of concurrent streaming camera device combinations
+    if (mMinorVersion >= 6) {
+        res = getConcurrentCameraIdsInternalLocked(interface2_6);
+        if (res != OK) {
+            return res;
+        }
+    }
+
     ret = interface->isSetTorchModeSupported(
         [this](auto status, bool supported) {
             if (status == Status::OK) {
@@ -1323,6 +1437,22 @@
         }
     }
 
+    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+    // before setCallback returns. setCallback must be called after addDevice so that
+    // the physical camera status callback can look up available regular
+    // cameras.
+    hardware::Return<Status> st = interface->setCallback(this);
+    if (!st.isOk()) {
+        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), st.description().c_str());
+        return DEAD_OBJECT;
+    }
+    if (st != Status::OK) {
+        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(st);
+    }
+
     ALOGI("Camera provider %s ready with %zu camera devices",
             mProviderName.c_str(), mDevices.size());
 
@@ -1530,6 +1660,75 @@
     return OK;
 }
 
+status_t CameraProviderManager::ProviderInfo::getConcurrentCameraIdsInternalLocked(
+        sp<provider::V2_6::ICameraProvider> &interface2_6) {
+    if (interface2_6 == nullptr) {
+        ALOGE("%s: null interface provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    Status status = Status::OK;
+    hardware::Return<void> ret =
+            interface2_6->getConcurrentStreamingCameraIds([&status, this](
+            Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+            const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+                        cameraDeviceIdCombinations) {
+            status = concurrentIdStatus;
+            if (status == Status::OK) {
+                mConcurrentCameraIdCombinations.clear();
+                for (auto& combination : cameraDeviceIdCombinations) {
+                    std::unordered_set<std::string> deviceIds;
+                    for (auto &cameraDeviceId : combination) {
+                        deviceIds.insert(cameraDeviceId.c_str());
+                    }
+                    mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+                }
+            } });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+            return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        ALOGE("%s: Unable to query for camera devices from provider '%s'",
+                    __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(status);
+    }
+    return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+    if (mMinorVersion < 6) {
+      // Unsupported operation, nothing to do here
+      return OK;
+    }
+    // Check if the provider is currently active - not going to start it up for this notification
+    auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+    if (interface == nullptr) {
+        ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+                mProviderName.c_str());
+        return INVALID_OPERATION;
+    }
+    auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+    if (castResult.isOk()) {
+        sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+        if (interface2_6 != nullptr) {
+            return getConcurrentCameraIdsInternalLocked(interface2_6);
+        } else {
+            // This should not happen since mMinorVersion >= 6
+            ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+            return UNKNOWN_ERROR;
+        }
+    }
+    return OK;
+}
+
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mConcurrentCameraIdCombinations;
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         CameraDeviceStatus newStatus) {
@@ -1563,6 +1762,10 @@
         }
         listener = mManager->getStatusListener();
         initialized = mInitialized;
+        if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+            ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+                      __FUNCTION__, mProviderName.c_str());
+        }
     }
     // Call without lock held to allow reentrancy into provider manager
     // Don't send the callback if providerInfo hasn't been initialized.
@@ -1574,6 +1777,61 @@
     return hardware::Void();
 }
 
+hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
+        const hardware::hidl_string& cameraDeviceName,
+        const hardware::hidl_string& physicalCameraDeviceName,
+        CameraDeviceStatus newStatus) {
+    sp<StatusListener> listener;
+    std::string id;
+    bool initialized = false;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        bool known = false;
+        for (auto& deviceInfo : mDevices) {
+            if (deviceInfo->mName == cameraDeviceName) {
+                id = deviceInfo->mId;
+
+                if (!deviceInfo->mIsLogicalCamera) {
+                    ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                            __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
+                    return hardware::Void();
+                }
+                if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+                        physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+                    ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                            __FUNCTION__, id.c_str(), physicalCameraDeviceName.c_str());
+                    return hardware::Void();
+                }
+                ALOGI("Camera device %s physical device %s status is now %s, was %s",
+                        cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+                        deviceStatusToString(newStatus), deviceStatusToString(
+                        deviceInfo->mPhysicalStatus[physicalCameraDeviceName]));
+                known = true;
+                break;
+            }
+        }
+        // Previously unseen device; status must not be NOT_PRESENT
+        if (!known) {
+            ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+                    mProviderName.c_str(), cameraDeviceName.c_str(),
+                    physicalCameraDeviceName.c_str());
+            return hardware::Void();
+        }
+        listener = mManager->getStatusListener();
+        initialized = mInitialized;
+    }
+    // Call without lock held to allow reentrancy into provider manager
+    // Don't send the callback if providerInfo hasn't been initialized.
+    // CameraService will initialize device status after provider is
+    // initialized
+    if (listener != nullptr && initialized) {
+        String8 physicalId(physicalCameraDeviceName.c_str());
+        listener->onDeviceStatusChanged(String8(id.c_str()),
+                physicalId, newStatus);
+    }
+    return hardware::Void();
+}
+
 hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         TorchModeStatus newStatus) {
@@ -1679,6 +1937,55 @@
     return OK;
 }
 
+status_t CameraProviderManager::ProviderInfo::isConcurrentSessionConfigurationSupported(
+        const hardware::hidl_vec<CameraIdAndStreamCombination> &halCameraIdsAndStreamCombinations,
+        bool *isSupported) {
+    status_t res = OK;
+    if (mMinorVersion >= 6) {
+        // Check if the provider is currently active - not going to start it up for this notification
+        auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+        if (interface == nullptr) {
+            // TODO: This might be some other problem
+            return INVALID_OPERATION;
+        }
+        auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+        if (castResult.isOk()) {
+            sp<provider::V2_6::ICameraProvider> interface_2_6 = castResult;
+            if (interface_2_6 != nullptr) {
+                Status callStatus;
+                auto cb =
+                        [&isSupported, &callStatus](Status s, bool supported) {
+                              callStatus = s;
+                              *isSupported = supported; };
+
+                auto ret =  interface_2_6->isConcurrentStreamCombinationSupported(
+                            halCameraIdsAndStreamCombinations, cb);
+                if (ret.isOk()) {
+                    switch (callStatus) {
+                        case Status::OK:
+                            // Expected case, do nothing.
+                            res = OK;
+                            break;
+                        case Status::METHOD_NOT_SUPPORTED:
+                            res = INVALID_OPERATION;
+                            break;
+                        default:
+                            ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
+                                      callStatus);
+                            res = UNKNOWN_ERROR;
+                    }
+                } else {
+                    ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+                    res = UNKNOWN_ERROR;
+                }
+                return res;
+            }
+        }
+    }
+    // unsupported operation
+    return INVALID_OPERATION;
+}
+
 template<class DeviceInfoT>
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     CameraProviderManager::ProviderInfo::initializeDeviceInfo(
@@ -1791,7 +2098,10 @@
     sp<InterfaceT> device;
     ATRACE_CALL();
     if (mSavedInterface == nullptr) {
-        device = mParentProvider->startDeviceInterface<InterfaceT>(mName);
+        sp<ProviderInfo> parentProvider = mParentProvider.promote();
+        if (parentProvider != nullptr) {
+            device = parentProvider->startDeviceInterface<InterfaceT>(mName);
+        }
     } else {
         device = (InterfaceT *) mSavedInterface.get();
     }
@@ -1966,7 +2276,7 @@
         return;
     }
 
-    mIsPublicallyHiddenSecureCamera = isPublicallyHiddenSecureCamera();
+    mSystemCameraKind = getSystemCameraKind();
 
     status_t res = fixupMonochromeTags();
     if (OK != res) {
@@ -1984,6 +2294,22 @@
         ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
     }
+    res = addRotateCropTags();
+    if (OK != res) {
+        ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+    }
+    res = addPreCorrectionActiveArraySize();
+    if (OK != res) {
+        ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+    }
+    res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+            &mCameraCharacteristics, &mSupportNativeZoomRatio);
+    if (OK != res) {
+        ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+    }
 
     camera_metadata_entry flashAvailable =
             mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
@@ -2045,6 +2371,13 @@
                         CameraProviderManager::statusToString(status), status);
                 return;
             }
+
+            res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+                    &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
+            if (OK != res) {
+                ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+            }
         }
     }
 
@@ -2522,6 +2855,125 @@
     return OK;
 }
 
+// Expects to have mInterfaceMutex locked
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::getConcurrentCameraIds() const {
+    std::vector<std::unordered_set<std::string>> deviceIdCombinations;
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    for (auto &provider : mProviders) {
+        for (auto &combinations : provider->getConcurrentCameraIdCombinations()) {
+            deviceIdCombinations.push_back(combinations);
+        }
+    }
+    return deviceIdCombinations;
+}
+
+status_t CameraProviderManager::convertToHALStreamCombinationAndCameraIdsLocked(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
+        bool *earlyExit) {
+    binder::Status bStatus = binder::Status::ok();
+    std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
+    bool shouldExit = false;
+    status_t res = OK;
+    for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+        hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+        CameraMetadata deviceInfo;
+        res = getCameraCharacteristicsLocked(cameraIdAndSessionConfig.mCameraId, &deviceInfo);
+        if (res != OK) {
+            return res;
+        }
+        metadataGetter getMetadata =
+                [this](const String8 &id) {
+                    CameraMetadata physicalDeviceInfo;
+                    getCameraCharacteristicsLocked(id.string(), &physicalDeviceInfo);
+                    return physicalDeviceInfo;
+                };
+        std::vector<std::string> physicalCameraIds;
+        isLogicalCameraLocked(cameraIdAndSessionConfig.mCameraId, &physicalCameraIds);
+        bStatus =
+            SessionConfigurationUtils::convertToHALStreamCombination(
+                    cameraIdAndSessionConfig.mSessionConfiguration,
+                    String8(cameraIdAndSessionConfig.mCameraId.c_str()), deviceInfo, getMetadata,
+                    physicalCameraIds, streamConfiguration, &shouldExit);
+        if (!bStatus.isOk()) {
+            ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
+            return INVALID_OPERATION;
+        }
+        if (shouldExit) {
+            *earlyExit = true;
+            return OK;
+        }
+        CameraIdAndStreamCombination halCameraIdAndStream;
+        halCameraIdAndStream.cameraId = cameraIdAndSessionConfig.mCameraId;
+        halCameraIdAndStream.streamConfiguration = streamConfiguration;
+        halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
+    }
+    *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
+    return OK;
+}
+
+// Checks if the containing vector of sets has any set that contains all of the
+// camera ids in cameraIdsAndSessionConfigs.
+static bool checkIfSetContainsAll(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        const std::vector<std::unordered_set<std::string>> &containingSets) {
+    for (auto &containingSet : containingSets) {
+        bool didHaveAll = true;
+        for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+            if (containingSet.find(cameraIdAndSessionConfig.mCameraId) == containingSet.end()) {
+                // a camera id doesn't belong to this set, keep looking in other
+                // sets
+                didHaveAll = false;
+                break;
+            }
+        }
+        if (didHaveAll) {
+            // found a set that has all camera ids, lets return;
+            return true;
+        }
+    }
+    return false;
+}
+
+status_t CameraProviderManager::isConcurrentSessionConfigurationSupported(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        bool *isSupported) {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    // Check if all the devices are a subset of devices advertised by the
+    // same provider through getConcurrentStreamingCameraIds()
+    // TODO: we should also do a findDeviceInfoLocked here ?
+    for (auto &provider : mProviders) {
+        if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
+                provider->getConcurrentCameraIdCombinations())) {
+            // For each camera device in cameraIdsAndSessionConfigs collect
+            // the streamConfigs and create the HAL
+            // CameraIdAndStreamCombination, exit early if needed
+            hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
+            bool knowUnsupported = false;
+            status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
+                    cameraIdsAndSessionConfigs, &halCameraIdsAndStreamCombinations,
+                    &knowUnsupported);
+            if (res != OK) {
+                ALOGE("%s unable to convert session configurations provided to HAL stream"
+                      "combinations", __FUNCTION__);
+                return res;
+            }
+            if (knowUnsupported) {
+                // We got to know the streams aren't valid before doing the HAL
+                // call itself.
+                *isSupported = false;
+                return OK;
+            }
+            return provider->isConcurrentSessionConfigurationSupported(
+                    halCameraIdsAndStreamCombinations, isSupported);
+        }
+    }
+    *isSupported = false;
+    //The set of camera devices were not found
+    return INVALID_OPERATION;
+}
+
 status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
         CameraMetadata* characteristics) const {
     auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 3a4655c..25d3639 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -23,12 +23,15 @@
 #include <string>
 #include <mutex>
 
+#include <camera/camera2/ConcurrentCamera.h>
 #include <camera/CameraParameters2.h>
 #include <camera/CameraMetadata.h>
 #include <camera/CameraBase.h>
 #include <utils/Errors.h>
 #include <android/hardware/camera/common/1.0/types.h>
 #include <android/hardware/camera/provider/2.5/ICameraProvider.h>
+#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
+#include <android/hardware/camera/provider/2.6/ICameraProvider.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <android/hidl/manager/1.0/IServiceNotification.h>
 #include <camera/VendorTagDescriptor.h>
@@ -54,6 +57,26 @@
             sp<VendorTagDescriptor>& descriptor);
 };
 
+enum SystemCameraKind {
+   /**
+    * These camera devices are visible to all apps and system components alike
+    */
+   PUBLIC = 0,
+
+   /**
+    * These camera devices are visible only to processes having the
+    * android.permission.SYSTEM_CAMERA permission. They are not exposed to 3P
+    * apps.
+    */
+   SYSTEM_ONLY_CAMERA,
+
+   /**
+    * These camera devices are visible only to HAL clients (that try to connect
+    * on a hwbinder thread).
+    */
+   HIDDEN_SECURE_CAMERA
+};
+
 /**
  * A manager for all camera providers available on an Android device.
  *
@@ -76,6 +99,10 @@
                 const std::string &serviceName,
                 const sp<hidl::manager::V1_0::IServiceNotification>
                 &notification) = 0;
+        // Will not wait for service to start if it's not already running
+        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> tryGetService(
+                const std::string &serviceName) = 0;
+        // Will block for service if it exists but isn't running
         virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                 const std::string &serviceName) = 0;
         virtual hardware::hidl_vec<hardware::hidl_string> listServices() = 0;
@@ -92,6 +119,10 @@
             return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
                     serviceName, notification);
         }
+        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> tryGetService(
+                const std::string &serviceName) override {
+            return hardware::camera::provider::V2_4::ICameraProvider::tryGetService(serviceName);
+        }
         virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                 const std::string &serviceName) override {
             return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
@@ -108,6 +139,9 @@
 
         virtual void onDeviceStatusChanged(const String8 &cameraId,
                 hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+        virtual void onDeviceStatusChanged(const String8 &cameraId,
+                const String8 &physicalCameraId,
+                hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
         virtual void onTorchStatusChanged(const String8 &cameraId,
                 hardware::camera::common::V1_0::TorchModeStatus newStatus) = 0;
         virtual void onNewProviderRegistered() = 0;
@@ -132,10 +166,10 @@
             ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
 
     /**
-     * Retrieve the total number of available cameras. This value may change dynamically as cameras
-     * are added or removed.
+     * Retrieve the total number of available cameras.
+     * This value may change dynamically as cameras are added or removed.
      */
-    int getCameraCount() const;
+    std::pair<int, int> getCameraCount() const;
 
     std::vector<std::string> getCameraDeviceIds() const;
 
@@ -159,6 +193,11 @@
     bool hasFlashUnit(const std::string &id) const;
 
     /**
+     * Return true if the camera device has native zoom ratio support.
+     */
+    bool supportNativeZoomRatio(const std::string &id) const;
+
+    /**
      * Return the resource cost of this camera device
      */
     status_t getResourceCost(const std::string &id,
@@ -177,6 +216,12 @@
     status_t getCameraCharacteristics(const std::string &id,
             CameraMetadata* characteristics) const;
 
+    status_t isConcurrentSessionConfigurationSupported(
+            const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
+                    &cameraIdsAndSessionConfigs,
+            bool *isSupported);
+
+    std::vector<std::unordered_set<std::string>> getConcurrentCameraIds() const;
     /**
      * Check for device support of specific stream combination.
      */
@@ -272,7 +317,7 @@
      */
     bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
 
-    bool isPublicallyHiddenSecureCamera(const std::string& id) const;
+    status_t getSystemCameraKind(const std::string& id, SystemCameraKind *kind) const;
     bool isHiddenPhysicalCamera(const std::string& cameraId) const;
 
     static const float kDepthARTolerance;
@@ -309,7 +354,7 @@
     std::mutex mProviderInterfaceMapLock;
 
     struct ProviderInfo :
-            virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
+            virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
             virtual public hardware::hidl_death_recipient
     {
         const std::string mProviderName;
@@ -347,12 +392,16 @@
         status_t dump(int fd, const Vector<String16>& args) const;
 
         // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
-        virtual hardware::Return<void> cameraDeviceStatusChange(
+        hardware::Return<void> cameraDeviceStatusChange(
                 const hardware::hidl_string& cameraDeviceName,
                 hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
-        virtual hardware::Return<void> torchModeStatusChange(
+        hardware::Return<void> torchModeStatusChange(
                 const hardware::hidl_string& cameraDeviceName,
                 hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
+        hardware::Return<void> physicalCameraDeviceStatusChange(
+                const hardware::hidl_string& cameraDeviceName,
+                const hardware::hidl_string& physicalCameraDeviceName,
+                hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
 
         // hidl_death_recipient interface - this locks the parent mInterfaceMutex
         virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
@@ -369,6 +418,17 @@
                 hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
                     newDeviceState);
 
+        std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
+
+        /**
+         * Query the camera provider for concurrent stream configuration support
+         */
+        status_t isConcurrentSessionConfigurationSupported(
+                const hardware::hidl_vec<
+                        hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+                                &halCameraIdsAndStreamCombinations,
+                bool *isSupported);
+
         // Basic device information, common to all camera devices
         struct DeviceInfo {
             const std::string mName;  // Full instance name
@@ -379,15 +439,18 @@
             std::vector<std::string> mPhysicalIds;
             hardware::CameraInfo mInfo;
             sp<IBase> mSavedInterface;
-            bool mIsPublicallyHiddenSecureCamera = false;
+            SystemCameraKind mSystemCameraKind = SystemCameraKind::PUBLIC;
 
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
             hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
+            std::map<std::string, hardware::camera::common::V1_0::CameraDeviceStatus>
+                    mPhysicalStatus;
 
-            sp<ProviderInfo> mParentProvider;
+            wp<ProviderInfo> mParentProvider;
 
             bool hasFlashUnit() const { return mHasFlashUnit; }
+            bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
             virtual status_t setTorchMode(bool enabled) = 0;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
             virtual bool isAPI1Compatible() const = 0;
@@ -421,10 +484,11 @@
                     mIsLogicalCamera(false), mResourceCost(resourceCost),
                     mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
                     mParentProvider(parentProvider), mHasFlashUnit(false),
-                    mPublicCameraIds(publicCameraIds) {}
+                    mSupportNativeZoomRatio(false), mPublicCameraIds(publicCameraIds) {}
             virtual ~DeviceInfo();
         protected:
-            bool mHasFlashUnit;
+            bool mHasFlashUnit; // const after constructor
+            bool mSupportNativeZoomRatio; // const after constructor
             const std::vector<std::string>& mPublicCameraIds;
 
             template<class InterfaceT>
@@ -497,9 +561,13 @@
             CameraMetadata mCameraCharacteristics;
             std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
             void queryPhysicalCameraIds();
-            bool isPublicallyHiddenSecureCamera();
+            SystemCameraKind getSystemCameraKind();
             status_t fixupMonochromeTags();
             status_t addDynamicDepthTags();
+            status_t deriveHeicTags();
+            status_t addRotateCropTags();
+            status_t addPreCorrectionActiveArraySize();
+
             static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
                     android_pixel_format_t format,
                     std::vector<std::tuple<size_t, size_t>> *sizes /*out*/);
@@ -510,7 +578,6 @@
             void getSupportedDynamicDepthDurations(const std::vector<int64_t>& depthDurations,
                     const std::vector<int64_t>& blobDurations,
                     std::vector<int64_t> *dynamicDepthDurations /*out*/);
-            static bool isDepthPhotoLibraryPresent();
             static void getSupportedDynamicDepthSizes(
                     const std::vector<std::tuple<size_t, size_t>>& blobSizes,
                     const std::vector<std::tuple<size_t, size_t>>& depthSizes,
@@ -523,7 +590,6 @@
                     std::vector<int64_t>* stallDurations,
                     const camera_metadata_entry& halStreamConfigs,
                     const camera_metadata_entry& halStreamDurations);
-            status_t deriveHeicTags();
         };
 
     private:
@@ -536,6 +602,8 @@
 
         bool mInitialized = false;
 
+        std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
+
         // Templated method to instantiate the right kind of DeviceInfo and call the
         // right CameraProvider getCameraDeviceInterface_* method.
         template<class DeviceInfoT>
@@ -559,6 +627,12 @@
         static metadata_vendor_id_t generateVendorTagId(const std::string &name);
 
         void removeDevice(std::string id);
+
+        // Expects to have mLock locked
+        status_t reCacheConcurrentStreamingCameraIdsLocked();
+        // Expects to have mLock locked
+        status_t getConcurrentCameraIdsInternalLocked(
+                sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
     };
 
     // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
@@ -572,6 +646,8 @@
 
     status_t addProviderLocked(const std::string& newProvider);
 
+    bool isLogicalCameraLocked(const std::string& id, std::vector<std::string>* physicalCameraIds);
+
     status_t removeProvider(const std::string& provider);
     sp<StatusListener> getStatusListener() const;
 
@@ -594,15 +670,21 @@
 
     status_t getCameraCharacteristicsLocked(const std::string &id,
             CameraMetadata* characteristics) const;
-
-    bool isPublicallyHiddenSecureCameraLocked(const std::string& id) const;
-
     void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
 
-    bool isPublicallyHiddenSecureCameraLocked(const std::string& id);
+    status_t getSystemCameraKindLocked(const std::string& id, SystemCameraKind *kind) const;
+    std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
 
-    std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
-            isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
+    void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+            std::vector<std::string>& normalDeviceIds,
+            std::vector<std::string>& systemCameraDeviceIds) const;
+
+    status_t convertToHALStreamCombinationAndCameraIdsLocked(
+              const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
+                      &cameraIdsAndSessionConfigs,
+              hardware::hidl_vec<hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+                      *halCameraIdsAndStreamCombinations,
+              bool *earlyExit);
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
index 94541d8..c995670 100644
--- a/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
+++ b/services/camera/libcameraservice/common/DepthPhotoProcessor.cpp
@@ -410,7 +410,7 @@
     return DepthMap::FromData(depthParams, items);
 }
 
-extern "C" int processDepthPhotoFrame(DepthPhotoInputFrame inputFrame, size_t depthPhotoBufferSize,
+int processDepthPhotoFrame(DepthPhotoInputFrame inputFrame, size_t depthPhotoBufferSize,
         void* depthPhotoBuffer /*out*/, size_t* depthPhotoActualSize /*out*/) {
     if ((inputFrame.mMainJpegBuffer == nullptr) || (inputFrame.mDepthMapBuffer == nullptr) ||
             (depthPhotoBuffer == nullptr) || (depthPhotoActualSize == nullptr)) {
diff --git a/services/camera/libcameraservice/common/DepthPhotoProcessor.h b/services/camera/libcameraservice/common/DepthPhotoProcessor.h
index ba5ca9e..09b6935 100644
--- a/services/camera/libcameraservice/common/DepthPhotoProcessor.h
+++ b/services/camera/libcameraservice/common/DepthPhotoProcessor.h
@@ -64,9 +64,7 @@
             mOrientation(DepthPhotoOrientation::DEPTH_ORIENTATION_0_DEGREES) {}
 };
 
-static const char *kDepthPhotoLibrary = "libdepthphoto.so";
-static const char *kDepthPhotoProcessFunction = "processDepthPhotoFrame";
-typedef int (*process_depth_photo_frame) (DepthPhotoInputFrame /*inputFrame*/,
+int processDepthPhotoFrame(DepthPhotoInputFrame /*inputFrame*/,
         size_t /*depthPhotoBufferSize*/, void* /*depthPhotoBuffer out*/,
         size_t* /*depthPhotoActualSize out*/);
 
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index 3d56cd2..e259379 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -18,20 +18,21 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <map>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include "common/FrameProducer.h"
 #include "common/FrameProcessorBase.h"
-#include "common/CameraDeviceBase.h"
 
 namespace android {
 namespace camera2 {
 
-FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
+FrameProcessorBase::FrameProcessorBase(wp<FrameProducer> device) :
     Thread(/*canCallJava*/false),
     mDevice(device),
     mNumPartialResults(1) {
-    sp<CameraDeviceBase> cameraDevice = device.promote();
+    sp<FrameProducer> cameraDevice = device.promote();
     if (cameraDevice != 0) {
         CameraMetadata staticInfo = cameraDevice->info();
         camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
@@ -115,7 +116,7 @@
 bool FrameProcessorBase::threadLoop() {
     status_t res;
 
-    sp<CameraDeviceBase> device;
+    sp<FrameProducer> device;
     {
         device = mDevice.promote();
         if (device == 0) return false;
@@ -132,7 +133,7 @@
     return true;
 }
 
-void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
+void FrameProcessorBase::processNewFrames(const sp<FrameProducer> &device) {
     status_t res;
     ATRACE_CALL();
     CaptureResult result;
@@ -142,7 +143,7 @@
     while ( (res = device->getNextResult(&result)) == OK) {
 
         // TODO: instead of getting frame number from metadata, we should read
-        // this from result.mResultExtras when CameraDeviceBase interface is fixed.
+        // this from result.mResultExtras when FrameProducer interface is fixed.
         camera_metadata_entry_t entry;
 
         entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
@@ -174,14 +175,14 @@
 }
 
 bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
-                                            const sp<CameraDeviceBase> &device) {
+                                            const sp<FrameProducer> &device) {
     ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
             __FUNCTION__, device->getId().string(), result.mMetadata.isEmpty());
     return processListeners(result, device) == OK;
 }
 
 status_t FrameProcessorBase::processListeners(const CaptureResult &result,
-        const sp<CameraDeviceBase> &device) {
+        const sp<FrameProducer> &device) {
     ATRACE_CALL();
 
     camera_metadata_ro_entry_t entry;
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h
index ae6d15d..be1ebc6 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.h
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.h
@@ -27,22 +27,25 @@
 
 namespace android {
 
-class CameraDeviceBase;
+class FrameProducer;
 
 namespace camera2 {
 
 /* Output frame metadata processing thread.  This thread waits for new
- * frames from the device, and analyzes them as necessary.
+ * frames from the frame producer, and analyzes them as necessary.
  */
 class FrameProcessorBase: public Thread {
   public:
-    explicit FrameProcessorBase(wp<CameraDeviceBase> device);
+    explicit FrameProcessorBase(wp<FrameProducer> device);
     virtual ~FrameProcessorBase();
 
     struct FilteredListener: virtual public RefBase {
         virtual void onResultAvailable(const CaptureResult &result) = 0;
     };
 
+    static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
+    static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
+
     // Register a listener for a range of IDs [minId, maxId). Multiple listeners
     // can be listening to the same range. Registering the same listener with
     // the same range of IDs has no effect.
@@ -56,7 +59,7 @@
     void dump(int fd, const Vector<String16>& args);
   protected:
     static const nsecs_t kWaitDuration = 10000000; // 10 ms
-    wp<CameraDeviceBase> mDevice;
+    wp<FrameProducer> mDevice;
 
     virtual bool threadLoop();
 
@@ -74,13 +77,13 @@
     // Number of partial result the HAL will potentially send.
     int32_t mNumPartialResults;
 
-    void processNewFrames(const sp<CameraDeviceBase> &device);
+    void processNewFrames(const sp<FrameProducer> &device);
 
     virtual bool processSingleFrame(CaptureResult &result,
-                                    const sp<CameraDeviceBase> &device);
+                                    const sp<FrameProducer> &device);
 
     status_t processListeners(const CaptureResult &result,
-                              const sp<CameraDeviceBase> &device);
+                              const sp<FrameProducer> &device);
 
     CameraMetadata mLastFrame;
     std::vector<PhysicalCaptureResultInfo> mLastPhysicalFrames;
diff --git a/services/camera/libcameraservice/common/FrameProducer.h b/services/camera/libcameraservice/common/FrameProducer.h
new file mode 100644
index 0000000..a14b3d6
--- /dev/null
+++ b/services/camera/libcameraservice/common/FrameProducer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_FRAMEPRODUCER_H
+#define ANDROID_SERVERS_CAMERA_FRAMEPRODUCER_H
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "camera/CameraMetadata.h"
+#include "camera/CaptureResult.h"
+
+namespace android {
+
+/**
+ * Abstract class for HAL frame producers
+ */
+class FrameProducer : public virtual RefBase {
+  public:
+    /**
+     * Retrieve the static characteristics metadata buffer
+     */
+    virtual const CameraMetadata& info() const = 0;
+
+    /**
+     * Retrieve the device camera ID
+     */
+    virtual const String8& getId() const = 0;
+
+    /**
+     * Wait for a new frame to be produced, with timeout in nanoseconds.
+     * Returns TIMED_OUT when no frame produced within the specified duration
+     * May be called concurrently to most methods, except for getNextFrame
+     */
+    virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
+
+    /**
+     * Get next capture result frame from the result queue. Returns NOT_ENOUGH_DATA
+     * if the queue is empty; caller takes ownership of the metadata buffer inside
+     * the capture result object's metadata field.
+     * May be called concurrently to most methods, except for waitForNextFrame.
+     */
+    virtual status_t getNextResult(CaptureResult *frame) = 0;
+
+}; // class FrameProducer
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 522d521..62ef681 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -165,8 +165,12 @@
         mem = mHidlMemPoolMap.at(data);
     }
     sp<CameraHeapMemory> heapMem(static_cast<CameraHeapMemory *>(mem->handle));
+    // TODO: Using unsecurePointer() has some associated security pitfalls
+    //       (see declaration for details).
+    //       Either document why it is safe in this case or address the
+    //       issue (e.g. by copying).
     VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*)
-            heapMem->mBuffers[bufferIndex]->pointer();
+            heapMem->mBuffers[bufferIndex]->unsecurePointer();
     md->pHandle = const_cast<native_handle_t*>(frameData.getNativeHandle());
     sDataCbTimestamp(timestamp, (int32_t) msgType, mem, bufferIndex, this);
     return hardware::Void();
@@ -192,8 +196,12 @@
                      hidl_msg.bufferIndex, mem->mNumBufs);
                 return hardware::Void();
             }
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
             VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*)
-                    mem->mBuffers[hidl_msg.bufferIndex]->pointer();
+                    mem->mBuffers[hidl_msg.bufferIndex]->unsecurePointer();
             md->pHandle = const_cast<native_handle_t*>(hidl_msg.frameData.getNativeHandle());
 
             msgs.push_back({hidl_msg.timestamp, mem->mBuffers[hidl_msg.bufferIndex]});
@@ -578,7 +586,11 @@
     int bufferIndex = offset / size;
     if (CC_LIKELY(mHidlDevice != nullptr)) {
         if (size == sizeof(VideoNativeHandleMetadata)) {
-            VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->pointer();
+            // TODO: Using unsecurePointer() has some associated security pitfalls
+            //       (see declaration for details).
+            //       Either document why it is safe in this case or address the
+            //       issue (e.g. by copying).
+            VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->unsecurePointer();
             // Caching the handle here because md->pHandle will be subject to HAL's edit
             native_handle_t* nh = md->pHandle;
             hidl_handle frame = nh;
@@ -605,7 +617,11 @@
             if (size == sizeof(VideoNativeHandleMetadata)) {
                 uint32_t heapId = heap->getHeapID();
                 uint32_t bufferIndex = offset / size;
-                VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->pointer();
+                // TODO: Using unsecurePointer() has some associated security pitfalls
+                //       (see declaration for details).
+                //       Either document why it is safe in this case or address the
+                //       issue (e.g. by copying).
+                VideoNativeHandleMetadata* md = (VideoNativeHandleMetadata*) mem->unsecurePointer();
                 // Caching the handle here because md->pHandle will be subject to HAL's edit
                 native_handle_t* nh = md->pHandle;
                 VideoFrameMessage msg;
diff --git a/services/camera/libcameraservice/device3/BufferUtils.cpp b/services/camera/libcameraservice/device3/BufferUtils.cpp
new file mode 100644
index 0000000..cc29390
--- /dev/null
+++ b/services/camera/libcameraservice/device3/BufferUtils.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2019 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_TAG "Camera3-BufUtils"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+
+#include "device3/BufferUtils.h"
+
+namespace android {
+namespace camera3 {
+
+camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
+    using hardware::camera::device::V3_2::BufferStatus;
+
+    switch (status) {
+        case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
+        case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
+    }
+    return CAMERA3_BUFFER_STATUS_ERROR;
+}
+
+void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
+    std::lock_guard<std::mutex> oLock(other.mInflightLock);
+    std::lock_guard<std::mutex> lock(mInflightLock);
+    if (mInflightBufferMap.size() > 0) {
+        ALOGE("%s: inflight map is set in non-empty state!", __FUNCTION__);
+    }
+    mInflightBufferMap = std::move(other.mInflightBufferMap);
+    other.mInflightBufferMap.clear();
+}
+
+void BufferRecords::takeRequestedBufferMap(BufferRecords& other) {
+    std::lock_guard<std::mutex> oLock(other.mRequestedBuffersLock);
+    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
+    if (mRequestedBufferMap.size() > 0) {
+        ALOGE("%s: requested buffer map is set in non-empty state!", __FUNCTION__);
+    }
+    mRequestedBufferMap = std::move(other.mRequestedBufferMap);
+    other.mRequestedBufferMap.clear();
+}
+
+void BufferRecords::takeBufferCaches(BufferRecords& other, const std::vector<int32_t>& streams) {
+    std::lock_guard<std::mutex> oLock(other.mBufferIdMapLock);
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    if (mBufferIdMaps.size() > 0) {
+        ALOGE("%s: buffer ID map is set in non-empty state!", __FUNCTION__);
+    }
+    for (auto streamId : streams) {
+        mBufferIdMaps.insert({streamId, std::move(other.mBufferIdMaps.at(streamId))});
+    }
+    other.mBufferIdMaps.clear();
+}
+
+std::pair<bool, uint64_t> BufferRecords::getBufferId(
+        const buffer_handle_t& buf, int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+    BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
+    auto it = bIdMap.find(buf);
+    if (it == bIdMap.end()) {
+        bIdMap[buf] = mNextBufferId++;
+        ALOGV("stream %d now have %zu buffer caches, buf %p",
+                streamId, bIdMap.size(), buf);
+        return std::make_pair(true, mNextBufferId - 1);
+    } else {
+        return std::make_pair(false, it->second);
+    }
+}
+
+void BufferRecords::tryCreateBufferCache(int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    if (mBufferIdMaps.count(streamId) == 0) {
+        mBufferIdMaps.emplace(streamId, BufferIdMap{});
+    }
+}
+
+void BufferRecords::removeInactiveBufferCaches(const std::set<int32_t>& activeStreams) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
+        int streamId = it->first;
+        bool active = activeStreams.count(streamId) > 0;
+        if (!active) {
+            it = mBufferIdMaps.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+uint64_t BufferRecords::removeOneBufferCache(int streamId, const native_handle_t* handle) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    uint64_t bufferId = BUFFER_ID_NO_BUFFER;
+    auto mapIt = mBufferIdMaps.find(streamId);
+    if (mapIt == mBufferIdMaps.end()) {
+        // streamId might be from a deleted stream here
+        ALOGI("%s: stream %d has been removed",
+                __FUNCTION__, streamId);
+        return BUFFER_ID_NO_BUFFER;
+    }
+    BufferIdMap& bIdMap = mapIt->second;
+    auto it = bIdMap.find(handle);
+    if (it == bIdMap.end()) {
+        ALOGW("%s: cannot find buffer %p in stream %d",
+                __FUNCTION__, handle, streamId);
+        return BUFFER_ID_NO_BUFFER;
+    } else {
+        bufferId = it->second;
+        bIdMap.erase(it);
+        ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
+                __FUNCTION__, streamId, bIdMap.size(), handle);
+    }
+    return bufferId;
+}
+
+std::vector<uint64_t> BufferRecords::clearBufferCaches(int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    std::vector<uint64_t> ret;
+    auto mapIt = mBufferIdMaps.find(streamId);
+    if (mapIt == mBufferIdMaps.end()) {
+        ALOGE("%s: streamId %d not found!", __FUNCTION__, streamId);
+        return ret;
+    }
+    BufferIdMap& bIdMap = mapIt->second;
+    ret.reserve(bIdMap.size());
+    for (const auto& it : bIdMap) {
+        ret.push_back(it.second);
+    }
+    bIdMap.clear();
+    return ret;
+}
+
+bool BufferRecords::isStreamCached(int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    return mBufferIdMaps.find(streamId) != mBufferIdMaps.end();
+}
+
+bool BufferRecords::verifyBufferIds(
+        int32_t streamId, std::vector<uint64_t>& bufIds) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+    camera3::BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
+    if (bIdMap.size() != bufIds.size()) {
+        ALOGE("%s: stream ID %d buffer cache number mismatch: %zu/%zu (service/HAL)",
+                __FUNCTION__, streamId, bIdMap.size(), bufIds.size());
+        return false;
+    }
+    std::vector<uint64_t> internalBufIds;
+    internalBufIds.reserve(bIdMap.size());
+    for (const auto& pair : bIdMap) {
+        internalBufIds.push_back(pair.second);
+    }
+    std::sort(bufIds.begin(), bufIds.end());
+    std::sort(internalBufIds.begin(), internalBufIds.end());
+    for (size_t i = 0; i < bufIds.size(); i++) {
+        if (bufIds[i] != internalBufIds[i]) {
+            ALOGE("%s: buffer cache mismatch! Service %" PRIu64 ", HAL %" PRIu64,
+                    __FUNCTION__, internalBufIds[i], bufIds[i]);
+            return false;
+        }
+    }
+    return true;
+}
+
+void BufferRecords::getInflightBufferKeys(
+        std::vector<std::pair<int32_t, int32_t>>* out) {
+    std::lock_guard<std::mutex> lock(mInflightLock);
+    out->clear();
+    out->reserve(mInflightBufferMap.size());
+    for (auto& pair : mInflightBufferMap) {
+        uint64_t key = pair.first;
+        int32_t streamId = key & 0xFFFFFFFF;
+        int32_t frameNumber = (key >> 32) & 0xFFFFFFFF;
+        out->push_back(std::make_pair(frameNumber, streamId));
+    }
+    return;
+}
+
+status_t BufferRecords::pushInflightBuffer(
+        int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer) {
+    std::lock_guard<std::mutex> lock(mInflightLock);
+    uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
+    mInflightBufferMap[key] = buffer;
+    return OK;
+}
+
+status_t BufferRecords::popInflightBuffer(
+        int32_t frameNumber, int32_t streamId,
+        /*out*/ buffer_handle_t **buffer) {
+    std::lock_guard<std::mutex> lock(mInflightLock);
+
+    uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
+    auto it = mInflightBufferMap.find(key);
+    if (it == mInflightBufferMap.end()) return NAME_NOT_FOUND;
+    if (buffer != nullptr) {
+        *buffer = it->second;
+    }
+    mInflightBufferMap.erase(it);
+    return OK;
+}
+
+void BufferRecords::popInflightBuffers(
+        const std::vector<std::pair<int32_t, int32_t>>& buffers) {
+    for (const auto& pair : buffers) {
+        int32_t frameNumber = pair.first;
+        int32_t streamId = pair.second;
+        popInflightBuffer(frameNumber, streamId, nullptr);
+    }
+}
+
+status_t BufferRecords::pushInflightRequestBuffer(
+        uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
+    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
+    auto pair = mRequestedBufferMap.insert({bufferId, {streamId, buf}});
+    if (!pair.second) {
+        ALOGE("%s: bufId %" PRIu64 " is already inflight!",
+                __FUNCTION__, bufferId);
+        return BAD_VALUE;
+    }
+    return OK;
+}
+
+// Find and pop a buffer_handle_t based on bufferId
+status_t BufferRecords::popInflightRequestBuffer(
+        uint64_t bufferId,
+        /*out*/ buffer_handle_t** buffer,
+        /*optional out*/ int32_t* streamId) {
+    if (buffer == nullptr) {
+        ALOGE("%s: buffer (%p) must not be null", __FUNCTION__, buffer);
+        return BAD_VALUE;
+    }
+    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
+    auto it = mRequestedBufferMap.find(bufferId);
+    if (it == mRequestedBufferMap.end()) {
+        ALOGE("%s: bufId %" PRIu64 " is not inflight!",
+                __FUNCTION__, bufferId);
+        return BAD_VALUE;
+    }
+    *buffer = it->second.second;
+    if (streamId != nullptr) {
+        *streamId = it->second.first;
+    }
+    mRequestedBufferMap.erase(it);
+    return OK;
+}
+
+void BufferRecords::getInflightRequestBufferKeys(
+        std::vector<uint64_t>* out) {
+    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
+    out->clear();
+    out->reserve(mRequestedBufferMap.size());
+    for (auto& pair : mRequestedBufferMap) {
+        out->push_back(pair.first);
+    }
+    return;
+}
+
+
+} // camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/BufferUtils.h b/services/camera/libcameraservice/device3/BufferUtils.h
new file mode 100644
index 0000000..452a908
--- /dev/null
+++ b/services/camera/libcameraservice/device3/BufferUtils.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
+#define ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
+
+#include <unordered_map>
+#include <mutex>
+#include <set>
+
+#include <cutils/native_handle.h>
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+
+// TODO: remove legacy camera3.h references
+#include "hardware/camera3.h"
+
+#include <device3/Camera3OutputInterface.h>
+
+namespace android {
+
+namespace camera3 {
+
+    struct BufferHasher {
+        size_t operator()(const buffer_handle_t& buf) const {
+            if (buf == nullptr)
+                return 0;
+
+            size_t result = 1;
+            result = 31 * result + buf->numFds;
+            for (int i = 0; i < buf->numFds; i++) {
+                result = 31 * result + buf->data[i];
+            }
+            return result;
+        }
+    };
+
+    struct BufferComparator {
+        bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+            if (buf1->numFds == buf2->numFds) {
+                for (int i = 0; i < buf1->numFds; i++) {
+                    if (buf1->data[i] != buf2->data[i]) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+
+    // Per stream buffer native handle -> bufId map
+    typedef std::unordered_map<const buffer_handle_t, uint64_t,
+            BufferHasher, BufferComparator> BufferIdMap;
+
+    // streamId -> BufferIdMap
+    typedef std::unordered_map<int, BufferIdMap> BufferIdMaps;
+
+    // Map of inflight buffers sent along in capture requests.
+    // Key is composed by (frameNumber << 32 | streamId)
+    typedef std::unordered_map<uint64_t, buffer_handle_t*> InflightBufferMap;
+
+    // Map of inflight buffers dealt by requestStreamBuffers API
+    typedef std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> RequestedBufferMap;
+
+    // A struct containing all buffer tracking information like inflight buffers
+    // and buffer ID caches
+    class BufferRecords : public BufferRecordsInterface {
+
+    public:
+        BufferRecords() {}
+
+        BufferRecords(BufferRecords&& other) :
+                mBufferIdMaps(other.mBufferIdMaps),
+                mNextBufferId(other.mNextBufferId),
+                mInflightBufferMap(other.mInflightBufferMap),
+                mRequestedBufferMap(other.mRequestedBufferMap) {}
+
+        virtual ~BufferRecords() {}
+
+        // Helper methods to help moving buffer records
+        void takeInflightBufferMap(BufferRecords& other);
+        void takeRequestedBufferMap(BufferRecords& other);
+        void takeBufferCaches(BufferRecords& other, const std::vector<int32_t>& streams);
+
+        // method to extract buffer's unique ID
+        // return pair of (newlySeenBuffer?, bufferId)
+        virtual std::pair<bool, uint64_t> getBufferId(
+                const buffer_handle_t& buf, int streamId) override;
+
+        void tryCreateBufferCache(int streamId);
+
+        void removeInactiveBufferCaches(const std::set<int32_t>& activeStreams);
+
+        // Return the removed buffer ID if input cache is found.
+        // Otherwise return BUFFER_ID_NO_BUFFER
+        uint64_t removeOneBufferCache(int streamId, const native_handle_t* handle);
+
+        // Clear all caches for input stream, but do not remove the stream
+        // Removed buffers' ID are returned
+        std::vector<uint64_t> clearBufferCaches(int streamId);
+
+        bool isStreamCached(int streamId);
+
+        // Return true if the input caches match what we have; otherwise false
+        bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
+
+        // Get a vector of (frameNumber, streamId) pair of currently inflight
+        // buffers
+        void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
+
+        status_t pushInflightBuffer(int32_t frameNumber, int32_t streamId,
+                buffer_handle_t *buffer);
+
+        // Find a buffer_handle_t based on frame number and stream ID
+        virtual status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
+                /*out*/ buffer_handle_t **buffer) override;
+
+        // Pop inflight buffers based on pairs of (frameNumber,streamId)
+        void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
+
+        // Get a vector of bufferId of currently inflight buffers
+        void getInflightRequestBufferKeys(std::vector<uint64_t>* out);
+
+        // Register a bufId (streamId, buffer_handle_t) to inflight request buffer
+        virtual status_t pushInflightRequestBuffer(
+                uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) override;
+
+        // Find a buffer_handle_t based on bufferId
+        virtual status_t popInflightRequestBuffer(uint64_t bufferId,
+                /*out*/ buffer_handle_t** buffer,
+                /*optional out*/ int32_t* streamId = nullptr) override;
+
+    private:
+        std::mutex mBufferIdMapLock;
+        BufferIdMaps mBufferIdMaps;
+        uint64_t mNextBufferId = 1; // 0 means no buffer
+
+        std::mutex mInflightLock;
+        InflightBufferMap mInflightBufferMap;
+
+        std::mutex mRequestedBuffersLock;
+        RequestedBufferMap mRequestedBufferMap;
+    }; // class BufferRecords
+
+    static const uint64_t BUFFER_ID_NO_BUFFER = 0;
+
+    camera3_buffer_status_t mapHidlBufferStatus(
+            hardware::camera::device::V3_2::BufferStatus status);
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 93e18cf..4a509aa 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -60,7 +60,9 @@
 #include "device3/Camera3SharedOutputStream.h"
 #include "CameraService.h"
 #include "utils/CameraThreadState.h"
+#include "utils/TraceHFR.h"
 
+#include <algorithm>
 #include <tuple>
 
 using namespace android::camera3;
@@ -132,6 +134,7 @@
         session->close();
         return res;
     }
+    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
 
     std::vector<std::string> physicalCameraIds;
     bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
@@ -146,8 +149,11 @@
                 return res;
             }
 
-            if (DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId])) {
-                mDistortionMappers[physicalId].setupStaticInfo(mPhysicalDeviceInfoMap[physicalId]);
+            bool usePrecorrectArray =
+                    DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
+            if (usePrecorrectArray) {
+                res = mDistortionMappers[physicalId].setupStaticInfo(
+                        mPhysicalDeviceInfoMap[physicalId]);
                 if (res != OK) {
                     SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
                             "correction", physicalId.c_str());
@@ -155,6 +161,10 @@
                     return res;
                 }
             }
+
+            mZoomRatioMappers[physicalId] = ZoomRatioMapper(
+                    &mPhysicalDeviceInfoMap[physicalId],
+                    mSupportNativeZoomRatio, usePrecorrectArray);
         }
     }
 
@@ -206,7 +216,15 @@
             ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
     }
 
-    mInterface = new HalInterface(session, queue, mUseHalBufManager);
+    camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    for (size_t i = 0; i < capabilities.count; i++) {
+        uint8_t capability = capabilities.data.u8[i];
+        if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
+            mSupportOfflineProcessing = true;
+        }
+    }
+
+    mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
     std::string providerType;
     mVendorTagId = manager->getProviderTagIdLocked(mId.string());
     mTagMonitor.initialize(mVendorTagId);
@@ -227,9 +245,8 @@
             maxVersion.get_major(), maxVersion.get_minor());
 
     bool isMonochrome = false;
-    camera_metadata_entry_t entry = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
-    for (size_t i = 0; i < entry.count; i++) {
-        uint8_t capability = entry.data.u8[i];
+    for (size_t i = 0; i < capabilities.count; i++) {
+        uint8_t capability = capabilities.data.u8[i];
         if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
             isMonochrome = true;
         }
@@ -323,13 +340,22 @@
         }
     }
 
-    if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
+    bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
+    if (usePrecorrectArray) {
         res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
         if (res != OK) {
             SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
             return res;
         }
     }
+
+    mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
+            mSupportNativeZoomRatio, usePrecorrectArray);
+
+    if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
+        mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
+    }
+
     return OK;
 }
 
@@ -339,100 +365,103 @@
 
 status_t Camera3Device::disconnectImpl() {
     ATRACE_CALL();
-    Mutex::Autolock il(mInterfaceLock);
-
     ALOGI("%s: E", __FUNCTION__);
 
     status_t res = OK;
     std::vector<wp<Camera3StreamInterface>> streams;
-    nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     {
-        Mutex::Autolock l(mLock);
-        if (mStatus == STATUS_UNINITIALIZED) return res;
+        Mutex::Autolock il(mInterfaceLock);
+        nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+        {
+            Mutex::Autolock l(mLock);
+            if (mStatus == STATUS_UNINITIALIZED) return res;
 
-        if (mStatus == STATUS_ACTIVE ||
-                (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
-            res = mRequestThread->clearRepeatingRequests();
-            if (res != OK) {
-                SET_ERR_L("Can't stop streaming");
-                // Continue to close device even in case of error
-            } else {
-                res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+            if (mStatus == STATUS_ACTIVE ||
+                    (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
+                res = mRequestThread->clearRepeatingRequests();
                 if (res != OK) {
-                    SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
-                            maxExpectedDuration);
+                    SET_ERR_L("Can't stop streaming");
                     // Continue to close device even in case of error
+                } else {
+                    res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+                    if (res != OK) {
+                        SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+                                maxExpectedDuration);
+                        // Continue to close device even in case of error
+                    }
                 }
             }
-        }
 
-        if (mStatus == STATUS_ERROR) {
-            CLOGE("Shutting down in an error state");
-        }
+            if (mStatus == STATUS_ERROR) {
+                CLOGE("Shutting down in an error state");
+            }
 
-        if (mStatusTracker != NULL) {
-            mStatusTracker->requestExit();
-        }
+            if (mStatusTracker != NULL) {
+                mStatusTracker->requestExit();
+            }
 
-        if (mRequestThread != NULL) {
-            mRequestThread->requestExit();
-        }
+            if (mRequestThread != NULL) {
+                mRequestThread->requestExit();
+            }
 
-        streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
-        for (size_t i = 0; i < mOutputStreams.size(); i++) {
-            streams.push_back(mOutputStreams[i]);
-        }
-        if (mInputStream != nullptr) {
-            streams.push_back(mInputStream);
+            streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+            for (size_t i = 0; i < mOutputStreams.size(); i++) {
+                streams.push_back(mOutputStreams[i]);
+            }
+            if (mInputStream != nullptr) {
+                streams.push_back(mInputStream);
+            }
         }
     }
-
-    // Joining done without holding mLock, otherwise deadlocks may ensue
-    // as the threads try to access parent state
+    // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
+    // as the threads try to access parent state (b/143513518)
     if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
         // HAL may be in a bad state, so waiting for request thread
         // (which may be stuck in the HAL processCaptureRequest call)
         // could be dangerous.
+        // give up mInterfaceLock here and then lock it again. Could this lead
+        // to other deadlocks
         mRequestThread->join();
     }
-
-    if (mStatusTracker != NULL) {
-        mStatusTracker->join();
-    }
-
-    HalInterface* interface;
     {
-        Mutex::Autolock l(mLock);
-        mRequestThread.clear();
-        Mutex::Autolock stLock(mTrackerLock);
-        mStatusTracker.clear();
-        interface = mInterface.get();
-    }
+        Mutex::Autolock il(mInterfaceLock);
+        if (mStatusTracker != NULL) {
+            mStatusTracker->join();
+        }
 
-    // Call close without internal mutex held, as the HAL close may need to
-    // wait on assorted callbacks,etc, to complete before it can return.
-    interface->close();
+        HalInterface* interface;
+        {
+            Mutex::Autolock l(mLock);
+            mRequestThread.clear();
+            Mutex::Autolock stLock(mTrackerLock);
+            mStatusTracker.clear();
+            interface = mInterface.get();
+        }
 
-    flushInflightRequests();
+        // Call close without internal mutex held, as the HAL close may need to
+        // wait on assorted callbacks,etc, to complete before it can return.
+        interface->close();
 
-    {
-        Mutex::Autolock l(mLock);
-        mInterface->clear();
-        mOutputStreams.clear();
-        mInputStream.clear();
-        mDeletedStreams.clear();
-        mBufferManager.clear();
-        internalUpdateStatusLocked(STATUS_UNINITIALIZED);
-    }
+        flushInflightRequests();
 
-    for (auto& weakStream : streams) {
-        sp<Camera3StreamInterface> stream = weakStream.promote();
-        if (stream != nullptr) {
-            ALOGE("%s: Stream %d leaked! strong reference (%d)!",
-                    __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+        {
+            Mutex::Autolock l(mLock);
+            mInterface->clear();
+            mOutputStreams.clear();
+            mInputStream.clear();
+            mDeletedStreams.clear();
+            mBufferManager.clear();
+            internalUpdateStatusLocked(STATUS_UNINITIALIZED);
+        }
+
+        for (auto& weakStream : streams) {
+              sp<Camera3StreamInterface> stream = weakStream.promote();
+            if (stream != nullptr) {
+                ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+                        __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+            }
         }
     }
-
     ALOGI("%s: X", __FUNCTION__);
     return res;
 }
@@ -553,14 +582,6 @@
     return OK;
 }
 
-camera3_buffer_status_t Camera3Device::mapHidlBufferStatus(BufferStatus status) {
-    switch (status) {
-        case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
-        case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
-    }
-    return CAMERA3_BUFFER_STATUS_ERROR;
-}
-
 int Camera3Device::mapToFrameworkFormat(
         hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
     return static_cast<uint32_t>(pixelFormat);
@@ -797,7 +818,7 @@
     return OK;
 }
 
-const CameraMetadata& Camera3Device::info(const String8& physicalId) const {
+const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
     ALOGVV("%s: E", __FUNCTION__);
     if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
                     mStatus == STATUS_ERROR)) {
@@ -820,7 +841,7 @@
 
 const CameraMetadata& Camera3Device::info() const {
     String8 emptyId;
-    return info(emptyId);
+    return infoPhysical(emptyId);
 }
 
 status_t Camera3Device::checkStatusOkToCaptureLocked() {
@@ -868,17 +889,12 @@
 
         // Setup burst Id and request Id
         newRequest->mResultExtras.burstId = burstId++;
-        if (metadataIt->begin()->metadata.exists(ANDROID_REQUEST_ID)) {
-            if (metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID).count == 0) {
-                CLOGE("RequestID entry exists; but must not be empty in metadata");
-                return BAD_VALUE;
-            }
-            newRequest->mResultExtras.requestId = metadataIt->begin()->metadata.find(
-                    ANDROID_REQUEST_ID).data.i32[0];
-        } else {
+        auto requestIdEntry = metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID);
+        if (requestIdEntry.count == 0) {
             CLOGE("RequestID does not exist in metadata");
             return BAD_VALUE;
         }
+        newRequest->mResultExtras.requestId = requestIdEntry.data.i32[0];
 
         requestList->push_back(newRequest);
 
@@ -980,230 +996,18 @@
 hardware::Return<void> Camera3Device::requestStreamBuffers(
         const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
         requestStreamBuffers_cb _hidl_cb) {
-    using hardware::camera::device::V3_5::BufferRequestStatus;
-    using hardware::camera::device::V3_5::StreamBufferRet;
-    using hardware::camera::device::V3_5::StreamBufferRequestError;
-
-    std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
-
-    hardware::hidl_vec<StreamBufferRet> bufRets;
-    if (!mUseHalBufManager) {
-        ALOGE("%s: Camera %s does not support HAL buffer management",
-                __FUNCTION__, mId.string());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return hardware::Void();
-    }
-
-    SortedVector<int32_t> streamIds;
-    ssize_t sz = streamIds.setCapacity(bufReqs.size());
-    if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
-        ALOGE("%s: failed to allocate memory for %zu buffer requests",
-                __FUNCTION__, bufReqs.size());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return hardware::Void();
-    }
-
-    if (bufReqs.size() > mOutputStreams.size()) {
-        ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
-                __FUNCTION__, bufReqs.size(), mOutputStreams.size());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return hardware::Void();
-    }
-
-    // Check for repeated streamId
-    for (const auto& bufReq : bufReqs) {
-        if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
-            ALOGE("%s: Stream %d appear multiple times in buffer requests",
-                    __FUNCTION__, bufReq.streamId);
-            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-            return hardware::Void();
-        }
-        streamIds.add(bufReq.streamId);
-    }
-
-    if (!mRequestBufferSM.startRequestBuffer()) {
-        ALOGE("%s: request buffer disallowed while camera service is configuring",
-                __FUNCTION__);
-        _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
-        return hardware::Void();
-    }
-
-    bufRets.resize(bufReqs.size());
-
-    bool allReqsSucceeds = true;
-    bool oneReqSucceeds = false;
-    for (size_t i = 0; i < bufReqs.size(); i++) {
-        const auto& bufReq = bufReqs[i];
-        auto& bufRet = bufRets[i];
-        int32_t streamId = bufReq.streamId;
-        sp<Camera3OutputStreamInterface> outputStream = mOutputStreams.get(streamId);
-        if (outputStream == nullptr) {
-            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
-            hardware::hidl_vec<StreamBufferRet> emptyBufRets;
-            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
-            mRequestBufferSM.endRequestBuffer();
-            return hardware::Void();
-        }
-
-        if (outputStream->isAbandoned()) {
-            bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
-            allReqsSucceeds = false;
-            continue;
-        }
-
-        bufRet.streamId = streamId;
-        size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
-        uint32_t numBuffersRequested = bufReq.numBuffersRequested;
-        size_t totalHandout = handOutBufferCount + numBuffersRequested;
-        uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
-        if (totalHandout > maxBuffers) {
-            // Not able to allocate enough buffer. Exit early for this stream
-            ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
-                    " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
-                    numBuffersRequested, maxBuffers);
-            bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
-            allReqsSucceeds = false;
-            continue;
-        }
-
-        hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
-        bool currentReqSucceeds = true;
-        std::vector<camera3_stream_buffer_t> streamBuffers(numBuffersRequested);
-        size_t numAllocatedBuffers = 0;
-        size_t numPushedInflightBuffers = 0;
-        for (size_t b = 0; b < numBuffersRequested; b++) {
-            camera3_stream_buffer_t& sb = streamBuffers[b];
-            // Since this method can run concurrently with request thread
-            // We need to update the wait duration everytime we call getbuffer
-            nsecs_t waitDuration = kBaseGetBufferWait + getExpectedInFlightDuration();
-            status_t res = outputStream->getBuffer(&sb, waitDuration);
-            if (res != OK) {
-                if (res == NO_INIT || res == DEAD_OBJECT) {
-                    ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                    bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
-                } else {
-                    ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                    if (res == TIMED_OUT || res == NO_MEMORY) {
-                        bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
-                    } else {
-                        bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
-                    }
-                }
-                currentReqSucceeds = false;
-                break;
-            }
-            numAllocatedBuffers++;
-
-            buffer_handle_t *buffer = sb.buffer;
-            auto pair = mInterface->getBufferId(*buffer, streamId);
-            bool isNewBuffer = pair.first;
-            uint64_t bufferId = pair.second;
-            StreamBuffer& hBuf = tmpRetBuffers[b];
-
-            hBuf.streamId = streamId;
-            hBuf.bufferId = bufferId;
-            hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
-            hBuf.status = BufferStatus::OK;
-            hBuf.releaseFence = nullptr;
-
-            native_handle_t *acquireFence = nullptr;
-            if (sb.acquire_fence != -1) {
-                acquireFence = native_handle_create(1,0);
-                acquireFence->data[0] = sb.acquire_fence;
-            }
-            hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
-            hBuf.releaseFence = nullptr;
-
-            res = mInterface->pushInflightRequestBuffer(bufferId, buffer, streamId);
-            if (res != OK) {
-                ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
-                        __FUNCTION__, streamId, strerror(-res), res);
-                bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
-                currentReqSucceeds = false;
-                break;
-            }
-            numPushedInflightBuffers++;
-        }
-        if (currentReqSucceeds) {
-            bufRet.val.buffers(std::move(tmpRetBuffers));
-            oneReqSucceeds = true;
-        } else {
-            allReqsSucceeds = false;
-            for (size_t b = 0; b < numPushedInflightBuffers; b++) {
-                StreamBuffer& hBuf = tmpRetBuffers[b];
-                buffer_handle_t* buffer;
-                status_t res = mInterface->popInflightRequestBuffer(hBuf.bufferId, &buffer);
-                if (res != OK) {
-                    SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                }
-            }
-            for (size_t b = 0; b < numAllocatedBuffers; b++) {
-                camera3_stream_buffer_t& sb = streamBuffers[b];
-                sb.acquire_fence = -1;
-                sb.status = CAMERA3_BUFFER_STATUS_ERROR;
-            }
-            returnOutputBuffers(streamBuffers.data(), numAllocatedBuffers, 0);
-        }
-    }
-
-    _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
-            oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
-                             BufferRequestStatus::FAILED_UNKNOWN,
-            bufRets);
-    mRequestBufferSM.endRequestBuffer();
+    RequestBufferStates states {
+        mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
+        *this, *mInterface, *this};
+    camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
     return hardware::Void();
 }
 
 hardware::Return<void> Camera3Device::returnStreamBuffers(
         const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
-    if (!mUseHalBufManager) {
-        ALOGE("%s: Camera %s does not support HAL buffer managerment",
-                __FUNCTION__, mId.string());
-        return hardware::Void();
-    }
-
-    for (const auto& buf : buffers) {
-        if (buf.bufferId == HalInterface::BUFFER_ID_NO_BUFFER) {
-            ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
-            continue;
-        }
-
-        buffer_handle_t* buffer;
-        status_t res = mInterface->popInflightRequestBuffer(buf.bufferId, &buffer);
-
-        if (res != OK) {
-            ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
-                    __FUNCTION__, buf.bufferId, buf.streamId);
-            continue;
-        }
-
-        camera3_stream_buffer_t streamBuffer;
-        streamBuffer.buffer = buffer;
-        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
-        streamBuffer.acquire_fence = -1;
-        streamBuffer.release_fence = -1;
-
-        if (buf.releaseFence == nullptr) {
-            streamBuffer.release_fence = -1;
-        } else if (buf.releaseFence->numFds == 1) {
-            streamBuffer.release_fence = dup(buf.releaseFence->data[0]);
-        } else {
-            ALOGE("%s: Invalid release fence, fd count is %d, not 1",
-                    __FUNCTION__, buf.releaseFence->numFds);
-            continue;
-        }
-
-        sp<Camera3StreamInterface> stream = mOutputStreams.get(buf.streamId);
-        if (stream == nullptr) {
-            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
-            continue;
-        }
-        streamBuffer.stream = stream->asHalStream();
-        returnOutputBuffers(&streamBuffer, /*size*/1, /*timestamp*/ 0);
-    }
+    ReturnBufferStates states {
+        mId, mUseHalBufManager, mOutputStreams, *mInterface};
+    camera3::returnStreamBuffers(states, buffers);
     return hardware::Void();
 }
 
@@ -1220,6 +1024,12 @@
         ALOGW("%s: received capture result in error state.", __FUNCTION__);
     }
 
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> l(mOutputLock);
+        listener = mListener.promote();
+    }
+
     if (mProcessCaptureResultLock.tryLock() != OK) {
         // This should never happen; it indicates a wrong client implementation
         // that doesn't follow the contract. But, we can be tolerant here.
@@ -1232,8 +1042,23 @@
             return hardware::Void();
         }
     }
+    CaptureOutputStates states {
+        mId,
+        mInFlightLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
+    };
+
     for (const auto& result : results) {
-        processOneCaptureResultLocked(result.v3_2, result.physicalCameraMetadata);
+        processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
     }
     mProcessCaptureResultLock.unlock();
     return hardware::Void();
@@ -1256,6 +1081,12 @@
         ALOGW("%s: received capture result in error state.", __FUNCTION__);
     }
 
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> l(mOutputLock);
+        listener = mListener.promote();
+    }
+
     if (mProcessCaptureResultLock.tryLock() != OK) {
         // This should never happen; it indicates a wrong client implementation
         // that doesn't follow the contract. But, we can be tolerant here.
@@ -1268,186 +1099,29 @@
             return hardware::Void();
         }
     }
+
+    CaptureOutputStates states {
+        mId,
+        mInFlightLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
+    };
+
     for (const auto& result : results) {
-        processOneCaptureResultLocked(result, noPhysMetadata);
+        processOneCaptureResultLocked(states, result, noPhysMetadata);
     }
     mProcessCaptureResultLock.unlock();
     return hardware::Void();
 }
 
-status_t Camera3Device::readOneCameraMetadataLocked(
-        uint64_t fmqResultSize, hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
-        const hardware::camera::device::V3_2::CameraMetadata& result) {
-    if (fmqResultSize > 0) {
-        resultMetadata.resize(fmqResultSize);
-        if (mResultMetadataQueue == nullptr) {
-            return NO_MEMORY; // logged in initialize()
-        }
-        if (!mResultMetadataQueue->read(resultMetadata.data(), fmqResultSize)) {
-            ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
-                    __FUNCTION__, fmqResultSize);
-            return INVALID_OPERATION;
-        }
-    } else {
-        resultMetadata.setToExternal(const_cast<uint8_t *>(result.data()),
-                result.size());
-    }
-
-    if (resultMetadata.size() != 0) {
-        status_t res;
-        const camera_metadata_t* metadata =
-                reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
-        size_t expected_metadata_size = resultMetadata.size();
-        if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
-            ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return INVALID_OPERATION;
-        }
-    }
-
-    return OK;
-}
-
-void Camera3Device::processOneCaptureResultLocked(
-        const hardware::camera::device::V3_2::CaptureResult& result,
-        const hardware::hidl_vec<
-                hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata) {
-    camera3_capture_result r;
-    status_t res;
-    r.frame_number = result.frameNumber;
-
-    // Read and validate the result metadata.
-    hardware::camera::device::V3_2::CameraMetadata resultMetadata;
-    res = readOneCameraMetadataLocked(result.fmqResultSize, resultMetadata, result.result);
-    if (res != OK) {
-        ALOGE("%s: Frame %d: Failed to read capture result metadata",
-                __FUNCTION__, result.frameNumber);
-        return;
-    }
-    r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
-
-    // Read and validate physical camera metadata
-    size_t physResultCount = physicalCameraMetadata.size();
-    std::vector<const char*> physCamIds(physResultCount);
-    std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
-    std::vector<hardware::camera::device::V3_2::CameraMetadata> physResultMetadata;
-    physResultMetadata.resize(physResultCount);
-    for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
-        res = readOneCameraMetadataLocked(physicalCameraMetadata[i].fmqMetadataSize,
-                physResultMetadata[i], physicalCameraMetadata[i].metadata);
-        if (res != OK) {
-            ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
-                    __FUNCTION__, result.frameNumber,
-                    physicalCameraMetadata[i].physicalCameraId.c_str());
-            return;
-        }
-        physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
-        phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
-                physResultMetadata[i].data());
-    }
-    r.num_physcam_metadata = physResultCount;
-    r.physcam_ids = physCamIds.data();
-    r.physcam_metadata = phyCamMetadatas.data();
-
-    std::vector<camera3_stream_buffer_t> outputBuffers(result.outputBuffers.size());
-    std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
-    for (size_t i = 0; i < result.outputBuffers.size(); i++) {
-        auto& bDst = outputBuffers[i];
-        const StreamBuffer &bSrc = result.outputBuffers[i];
-
-        sp<Camera3StreamInterface> stream = mOutputStreams.get(bSrc.streamId);
-        if (stream == nullptr) {
-            ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
-                    __FUNCTION__, result.frameNumber, i, bSrc.streamId);
-            return;
-        }
-        bDst.stream = stream->asHalStream();
-
-        bool noBufferReturned = false;
-        buffer_handle_t *buffer = nullptr;
-        if (mUseHalBufManager) {
-            // This is suspicious most of the time but can be correct during flush where HAL
-            // has to return capture result before a buffer is requested
-            if (bSrc.bufferId == HalInterface::BUFFER_ID_NO_BUFFER) {
-                if (bSrc.status == BufferStatus::OK) {
-                    ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
-                            __FUNCTION__, result.frameNumber, i, bSrc.streamId);
-                    // Still proceeds so other buffers can be returned
-                }
-                noBufferReturned = true;
-            }
-            if (noBufferReturned) {
-                res = OK;
-            } else {
-                res = mInterface->popInflightRequestBuffer(bSrc.bufferId, &buffer);
-            }
-        } else {
-            res = mInterface->popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
-        }
-
-        if (res != OK) {
-            ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
-                    __FUNCTION__, result.frameNumber, i, bSrc.streamId);
-            return;
-        }
-
-        bDst.buffer = buffer;
-        bDst.status = mapHidlBufferStatus(bSrc.status);
-        bDst.acquire_fence = -1;
-        if (bSrc.releaseFence == nullptr) {
-            bDst.release_fence = -1;
-        } else if (bSrc.releaseFence->numFds == 1) {
-            if (noBufferReturned) {
-                ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
-            }
-            bDst.release_fence = dup(bSrc.releaseFence->data[0]);
-        } else {
-            ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
-                    __FUNCTION__, result.frameNumber, i, bSrc.releaseFence->numFds);
-            return;
-        }
-    }
-    r.num_output_buffers = outputBuffers.size();
-    r.output_buffers = outputBuffers.data();
-
-    camera3_stream_buffer_t inputBuffer;
-    if (result.inputBuffer.streamId == -1) {
-        r.input_buffer = nullptr;
-    } else {
-        if (mInputStream->getId() != result.inputBuffer.streamId) {
-            ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
-                    result.frameNumber, result.inputBuffer.streamId);
-            return;
-        }
-        inputBuffer.stream = mInputStream->asHalStream();
-        buffer_handle_t *buffer;
-        res = mInterface->popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
-                &buffer);
-        if (res != OK) {
-            ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
-                    __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
-            return;
-        }
-        inputBuffer.buffer = buffer;
-        inputBuffer.status = mapHidlBufferStatus(result.inputBuffer.status);
-        inputBuffer.acquire_fence = -1;
-        if (result.inputBuffer.releaseFence == nullptr) {
-            inputBuffer.release_fence = -1;
-        } else if (result.inputBuffer.releaseFence->numFds == 1) {
-            inputBuffer.release_fence = dup(result.inputBuffer.releaseFence->data[0]);
-        } else {
-            ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
-                    __FUNCTION__, result.frameNumber, result.inputBuffer.releaseFence->numFds);
-            return;
-        }
-        r.input_buffer = &inputBuffer;
-    }
-
-    r.partial_result = result.partialResult;
-
-    processCaptureResult(&r);
-}
-
 hardware::Return<void> Camera3Device::notify(
         const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
     // Ideally we should grab mLock, but that can lead to deadlock, and
@@ -1460,55 +1134,32 @@
         ALOGW("%s: received notify message in error state.", __FUNCTION__);
     }
 
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> l(mOutputLock);
+        listener = mListener.promote();
+    }
+
+    CaptureOutputStates states {
+        mId,
+        mInFlightLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, *mInterface
+    };
     for (const auto& msg : msgs) {
-        notify(msg);
+        camera3::notify(states, msg);
     }
     return hardware::Void();
 }
 
-void Camera3Device::notify(
-        const hardware::camera::device::V3_2::NotifyMsg& msg) {
-
-    camera3_notify_msg m;
-    switch (msg.type) {
-        case MsgType::ERROR:
-            m.type = CAMERA3_MSG_ERROR;
-            m.message.error.frame_number = msg.msg.error.frameNumber;
-            if (msg.msg.error.errorStreamId >= 0) {
-                sp<Camera3StreamInterface> stream = mOutputStreams.get(msg.msg.error.errorStreamId);
-                if (stream == nullptr) {
-                    ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
-                            m.message.error.frame_number, msg.msg.error.errorStreamId);
-                    return;
-                }
-                m.message.error.error_stream = stream->asHalStream();
-            } else {
-                m.message.error.error_stream = nullptr;
-            }
-            switch (msg.msg.error.errorCode) {
-                case ErrorCode::ERROR_DEVICE:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
-                    break;
-                case ErrorCode::ERROR_REQUEST:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
-                    break;
-                case ErrorCode::ERROR_RESULT:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
-                    break;
-                case ErrorCode::ERROR_BUFFER:
-                    m.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
-                    break;
-            }
-            break;
-        case MsgType::SHUTTER:
-            m.type = CAMERA3_MSG_SHUTTER;
-            m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
-            m.message.shutter.timestamp = msg.msg.shutter.timestamp;
-            break;
-    }
-    notify(&m);
-}
-
 status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
                                     const std::list<const SurfaceMap> &surfaceMaps,
                                     int64_t *lastFrameNumber) {
@@ -1662,56 +1313,6 @@
     return OK;
 }
 
-status_t Camera3Device::StreamSet::add(
-        int streamId, sp<camera3::Camera3OutputStreamInterface> stream) {
-    if (stream == nullptr) {
-        ALOGE("%s: cannot add null stream", __FUNCTION__);
-        return BAD_VALUE;
-    }
-    std::lock_guard<std::mutex> lock(mLock);
-    return mData.add(streamId, stream);
-}
-
-ssize_t Camera3Device::StreamSet::remove(int streamId) {
-    std::lock_guard<std::mutex> lock(mLock);
-    return mData.removeItem(streamId);
-}
-
-sp<camera3::Camera3OutputStreamInterface>
-Camera3Device::StreamSet::get(int streamId) {
-    std::lock_guard<std::mutex> lock(mLock);
-    ssize_t idx = mData.indexOfKey(streamId);
-    if (idx == NAME_NOT_FOUND) {
-        return nullptr;
-    }
-    return mData.editValueAt(idx);
-}
-
-sp<camera3::Camera3OutputStreamInterface>
-Camera3Device::StreamSet::operator[] (size_t index) {
-    std::lock_guard<std::mutex> lock(mLock);
-    return mData.editValueAt(index);
-}
-
-size_t Camera3Device::StreamSet::size() const {
-    std::lock_guard<std::mutex> lock(mLock);
-    return mData.size();
-}
-
-void Camera3Device::StreamSet::clear() {
-    std::lock_guard<std::mutex> lock(mLock);
-    return mData.clear();
-}
-
-std::vector<int> Camera3Device::StreamSet::getStreamIds() {
-    std::lock_guard<std::mutex> lock(mLock);
-    std::vector<int> streamIds(mData.size());
-    for (size_t i = 0; i < mData.size(); i++) {
-        streamIds[i] = mData.keyAt(i);
-    }
-    return streamIds;
-}
-
 status_t Camera3Device::createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
@@ -2116,6 +1717,22 @@
         set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
         mRequestTemplateCache[templateId].acquire(rawRequest);
 
+        // Override the template request with zoomRatioMapper
+        res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
+                &mRequestTemplateCache[templateId]);
+        if (res != OK) {
+            CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
+                    templateId, strerror(-res), res);
+            return res;
+        }
+
+        // Fill in JPEG_QUALITY if not available
+        if (!mRequestTemplateCache[templateId].exists(ANDROID_JPEG_QUALITY)) {
+            static const uint8_t kDefaultJpegQuality = 95;
+            mRequestTemplateCache[templateId].update(ANDROID_JPEG_QUALITY,
+                    &kDefaultJpegQuality, 1);
+        }
+
         *request = mRequestTemplateCache[templateId];
         mLastTemplateId = templateId;
     }
@@ -2164,13 +1781,6 @@
     mStatusChanged.broadcast();
 }
 
-void Camera3Device::pauseStateNotify(bool enable) {
-    Mutex::Autolock il(mInterfaceLock);
-    Mutex::Autolock l(mLock);
-
-    mPauseStateNotify = enable;
-}
-
 // Pause to reconfigure
 status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
     if (mRequestThread.get() != nullptr) {
@@ -2264,7 +1874,7 @@
 
 status_t Camera3Device::setNotifyCallback(wp<NotificationListener> listener) {
     ATRACE_CALL();
-    Mutex::Autolock l(mOutputLock);
+    std::lock_guard<std::mutex> l(mOutputLock);
 
     if (listener != NULL && mListener != NULL) {
         ALOGW("%s: Replacing old callback listener", __FUNCTION__);
@@ -2282,17 +1892,12 @@
 
 status_t Camera3Device::waitForNextFrame(nsecs_t timeout) {
     ATRACE_CALL();
-    status_t res;
-    Mutex::Autolock l(mOutputLock);
+    std::unique_lock<std::mutex> l(mOutputLock);
 
     while (mResultQueue.empty()) {
-        res = mResultSignal.waitRelative(mOutputLock, timeout);
-        if (res == TIMED_OUT) {
-            return res;
-        } else if (res != OK) {
-            ALOGW("%s: Camera %s: No frame in %" PRId64 " ns: %s (%d)",
-                    __FUNCTION__, mId.string(), timeout, strerror(-res), res);
-            return res;
+        auto st = mResultSignal.wait_for(l, std::chrono::nanoseconds(timeout));
+        if (st == std::cv_status::timeout) {
+            return TIMED_OUT;
         }
     }
     return OK;
@@ -2300,7 +1905,7 @@
 
 status_t Camera3Device::getNextResult(CaptureResult *frame) {
     ATRACE_CALL();
-    Mutex::Autolock l(mOutputLock);
+    std::lock_guard<std::mutex> l(mOutputLock);
 
     if (mResultQueue.empty()) {
         return NOT_ENOUGH_DATA;
@@ -2496,7 +2101,7 @@
 
     sp<NotificationListener> listener;
     {
-        Mutex::Autolock l(mOutputLock);
+        std::lock_guard<std::mutex> l(mOutputLock);
         listener = mListener.promote();
     }
     if (idle && listener != NULL) {
@@ -2621,7 +2226,7 @@
         const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
     ATRACE_CALL();
 
-    sp<CaptureRequest> newRequest = new CaptureRequest;
+    sp<CaptureRequest> newRequest = new CaptureRequest();
     newRequest->mSettingsList = request;
 
     camera_metadata_entry_t inputStreams =
@@ -2692,18 +2297,16 @@
     newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
     newRequest->mBatchSize = 1;
 
-    return newRequest;
-}
-
-bool Camera3Device::isOpaqueInputSizeSupported(uint32_t width, uint32_t height) {
-    for (uint32_t i = 0; i < mSupportedOpaqueInputSizes.size(); i++) {
-        Size size = mSupportedOpaqueInputSizes[i];
-        if (size.width == width && size.height == height) {
-            return true;
-        }
+    auto rotateAndCropEntry =
+            newRequest->mSettingsList.begin()->metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if (rotateAndCropEntry.count > 0 &&
+            rotateAndCropEntry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
+        newRequest->mRotateAndCropAuto = true;
+    } else {
+        newRequest->mRotateAndCropAuto = false;
     }
 
-    return false;
+    return newRequest;
 }
 
 void Camera3Device::cancelStreamsConfigurationLocked() {
@@ -2738,7 +2341,22 @@
     }
 }
 
-bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
+bool Camera3Device::checkAbandonedStreamsLocked() {
+    if ((mInputStream.get() != nullptr) && (mInputStream->isAbandoned())) {
+        return true;
+    }
+
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        auto stream = mOutputStreams[i];
+        if ((stream.get() != nullptr) && (stream->isAbandoned())) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId) {
     ATRACE_CALL();
     bool ret = false;
 
@@ -2746,7 +2364,22 @@
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
 
     Mutex::Autolock l(mLock);
-    auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
+    if (checkAbandonedStreamsLocked()) {
+        ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
+                __FUNCTION__);
+        return true;
+    }
+
+    status_t rc = NO_ERROR;
+    bool markClientActive = false;
+    if (mStatus == STATUS_ACTIVE) {
+        markClientActive = true;
+        mPauseStateNotify = true;
+        mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
+
+        rc = internalPauseAndWaitLocked(maxExpectedDuration);
+    }
+
     if (rc == NO_ERROR) {
         mNeedConfig = true;
         rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
@@ -2774,6 +2407,10 @@
         ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
     }
 
+    if (markClientActive) {
+        mStatusTracker->markComponentActive(clientStatusId);
+    }
+
     return ret;
 }
 
@@ -2802,6 +2439,27 @@
         mOperatingMode = operatingMode;
     }
 
+    // In case called from configureStreams, abort queued input buffers not belonging to
+    // any pending requests.
+    if (mInputStream != NULL && notifyRequestThread) {
+        while (true) {
+            camera3_stream_buffer_t inputBuffer;
+            status_t res = mInputStream->getInputBuffer(&inputBuffer,
+                    /*respectHalLimit*/ false);
+            if (res != OK) {
+                // Exhausted acquiring all input buffers.
+                break;
+            }
+
+            inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+            res = mInputStream->returnInputBuffer(inputBuffer);
+            if (res != OK) {
+                ALOGE("%s: %d: couldn't return input buffer while clearing input queue: "
+                        "%s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
+            }
+        }
+    }
+
     if (!mNeedConfig) {
         ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
         return OK;
@@ -3117,14 +2775,15 @@
         int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
         bool hasAppCallback, nsecs_t maxExpectedDuration,
         std::set<String8>& physicalCameraIds, bool isStillCapture,
-        bool isZslCapture, const SurfaceMap& outputSurfaces) {
+        bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& cameraIdsWithZoom,
+        const SurfaceMap& outputSurfaces) {
     ATRACE_CALL();
-    Mutex::Autolock l(mInFlightLock);
+    std::lock_guard<std::mutex> l(mInFlightLock);
 
     ssize_t res;
     res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
             hasAppCallback, maxExpectedDuration, physicalCameraIds, isStillCapture, isZslCapture,
-            outputSurfaces));
+            rotateAndCropAuto, cameraIdsWithZoom, outputSurfaces));
     if (res < 0) return res;
 
     if (mInFlightMap.size() == 1) {
@@ -3140,79 +2799,7 @@
     return OK;
 }
 
-void Camera3Device::returnOutputBuffers(
-        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
-        nsecs_t timestamp, bool timestampIncreasing,
-        const SurfaceMap& outputSurfaces,
-        const CaptureResultExtras &inResultExtras) {
-
-    for (size_t i = 0; i < numBuffers; i++)
-    {
-        if (outputBuffers[i].buffer == nullptr) {
-            if (!mUseHalBufManager) {
-                // With HAL buffer management API, HAL sometimes will have to return buffers that
-                // has not got a output buffer handle filled yet. This is though illegal if HAL
-                // buffer management API is not being used.
-                ALOGE("%s: cannot return a null buffer!", __FUNCTION__);
-            }
-            continue;
-        }
-
-        Camera3StreamInterface *stream = Camera3Stream::cast(outputBuffers[i].stream);
-        int streamId = stream->getId();
-        const auto& it = outputSurfaces.find(streamId);
-        status_t res = OK;
-        if (it != outputSurfaces.end()) {
-            res = stream->returnBuffer(
-                    outputBuffers[i], timestamp, timestampIncreasing, it->second,
-                    inResultExtras.frameNumber);
-        } else {
-            res = stream->returnBuffer(
-                    outputBuffers[i], timestamp, timestampIncreasing, std::vector<size_t> (),
-                    inResultExtras.frameNumber);
-        }
-
-        // Note: stream may be deallocated at this point, if this buffer was
-        // the last reference to it.
-        if (res == NO_INIT || res == DEAD_OBJECT) {
-            ALOGV("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
-        } else if (res != OK) {
-            ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
-        }
-
-        // Long processing consumers can cause returnBuffer timeout for shared stream
-        // If that happens, cancel the buffer and send a buffer error to client
-        if (it != outputSurfaces.end() && res == TIMED_OUT &&
-                outputBuffers[i].status == CAMERA3_BUFFER_STATUS_OK) {
-            // cancel the buffer
-            camera3_stream_buffer_t sb = outputBuffers[i];
-            sb.status = CAMERA3_BUFFER_STATUS_ERROR;
-            stream->returnBuffer(sb, /*timestamp*/0, timestampIncreasing, std::vector<size_t> (),
-                    inResultExtras.frameNumber);
-
-            // notify client buffer error
-            sp<NotificationListener> listener;
-            {
-                Mutex::Autolock l(mOutputLock);
-                listener = mListener.promote();
-            }
-
-            if (listener != nullptr) {
-                CaptureResultExtras extras = inResultExtras;
-                extras.errorStreamId = streamId;
-                listener->notifyError(
-                        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
-                        extras);
-            }
-        }
-    }
-}
-
-void Camera3Device::removeInFlightMapEntryLocked(int idx) {
-    ATRACE_CALL();
-    nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
-    mInFlightMap.removeItemsAt(idx, 1);
-
+void Camera3Device::onInflightEntryRemovedLocked(nsecs_t duration) {
     // Indicate idle inFlightMap to the status tracker
     if (mInFlightMap.size() == 0) {
         mRequestBufferSM.onInflightMapEmpty();
@@ -3226,50 +2813,7 @@
     mExpectedInflightDuration -= duration;
 }
 
-void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
-
-    const InFlightRequest &request = mInFlightMap.valueAt(idx);
-    const uint32_t frameNumber = mInFlightMap.keyAt(idx);
-
-    nsecs_t sensorTimestamp = request.sensorTimestamp;
-    nsecs_t shutterTimestamp = request.shutterTimestamp;
-
-    // Check if it's okay to remove the request from InFlightMap:
-    // In the case of a successful request:
-    //      all input and output buffers, all result metadata, shutter callback
-    //      arrived.
-    // In the case of a unsuccessful request:
-    //      all input and output buffers arrived.
-    if (request.numBuffersLeft == 0 &&
-            (request.skipResultMetadata ||
-            (request.haveResultMetadata && shutterTimestamp != 0))) {
-        if (request.stillCapture) {
-            ATRACE_ASYNC_END("still capture", frameNumber);
-        }
-
-        ATRACE_ASYNC_END("frame capture", frameNumber);
-
-        // Sanity check - if sensor timestamp matches shutter timestamp in the
-        // case of request having callback.
-        if (request.hasCallback && request.requestStatus == OK &&
-                sensorTimestamp != shutterTimestamp) {
-            SET_ERR("sensor timestamp (%" PRId64
-                ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
-                sensorTimestamp, frameNumber, shutterTimestamp);
-        }
-
-        // for an unsuccessful request, it may have pending output buffers to
-        // return.
-        assert(request.requestStatus != OK ||
-               request.pendingOutputBuffers.size() == 0);
-        returnOutputBuffers(request.pendingOutputBuffers.array(),
-            request.pendingOutputBuffers.size(), 0, /*timestampIncreasing*/true,
-            request.outputSurfaces, request.resultExtras);
-
-        removeInFlightMapEntryLocked(idx);
-        ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
-     }
-
+void Camera3Device::checkInflightMapLengthLocked() {
     // Sanity check - if we have too many in-flight frames with long total inflight duration,
     // something has likely gone wrong. This might still be legit only if application send in
     // a long burst of long exposure requests.
@@ -3286,714 +2830,32 @@
     }
 }
 
+void Camera3Device::onInflightMapFlushedLocked() {
+    mExpectedInflightDuration = 0;
+}
+
+void Camera3Device::removeInFlightMapEntryLocked(int idx) {
+    ATRACE_HFR_CALL();
+    nsecs_t duration = mInFlightMap.valueAt(idx).maxExpectedDuration;
+    mInFlightMap.removeItemsAt(idx, 1);
+
+    onInflightEntryRemovedLocked(duration);
+}
+
+
 void Camera3Device::flushInflightRequests() {
     ATRACE_CALL();
-    { // First return buffers cached in mInFlightMap
-        Mutex::Autolock l(mInFlightLock);
-        for (size_t idx = 0; idx < mInFlightMap.size(); idx++) {
-            const InFlightRequest &request = mInFlightMap.valueAt(idx);
-            returnOutputBuffers(request.pendingOutputBuffers.array(),
-                request.pendingOutputBuffers.size(), 0,
-                /*timestampIncreasing*/true, request.outputSurfaces,
-                request.resultExtras);
-        }
-        mInFlightMap.clear();
-        mExpectedInflightDuration = 0;
-    }
-
-    // Then return all inflight buffers not returned by HAL
-    std::vector<std::pair<int32_t, int32_t>> inflightKeys;
-    mInterface->getInflightBufferKeys(&inflightKeys);
-
-    // Inflight buffers for HAL buffer manager
-    std::vector<uint64_t> inflightRequestBufferKeys;
-    mInterface->getInflightRequestBufferKeys(&inflightRequestBufferKeys);
-
-    // (streamId, frameNumber, buffer_handle_t*) tuple for all inflight buffers.
-    // frameNumber will be -1 for buffers from HAL buffer manager
-    std::vector<std::tuple<int32_t, int32_t, buffer_handle_t*>> inflightBuffers;
-    inflightBuffers.reserve(inflightKeys.size() + inflightRequestBufferKeys.size());
-
-    for (auto& pair : inflightKeys) {
-        int32_t frameNumber = pair.first;
-        int32_t streamId = pair.second;
-        buffer_handle_t* buffer;
-        status_t res = mInterface->popInflightBuffer(frameNumber, streamId, &buffer);
-        if (res != OK) {
-            ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
-                    __FUNCTION__, frameNumber, streamId);
-            continue;
-        }
-        inflightBuffers.push_back(std::make_tuple(streamId, frameNumber, buffer));
-    }
-
-    for (auto& bufferId : inflightRequestBufferKeys) {
-        int32_t streamId = -1;
-        buffer_handle_t* buffer = nullptr;
-        status_t res = mInterface->popInflightRequestBuffer(bufferId, &buffer, &streamId);
-        if (res != OK) {
-            ALOGE("%s: cannot find in-flight buffer %" PRIu64, __FUNCTION__, bufferId);
-            continue;
-        }
-        inflightBuffers.push_back(std::make_tuple(streamId, /*frameNumber*/-1, buffer));
-    }
-
-    int32_t inputStreamId = (mInputStream != nullptr) ? mInputStream->getId() : -1;
-    for (auto& tuple : inflightBuffers) {
-        status_t res = OK;
-        int32_t streamId = std::get<0>(tuple);
-        int32_t frameNumber = std::get<1>(tuple);
-        buffer_handle_t* buffer = std::get<2>(tuple);
-
-        camera3_stream_buffer_t streamBuffer;
-        streamBuffer.buffer = buffer;
-        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
-        streamBuffer.acquire_fence = -1;
-        streamBuffer.release_fence = -1;
-
-        // First check if the buffer belongs to deleted stream
-        bool streamDeleted = false;
-        for (auto& stream : mDeletedStreams) {
-            if (streamId == stream->getId()) {
-                streamDeleted = true;
-                // Return buffer to deleted stream
-                camera3_stream* halStream = stream->asHalStream();
-                streamBuffer.stream = halStream;
-                switch (halStream->stream_type) {
-                    case CAMERA3_STREAM_OUTPUT:
-                        res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
-                                /*timestampIncreasing*/true, std::vector<size_t> (), frameNumber);
-                        if (res != OK) {
-                            ALOGE("%s: Can't return output buffer for frame %d to"
-                                  " stream %d: %s (%d)",  __FUNCTION__,
-                                  frameNumber, streamId, strerror(-res), res);
-                        }
-                        break;
-                    case CAMERA3_STREAM_INPUT:
-                        res = stream->returnInputBuffer(streamBuffer);
-                        if (res != OK) {
-                            ALOGE("%s: Can't return input buffer for frame %d to"
-                                  " stream %d: %s (%d)",  __FUNCTION__,
-                                  frameNumber, streamId, strerror(-res), res);
-                        }
-                        break;
-                    default: // Bi-direcitonal stream is deprecated
-                        ALOGE("%s: stream %d has unknown stream type %d",
-                                __FUNCTION__, streamId, halStream->stream_type);
-                        break;
-                }
-                break;
-            }
-        }
-        if (streamDeleted) {
-            continue;
-        }
-
-        // Then check against configured streams
-        if (streamId == inputStreamId) {
-            streamBuffer.stream = mInputStream->asHalStream();
-            res = mInputStream->returnInputBuffer(streamBuffer);
-            if (res != OK) {
-                ALOGE("%s: Can't return input buffer for frame %d to"
-                      " stream %d: %s (%d)",  __FUNCTION__,
-                      frameNumber, streamId, strerror(-res), res);
-            }
-        } else {
-            sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
-            if (stream == nullptr) {
-                ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
-                continue;
-            }
-            streamBuffer.stream = stream->asHalStream();
-            returnOutputBuffers(&streamBuffer, /*size*/1, /*timestamp*/ 0);
-        }
-    }
-}
-
-void Camera3Device::insertResultLocked(CaptureResult *result,
-        uint32_t frameNumber) {
-    if (result == nullptr) return;
-
-    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
-            result->mMetadata.getAndLock());
-    set_camera_metadata_vendor_id(meta, mVendorTagId);
-    result->mMetadata.unlock(meta);
-
-    if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
-            (int32_t*)&frameNumber, 1) != OK) {
-        SET_ERR("Failed to set frame number %d in metadata", frameNumber);
-        return;
-    }
-
-    if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
-        SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
-        return;
-    }
-
-    // Update vendor tag id for physical metadata
-    for (auto& physicalMetadata : result->mPhysicalMetadatas) {
-        camera_metadata_t *pmeta = const_cast<camera_metadata_t *>(
-                physicalMetadata.mPhysicalCameraMetadata.getAndLock());
-        set_camera_metadata_vendor_id(pmeta, mVendorTagId);
-        physicalMetadata.mPhysicalCameraMetadata.unlock(pmeta);
-    }
-
-    // Valid result, insert into queue
-    List<CaptureResult>::iterator queuedResult =
-            mResultQueue.insert(mResultQueue.end(), CaptureResult(*result));
-    ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
-           ", burstId = %" PRId32, __FUNCTION__,
-           queuedResult->mResultExtras.requestId,
-           queuedResult->mResultExtras.frameNumber,
-           queuedResult->mResultExtras.burstId);
-
-    mResultSignal.signal();
-}
-
-
-void Camera3Device::sendPartialCaptureResult(const camera_metadata_t * partialResult,
-        const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
-    ATRACE_CALL();
-    Mutex::Autolock l(mOutputLock);
-
-    CaptureResult captureResult;
-    captureResult.mResultExtras = resultExtras;
-    captureResult.mMetadata = partialResult;
-
-    // Fix up result metadata for monochrome camera.
-    status_t res = fixupMonochromeTags(mDeviceInfo, captureResult.mMetadata);
-    if (res != OK) {
-        SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
-        return;
-    }
-
-    insertResultLocked(&captureResult, frameNumber);
-}
-
-
-void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
-        CaptureResultExtras &resultExtras,
-        CameraMetadata &collectedPartialResult,
-        uint32_t frameNumber,
-        bool reprocess, bool zslStillCapture,
-        const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas) {
-    ATRACE_CALL();
-    if (pendingMetadata.isEmpty())
-        return;
-
-    Mutex::Autolock l(mOutputLock);
-
-    // TODO: need to track errors for tighter bounds on expected frame number
-    if (reprocess) {
-        if (frameNumber < mNextReprocessResultFrameNumber) {
-            SET_ERR("Out-of-order reprocess capture result metadata submitted! "
-                "(got frame number %d, expecting %d)",
-                frameNumber, mNextReprocessResultFrameNumber);
-            return;
-        }
-        mNextReprocessResultFrameNumber = frameNumber + 1;
-    } else if (zslStillCapture) {
-        if (frameNumber < mNextZslStillResultFrameNumber) {
-            SET_ERR("Out-of-order ZSL still capture result metadata submitted! "
-                "(got frame number %d, expecting %d)",
-                frameNumber, mNextZslStillResultFrameNumber);
-            return;
-        }
-        mNextZslStillResultFrameNumber = frameNumber + 1;
-    } else {
-        if (frameNumber < mNextResultFrameNumber) {
-            SET_ERR("Out-of-order capture result metadata submitted! "
-                    "(got frame number %d, expecting %d)",
-                    frameNumber, mNextResultFrameNumber);
-            return;
-        }
-        mNextResultFrameNumber = frameNumber + 1;
-    }
-
-    CaptureResult captureResult;
-    captureResult.mResultExtras = resultExtras;
-    captureResult.mMetadata = pendingMetadata;
-    captureResult.mPhysicalMetadatas = physicalMetadatas;
-
-    // Append any previous partials to form a complete result
-    if (mUsePartialResult && !collectedPartialResult.isEmpty()) {
-        captureResult.mMetadata.append(collectedPartialResult);
-    }
-
-    captureResult.mMetadata.sort();
-
-    // Check that there's a timestamp in the result metadata
-    camera_metadata_entry timestamp = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
-    if (timestamp.count == 0) {
-        SET_ERR("No timestamp provided by HAL for frame %d!",
-                frameNumber);
-        return;
-    }
-    nsecs_t sensorTimestamp = timestamp.data.i64[0];
-
-    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
-        camera_metadata_entry timestamp =
-                physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP);
-        if (timestamp.count == 0) {
-            SET_ERR("No timestamp provided by HAL for physical camera %s frame %d!",
-                    String8(physicalMetadata.mPhysicalCameraId).c_str(), frameNumber);
-            return;
-        }
-    }
-
-    // Fix up some result metadata to account for HAL-level distortion correction
-    status_t res =
-            mDistortionMappers[mId.c_str()].correctCaptureResult(&captureResult.mMetadata);
-    if (res != OK) {
-        SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
-                frameNumber, strerror(res), res);
-        return;
-    }
-    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
-        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
-        if (mDistortionMappers.find(cameraId8.c_str()) == mDistortionMappers.end()) {
-            continue;
-        }
-        res = mDistortionMappers[cameraId8.c_str()].correctCaptureResult(
-                &physicalMetadata.mPhysicalCameraMetadata);
-        if (res != OK) {
-            SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
-                    frameNumber, strerror(res), res);
-            return;
-        }
-    }
-
-    // Fix up result metadata for monochrome camera.
-    res = fixupMonochromeTags(mDeviceInfo, captureResult.mMetadata);
-    if (res != OK) {
-        SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
-        return;
-    }
-    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
-        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
-        res = fixupMonochromeTags(mPhysicalDeviceInfoMap.at(cameraId8.c_str()),
-                physicalMetadata.mPhysicalCameraMetadata);
-        if (res != OK) {
-            SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
-            return;
-        }
-    }
-
-    std::unordered_map<std::string, CameraMetadata> monitoredPhysicalMetadata;
-    for (auto& m : physicalMetadatas) {
-        monitoredPhysicalMetadata.emplace(String8(m.mPhysicalCameraId).string(),
-                CameraMetadata(m.mPhysicalCameraMetadata));
-    }
-    mTagMonitor.monitorMetadata(TagMonitor::RESULT,
-            frameNumber, sensorTimestamp, captureResult.mMetadata,
-            monitoredPhysicalMetadata);
-
-    insertResultLocked(&captureResult, frameNumber);
-}
-
-/**
- * Camera HAL device callback methods
- */
-
-void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
-    ATRACE_CALL();
-
-    status_t res;
-
-    uint32_t frameNumber = result->frame_number;
-    if (result->result == NULL && result->num_output_buffers == 0 &&
-            result->input_buffer == NULL) {
-        SET_ERR("No result data provided by HAL for frame %d",
-                frameNumber);
-        return;
-    }
-
-    if (!mUsePartialResult &&
-            result->result != NULL &&
-            result->partial_result != 1) {
-        SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
-                " if partial result is not supported",
-                frameNumber, result->partial_result);
-        return;
-    }
-
-    bool isPartialResult = false;
-    CameraMetadata collectedPartialResult;
-    bool hasInputBufferInRequest = false;
-
-    // Get shutter timestamp and resultExtras from list of in-flight requests,
-    // where it was added by the shutter notification for this frame. If the
-    // shutter timestamp isn't received yet, append the output buffers to the
-    // in-flight request and they will be returned when the shutter timestamp
-    // arrives. Update the in-flight status and remove the in-flight entry if
-    // all result data and shutter timestamp have been received.
-    nsecs_t shutterTimestamp = 0;
-
-    {
-        Mutex::Autolock l(mInFlightLock);
-        ssize_t idx = mInFlightMap.indexOfKey(frameNumber);
-        if (idx == NAME_NOT_FOUND) {
-            SET_ERR("Unknown frame number for capture result: %d",
-                    frameNumber);
-            return;
-        }
-        InFlightRequest &request = mInFlightMap.editValueAt(idx);
-        ALOGVV("%s: got InFlightRequest requestId = %" PRId32
-                ", frameNumber = %" PRId64 ", burstId = %" PRId32
-                ", partialResultCount = %d, hasCallback = %d",
-                __FUNCTION__, request.resultExtras.requestId,
-                request.resultExtras.frameNumber, request.resultExtras.burstId,
-                result->partial_result, request.hasCallback);
-        // Always update the partial count to the latest one if it's not 0
-        // (buffers only). When framework aggregates adjacent partial results
-        // into one, the latest partial count will be used.
-        if (result->partial_result != 0)
-            request.resultExtras.partialResultCount = result->partial_result;
-
-        // Check if this result carries only partial metadata
-        if (mUsePartialResult && result->result != NULL) {
-            if (result->partial_result > mNumPartialResults || result->partial_result < 1) {
-                SET_ERR("Result is malformed for frame %d: partial_result %u must be  in"
-                        " the range of [1, %d] when metadata is included in the result",
-                        frameNumber, result->partial_result, mNumPartialResults);
-                return;
-            }
-            isPartialResult = (result->partial_result < mNumPartialResults);
-            if (isPartialResult && result->num_physcam_metadata) {
-                SET_ERR("Result is malformed for frame %d: partial_result not allowed for"
-                        " physical camera result", frameNumber);
-                return;
-            }
-            if (isPartialResult) {
-                request.collectedPartialResult.append(result->result);
-            }
-
-            if (isPartialResult && request.hasCallback) {
-                // Send partial capture result
-                sendPartialCaptureResult(result->result, request.resultExtras,
-                        frameNumber);
-            }
-        }
-
-        shutterTimestamp = request.shutterTimestamp;
-        hasInputBufferInRequest = request.hasInputBuffer;
-
-        // Did we get the (final) result metadata for this capture?
-        if (result->result != NULL && !isPartialResult) {
-            if (request.physicalCameraIds.size() != result->num_physcam_metadata) {
-                SET_ERR("Requested physical Camera Ids %d not equal to number of metadata %d",
-                        request.physicalCameraIds.size(), result->num_physcam_metadata);
-                return;
-            }
-            if (request.haveResultMetadata) {
-                SET_ERR("Called multiple times with metadata for frame %d",
-                        frameNumber);
-                return;
-            }
-            for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
-                String8 physicalId(result->physcam_ids[i]);
-                std::set<String8>::iterator cameraIdIter =
-                        request.physicalCameraIds.find(physicalId);
-                if (cameraIdIter != request.physicalCameraIds.end()) {
-                    request.physicalCameraIds.erase(cameraIdIter);
-                } else {
-                    SET_ERR("Total result for frame %d has already returned for camera %s",
-                            frameNumber, physicalId.c_str());
-                    return;
-                }
-            }
-            if (mUsePartialResult &&
-                    !request.collectedPartialResult.isEmpty()) {
-                collectedPartialResult.acquire(
-                    request.collectedPartialResult);
-            }
-            request.haveResultMetadata = true;
-        }
-
-        uint32_t numBuffersReturned = result->num_output_buffers;
-        if (result->input_buffer != NULL) {
-            if (hasInputBufferInRequest) {
-                numBuffersReturned += 1;
-            } else {
-                ALOGW("%s: Input buffer should be NULL if there is no input"
-                        " buffer sent in the request",
-                        __FUNCTION__);
-            }
-        }
-        request.numBuffersLeft -= numBuffersReturned;
-        if (request.numBuffersLeft < 0) {
-            SET_ERR("Too many buffers returned for frame %d",
-                    frameNumber);
-            return;
-        }
-
-        camera_metadata_ro_entry_t entry;
-        res = find_camera_metadata_ro_entry(result->result,
-                ANDROID_SENSOR_TIMESTAMP, &entry);
-        if (res == OK && entry.count == 1) {
-            request.sensorTimestamp = entry.data.i64[0];
-        }
-
-        // If shutter event isn't received yet, append the output buffers to
-        // the in-flight request. Otherwise, return the output buffers to
-        // streams.
-        if (shutterTimestamp == 0) {
-            request.pendingOutputBuffers.appendArray(result->output_buffers,
-                result->num_output_buffers);
-        } else {
-            bool timestampIncreasing = !(request.zslCapture || request.hasInputBuffer);
-            returnOutputBuffers(result->output_buffers,
-                result->num_output_buffers, shutterTimestamp, timestampIncreasing,
-                request.outputSurfaces, request.resultExtras);
-        }
-
-        if (result->result != NULL && !isPartialResult) {
-            for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
-                CameraMetadata physicalMetadata;
-                physicalMetadata.append(result->physcam_metadata[i]);
-                request.physicalMetadatas.push_back({String16(result->physcam_ids[i]),
-                        physicalMetadata});
-            }
-            if (shutterTimestamp == 0) {
-                request.pendingMetadata = result->result;
-                request.collectedPartialResult = collectedPartialResult;
-            } else if (request.hasCallback) {
-                CameraMetadata metadata;
-                metadata = result->result;
-                sendCaptureResult(metadata, request.resultExtras,
-                    collectedPartialResult, frameNumber,
-                    hasInputBufferInRequest, request.zslCapture && request.stillCapture,
-                    request.physicalMetadatas);
-            }
-        }
-
-        removeInFlightRequestIfReadyLocked(idx);
-    } // scope for mInFlightLock
-
-    if (result->input_buffer != NULL) {
-        if (hasInputBufferInRequest) {
-            Camera3Stream *stream =
-                Camera3Stream::cast(result->input_buffer->stream);
-            res = stream->returnInputBuffer(*(result->input_buffer));
-            // Note: stream may be deallocated at this point, if this buffer was the
-            // last reference to it.
-            if (res != OK) {
-                ALOGE("%s: RequestThread: Can't return input buffer for frame %d to"
-                      "  its stream:%s (%d)",  __FUNCTION__,
-                      frameNumber, strerror(-res), res);
-            }
-        } else {
-            ALOGW("%s: Input buffer should be NULL if there is no input"
-                    " buffer sent in the request, skipping input buffer return.",
-                    __FUNCTION__);
-        }
-    }
-}
-
-void Camera3Device::notify(const camera3_notify_msg *msg) {
-    ATRACE_CALL();
     sp<NotificationListener> listener;
     {
-        Mutex::Autolock l(mOutputLock);
+        std::lock_guard<std::mutex> l(mOutputLock);
         listener = mListener.promote();
     }
 
-    if (msg == NULL) {
-        SET_ERR("HAL sent NULL notify message!");
-        return;
-    }
+    FlushInflightReqStates states {
+        mId, mInFlightLock, mInFlightMap, mUseHalBufManager,
+        listener, *this, *mInterface, *this};
 
-    switch (msg->type) {
-        case CAMERA3_MSG_ERROR: {
-            notifyError(msg->message.error, listener);
-            break;
-        }
-        case CAMERA3_MSG_SHUTTER: {
-            notifyShutter(msg->message.shutter, listener);
-            break;
-        }
-        default:
-            SET_ERR("Unknown notify message from HAL: %d",
-                    msg->type);
-    }
-}
-
-void Camera3Device::notifyError(const camera3_error_msg_t &msg,
-        sp<NotificationListener> listener) {
-    ATRACE_CALL();
-    // Map camera HAL error codes to ICameraDeviceCallback error codes
-    // Index into this with the HAL error code
-    static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
-        // 0 = Unused error code
-        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
-        // 1 = CAMERA3_MSG_ERROR_DEVICE
-        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
-        // 2 = CAMERA3_MSG_ERROR_REQUEST
-        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
-        // 3 = CAMERA3_MSG_ERROR_RESULT
-        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
-        // 4 = CAMERA3_MSG_ERROR_BUFFER
-        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
-    };
-
-    int32_t errorCode =
-            ((msg.error_code >= 0) &&
-                    (msg.error_code < CAMERA3_MSG_NUM_ERRORS)) ?
-            halErrorMap[msg.error_code] :
-            hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
-
-    int streamId = 0;
-    String16 physicalCameraId;
-    if (msg.error_stream != NULL) {
-        Camera3Stream *stream =
-                Camera3Stream::cast(msg.error_stream);
-        streamId = stream->getId();
-        physicalCameraId = String16(stream->physicalCameraId());
-    }
-    ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
-            mId.string(), __FUNCTION__, msg.frame_number,
-            streamId, msg.error_code);
-
-    CaptureResultExtras resultExtras;
-    switch (errorCode) {
-        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
-            // SET_ERR calls notifyError
-            SET_ERR("Camera HAL reported serious device error");
-            break;
-        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
-        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
-        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
-            {
-                Mutex::Autolock l(mInFlightLock);
-                ssize_t idx = mInFlightMap.indexOfKey(msg.frame_number);
-                if (idx >= 0) {
-                    InFlightRequest &r = mInFlightMap.editValueAt(idx);
-                    r.requestStatus = msg.error_code;
-                    resultExtras = r.resultExtras;
-                    bool logicalDeviceResultError = false;
-                    if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
-                            errorCode) {
-                        if (physicalCameraId.size() > 0) {
-                            String8 cameraId(physicalCameraId);
-                            if (r.physicalCameraIds.find(cameraId) == r.physicalCameraIds.end()) {
-                                ALOGE("%s: Reported result failure for physical camera device: %s "
-                                        " which is not part of the respective request!",
-                                        __FUNCTION__, cameraId.string());
-                                break;
-                            }
-                            resultExtras.errorPhysicalCameraId = physicalCameraId;
-                        } else {
-                            logicalDeviceResultError = true;
-                        }
-                    }
-
-                    if (logicalDeviceResultError
-                            ||  hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST ==
-                            errorCode) {
-                        r.skipResultMetadata = true;
-                    }
-                    if (logicalDeviceResultError) {
-                        // In case of missing result check whether the buffers
-                        // returned. If they returned, then remove inflight
-                        // request.
-                        // TODO: should we call this for ERROR_CAMERA_REQUEST as well?
-                        //       otherwise we are depending on HAL to send the buffers back after
-                        //       calling notifyError. Not sure if that's in the spec.
-                        removeInFlightRequestIfReadyLocked(idx);
-                    }
-                } else {
-                    resultExtras.frameNumber = msg.frame_number;
-                    ALOGE("Camera %s: %s: cannot find in-flight request on "
-                            "frame %" PRId64 " error", mId.string(), __FUNCTION__,
-                            resultExtras.frameNumber);
-                }
-            }
-            resultExtras.errorStreamId = streamId;
-            if (listener != NULL) {
-                listener->notifyError(errorCode, resultExtras);
-            } else {
-                ALOGE("Camera %s: %s: no listener available", mId.string(), __FUNCTION__);
-            }
-            break;
-        default:
-            // SET_ERR calls notifyError
-            SET_ERR("Unknown error message from HAL: %d", msg.error_code);
-            break;
-    }
-}
-
-void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
-        sp<NotificationListener> listener) {
-    ATRACE_CALL();
-    ssize_t idx;
-
-    // Set timestamp for the request in the in-flight tracking
-    // and get the request ID to send upstream
-    {
-        Mutex::Autolock l(mInFlightLock);
-        idx = mInFlightMap.indexOfKey(msg.frame_number);
-        if (idx >= 0) {
-            InFlightRequest &r = mInFlightMap.editValueAt(idx);
-
-            // Verify ordering of shutter notifications
-            {
-                Mutex::Autolock l(mOutputLock);
-                // TODO: need to track errors for tighter bounds on expected frame number.
-                if (r.hasInputBuffer) {
-                    if (msg.frame_number < mNextReprocessShutterFrameNumber) {
-                        SET_ERR("Reprocess shutter notification out-of-order. Expected "
-                                "notification for frame %d, got frame %d",
-                                mNextReprocessShutterFrameNumber, msg.frame_number);
-                        return;
-                    }
-                    mNextReprocessShutterFrameNumber = msg.frame_number + 1;
-                } else if (r.zslCapture && r.stillCapture) {
-                    if (msg.frame_number < mNextZslStillShutterFrameNumber) {
-                        SET_ERR("ZSL still capture shutter notification out-of-order. Expected "
-                                "notification for frame %d, got frame %d",
-                                mNextZslStillShutterFrameNumber, msg.frame_number);
-                        return;
-                    }
-                    mNextZslStillShutterFrameNumber = msg.frame_number + 1;
-                } else {
-                    if (msg.frame_number < mNextShutterFrameNumber) {
-                        SET_ERR("Shutter notification out-of-order. Expected "
-                                "notification for frame %d, got frame %d",
-                                mNextShutterFrameNumber, msg.frame_number);
-                        return;
-                    }
-                    mNextShutterFrameNumber = msg.frame_number + 1;
-                }
-            }
-
-            r.shutterTimestamp = msg.timestamp;
-            if (r.hasCallback) {
-                ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
-                    mId.string(), __FUNCTION__,
-                    msg.frame_number, r.resultExtras.requestId, msg.timestamp);
-                // Call listener, if any
-                if (listener != NULL) {
-                    listener->notifyShutter(r.resultExtras, msg.timestamp);
-                }
-                // send pending result and buffers
-                sendCaptureResult(r.pendingMetadata, r.resultExtras,
-                    r.collectedPartialResult, msg.frame_number,
-                    r.hasInputBuffer, r.zslCapture && r.stillCapture,
-                    r.physicalMetadatas);
-            }
-            bool timestampIncreasing = !(r.zslCapture || r.hasInputBuffer);
-            returnOutputBuffers(r.pendingOutputBuffers.array(),
-                    r.pendingOutputBuffers.size(), r.shutterTimestamp, timestampIncreasing,
-                    r.outputSurfaces, r.resultExtras);
-            r.pendingOutputBuffers.clear();
-
-            removeInFlightRequestIfReadyLocked(idx);
-        }
-    }
-    if (idx < 0) {
-        SET_ERR("Shutter notification for non-existent frame number %d",
-                msg.frame_number);
-    }
+    camera3::flushInflightRequests(states);
 }
 
 CameraMetadata Camera3Device::getLatestRequestLocked() {
@@ -4008,7 +2870,6 @@
     return retVal;
 }
 
-
 void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
         int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
         const std::unordered_map<std::string, CameraMetadata>& physicalMetadata) {
@@ -4024,13 +2885,18 @@
 Camera3Device::HalInterface::HalInterface(
             sp<ICameraDeviceSession> &session,
             std::shared_ptr<RequestMetadataQueue> queue,
-            bool useHalBufManager) :
+            bool useHalBufManager, bool supportOfflineProcessing) :
         mHidlSession(session),
         mRequestMetadataQueue(queue),
         mUseHalBufManager(useHalBufManager),
-        mIsReconfigurationQuerySupported(true) {
+        mIsReconfigurationQuerySupported(true),
+        mSupportOfflineProcessing(supportOfflineProcessing) {
     // Check with hardware service manager if we can downcast these interfaces
     // Somewhat expensive, so cache the results at startup
+    auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
+    if (castResult_3_6.isOk()) {
+        mHidlSession_3_6 = castResult_3_6;
+    }
     auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
     if (castResult_3_5.isOk()) {
         mHidlSession_3_5 = castResult_3_5;
@@ -4045,18 +2911,22 @@
     }
 }
 
-Camera3Device::HalInterface::HalInterface() : mUseHalBufManager(false) {}
+Camera3Device::HalInterface::HalInterface() :
+        mUseHalBufManager(false),
+        mSupportOfflineProcessing(false) {}
 
 Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
         mHidlSession(other.mHidlSession),
         mRequestMetadataQueue(other.mRequestMetadataQueue),
-        mUseHalBufManager(other.mUseHalBufManager) {}
+        mUseHalBufManager(other.mUseHalBufManager),
+        mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
 
 bool Camera3Device::HalInterface::valid() {
     return (mHidlSession != nullptr);
 }
 
 void Camera3Device::HalInterface::clear() {
+    mHidlSession_3_6.clear();
     mHidlSession_3_5.clear();
     mHidlSession_3_4.clear();
     mHidlSession_3_3.clear();
@@ -4234,20 +3104,10 @@
 
         activeStreams.insert(streamId);
         // Create Buffer ID map if necessary
-        if (mBufferIdMaps.count(streamId) == 0) {
-            mBufferIdMaps.emplace(streamId, BufferIdMap{});
-        }
+        mBufferRecords.tryCreateBufferCache(streamId);
     }
     // remove BufferIdMap for deleted streams
-    for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
-        int streamId = it->first;
-        bool active = activeStreams.count(streamId) > 0;
-        if (!active) {
-            it = mBufferIdMaps.erase(it);
-        } else {
-            ++it;
-        }
-    }
+    mBufferRecords.removeInactiveBufferCaches(activeStreams);
 
     StreamConfigurationMode operationMode;
     res = mapToStreamConfigurationMode(
@@ -4265,6 +3125,7 @@
     // Invoke configureStreams
     device::V3_3::HalStreamConfiguration finalConfiguration;
     device::V3_4::HalStreamConfiguration finalConfiguration3_4;
+    device::V3_6::HalStreamConfiguration finalConfiguration3_6;
     common::V1_0::Status status;
 
     auto configStream34Cb = [&status, &finalConfiguration3_4]
@@ -4273,6 +3134,12 @@
                 status = s;
             };
 
+    auto configStream36Cb = [&status, &finalConfiguration3_6]
+            (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
+                finalConfiguration3_6 = halConfiguration;
+                status = s;
+            };
+
     auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
             (hardware::Return<void>& err) -> status_t {
                 if (!err.isOk()) {
@@ -4286,8 +3153,32 @@
                 return OK;
             };
 
+    auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
+            (hardware::Return<void>& err) -> status_t {
+                if (!err.isOk()) {
+                    ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+                    return DEAD_OBJECT;
+                }
+                finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
+                for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
+                    finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
+                }
+                return OK;
+            };
+
     // See which version of HAL we have
-    if (mHidlSession_3_5 != nullptr) {
+    if (mHidlSession_3_6 != nullptr) {
+        ALOGV("%s: v3.6 device found", __FUNCTION__);
+        device::V3_5::StreamConfiguration requestedConfiguration3_5;
+        requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
+        requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
+        auto err = mHidlSession_3_6->configureStreams_3_6(
+                requestedConfiguration3_5, configStream36Cb);
+        res = postprocConfigStream36(err);
+        if (res != OK) {
+            return res;
+        }
+    } else if (mHidlSession_3_5 != nullptr) {
         ALOGV("%s: v3.5 device found", __FUNCTION__);
         device::V3_5::StreamConfiguration requestedConfiguration3_5;
         requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
@@ -4369,11 +3260,16 @@
             return INVALID_OPERATION;
         }
         device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
+        device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
 
         Camera3Stream* dstStream = Camera3Stream::cast(dst);
         int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
         android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
 
+        if (mHidlSession_3_6 != nullptr) {
+            dstStream->setOfflineProcessingSupport(src_36.supportOffline);
+        }
+
         if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
             dstStream->setFormatOverride(false);
             dstStream->setDataSpaceOverride(false);
@@ -4437,7 +3333,6 @@
     captureRequest->fmqSettingsSize = 0;
 
     {
-        std::lock_guard<std::mutex> lock(mInflightLock);
         if (request->input_buffer != nullptr) {
             int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
             buffer_handle_t buf = *(request->input_buffer->buffer);
@@ -4457,7 +3352,7 @@
             captureRequest->inputBuffer.acquireFence = acquireFence;
             captureRequest->inputBuffer.releaseFence = nullptr;
 
-            pushInflightBufferLocked(captureRequest->frameNumber, streamId,
+            mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
                     request->input_buffer->buffer);
             inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
         } else {
@@ -4498,7 +3393,8 @@
 
             // Output buffers are empty when using HAL buffer manager
             if (!mUseHalBufManager) {
-                pushInflightBufferLocked(captureRequest->frameNumber, streamId, src->buffer);
+                mBufferRecords.pushInflightBuffer(
+                        captureRequest->frameNumber, streamId, src->buffer);
                 inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
             }
         }
@@ -4555,7 +3451,7 @@
                     /*out*/&handlesCreated, /*out*/&inflightBuffers);
         }
         if (res != OK) {
-            popInflightBuffers(inflightBuffers);
+            mBufferRecords.popInflightBuffers(inflightBuffers);
             cleanupNativeHandles(&handlesCreated);
             return res;
         }
@@ -4563,10 +3459,10 @@
 
     std::vector<device::V3_2::BufferCache> cachesToRemove;
     {
-        std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+        std::lock_guard<std::mutex> lock(mFreedBuffersLock);
         for (auto& pair : mFreedBuffers) {
             // The stream might have been removed since onBufferFreed
-            if (mBufferIdMaps.find(pair.first) != mBufferIdMaps.end()) {
+            if (mBufferRecords.isStreamCached(pair.first)) {
                 cachesToRemove.push_back({pair.first, pair.second});
             }
         }
@@ -4673,7 +3569,7 @@
             cleanupNativeHandles(&handlesCreated);
         }
     } else {
-        popInflightBuffers(inflightBuffers);
+        mBufferRecords.popInflightBuffers(inflightBuffers);
         cleanupNativeHandles(&handlesCreated);
     }
     return res;
@@ -4732,72 +3628,94 @@
     }
 }
 
+status_t Camera3Device::HalInterface::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+        /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+        /*out*/camera3::BufferRecords* bufferRecords) {
+    ATRACE_NAME("CameraHal::switchToOffline");
+    if (!valid() || mHidlSession_3_6 == nullptr) {
+        ALOGE("%s called on invalid camera!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
+        ALOGE("%s: output arguments must not be null!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+    auto resultCallback =
+        [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
+                status = s;
+                *offlineSessionInfo = info;
+                *offlineSession = session;
+        };
+    auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
+
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+        return DEAD_OBJECT;
+    }
+
+    status_t ret = CameraProviderManager::mapToStatusT(status);
+    if (ret != OK) {
+        return ret;
+    }
+
+    // TODO: assert no ongoing requestBuffer/returnBuffer call here
+    // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
+    //       returns from switchToOffline.
+
+
+    // Validate buffer caches
+    std::vector<int32_t> streams;
+    streams.reserve(offlineSessionInfo->offlineStreams.size());
+    for (auto offlineStream : offlineSessionInfo->offlineStreams) {
+        int32_t id = offlineStream.id;
+        streams.push_back(id);
+        // Verify buffer caches
+        std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
+                offlineStream.circulatingBufferIds.end());
+        if (!verifyBufferIds(id, bufIds)) {
+            ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    // Move buffer records
+    bufferRecords->takeBufferCaches(mBufferRecords, streams);
+    bufferRecords->takeInflightBufferMap(mBufferRecords);
+    bufferRecords->takeRequestedBufferMap(mBufferRecords);
+    return ret;
+}
+
 void Camera3Device::HalInterface::getInflightBufferKeys(
         std::vector<std::pair<int32_t, int32_t>>* out) {
-    std::lock_guard<std::mutex> lock(mInflightLock);
-    out->clear();
-    out->reserve(mInflightBufferMap.size());
-    for (auto& pair : mInflightBufferMap) {
-        uint64_t key = pair.first;
-        int32_t streamId = key & 0xFFFFFFFF;
-        int32_t frameNumber = (key >> 32) & 0xFFFFFFFF;
-        out->push_back(std::make_pair(frameNumber, streamId));
-    }
+    mBufferRecords.getInflightBufferKeys(out);
     return;
 }
 
 void Camera3Device::HalInterface::getInflightRequestBufferKeys(
         std::vector<uint64_t>* out) {
-    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
-    out->clear();
-    out->reserve(mRequestedBuffers.size());
-    for (auto& pair : mRequestedBuffers) {
-        out->push_back(pair.first);
-    }
+    mBufferRecords.getInflightRequestBufferKeys(out);
     return;
 }
 
-status_t Camera3Device::HalInterface::pushInflightBufferLocked(
-        int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer) {
-    uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
-    mInflightBufferMap[key] = buffer;
-    return OK;
+bool Camera3Device::HalInterface::verifyBufferIds(
+        int32_t streamId, std::vector<uint64_t>& bufIds) {
+    return mBufferRecords.verifyBufferIds(streamId, bufIds);
 }
 
 status_t Camera3Device::HalInterface::popInflightBuffer(
         int32_t frameNumber, int32_t streamId,
         /*out*/ buffer_handle_t **buffer) {
-    std::lock_guard<std::mutex> lock(mInflightLock);
-
-    uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
-    auto it = mInflightBufferMap.find(key);
-    if (it == mInflightBufferMap.end()) return NAME_NOT_FOUND;
-    if (buffer != nullptr) {
-        *buffer = it->second;
-    }
-    mInflightBufferMap.erase(it);
-    return OK;
-}
-
-void Camera3Device::HalInterface::popInflightBuffers(
-        const std::vector<std::pair<int32_t, int32_t>>& buffers) {
-    for (const auto& pair : buffers) {
-        int32_t frameNumber = pair.first;
-        int32_t streamId = pair.second;
-        popInflightBuffer(frameNumber, streamId, nullptr);
-    }
+    return mBufferRecords.popInflightBuffer(frameNumber, streamId, buffer);
 }
 
 status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
         uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
-    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
-    auto pair = mRequestedBuffers.insert({bufferId, {streamId, buf}});
-    if (!pair.second) {
-        ALOGE("%s: bufId %" PRIu64 " is already inflight!",
-                __FUNCTION__, bufferId);
-        return BAD_VALUE;
-    }
-    return OK;
+    return mBufferRecords.pushInflightRequestBuffer(bufferId, buf, streamId);
 }
 
 // Find and pop a buffer_handle_t based on bufferId
@@ -4805,81 +3723,29 @@
         uint64_t bufferId,
         /*out*/ buffer_handle_t** buffer,
         /*optional out*/ int32_t* streamId) {
-    if (buffer == nullptr) {
-        ALOGE("%s: buffer (%p) must not be null", __FUNCTION__, buffer);
-        return BAD_VALUE;
-    }
-    std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
-    auto it = mRequestedBuffers.find(bufferId);
-    if (it == mRequestedBuffers.end()) {
-        ALOGE("%s: bufId %" PRIu64 " is not inflight!",
-                __FUNCTION__, bufferId);
-        return BAD_VALUE;
-    }
-    *buffer = it->second.second;
-    if (streamId != nullptr) {
-        *streamId = it->second.first;
-    }
-    mRequestedBuffers.erase(it);
-    return OK;
+    return mBufferRecords.popInflightRequestBuffer(bufferId, buffer, streamId);
 }
 
 std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
         const buffer_handle_t& buf, int streamId) {
-    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
-
-    BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
-    auto it = bIdMap.find(buf);
-    if (it == bIdMap.end()) {
-        bIdMap[buf] = mNextBufferId++;
-        ALOGV("stream %d now have %zu buffer caches, buf %p",
-                streamId, bIdMap.size(), buf);
-        return std::make_pair(true, mNextBufferId - 1);
-    } else {
-        return std::make_pair(false, it->second);
-    }
+    return mBufferRecords.getBufferId(buf, streamId);
 }
 
 void Camera3Device::HalInterface::onBufferFreed(
         int streamId, const native_handle_t* handle) {
-    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
-    uint64_t bufferId = BUFFER_ID_NO_BUFFER;
-    auto mapIt = mBufferIdMaps.find(streamId);
-    if (mapIt == mBufferIdMaps.end()) {
-        // streamId might be from a deleted stream here
-        ALOGI("%s: stream %d has been removed",
-                __FUNCTION__, streamId);
-        return;
+    uint32_t bufferId = mBufferRecords.removeOneBufferCache(streamId, handle);
+    std::lock_guard<std::mutex> lock(mFreedBuffersLock);
+    if (bufferId != BUFFER_ID_NO_BUFFER) {
+        mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
     }
-    BufferIdMap& bIdMap = mapIt->second;
-    auto it = bIdMap.find(handle);
-    if (it == bIdMap.end()) {
-        ALOGW("%s: cannot find buffer %p in stream %d",
-                __FUNCTION__, handle, streamId);
-        return;
-    } else {
-        bufferId = it->second;
-        bIdMap.erase(it);
-        ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
-                __FUNCTION__, streamId, bIdMap.size(), handle);
-    }
-    mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
 }
 
 void Camera3Device::HalInterface::onStreamReConfigured(int streamId) {
-    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
-    auto mapIt = mBufferIdMaps.find(streamId);
-    if (mapIt == mBufferIdMaps.end()) {
-        ALOGE("%s: streamId %d not found!", __FUNCTION__, streamId);
-        return;
-    }
-
-    BufferIdMap& bIdMap = mapIt->second;
-    for (const auto& it : bIdMap) {
-        uint64_t bufferId = it.second;
+    std::vector<uint64_t> bufIds = mBufferRecords.clearBufferCaches(streamId);
+    std::lock_guard<std::mutex> lock(mFreedBuffersLock);
+    for (auto bufferId : bufIds) {
         mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
     }
-    bIdMap.clear();
 }
 
 /**
@@ -4904,6 +3770,7 @@
         mLatestRequestId(NAME_NOT_FOUND),
         mCurrentAfTriggerId(0),
         mCurrentPreCaptureTriggerId(0),
+        mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
         mRepeatingLastFrameNumber(
             hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
         mPrepareVideoStream(false),
@@ -5084,6 +3951,7 @@
                     ALOGW("%s: %d: couldn't get input buffer while clearing the request "
                             "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
                 } else {
+                    inputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
                     res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
                     if (res != OK) {
                         ALOGE("%s: %d: couldn't return input buffer while clearing the request "
@@ -5108,6 +3976,7 @@
         *lastFrameNumber = mRepeatingLastFrameNumber;
     }
     mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
+    mRequestSignal.signal();
     return OK;
 }
 
@@ -5373,6 +4242,9 @@
 bool Camera3Device::RequestThread::threadLoop() {
     ATRACE_CALL();
     status_t res;
+    // Any function called from threadLoop() must not hold mInterfaceLock since
+    // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
+    // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
 
     // Handle paused state.
     if (waitIfPaused()) {
@@ -5415,22 +4287,11 @@
         }
 
         if (res == OK) {
-            sp<StatusTracker> statusTracker = mStatusTracker.promote();
-            if (statusTracker != 0) {
-                sp<Camera3Device> parent = mParent.promote();
-                if (parent != nullptr) {
-                    parent->pauseStateNotify(true);
-                }
-
-                statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
-
-                if (parent != nullptr) {
-                    mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
-                }
-
-                statusTracker->markComponentActive(mStatusId);
-                setPaused(false);
+            sp<Camera3Device> parent = mParent.promote();
+            if (parent != nullptr) {
+                mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
             }
+            setPaused(false);
 
             if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
                 mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
@@ -5501,6 +4362,7 @@
         Mutex::Autolock l(mRequestLock);
         mNextRequests.clear();
     }
+    mRequestSubmittedSignal.signal();
 
     return submitRequestSuccess;
 }
@@ -5531,12 +4393,16 @@
         bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
         mPrevTriggers = triggerCount;
 
+        bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
+
         // If the request is the same as last, or we had triggers last time
-        bool newRequest = (mPrevRequest != captureRequest || triggersMixedIn) &&
+        bool newRequest =
+                (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
                 // Request settings are all the same within one batch, so only treat the first
                 // request in a batch as new
                 !(batchedRequest && i > 0);
         if (newRequest) {
+            std::set<std::string> cameraIdsWithZoom;
             /**
              * HAL workaround:
              * Insert a dummy trigger ID if a trigger is set but no trigger ID is
@@ -5569,6 +4435,43 @@
                             return INVALID_OPERATION;
                         }
                     }
+
+                    for (it = captureRequest->mSettingsList.begin();
+                            it != captureRequest->mSettingsList.end(); it++) {
+                        if (parent->mZoomRatioMappers.find(it->cameraId) ==
+                                parent->mZoomRatioMappers.end()) {
+                            continue;
+                        }
+
+                        camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+                        if (e.count > 0 && e.data.f[0] != 1.0f) {
+                            cameraIdsWithZoom.insert(it->cameraId);
+                        }
+
+                        res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
+                            &(it->metadata));
+                        if (res != OK) {
+                            SET_ERR("RequestThread: Unable to correct capture requests "
+                                    "for zoom ratio for request %d: %s (%d)",
+                                    halRequest->frame_number, strerror(-res), res);
+                            return INVALID_OPERATION;
+                        }
+                    }
+                    if (captureRequest->mRotateAndCropAuto) {
+                        for (it = captureRequest->mSettingsList.begin();
+                                it != captureRequest->mSettingsList.end(); it++) {
+                            auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
+                            if (mapper != parent->mRotateAndCropMappers.end()) {
+                                res = mapper->second.updateCaptureRequest(&(it->metadata));
+                                if (res != OK) {
+                                    SET_ERR("RequestThread: Unable to correct capture requests "
+                                            "for rotate-and-crop for request %d: %s (%d)",
+                                            halRequest->frame_number, strerror(-res), res);
+                                    return INVALID_OPERATION;
+                                }
+                            }
+                        }
+                    }
                 }
             }
 
@@ -5579,6 +4482,7 @@
             captureRequest->mSettingsList.begin()->metadata.sort();
             halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
             mPrevRequest = captureRequest;
+            mPrevCameraIdsWithZoom = cameraIdsWithZoom;
             ALOGVV("%s: Request settings are NEW", __FUNCTION__);
 
             IF_ALOGV() {
@@ -5767,6 +4671,7 @@
                 hasCallback,
                 calculateMaxExpectedDuration(halRequest->settings),
                 requestedPhysicalCameras, isStillCapture, isZslCapture,
+                captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
                 (mUseHalBufManager) ? uniqueSurfaceIdMap :
                                       SurfaceMap{});
         ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
@@ -5880,9 +4785,57 @@
     mStreamIdsToBeDrained = streamIds;
 }
 
+void Camera3Device::RequestThread::clearPreviousRequest() {
+    Mutex::Autolock l(mRequestLock);
+    mPrevRequest.clear();
+}
+
+status_t Camera3Device::RequestThread::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+        /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+        /*out*/camera3::BufferRecords* bufferRecords) {
+    Mutex::Autolock l(mRequestLock);
+    clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
+
+    // Wait until request thread is fully stopped
+    // TBD: check if request thread is being paused by other APIs (shouldn't be)
+
+    // We could also check for mRepeatingRequests.empty(), but the API interface
+    // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
+    // new requests during the call; hence skip that check.
+    bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+    while (!queueEmpty) {
+        status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
+        if (res == TIMED_OUT) {
+            ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
+            return res;
+        } else if (res != OK) {
+            ALOGE("%s: request thread failed to submit a request: %s (%d)!",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+        queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+    }
+
+    return mInterface->switchToOffline(
+            streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
+}
+
+status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
+        camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
+    ATRACE_CALL();
+    Mutex::Autolock l(mTriggerMutex);
+    if (rotateAndCropValue == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) {
+        return BAD_VALUE;
+    }
+    mRotateAndCropOverride = rotateAndCropValue;
+    return OK;
+}
+
 nsecs_t Camera3Device::getExpectedInFlightDuration() {
     ATRACE_CALL();
-    Mutex::Autolock al(mInFlightLock);
+    std::lock_guard<std::mutex> l(mInFlightLock);
     return mExpectedInflightDuration > kMinInflightDuration ?
             mExpectedInflightDuration : kMinInflightDuration;
 }
@@ -5968,7 +4921,7 @@
         {
           sp<Camera3Device> parent = mParent.promote();
           if (parent != NULL) {
-              Mutex::Autolock l(parent->mInFlightLock);
+              std::lock_guard<std::mutex> l(parent->mInFlightLock);
               ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
               if (idx >= 0) {
                   ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
@@ -6395,6 +5348,32 @@
     return OK;
 }
 
+bool Camera3Device::RequestThread::overrideAutoRotateAndCrop(
+        const sp<CaptureRequest> &request) {
+    ATRACE_CALL();
+
+    if (request->mRotateAndCropAuto) {
+        Mutex::Autolock l(mTriggerMutex);
+        CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
+
+        auto rotateAndCropEntry = metadata.find(ANDROID_SCALER_ROTATE_AND_CROP);
+        if (rotateAndCropEntry.count > 0) {
+            if (rotateAndCropEntry.data.u8[0] == mRotateAndCropOverride) {
+                return false;
+            } else {
+                rotateAndCropEntry.data.u8[0] = mRotateAndCropOverride;
+                return true;
+            }
+        } else {
+            uint8_t rotateAndCrop_u8 = mRotateAndCropOverride;
+            metadata.update(ANDROID_SCALER_ROTATE_AND_CROP,
+                    &rotateAndCrop_u8, 1);
+            return true;
+        }
+    }
+    return false;
+}
+
 /**
  * PreparerThread inner class methods
  */
@@ -6657,6 +5636,7 @@
 
 void Camera3Device::RequestBufferStateMachine::onStreamsConfigured() {
     std::lock_guard<std::mutex> lock(mLock);
+    mSwitchedToOffline = false;
     mStatus = RB_STATUS_READY;
     return;
 }
@@ -6699,6 +5679,20 @@
     return;
 }
 
+bool Camera3Device::RequestBufferStateMachine::onSwitchToOfflineSuccess() {
+    std::lock_guard<std::mutex> lock(mLock);
+    if (mRequestBufferOngoing) {
+        ALOGE("%s: HAL must not be requesting buffer after HAL returns switchToOffline!",
+                __FUNCTION__);
+        return false;
+    }
+    mSwitchedToOffline = true;
+    mInflightMapEmpty = true;
+    mRequestThreadPaused = true;
+    mStatus = RB_STATUS_STOPPED;
+    return true;
+}
+
 void Camera3Device::RequestBufferStateMachine::notifyTrackerLocked(bool active) {
     sp<StatusTracker> statusTracker = mStatusTracker.promote();
     if (statusTracker != nullptr) {
@@ -6718,75 +5712,291 @@
     return false;
 }
 
-status_t Camera3Device::fixupMonochromeTags(const CameraMetadata& deviceInfo,
-        CameraMetadata& resultMetadata) {
-    status_t res = OK;
-    if (!mNeedFixupMonochromeTags) {
-        return res;
+bool Camera3Device::startRequestBuffer() {
+    return mRequestBufferSM.startRequestBuffer();
+}
+
+void Camera3Device::endRequestBuffer() {
+    mRequestBufferSM.endRequestBuffer();
+}
+
+nsecs_t Camera3Device::getWaitDuration() {
+    return kBaseGetBufferWait + getExpectedInFlightDuration();
+}
+
+void Camera3Device::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
+    mInterface->getInflightBufferKeys(out);
+}
+
+void Camera3Device::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
+    mInterface->getInflightRequestBufferKeys(out);
+}
+
+std::vector<sp<Camera3StreamInterface>> Camera3Device::getAllStreams() {
+    std::vector<sp<Camera3StreamInterface>> ret;
+    bool hasInputStream = mInputStream != nullptr;
+    ret.reserve(mOutputStreams.size() + mDeletedStreams.size() + ((hasInputStream) ? 1 : 0));
+    if (hasInputStream) {
+        ret.push_back(mInputStream);
+    }
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        ret.push_back(mOutputStreams[i]);
+    }
+    for (size_t i = 0; i < mDeletedStreams.size(); i++) {
+        ret.push_back(mDeletedStreams[i]);
+    }
+    return ret;
+}
+
+status_t Camera3Device::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/ sp<CameraOfflineSessionBase>* session) {
+    ATRACE_CALL();
+    if (session == nullptr) {
+        ALOGE("%s: session must not be null", __FUNCTION__);
+        return BAD_VALUE;
     }
 
-    // Remove tags that are not applicable to monochrome camera.
-    int32_t tagsToRemove[] = {
-           ANDROID_SENSOR_GREEN_SPLIT,
-           ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
-           ANDROID_COLOR_CORRECTION_MODE,
-           ANDROID_COLOR_CORRECTION_TRANSFORM,
-           ANDROID_COLOR_CORRECTION_GAINS,
-    };
-    for (auto tag : tagsToRemove) {
-        res = resultMetadata.erase(tag);
-        if (res != OK) {
-            ALOGE("%s: Failed to remove tag %d for monochrome camera", __FUNCTION__, tag);
-            return res;
+    Mutex::Autolock il(mInterfaceLock);
+
+    bool hasInputStream = mInputStream != nullptr;
+    int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
+    bool inputStreamSupportsOffline = hasInputStream ?
+            mInputStream->getOfflineProcessingSupport() : false;
+    auto outputStreamIds = mOutputStreams.getStreamIds();
+    auto streamIds = outputStreamIds;
+    if (hasInputStream) {
+        streamIds.push_back(mInputStream->getId());
+    }
+
+    // Check all streams in streamsToKeep supports offline mode
+    for (auto id : streamsToKeep) {
+        if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+            ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
+            return BAD_VALUE;
+        } else if (id == inputStreamId) {
+            if (!inputStreamSupportsOffline) {
+                ALOGE("%s: input stream %d cannot be switched to offline",
+                        __FUNCTION__, id);
+                return BAD_VALUE;
+            }
+        } else {
+            sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
+            if (!stream->getOfflineProcessingSupport()) {
+                ALOGE("%s: output stream %d cannot be switched to offline",
+                        __FUNCTION__, id);
+                return BAD_VALUE;
+            }
         }
     }
 
-    // ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
-    camera_metadata_entry blEntry = resultMetadata.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
-    for (size_t i = 1; i < blEntry.count; i++) {
-        blEntry.data.f[i] = blEntry.data.f[0];
+    // TODO: block surface sharing and surface group streams until we can support them
+
+    // Stop repeating request, wait until all remaining requests are submitted, then call into
+    // HAL switchToOffline
+    hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
+    sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
+    camera3::BufferRecords bufferRecords;
+    status_t ret = mRequestThread->switchToOffline(
+            streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
+
+    if (ret != OK) {
+        SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
+        return ret;
     }
 
-    // ANDROID_SENSOR_NOISE_PROFILE
-    camera_metadata_entry npEntry = resultMetadata.find(ANDROID_SENSOR_NOISE_PROFILE);
-    if (npEntry.count > 0 && npEntry.count % 2 == 0) {
-        double np[] = {npEntry.data.d[0], npEntry.data.d[1]};
-        res = resultMetadata.update(ANDROID_SENSOR_NOISE_PROFILE, np, 2);
-        if (res != OK) {
-             ALOGE("%s: Failed to update SENSOR_NOISE_PROFILE: %s (%d)",
-                    __FUNCTION__, strerror(-res), res);
-            return res;
+    bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
+    if (!succ) {
+        SET_ERR("HAL must not be calling requestStreamBuffers call");
+        // TODO: block ALL callbacks from HAL till app configured new streams?
+        return UNKNOWN_ERROR;
+    }
+
+    // Verify offlineSessionInfo
+    std::vector<int32_t> offlineStreamIds;
+    offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        // verify stream IDs
+        int32_t id = offlineStream.id;
+        if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+            SET_ERR("stream ID %d not found!", id);
+            return UNKNOWN_ERROR;
+        }
+
+        // When not using HAL buf manager, only allow streams requested by app to be preserved
+        if (!mUseHalBufManager) {
+            if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
+                SET_ERR("stream ID %d must not be switched to offline!", id);
+                return UNKNOWN_ERROR;
+            }
+        }
+
+        offlineStreamIds.push_back(id);
+        sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
+                static_cast<sp<Camera3StreamInterface>>(mInputStream) :
+                static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
+        // Verify number of outstanding buffers
+        if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
+            SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
+                    id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
+            return UNKNOWN_ERROR;
         }
     }
 
-    // ANDROID_STATISTICS_LENS_SHADING_MAP
-    camera_metadata_ro_entry lsSizeEntry = deviceInfo.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
-    camera_metadata_entry lsEntry = resultMetadata.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
-    if (lsSizeEntry.count == 2 && lsEntry.count > 0
-            && (int32_t)lsEntry.count == 4 * lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]) {
-        for (int32_t i = 0; i < lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]; i++) {
-            lsEntry.data.f[4*i+1] = lsEntry.data.f[4*i];
-            lsEntry.data.f[4*i+2] = lsEntry.data.f[4*i];
-            lsEntry.data.f[4*i+3] = lsEntry.data.f[4*i];
+    // Verify all streams to be deleted don't have any outstanding buffers
+    if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+                inputStreamId) == offlineStreamIds.end()) {
+        if (mInputStream->hasOutstandingBuffers()) {
+            SET_ERR("Input stream %d still has %zu outstanding buffer!",
+                    inputStreamId, mInputStream->getOutstandingBuffersCount());
+            return UNKNOWN_ERROR;
         }
     }
 
-    // ANDROID_TONEMAP_CURVE_BLUE
-    // ANDROID_TONEMAP_CURVE_GREEN
-    // ANDROID_TONEMAP_CURVE_RED
-    camera_metadata_entry tcbEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_BLUE);
-    camera_metadata_entry tcgEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_GREEN);
-    camera_metadata_entry tcrEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_RED);
-    if (tcbEntry.count > 0
-            && tcbEntry.count == tcgEntry.count
-            && tcbEntry.count == tcrEntry.count) {
-        for (size_t i = 0; i < tcbEntry.count; i++) {
-            tcbEntry.data.f[i] = tcrEntry.data.f[i];
-            tcgEntry.data.f[i] = tcrEntry.data.f[i];
+    for (const auto& outStreamId : outputStreamIds) {
+        if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+                outStreamId) == offlineStreamIds.end()) {
+            auto outStream = mOutputStreams.get(outStreamId);
+            if (outStream->hasOutstandingBuffers()) {
+                SET_ERR("Output stream %d still has %zu outstanding buffer!",
+                        outStreamId, outStream->getOutstandingBuffersCount());
+                return UNKNOWN_ERROR;
+            }
         }
     }
 
-    return res;
+    InFlightRequestMap offlineReqs;
+    // Verify inflight requests and their pending buffers
+    {
+        std::lock_guard<std::mutex> l(mInFlightLock);
+        for (auto offlineReq : offlineSessionInfo.offlineRequests) {
+            int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
+            if (idx == NAME_NOT_FOUND) {
+                SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
+                return UNKNOWN_ERROR;
+            }
+
+            const auto& inflightReq = mInFlightMap.valueAt(idx);
+            // TODO: check specific stream IDs
+            size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
+            if (numBuffersLeft != offlineReq.pendingStreams.size()) {
+                SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
+                        inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
+                return UNKNOWN_ERROR;
+            }
+            offlineReqs.add(offlineReq.frameNumber, inflightReq);
+        }
+    }
+
+    // Create Camera3OfflineSession and transfer object ownership
+    //   (streams, inflight requests, buffer caches)
+    camera3::StreamSet offlineStreamSet;
+    sp<camera3::Camera3Stream> inputStream;
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        int32_t id = offlineStream.id;
+        if (mInputStream != nullptr && id == mInputStream->getId()) {
+            inputStream = mInputStream;
+        } else {
+            offlineStreamSet.add(id, mOutputStreams.get(id));
+        }
+    }
+
+    // TODO: check if we need to lock before copying states
+    //       though technically no other thread should be talking to Camera3Device at this point
+    Camera3OfflineStates offlineStates(
+            mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
+            mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
+            mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+            mNextResultFrameNumber, mNextReprocessResultFrameNumber,
+            mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
+            mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+            mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
+            mZoomRatioMappers, mRotateAndCropMappers);
+
+    *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
+            std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
+
+    // Delete all streams that has been transferred to offline session
+    Mutex::Autolock l(mLock);
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        int32_t id = offlineStream.id;
+        if (mInputStream != nullptr && id == mInputStream->getId()) {
+            mInputStream.clear();
+        } else {
+            mOutputStreams.remove(id);
+        }
+    }
+
+    // disconnect all other streams and switch to UNCONFIGURED state
+    if (mInputStream != nullptr) {
+        ret = mInputStream->disconnect();
+        if (ret != OK) {
+            SET_ERR_L("disconnect input stream failed!");
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    for (auto streamId : mOutputStreams.getStreamIds()) {
+        sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
+        ret = stream->disconnect();
+        if (ret != OK) {
+            SET_ERR_L("disconnect output stream %d failed!", streamId);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    mInputStream.clear();
+    mOutputStreams.clear();
+    mNeedConfig = true;
+    internalUpdateStatusLocked(STATUS_UNCONFIGURED);
+    mOperatingMode = NO_MODE;
+    mIsConstrainedHighSpeedConfiguration = false;
+    mRequestThread->clearPreviousRequest();
+
+    return OK;
+    // TO be done by CameraDeviceClient/Camera3OfflineSession
+    // register the offline client to camera service
+    // Setup result passthing threads etc
+    // Initialize offline session so HAL can start sending callback to it (result Fmq)
+    // TODO: check how many onIdle callback will be sent
+    // Java side to make sure the CameraCaptureSession is properly closed
+}
+
+void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
+    ATRACE_CALL();
+
+    if (offlineStreamIds == nullptr) {
+        return;
+    }
+
+    Mutex::Autolock il(mInterfaceLock);
+
+    auto streamIds = mOutputStreams.getStreamIds();
+    bool hasInputStream = mInputStream != nullptr;
+    if (hasInputStream && mInputStream->getOfflineProcessingSupport()) {
+        offlineStreamIds->push_back(mInputStream->getId());
+    }
+
+    for (const auto & streamId : streamIds) {
+        sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
+        // Streams that use the camera buffer manager are currently not supported in
+        // offline mode
+        if (stream->getOfflineProcessingSupport() &&
+                (stream->getStreamSetId() == CAMERA3_STREAM_SET_ID_INVALID)) {
+            offlineStreamIds->push_back(streamId);
+        }
+    }
+}
+
+status_t Camera3Device::setRotateAndCropAutoBehavior(
+    camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
+    ATRACE_CALL();
+    Mutex::Autolock il(mInterfaceLock);
+    Mutex::Autolock l(mLock);
+    if (mRequestThread == nullptr) {
+        return INVALID_OPERATION;
+    }
+    return mRequestThread->setRotateAndCropAutoBehavior(rotateAndCropValue);
 }
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cae34ce..408f1f9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -34,6 +34,7 @@
 #include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
 #include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
@@ -42,9 +43,15 @@
 #include <camera/CaptureResult.h>
 
 #include "common/CameraDeviceBase.h"
+#include "device3/BufferUtils.h"
 #include "device3/StatusTracker.h"
 #include "device3/Camera3BufferManager.h"
 #include "device3/DistortionMapper.h"
+#include "device3/ZoomRatioMapper.h"
+#include "device3/RotateAndCropMapper.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3OutputInterface.h"
+#include "device3/Camera3OfflineSession.h"
 #include "utils/TagMonitor.h"
 #include "utils/LatencyHistogram.h"
 #include <camera_metadata_hidden.h>
@@ -67,7 +74,11 @@
  */
 class Camera3Device :
             public CameraDeviceBase,
-            virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
+            virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
+            public camera3::SetErrorInterface,
+            public camera3::InflightRequestUpdateInterface,
+            public camera3::RequestBufferInterface,
+            public camera3::FlushBufferInterface {
   public:
 
     explicit Camera3Device(const String8& id);
@@ -87,7 +98,7 @@
     status_t disconnect() override;
     status_t dump(int fd, const Vector<String16> &args) override;
     const CameraMetadata& info() const override;
-    const CameraMetadata& info(const String8& physicalId) const override;
+    const CameraMetadata& infoPhysical(const String8& physicalId) const override;
 
     // Capture and setStreamingRequest will configure streams if currently in
     // idle state
@@ -140,6 +151,8 @@
     status_t getInputBufferProducer(
             sp<IGraphicBufferProducer> *producer) override;
 
+    void getOfflineStreamIds(std::vector<int> *offlineStreamIds) override;
+
     status_t createDefaultRequest(int templateId, CameraMetadata *request) override;
 
     // Transitions to the idle state on success
@@ -194,6 +207,33 @@
      */
     status_t dropStreamBuffers(bool dropping, int streamId) override;
 
+    nsecs_t getExpectedInFlightDuration() override;
+
+    status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
+            /*out*/ sp<CameraOfflineSessionBase>* session) override;
+
+    // RequestBufferInterface
+    bool startRequestBuffer() override;
+    void endRequestBuffer() override;
+    nsecs_t getWaitDuration() override;
+
+    // FlushBufferInterface
+    void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) override;
+    void getInflightRequestBufferKeys(std::vector<uint64_t>* out) override;
+    std::vector<sp<camera3::Camera3StreamInterface>> getAllStreams() override;
+
+    /**
+     * Set the current behavior for the ROTATE_AND_CROP control when in AUTO.
+     *
+     * The value must be one of the ROTATE_AND_CROP_* values besides AUTO,
+     * and defaults to NONE.
+     */
+    status_t setRotateAndCropAutoBehavior(
+            camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
+
+    // Get the status trackeer for the camera device
+    wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }
+
     /**
      * Helper functions to map between framework and HIDL values
      */
@@ -206,8 +246,6 @@
     // Returns a negative error code if the passed-in operation mode is not valid.
     static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
             /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
-    static camera3_buffer_status_t mapHidlBufferStatus(
-            hardware::camera::device::V3_2::BufferStatus status);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
     static android_dataspace mapToFrameworkDataspace(
             hardware::camera::device::V3_2::DataspaceFlags);
@@ -222,7 +260,6 @@
 
     // internal typedefs
     using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-    using ResultMetadataQueue  = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
 
     static const size_t        kDumpLockAttempts  = 10;
     static const size_t        kDumpSleepDuration = 100000; // 0.10 sec
@@ -244,7 +281,6 @@
 
     // A lock to enforce serialization on the input/configure side
     // of the public interface.
-    // Only locked by public methods inherited from CameraDeviceBase.
     // Not locked by methods guarded by mOutputLock, since they may act
     // concurrently to the input/configure side of the interface.
     // Must be locked before mLock if both will be locked by a method
@@ -276,11 +312,12 @@
      * Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
      * HIDL HALv3 interfaces.
      */
-    class HalInterface : public camera3::Camera3StreamBufferFreedListener {
+    class HalInterface : public camera3::Camera3StreamBufferFreedListener,
+            public camera3::BufferRecordsInterface {
       public:
         HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
                      std::shared_ptr<RequestMetadataQueue> queue,
-                     bool useHalBufManager);
+                     bool useHalBufManager, bool supportOfflineProcessing);
         HalInterface(const HalInterface &other);
         HalInterface();
 
@@ -314,22 +351,31 @@
         bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
                 CameraMetadata& newSessionParams);
 
-        // method to extract buffer's unique ID
-        // return pair of (newlySeenBuffer?, bufferId)
-        std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
+        // Upon successful return, HalInterface will return buffer maps needed for offline
+        // processing, and clear all its internal buffer maps.
+        status_t switchToOffline(
+                const std::vector<int32_t>& streamsToKeep,
+                /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+                /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+                /*out*/camera3::BufferRecords* bufferRecords);
 
-        // Find a buffer_handle_t based on frame number and stream ID
+        /////////////////////////////////////////////////////////////////////
+        // Implements BufferRecordsInterface
+
+        std::pair<bool, uint64_t> getBufferId(
+                const buffer_handle_t& buf, int streamId) override;
+
         status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
-                /*out*/ buffer_handle_t **buffer);
+                /*out*/ buffer_handle_t **buffer) override;
 
-        // Register a bufId (streamId, buffer_handle_t) to inflight request buffer
         status_t pushInflightRequestBuffer(
-                uint64_t bufferId, buffer_handle_t* buf, int32_t streamId);
+                uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) override;
 
-        // Find a buffer_handle_t based on bufferId
         status_t popInflightRequestBuffer(uint64_t bufferId,
                 /*out*/ buffer_handle_t** buffer,
-                /*optional out*/ int32_t* streamId = nullptr);
+                /*optional out*/ int32_t* streamId = nullptr) override;
+
+        /////////////////////////////////////////////////////////////////////
 
         // Get a vector of (frameNumber, streamId) pair of currently inflight
         // buffers
@@ -340,7 +386,6 @@
 
         void onStreamReConfigured(int streamId);
 
-        static const uint64_t BUFFER_ID_NO_BUFFER = 0;
       private:
         // Always valid
         sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
@@ -350,11 +395,11 @@
         sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
         // Valid if ICameraDeviceSession is @3.5 or newer
         sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
+        // Valid if ICameraDeviceSession is @3.6 or newer
+        sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
 
         std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
 
-        std::mutex mInflightLock;
-
         // The output HIDL request still depends on input camera3_capture_request_t
         // Do not free input camera3_capture_request_t before output HIDL request
         status_t wrapAsHidlRequest(camera3_capture_request_t* in,
@@ -368,65 +413,33 @@
         // Pop inflight buffers based on pairs of (frameNumber,streamId)
         void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
 
-        // Cache of buffer handles keyed off (frameNumber << 32 | streamId)
-        std::unordered_map<uint64_t, buffer_handle_t*> mInflightBufferMap;
+        // Return true if the input caches match what we have; otherwise false
+        bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
 
         // Delete and optionally close native handles and clear the input vector afterward
         static void cleanupNativeHandles(
                 std::vector<native_handle_t*> *handles, bool closeFd = false);
 
-        struct BufferHasher {
-            size_t operator()(const buffer_handle_t& buf) const {
-                if (buf == nullptr)
-                    return 0;
-
-                size_t result = 1;
-                result = 31 * result + buf->numFds;
-                for (int i = 0; i < buf->numFds; i++) {
-                    result = 31 * result + buf->data[i];
-                }
-                return result;
-            }
-        };
-
-        struct BufferComparator {
-            bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
-                if (buf1->numFds == buf2->numFds) {
-                    for (int i = 0; i < buf1->numFds; i++) {
-                        if (buf1->data[i] != buf2->data[i]) {
-                            return false;
-                        }
-                    }
-                    return true;
-                }
-                return false;
-            }
-        };
-
-        std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
-        typedef std::unordered_map<const buffer_handle_t, uint64_t,
-                BufferHasher, BufferComparator> BufferIdMap;
-        // stream ID -> per stream buffer ID map
-        std::unordered_map<int, BufferIdMap> mBufferIdMaps;
-        uint64_t mNextBufferId = 1; // 0 means no buffer
-
         virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
 
+        std::mutex mFreedBuffersLock;
         std::vector<std::pair<int, uint64_t>> mFreedBuffers;
 
-        // Buffers given to HAL through requestStreamBuffer API
-        std::mutex mRequestedBuffersLock;
-        std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> mRequestedBuffers;
+        // Keep track of buffer cache and inflight buffer records
+        camera3::BufferRecords mBufferRecords;
 
         uint32_t mNextStreamConfigCounter = 1;
 
         const bool mUseHalBufManager;
         bool mIsReconfigurationQuerySupported;
+
+        const bool mSupportOfflineProcessing;
     };
 
     sp<HalInterface> mInterface;
 
     CameraMetadata             mDeviceInfo;
+    bool                       mSupportNativeZoomRatio;
     std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
 
     CameraMetadata             mRequestTemplateCache[CAMERA3_TEMPLATE_COUNT];
@@ -456,24 +469,7 @@
     // Tracking cause of fatal errors when in STATUS_ERROR
     String8                    mErrorCause;
 
-    // Synchronized mapping of stream IDs to stream instances
-    class StreamSet {
-      public:
-        status_t add(int streamId, sp<camera3::Camera3OutputStreamInterface>);
-        ssize_t remove(int streamId);
-        sp<camera3::Camera3OutputStreamInterface> get(int streamId);
-        // get by (underlying) vector index
-        sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index);
-        size_t size() const;
-        std::vector<int> getStreamIds();
-        void clear();
-
-      private:
-        mutable std::mutex mLock;
-        KeyedVector<int, sp<camera3::Camera3OutputStreamInterface>> mData;
-    };
-
-    StreamSet                  mOutputStreams;
+    camera3::StreamSet         mOutputStreams;
     sp<camera3::Camera3Stream> mInputStream;
     int                        mNextStreamId;
     bool                       mNeedConfig;
@@ -517,6 +513,10 @@
         int                                 mBatchSize;
         //  Whether this request is from a repeating or repeating burst.
         bool                                mRepeating;
+        // Whether this request has ROTATE_AND_CROP_AUTO set, so needs both
+        // overriding of ROTATE_AND_CROP value and adjustment of coordinates
+        // in several other controls in both the request and the result
+        bool                                mRotateAndCropAuto;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -562,15 +562,6 @@
             const hardware::hidl_vec<
                     hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
 
-    // Handle one capture result. Assume that mProcessCaptureResultLock is held.
-    void processOneCaptureResultLocked(
-            const hardware::camera::device::V3_2::CaptureResult& result,
-            const hardware::hidl_vec<
-            hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
-    status_t readOneCameraMetadataLocked(uint64_t fmqResultSize,
-            hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
-            const hardware::camera::device::V3_2::CameraMetadata& result);
-
     // Handle one notify message
     void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
 
@@ -647,17 +638,16 @@
                                             const SurfaceMap &surfaceMap);
 
     /**
-     * Pause state updates to the client application.  Needed to mask out idle/active
-     * transitions during internal reconfigure
+     * Internally re-configure camera device using new session parameters.
+     * This will get triggered by the request thread.
      */
-    void pauseStateNotify(bool enable);
+    bool reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId);
 
     /**
-     * Internally re-configure camera device using new session parameters.
-     * This will get triggered by the request thread. Be sure to call
-     * pauseStateNotify(true) before going idle in the requesting location.
+     * Return true in case of any output or input abandoned streams,
+     * otherwise return false.
      */
-    bool reconfigureCamera(const CameraMetadata& sessionParams);
+    bool checkAbandonedStreamsLocked();
 
     /**
      * Filter stream session parameters and configure camera HAL.
@@ -693,11 +683,20 @@
      * error message to indicate why. Only the first call's message will be
      * used. The message is also sent to the log.
      */
-    void               setErrorState(const char *fmt, ...);
+    void               setErrorState(const char *fmt, ...) override;
+    void               setErrorStateLocked(const char *fmt, ...) override;
     void               setErrorStateV(const char *fmt, va_list args);
-    void               setErrorStateLocked(const char *fmt, ...);
     void               setErrorStateLockedV(const char *fmt, va_list args);
 
+    /////////////////////////////////////////////////////////////////////
+    // Implements InflightRequestUpdateInterface
+
+    void onInflightEntryRemovedLocked(nsecs_t duration) override;
+    void checkInflightMapLengthLocked() override;
+    void onInflightMapFlushedLocked() override;
+
+    /////////////////////////////////////////////////////////////////////
+
     /**
      * Debugging trylock/spin method
      * Try to acquire a lock a few times with sleeps between before giving up.
@@ -705,12 +704,6 @@
     bool               tryLockSpinRightRound(Mutex& lock);
 
     /**
-     * Helper function to determine if an input size for implementation defined
-     * format is supported.
-     */
-    bool isOpaqueInputSizeSupported(uint32_t width, uint32_t height);
-
-    /**
      * Helper function to get the largest Jpeg resolution (in area)
      * Return Size(0, 0) if static metatdata is invalid
      */
@@ -840,6 +833,17 @@
 
         void signalPipelineDrain(const std::vector<int>& streamIds);
 
+        status_t switchToOffline(
+                const std::vector<int32_t>& streamsToKeep,
+                /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+                /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+                /*out*/camera3::BufferRecords* bufferRecords);
+
+        void clearPreviousRequest();
+
+        status_t setRotateAndCropAutoBehavior(
+                camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
+
       protected:
 
         virtual bool threadLoop();
@@ -856,10 +860,16 @@
 
         // HAL workaround: Make sure a trigger ID always exists if
         // a trigger does
-        status_t          addDummyTriggerIds(const sp<CaptureRequest> &request);
+        status_t           addDummyTriggerIds(const sp<CaptureRequest> &request);
+
+        // Override rotate_and_crop control if needed; returns true if the current value was changed
+        bool               overrideAutoRotateAndCrop(const sp<CaptureRequest> &request);
 
         static const nsecs_t kRequestTimeout = 50e6; // 50 ms
 
+        // TODO: does this need to be adjusted for long exposure requests?
+        static const nsecs_t kRequestSubmitTimeout = 200e6; // 200 ms
+
         // Used to prepare a batch of requests.
         struct NextRequest {
             sp<CaptureRequest>              captureRequest;
@@ -934,6 +944,7 @@
 
         Mutex              mRequestLock;
         Condition          mRequestSignal;
+        Condition          mRequestSubmittedSignal;
         RequestList        mRequestQueue;
         RequestList        mRepeatingRequests;
         // The next batch of requests being prepped for submission to the HAL, no longer
@@ -956,6 +967,7 @@
 
         sp<CaptureRequest> mPrevRequest;
         int32_t            mPrevTriggers;
+        std::set<std::string> mPrevCameraIdsWithZoom;
 
         uint32_t           mFrameNumber;
 
@@ -973,6 +985,7 @@
         TriggerMap         mTriggerReplacedMap;
         uint32_t           mCurrentAfTriggerId;
         uint32_t           mCurrentPreCaptureTriggerId;
+        camera_metadata_enum_android_scaler_rotate_and_crop_t mRotateAndCropOverride;
 
         int64_t            mRepeatingLastFrameNumber;
 
@@ -994,127 +1007,21 @@
     /**
      * In-flight queue for tracking completion of capture requests.
      */
+    std::mutex                    mInFlightLock;
+    camera3::InFlightRequestMap   mInFlightMap;
+    nsecs_t                       mExpectedInflightDuration = 0;
+    int64_t                       mLastCompletedRegularFrameNumber = -1;
+    int64_t                       mLastCompletedReprocessFrameNumber = -1;
+    int64_t                       mLastCompletedZslFrameNumber = -1;
+    // End of mInFlightLock protection scope
 
-    struct InFlightRequest {
-        // Set by notify() SHUTTER call.
-        nsecs_t shutterTimestamp;
-        // Set by process_capture_result().
-        nsecs_t sensorTimestamp;
-        int     requestStatus;
-        // Set by process_capture_result call with valid metadata
-        bool    haveResultMetadata;
-        // Decremented by calls to process_capture_result with valid output
-        // and input buffers
-        int     numBuffersLeft;
-        CaptureResultExtras resultExtras;
-        // If this request has any input buffer
-        bool hasInputBuffer;
-
-        // The last metadata that framework receives from HAL and
-        // not yet send out because the shutter event hasn't arrived.
-        // It's added by process_capture_result and sent when framework
-        // receives the shutter event.
-        CameraMetadata pendingMetadata;
-
-        // The metadata of the partial results that framework receives from HAL so far
-        // and has sent out.
-        CameraMetadata collectedPartialResult;
-
-        // Buffers are added by process_capture_result when output buffers
-        // return from HAL but framework has not yet received the shutter
-        // event. They will be returned to the streams when framework receives
-        // the shutter event.
-        Vector<camera3_stream_buffer_t> pendingOutputBuffers;
-
-        // Whether this inflight request's shutter and result callback are to be
-        // called. The policy is that if the request is the last one in the constrained
-        // high speed recording request list, this flag will be true. If the request list
-        // is not for constrained high speed recording, this flag will also be true.
-        bool hasCallback;
-
-        // Maximum expected frame duration for this request.
-        // For manual captures, equal to the max of requested exposure time and frame duration
-        // For auto-exposure modes, equal to 1/(lower end of target FPS range)
-        nsecs_t maxExpectedDuration;
-
-        // Whether the result metadata for this request is to be skipped. The
-        // result metadata should be skipped in the case of
-        // REQUEST/RESULT error.
-        bool skipResultMetadata;
-
-        // The physical camera ids being requested.
-        std::set<String8> physicalCameraIds;
-
-        // Map of physicalCameraId <-> Metadata
-        std::vector<PhysicalCaptureResultInfo> physicalMetadatas;
-
-        // Indicates a still capture request.
-        bool stillCapture;
-
-        // Indicates a ZSL capture request
-        bool zslCapture;
-
-        // What shared surfaces an output should go to
-        SurfaceMap outputSurfaces;
-
-        // Default constructor needed by KeyedVector
-        InFlightRequest() :
-                shutterTimestamp(0),
-                sensorTimestamp(0),
-                requestStatus(OK),
-                haveResultMetadata(false),
-                numBuffersLeft(0),
-                hasInputBuffer(false),
-                hasCallback(true),
-                maxExpectedDuration(kDefaultExpectedDuration),
-                skipResultMetadata(false),
-                stillCapture(false),
-                zslCapture(false) {
-        }
-
-        InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
-                bool hasAppCallback, nsecs_t maxDuration,
-                const std::set<String8>& physicalCameraIdSet, bool isStillCapture,
-                bool isZslCapture,
-                const SurfaceMap& outSurfaces = SurfaceMap{}) :
-                shutterTimestamp(0),
-                sensorTimestamp(0),
-                requestStatus(OK),
-                haveResultMetadata(false),
-                numBuffersLeft(numBuffers),
-                resultExtras(extras),
-                hasInputBuffer(hasInput),
-                hasCallback(hasAppCallback),
-                maxExpectedDuration(maxDuration),
-                skipResultMetadata(false),
-                physicalCameraIds(physicalCameraIdSet),
-                stillCapture(isStillCapture),
-                zslCapture(isZslCapture),
-                outputSurfaces(outSurfaces) {
-        }
-    };
-
-    // Map from frame number to the in-flight request state
-    typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
-
-
-    Mutex                  mInFlightLock; // Protects mInFlightMap and
-                                          // mExpectedInflightDuration
-    InFlightMap            mInFlightMap;
-    nsecs_t                mExpectedInflightDuration = 0;
-    int                    mInFlightStatusId;
+    int mInFlightStatusId; // const after initialize
 
     status_t registerInFlight(uint32_t frameNumber,
             int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
             bool callback, nsecs_t maxExpectedDuration, std::set<String8>& physicalCameraIds,
-            bool isStillCapture, bool isZslCapture,
-            const SurfaceMap& outputSurfaces);
-
-    /**
-     * Returns the maximum expected time it'll take for all currently in-flight
-     * requests to complete, based on their settings
-     */
-    nsecs_t getExpectedInFlightDuration();
+            bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto,
+            const std::set<std::string>& cameraIdsWithZoom, const SurfaceMap& outputSurfaces);
 
     /**
      * Tracking for idle detection
@@ -1186,7 +1093,7 @@
      */
 
     // Lock for output side of device
-    Mutex                  mOutputLock;
+    std::mutex             mOutputLock;
 
     /**** Scope for mOutputLock ****/
     // the minimal frame number of the next non-reprocess result
@@ -1201,60 +1108,18 @@
     uint32_t               mNextReprocessShutterFrameNumber;
     // the minimal frame number of the next ZSL still capture shutter
     uint32_t               mNextZslStillShutterFrameNumber;
-    List<CaptureResult>   mResultQueue;
-    Condition              mResultSignal;
-    wp<NotificationListener>  mListener;
+    std::list<CaptureResult>    mResultQueue;
+    std::condition_variable  mResultSignal;
+    wp<NotificationListener> mListener;
 
     /**** End scope for mOutputLock ****/
 
-    /**
-     * Callback functions from HAL device
-     */
-    void processCaptureResult(const camera3_capture_result *result);
-
-    void notify(const camera3_notify_msg *msg);
-
-    // Specific notify handlers
-    void notifyError(const camera3_error_msg_t &msg,
-            sp<NotificationListener> listener);
-    void notifyShutter(const camera3_shutter_msg_t &msg,
-            sp<NotificationListener> listener);
-
-    // helper function to return the output buffers to the streams.
-    void returnOutputBuffers(const camera3_stream_buffer_t *outputBuffers,
-            size_t numBuffers, nsecs_t timestamp, bool timestampIncreasing = true,
-            // The following arguments are only meant for surface sharing use case
-            const SurfaceMap& outputSurfaces = SurfaceMap{},
-            // Used to send buffer error callback when failing to return buffer
-            const CaptureResultExtras &resultExtras = CaptureResultExtras{});
-
-    // Send a partial capture result.
-    void sendPartialCaptureResult(const camera_metadata_t * partialResult,
-            const CaptureResultExtras &resultExtras, uint32_t frameNumber);
-
-    // Send a total capture result given the pending metadata and result extras,
-    // partial results, and the frame number to the result queue.
-    void sendCaptureResult(CameraMetadata &pendingMetadata,
-            CaptureResultExtras &resultExtras,
-            CameraMetadata &collectedPartialResult, uint32_t frameNumber,
-            bool reprocess, bool zslStillCapture,
-            const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas);
-
-    bool isLastFullResult(const InFlightRequest& inFlightRequest);
-
-    // Insert the result to the result queue after updating frame number and overriding AE
-    // trigger cancel.
-    // mOutputLock must be held when calling this function.
-    void insertResultLocked(CaptureResult *result, uint32_t frameNumber);
-
     /**** Scope for mInFlightLock ****/
 
     // Remove the in-flight map entry of the given index from mInFlightMap.
     // It must only be called with mInFlightLock held.
     void removeInFlightMapEntryLocked(int idx);
-    // Remove the in-flight request of the given index from mInFlightMap
-    // if it's no longer needed. It must only be called with mInFlightLock held.
-    void removeInFlightRequestIfReadyLocked(int idx);
+
     // Remove all in-flight requests and return all buffers.
     // This is used after HAL interface is closed to cleanup any request/buffers
     // not returned by HAL.
@@ -1270,6 +1135,16 @@
     // logical camera and its physical subcameras.
     std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;
 
+    /**
+     * Zoom ratio mapper support
+     */
+    std::unordered_map<std::string, camera3::ZoomRatioMapper> mZoomRatioMappers;
+
+    /**
+     * RotateAndCrop mapper support
+     */
+    std::unordered_map<std::string, camera3::RotateAndCropMapper> mRotateAndCropMappers;
+
     // Debug tracker for metadata tag value changes
     // - Enabled with the -m <taglist> option to dumpsys, such as
     //   dumpsys -m android.control.aeState,android.control.aeMode
@@ -1347,6 +1222,10 @@
         void onSubmittingRequest();
         void onRequestThreadPaused();
 
+        // Events triggered by successful switchToOffline call
+        // Return true is there is no ongoing requestBuffer call.
+        bool onSwitchToOfflineSuccess();
+
       private:
         void notifyTrackerLocked(bool active);
 
@@ -1360,6 +1239,7 @@
         bool mRequestThreadPaused = true;
         bool mInflightMapEmpty = true;
         bool mRequestBufferOngoing = false;
+        bool mSwitchedToOffline = false;
 
         wp<camera3::StatusTracker> mStatusTracker;
         int  mRequestBufferStatusId;
@@ -1367,7 +1247,9 @@
 
     // Fix up result metadata for monochrome camera.
     bool mNeedFixupMonochromeTags;
-    status_t fixupMonochromeTags(const CameraMetadata& deviceInfo, CameraMetadata& resultMetadata);
+
+    // Whether HAL supports offline processing capability.
+    bool mSupportOfflineProcessing = false;
 }; // class Camera3Device
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index ef0d919..bda2961 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -269,8 +269,6 @@
         }
     }
 
-    mBufferReturnedSignal.signal();
-
     if (output) {
         mLastTimestamp = timestamp;
     }
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 750f64d..448379c 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -55,7 +55,6 @@
     // number of output buffers that are currently acquired by HAL. This will be
     // Redundant when camera3 streams are no longer bidirectional streams.
     size_t            mHandoutOutputBufferCount;
-    Condition         mBufferReturnedSignal;
     uint32_t          mFrameCount;
     // Last received output buffer's timestamp
     nsecs_t           mLastTimestamp;
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index fc83684..cb59a76 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -71,7 +71,8 @@
 
     res = mConsumer->acquireBuffer(&bufferItem, /*waitForFence*/false);
     if (res != OK) {
-        ALOGE("%s: Stream %d: Can't acquire next output buffer: %s (%d)",
+        // This may or may not be an error condition depending on caller.
+        ALOGV("%s: Stream %d: Can't acquire next output buffer: %s (%d)",
                 __FUNCTION__, mId, strerror(-res), res);
         return res;
     }
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
new file mode 100644
index 0000000..95f9633
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2019 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_TAG "Camera3-OffLnSsn"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+#include <inttypes.h>
+
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include "device3/Camera3OfflineSession.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "utils/CameraTraces.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+
+Camera3OfflineSession::Camera3OfflineSession(const String8 &id,
+        const sp<camera3::Camera3Stream>& inputStream,
+        const camera3::StreamSet& offlineStreamSet,
+        camera3::BufferRecords&& bufferRecords,
+        const camera3::InFlightRequestMap& offlineReqs,
+        const Camera3OfflineStates& offlineStates,
+        sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
+        mId(id),
+        mInputStream(inputStream),
+        mOutputStreams(offlineStreamSet),
+        mBufferRecords(std::move(bufferRecords)),
+        mOfflineReqs(offlineReqs),
+        mSession(offlineSession),
+        mTagMonitor(offlineStates.mTagMonitor),
+        mVendorTagId(offlineStates.mVendorTagId),
+        mUseHalBufManager(offlineStates.mUseHalBufManager),
+        mNeedFixupMonochromeTags(offlineStates.mNeedFixupMonochromeTags),
+        mUsePartialResult(offlineStates.mUsePartialResult),
+        mNumPartialResults(offlineStates.mNumPartialResults),
+        mLastCompletedRegularFrameNumber(offlineStates.mLastCompletedRegularFrameNumber),
+        mLastCompletedReprocessFrameNumber(offlineStates.mLastCompletedReprocessFrameNumber),
+        mLastCompletedZslFrameNumber(offlineStates.mLastCompletedZslFrameNumber),
+        mNextResultFrameNumber(offlineStates.mNextResultFrameNumber),
+        mNextReprocessResultFrameNumber(offlineStates.mNextReprocessResultFrameNumber),
+        mNextZslStillResultFrameNumber(offlineStates.mNextZslStillResultFrameNumber),
+        mNextShutterFrameNumber(offlineStates.mNextShutterFrameNumber),
+        mNextReprocessShutterFrameNumber(offlineStates.mNextReprocessShutterFrameNumber),
+        mNextZslStillShutterFrameNumber(offlineStates.mNextZslStillShutterFrameNumber),
+        mDeviceInfo(offlineStates.mDeviceInfo),
+        mPhysicalDeviceInfoMap(offlineStates.mPhysicalDeviceInfoMap),
+        mDistortionMappers(offlineStates.mDistortionMappers),
+        mZoomRatioMappers(offlineStates.mZoomRatioMappers),
+        mRotateAndCropMappers(offlineStates.mRotateAndCropMappers),
+        mStatus(STATUS_UNINITIALIZED) {
+    ATRACE_CALL();
+    ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
+}
+
+Camera3OfflineSession::~Camera3OfflineSession() {
+    ATRACE_CALL();
+    ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
+    disconnectImpl();
+}
+
+const String8& Camera3OfflineSession::getId() const {
+    return mId;
+}
+
+status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
+    ATRACE_CALL();
+
+    if (mSession == nullptr) {
+        ALOGE("%s: HIDL session is null!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+
+        mListener = listener;
+
+        // setup result FMQ
+        std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
+        auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
+            [&resQueue](const auto& descriptor) {
+                resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+                if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+                    ALOGE("HAL returns empty result metadata fmq, not use it");
+                    resQueue = nullptr;
+                    // Don't use resQueue onwards.
+                }
+            });
+        if (!resultQueueRet.isOk()) {
+            ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+                    resultQueueRet.description().c_str());
+            return DEAD_OBJECT;
+        }
+        mStatus = STATUS_ACTIVE;
+    }
+
+    mSession->setCallback(this);
+
+    return OK;
+}
+
+status_t Camera3OfflineSession::dump(int /*fd*/) {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> il(mInterfaceLock);
+    return OK;
+}
+
+status_t Camera3OfflineSession::disconnect() {
+    ATRACE_CALL();
+    return disconnectImpl();
+}
+
+status_t Camera3OfflineSession::disconnectImpl() {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> il(mInterfaceLock);
+
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus == STATUS_CLOSED) {
+            return OK; // don't close twice
+        } else if (mStatus == STATUS_ERROR) {
+            ALOGE("%s: offline session %s shutting down in error state",
+                    __FUNCTION__, mId.string());
+        }
+        listener = mListener.promote();
+    }
+
+    ALOGV("%s: E", __FUNCTION__);
+
+    {
+        std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
+        mAllowRequestBuffer = false;
+    }
+
+    std::vector<wp<Camera3StreamInterface>> streams;
+    streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        streams.push_back(mOutputStreams[i]);
+    }
+    if (mInputStream != nullptr) {
+        streams.push_back(mInputStream);
+    }
+
+    if (mSession != nullptr) {
+        mSession->close();
+    }
+
+    FlushInflightReqStates states {
+        mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
+        listener, *this, mBufferRecords, *this};
+
+    camera3::flushInflightRequests(states);
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        mSession.clear();
+        mOutputStreams.clear();
+        mInputStream.clear();
+        mStatus = STATUS_CLOSED;
+    }
+
+    for (auto& weakStream : streams) {
+        sp<Camera3StreamInterface> stream = weakStream.promote();
+        if (stream != nullptr) {
+            ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+                    __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+        }
+    }
+
+    ALOGV("%s: X", __FUNCTION__);
+    return OK;
+}
+
+status_t Camera3OfflineSession::waitForNextFrame(nsecs_t timeout) {
+    ATRACE_CALL();
+    std::unique_lock<std::mutex> lk(mOutputLock);
+
+    while (mResultQueue.empty()) {
+        auto st = mResultSignal.wait_for(lk, std::chrono::nanoseconds(timeout));
+        if (st == std::cv_status::timeout) {
+            return TIMED_OUT;
+        }
+    }
+    return OK;
+}
+
+status_t Camera3OfflineSession::getNextResult(CaptureResult* frame) {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> l(mOutputLock);
+
+    if (mResultQueue.empty()) {
+        return NOT_ENOUGH_DATA;
+    }
+
+    if (frame == nullptr) {
+        ALOGE("%s: argument cannot be NULL", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    CaptureResult &result = *(mResultQueue.begin());
+    frame->mResultExtras = result.mResultExtras;
+    frame->mMetadata.acquire(result.mMetadata);
+    frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
+    mResultQueue.erase(mResultQueue.begin());
+
+    return OK;
+}
+
+hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
+        const hardware::hidl_vec<
+                hardware::camera::device::V3_4::CaptureResult>& results) {
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return hardware::Void();
+        }
+        listener = mListener.promote();
+    }
+
+    CaptureOutputStates states {
+        mId,
+        mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
+    };
+
+    std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+    for (const auto& result : results) {
+        processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
+    }
+    return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::processCaptureResult(
+        const hardware::hidl_vec<
+                hardware::camera::device::V3_2::CaptureResult>& results) {
+    // TODO: changed impl to call into processCaptureResult_3_4 instead?
+    //       might need to figure how to reduce copy though.
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return hardware::Void();
+        }
+        listener = mListener.promote();
+    }
+
+    hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
+
+    CaptureOutputStates states {
+        mId,
+        mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
+    };
+
+    std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+    for (const auto& result : results) {
+        processOneCaptureResultLocked(states, result, noPhysMetadata);
+    }
+    return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::notify(
+        const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return hardware::Void();
+        }
+        listener = mListener.promote();
+    }
+
+    CaptureOutputStates states {
+        mId,
+        mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
+    };
+    for (const auto& msg : msgs) {
+        camera3::notify(states, msg);
+    }
+    return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
+        const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+        requestStreamBuffers_cb _hidl_cb) {
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return hardware::Void();
+        }
+    }
+
+    RequestBufferStates states {
+        mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
+        *this, mBufferRecords, *this};
+    camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
+    return hardware::Void();
+}
+
+hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
+        const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return hardware::Void();
+        }
+    }
+
+    ReturnBufferStates states {
+        mId, mUseHalBufManager, mOutputStreams, mBufferRecords};
+    camera3::returnStreamBuffers(states, buffers);
+    return hardware::Void();
+}
+
+void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> lock(mLock);
+    va_list args;
+    va_start(args, fmt);
+
+    setErrorStateLockedV(fmt, args);
+
+    va_end(args);
+
+    //FIXME: automatically disconnect here?
+}
+
+void Camera3OfflineSession::setErrorStateLocked(const char *fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+
+    setErrorStateLockedV(fmt, args);
+
+    va_end(args);
+}
+
+void Camera3OfflineSession::setErrorStateLockedV(const char *fmt, va_list args) {
+    // Print out all error messages to log
+    String8 errorCause = String8::formatV(fmt, args);
+    ALOGE("Camera %s: %s", mId.string(), errorCause.string());
+
+    // But only do error state transition steps for the first error
+    if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
+
+    mErrorCause = errorCause;
+
+    mStatus = STATUS_ERROR;
+
+    // Notify upstream about a device error
+    sp<NotificationListener> listener = mListener.promote();
+    if (listener != NULL) {
+        listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                CaptureResultExtras());
+    }
+
+    // Save stack trace. View by dumping it later.
+    CameraTraces::saveTrace();
+}
+
+void Camera3OfflineSession::onInflightEntryRemovedLocked(nsecs_t /*duration*/) {
+    if (mOfflineReqs.size() == 0) {
+        std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
+        mAllowRequestBuffer = false;
+    }
+}
+
+void Camera3OfflineSession::checkInflightMapLengthLocked() {
+    // Intentional empty impl.
+}
+
+void Camera3OfflineSession::onInflightMapFlushedLocked() {
+    // Intentional empty impl.
+}
+
+bool Camera3OfflineSession::startRequestBuffer() {
+    return mAllowRequestBuffer;
+}
+
+void Camera3OfflineSession::endRequestBuffer() {
+    // Intentional empty impl.
+}
+
+nsecs_t Camera3OfflineSession::getWaitDuration() {
+    const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
+    return kBaseGetBufferWait;
+}
+
+void Camera3OfflineSession::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
+    mBufferRecords.getInflightBufferKeys(out);
+}
+
+void Camera3OfflineSession::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
+    mBufferRecords.getInflightRequestBufferKeys(out);
+}
+
+std::vector<sp<Camera3StreamInterface>> Camera3OfflineSession::getAllStreams() {
+    std::vector<sp<Camera3StreamInterface>> ret;
+    bool hasInputStream = mInputStream != nullptr;
+    ret.reserve(mOutputStreams.size() + ((hasInputStream) ? 1 : 0));
+    if (hasInputStream) {
+        ret.push_back(mInputStream);
+    }
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        ret.push_back(mOutputStreams[i]);
+    }
+    return ret;
+}
+
+const CameraMetadata& Camera3OfflineSession::info() const {
+    return mDeviceInfo;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
new file mode 100644
index 0000000..c4c7a85
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
+#define ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
+
+#include <memory>
+#include <mutex>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
+
+#include <fmq/MessageQueue.h>
+
+#include "common/CameraOfflineSessionBase.h"
+
+#include "device3/Camera3BufferManager.h"
+#include "device3/DistortionMapper.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3OutputUtils.h"
+#include "device3/RotateAndCropMapper.h"
+#include "device3/ZoomRatioMapper.h"
+#include "utils/TagMonitor.h"
+#include "utils/LatencyHistogram.h"
+#include <camera_metadata_hidden.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3Stream;
+class Camera3OutputStreamInterface;
+class Camera3StreamInterface;
+
+} // namespace camera3
+
+
+// An immutable struct containing general states that will be copied from Camera3Device to
+// Camera3OfflineSession
+struct Camera3OfflineStates {
+    Camera3OfflineStates(
+            const TagMonitor& tagMonitor, const metadata_vendor_id_t vendorTagId,
+            const bool useHalBufManager, const bool needFixupMonochromeTags,
+            const bool usePartialResult, const uint32_t numPartialResults,
+            const int64_t lastCompletedRegularFN, const int64_t lastCompletedReprocessFN,
+            const int64_t lastCompletedZslFN, const uint32_t nextResultFN,
+            const uint32_t nextReprocResultFN, const uint32_t nextZslResultFN,
+            const uint32_t nextShutterFN, const uint32_t nextReprocShutterFN,
+            const uint32_t nextZslShutterFN, const CameraMetadata& deviceInfo,
+            const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap,
+            const std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers,
+            const std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers,
+            const std::unordered_map<std::string, camera3::RotateAndCropMapper>&
+                rotateAndCropMappers) :
+            mTagMonitor(tagMonitor), mVendorTagId(vendorTagId),
+            mUseHalBufManager(useHalBufManager), mNeedFixupMonochromeTags(needFixupMonochromeTags),
+            mUsePartialResult(usePartialResult), mNumPartialResults(numPartialResults),
+            mLastCompletedRegularFrameNumber(lastCompletedRegularFN),
+            mLastCompletedReprocessFrameNumber(lastCompletedReprocessFN),
+            mLastCompletedZslFrameNumber(lastCompletedZslFN),
+            mNextResultFrameNumber(nextResultFN),
+            mNextReprocessResultFrameNumber(nextReprocResultFN),
+            mNextZslStillResultFrameNumber(nextZslResultFN),
+            mNextShutterFrameNumber(nextShutterFN),
+            mNextReprocessShutterFrameNumber(nextReprocShutterFN),
+            mNextZslStillShutterFrameNumber(nextZslShutterFN),
+            mDeviceInfo(deviceInfo),
+            mPhysicalDeviceInfoMap(physicalDeviceInfoMap),
+            mDistortionMappers(distortionMappers),
+            mZoomRatioMappers(zoomRatioMappers),
+            mRotateAndCropMappers(rotateAndCropMappers) {}
+
+    const TagMonitor& mTagMonitor;
+    const metadata_vendor_id_t mVendorTagId;
+
+    const bool mUseHalBufManager;
+    const bool mNeedFixupMonochromeTags;
+
+    const bool mUsePartialResult;
+    const uint32_t mNumPartialResults;
+
+    // The last completed (buffers, result metadata, and error notify) regular
+    // request frame number
+    const int64_t mLastCompletedRegularFrameNumber;
+    // The last completed (buffers, result metadata, and error notify) reprocess
+    // request frame number
+    const int64_t mLastCompletedReprocessFrameNumber;
+    // The last completed (buffers, result metadata, and error notify) zsl
+    // request frame number
+    const int64_t mLastCompletedZslFrameNumber;
+    // the minimal frame number of the next non-reprocess result
+    const uint32_t mNextResultFrameNumber;
+    // the minimal frame number of the next reprocess result
+    const uint32_t mNextReprocessResultFrameNumber;
+    // the minimal frame number of the next ZSL still capture result
+    const uint32_t mNextZslStillResultFrameNumber;
+    // the minimal frame number of the next non-reprocess shutter
+    const uint32_t mNextShutterFrameNumber;
+    // the minimal frame number of the next reprocess shutter
+    const uint32_t mNextReprocessShutterFrameNumber;
+    // the minimal frame number of the next ZSL still capture shutter
+    const uint32_t mNextZslStillShutterFrameNumber;
+
+    const CameraMetadata& mDeviceInfo;
+
+    const std::unordered_map<std::string, CameraMetadata>& mPhysicalDeviceInfoMap;
+
+    const std::unordered_map<std::string, camera3::DistortionMapper>& mDistortionMappers;
+
+    const std::unordered_map<std::string, camera3::ZoomRatioMapper>& mZoomRatioMappers;
+
+    const std::unordered_map<std::string, camera3::RotateAndCropMapper>& mRotateAndCropMappers;
+};
+
+/**
+ * Camera3OfflineSession for offline session defined in HIDL ICameraOfflineSession@3.6 or higher
+ */
+class Camera3OfflineSession :
+            public CameraOfflineSessionBase,
+            virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
+            public camera3::SetErrorInterface,
+            public camera3::InflightRequestUpdateInterface,
+            public camera3::RequestBufferInterface,
+            public camera3::FlushBufferInterface {
+  public:
+
+    // initialize by Camera3Device.
+    explicit Camera3OfflineSession(const String8& id,
+            const sp<camera3::Camera3Stream>& inputStream,
+            const camera3::StreamSet& offlineStreamSet,
+            camera3::BufferRecords&& bufferRecords,
+            const camera3::InFlightRequestMap& offlineReqs,
+            const Camera3OfflineStates& offlineStates,
+            sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession);
+
+    virtual ~Camera3OfflineSession();
+
+    virtual status_t initialize(wp<NotificationListener> listener) override;
+
+    /**
+     * CameraOfflineSessionBase interface
+     */
+    status_t disconnect() override;
+    status_t dump(int fd) override;
+
+    /**
+     * FrameProducer interface
+     */
+    const String8& getId() const override;
+    const CameraMetadata& info() const override;
+    status_t waitForNextFrame(nsecs_t timeout) override;
+    status_t getNextResult(CaptureResult *frame) override;
+
+    // TODO: methods for notification (error/idle/finished etc) passing
+
+    /**
+     * End of CameraOfflineSessionBase interface
+     */
+
+    /**
+     * HIDL ICameraDeviceCallback interface
+     */
+
+    /**
+     * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+     */
+
+    hardware::Return<void> processCaptureResult_3_4(
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_4::CaptureResult>& results) override;
+    hardware::Return<void> processCaptureResult(
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_2::CaptureResult>& results) override;
+    hardware::Return<void> notify(
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+    hardware::Return<void> requestStreamBuffers(
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+            requestStreamBuffers_cb _hidl_cb) override;
+
+    hardware::Return<void> returnStreamBuffers(
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+    /**
+     * End of CameraOfflineSessionBase interface
+     */
+
+  private:
+    // Camera device ID
+    const String8 mId;
+    sp<camera3::Camera3Stream> mInputStream;
+    camera3::StreamSet mOutputStreams;
+    camera3::BufferRecords mBufferRecords;
+
+    std::mutex mOfflineReqsLock;
+    camera3::InFlightRequestMap mOfflineReqs;
+
+    sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
+
+    TagMonitor mTagMonitor;
+    const metadata_vendor_id_t mVendorTagId;
+
+    const bool mUseHalBufManager;
+    const bool mNeedFixupMonochromeTags;
+
+    const bool mUsePartialResult;
+    const uint32_t mNumPartialResults;
+
+    std::mutex mOutputLock;
+    std::list<CaptureResult> mResultQueue;
+    std::condition_variable mResultSignal;
+    // the last completed frame number of regular requests
+    int64_t mLastCompletedRegularFrameNumber;
+    // the last completed frame number of reprocess requests
+    int64_t mLastCompletedReprocessFrameNumber;
+    // the last completed frame number of ZSL still capture requests
+    int64_t mLastCompletedZslFrameNumber;
+    // the minimal frame number of the next non-reprocess result
+    uint32_t mNextResultFrameNumber;
+    // the minimal frame number of the next reprocess result
+    uint32_t mNextReprocessResultFrameNumber;
+    // the minimal frame number of the next ZSL still capture result
+    uint32_t mNextZslStillResultFrameNumber;
+    // the minimal frame number of the next non-reprocess shutter
+    uint32_t mNextShutterFrameNumber;
+    // the minimal frame number of the next reprocess shutter
+    uint32_t mNextReprocessShutterFrameNumber;
+    // the minimal frame number of the next ZSL still capture shutter
+    uint32_t mNextZslStillShutterFrameNumber;
+    // End of mOutputLock scope
+
+    const CameraMetadata mDeviceInfo;
+    std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
+
+    std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;
+
+    std::unordered_map<std::string, camera3::ZoomRatioMapper> mZoomRatioMappers;
+
+    std::unordered_map<std::string, camera3::RotateAndCropMapper> mRotateAndCropMappers;
+
+    mutable std::mutex mLock;
+
+    enum Status {
+        STATUS_UNINITIALIZED = 0,
+        STATUS_ACTIVE,
+        STATUS_ERROR,
+        STATUS_CLOSED
+    } mStatus;
+
+    wp<NotificationListener> mListener;
+    // End of mLock protect scope
+
+    std::mutex mProcessCaptureResultLock;
+    // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+    std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+    // Tracking cause of fatal errors when in STATUS_ERROR
+    String8 mErrorCause;
+
+    // Lock to ensure requestStreamBuffers() callbacks are serialized
+    std::mutex mRequestBufferInterfaceLock;
+    // allow request buffer until all requests are processed or disconnectImpl is called
+    bool mAllowRequestBuffer = true;
+
+    // For client methods such as disconnect/dump
+    std::mutex mInterfaceLock;
+
+    // SetErrorInterface
+    void setErrorState(const char *fmt, ...) override;
+    void setErrorStateLocked(const char *fmt, ...) override;
+
+    // InflightRequestUpdateInterface
+    void onInflightEntryRemovedLocked(nsecs_t duration) override;
+    void checkInflightMapLengthLocked() override;
+    void onInflightMapFlushedLocked() override;
+
+    // RequestBufferInterface
+    bool startRequestBuffer() override;
+    void endRequestBuffer() override;
+    nsecs_t getWaitDuration() override;
+
+    // FlushBufferInterface
+    void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) override;
+    void getInflightRequestBufferKeys(std::vector<uint64_t>* out) override;
+    std::vector<sp<camera3::Camera3StreamInterface>> getAllStreams() override;
+
+    void setErrorStateLockedV(const char *fmt, va_list args);
+
+    status_t disconnectImpl();
+}; // class Camera3OfflineSession
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3OutputInterface.h b/services/camera/libcameraservice/device3/Camera3OutputInterface.h
new file mode 100644
index 0000000..8817833
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputInterface.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA3_OUTPUT_INTERFACE_H
+#define ANDROID_SERVERS_CAMERA3_OUTPUT_INTERFACE_H
+
+#include <memory>
+
+#include <cutils/native_handle.h>
+
+#include <utils/Timers.h>
+
+#include "device3/Camera3StreamInterface.h"
+
+namespace android {
+
+namespace camera3 {
+
+    /**
+     * Interfaces used by result/notification path shared between Camera3Device and
+     * Camera3OfflineSession
+     */
+    class SetErrorInterface {
+    public:
+        // Switch device into error state and send a ERROR_DEVICE notification
+        virtual void setErrorState(const char *fmt, ...) = 0;
+        // Same as setErrorState except this method assumes callers holds the main object lock
+        virtual void setErrorStateLocked(const char *fmt, ...) = 0;
+
+        virtual ~SetErrorInterface() {}
+    };
+
+    // Interface used by callback path to update buffer records
+    class BufferRecordsInterface {
+    public:
+        // method to extract buffer's unique ID
+        // return pair of (newlySeenBuffer?, bufferId)
+        virtual std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId) = 0;
+
+        // Find a buffer_handle_t based on frame number and stream ID
+        virtual status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
+                /*out*/ buffer_handle_t **buffer) = 0;
+
+        // Register a bufId (streamId, buffer_handle_t) to inflight request buffer
+        virtual status_t pushInflightRequestBuffer(
+                uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) = 0;
+
+        // Find a buffer_handle_t based on bufferId
+        virtual status_t popInflightRequestBuffer(uint64_t bufferId,
+                /*out*/ buffer_handle_t** buffer,
+                /*optional out*/ int32_t* streamId = nullptr) = 0;
+
+        virtual ~BufferRecordsInterface() {}
+    };
+
+    class InflightRequestUpdateInterface {
+    public:
+        // Caller must hold the lock proctecting InflightRequestMap
+        // duration: the maxExpectedDuration of the removed entry
+        virtual void onInflightEntryRemovedLocked(nsecs_t duration) = 0;
+
+        virtual void checkInflightMapLengthLocked() = 0;
+
+        virtual void onInflightMapFlushedLocked() = 0;
+
+        virtual ~InflightRequestUpdateInterface() {}
+    };
+
+    class RequestBufferInterface {
+    public:
+        // Return if the state machine currently allows for requestBuffers.
+        // If this returns true, caller must call endRequestBuffer() later to signal end of a
+        // request buffer transaction.
+        virtual bool startRequestBuffer() = 0;
+
+        virtual void endRequestBuffer() = 0;
+
+        // Returns how long should implementation wait for a buffer returned
+        virtual nsecs_t getWaitDuration() = 0;
+
+        virtual ~RequestBufferInterface() {}
+    };
+
+    class FlushBufferInterface {
+    public:
+        virtual void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) = 0;
+
+        virtual void getInflightRequestBufferKeys(std::vector<uint64_t>* out) = 0;
+
+        virtual std::vector<sp<Camera3StreamInterface>> getAllStreams() = 0;
+
+        virtual ~FlushBufferInterface() {}
+    };
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index e1d35e8..01ca006 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include "Camera3OutputStream.h"
+#include "utils/TraceHFR.h"
 
 #ifndef container_of
 #define container_of(ptr, type, member) \
@@ -160,7 +161,7 @@
 
 status_t Camera3OutputStream::getBufferLocked(camera3_stream_buffer *buffer,
         const std::vector<size_t>&) {
-    ATRACE_CALL();
+    ATRACE_HFR_CALL();
 
     ANativeWindowBuffer* anb;
     int fenceFd = -1;
@@ -190,7 +191,7 @@
 status_t Camera3OutputStream::returnBufferLocked(
         const camera3_stream_buffer &buffer,
         nsecs_t timestamp, const std::vector<size_t>& surface_ids) {
-    ATRACE_CALL();
+    ATRACE_HFR_CALL();
 
     status_t res = returnAnyBufferLocked(buffer, timestamp, /*output*/true, surface_ids);
 
@@ -516,7 +517,7 @@
 }
 
 status_t Camera3OutputStream::getBufferLockedCommon(ANativeWindowBuffer** anb, int* fenceFd) {
-    ATRACE_CALL();
+    ATRACE_HFR_CALL();
     status_t res;
 
     if ((res = getBufferPreconditionCheckLocked()) != OK) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.cpp b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.cpp
new file mode 100644
index 0000000..64af91e
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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_TAG "Camera3-OutStrmIntf"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+
+#include "Camera3OutputStreamInterface.h"
+
+namespace android {
+
+namespace camera3 {
+
+status_t StreamSet::add(
+        int streamId, sp<camera3::Camera3OutputStreamInterface> stream) {
+    if (stream == nullptr) {
+        ALOGE("%s: cannot add null stream", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    std::lock_guard<std::mutex> lock(mLock);
+    return mData.add(streamId, stream);
+}
+
+ssize_t StreamSet::remove(int streamId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mData.removeItem(streamId);
+}
+
+sp<camera3::Camera3OutputStreamInterface> StreamSet::get(int streamId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mData.indexOfKey(streamId);
+    if (idx == NAME_NOT_FOUND) {
+        return nullptr;
+    }
+    return mData.editValueAt(idx);
+}
+
+sp<camera3::Camera3OutputStreamInterface> StreamSet::operator[] (size_t index) {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mData.editValueAt(index);
+}
+
+size_t StreamSet::size() const {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mData.size();
+}
+
+void StreamSet::clear() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mData.clear();
+}
+
+std::vector<int> StreamSet::getStreamIds() {
+    std::lock_guard<std::mutex> lock(mLock);
+    std::vector<int> streamIds(mData.size());
+    for (size_t i = 0; i < mData.size(); i++) {
+        streamIds[i] = mData.keyAt(i);
+    }
+    return streamIds;
+}
+
+StreamSet::StreamSet(const StreamSet& other) {
+    std::lock_guard<std::mutex> lock(other.mLock);
+    mData = other.mData;
+}
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 2bde949..7f5c87a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -97,6 +97,26 @@
     virtual const String8& getPhysicalCameraId() const = 0;
 };
 
+// Helper class to organize a synchronized mapping of stream IDs to stream instances
+class StreamSet {
+  public:
+    status_t add(int streamId, sp<camera3::Camera3OutputStreamInterface>);
+    ssize_t remove(int streamId);
+    sp<camera3::Camera3OutputStreamInterface> get(int streamId);
+    // get by (underlying) vector index
+    sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index);
+    size_t size() const;
+    std::vector<int> getStreamIds();
+    void clear();
+
+    StreamSet() {};
+    StreamSet(const StreamSet& other);
+
+  private:
+    mutable std::mutex mLock;
+    KeyedVector<int, sp<camera3::Camera3OutputStreamInterface>> mData;
+};
+
 } // namespace camera3
 
 } // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
new file mode 100644
index 0000000..eea5ef1
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -0,0 +1,1494 @@
+/*
+ * Copyright (C) 2019 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_TAG "Camera3-OutputUtils"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) states.setErrIntf.setErrorState(   \
+    "%s: " fmt, __FUNCTION__,                         \
+    ##__VA_ARGS__)
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+
+#include <camera_metadata_hidden.h>
+
+#include "device3/Camera3OutputUtils.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+status_t fixupMonochromeTags(
+        CaptureOutputStates& states,
+        const CameraMetadata& deviceInfo,
+        CameraMetadata& resultMetadata) {
+    status_t res = OK;
+    if (!states.needFixupMonoChrome) {
+        return res;
+    }
+
+    // Remove tags that are not applicable to monochrome camera.
+    int32_t tagsToRemove[] = {
+           ANDROID_SENSOR_GREEN_SPLIT,
+           ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+           ANDROID_COLOR_CORRECTION_MODE,
+           ANDROID_COLOR_CORRECTION_TRANSFORM,
+           ANDROID_COLOR_CORRECTION_GAINS,
+    };
+    for (auto tag : tagsToRemove) {
+        res = resultMetadata.erase(tag);
+        if (res != OK) {
+            ALOGE("%s: Failed to remove tag %d for monochrome camera", __FUNCTION__, tag);
+            return res;
+        }
+    }
+
+    // ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
+    camera_metadata_entry blEntry = resultMetadata.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
+    for (size_t i = 1; i < blEntry.count; i++) {
+        blEntry.data.f[i] = blEntry.data.f[0];
+    }
+
+    // ANDROID_SENSOR_NOISE_PROFILE
+    camera_metadata_entry npEntry = resultMetadata.find(ANDROID_SENSOR_NOISE_PROFILE);
+    if (npEntry.count > 0 && npEntry.count % 2 == 0) {
+        double np[] = {npEntry.data.d[0], npEntry.data.d[1]};
+        res = resultMetadata.update(ANDROID_SENSOR_NOISE_PROFILE, np, 2);
+        if (res != OK) {
+             ALOGE("%s: Failed to update SENSOR_NOISE_PROFILE: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+    }
+
+    // ANDROID_STATISTICS_LENS_SHADING_MAP
+    camera_metadata_ro_entry lsSizeEntry = deviceInfo.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+    camera_metadata_entry lsEntry = resultMetadata.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
+    if (lsSizeEntry.count == 2 && lsEntry.count > 0
+            && (int32_t)lsEntry.count == 4 * lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]) {
+        for (int32_t i = 0; i < lsSizeEntry.data.i32[0] * lsSizeEntry.data.i32[1]; i++) {
+            lsEntry.data.f[4*i+1] = lsEntry.data.f[4*i];
+            lsEntry.data.f[4*i+2] = lsEntry.data.f[4*i];
+            lsEntry.data.f[4*i+3] = lsEntry.data.f[4*i];
+        }
+    }
+
+    // ANDROID_TONEMAP_CURVE_BLUE
+    // ANDROID_TONEMAP_CURVE_GREEN
+    // ANDROID_TONEMAP_CURVE_RED
+    camera_metadata_entry tcbEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_BLUE);
+    camera_metadata_entry tcgEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_GREEN);
+    camera_metadata_entry tcrEntry = resultMetadata.find(ANDROID_TONEMAP_CURVE_RED);
+    if (tcbEntry.count > 0
+            && tcbEntry.count == tcgEntry.count
+            && tcbEntry.count == tcrEntry.count) {
+        for (size_t i = 0; i < tcbEntry.count; i++) {
+            tcbEntry.data.f[i] = tcrEntry.data.f[i];
+            tcgEntry.data.f[i] = tcrEntry.data.f[i];
+        }
+    }
+
+    return res;
+}
+
+void insertResultLocked(CaptureOutputStates& states, CaptureResult *result, uint32_t frameNumber) {
+    if (result == nullptr) return;
+
+    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+            result->mMetadata.getAndLock());
+    set_camera_metadata_vendor_id(meta, states.vendorTagId);
+    result->mMetadata.unlock(meta);
+
+    if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
+            (int32_t*)&frameNumber, 1) != OK) {
+        SET_ERR("Failed to set frame number %d in metadata", frameNumber);
+        return;
+    }
+
+    if (result->mMetadata.update(ANDROID_REQUEST_ID, &result->mResultExtras.requestId, 1) != OK) {
+        SET_ERR("Failed to set request ID in metadata for frame %d", frameNumber);
+        return;
+    }
+
+    // Update vendor tag id for physical metadata
+    for (auto& physicalMetadata : result->mPhysicalMetadatas) {
+        camera_metadata_t *pmeta = const_cast<camera_metadata_t *>(
+                physicalMetadata.mPhysicalCameraMetadata.getAndLock());
+        set_camera_metadata_vendor_id(pmeta, states.vendorTagId);
+        physicalMetadata.mPhysicalCameraMetadata.unlock(pmeta);
+    }
+
+    // Valid result, insert into queue
+    std::list<CaptureResult>::iterator queuedResult =
+            states.resultQueue.insert(states.resultQueue.end(), CaptureResult(*result));
+    ALOGV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+           ", burstId = %" PRId32, __FUNCTION__,
+           queuedResult->mResultExtras.requestId,
+           queuedResult->mResultExtras.frameNumber,
+           queuedResult->mResultExtras.burstId);
+
+    states.resultSignal.notify_one();
+}
+
+
+void sendPartialCaptureResult(CaptureOutputStates& states,
+        const camera_metadata_t * partialResult,
+        const CaptureResultExtras &resultExtras, uint32_t frameNumber) {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> l(states.outputLock);
+
+    CaptureResult captureResult;
+    captureResult.mResultExtras = resultExtras;
+    captureResult.mMetadata = partialResult;
+
+    // Fix up result metadata for monochrome camera.
+    status_t res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
+    if (res != OK) {
+        SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
+        return;
+    }
+
+    insertResultLocked(states, &captureResult, frameNumber);
+}
+
+void sendCaptureResult(
+        CaptureOutputStates& states,
+        CameraMetadata &pendingMetadata,
+        CaptureResultExtras &resultExtras,
+        CameraMetadata &collectedPartialResult,
+        uint32_t frameNumber,
+        bool reprocess, bool zslStillCapture, bool rotateAndCropAuto,
+        const std::set<std::string>& cameraIdsWithZoom,
+        const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas) {
+    ATRACE_CALL();
+    if (pendingMetadata.isEmpty())
+        return;
+
+    std::lock_guard<std::mutex> l(states.outputLock);
+
+    // TODO: need to track errors for tighter bounds on expected frame number
+    if (reprocess) {
+        if (frameNumber < states.nextReprocResultFrameNum) {
+            SET_ERR("Out-of-order reprocess capture result metadata submitted! "
+                "(got frame number %d, expecting %d)",
+                frameNumber, states.nextReprocResultFrameNum);
+            return;
+        }
+        states.nextReprocResultFrameNum = frameNumber + 1;
+    } else if (zslStillCapture) {
+        if (frameNumber < states.nextZslResultFrameNum) {
+            SET_ERR("Out-of-order ZSL still capture result metadata submitted! "
+                "(got frame number %d, expecting %d)",
+                frameNumber, states.nextZslResultFrameNum);
+            return;
+        }
+        states.nextZslResultFrameNum = frameNumber + 1;
+    } else {
+        if (frameNumber < states.nextResultFrameNum) {
+            SET_ERR("Out-of-order capture result metadata submitted! "
+                    "(got frame number %d, expecting %d)",
+                    frameNumber, states.nextResultFrameNum);
+            return;
+        }
+        states.nextResultFrameNum = frameNumber + 1;
+    }
+
+    CaptureResult captureResult;
+    captureResult.mResultExtras = resultExtras;
+    captureResult.mMetadata = pendingMetadata;
+    captureResult.mPhysicalMetadatas = physicalMetadatas;
+
+    // Append any previous partials to form a complete result
+    if (states.usePartialResult && !collectedPartialResult.isEmpty()) {
+        captureResult.mMetadata.append(collectedPartialResult);
+    }
+
+    captureResult.mMetadata.sort();
+
+    // Check that there's a timestamp in the result metadata
+    camera_metadata_entry timestamp = captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
+    if (timestamp.count == 0) {
+        SET_ERR("No timestamp provided by HAL for frame %d!",
+                frameNumber);
+        return;
+    }
+    nsecs_t sensorTimestamp = timestamp.data.i64[0];
+
+    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+        camera_metadata_entry timestamp =
+                physicalMetadata.mPhysicalCameraMetadata.find(ANDROID_SENSOR_TIMESTAMP);
+        if (timestamp.count == 0) {
+            SET_ERR("No timestamp provided by HAL for physical camera %s frame %d!",
+                    String8(physicalMetadata.mPhysicalCameraId).c_str(), frameNumber);
+            return;
+        }
+    }
+
+    // Fix up some result metadata to account for HAL-level distortion correction
+    status_t res = OK;
+    auto iter = states.distortionMappers.find(states.cameraId.c_str());
+    if (iter != states.distortionMappers.end()) {
+        res = iter->second.correctCaptureResult(&captureResult.mMetadata);
+        if (res != OK) {
+            SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
+                    frameNumber, strerror(-res), res);
+            return;
+        }
+    }
+
+    // Fix up result metadata to account for zoom ratio availabilities between
+    // HAL and app.
+    bool zoomRatioIs1 = cameraIdsWithZoom.find(states.cameraId.c_str()) == cameraIdsWithZoom.end();
+    res = states.zoomRatioMappers[states.cameraId.c_str()].updateCaptureResult(
+            &captureResult.mMetadata, zoomRatioIs1);
+    if (res != OK) {
+        SET_ERR("Failed to update capture result zoom ratio metadata for frame %d: %s (%d)",
+                frameNumber, strerror(-res), res);
+        return;
+    }
+
+    // Fix up result metadata to account for rotateAndCrop in AUTO mode
+    if (rotateAndCropAuto) {
+        auto mapper = states.rotateAndCropMappers.find(states.cameraId.c_str());
+        if (mapper != states.rotateAndCropMappers.end()) {
+            res = mapper->second.updateCaptureResult(
+                    &captureResult.mMetadata);
+            if (res != OK) {
+                SET_ERR("Unable to correct capture result rotate-and-crop for frame %d: %s (%d)",
+                        frameNumber, strerror(-res), res);
+                return;
+            }
+        }
+    }
+
+    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
+        auto mapper = states.distortionMappers.find(cameraId8.c_str());
+        if (mapper != states.distortionMappers.end()) {
+            res = mapper->second.correctCaptureResult(
+                    &physicalMetadata.mPhysicalCameraMetadata);
+            if (res != OK) {
+                SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
+                        frameNumber, strerror(-res), res);
+                return;
+            }
+        }
+
+        zoomRatioIs1 = cameraIdsWithZoom.find(cameraId8.c_str()) == cameraIdsWithZoom.end();
+        res = states.zoomRatioMappers[cameraId8.c_str()].updateCaptureResult(
+                &physicalMetadata.mPhysicalCameraMetadata, zoomRatioIs1);
+        if (res != OK) {
+            SET_ERR("Failed to update camera %s's physical zoom ratio metadata for "
+                    "frame %d: %s(%d)", cameraId8.c_str(), frameNumber, strerror(-res), res);
+            return;
+        }
+    }
+
+    // Fix up result metadata for monochrome camera.
+    res = fixupMonochromeTags(states, states.deviceInfo, captureResult.mMetadata);
+    if (res != OK) {
+        SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
+        return;
+    }
+    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
+        res = fixupMonochromeTags(states,
+                states.physicalDeviceInfoMap.at(cameraId8.c_str()),
+                physicalMetadata.mPhysicalCameraMetadata);
+        if (res != OK) {
+            SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
+            return;
+        }
+    }
+
+    std::unordered_map<std::string, CameraMetadata> monitoredPhysicalMetadata;
+    for (auto& m : physicalMetadatas) {
+        monitoredPhysicalMetadata.emplace(String8(m.mPhysicalCameraId).string(),
+                CameraMetadata(m.mPhysicalCameraMetadata));
+    }
+    states.tagMonitor.monitorMetadata(TagMonitor::RESULT,
+            frameNumber, sensorTimestamp, captureResult.mMetadata,
+            monitoredPhysicalMetadata);
+
+    insertResultLocked(states, &captureResult, frameNumber);
+}
+
+// Reading one camera metadata from result argument via fmq or from the result
+// Assuming the fmq is protected by a lock already
+status_t readOneCameraMetadataLocked(
+        std::unique_ptr<ResultMetadataQueue>& fmq,
+        uint64_t fmqResultSize,
+        hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
+        const hardware::camera::device::V3_2::CameraMetadata& result) {
+    if (fmqResultSize > 0) {
+        resultMetadata.resize(fmqResultSize);
+        if (fmq == nullptr) {
+            return NO_MEMORY; // logged in initialize()
+        }
+        if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
+            ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
+                    __FUNCTION__, fmqResultSize);
+            return INVALID_OPERATION;
+        }
+    } else {
+        resultMetadata.setToExternal(const_cast<uint8_t *>(result.data()),
+                result.size());
+    }
+
+    if (resultMetadata.size() != 0) {
+        status_t res;
+        const camera_metadata_t* metadata =
+                reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+        size_t expected_metadata_size = resultMetadata.size();
+        if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
+            ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return INVALID_OPERATION;
+        }
+    }
+
+    return OK;
+}
+
+void removeInFlightMapEntryLocked(CaptureOutputStates& states, int idx) {
+    ATRACE_CALL();
+    InFlightRequestMap& inflightMap = states.inflightMap;
+    nsecs_t duration = inflightMap.valueAt(idx).maxExpectedDuration;
+    inflightMap.removeItemsAt(idx, 1);
+
+    states.inflightIntf.onInflightEntryRemovedLocked(duration);
+}
+
+void removeInFlightRequestIfReadyLocked(CaptureOutputStates& states, int idx) {
+    InFlightRequestMap& inflightMap = states.inflightMap;
+    const InFlightRequest &request = inflightMap.valueAt(idx);
+    const uint32_t frameNumber = inflightMap.keyAt(idx);
+
+    nsecs_t sensorTimestamp = request.sensorTimestamp;
+    nsecs_t shutterTimestamp = request.shutterTimestamp;
+
+    // Check if it's okay to remove the request from InFlightMap:
+    // In the case of a successful request:
+    //      all input and output buffers, all result metadata, shutter callback
+    //      arrived.
+    // In the case of an unsuccessful request:
+    //      all input and output buffers, as well as request/result error notifications, arrived.
+    if (request.numBuffersLeft == 0 &&
+            (request.skipResultMetadata ||
+            (request.haveResultMetadata && shutterTimestamp != 0))) {
+        if (request.stillCapture) {
+            ATRACE_ASYNC_END("still capture", frameNumber);
+        }
+
+        ATRACE_ASYNC_END("frame capture", frameNumber);
+
+        // Sanity check - if sensor timestamp matches shutter timestamp in the
+        // case of request having callback.
+        if (request.hasCallback && request.requestStatus == OK &&
+                sensorTimestamp != shutterTimestamp) {
+            SET_ERR("sensor timestamp (%" PRId64
+                ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
+                sensorTimestamp, frameNumber, shutterTimestamp);
+        }
+
+        // for an unsuccessful request, it may have pending output buffers to
+        // return.
+        assert(request.requestStatus != OK ||
+               request.pendingOutputBuffers.size() == 0);
+
+        returnOutputBuffers(
+            states.useHalBufManager, states.listener,
+            request.pendingOutputBuffers.array(),
+            request.pendingOutputBuffers.size(), 0, /*timestampIncreasing*/true,
+            request.outputSurfaces, request.resultExtras,
+            request.errorBufStrategy);
+
+        // Note down the just completed frame number
+        if (request.hasInputBuffer) {
+            states.lastCompletedReprocessFrameNumber = frameNumber;
+        } else if (request.zslCapture) {
+            states.lastCompletedZslFrameNumber = frameNumber;
+        } else {
+            states.lastCompletedRegularFrameNumber = frameNumber;
+        }
+
+        removeInFlightMapEntryLocked(states, idx);
+        ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
+    }
+
+    states.inflightIntf.checkInflightMapLengthLocked();
+}
+
+void processCaptureResult(CaptureOutputStates& states, const camera3_capture_result *result) {
+    ATRACE_CALL();
+
+    status_t res;
+
+    uint32_t frameNumber = result->frame_number;
+    if (result->result == NULL && result->num_output_buffers == 0 &&
+            result->input_buffer == NULL) {
+        SET_ERR("No result data provided by HAL for frame %d",
+                frameNumber);
+        return;
+    }
+
+    if (!states.usePartialResult &&
+            result->result != NULL &&
+            result->partial_result != 1) {
+        SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
+                " if partial result is not supported",
+                frameNumber, result->partial_result);
+        return;
+    }
+
+    bool isPartialResult = false;
+    CameraMetadata collectedPartialResult;
+    bool hasInputBufferInRequest = false;
+
+    // Get shutter timestamp and resultExtras from list of in-flight requests,
+    // where it was added by the shutter notification for this frame. If the
+    // shutter timestamp isn't received yet, append the output buffers to the
+    // in-flight request and they will be returned when the shutter timestamp
+    // arrives. Update the in-flight status and remove the in-flight entry if
+    // all result data and shutter timestamp have been received.
+    nsecs_t shutterTimestamp = 0;
+    {
+        std::lock_guard<std::mutex> l(states.inflightLock);
+        ssize_t idx = states.inflightMap.indexOfKey(frameNumber);
+        if (idx == NAME_NOT_FOUND) {
+            SET_ERR("Unknown frame number for capture result: %d",
+                    frameNumber);
+            return;
+        }
+        InFlightRequest &request = states.inflightMap.editValueAt(idx);
+        ALOGVV("%s: got InFlightRequest requestId = %" PRId32
+                ", frameNumber = %" PRId64 ", burstId = %" PRId32
+                ", partialResultCount = %d/%d, hasCallback = %d, num_output_buffers %d"
+                ", usePartialResult = %d",
+                __FUNCTION__, request.resultExtras.requestId,
+                request.resultExtras.frameNumber, request.resultExtras.burstId,
+                result->partial_result, states.numPartialResults,
+                request.hasCallback, result->num_output_buffers,
+                states.usePartialResult);
+        // Always update the partial count to the latest one if it's not 0
+        // (buffers only). When framework aggregates adjacent partial results
+        // into one, the latest partial count will be used.
+        if (result->partial_result != 0)
+            request.resultExtras.partialResultCount = result->partial_result;
+
+        // Check if this result carries only partial metadata
+        if (states.usePartialResult && result->result != NULL) {
+            if (result->partial_result > states.numPartialResults || result->partial_result < 1) {
+                SET_ERR("Result is malformed for frame %d: partial_result %u must be  in"
+                        " the range of [1, %d] when metadata is included in the result",
+                        frameNumber, result->partial_result, states.numPartialResults);
+                return;
+            }
+            isPartialResult = (result->partial_result < states.numPartialResults);
+            if (isPartialResult && result->num_physcam_metadata) {
+                SET_ERR("Result is malformed for frame %d: partial_result not allowed for"
+                        " physical camera result", frameNumber);
+                return;
+            }
+            if (isPartialResult) {
+                request.collectedPartialResult.append(result->result);
+            }
+
+            if (isPartialResult && request.hasCallback) {
+                // Send partial capture result
+                sendPartialCaptureResult(states, result->result, request.resultExtras,
+                        frameNumber);
+            }
+        }
+
+        shutterTimestamp = request.shutterTimestamp;
+        hasInputBufferInRequest = request.hasInputBuffer;
+
+        // Did we get the (final) result metadata for this capture?
+        if (result->result != NULL && !isPartialResult) {
+            if (request.physicalCameraIds.size() != result->num_physcam_metadata) {
+                SET_ERR("Expected physical Camera metadata count %d not equal to actual count %d",
+                        request.physicalCameraIds.size(), result->num_physcam_metadata);
+                return;
+            }
+            if (request.haveResultMetadata) {
+                SET_ERR("Called multiple times with metadata for frame %d",
+                        frameNumber);
+                return;
+            }
+            for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
+                String8 physicalId(result->physcam_ids[i]);
+                std::set<String8>::iterator cameraIdIter =
+                        request.physicalCameraIds.find(physicalId);
+                if (cameraIdIter != request.physicalCameraIds.end()) {
+                    request.physicalCameraIds.erase(cameraIdIter);
+                } else {
+                    SET_ERR("Total result for frame %d has already returned for camera %s",
+                            frameNumber, physicalId.c_str());
+                    return;
+                }
+            }
+            if (states.usePartialResult &&
+                    !request.collectedPartialResult.isEmpty()) {
+                collectedPartialResult.acquire(
+                    request.collectedPartialResult);
+            }
+            request.haveResultMetadata = true;
+            request.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
+        }
+
+        uint32_t numBuffersReturned = result->num_output_buffers;
+        if (result->input_buffer != NULL) {
+            if (hasInputBufferInRequest) {
+                numBuffersReturned += 1;
+            } else {
+                ALOGW("%s: Input buffer should be NULL if there is no input"
+                        " buffer sent in the request",
+                        __FUNCTION__);
+            }
+        }
+        request.numBuffersLeft -= numBuffersReturned;
+        if (request.numBuffersLeft < 0) {
+            SET_ERR("Too many buffers returned for frame %d",
+                    frameNumber);
+            return;
+        }
+
+        camera_metadata_ro_entry_t entry;
+        res = find_camera_metadata_ro_entry(result->result,
+                ANDROID_SENSOR_TIMESTAMP, &entry);
+        if (res == OK && entry.count == 1) {
+            request.sensorTimestamp = entry.data.i64[0];
+        }
+
+        // If shutter event isn't received yet, do not return the pending output
+        // buffers.
+        request.pendingOutputBuffers.appendArray(result->output_buffers,
+                result->num_output_buffers);
+        if (shutterTimestamp != 0) {
+            returnAndRemovePendingOutputBuffers(
+                states.useHalBufManager, states.listener,
+                request);
+        }
+
+        if (result->result != NULL && !isPartialResult) {
+            for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
+                CameraMetadata physicalMetadata;
+                physicalMetadata.append(result->physcam_metadata[i]);
+                request.physicalMetadatas.push_back({String16(result->physcam_ids[i]),
+                        physicalMetadata});
+            }
+            if (shutterTimestamp == 0) {
+                request.pendingMetadata = result->result;
+                request.collectedPartialResult = collectedPartialResult;
+            } else if (request.hasCallback) {
+                CameraMetadata metadata;
+                metadata = result->result;
+                sendCaptureResult(states, metadata, request.resultExtras,
+                    collectedPartialResult, frameNumber,
+                    hasInputBufferInRequest, request.zslCapture && request.stillCapture,
+                    request.rotateAndCropAuto, request.cameraIdsWithZoom,
+                    request.physicalMetadatas);
+            }
+        }
+        removeInFlightRequestIfReadyLocked(states, idx);
+    } // scope for states.inFlightLock
+
+    if (result->input_buffer != NULL) {
+        if (hasInputBufferInRequest) {
+            Camera3Stream *stream =
+                Camera3Stream::cast(result->input_buffer->stream);
+            res = stream->returnInputBuffer(*(result->input_buffer));
+            // Note: stream may be deallocated at this point, if this buffer was the
+            // last reference to it.
+            if (res != OK) {
+                ALOGE("%s: RequestThread: Can't return input buffer for frame %d to"
+                      "  its stream:%s (%d)",  __FUNCTION__,
+                      frameNumber, strerror(-res), res);
+            }
+        } else {
+            ALOGW("%s: Input buffer should be NULL if there is no input"
+                    " buffer sent in the request, skipping input buffer return.",
+                    __FUNCTION__);
+        }
+    }
+}
+
+void processOneCaptureResultLocked(
+        CaptureOutputStates& states,
+        const hardware::camera::device::V3_2::CaptureResult& result,
+        const hardware::hidl_vec<
+                hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata) {
+    using hardware::camera::device::V3_2::StreamBuffer;
+    using hardware::camera::device::V3_2::BufferStatus;
+    std::unique_ptr<ResultMetadataQueue>& fmq = states.fmq;
+    BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
+    camera3_capture_result r;
+    status_t res;
+    r.frame_number = result.frameNumber;
+
+    // Read and validate the result metadata.
+    hardware::camera::device::V3_2::CameraMetadata resultMetadata;
+    res = readOneCameraMetadataLocked(
+            fmq, result.fmqResultSize,
+            resultMetadata, result.result);
+    if (res != OK) {
+        ALOGE("%s: Frame %d: Failed to read capture result metadata",
+                __FUNCTION__, result.frameNumber);
+        return;
+    }
+    r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+
+    // Read and validate physical camera metadata
+    size_t physResultCount = physicalCameraMetadata.size();
+    std::vector<const char*> physCamIds(physResultCount);
+    std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
+    std::vector<hardware::camera::device::V3_2::CameraMetadata> physResultMetadata;
+    physResultMetadata.resize(physResultCount);
+    for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
+        res = readOneCameraMetadataLocked(fmq, physicalCameraMetadata[i].fmqMetadataSize,
+                physResultMetadata[i], physicalCameraMetadata[i].metadata);
+        if (res != OK) {
+            ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
+                    __FUNCTION__, result.frameNumber,
+                    physicalCameraMetadata[i].physicalCameraId.c_str());
+            return;
+        }
+        physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
+        phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
+                physResultMetadata[i].data());
+    }
+    r.num_physcam_metadata = physResultCount;
+    r.physcam_ids = physCamIds.data();
+    r.physcam_metadata = phyCamMetadatas.data();
+
+    std::vector<camera3_stream_buffer_t> outputBuffers(result.outputBuffers.size());
+    std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
+    for (size_t i = 0; i < result.outputBuffers.size(); i++) {
+        auto& bDst = outputBuffers[i];
+        const StreamBuffer &bSrc = result.outputBuffers[i];
+
+        sp<Camera3StreamInterface> stream = states.outputStreams.get(bSrc.streamId);
+        if (stream == nullptr) {
+            ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
+                    __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+            return;
+        }
+        bDst.stream = stream->asHalStream();
+
+        bool noBufferReturned = false;
+        buffer_handle_t *buffer = nullptr;
+        if (states.useHalBufManager) {
+            // This is suspicious most of the time but can be correct during flush where HAL
+            // has to return capture result before a buffer is requested
+            if (bSrc.bufferId == BUFFER_ID_NO_BUFFER) {
+                if (bSrc.status == BufferStatus::OK) {
+                    ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
+                            __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+                    // Still proceeds so other buffers can be returned
+                }
+                noBufferReturned = true;
+            }
+            if (noBufferReturned) {
+                res = OK;
+            } else {
+                res = bufferRecords.popInflightRequestBuffer(bSrc.bufferId, &buffer);
+            }
+        } else {
+            res = bufferRecords.popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
+        }
+
+        if (res != OK) {
+            ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
+                    __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+            return;
+        }
+
+        bDst.buffer = buffer;
+        bDst.status = mapHidlBufferStatus(bSrc.status);
+        bDst.acquire_fence = -1;
+        if (bSrc.releaseFence == nullptr) {
+            bDst.release_fence = -1;
+        } else if (bSrc.releaseFence->numFds == 1) {
+            if (noBufferReturned) {
+                ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
+            }
+            bDst.release_fence = dup(bSrc.releaseFence->data[0]);
+        } else {
+            ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
+                    __FUNCTION__, result.frameNumber, i, bSrc.releaseFence->numFds);
+            return;
+        }
+    }
+    r.num_output_buffers = outputBuffers.size();
+    r.output_buffers = outputBuffers.data();
+
+    camera3_stream_buffer_t inputBuffer;
+    if (result.inputBuffer.streamId == -1) {
+        r.input_buffer = nullptr;
+    } else {
+        if (states.inputStream->getId() != result.inputBuffer.streamId) {
+            ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
+                    result.frameNumber, result.inputBuffer.streamId);
+            return;
+        }
+        inputBuffer.stream = states.inputStream->asHalStream();
+        buffer_handle_t *buffer;
+        res = bufferRecords.popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
+                &buffer);
+        if (res != OK) {
+            ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
+                    __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
+            return;
+        }
+        inputBuffer.buffer = buffer;
+        inputBuffer.status = mapHidlBufferStatus(result.inputBuffer.status);
+        inputBuffer.acquire_fence = -1;
+        if (result.inputBuffer.releaseFence == nullptr) {
+            inputBuffer.release_fence = -1;
+        } else if (result.inputBuffer.releaseFence->numFds == 1) {
+            inputBuffer.release_fence = dup(result.inputBuffer.releaseFence->data[0]);
+        } else {
+            ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
+                    __FUNCTION__, result.frameNumber, result.inputBuffer.releaseFence->numFds);
+            return;
+        }
+        r.input_buffer = &inputBuffer;
+    }
+
+    r.partial_result = result.partialResult;
+
+    processCaptureResult(states, &r);
+}
+
+void returnOutputBuffers(
+        bool useHalBufManager,
+        sp<NotificationListener> listener,
+        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
+        nsecs_t timestamp, bool timestampIncreasing,
+        const SurfaceMap& outputSurfaces,
+        const CaptureResultExtras &inResultExtras,
+        ERROR_BUF_STRATEGY errorBufStrategy) {
+
+    for (size_t i = 0; i < numBuffers; i++)
+    {
+        Camera3StreamInterface *stream = Camera3Stream::cast(outputBuffers[i].stream);
+        int streamId = stream->getId();
+
+        // Call notify(ERROR_BUFFER) if necessary.
+        if (outputBuffers[i].status == CAMERA3_BUFFER_STATUS_ERROR &&
+                errorBufStrategy == ERROR_BUF_RETURN_NOTIFY) {
+            if (listener != nullptr) {
+                CaptureResultExtras extras = inResultExtras;
+                extras.errorStreamId = streamId;
+                listener->notifyError(
+                        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
+                        extras);
+            }
+        }
+
+        if (outputBuffers[i].buffer == nullptr) {
+            if (!useHalBufManager) {
+                // With HAL buffer management API, HAL sometimes will have to return buffers that
+                // has not got a output buffer handle filled yet. This is though illegal if HAL
+                // buffer management API is not being used.
+                ALOGE("%s: cannot return a null buffer!", __FUNCTION__);
+            }
+            continue;
+        }
+
+        const auto& it = outputSurfaces.find(streamId);
+        status_t res = OK;
+
+        // Do not return the buffer if the buffer status is error, and the error
+        // buffer strategy is CACHE.
+        if (outputBuffers[i].status != CAMERA3_BUFFER_STATUS_ERROR ||
+                errorBufStrategy != ERROR_BUF_CACHE) {
+            if (it != outputSurfaces.end()) {
+                res = stream->returnBuffer(
+                        outputBuffers[i], timestamp, timestampIncreasing, it->second,
+                        inResultExtras.frameNumber);
+            } else {
+                res = stream->returnBuffer(
+                        outputBuffers[i], timestamp, timestampIncreasing, std::vector<size_t> (),
+                        inResultExtras.frameNumber);
+            }
+        }
+        // Note: stream may be deallocated at this point, if this buffer was
+        // the last reference to it.
+        if (res == NO_INIT || res == DEAD_OBJECT) {
+            ALOGV("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
+        } else if (res != OK) {
+            ALOGE("Can't return buffer to its stream: %s (%d)", strerror(-res), res);
+        }
+
+        // Long processing consumers can cause returnBuffer timeout for shared stream
+        // If that happens, cancel the buffer and send a buffer error to client
+        if (it != outputSurfaces.end() && res == TIMED_OUT &&
+                outputBuffers[i].status == CAMERA3_BUFFER_STATUS_OK) {
+            // cancel the buffer
+            camera3_stream_buffer_t sb = outputBuffers[i];
+            sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+            stream->returnBuffer(sb, /*timestamp*/0, timestampIncreasing, std::vector<size_t> (),
+                    inResultExtras.frameNumber);
+
+            if (listener != nullptr) {
+                CaptureResultExtras extras = inResultExtras;
+                extras.errorStreamId = streamId;
+                listener->notifyError(
+                        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER,
+                        extras);
+            }
+        }
+    }
+}
+
+void returnAndRemovePendingOutputBuffers(bool useHalBufManager,
+        sp<NotificationListener> listener, InFlightRequest& request) {
+    bool timestampIncreasing = !(request.zslCapture || request.hasInputBuffer);
+    returnOutputBuffers(useHalBufManager, listener,
+            request.pendingOutputBuffers.array(),
+            request.pendingOutputBuffers.size(),
+            request.shutterTimestamp, timestampIncreasing,
+            request.outputSurfaces, request.resultExtras,
+            request.errorBufStrategy);
+
+    // Remove error buffers that are not cached.
+    for (auto iter = request.pendingOutputBuffers.begin();
+            iter != request.pendingOutputBuffers.end(); ) {
+        if (request.errorBufStrategy != ERROR_BUF_CACHE ||
+                iter->status != CAMERA3_BUFFER_STATUS_ERROR) {
+            iter = request.pendingOutputBuffers.erase(iter);
+        } else {
+            iter++;
+        }
+    }
+}
+
+void notifyShutter(CaptureOutputStates& states, const camera3_shutter_msg_t &msg) {
+    ATRACE_CALL();
+    ssize_t idx;
+
+    // Set timestamp for the request in the in-flight tracking
+    // and get the request ID to send upstream
+    {
+        std::lock_guard<std::mutex> l(states.inflightLock);
+        InFlightRequestMap& inflightMap = states.inflightMap;
+        idx = inflightMap.indexOfKey(msg.frame_number);
+        if (idx >= 0) {
+            InFlightRequest &r = inflightMap.editValueAt(idx);
+
+            // Verify ordering of shutter notifications
+            {
+                std::lock_guard<std::mutex> l(states.outputLock);
+                // TODO: need to track errors for tighter bounds on expected frame number.
+                if (r.hasInputBuffer) {
+                    if (msg.frame_number < states.nextReprocShutterFrameNum) {
+                        SET_ERR("Reprocess shutter notification out-of-order. Expected "
+                                "notification for frame %d, got frame %d",
+                                states.nextReprocShutterFrameNum, msg.frame_number);
+                        return;
+                    }
+                    states.nextReprocShutterFrameNum = msg.frame_number + 1;
+                } else if (r.zslCapture && r.stillCapture) {
+                    if (msg.frame_number < states.nextZslShutterFrameNum) {
+                        SET_ERR("ZSL still capture shutter notification out-of-order. Expected "
+                                "notification for frame %d, got frame %d",
+                                states.nextZslShutterFrameNum, msg.frame_number);
+                        return;
+                    }
+                    states.nextZslShutterFrameNum = msg.frame_number + 1;
+                } else {
+                    if (msg.frame_number < states.nextShutterFrameNum) {
+                        SET_ERR("Shutter notification out-of-order. Expected "
+                                "notification for frame %d, got frame %d",
+                                states.nextShutterFrameNum, msg.frame_number);
+                        return;
+                    }
+                    states.nextShutterFrameNum = msg.frame_number + 1;
+                }
+            }
+
+            r.shutterTimestamp = msg.timestamp;
+            if (r.hasCallback) {
+                ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
+                    states.cameraId.string(), __FUNCTION__,
+                    msg.frame_number, r.resultExtras.requestId, msg.timestamp);
+                // Call listener, if any
+                if (states.listener != nullptr) {
+                    r.resultExtras.lastCompletedRegularFrameNumber =
+                            states.lastCompletedRegularFrameNumber;
+                    r.resultExtras.lastCompletedReprocessFrameNumber =
+                            states.lastCompletedReprocessFrameNumber;
+                    r.resultExtras.lastCompletedZslFrameNumber =
+                            states.lastCompletedZslFrameNumber;
+                    states.listener->notifyShutter(r.resultExtras, msg.timestamp);
+                }
+                // send pending result and buffers
+                sendCaptureResult(states,
+                    r.pendingMetadata, r.resultExtras,
+                    r.collectedPartialResult, msg.frame_number,
+                    r.hasInputBuffer, r.zslCapture && r.stillCapture,
+                    r.rotateAndCropAuto, r.cameraIdsWithZoom, r.physicalMetadatas);
+            }
+            returnAndRemovePendingOutputBuffers(
+                    states.useHalBufManager, states.listener, r);
+
+            removeInFlightRequestIfReadyLocked(states, idx);
+        }
+    }
+    if (idx < 0) {
+        SET_ERR("Shutter notification for non-existent frame number %d",
+                msg.frame_number);
+    }
+}
+
+void notifyError(CaptureOutputStates& states, const camera3_error_msg_t &msg) {
+    ATRACE_CALL();
+    // Map camera HAL error codes to ICameraDeviceCallback error codes
+    // Index into this with the HAL error code
+    static const int32_t halErrorMap[CAMERA3_MSG_NUM_ERRORS] = {
+        // 0 = Unused error code
+        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR,
+        // 1 = CAMERA3_MSG_ERROR_DEVICE
+        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+        // 2 = CAMERA3_MSG_ERROR_REQUEST
+        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
+        // 3 = CAMERA3_MSG_ERROR_RESULT
+        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT,
+        // 4 = CAMERA3_MSG_ERROR_BUFFER
+        hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER
+    };
+
+    int32_t errorCode =
+            ((msg.error_code >= 0) &&
+                    (msg.error_code < CAMERA3_MSG_NUM_ERRORS)) ?
+            halErrorMap[msg.error_code] :
+            hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
+
+    int streamId = 0;
+    String16 physicalCameraId;
+    if (msg.error_stream != nullptr) {
+        Camera3Stream *stream =
+                Camera3Stream::cast(msg.error_stream);
+        streamId = stream->getId();
+        physicalCameraId = String16(stream->physicalCameraId());
+    }
+    ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
+            states.cameraId.string(), __FUNCTION__, msg.frame_number,
+            streamId, msg.error_code);
+
+    CaptureResultExtras resultExtras;
+    switch (errorCode) {
+        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
+            // SET_ERR calls into listener to notify application
+            SET_ERR("Camera HAL reported serious device error");
+            break;
+        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
+        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
+            {
+                std::lock_guard<std::mutex> l(states.inflightLock);
+                ssize_t idx = states.inflightMap.indexOfKey(msg.frame_number);
+                if (idx >= 0) {
+                    InFlightRequest &r = states.inflightMap.editValueAt(idx);
+                    r.requestStatus = msg.error_code;
+                    resultExtras = r.resultExtras;
+                    bool physicalDeviceResultError = false;
+                    if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
+                            errorCode) {
+                        if (physicalCameraId.size() > 0) {
+                            String8 cameraId(physicalCameraId);
+                            auto iter = r.physicalCameraIds.find(cameraId);
+                            if (iter == r.physicalCameraIds.end()) {
+                                ALOGE("%s: Reported result failure for physical camera device: %s "
+                                        " which is not part of the respective request!",
+                                        __FUNCTION__, cameraId.string());
+                                break;
+                            }
+                            r.physicalCameraIds.erase(iter);
+                            resultExtras.errorPhysicalCameraId = physicalCameraId;
+                            physicalDeviceResultError = true;
+                        }
+                    }
+
+                    if (!physicalDeviceResultError) {
+                        r.skipResultMetadata = true;
+                        if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT
+                                == errorCode) {
+                            r.errorBufStrategy = ERROR_BUF_RETURN_NOTIFY;
+                        } else {
+                            // errorCode is ERROR_CAMERA_REQUEST
+                            r.errorBufStrategy = ERROR_BUF_RETURN;
+                        }
+
+                        // Check whether the buffers returned. If they returned,
+                        // remove inflight request.
+                        removeInFlightRequestIfReadyLocked(states, idx);
+                    }
+                } else {
+                    resultExtras.frameNumber = msg.frame_number;
+                    ALOGE("Camera %s: %s: cannot find in-flight request on "
+                            "frame %" PRId64 " error", states.cameraId.string(), __FUNCTION__,
+                            resultExtras.frameNumber);
+                }
+            }
+            resultExtras.errorStreamId = streamId;
+            if (states.listener != nullptr) {
+                states.listener->notifyError(errorCode, resultExtras);
+            } else {
+                ALOGE("Camera %s: %s: no listener available",
+                        states.cameraId.string(), __FUNCTION__);
+            }
+            break;
+        case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
+            // Do not depend on HAL ERROR_CAMERA_BUFFER to send buffer error
+            // callback to the app. Rather, use STATUS_ERROR of image buffers.
+            break;
+        default:
+            // SET_ERR calls notifyError
+            SET_ERR("Unknown error message from HAL: %d", msg.error_code);
+            break;
+    }
+}
+
+void notify(CaptureOutputStates& states, const camera3_notify_msg *msg) {
+    switch (msg->type) {
+        case CAMERA3_MSG_ERROR: {
+            notifyError(states, msg->message.error);
+            break;
+        }
+        case CAMERA3_MSG_SHUTTER: {
+            notifyShutter(states, msg->message.shutter);
+            break;
+        }
+        default:
+            SET_ERR("Unknown notify message from HAL: %d",
+                    msg->type);
+    }
+}
+
+void notify(CaptureOutputStates& states,
+        const hardware::camera::device::V3_2::NotifyMsg& msg) {
+    using android::hardware::camera::device::V3_2::MsgType;
+    using android::hardware::camera::device::V3_2::ErrorCode;
+
+    ATRACE_CALL();
+    camera3_notify_msg m;
+    switch (msg.type) {
+        case MsgType::ERROR:
+            m.type = CAMERA3_MSG_ERROR;
+            m.message.error.frame_number = msg.msg.error.frameNumber;
+            if (msg.msg.error.errorStreamId >= 0) {
+                sp<Camera3StreamInterface> stream =
+                        states.outputStreams.get(msg.msg.error.errorStreamId);
+                if (stream == nullptr) {
+                    ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
+                            m.message.error.frame_number, msg.msg.error.errorStreamId);
+                    return;
+                }
+                m.message.error.error_stream = stream->asHalStream();
+            } else {
+                m.message.error.error_stream = nullptr;
+            }
+            switch (msg.msg.error.errorCode) {
+                case ErrorCode::ERROR_DEVICE:
+                    m.message.error.error_code = CAMERA3_MSG_ERROR_DEVICE;
+                    break;
+                case ErrorCode::ERROR_REQUEST:
+                    m.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
+                    break;
+                case ErrorCode::ERROR_RESULT:
+                    m.message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
+                    break;
+                case ErrorCode::ERROR_BUFFER:
+                    m.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
+                    break;
+            }
+            break;
+        case MsgType::SHUTTER:
+            m.type = CAMERA3_MSG_SHUTTER;
+            m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
+            m.message.shutter.timestamp = msg.msg.shutter.timestamp;
+            break;
+    }
+    notify(states, &m);
+}
+
+void requestStreamBuffers(RequestBufferStates& states,
+        const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+        hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
+    using android::hardware::camera::device::V3_2::BufferStatus;
+    using android::hardware::camera::device::V3_2::StreamBuffer;
+    using android::hardware::camera::device::V3_5::BufferRequestStatus;
+    using android::hardware::camera::device::V3_5::StreamBufferRet;
+    using android::hardware::camera::device::V3_5::StreamBufferRequestError;
+
+    std::lock_guard<std::mutex> lock(states.reqBufferLock);
+
+    hardware::hidl_vec<StreamBufferRet> bufRets;
+    if (!states.useHalBufManager) {
+        ALOGE("%s: Camera %s does not support HAL buffer management",
+                __FUNCTION__, states.cameraId.string());
+        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+        return;
+    }
+
+    SortedVector<int32_t> streamIds;
+    ssize_t sz = streamIds.setCapacity(bufReqs.size());
+    if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
+        ALOGE("%s: failed to allocate memory for %zu buffer requests",
+                __FUNCTION__, bufReqs.size());
+        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+        return;
+    }
+
+    if (bufReqs.size() > states.outputStreams.size()) {
+        ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
+                __FUNCTION__, bufReqs.size(), states.outputStreams.size());
+        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+        return;
+    }
+
+    // Check for repeated streamId
+    for (const auto& bufReq : bufReqs) {
+        if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
+            ALOGE("%s: Stream %d appear multiple times in buffer requests",
+                    __FUNCTION__, bufReq.streamId);
+            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+            return;
+        }
+        streamIds.add(bufReq.streamId);
+    }
+
+    if (!states.reqBufferIntf.startRequestBuffer()) {
+        ALOGE("%s: request buffer disallowed while camera service is configuring",
+                __FUNCTION__);
+        _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
+        return;
+    }
+
+    bufRets.resize(bufReqs.size());
+
+    bool allReqsSucceeds = true;
+    bool oneReqSucceeds = false;
+    for (size_t i = 0; i < bufReqs.size(); i++) {
+        const auto& bufReq = bufReqs[i];
+        auto& bufRet = bufRets[i];
+        int32_t streamId = bufReq.streamId;
+        sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
+        if (outputStream == nullptr) {
+            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
+            hardware::hidl_vec<StreamBufferRet> emptyBufRets;
+            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
+            states.reqBufferIntf.endRequestBuffer();
+            return;
+        }
+
+        if (outputStream->isAbandoned()) {
+            bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+            allReqsSucceeds = false;
+            continue;
+        }
+
+        bufRet.streamId = streamId;
+        size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
+        uint32_t numBuffersRequested = bufReq.numBuffersRequested;
+        size_t totalHandout = handOutBufferCount + numBuffersRequested;
+        uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
+        if (totalHandout > maxBuffers) {
+            // Not able to allocate enough buffer. Exit early for this stream
+            ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
+                    " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
+                    numBuffersRequested, maxBuffers);
+            bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
+            allReqsSucceeds = false;
+            continue;
+        }
+
+        hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
+        bool currentReqSucceeds = true;
+        std::vector<camera3_stream_buffer_t> streamBuffers(numBuffersRequested);
+        size_t numAllocatedBuffers = 0;
+        size_t numPushedInflightBuffers = 0;
+        for (size_t b = 0; b < numBuffersRequested; b++) {
+            camera3_stream_buffer_t& sb = streamBuffers[b];
+            // Since this method can run concurrently with request thread
+            // We need to update the wait duration everytime we call getbuffer
+            nsecs_t waitDuration =  states.reqBufferIntf.getWaitDuration();
+            status_t res = outputStream->getBuffer(&sb, waitDuration);
+            if (res != OK) {
+                if (res == NO_INIT || res == DEAD_OBJECT) {
+                    ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                    bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+                } else {
+                    ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                    if (res == TIMED_OUT || res == NO_MEMORY) {
+                        bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+                    } else {
+                        bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+                    }
+                }
+                currentReqSucceeds = false;
+                break;
+            }
+            numAllocatedBuffers++;
+
+            buffer_handle_t *buffer = sb.buffer;
+            auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
+            bool isNewBuffer = pair.first;
+            uint64_t bufferId = pair.second;
+            StreamBuffer& hBuf = tmpRetBuffers[b];
+
+            hBuf.streamId = streamId;
+            hBuf.bufferId = bufferId;
+            hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
+            hBuf.status = BufferStatus::OK;
+            hBuf.releaseFence = nullptr;
+
+            native_handle_t *acquireFence = nullptr;
+            if (sb.acquire_fence != -1) {
+                acquireFence = native_handle_create(1,0);
+                acquireFence->data[0] = sb.acquire_fence;
+            }
+            hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
+            hBuf.releaseFence = nullptr;
+
+            res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
+            if (res != OK) {
+                ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
+                        __FUNCTION__, streamId, strerror(-res), res);
+                bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+                currentReqSucceeds = false;
+                break;
+            }
+            numPushedInflightBuffers++;
+        }
+        if (currentReqSucceeds) {
+            bufRet.val.buffers(std::move(tmpRetBuffers));
+            oneReqSucceeds = true;
+        } else {
+            allReqsSucceeds = false;
+            for (size_t b = 0; b < numPushedInflightBuffers; b++) {
+                StreamBuffer& hBuf = tmpRetBuffers[b];
+                buffer_handle_t* buffer;
+                status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
+                        hBuf.bufferId, &buffer);
+                if (res != OK) {
+                    SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                }
+            }
+            for (size_t b = 0; b < numAllocatedBuffers; b++) {
+                camera3_stream_buffer_t& sb = streamBuffers[b];
+                sb.acquire_fence = -1;
+                sb.status = CAMERA3_BUFFER_STATUS_ERROR;
+            }
+            returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+                    streamBuffers.data(), numAllocatedBuffers, 0);
+        }
+    }
+
+    _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
+            oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
+                             BufferRequestStatus::FAILED_UNKNOWN,
+            bufRets);
+    states.reqBufferIntf.endRequestBuffer();
+}
+
+void returnStreamBuffers(ReturnBufferStates& states,
+        const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+    if (!states.useHalBufManager) {
+        ALOGE("%s: Camera %s does not support HAL buffer managerment",
+                __FUNCTION__, states.cameraId.string());
+        return;
+    }
+
+    for (const auto& buf : buffers) {
+        if (buf.bufferId == BUFFER_ID_NO_BUFFER) {
+            ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
+            continue;
+        }
+
+        buffer_handle_t* buffer;
+        status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(buf.bufferId, &buffer);
+
+        if (res != OK) {
+            ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
+                    __FUNCTION__, buf.bufferId, buf.streamId);
+            continue;
+        }
+
+        camera3_stream_buffer_t streamBuffer;
+        streamBuffer.buffer = buffer;
+        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+        streamBuffer.acquire_fence = -1;
+        streamBuffer.release_fence = -1;
+
+        if (buf.releaseFence == nullptr) {
+            streamBuffer.release_fence = -1;
+        } else if (buf.releaseFence->numFds == 1) {
+            streamBuffer.release_fence = dup(buf.releaseFence->data[0]);
+        } else {
+            ALOGE("%s: Invalid release fence, fd count is %d, not 1",
+                    __FUNCTION__, buf.releaseFence->numFds);
+            continue;
+        }
+
+        sp<Camera3StreamInterface> stream = states.outputStreams.get(buf.streamId);
+        if (stream == nullptr) {
+            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
+            continue;
+        }
+        streamBuffer.stream = stream->asHalStream();
+        returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+                &streamBuffer, /*size*/1, /*timestamp*/ 0);
+    }
+}
+
+void flushInflightRequests(FlushInflightReqStates& states) {
+    ATRACE_CALL();
+    { // First return buffers cached in mInFlightMap
+        std::lock_guard<std::mutex> l(states.inflightLock);
+        for (size_t idx = 0; idx < states.inflightMap.size(); idx++) {
+            const InFlightRequest &request = states.inflightMap.valueAt(idx);
+            returnOutputBuffers(
+                states.useHalBufManager, states.listener,
+                request.pendingOutputBuffers.array(),
+                request.pendingOutputBuffers.size(), 0,
+                /*timestampIncreasing*/true, request.outputSurfaces,
+                request.resultExtras, request.errorBufStrategy);
+            ALOGW("%s: Frame %d |  Timestamp: %" PRId64 ", metadata"
+                    " arrived: %s, buffers left: %d.\n", __FUNCTION__,
+                    states.inflightMap.keyAt(idx), request.shutterTimestamp,
+                    request.haveResultMetadata ? "true" : "false",
+                    request.numBuffersLeft);
+        }
+
+        states.inflightMap.clear();
+        states.inflightIntf.onInflightMapFlushedLocked();
+    }
+
+    // Then return all inflight buffers not returned by HAL
+    std::vector<std::pair<int32_t, int32_t>> inflightKeys;
+    states.flushBufferIntf.getInflightBufferKeys(&inflightKeys);
+
+    // Inflight buffers for HAL buffer manager
+    std::vector<uint64_t> inflightRequestBufferKeys;
+    states.flushBufferIntf.getInflightRequestBufferKeys(&inflightRequestBufferKeys);
+
+    // (streamId, frameNumber, buffer_handle_t*) tuple for all inflight buffers.
+    // frameNumber will be -1 for buffers from HAL buffer manager
+    std::vector<std::tuple<int32_t, int32_t, buffer_handle_t*>> inflightBuffers;
+    inflightBuffers.reserve(inflightKeys.size() + inflightRequestBufferKeys.size());
+
+    for (auto& pair : inflightKeys) {
+        int32_t frameNumber = pair.first;
+        int32_t streamId = pair.second;
+        buffer_handle_t* buffer;
+        status_t res = states.bufferRecordsIntf.popInflightBuffer(frameNumber, streamId, &buffer);
+        if (res != OK) {
+            ALOGE("%s: Frame %d: No in-flight buffer for stream %d",
+                    __FUNCTION__, frameNumber, streamId);
+            continue;
+        }
+        inflightBuffers.push_back(std::make_tuple(streamId, frameNumber, buffer));
+    }
+
+    for (auto& bufferId : inflightRequestBufferKeys) {
+        int32_t streamId = -1;
+        buffer_handle_t* buffer = nullptr;
+        status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
+                bufferId, &buffer, &streamId);
+        if (res != OK) {
+            ALOGE("%s: cannot find in-flight buffer %" PRIu64, __FUNCTION__, bufferId);
+            continue;
+        }
+        inflightBuffers.push_back(std::make_tuple(streamId, /*frameNumber*/-1, buffer));
+    }
+
+    std::vector<sp<Camera3StreamInterface>> streams = states.flushBufferIntf.getAllStreams();
+
+    for (auto& tuple : inflightBuffers) {
+        status_t res = OK;
+        int32_t streamId = std::get<0>(tuple);
+        int32_t frameNumber = std::get<1>(tuple);
+        buffer_handle_t* buffer = std::get<2>(tuple);
+
+        camera3_stream_buffer_t streamBuffer;
+        streamBuffer.buffer = buffer;
+        streamBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+        streamBuffer.acquire_fence = -1;
+        streamBuffer.release_fence = -1;
+
+        for (auto& stream : streams) {
+            if (streamId == stream->getId()) {
+                // Return buffer to deleted stream
+                camera3_stream* halStream = stream->asHalStream();
+                streamBuffer.stream = halStream;
+                switch (halStream->stream_type) {
+                    case CAMERA3_STREAM_OUTPUT:
+                        res = stream->returnBuffer(streamBuffer, /*timestamp*/ 0,
+                                /*timestampIncreasing*/true, std::vector<size_t> (), frameNumber);
+                        if (res != OK) {
+                            ALOGE("%s: Can't return output buffer for frame %d to"
+                                  " stream %d: %s (%d)",  __FUNCTION__,
+                                  frameNumber, streamId, strerror(-res), res);
+                        }
+                        break;
+                    case CAMERA3_STREAM_INPUT:
+                        res = stream->returnInputBuffer(streamBuffer);
+                        if (res != OK) {
+                            ALOGE("%s: Can't return input buffer for frame %d to"
+                                  " stream %d: %s (%d)",  __FUNCTION__,
+                                  frameNumber, streamId, strerror(-res), res);
+                        }
+                        break;
+                    default: // Bi-direcitonal stream is deprecated
+                        ALOGE("%s: stream %d has unknown stream type %d",
+                                __FUNCTION__, streamId, halStream->stream_type);
+                        break;
+                }
+                break;
+            }
+        }
+    }
+}
+
+} // camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
new file mode 100644
index 0000000..9946312
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA3_OUTPUT_UTILS_H
+#define ANDROID_SERVERS_CAMERA3_OUTPUT_UTILS_H
+
+#include <memory>
+#include <mutex>
+
+#include <cutils/native_handle.h>
+
+#include <fmq/MessageQueue.h>
+
+#include <common/CameraDeviceBase.h>
+
+#include "device3/BufferUtils.h"
+#include "device3/DistortionMapper.h"
+#include "device3/ZoomRatioMapper.h"
+#include "device3/RotateAndCropMapper.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3Stream.h"
+#include "device3/Camera3OutputStreamInterface.h"
+#include "utils/TagMonitor.h"
+
+namespace android {
+
+using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
+
+namespace camera3 {
+
+    /**
+     * Helper methods shared between Camera3Device/Camera3OfflineSession for HAL callbacks
+     */
+
+    // helper function to return the output buffers to output streams. The
+    // function also optionally calls notify(ERROR_BUFFER).
+    void returnOutputBuffers(
+            bool useHalBufManager,
+            sp<NotificationListener> listener, // Only needed when outputSurfaces is not empty
+            const camera3_stream_buffer_t *outputBuffers,
+            size_t numBuffers, nsecs_t timestamp, bool timestampIncreasing = true,
+            // The following arguments are only meant for surface sharing use case
+            const SurfaceMap& outputSurfaces = SurfaceMap{},
+            // Used to send buffer error callback when failing to return buffer
+            const CaptureResultExtras &resultExtras = CaptureResultExtras{},
+            ERROR_BUF_STRATEGY errorBufStrategy = ERROR_BUF_RETURN);
+
+    // helper function to return the output buffers to output streams, and
+    // remove the returned buffers from the inflight request's pending buffers
+    // vector.
+    void returnAndRemovePendingOutputBuffers(
+            bool useHalBufManager,
+            sp<NotificationListener> listener, // Only needed when outputSurfaces is not empty
+            InFlightRequest& request);
+
+    // Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
+    // callbacks
+    struct CaptureOutputStates {
+        const String8& cameraId;
+        std::mutex& inflightLock;
+        int64_t& lastCompletedRegularFrameNumber;
+        int64_t& lastCompletedZslFrameNumber;
+        int64_t& lastCompletedReprocessFrameNumber;
+        InFlightRequestMap& inflightMap; // end of inflightLock scope
+        std::mutex& outputLock;
+        std::list<CaptureResult>& resultQueue;
+        std::condition_variable& resultSignal;
+        uint32_t& nextShutterFrameNum;
+        uint32_t& nextReprocShutterFrameNum;
+        uint32_t& nextZslShutterFrameNum;
+        uint32_t& nextResultFrameNum;
+        uint32_t& nextReprocResultFrameNum;
+        uint32_t& nextZslResultFrameNum; // end of outputLock scope
+        const bool useHalBufManager;
+        const bool usePartialResult;
+        const bool needFixupMonoChrome;
+        const uint32_t numPartialResults;
+        const metadata_vendor_id_t vendorTagId;
+        const CameraMetadata& deviceInfo;
+        const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap;
+        std::unique_ptr<ResultMetadataQueue>& fmq;
+        std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers;
+        std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers;
+        std::unordered_map<std::string, camera3::RotateAndCropMapper>& rotateAndCropMappers;
+        TagMonitor& tagMonitor;
+        sp<Camera3Stream> inputStream;
+        StreamSet& outputStreams;
+        sp<NotificationListener> listener;
+        SetErrorInterface& setErrIntf;
+        InflightRequestUpdateInterface& inflightIntf;
+        BufferRecordsInterface& bufferRecordsIntf;
+    };
+
+    // Handle one capture result. Assume callers hold the lock to serialize all
+    // processCaptureResult calls
+    void processOneCaptureResultLocked(
+            CaptureOutputStates& states,
+            const hardware::camera::device::V3_2::CaptureResult& result,
+            const hardware::hidl_vec<
+                    hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
+
+    // Handle one notify message
+    void notify(CaptureOutputStates& states,
+            const hardware::camera::device::V3_2::NotifyMsg& msg);
+
+    struct RequestBufferStates {
+        const String8& cameraId;
+        std::mutex& reqBufferLock; // lock to serialize request buffer calls
+        const bool useHalBufManager;
+        StreamSet& outputStreams;
+        SetErrorInterface& setErrIntf;
+        BufferRecordsInterface& bufferRecordsIntf;
+        RequestBufferInterface& reqBufferIntf;
+    };
+
+    void requestStreamBuffers(RequestBufferStates& states,
+            const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+            hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb);
+
+    struct ReturnBufferStates {
+        const String8& cameraId;
+        const bool useHalBufManager;
+        StreamSet& outputStreams;
+        BufferRecordsInterface& bufferRecordsIntf;
+    };
+
+    void returnStreamBuffers(ReturnBufferStates& states,
+            const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
+
+    struct FlushInflightReqStates {
+        const String8& cameraId;
+        std::mutex& inflightLock;
+        InFlightRequestMap& inflightMap; // end of inflightLock scope
+        const bool useHalBufManager;
+        sp<NotificationListener> listener;
+        InflightRequestUpdateInterface& inflightIntf;
+        BufferRecordsInterface& bufferRecordsIntf;
+        FlushBufferInterface& flushBufferIntf;
+    };
+
+    void flushInflightRequests(FlushInflightReqStates& states);
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index b5e37c2..e645e05 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -65,6 +65,12 @@
             const std::vector<size_t> &removedSurfaceIds,
             KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
 
+    virtual bool getOfflineProcessingSupport() const {
+        // As per Camera spec. shared streams currently do not support
+        // offline mode.
+        return false;
+    }
+
 private:
 
     static const size_t kMaxOutputs = 4;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index fd9b4b0..20f6168 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -22,6 +22,7 @@
 #include <utils/Trace.h>
 #include "device3/Camera3Stream.h"
 #include "device3/StatusTracker.h"
+#include "utils/TraceHFR.h"
 
 #include <cutils/properties.h>
 
@@ -70,7 +71,7 @@
     mFormatOverridden(false),
     mOriginalFormat(format),
     mDataSpaceOverridden(false),
-    mOriginalDataSpace(HAL_DATASPACE_UNKNOWN),
+    mOriginalDataSpace(dataSpace),
     mPhysicalCameraId(physicalCameraId),
     mLastTimestamp(0) {
 
@@ -137,9 +138,6 @@
 
 void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
     mDataSpaceOverridden = dataSpaceOverridden;
-    if (dataSpaceOverridden && mOriginalDataSpace == HAL_DATASPACE_UNKNOWN) {
-        mOriginalDataSpace = camera3_stream::data_space;
-    }
 }
 
 bool Camera3Stream::isDataSpaceOverridden() const {
@@ -154,6 +152,14 @@
     return mPhysicalCameraId;
 }
 
+void Camera3Stream::setOfflineProcessingSupport(bool support) {
+    mSupportOfflineProcessing = support;
+}
+
+bool Camera3Stream::getOfflineProcessingSupport() const {
+    return mSupportOfflineProcessing;
+}
+
 status_t Camera3Stream::forceToIdle() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
@@ -596,7 +602,7 @@
 status_t Camera3Stream::getBuffer(camera3_stream_buffer *buffer,
         nsecs_t waitBufferTimeout,
         const std::vector<size_t>& surface_ids) {
-    ATRACE_CALL();
+    ATRACE_HFR_CALL();
     Mutex::Autolock l(mLock);
     status_t res = OK;
 
@@ -677,7 +683,7 @@
 status_t Camera3Stream::returnBuffer(const camera3_stream_buffer &buffer,
         nsecs_t timestamp, bool timestampIncreasing,
          const std::vector<size_t>& surface_ids, uint64_t frameNumber) {
-    ATRACE_CALL();
+    ATRACE_HFR_CALL();
     Mutex::Autolock l(mLock);
 
     // Check if this buffer is outstanding.
@@ -809,6 +815,8 @@
     info.mError = (buffer.status == CAMERA3_BUFFER_STATUS_ERROR);
     info.mFrameNumber = frameNumber;
     info.mTimestamp = timestamp;
+    info.mStreamId = getId();
+
     // TODO: rest of fields
 
     for (it = mBufferListenerList.begin(), end = mBufferListenerList.end();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 67afd0f..d768d3d 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -167,6 +167,9 @@
     android_dataspace getOriginalDataSpace() const;
     const String8&    physicalCameraId() const;
 
+    void              setOfflineProcessingSupport(bool) override;
+    bool              getOfflineProcessingSupport() const override;
+
     camera3_stream*   asHalStream() override {
         return this;
     }
@@ -588,10 +591,12 @@
 
     //Keep track of original dataSpace in case it gets overridden
     bool mDataSpaceOverridden;
-    android_dataspace mOriginalDataSpace;
+    const android_dataspace mOriginalDataSpace;
 
     String8 mPhysicalCameraId;
     nsecs_t mLastTimestamp;
+
+    bool mSupportOfflineProcessing = false;
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamBufferListener.h b/services/camera/libcameraservice/device3/Camera3StreamBufferListener.h
index d0aee27..170da5a 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamBufferListener.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamBufferListener.h
@@ -29,6 +29,7 @@
 public:
 
     struct BufferInfo {
+        int mStreamId;
         bool mOutput; // if false then input buffer
         Rect mCrop;
         uint32_t mTransform;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 73f501a..667e3bb 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -23,6 +23,7 @@
 #include "Camera3StreamBufferListener.h"
 #include "Camera3StreamBufferFreedListener.h"
 
+struct camera3_stream;
 struct camera3_stream_buffer;
 
 namespace android {
@@ -54,6 +55,7 @@
         android_dataspace dataSpace;
         uint64_t consumerUsage;
         bool finalized = false;
+        bool supportsOffline = false;
         OutputStreamInfo() :
             width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
             consumerUsage(0) {}
@@ -99,6 +101,12 @@
     virtual android_dataspace getOriginalDataSpace() const = 0;
 
     /**
+     * Offline processing
+     */
+    virtual void setOfflineProcessingSupport(bool support) = 0;
+    virtual bool getOfflineProcessingSupport() const = 0;
+
+    /**
      * Get a HAL3 handle for the stream, without starting stream configuration.
      */
     virtual camera3_stream* asHalStream() = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 3089181..5c6c518 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -498,7 +498,7 @@
         mInputSlots[bufferItem.mSlot].mFrameNumber = bufferItem.mFrameNumber;
     } else {
         SP_LOGE("%s: Invalid input graphic buffer!", __FUNCTION__);
-        res = BAD_VALUE;
+        mOnFrameAvailableRes.store(BAD_VALUE);
         return;
     }
     bufferId = bufferItem.mGraphicBuffer->getId();
@@ -543,6 +543,11 @@
     mOnFrameAvailableRes.store(res);
 }
 
+void Camera3StreamSplitter::onFrameReplaced(const BufferItem& item) {
+    ATRACE_CALL();
+    onFrameAvailable(item);
+}
+
 void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfaceId) {
     ATRACE_CALL();
 
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 960f7aa..4eb455a 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -102,6 +102,13 @@
     void onFrameAvailable(const BufferItem& item) override;
 
     // From IConsumerListener
+    //
+    // Similar to onFrameAvailable, but buffer item is indeed replacing a buffer
+    // in the buffer queue. This can happen when buffer queue is in droppable
+    // mode.
+    void onFrameReplaced(const BufferItem& item) override;
+
+    // From IConsumerListener
     // We don't care about released buffers because we detach each buffer as
     // soon as we acquire it. See the comment for onBufferReleased below for
     // some clarifying notes about the name.
diff --git a/services/camera/libcameraservice/device3/CoordinateMapper.cpp b/services/camera/libcameraservice/device3/CoordinateMapper.cpp
new file mode 100644
index 0000000..a0bbe54
--- /dev/null
+++ b/services/camera/libcameraservice/device3/CoordinateMapper.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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 <system/camera_metadata_tags.h>
+
+#include "device3/CoordinateMapper.h"
+
+namespace android {
+
+namespace camera3 {
+
+/**
+ * Metadata keys to correct when adjusting coordinates for distortion correction
+ * or for crop and rotate
+ */
+
+// Both capture request and result
+constexpr std::array<uint32_t, 3> CoordinateMapper::kMeteringRegionsToCorrect = {
+    ANDROID_CONTROL_AF_REGIONS,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS
+};
+
+// Both capture request and result, not applicable to crop and rotate
+constexpr std::array<uint32_t, 1> CoordinateMapper::kRectsToCorrect = {
+    ANDROID_SCALER_CROP_REGION,
+};
+
+// Only for capture result
+constexpr std::array<uint32_t, 2> CoordinateMapper::kResultPointsToCorrectNoClamp = {
+    ANDROID_STATISTICS_FACE_RECTANGLES, // Says rectangles, is really points
+    ANDROID_STATISTICS_FACE_LANDMARKS,
+};
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/CoordinateMapper.h b/services/camera/libcameraservice/device3/CoordinateMapper.h
new file mode 100644
index 0000000..5164856
--- /dev/null
+++ b/services/camera/libcameraservice/device3/CoordinateMapper.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_COORDINATEMAPPER_H
+#define ANDROID_SERVERS_COORDINATEMAPPER_H
+
+#include <array>
+
+namespace android {
+
+namespace camera3 {
+
+class CoordinateMapper {
+    // Right now only stores metadata tags containing 2D coordinates
+    // to be corrected.
+protected:
+    // Metadata key lists to correct
+
+    // Both capture request and result
+    static const std::array<uint32_t, 3> kMeteringRegionsToCorrect;
+
+    // Both capture request and result
+    static const std::array<uint32_t, 1> kRectsToCorrect;
+
+    // Only for capture results; don't clamp
+    static const std::array<uint32_t, 2> kResultPointsToCorrectNoClamp;
+}; // class CoordinateMapper
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.cpp b/services/camera/libcameraservice/device3/DistortionMapper.cpp
index ae7af8e..8132225 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.cpp
+++ b/services/camera/libcameraservice/device3/DistortionMapper.cpp
@@ -27,41 +27,14 @@
 
 namespace camera3 {
 
-/**
- * Metadata keys to correct when adjusting coordinates for distortion correction
- */
-
-// Both capture request and result
-constexpr std::array<uint32_t, 3> DistortionMapper::kMeteringRegionsToCorrect = {
-    ANDROID_CONTROL_AF_REGIONS,
-    ANDROID_CONTROL_AE_REGIONS,
-    ANDROID_CONTROL_AWB_REGIONS
-};
-
-// Only capture request
-constexpr std::array<uint32_t, 1> DistortionMapper::kRequestRectsToCorrect = {
-    ANDROID_SCALER_CROP_REGION,
-};
-
-// Only for capture result
-constexpr std::array<uint32_t, 1> DistortionMapper::kResultRectsToCorrect = {
-    ANDROID_SCALER_CROP_REGION,
-};
-
-// Only for capture result
-constexpr std::array<uint32_t, 2> DistortionMapper::kResultPointsToCorrectNoClamp = {
-    ANDROID_STATISTICS_FACE_RECTANGLES, // Says rectangles, is really points
-    ANDROID_STATISTICS_FACE_LANDMARKS,
-};
-
 
 DistortionMapper::DistortionMapper() : mValidMapping(false), mValidGrids(false) {
 }
 
-bool DistortionMapper::isDistortionSupported(const CameraMetadata &result) {
+bool DistortionMapper::isDistortionSupported(const CameraMetadata &deviceInfo) {
     bool isDistortionCorrectionSupported = false;
     camera_metadata_ro_entry_t distortionCorrectionModes =
-            result.find(ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES);
+            deviceInfo.find(ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES);
     for (size_t i = 0; i < distortionCorrectionModes.count; i++) {
         if (distortionCorrectionModes.data.u8[i] !=
                 ANDROID_DISTORTION_CORRECTION_MODE_OFF) {
@@ -124,7 +97,7 @@
                 if (res != OK) return res;
             }
         }
-        for (auto rect : kRequestRectsToCorrect) {
+        for (auto rect : kRectsToCorrect) {
             e = request->find(rect);
             res = mapCorrectedRectToRaw(e.data.i32, e.count / 4, /*clamp*/true);
             if (res != OK) return res;
@@ -160,7 +133,7 @@
                 if (res != OK) return res;
             }
         }
-        for (auto rect : kResultRectsToCorrect) {
+        for (auto rect : kRectsToCorrect) {
             e = result->find(rect);
             res = mapRawRectToCorrected(e.data.i32, e.count / 4, /*clamp*/true);
             if (res != OK) return res;
@@ -390,7 +363,6 @@
     return OK;
 }
 
-
 status_t DistortionMapper::mapCorrectedRectToRaw(int32_t *rects, int rectCount, bool clamp,
         bool simple) const {
     if (!mValidMapping) return INVALID_OPERATION;
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.h b/services/camera/libcameraservice/device3/DistortionMapper.h
index 4c0a1a6..7dcb67b 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.h
+++ b/services/camera/libcameraservice/device3/DistortionMapper.h
@@ -22,6 +22,7 @@
 #include <mutex>
 
 #include "camera/CameraMetadata.h"
+#include "device3/CoordinateMapper.h"
 
 namespace android {
 
@@ -31,10 +32,19 @@
  * Utilities to transform between raw (distorted) and warped (corrected) coordinate systems
  * for cameras that support geometric distortion
  */
-class DistortionMapper {
+class DistortionMapper : private CoordinateMapper {
   public:
     DistortionMapper();
 
+    DistortionMapper(const DistortionMapper& other) :
+            mValidMapping(other.mValidMapping), mValidGrids(other.mValidGrids),
+            mFx(other.mFx), mFy(other.mFy), mCx(other.mCx), mCy(other.mCy), mS(other.mS),
+            mInvFx(other.mInvFx), mInvFy(other.mInvFy), mK(other.mK),
+            mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight),
+            mActiveWidth(other.mActiveWidth), mActiveHeight(other.mActiveHeight),
+            mArrayDiffX(other.mArrayDiffX), mArrayDiffY(other.mArrayDiffY),
+            mCorrectedGrid(other.mCorrectedGrid), mDistortedGrid(other.mDistortedGrid) {}
+
     /**
      * Check whether distortion correction is supported by the camera HAL
      */
@@ -150,20 +160,6 @@
     // Fuzziness for float inequality tests
     constexpr static float kFloatFuzz = 1e-4;
 
-    // Metadata key lists to correct
-
-    // Both capture request and result
-    static const std::array<uint32_t, 3> kMeteringRegionsToCorrect;
-
-    // Only capture request
-    static const std::array<uint32_t, 1> kRequestRectsToCorrect;
-
-    // Only capture result
-    static const std::array<uint32_t, 1> kResultRectsToCorrect;
-
-    // Only for capture results; don't clamp
-    static const std::array<uint32_t, 2> kResultPointsToCorrectNoClamp;
-
     // Single implementation for various mapCorrectedToRaw methods
     template<typename T>
     status_t mapCorrectedToRawImpl(T* coordPairs, int coordCount, bool clamp, bool simple) const;
@@ -186,7 +182,7 @@
     // pre-calculated inverses for speed
     float mInvFx, mInvFy;
     // radial/tangential distortion parameters
-    float mK[5];
+    std::array<float, 5> mK;
 
     // pre-correction active array dimensions
     float mArrayWidth, mArrayHeight;
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
new file mode 100644
index 0000000..da4f228
--- /dev/null
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_CAMERA3_INFLIGHT_REQUEST_H
+#define ANDROID_SERVERS_CAMERA3_INFLIGHT_REQUEST_H
+
+#include <set>
+
+#include <camera/CaptureResult.h>
+#include <camera/CameraMetadata.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "hardware/camera3.h"
+
+#include "common/CameraDeviceBase.h"
+
+namespace android {
+
+namespace camera3 {
+
+typedef enum {
+    // Cache the buffers with STATUS_ERROR within InFlightRequest
+    ERROR_BUF_CACHE,
+    // Return the buffers with STATUS_ERROR to the buffer queue
+    ERROR_BUF_RETURN,
+    // Return the buffers with STATUS_ERROR to the buffer queue, and call
+    // notify(ERROR_BUFFER) as well
+    ERROR_BUF_RETURN_NOTIFY
+} ERROR_BUF_STRATEGY;
+
+struct InFlightRequest {
+
+    // Set by notify() SHUTTER call.
+    nsecs_t shutterTimestamp;
+    // Set by process_capture_result().
+    nsecs_t sensorTimestamp;
+    int     requestStatus;
+    // Set by process_capture_result call with valid metadata
+    bool    haveResultMetadata;
+    // Decremented by calls to process_capture_result with valid output
+    // and input buffers
+    int     numBuffersLeft;
+
+    // The inflight request is considered complete if all buffers are returned
+
+    CaptureResultExtras resultExtras;
+    // If this request has any input buffer
+    bool hasInputBuffer;
+
+    // The last metadata that framework receives from HAL and
+    // not yet send out because the shutter event hasn't arrived.
+    // It's added by process_capture_result and sent when framework
+    // receives the shutter event.
+    CameraMetadata pendingMetadata;
+
+    // The metadata of the partial results that framework receives from HAL so far
+    // and has sent out.
+    CameraMetadata collectedPartialResult;
+
+    // Buffers are added by process_capture_result when output buffers
+    // return from HAL but framework has not yet received the shutter
+    // event. They will be returned to the streams when framework receives
+    // the shutter event.
+    Vector<camera3_stream_buffer_t> pendingOutputBuffers;
+
+    // Whether this inflight request's shutter and result callback are to be
+    // called. The policy is that if the request is the last one in the constrained
+    // high speed recording request list, this flag will be true. If the request list
+    // is not for constrained high speed recording, this flag will also be true.
+    bool hasCallback;
+
+    // Maximum expected frame duration for this request.
+    // For manual captures, equal to the max of requested exposure time and frame duration
+    // For auto-exposure modes, equal to 1/(lower end of target FPS range)
+    nsecs_t maxExpectedDuration;
+
+    // Whether the result metadata for this request is to be skipped. The
+    // result metadata should be skipped in the case of
+    // REQUEST/RESULT error.
+    bool skipResultMetadata;
+
+    // Whether the buffers with STATUS_ERROR should be cached as pending buffers,
+    // returned to the buffer queue, or returned to the buffer queue and notify with ERROR_BUFFER.
+    ERROR_BUF_STRATEGY errorBufStrategy;
+
+    // The physical camera ids being requested.
+    std::set<String8> physicalCameraIds;
+
+    // Map of physicalCameraId <-> Metadata
+    std::vector<PhysicalCaptureResultInfo> physicalMetadatas;
+
+    // Indicates a still capture request.
+    bool stillCapture;
+
+    // Indicates a ZSL capture request
+    bool zslCapture;
+
+    // Indicates that ROTATE_AND_CROP was set to AUTO
+    bool rotateAndCropAuto;
+
+    // Requested camera ids (both logical and physical) with zoomRatio != 1.0f
+    std::set<std::string> cameraIdsWithZoom;
+
+    // What shared surfaces an output should go to
+    SurfaceMap outputSurfaces;
+
+    // TODO: dedupe
+    static const nsecs_t kDefaultExpectedDuration = 100000000; // 100 ms
+
+    // Default constructor needed by KeyedVector
+    InFlightRequest() :
+            shutterTimestamp(0),
+            sensorTimestamp(0),
+            requestStatus(OK),
+            haveResultMetadata(false),
+            numBuffersLeft(0),
+            hasInputBuffer(false),
+            hasCallback(true),
+            maxExpectedDuration(kDefaultExpectedDuration),
+            skipResultMetadata(false),
+            errorBufStrategy(ERROR_BUF_CACHE),
+            stillCapture(false),
+            zslCapture(false),
+            rotateAndCropAuto(false) {
+    }
+
+    InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
+            bool hasAppCallback, nsecs_t maxDuration,
+            const std::set<String8>& physicalCameraIdSet, bool isStillCapture,
+            bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& idsWithZoom,
+            const SurfaceMap& outSurfaces = SurfaceMap{}) :
+            shutterTimestamp(0),
+            sensorTimestamp(0),
+            requestStatus(OK),
+            haveResultMetadata(false),
+            numBuffersLeft(numBuffers),
+            resultExtras(extras),
+            hasInputBuffer(hasInput),
+            hasCallback(hasAppCallback),
+            maxExpectedDuration(maxDuration),
+            skipResultMetadata(false),
+            errorBufStrategy(ERROR_BUF_CACHE),
+            physicalCameraIds(physicalCameraIdSet),
+            stillCapture(isStillCapture),
+            zslCapture(isZslCapture),
+            rotateAndCropAuto(rotateAndCropAuto),
+            cameraIdsWithZoom(idsWithZoom),
+            outputSurfaces(outSurfaces) {
+    }
+};
+
+// Map from frame number to the in-flight request state
+typedef KeyedVector<uint32_t, InFlightRequest> InFlightRequestMap;
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp b/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp
new file mode 100644
index 0000000..3718f54
--- /dev/null
+++ b/services/camera/libcameraservice/device3/RotateAndCropMapper.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera3-RotCropMapper"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <cmath>
+
+#include "device3/RotateAndCropMapper.h"
+
+namespace android {
+
+namespace camera3 {
+
+bool RotateAndCropMapper::isNeeded(const CameraMetadata* deviceInfo) {
+    auto entry = deviceInfo->find(ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES);
+    for (size_t i = 0; i < entry.count; i++) {
+        if (entry.data.u8[i] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return true;
+    }
+    return false;
+}
+
+RotateAndCropMapper::RotateAndCropMapper(const CameraMetadata* deviceInfo) {
+    auto entry = deviceInfo->find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+    if (entry.count != 4) return;
+
+    mArrayWidth = entry.data.i32[2];
+    mArrayHeight = entry.data.i32[3];
+    mArrayAspect = static_cast<float>(mArrayWidth) / mArrayHeight;
+    mRotateAspect = 1.f/mArrayAspect;
+}
+
+/**
+ * Adjust capture request when rotate and crop AUTO is enabled
+ */
+status_t RotateAndCropMapper::updateCaptureRequest(CameraMetadata *request) {
+    auto entry = request->find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if (entry.count == 0) return OK;
+    uint8_t rotateMode = entry.data.u8[0];
+    if (rotateMode == ANDROID_SCALER_ROTATE_AND_CROP_NONE) return OK;
+
+    int32_t cx = 0;
+    int32_t cy = 0;
+    int32_t cw = mArrayWidth;
+    int32_t ch = mArrayHeight;
+    entry = request->find(ANDROID_SCALER_CROP_REGION);
+    if (entry.count == 4) {
+        cx = entry.data.i32[0];
+        cy = entry.data.i32[1];
+        cw = entry.data.i32[2];
+        ch = entry.data.i32[3];
+    }
+
+    // User inputs are relative to the rotated-and-cropped view, so convert back
+    // to active array coordinates. To be more specific, the application is
+    // calculating coordinates based on the crop rectangle and the active array,
+    // even though the view the user sees is the cropped-and-rotated one. So we
+    // need to adjust the coordinates so that a point that would be on the
+    // top-left corner of the crop region is mapped to the top-left corner of
+    // the rotated-and-cropped fov within the crop region, and the same for the
+    // bottom-right corner.
+    //
+    // Since the zoom ratio control scales everything uniformly (so an app does
+    // not need to adjust anything if it wants to put a metering region on the
+    // top-left quadrant of the preview FOV, when changing zoomRatio), it does
+    // not need to be factored into this calculation at all.
+    //
+    //   ->+x                       active array  aw
+    //  |+--------------------------------------------------------------------+
+    //  v|                                                                    |
+    // +y|         a         1       cw        2           b                  |
+    //   |          +=========*HHHHHHHHHHHHHHH*===========+                   |
+    //   |          I         H      rw       H           I                   |
+    //   |          I         H               H           I                   |
+    //   |          I         H               H           I                   |
+    //ah |       ch I         H rh            H           I crop region       |
+    //   |          I         H               H           I                   |
+    //   |          I         H               H           I                   |
+    //   |          I         H rotate region H           I                   |
+    //   |          +=========*HHHHHHHHHHHHHHH*===========+                   |
+    //   |         d         4                 3           c                  |
+    //   |                                                                    |
+    //   +--------------------------------------------------------------------+
+    //
+    // aw , ah = active array width,height
+    // cw , ch = crop region width,height
+    // rw , rh = rotated-and-cropped region width,height
+    // aw / ah = array aspect = rh / rw = 1 / rotated aspect
+    // Coordinate mappings:
+    //    ROTATE_AND_CROP_90: point a -> point 2
+    //                        point c -> point 4 = +x -> +y, +y -> -x
+    //    ROTATE_AND_CROP_180: point a -> point c
+    //                         point c -> point a = +x -> -x, +y -> -y
+    //    ROTATE_AND_CROP_270: point a -> point 4
+    //                         point c -> point 2 = +x -> -y, +y -> +x
+
+    float cropAspect = static_cast<float>(cw) / ch;
+    float transformMat[4] = {0, 0,
+                             0, 0};
+    float xShift = 0;
+    float yShift = 0;
+
+    if (rotateMode == ANDROID_SCALER_ROTATE_AND_CROP_180) {
+        transformMat[0] = -1;
+        transformMat[3] = -1;
+        xShift = cw;
+        yShift = ch;
+    } else {
+        float rw = cropAspect > mRotateAspect ?
+                   ch * mRotateAspect : // pillarbox, not full width
+                   cw;                  // letterbox or 1:1, full width
+        float rh = cropAspect >= mRotateAspect ?
+                   ch :                 // pillarbox or 1:1, full height
+                   cw / mRotateAspect;  // letterbox, not full height
+        switch (rotateMode) {
+            case ANDROID_SCALER_ROTATE_AND_CROP_90:
+                transformMat[1] = -rw / ch; // +y -> -x
+                transformMat[2] =  rh / cw; // +x -> +y
+                xShift = (cw + rw) / 2; // left edge of crop to right edge of rotated
+                yShift = (ch - rh) / 2; // top edge of crop to top edge of rotated
+                break;
+            case ANDROID_SCALER_ROTATE_AND_CROP_270:
+                transformMat[1] =  rw / ch; // +y -> +x
+                transformMat[2] = -rh / cw; // +x -> -y
+                xShift = (cw - rw) / 2; // left edge of crop to left edge of rotated
+                yShift = (ch + rh) / 2; // top edge of crop to bottom edge of rotated
+                break;
+            default:
+                ALOGE("%s: Unexpected rotate mode: %d", __FUNCTION__, rotateMode);
+                return BAD_VALUE;
+        }
+    }
+
+    for (auto regionTag : kMeteringRegionsToCorrect) {
+        entry = request->find(regionTag);
+        for (size_t i = 0; i < entry.count; i += 5) {
+            int32_t weight = entry.data.i32[i + 4];
+            if (weight == 0) {
+                continue;
+            }
+            transformPoints(entry.data.i32 + i, 2, transformMat, xShift, yShift, cx, cy);
+            swapRectToMinFirst(entry.data.i32 + i);
+        }
+    }
+
+    return OK;
+}
+
+/**
+ * Adjust capture result when rotate and crop AUTO is enabled
+ */
+status_t RotateAndCropMapper::updateCaptureResult(CameraMetadata *result) {
+    auto entry = result->find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if (entry.count == 0) return OK;
+    uint8_t rotateMode = entry.data.u8[0];
+    if (rotateMode == ANDROID_SCALER_ROTATE_AND_CROP_NONE) return OK;
+
+    int32_t cx = 0;
+    int32_t cy = 0;
+    int32_t cw = mArrayWidth;
+    int32_t ch = mArrayHeight;
+    entry = result->find(ANDROID_SCALER_CROP_REGION);
+    if (entry.count == 4) {
+        cx = entry.data.i32[0];
+        cy = entry.data.i32[1];
+        cw = entry.data.i32[2];
+        ch = entry.data.i32[3];
+    }
+
+    // HAL inputs are relative to the full active array, so convert back to
+    // rotated-and-cropped coordinates for apps. To be more specific, the
+    // application is calculating coordinates based on the crop rectangle and
+    // the active array, even though the view the user sees is the
+    // cropped-and-rotated one. So we need to adjust the coordinates so that a
+    // point that would be on the top-left corner of the rotate-and-cropped
+    // region is mapped to the top-left corner of the crop region, and the same
+    // for the bottom-right corner.
+    //
+    // Since the zoom ratio control scales everything uniformly (so an app does
+    // not need to adjust anything if it wants to put a metering region on the
+    // top-left quadrant of the preview FOV, when changing zoomRatio), it does
+    // not need to be factored into this calculation at all.
+    //
+    // Also note that round-tripping between original request and final result
+    // fields can't be perfect, since the intermediate values have to be
+    // integers on a smaller range than the original crop region range. That
+    // means that multiple input values map to a single output value in
+    // adjusting a request, so when adjusting a result, the original answer may
+    // not be obtainable.  Given that aspect ratios are rarely > 16/9, the
+    // round-trip values should generally only be off by 1 at most.
+    //
+    //   ->+x                       active array  aw
+    //  |+--------------------------------------------------------------------+
+    //  v|                                                                    |
+    // +y|         a         1       cw        2           b                  |
+    //   |          +=========*HHHHHHHHHHHHHHH*===========+                   |
+    //   |          I         H      rw       H           I                   |
+    //   |          I         H               H           I                   |
+    //   |          I         H               H           I                   |
+    //ah |       ch I         H rh            H           I crop region       |
+    //   |          I         H               H           I                   |
+    //   |          I         H               H           I                   |
+    //   |          I         H rotate region H           I                   |
+    //   |          +=========*HHHHHHHHHHHHHHH*===========+                   |
+    //   |         d         4                 3           c                  |
+    //   |                                                                    |
+    //   +--------------------------------------------------------------------+
+    //
+    // aw , ah = active array width,height
+    // cw , ch = crop region width,height
+    // rw , rh = rotated-and-cropped region width,height
+    // aw / ah = array aspect = rh / rw = 1 / rotated aspect
+    // Coordinate mappings:
+    //    ROTATE_AND_CROP_90: point 2 -> point a
+    //                        point 4 -> point c = +x -> -y, +y -> +x
+    //    ROTATE_AND_CROP_180: point c -> point a
+    //                         point a -> point c = +x -> -x, +y -> -y
+    //    ROTATE_AND_CROP_270: point 4 -> point a
+    //                         point 2 -> point c = +x -> +y, +y -> -x
+
+    float cropAspect = static_cast<float>(cw) / ch;
+    float transformMat[4] = {0, 0,
+                             0, 0};
+    float xShift = 0;
+    float yShift = 0;
+    float rx = 0; // top-left corner of rotated region
+    float ry = 0;
+    if (rotateMode == ANDROID_SCALER_ROTATE_AND_CROP_180) {
+        transformMat[0] = -1;
+        transformMat[3] = -1;
+        xShift = cw;
+        yShift = ch;
+        rx = cx;
+        ry = cy;
+    } else {
+        float rw = cropAspect > mRotateAspect ?
+                   ch * mRotateAspect : // pillarbox, not full width
+                   cw;                  // letterbox or 1:1, full width
+        float rh = cropAspect >= mRotateAspect ?
+                   ch :                 // pillarbox or 1:1, full height
+                   cw / mRotateAspect;  // letterbox, not full height
+        rx = cx + (cw - rw) / 2;
+        ry = cy + (ch - rh) / 2;
+        switch (rotateMode) {
+            case ANDROID_SCALER_ROTATE_AND_CROP_90:
+                transformMat[1] =  ch / rw; // +y -> +x
+                transformMat[2] = -cw / rh; // +x -> -y
+                xShift = -(cw - rw) / 2; // left edge of rotated to left edge of cropped
+                yShift = ry - cy + ch;   // top edge of rotated to bottom edge of cropped
+                break;
+            case ANDROID_SCALER_ROTATE_AND_CROP_270:
+                transformMat[1] = -ch / rw; // +y -> -x
+                transformMat[2] =  cw / rh; // +x -> +y
+                xShift = (cw + rw) / 2; // left edge of rotated to left edge of cropped
+                yShift = (ch - rh) / 2; // top edge of rotated to bottom edge of cropped
+                break;
+            default:
+                ALOGE("%s: Unexpected rotate mode: %d", __FUNCTION__, rotateMode);
+                return BAD_VALUE;
+        }
+    }
+
+    for (auto regionTag : kMeteringRegionsToCorrect) {
+        entry = result->find(regionTag);
+        for (size_t i = 0; i < entry.count; i += 5) {
+            int32_t weight = entry.data.i32[i + 4];
+            if (weight == 0) {
+                continue;
+            }
+            transformPoints(entry.data.i32 + i, 2, transformMat, xShift, yShift, rx, ry);
+            swapRectToMinFirst(entry.data.i32 + i);
+        }
+    }
+
+    for (auto pointsTag: kResultPointsToCorrectNoClamp) {
+        entry = result->find(pointsTag);
+        transformPoints(entry.data.i32, entry.count / 2, transformMat, xShift, yShift, rx, ry);
+        if (pointsTag == ANDROID_STATISTICS_FACE_RECTANGLES) {
+            for (size_t i = 0; i < entry.count; i += 4) {
+                swapRectToMinFirst(entry.data.i32 + i);
+            }
+        }
+    }
+
+    return OK;
+}
+
+void RotateAndCropMapper::transformPoints(int32_t* pts, size_t count, float transformMat[4],
+        float xShift, float yShift, float ox, float oy) {
+    for (size_t i = 0; i < count * 2; i += 2) {
+        float x0 = pts[i] - ox;
+        float y0 = pts[i + 1] - oy;
+        int32_t nx = std::round(transformMat[0] * x0 + transformMat[1] * y0 + xShift + ox);
+        int32_t ny = std::round(transformMat[2] * x0 + transformMat[3] * y0 + yShift + oy);
+
+        pts[i] = std::min(std::max(nx, 0), mArrayWidth);
+        pts[i + 1] = std::min(std::max(ny, 0), mArrayHeight);
+    }
+}
+
+void RotateAndCropMapper::swapRectToMinFirst(int32_t* rect) {
+    if (rect[0] > rect[2]) {
+        auto tmp = rect[0];
+        rect[0] = rect[2];
+        rect[2] = tmp;
+    }
+    if (rect[1] > rect[3]) {
+        auto tmp = rect[1];
+        rect[1] = rect[3];
+        rect[3] = tmp;
+    }
+}
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/RotateAndCropMapper.h b/services/camera/libcameraservice/device3/RotateAndCropMapper.h
new file mode 100644
index 0000000..459e27f
--- /dev/null
+++ b/services/camera/libcameraservice/device3/RotateAndCropMapper.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_ROTATEANDCROPMAPPER_H
+#define ANDROID_SERVERS_ROTATEANDCROPMAPPER_H
+
+#include <utils/Errors.h>
+#include <array>
+#include <mutex>
+
+#include "camera/CameraMetadata.h"
+#include "device3/CoordinateMapper.h"
+
+namespace android {
+
+namespace camera3 {
+
+/**
+ * Utilities to transform between unrotated and rotated-and-cropped coordinate systems
+ * for cameras that support SCALER_ROTATE_AND_CROP controls in AUTO mode.
+ */
+class RotateAndCropMapper : private CoordinateMapper {
+  public:
+    static bool isNeeded(const CameraMetadata* deviceInfo);
+
+    RotateAndCropMapper(const CameraMetadata* deviceInfo);
+
+    /**
+     * Adjust capture request assuming rotate and crop AUTO is enabled
+     */
+    status_t updateCaptureRequest(CameraMetadata *request);
+
+    /**
+     * Adjust capture result assuming rotate and crop AUTO is enabled
+     */
+    status_t updateCaptureResult(CameraMetadata *result);
+
+  private:
+    // Transform count's worth of x,y points passed in with 2x2 matrix + translate with transform
+    // origin (cx,cy)
+    void transformPoints(int32_t* pts, size_t count, float transformMat[4],
+            float xShift, float yShift, float cx, float cy);
+    // Take two corners of a rect as (x1,y1,x2,y2) and swap x and y components
+    // if needed so that x1 < x2, y1 < y2.
+    void swapRectToMinFirst(int32_t* rect);
+
+    int32_t mArrayWidth, mArrayHeight;
+    float mArrayAspect, mRotateAspect;
+}; // class RotateAndCroMapper
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
new file mode 100644
index 0000000..a87de77
--- /dev/null
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2019 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_TAG "Camera3-ZoomRatioMapper"
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+
+#include "device3/ZoomRatioMapper.h"
+
+namespace android {
+
+namespace camera3 {
+
+
+status_t ZoomRatioMapper::initZoomRatioInTemplate(CameraMetadata *request) {
+    camera_metadata_entry_t entry;
+    entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
+    float defaultZoomRatio = 1.0f;
+    if (entry.count == 0) {
+        return request->update(ANDROID_CONTROL_ZOOM_RATIO, &defaultZoomRatio, 1);
+    }
+    return OK;
+}
+
+status_t ZoomRatioMapper::overrideZoomRatioTags(
+        CameraMetadata* deviceInfo, bool* supportNativeZoomRatio) {
+    if (deviceInfo == nullptr || supportNativeZoomRatio == nullptr) {
+        return BAD_VALUE;
+    }
+
+    camera_metadata_entry_t entry;
+    entry = deviceInfo->find(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
+    if (entry.count != 2 && entry.count != 0) return BAD_VALUE;
+
+    // Hal has zoom ratio support
+    if (entry.count == 2) {
+        *supportNativeZoomRatio = true;
+        return OK;
+    }
+
+    // Hal has no zoom ratio support
+    *supportNativeZoomRatio = false;
+
+    entry = deviceInfo->find(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
+    if (entry.count != 1) {
+        ALOGI("%s: Camera device doesn't support SCALER_AVAILABLE_MAX_DIGITAL_ZOOM key!",
+                __FUNCTION__);
+        return OK;
+    }
+
+    float zoomRange[] = {1.0f, entry.data.f[0]};
+    status_t res = deviceInfo->update(ANDROID_CONTROL_ZOOM_RATIO_RANGE, zoomRange, 2);
+    if (res != OK) {
+        ALOGE("%s: Failed to update CONTROL_ZOOM_RATIO_RANGE key: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    std::vector<int32_t> requestKeys;
+    entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
+    if (entry.count > 0) {
+        requestKeys.insert(requestKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
+    }
+    requestKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO);
+    res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
+            requestKeys.data(), requestKeys.size());
+    if (res != OK) {
+        ALOGE("%s: Failed to update REQUEST_AVAILABLE_REQUEST_KEYS: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    std::vector<int32_t> resultKeys;
+    entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS);
+    if (entry.count > 0) {
+        resultKeys.insert(resultKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
+    }
+    resultKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO);
+    res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
+            resultKeys.data(), resultKeys.size());
+    if (res != OK) {
+        ALOGE("%s: Failed to update REQUEST_AVAILABLE_RESULT_KEYS: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    std::vector<int32_t> charKeys;
+    entry = deviceInfo->find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+    if (entry.count > 0) {
+        charKeys.insert(charKeys.end(), entry.data.i32, entry.data.i32 + entry.count);
+    }
+    charKeys.push_back(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
+    res = deviceInfo->update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+            charKeys.data(), charKeys.size());
+    if (res != OK) {
+        ALOGE("%s: Failed to update REQUEST_AVAILABLE_CHARACTERISTICS_KEYS: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    return OK;
+}
+
+ZoomRatioMapper::ZoomRatioMapper(const CameraMetadata* deviceInfo,
+        bool supportNativeZoomRatio, bool usePrecorrectArray) {
+    camera_metadata_ro_entry_t entry;
+
+    entry = deviceInfo->find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+    if (entry.count != 4) return;
+    int32_t arrayW = entry.data.i32[2];
+    int32_t arrayH = entry.data.i32[3];
+
+    entry = deviceInfo->find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+    if (entry.count != 4) return;
+    int32_t activeW = entry.data.i32[2];
+    int32_t activeH = entry.data.i32[3];
+
+    if (usePrecorrectArray) {
+        mArrayWidth = arrayW;
+        mArrayHeight = arrayH;
+    } else {
+        mArrayWidth = activeW;
+        mArrayHeight = activeH;
+    }
+    mHalSupportsZoomRatio = supportNativeZoomRatio;
+
+    ALOGV("%s: array size: %d x %d, mHalSupportsZoomRatio %d",
+            __FUNCTION__, mArrayWidth, mArrayHeight, mHalSupportsZoomRatio);
+    mIsValid = true;
+}
+
+status_t ZoomRatioMapper::updateCaptureRequest(CameraMetadata* request) {
+    if (!mIsValid) return INVALID_OPERATION;
+
+    status_t res = OK;
+    bool zoomRatioIs1 = true;
+    camera_metadata_entry_t entry;
+
+    entry = request->find(ANDROID_CONTROL_ZOOM_RATIO);
+    if (entry.count == 1 && entry.data.f[0] != 1.0f) {
+        zoomRatioIs1 = false;
+    }
+
+    if (mHalSupportsZoomRatio && zoomRatioIs1) {
+        res = separateZoomFromCropLocked(request, false/*isResult*/);
+    } else if (!mHalSupportsZoomRatio && !zoomRatioIs1) {
+        res = combineZoomAndCropLocked(request, false/*isResult*/);
+    }
+
+    // If CONTROL_ZOOM_RATIO is in request, but HAL doesn't support
+    // CONTROL_ZOOM_RATIO, remove it from the request.
+    if (!mHalSupportsZoomRatio && entry.count == 1) {
+        request->erase(ANDROID_CONTROL_ZOOM_RATIO);
+    }
+
+    return res;
+}
+
+status_t ZoomRatioMapper::updateCaptureResult(CameraMetadata* result, bool requestedZoomRatioIs1) {
+    if (!mIsValid) return INVALID_OPERATION;
+
+    status_t res = OK;
+
+    if (mHalSupportsZoomRatio && requestedZoomRatioIs1) {
+        res = combineZoomAndCropLocked(result, true/*isResult*/);
+    } else if (!mHalSupportsZoomRatio && !requestedZoomRatioIs1) {
+        res = separateZoomFromCropLocked(result, true/*isResult*/);
+    } else {
+        camera_metadata_entry_t entry = result->find(ANDROID_CONTROL_ZOOM_RATIO);
+        if (entry.count == 0) {
+            float zoomRatio1x = 1.0f;
+            result->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio1x, 1);
+        }
+    }
+
+    return res;
+}
+
+float ZoomRatioMapper::deriveZoomRatio(const CameraMetadata* metadata) {
+    float zoomRatio = 1.0;
+
+    camera_metadata_ro_entry_t entry;
+    entry = metadata->find(ANDROID_SCALER_CROP_REGION);
+    if (entry.count != 4) return zoomRatio;
+
+    // Center of the preCorrection/active size
+    float arrayCenterX = mArrayWidth / 2.0;
+    float arrayCenterY = mArrayHeight / 2.0;
+
+    // Re-map crop region to coordinate system centered to (arrayCenterX,
+    // arrayCenterY).
+    float cropRegionLeft = arrayCenterX - entry.data.i32[0] ;
+    float cropRegionTop = arrayCenterY - entry.data.i32[1];
+    float cropRegionRight = entry.data.i32[0] + entry.data.i32[2] - arrayCenterX;
+    float cropRegionBottom = entry.data.i32[1] + entry.data.i32[3] - arrayCenterY;
+
+    // Calculate the scaling factor for left, top, bottom, right
+    float zoomRatioLeft = std::max(mArrayWidth / (2 * cropRegionLeft), 1.0f);
+    float zoomRatioTop = std::max(mArrayHeight / (2 * cropRegionTop), 1.0f);
+    float zoomRatioRight = std::max(mArrayWidth / (2 * cropRegionRight), 1.0f);
+    float zoomRatioBottom = std::max(mArrayHeight / (2 * cropRegionBottom), 1.0f);
+
+    // Use minimum scaling factor to handle letterboxing or pillarboxing
+    zoomRatio = std::min(std::min(zoomRatioLeft, zoomRatioRight),
+            std::min(zoomRatioTop, zoomRatioBottom));
+
+    ALOGV("%s: derived zoomRatio is %f", __FUNCTION__, zoomRatio);
+    return zoomRatio;
+}
+
+status_t ZoomRatioMapper::separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult) {
+    status_t res;
+    float zoomRatio = deriveZoomRatio(metadata);
+
+    // Update zoomRatio metadata tag
+    res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+    if (res != OK) {
+        ALOGE("%s: Failed to update ANDROID_CONTROL_ZOOM_RATIO: %s(%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    // Scale regions using zoomRatio
+    camera_metadata_entry_t entry;
+    for (auto region : kMeteringRegionsToCorrect) {
+        entry = metadata->find(region);
+        for (size_t j = 0; j < entry.count; j += 5) {
+            int32_t weight = entry.data.i32[j + 4];
+            if (weight == 0) {
+                continue;
+            }
+            // Top left (inclusive)
+            scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, true /*clamp*/);
+            // Bottom right (exclusive): Use adjacent inclusive pixel to
+            // calculate.
+            entry.data.i32[j+2] -= 1;
+            entry.data.i32[j+3] -= 1;
+            scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, true /*clamp*/);
+            entry.data.i32[j+2] += 1;
+            entry.data.i32[j+3] += 1;
+        }
+    }
+
+    for (auto rect : kRectsToCorrect) {
+        entry = metadata->find(rect);
+        scaleRects(entry.data.i32, entry.count / 4, zoomRatio);
+    }
+
+    if (isResult) {
+        for (auto pts : kResultPointsToCorrectNoClamp) {
+            entry = metadata->find(pts);
+            scaleCoordinates(entry.data.i32, entry.count / 2, zoomRatio, false /*clamp*/);
+        }
+    }
+
+    return OK;
+}
+
+status_t ZoomRatioMapper::combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult) {
+    float zoomRatio = 1.0f;
+    camera_metadata_entry_t entry;
+    entry = metadata->find(ANDROID_CONTROL_ZOOM_RATIO);
+    if (entry.count == 1) {
+        zoomRatio = entry.data.f[0];
+    }
+
+    // Unscale regions with zoomRatio
+    status_t res;
+    for (auto region : kMeteringRegionsToCorrect) {
+        entry = metadata->find(region);
+        for (size_t j = 0; j < entry.count; j += 5) {
+            int32_t weight = entry.data.i32[j + 4];
+            if (weight == 0) {
+                continue;
+            }
+            // Top-left (inclusive)
+            scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, true /*clamp*/);
+            // Bottom-right (exclusive): Use adjacent inclusive pixel to
+            // calculate.
+            entry.data.i32[j+2] -= 1;
+            entry.data.i32[j+3] -= 1;
+            scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, true /*clamp*/);
+            entry.data.i32[j+2] += 1;
+            entry.data.i32[j+3] += 1;
+        }
+    }
+    for (auto rect : kRectsToCorrect) {
+        entry = metadata->find(rect);
+        scaleRects(entry.data.i32, entry.count / 4, 1.0 / zoomRatio);
+    }
+    if (isResult) {
+        for (auto pts : kResultPointsToCorrectNoClamp) {
+            entry = metadata->find(pts);
+            scaleCoordinates(entry.data.i32, entry.count / 2, 1.0 / zoomRatio, false /*clamp*/);
+        }
+    }
+
+    zoomRatio = 1.0;
+    res = metadata->update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+    if (res != OK) {
+        return res;
+    }
+
+    return OK;
+}
+
+void ZoomRatioMapper::scaleCoordinates(int32_t* coordPairs, int coordCount,
+        float scaleRatio, bool clamp) {
+    // A pixel's coordinate is represented by the position of its top-left corner.
+    // To avoid the rounding error, we use the coordinate for the center of the
+    // pixel instead:
+    // 1. First shift the coordinate system half pixel both horizontally and
+    // vertically, so that [x, y] is the center of the pixel, not the top-left corner.
+    // 2. Do zoom operation to scale the coordinate relative to the center of
+    // the active array (shifted by 0.5 pixel as well).
+    // 3. Shift the coordinate system back by directly using the pixel center
+    // coordinate.
+    for (int i = 0; i < coordCount * 2; i += 2) {
+        float x = coordPairs[i];
+        float y = coordPairs[i + 1];
+        float xCentered = x - (mArrayWidth - 2) / 2;
+        float yCentered = y - (mArrayHeight - 2) / 2;
+        float scaledX = xCentered * scaleRatio;
+        float scaledY = yCentered * scaleRatio;
+        scaledX += (mArrayWidth - 2) / 2;
+        scaledY += (mArrayHeight - 2) / 2;
+        coordPairs[i] = static_cast<int32_t>(std::round(scaledX));
+        coordPairs[i+1] = static_cast<int32_t>(std::round(scaledY));
+        // Clamp to within activeArray/preCorrectionActiveArray
+        if (clamp) {
+            int32_t right = mArrayWidth - 1;
+            int32_t bottom = mArrayHeight - 1;
+            coordPairs[i] =
+                    std::min(right, std::max(0, coordPairs[i]));
+            coordPairs[i+1] =
+                    std::min(bottom, std::max(0, coordPairs[i+1]));
+        }
+        ALOGV("%s: coordinates: %d, %d", __FUNCTION__, coordPairs[i], coordPairs[i+1]);
+    }
+}
+
+void ZoomRatioMapper::scaleRects(int32_t* rects, int rectCount,
+        float scaleRatio) {
+    for (int i = 0; i < rectCount * 4; i += 4) {
+        // Map from (l, t, width, height) to (l, t, l+width-1, t+height-1),
+        // where both top-left and bottom-right are inclusive.
+        int32_t coords[4] = {
+            rects[i],
+            rects[i + 1],
+            rects[i] + rects[i + 2] - 1,
+            rects[i + 1] + rects[i + 3] - 1
+        };
+
+        // top-left
+        scaleCoordinates(coords, 1, scaleRatio, true /*clamp*/);
+        // bottom-right
+        scaleCoordinates(coords+2, 1, scaleRatio, true /*clamp*/);
+
+        // Map back to (l, t, width, height)
+        rects[i] = coords[0];
+        rects[i + 1] = coords[1];
+        rects[i + 2] = coords[2] - coords[0] + 1;
+        rects[i + 3] = coords[3] - coords[1] + 1;
+    }
+}
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.h b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
new file mode 100644
index 0000000..698f87f
--- /dev/null
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_SERVERS_ZOOMRATIOMAPPER_H
+#define ANDROID_SERVERS_ZOOMRATIOMAPPER_H
+
+#include <utils/Errors.h>
+#include <array>
+
+#include "camera/CameraMetadata.h"
+#include "device3/CoordinateMapper.h"
+
+namespace android {
+
+namespace camera3 {
+
+/**
+ * Utilities to convert between the new zoomRatio and existing cropRegion
+ * metadata tags. Note that this class does conversions in 2 scenarios:
+ * - HAL supports zoomRatio and the application uses cropRegion, or
+ * - HAL doesn't support zoomRatio, but the application uses zoomRatio
+ */
+class ZoomRatioMapper : private CoordinateMapper {
+  public:
+    ZoomRatioMapper() = default;
+    ZoomRatioMapper(const CameraMetadata *deviceInfo,
+            bool supportNativeZoomRatio, bool usePrecorrectArray);
+    ZoomRatioMapper(const ZoomRatioMapper& other) :
+            mHalSupportsZoomRatio(other.mHalSupportsZoomRatio),
+            mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight),
+            mIsValid(other.mIsValid) {}
+
+    /**
+     * Initialize request template with valid zoomRatio if necessary.
+     */
+    static status_t initZoomRatioInTemplate(CameraMetadata *request);
+
+    /**
+     * Override zoomRatio related tags in the static metadata.
+     */
+    static status_t overrideZoomRatioTags(
+            CameraMetadata* deviceInfo, bool* supportNativeZoomRatio);
+
+    /**
+     * Update capture request to handle both cropRegion and zoomRatio.
+     */
+    status_t updateCaptureRequest(CameraMetadata *request);
+
+    /**
+     * Update capture result to handle both cropRegion and zoomRatio.
+     */
+    status_t updateCaptureResult(CameraMetadata *request, bool requestedZoomRatioIs1);
+
+  public: // Visible for testing. Do not use concurently.
+    void scaleCoordinates(int32_t* coordPairs, int coordCount,
+            float scaleRatio, bool clamp);
+
+    bool isValid() { return mIsValid; }
+  private:
+    // const after construction
+    bool mHalSupportsZoomRatio;
+    // active array / pre-correction array dimension
+    int32_t mArrayWidth, mArrayHeight;
+
+    bool mIsValid = false;
+
+    float deriveZoomRatio(const CameraMetadata* metadata);
+    void scaleRects(int32_t* rects, int rectCount, float scaleRatio);
+
+    status_t separateZoomFromCropLocked(CameraMetadata* metadata, bool isResult);
+    status_t combineZoomAndCropLocked(CameraMetadata* metadata, bool isResult);
+};
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
index 110ef8e..8e619e1 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
@@ -25,6 +25,7 @@
 namespace implementation {
 
 using hardware::cameraservice::utils::conversion::convertToHidlCameraDeviceStatus;
+typedef frameworks::cameraservice::service::V2_1::ICameraServiceListener HCameraServiceListener2_1;
 
 binder::Status H2BCameraServiceListener::onStatusChanged(
     int32_t status, const ::android::String16& cameraId) {
@@ -40,6 +41,29 @@
   return binder::Status::ok();
 }
 
+binder::Status H2BCameraServiceListener::onPhysicalCameraStatusChanged(
+    int32_t status, const ::android::String16& cameraId,
+    const ::android::String16& physicalCameraId) {
+  auto cast2_1 = HCameraServiceListener2_1::castFrom(mBase);
+  sp<HCameraServiceListener2_1> interface2_1 = nullptr;
+  if (cast2_1.isOk()) {
+    interface2_1 = cast2_1;
+    if (interface2_1 != nullptr) {
+      HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status);
+      V2_1::PhysicalCameraStatusAndId cameraStatusAndId;
+      cameraStatusAndId.deviceStatus = hCameraDeviceStatus;
+      cameraStatusAndId.cameraId = String8(cameraId).string();
+      cameraStatusAndId.physicalCameraId = String8(physicalCameraId).string();
+      auto ret = interface2_1->onPhysicalCameraStatusChanged(cameraStatusAndId);
+      if (!ret.isOk()) {
+        ALOGE("%s OnPhysicalCameraStatusChanged callback failed due to %s",__FUNCTION__,
+            ret.description().c_str());
+      }
+    }
+  }
+  return binder::Status::ok();
+}
+
 ::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged(
     int32_t, const ::android::String16&) {
   // We don't implement onTorchStatusChanged
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index b9e5857..7148035 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -19,6 +19,7 @@
 
 #include <android/frameworks/cameraservice/common/2.0/types.h>
 #include <android/frameworks/cameraservice/service/2.0/ICameraServiceListener.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 #include <android/hardware/BnCameraServiceListener.h>
 #include <android/hardware/BpCameraServiceListener.h>
@@ -46,10 +47,13 @@
     ~H2BCameraServiceListener() { }
 
     virtual ::android::binder::Status onStatusChanged(int32_t status,
-                                                      const ::android::String16& cameraId) override;
+            const ::android::String16& cameraId) override;
+    virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
+            const ::android::String16& cameraId,
+            const ::android::String16& physicalCameraId) override;
 
     virtual ::android::binder::Status onTorchStatusChanged(
-        int32_t status, const ::android::String16& cameraId) override;
+            int32_t status, const ::android::String16& cameraId) override;
     virtual binder::Status onCameraAccessPrioritiesChanged() {
         // TODO: no implementation yet.
         return binder::Status::ok();
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 866c3b5..597147b 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -197,6 +197,23 @@
     return;
 }
 
+void convertToHidl(const std::vector<hardware::CameraStatus> &src,
+                   hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* dst) {
+    dst->resize(src.size());
+    size_t i = 0;
+    for (const auto &statusAndId : src) {
+        auto &a = (*dst)[i++];
+        a.v2_0.cameraId = statusAndId.cameraId.c_str();
+        a.v2_0.deviceStatus = convertToHidlCameraDeviceStatus(statusAndId.status);
+        size_t numUnvailPhysicalCameras = statusAndId.unavailablePhysicalIds.size();
+        a.unavailPhysicalCameraIds.resize(numUnvailPhysicalCameras);
+        for (size_t j = 0; j < numUnvailPhysicalCameras; j++) {
+            a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j].c_str();
+        }
+    }
+    return;
+}
+
 void convertToHidl(
     const hardware::camera2::utils::SubmitInfo &submitInfo,
     frameworks::cameraservice::device::V2_0::SubmitInfo *hSubmitInfo) {
diff --git a/services/camera/libcameraservice/hidl/Convert.h b/services/camera/libcameraservice/hidl/Convert.h
index 79683f6..82ffc48 100644
--- a/services/camera/libcameraservice/hidl/Convert.h
+++ b/services/camera/libcameraservice/hidl/Convert.h
@@ -23,6 +23,7 @@
 #include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
 #include <android/frameworks/cameraservice/common/2.0/types.h>
 #include <android/frameworks/cameraservice/service/2.0/types.h>
+#include <android/frameworks/cameraservice/service/2.1/types.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 #include <android/hardware/camera/common/1.0/types.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -79,6 +80,9 @@
 void convertToHidl(const std::vector<hardware::CameraStatus> &src,
                    hidl_vec<HCameraStatusAndId>* dst);
 
+void convertToHidl(const std::vector<hardware::CameraStatus> &src,
+                   hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId>* dst);
+
 void convertToHidl(const hardware::camera2::utils::SubmitInfo &submitInfo,
                    HSubmitInfo *hSubmitInfo);
 
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
index 675ad24..bf89ca5 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
@@ -201,8 +201,9 @@
         return HStatus::ILLEGAL_ARGUMENT;
     }
 
+    std::vector<int> offlineStreamIds;
     binder::Status ret = mDeviceRemote->endConfigure(convertFromHidl(operatingMode),
-                                                     cameraMetadata);
+                                                     cameraMetadata, &offlineStreamIds);
     return B2HStatus(ret);
 }
 
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 74cfe42..a46133e 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -103,7 +103,7 @@
     }
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mAidlICameraService->connectDevice(
-            callbacks, String16(cameraId.c_str()), String16(""),
+            callbacks, String16(cameraId.c_str()), String16(""), std::unique_ptr<String16>(),
             hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
@@ -154,15 +154,50 @@
 
 Return<void> HidlCameraService::addListener(const sp<HCameraServiceListener>& hCsListener,
                                             addListener_cb _hidl_cb) {
-    if (mAidlICameraService == nullptr) {
-        _hidl_cb(HStatus::UNKNOWN_ERROR, {});
+    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+    HStatus status = addListenerInternal<HCameraServiceListener>(
+            hCsListener, &cameraStatusAndIds);
+    if (status != HStatus::NO_ERROR) {
+        _hidl_cb(status, {});
         return Void();
     }
-    if (hCsListener == nullptr) {
-        ALOGE("%s listener must not be NULL", __FUNCTION__);
-        _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {});
+
+    hidl_vec<HCameraStatusAndId> hCameraStatusAndIds;
+    //Convert cameraStatusAndIds to HIDL and call callback
+    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
+    _hidl_cb(status, hCameraStatusAndIds);
+
+    return Void();
+}
+
+Return<void> HidlCameraService::addListener_2_1(const sp<HCameraServiceListener2_1>& hCsListener,
+                                                addListener_2_1_cb _hidl_cb) {
+    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+    HStatus status = addListenerInternal<HCameraServiceListener2_1>(
+            hCsListener, &cameraStatusAndIds);
+    if (status != HStatus::NO_ERROR) {
+        _hidl_cb(status, {});
         return Void();
     }
+
+    hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> hCameraStatusAndIds;
+    //Convert cameraStatusAndIds to HIDL and call callback
+    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
+    _hidl_cb(status, hCameraStatusAndIds);
+
+    return Void();
+}
+
+template<class T>
+HStatus HidlCameraService::addListenerInternal(const sp<T>& hCsListener,
+        std::vector<hardware::CameraStatus>* cameraStatusAndIds) {
+    if (mAidlICameraService == nullptr) {
+        return HStatus::UNKNOWN_ERROR;
+    }
+    if (hCsListener == nullptr || cameraStatusAndIds == nullptr) {
+        ALOGE("%s listener and cameraStatusAndIds must not be NULL", __FUNCTION__);
+        return HStatus::ILLEGAL_ARGUMENT;
+    }
     sp<hardware::ICameraServiceListener> csListener = nullptr;
     // Check the cache for previously registered callbacks
     {
@@ -177,25 +212,27 @@
         } else {
             ALOGE("%s: Trying to add a listener %p already registered",
                   __FUNCTION__, hCsListener.get());
-            _hidl_cb(HStatus::ILLEGAL_ARGUMENT, {});
-            return Void();
+            return HStatus::ILLEGAL_ARGUMENT;
         }
     }
-    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
     binder::Status serviceRet =
-        mAidlICameraService->addListenerHelper(csListener, &cameraStatusAndIds, true);
+            mAidlICameraService->addListenerHelper(csListener, cameraStatusAndIds, true);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
-      ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
-      status = B2HStatus(serviceRet);
-      _hidl_cb(status, {});
-      return Void();
+        ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
+        status = B2HStatus(serviceRet);
+        return status;
     }
-    hidl_vec<HCameraStatusAndId> hCameraStatusAndIds;
-    //Convert cameraStatusAndIds to HIDL and call callback
-    convertToHidl(cameraStatusAndIds, &hCameraStatusAndIds);
-    _hidl_cb(status, hCameraStatusAndIds);
-    return Void();
+    cameraStatusAndIds->erase(std::remove_if(cameraStatusAndIds->begin(), cameraStatusAndIds->end(),
+            [this](const hardware::CameraStatus& s) {
+                bool supportsHAL3 = false;
+                binder::Status sRet =
+                            mAidlICameraService->supportsCameraApi(String16(s.cameraId),
+                                    hardware::ICameraService::API_VERSION_2, &supportsHAL3);
+                return !sRet.isOk() || !supportsHAL3;
+            }), cameraStatusAndIds->end());
+
+    return HStatus::NO_ERROR;
 }
 
 Return<HStatus> HidlCameraService::removeListener(const sp<HCameraServiceListener>& hCsListener) {
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.h b/services/camera/libcameraservice/hidl/HidlCameraService.h
index eead0bc..097f4c5 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.h
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.h
@@ -21,7 +21,7 @@
 #include <thread>
 
 #include <android/frameworks/cameraservice/common/2.0/types.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
 #include <android/frameworks/cameraservice/service/2.0/types.h>
 #include <android/frameworks/cameraservice/device/2.0/types.h>
 
@@ -42,8 +42,9 @@
 
 using HCameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback;
 using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata;
-using HCameraService = frameworks::cameraservice::service::V2_0::ICameraService;
+using HCameraService = frameworks::cameraservice::service::V2_1::ICameraService;
 using HCameraServiceListener = frameworks::cameraservice::service::V2_0::ICameraServiceListener;
+using HCameraServiceListener2_1 = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
 using HStatus = frameworks::cameraservice::common::V2_0::Status;
 using HCameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
 
@@ -66,6 +67,9 @@
 
     Return<void> getCameraVendorTagSections(getCameraVendorTagSections_cb _hidl_cb) override;
 
+    Return<void> addListener_2_1(const sp<HCameraServiceListener2_1>& listener,
+                                 addListener_2_1_cb _hidl_cb) override;
+
     // This method should only be called by the cameraservers main thread to
     // instantiate the hidl cameraserver.
     static sp<HidlCameraService> getInstance(android::CameraService *cs);
@@ -76,6 +80,11 @@
     sp<hardware::ICameraServiceListener> searchListenerCacheLocked(
         sp<HCameraServiceListener> listener, /*removeIfFound*/ bool shouldRemove = false);
 
+
+    template<class T>
+    HStatus addListenerInternal(const sp<T>& listener,
+                                std::vector<hardware::CameraStatus>* cameraStatusAndIds);
+
     void addToListenerCacheLocked(sp<HCameraServiceListener> hListener,
                                   sp<hardware::ICameraServiceListener> csListener);
 
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index b4e7c32..3ead715 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -23,18 +23,23 @@
     libcameraservice \
     libhidlbase \
     liblog \
-    libhidltransport \
     libcamera_client \
     libcamera_metadata \
+    libui \
     libutils \
     libjpeg \
     libexif \
     android.hardware.camera.common@1.0 \
     android.hardware.camera.provider@2.4 \
     android.hardware.camera.provider@2.5 \
+    android.hardware.camera.provider@2.6 \
     android.hardware.camera.device@1.0 \
     android.hardware.camera.device@3.2 \
-    android.hardware.camera.device@3.4
+    android.hardware.camera.device@3.4 \
+    android.hidl.token@1.0-utils
+
+LOCAL_STATIC_LIBRARIES := \
+    libgmock
 
 LOCAL_C_INCLUDES += \
     system/media/private/camera/include \
@@ -43,6 +48,8 @@
 
 LOCAL_CFLAGS += -Wall -Wextra -Werror
 
+LOCAL_SANITIZE := address
+
 LOCAL_MODULE:= cameraservice_test
 LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index 78d737d..855b5ab 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -40,8 +40,15 @@
  */
 struct TestDeviceInterface : public device::V3_2::ICameraDevice {
     std::vector<hardware::hidl_string> mDeviceNames;
+    android::hardware::hidl_vec<uint8_t> mCharacteristics;
+
+    TestDeviceInterface(std::vector<hardware::hidl_string> deviceNames,
+            android::hardware::hidl_vec<uint8_t> chars) :
+        mDeviceNames(deviceNames), mCharacteristics(chars) {}
+
     TestDeviceInterface(std::vector<hardware::hidl_string> deviceNames) :
         mDeviceNames(deviceNames) {}
+
     using getResourceCost_cb = std::function<void(
             hardware::camera::common::V1_0::Status status,
             const hardware::camera::common::V1_0::CameraResourceCost& resourceCost)>;
@@ -58,8 +65,7 @@
             const hardware::hidl_vec<uint8_t>& cameraCharacteristics)>;
     hardware::Return<void> getCameraCharacteristics(
             getCameraCharacteristics_cb _hidl_cb) override {
-        hardware::hidl_vec<uint8_t> cameraCharacteristics;
-        _hidl_cb(Status::OK, cameraCharacteristics);
+        _hidl_cb(Status::OK, mCharacteristics);
         return hardware::Void();
     }
 
@@ -100,6 +106,13 @@
         mDeviceInterface(new TestDeviceInterface(devices)),
         mVendorTagSections (vendorSection) {}
 
+    TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
+            const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection,
+            android::hardware::hidl_vec<uint8_t> chars) :
+        mDeviceNames(devices),
+        mDeviceInterface(new TestDeviceInterface(devices, chars)),
+        mVendorTagSections (vendorSection) {}
+
     virtual hardware::Return<Status> setCallback(
             const sp<provider::V2_4::ICameraProviderCallback>& callbacks) override {
         mCalledCounter[SET_CALLBACK]++;
@@ -183,6 +196,7 @@
     sp<TestICameraProvider> mTestCameraProvider;
 
     TestInteractionProxy() {}
+
     void setProvider(sp<TestICameraProvider> provider) {
         mTestCameraProvider = provider;
     }
@@ -199,13 +213,31 @@
         return true;
     }
 
+    virtual sp<hardware::camera::provider::V2_4::ICameraProvider> tryGetService(
+            const std::string &serviceName) override {
+        // If no provider has been given, act like the HAL isn't available and return null.
+        if (mTestCameraProvider == nullptr) return nullptr;
+        return getService(serviceName);
+    }
+
     virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
             const std::string &serviceName) override {
+        // If no provider has been given, fail; in reality, getService would
+        // block for HALs that don't start correctly, so we should never use
+        // getService when we don't have a valid HAL running
+        if (mTestCameraProvider == nullptr) {
+            ADD_FAILURE() << "getService called with no valid provider; would block indefinitely";
+            // Real getService would block, but that's bad in unit tests. So
+            // just record an error and return nullptr
+            return nullptr;
+        }
         mLastRequestedServiceNames.push_back(serviceName);
         return mTestCameraProvider;
     }
 
     virtual hardware::hidl_vec<hardware::hidl_string> listServices() override {
+        // Always provide a list even if there's no actual provider yet, to
+        // simulate stuck HAL situations as well
         hardware::hidl_vec<hardware::hidl_string> ret = {"test/0"};
         return ret;
     }
@@ -217,11 +249,59 @@
 
     void onDeviceStatusChanged(const String8 &,
             hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+    void onDeviceStatusChanged(const String8 &, const String8 &,
+            hardware::camera::common::V1_0::CameraDeviceStatus) override {}
     void onTorchStatusChanged(const String8 &,
             hardware::camera::common::V1_0::TorchModeStatus) override {}
     void onNewProviderRegistered() override {}
 };
 
+TEST(CameraProviderManagerTest, InitializeDynamicDepthTest) {
+    std::vector<hardware::hidl_string> deviceNames;
+    deviceNames.push_back("device@3.2/test/0");
+    hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
+    status_t res;
+    sp<CameraProviderManager> providerManager = new CameraProviderManager();
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+
+    android::hardware::hidl_vec<uint8_t> chars;
+    CameraMetadata meta;
+    int32_t charKeys[] = { ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
+            ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS };
+    meta.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, charKeys,
+            sizeof(charKeys) / sizeof(charKeys[0]));
+    uint8_t depthIsExclusive = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE;
+    meta.update(ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE, &depthIsExclusive, 1);
+    int32_t sizes[] = { HAL_PIXEL_FORMAT_BLOB,
+            640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT };
+    meta.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, sizes,
+            sizeof(sizes) / sizeof(sizes[0]));
+    sizes[0] = HAL_PIXEL_FORMAT_Y16;
+    meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, sizes,
+            sizeof(sizes) / sizeof(sizes[0]));
+    int64_t durations[] = { HAL_PIXEL_FORMAT_BLOB, 640, 480, 0 };
+    meta.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, durations,
+            sizeof(durations) / sizeof(durations[0]));
+    meta.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, durations,
+            sizeof(durations) / sizeof(durations[0]));
+    durations[0]= HAL_PIXEL_FORMAT_Y16;
+    meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS, durations,
+            sizeof(durations) / sizeof(durations[0]));
+    meta.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, durations,
+            sizeof(durations) / sizeof(durations[0]));
+    camera_metadata_t* metaBuffer = const_cast<camera_metadata_t*>(meta.getAndLock());
+    chars.setToExternal(reinterpret_cast<uint8_t*>(metaBuffer),
+            get_camera_metadata_size(metaBuffer));
+
+    sp<TestICameraProvider> provider =  new TestICameraProvider(deviceNames,
+            vendorSection, chars);
+    serviceProxy.setProvider(provider);
+
+    res = providerManager->initialize(statusListener, &serviceProxy);
+    ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+}
+
 TEST(CameraProviderManagerTest, InitializeTest) {
     std::vector<hardware::hidl_string> deviceNames;
     deviceNames.push_back("device@3.2/test/0");
@@ -438,3 +518,52 @@
             << "Unable to change device state";
 
 }
+
+// Test that CameraProviderManager doesn't get stuck when the camera HAL isn't really working
+TEST(CameraProviderManagerTest, BadHalStartupTest) {
+
+    std::vector<hardware::hidl_string> deviceNames;
+    deviceNames.push_back("device@3.2/test/0");
+    deviceNames.push_back("device@1.0/test/0");
+    deviceNames.push_back("device@3.2/test/1");
+    hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
+    status_t res;
+
+    sp<CameraProviderManager> providerManager = new CameraProviderManager();
+    sp<TestStatusListener> statusListener = new TestStatusListener();
+    TestInteractionProxy serviceProxy;
+    sp<TestICameraProvider> provider =  new TestICameraProvider(deviceNames,
+            vendorSection);
+
+    // Not setting up provider in the service proxy yet, to test cases where a
+    // HAL isn't starting right
+    res = providerManager->initialize(statusListener, &serviceProxy);
+    ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+
+    // Now set up provider and trigger a registration
+    serviceProxy.setProvider(provider);
+    int numProviders = static_cast<int>(serviceProxy.listServices().size());
+
+    hardware::hidl_string testProviderFqInterfaceName =
+            "android.hardware.camera.provider@2.4::ICameraProvider";
+    hardware::hidl_string testProviderInstanceName = "test/0";
+    serviceProxy.mManagerNotificationInterface->onRegistration(
+            testProviderFqInterfaceName,
+            testProviderInstanceName, false);
+
+    // Check that new provider is called once for all the init methods
+    EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::SET_CALLBACK], numProviders) <<
+            "Only one call to setCallback per provider expected during register";
+    EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_VENDOR_TAGS], numProviders) <<
+            "Only one call to getVendorTags per provider expected during register";
+    EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::IS_SET_TORCH_MODE_SUPPORTED],
+            numProviders) <<
+            "Only one call to isSetTorchModeSupported per provider expected during init";
+    EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::GET_CAMERA_ID_LIST], numProviders) <<
+            "Only one call to getCameraIdList per provider expected during init";
+    EXPECT_EQ(provider->mCalledCounter[TestICameraProvider::NOTIFY_DEVICE_STATE], numProviders) <<
+            "Only one call to notifyDeviceState per provider expected during init";
+
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) <<
+            "Incorrect instance requested from service manager";
+}
diff --git a/services/camera/libcameraservice/tests/ClientManagerTest.cpp b/services/camera/libcameraservice/tests/ClientManagerTest.cpp
new file mode 100644
index 0000000..6a38427
--- /dev/null
+++ b/services/camera/libcameraservice/tests/ClientManagerTest.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "ClientManagerTest"
+
+#include "../utils/ClientManager.h"
+#include <gtest/gtest.h>
+
+using namespace android::resource_policy;
+
+struct TestClient {
+    TestClient(int id, int32_t cost, const std::set<int>& conflictingKeys, int32_t ownerId,
+            int32_t score, int32_t state, bool isVendorClient) :
+            mId(id), mCost(cost), mConflictingKeys(conflictingKeys),
+            mOwnerId(ownerId), mScore(score), mState(state), mIsVendorClient(isVendorClient) {};
+    int mId;
+    int32_t mCost;    // Int 0..100
+    std::set<int> mConflictingKeys;
+    int32_t mOwnerId; // PID
+    int32_t mScore;   // Priority
+    int32_t mState;   // Foreground/background etc
+    bool mIsVendorClient;
+};
+
+using TestClientDescriptor = ClientDescriptor<int, TestClient>;
+using TestDescriptorPtr = std::shared_ptr<TestClientDescriptor>;
+
+TestDescriptorPtr makeDescFromTestClient(const TestClient& tc) {
+    return std::make_shared<TestClientDescriptor>(/*ID*/tc.mId, tc, tc.mCost, tc.mConflictingKeys,
+            tc.mScore, tc.mOwnerId, tc.mState, tc.mIsVendorClient);
+}
+
+class TestClientManager : public ClientManager<int, TestClient> {
+public:
+    TestClientManager() {}
+    virtual ~TestClientManager() {}
+};
+
+
+// Test ClientMager behavior when there is only one single owner
+// The expected behavior is that if one owner (application or vendor) is trying
+// to open second camera, it may succeed or not, but the first opened camera
+// should never be evicted.
+TEST(ClientManagerTest, SingleOwnerMultipleCamera) {
+
+    TestClientManager cm;
+    TestClient cam0Client(/*ID*/0, /*cost*/100, /*conflicts*/{1},
+            /*ownerId*/ 1000, /*score*/50, /*state*/ 1, /*isVendorClient*/ false);
+    auto cam0Desc = makeDescFromTestClient(cam0Client);
+    auto evicted = cm.addAndEvict(cam0Desc);
+    ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
+
+    TestClient cam1Client(/*ID*/1, /*cost*/100, /*conflicts*/{0},
+            /*ownerId*/ 1000, /*score*/50, /*state*/ 1, /*isVendorClient*/ false);
+    auto cam1Desc = makeDescFromTestClient(cam1Client);
+
+    // 1. Check with conflicting devices, new client would be evicted
+    auto wouldBeEvicted = cm.wouldEvict(cam1Desc);
+    ASSERT_EQ(wouldBeEvicted.size(), 1u) << "Evicted list length must be 1";
+    ASSERT_EQ(wouldBeEvicted[0]->getKey(), cam1Desc->getKey()) << "cam1 must be evicted";
+
+    cm.removeAll();
+
+    TestClient cam2Client(/*ID*/2, /*cost*/100, /*conflicts*/{},
+            /*ownerId*/ 1000, /*score*/50, /*state*/ 1, /*isVendorClient*/ false);
+    auto cam2Desc = makeDescFromTestClient(cam2Client);
+    evicted = cm.addAndEvict(cam2Desc);
+    ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
+
+    TestClient cam3Client(/*ID*/3, /*cost*/100, /*conflicts*/{},
+            /*ownerId*/ 1000, /*score*/50, /*state*/ 1, /*isVendorClient*/ false);
+    auto cam3Desc = makeDescFromTestClient(cam3Client);
+
+    // 2. Check without conflicting devices, the pre-existing client won't be evicted
+    // In this case, the new client would be granted, but could later be rejected by HAL due to
+    // resource cost.
+    wouldBeEvicted = cm.wouldEvict(cam3Desc);
+    ASSERT_EQ(wouldBeEvicted.size(), 0u) << "Evicted list must be empty";
+
+    cm.removeAll();
+
+    evicted = cm.addAndEvict(cam0Desc);
+    ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
+
+    TestClient cam0ClientNew(/*ID*/0, /*cost*/100, /*conflicts*/{1},
+            /*ownerId*/ 1000, /*score*/50, /*state*/ 1, /*isVendorClient*/ false);
+    auto cam0DescNew = makeDescFromTestClient(cam0ClientNew);
+    wouldBeEvicted = cm.wouldEvict(cam0DescNew);
+
+    // 3. Check opening the same camera twice will evict the older client
+    ASSERT_EQ(wouldBeEvicted.size(), 1u) << "Evicted list length must be 1";
+    ASSERT_EQ(wouldBeEvicted[0], cam0Desc) << "cam0 (old) must be evicted";
+}
+
diff --git a/services/camera/libcameraservice/tests/DepthProcessorTest.cpp b/services/camera/libcameraservice/tests/DepthProcessorTest.cpp
index 2162514..673c149 100644
--- a/services/camera/libcameraservice/tests/DepthProcessorTest.cpp
+++ b/services/camera/libcameraservice/tests/DepthProcessorTest.cpp
@@ -20,7 +20,6 @@
 #include <array>
 #include <random>
 
-#include <dlfcn.h>
 #include <gtest/gtest.h>
 
 #include "../common/DepthPhotoProcessor.h"
@@ -36,19 +35,6 @@
 static const size_t kTestBufferDepthSize (kTestBufferWidth * kTestBufferHeight);
 static const size_t kSeed = 1234;
 
-void linkToDepthPhotoLibrary(void **libHandle /*out*/,
-        process_depth_photo_frame *processFrameFunc /*out*/) {
-    ASSERT_NE(libHandle, nullptr);
-    ASSERT_NE(processFrameFunc, nullptr);
-
-    *libHandle = dlopen(kDepthPhotoLibrary, RTLD_NOW | RTLD_LOCAL);
-    if (*libHandle != nullptr) {
-        *processFrameFunc = reinterpret_cast<camera3::process_depth_photo_frame> (
-                dlsym(*libHandle, kDepthPhotoProcessFunction));
-        ASSERT_NE(*processFrameFunc, nullptr);
-    }
-}
-
 void generateColorJpegBuffer(int jpegQuality, ExifOrientation orientationValue, bool includeExif,
         bool switchDimensions, std::vector<uint8_t> *colorJpegBuffer /*out*/) {
     ASSERT_NE(colorJpegBuffer, nullptr);
@@ -91,26 +77,9 @@
     }
 }
 
-TEST(DepthProcessorTest, LinkToLibray) {
-    void *libHandle;
-    process_depth_photo_frame processFunc;
-    linkToDepthPhotoLibrary(&libHandle, &processFunc);
-    if (libHandle != nullptr) {
-        dlclose(libHandle);
-    }
-}
-
 TEST(DepthProcessorTest, BadInput) {
-    void *libHandle;
     int jpegQuality = 95;
 
-    process_depth_photo_frame processFunc;
-    linkToDepthPhotoLibrary(&libHandle, &processFunc);
-    if (libHandle == nullptr) {
-        // Depth library no present, nothing more to test.
-        return;
-    }
-
     DepthPhotoInputFrame inputFrame;
     // Worst case both depth and confidence maps have the same size as the main color image.
     inputFrame.mMaxJpegSize = inputFrame.mMainJpegSize * 3;
@@ -128,37 +97,27 @@
     inputFrame.mMainJpegWidth = kTestBufferWidth;
     inputFrame.mMainJpegHeight = kTestBufferHeight;
     inputFrame.mJpegQuality = jpegQuality;
-    ASSERT_NE(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
+    ASSERT_NE(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
                 &actualDepthPhotoSize), 0);
 
     inputFrame.mMainJpegBuffer = reinterpret_cast<const char*> (colorJpegBuffer.data());
     inputFrame.mMainJpegSize = colorJpegBuffer.size();
-    ASSERT_NE(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
+    ASSERT_NE(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
                 &actualDepthPhotoSize), 0);
 
     inputFrame.mDepthMapBuffer = depth16Buffer.data();
     inputFrame.mDepthMapWidth = inputFrame.mDepthMapStride = kTestBufferWidth;
     inputFrame.mDepthMapHeight = kTestBufferHeight;
-    ASSERT_NE(processFunc(inputFrame, depthPhotoBuffer.size(), nullptr,
+    ASSERT_NE(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), nullptr,
                 &actualDepthPhotoSize), 0);
 
-    ASSERT_NE(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(), nullptr),
-            0);
-
-    dlclose(libHandle);
+    ASSERT_NE(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
+                nullptr), 0);
 }
 
 TEST(DepthProcessorTest, BasicDepthPhotoValidation) {
-    void *libHandle;
     int jpegQuality = 95;
 
-    process_depth_photo_frame processFunc;
-    linkToDepthPhotoLibrary(&libHandle, &processFunc);
-    if (libHandle == nullptr) {
-        // Depth library no present, nothing more to test.
-        return;
-    }
-
     std::vector<uint8_t> colorJpegBuffer;
     generateColorJpegBuffer(jpegQuality, ExifOrientation::ORIENTATION_UNDEFINED,
             /*includeExif*/ false, /*switchDimensions*/ false, &colorJpegBuffer);
@@ -180,7 +139,7 @@
 
     std::vector<uint8_t> depthPhotoBuffer(inputFrame.mMaxJpegSize);
     size_t actualDepthPhotoSize = 0;
-    ASSERT_EQ(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
+    ASSERT_EQ(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
                 &actualDepthPhotoSize), 0);
     ASSERT_TRUE((actualDepthPhotoSize > 0) && (depthPhotoBuffer.size() >= actualDepthPhotoSize));
 
@@ -196,21 +155,11 @@
     ASSERT_EQ(NV12Compressor::findJpegSize(depthPhotoBuffer.data() + mainJpegSize,
                 actualDepthPhotoSize - mainJpegSize, &depthMapSize), OK);
     ASSERT_TRUE((depthMapSize > 0) && (depthMapSize < (actualDepthPhotoSize - mainJpegSize)));
-
-    dlclose(libHandle);
 }
 
 TEST(DepthProcessorTest, TestDepthPhotoExifOrientation) {
-    void *libHandle;
     int jpegQuality = 95;
 
-    process_depth_photo_frame processFunc;
-    linkToDepthPhotoLibrary(&libHandle, &processFunc);
-    if (libHandle == nullptr) {
-        // Depth library no present, nothing more to test.
-        return;
-    }
-
     ExifOrientation exifOrientations[] = { ExifOrientation::ORIENTATION_UNDEFINED,
             ExifOrientation::ORIENTATION_0_DEGREES, ExifOrientation::ORIENTATION_90_DEGREES,
             ExifOrientation::ORIENTATION_180_DEGREES, ExifOrientation::ORIENTATION_270_DEGREES };
@@ -242,8 +191,8 @@
 
         std::vector<uint8_t> depthPhotoBuffer(inputFrame.mMaxJpegSize);
         size_t actualDepthPhotoSize = 0;
-        ASSERT_EQ(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
-                &actualDepthPhotoSize), 0);
+        ASSERT_EQ(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(),
+                    depthPhotoBuffer.data(), &actualDepthPhotoSize), 0);
         ASSERT_TRUE((actualDepthPhotoSize > 0) &&
                 (depthPhotoBuffer.size() >= actualDepthPhotoSize));
 
@@ -281,21 +230,11 @@
             ASSERT_EQ(confidenceJpegExifOrientation, exifOrientation);
         }
     }
-
-    dlclose(libHandle);
 }
 
 TEST(DepthProcessorTest, TestDephtPhotoPhysicalRotation) {
-    void *libHandle;
     int jpegQuality = 95;
 
-    process_depth_photo_frame processFunc;
-    linkToDepthPhotoLibrary(&libHandle, &processFunc);
-    if (libHandle == nullptr) {
-        // Depth library no present, nothing more to test.
-        return;
-    }
-
     // In case of physical rotation, the EXIF orientation must always be 0.
     auto exifOrientation = ExifOrientation::ORIENTATION_0_DEGREES;
     DepthPhotoOrientation depthOrientations[] = {
@@ -339,8 +278,8 @@
 
         std::vector<uint8_t> depthPhotoBuffer(inputFrame.mMaxJpegSize);
         size_t actualDepthPhotoSize = 0;
-        ASSERT_EQ(processFunc(inputFrame, depthPhotoBuffer.size(), depthPhotoBuffer.data(),
-                &actualDepthPhotoSize), 0);
+        ASSERT_EQ(processDepthPhotoFrame(inputFrame, depthPhotoBuffer.size(),
+                    depthPhotoBuffer.data(), &actualDepthPhotoSize), 0);
         ASSERT_TRUE((actualDepthPhotoSize > 0) &&
                 (depthPhotoBuffer.size() >= actualDepthPhotoSize));
 
@@ -377,6 +316,4 @@
         ASSERT_EQ(confidenceMapWidth, expectedWidth);
         ASSERT_EQ(confidenceMapHeight, expectedHeight);
     }
-
-    dlclose(libHandle);
 }
diff --git a/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
new file mode 100644
index 0000000..3c187cd
--- /dev/null
+++ b/services/camera/libcameraservice/tests/RotateAndCropMapperTest.cpp
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "RotateAndCropMapperTest"
+
+#include <functional>
+#include <random>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "../device3/RotateAndCropMapper.h"
+
+namespace rotateAndCropMapperTest {
+
+using namespace android;
+using namespace android::camera3;
+
+using ::testing::ElementsAreArray;
+using ::testing::Each;
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::Le;
+
+#define EXPECT_EQUAL_WITHIN_N(vec, array, N, msg)   \
+{ \
+    for (size_t i = 0; i < vec.size(); i++) { \
+        EXPECT_THAT(vec[i] - array[i], AllOf(Ge(-N), Le(N))) << msg " failed at index:" << i; \
+    } \
+}
+
+int32_t testActiveArray[] = {100, 100, 4000, 3000};
+
+std::vector<uint8_t> basicModes = {
+    ANDROID_SCALER_ROTATE_AND_CROP_NONE,
+    ANDROID_SCALER_ROTATE_AND_CROP_90,
+    ANDROID_SCALER_ROTATE_AND_CROP_AUTO
+};
+
+CameraMetadata setupDeviceInfo(int32_t activeArray[4], std::vector<uint8_t> availableCropModes ) {
+    CameraMetadata deviceInfo;
+
+    deviceInfo.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+            activeArray, 4);
+
+    deviceInfo.update(ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES,
+            availableCropModes.data(), availableCropModes.size());
+
+    return deviceInfo;
+}
+
+TEST(RotationMapperTest, Initialization) {
+    CameraMetadata deviceInfo = setupDeviceInfo(testActiveArray,
+            {ANDROID_SCALER_ROTATE_AND_CROP_NONE});
+
+    ASSERT_FALSE(RotateAndCropMapper::isNeeded(&deviceInfo));
+
+    deviceInfo.update(ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES,
+            basicModes.data(), 3);
+
+    ASSERT_TRUE(RotateAndCropMapper::isNeeded(&deviceInfo));
+}
+
+TEST(RotationMapperTest, IdentityTransform) {
+    status_t res;
+
+    CameraMetadata deviceInfo = setupDeviceInfo(testActiveArray,
+            basicModes);
+
+    RotateAndCropMapper mapper(&deviceInfo);
+
+    CameraMetadata request;
+    uint8_t mode = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+    auto full_crop = std::vector<int32_t>{0,0, testActiveArray[2], testActiveArray[3]};
+    auto full_region = std::vector<int32_t>{0,0, testActiveArray[2], testActiveArray[3], 1};
+    request.update(ANDROID_SCALER_ROTATE_AND_CROP,
+            &mode, 1);
+    request.update(ANDROID_SCALER_CROP_REGION,
+            full_crop.data(), full_crop.size());
+    request.update(ANDROID_CONTROL_AE_REGIONS,
+            full_region.data(), full_region.size());
+
+    // Map to HAL
+
+    res = mapper.updateCaptureRequest(&request);
+    ASSERT_TRUE(res == OK);
+
+    auto e = request.find(ANDROID_CONTROL_AE_REGIONS);
+    EXPECT_THAT(full_region, ElementsAreArray(e.data.i32, e.count));
+
+    e = request.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count));
+
+    // Add fields in HAL
+
+    CameraMetadata result(request);
+
+    auto face = std::vector<int32_t> {300,300,500,500};
+    result.update(ANDROID_STATISTICS_FACE_RECTANGLES,
+            face.data(), face.size());
+
+    // Map to app
+
+    res = mapper.updateCaptureResult(&result);
+    ASSERT_TRUE(res == OK);
+
+    e = result.find(ANDROID_CONTROL_AE_REGIONS);
+    EXPECT_THAT(full_region, ElementsAreArray(e.data.i32, e.count));
+
+    e = result.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count));
+
+    e = result.find(ANDROID_STATISTICS_FACE_RECTANGLES);
+    EXPECT_THAT(face, ElementsAreArray(e.data.i32, e.count));
+}
+
+TEST(RotationMapperTest, Transform90) {
+    status_t res;
+
+    CameraMetadata deviceInfo = setupDeviceInfo(testActiveArray,
+            basicModes);
+
+    RotateAndCropMapper mapper(&deviceInfo);
+
+    CameraMetadata request;
+    uint8_t mode = ANDROID_SCALER_ROTATE_AND_CROP_90;
+    auto full_crop = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3]};
+    auto full_region = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3], 1};
+    request.update(ANDROID_SCALER_ROTATE_AND_CROP,
+            &mode, 1);
+    request.update(ANDROID_SCALER_CROP_REGION,
+            full_crop.data(), full_crop.size());
+    request.update(ANDROID_CONTROL_AE_REGIONS,
+            full_region.data(), full_region.size());
+
+    // Map to HAL
+
+    res = mapper.updateCaptureRequest(&request);
+    ASSERT_TRUE(res == OK);
+
+    auto e = request.find(ANDROID_CONTROL_AE_REGIONS);
+    float aspectRatio = static_cast<float>(full_crop[2]) / full_crop[3];
+    int32_t rw = full_crop[3] / aspectRatio;
+    int32_t rh = full_crop[3];
+    auto rotated_region = std::vector<int32_t> {
+        full_crop[0] + (full_crop[2] - rw) / 2, full_crop[1],
+        full_crop[0] + (full_crop[2] + rw) / 2, full_crop[1] + full_crop[3],
+        1
+    };
+    EXPECT_THAT(rotated_region, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated AE region isn't right";
+
+    e = request.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated crop region isn't right";
+
+    // Add fields in HAL
+
+    CameraMetadata result(request);
+
+    auto face = std::vector<int32_t> {
+        rotated_region[0] + rw / 4, rotated_region[1] + rh / 4,
+        rotated_region[2] - rw / 4, rotated_region[3] - rh / 4};
+    result.update(ANDROID_STATISTICS_FACE_RECTANGLES,
+            face.data(), face.size());
+
+    auto landmarks = std::vector<int32_t> {
+        rotated_region[0], rotated_region[1],
+        rotated_region[2], rotated_region[3],
+        rotated_region[0] + rw / 4, rotated_region[1] + rh / 4,
+        rotated_region[0] + rw / 2, rotated_region[1] + rh / 2,
+        rotated_region[2] - rw / 4, rotated_region[3] - rh / 4
+    };
+    result.update(ANDROID_STATISTICS_FACE_LANDMARKS,
+            landmarks.data(), landmarks.size());
+
+    // Map to app
+
+    res = mapper.updateCaptureResult(&result);
+    ASSERT_TRUE(res == OK);
+
+    // Round-trip results can't be exact since we've gone from a large int range -> small int range
+    // and back, leading to quantization. For 4/3 aspect ratio, no more than +-1 error expected
+    e = result.find(ANDROID_CONTROL_AE_REGIONS);
+    EXPECT_EQUAL_WITHIN_N(full_region, e.data.i32, 1, "Round-tripped AE region isn't right");
+
+    e = result.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_EQUAL_WITHIN_N(full_crop, e.data.i32, 1, "Round-tripped crop region isn't right");
+
+    auto full_face = std::vector<int32_t> {
+        full_crop[0] + full_crop[2]/4, full_crop[1] + full_crop[3]/4,
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_RECTANGLES);
+    EXPECT_EQUAL_WITHIN_N(full_face, e.data.i32, 1, "App-side face rectangle isn't right");
+
+    auto full_landmarks = std::vector<int32_t> {
+        full_crop[0], full_crop[1] + full_crop[3],
+        full_crop[0] + full_crop[2], full_crop[1],
+        full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4,
+        full_crop[0] + full_crop[2]/2, full_crop[1] + full_crop[3]/2,
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_LANDMARKS);
+    EXPECT_EQUAL_WITHIN_N(full_landmarks, e.data.i32, 1, "App-side face landmarks aren't right");
+}
+
+TEST(RotationMapperTest, Transform270) {
+    status_t res;
+
+    CameraMetadata deviceInfo = setupDeviceInfo(testActiveArray,
+            basicModes);
+
+    RotateAndCropMapper mapper(&deviceInfo);
+
+    CameraMetadata request;
+    uint8_t mode = ANDROID_SCALER_ROTATE_AND_CROP_270;
+    auto full_crop = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3]};
+    auto full_region = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3], 1};
+    request.update(ANDROID_SCALER_ROTATE_AND_CROP,
+            &mode, 1);
+    request.update(ANDROID_SCALER_CROP_REGION,
+            full_crop.data(), full_crop.size());
+    request.update(ANDROID_CONTROL_AE_REGIONS,
+            full_region.data(), full_region.size());
+
+    // Map to HAL
+
+    res = mapper.updateCaptureRequest(&request);
+    ASSERT_TRUE(res == OK);
+
+    auto e = request.find(ANDROID_CONTROL_AE_REGIONS);
+    float aspectRatio = static_cast<float>(full_crop[2]) / full_crop[3];
+    int32_t rw = full_crop[3] / aspectRatio;
+    int32_t rh = full_crop[3];
+    auto rotated_region = std::vector<int32_t> {
+        full_crop[0] + (full_crop[2] - rw) / 2, full_crop[1],
+        full_crop[0] + (full_crop[2] + rw) / 2, full_crop[1] + full_crop[3],
+        1
+    };
+    EXPECT_THAT(rotated_region, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated AE region isn't right";
+
+    e = request.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated crop region isn't right";
+
+    // Add fields in HAL
+
+    CameraMetadata result(request);
+
+    auto face = std::vector<int32_t> {
+        rotated_region[0] + rw / 4, rotated_region[1] + rh / 4,
+        rotated_region[2] - rw / 4, rotated_region[3] - rh / 4};
+    result.update(ANDROID_STATISTICS_FACE_RECTANGLES,
+            face.data(), face.size());
+
+    auto landmarks = std::vector<int32_t> {
+        rotated_region[0], rotated_region[1],
+        rotated_region[2], rotated_region[3],
+        rotated_region[0] + rw / 4, rotated_region[1] + rh / 4,
+        rotated_region[0] + rw / 2, rotated_region[1] + rh / 2,
+        rotated_region[2] - rw / 4, rotated_region[3] - rh / 4
+    };
+    result.update(ANDROID_STATISTICS_FACE_LANDMARKS,
+            landmarks.data(), landmarks.size());
+
+    // Map to app
+
+    res = mapper.updateCaptureResult(&result);
+    ASSERT_TRUE(res == OK);
+
+    // Round-trip results can't be exact since we've gone from a large int range -> small int range
+    // and back, leading to quantization. For 4/3 aspect ratio, no more than +-1 error expected
+
+    e = result.find(ANDROID_CONTROL_AE_REGIONS);
+    EXPECT_EQUAL_WITHIN_N(full_region, e.data.i32, 1, "Round-tripped AE region isn't right");
+
+    e = result.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_EQUAL_WITHIN_N(full_crop, e.data.i32, 1, "Round-tripped crop region isn't right");
+
+    auto full_face = std::vector<int32_t> {
+        full_crop[0] + full_crop[2]/4, full_crop[1] + full_crop[3]/4,
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_RECTANGLES);
+    EXPECT_EQUAL_WITHIN_N(full_face, e.data.i32, 1, "App-side face rectangle isn't right");
+
+    auto full_landmarks = std::vector<int32_t> {
+        full_crop[0] + full_crop[2], full_crop[1],
+        full_crop[0], full_crop[1] + full_crop[3],
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + full_crop[3]/4,
+        full_crop[0] + full_crop[2]/2, full_crop[1] + full_crop[3]/2,
+        full_crop[0] + full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_LANDMARKS);
+    EXPECT_EQUAL_WITHIN_N(full_landmarks, e.data.i32, 1, "App-side face landmarks aren't right");
+}
+
+TEST(RotationMapperTest, Transform180) {
+    status_t res;
+
+    CameraMetadata deviceInfo = setupDeviceInfo(testActiveArray,
+            basicModes);
+
+    RotateAndCropMapper mapper(&deviceInfo);
+
+    CameraMetadata request;
+    uint8_t mode = ANDROID_SCALER_ROTATE_AND_CROP_180;
+    auto full_crop = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3]};
+    auto full_region = std::vector<int32_t> {0,0, testActiveArray[2], testActiveArray[3], 1};
+    request.update(ANDROID_SCALER_ROTATE_AND_CROP,
+            &mode, 1);
+    request.update(ANDROID_SCALER_CROP_REGION,
+            full_crop.data(), full_crop.size());
+    request.update(ANDROID_CONTROL_AE_REGIONS,
+            full_region.data(), full_region.size());
+
+    // Map to HAL
+
+    res = mapper.updateCaptureRequest(&request);
+    ASSERT_TRUE(res == OK);
+
+    auto e = request.find(ANDROID_CONTROL_AE_REGIONS);
+    auto rotated_region = full_region;
+    EXPECT_THAT(rotated_region, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated AE region isn't right";
+
+    e = request.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count))
+            << "Rotated crop region isn't right";
+
+    // Add fields in HAL
+
+    CameraMetadata result(request);
+
+    float rw = full_region[2] - full_region[0];
+    float rh = full_region[3] - full_region[1];
+    auto face = std::vector<int32_t> {
+        rotated_region[0] + (int)(rw / 4), rotated_region[1] + (int)(rh / 4),
+        rotated_region[2] - (int)(rw / 4), rotated_region[3] - (int)(rh / 4)
+    };
+    result.update(ANDROID_STATISTICS_FACE_RECTANGLES,
+            face.data(), face.size());
+
+    auto landmarks = std::vector<int32_t> {
+        rotated_region[0], rotated_region[1],
+        rotated_region[2], rotated_region[3],
+        rotated_region[0] + (int)(rw / 4), rotated_region[1] + (int)(rh / 4),
+        rotated_region[0] + (int)(rw / 2), rotated_region[1] + (int)(rh / 2),
+        rotated_region[2] - (int)(rw / 4), rotated_region[3] - (int)(rh / 4)
+    };
+    result.update(ANDROID_STATISTICS_FACE_LANDMARKS,
+            landmarks.data(), landmarks.size());
+
+    // Map to app
+
+    res = mapper.updateCaptureResult(&result);
+    ASSERT_TRUE(res == OK);
+
+    e = result.find(ANDROID_CONTROL_AE_REGIONS);
+    EXPECT_THAT(full_region, ElementsAreArray(e.data.i32, e.count))
+            << "Round-tripped AE region isn't right";
+
+    e = result.find(ANDROID_SCALER_CROP_REGION);
+    EXPECT_THAT(full_crop, ElementsAreArray(e.data.i32, e.count))
+            << "Round-tripped crop region isn't right";
+
+    auto full_face = std::vector<int32_t> {
+        full_crop[0] + full_crop[2]/4, full_crop[1] + full_crop[3]/4,
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_RECTANGLES);
+    EXPECT_EQUAL_WITHIN_N(full_face, e.data.i32, 1, "App-side face rectangle isn't right");
+
+    auto full_landmarks = std::vector<int32_t> {
+        full_crop[0] + full_crop[2], full_crop[1] + full_crop[3],
+        full_crop[0], full_crop[1],
+        full_crop[0] + 3*full_crop[2]/4, full_crop[1] + 3*full_crop[3]/4,
+        full_crop[0] + full_crop[2]/2, full_crop[1] + full_crop[3]/2,
+        full_crop[0] + full_crop[2]/4, full_crop[1] + full_crop[3]/4
+    };
+    e = result.find(ANDROID_STATISTICS_FACE_LANDMARKS);
+    EXPECT_EQUAL_WITHIN_N(full_landmarks, e.data.i32, 1, "App-side face landmarks aren't right");
+}
+
+
+} // namespace rotateAndCropMapperTest
diff --git a/services/camera/libcameraservice/tests/ZoomRatioTest.cpp b/services/camera/libcameraservice/tests/ZoomRatioTest.cpp
new file mode 100644
index 0000000..4e94991
--- /dev/null
+++ b/services/camera/libcameraservice/tests/ZoomRatioTest.cpp
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2019 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 "ZoomRatioMapperTest"
+
+#include <gtest/gtest.h>
+#include <utils/Errors.h>
+
+#include "../device3/ZoomRatioMapper.h"
+
+using namespace std;
+using namespace android;
+using namespace android::camera3;
+
+constexpr int kMaxAllowedPixelError = 1;
+constexpr float kMaxAllowedRatioError = 0.1;
+
+constexpr int32_t testActiveArraySize[] = {100, 100, 1024, 768};
+constexpr int32_t testPreCorrActiveArraySize[] = {90, 90, 1044, 788};
+
+constexpr int32_t testDefaultCropSize[][4] = {
+      {0, 0, 1024, 768},   // active array default crop
+      {0, 0, 1044, 788},   // preCorrection active array default crop
+};
+
+constexpr int32_t test2xCropRegion[][4] = {
+      {256, 192, 512, 384}, // active array 2x zoom crop
+      {261, 197, 522, 394}, // preCorrection active array default crop
+};
+
+constexpr int32_t testLetterBoxSize[][4] = {
+      {0, 96, 1024, 576}, // active array 2x zoom crop
+      {0, 106, 1024, 576}, // preCorrection active array default crop
+};
+
+status_t setupTestMapper(ZoomRatioMapper *m, float maxDigitalZoom,
+        const int32_t activeArray[4], const int32_t preCorrectArray[4],
+        bool hasZoomRatioRange, float zoomRatioRange[2],
+        bool usePreCorrectArray) {
+    CameraMetadata deviceInfo;
+
+    deviceInfo.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArray, 4);
+    deviceInfo.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, preCorrectArray, 4);
+    deviceInfo.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &maxDigitalZoom, 1);
+    if (hasZoomRatioRange) {
+        deviceInfo.update(ANDROID_CONTROL_ZOOM_RATIO_RANGE, zoomRatioRange, 2);
+    }
+
+    bool supportNativeZoomRatio;
+    status_t res = ZoomRatioMapper::overrideZoomRatioTags(&deviceInfo, &supportNativeZoomRatio);
+    if (res != OK) {
+        return res;
+    }
+
+    *m = ZoomRatioMapper(&deviceInfo, hasZoomRatioRange, usePreCorrectArray);
+    return OK;
+}
+
+TEST(ZoomRatioTest, Initialization) {
+    CameraMetadata deviceInfo;
+    status_t res;
+    camera_metadata_entry_t entry;
+
+    deviceInfo.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+            testPreCorrActiveArraySize, 4);
+    deviceInfo.update(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, testActiveArraySize, 4);
+
+    // Test initialization from devices not supporting zoomRange
+    float maxDigitalZoom = 4.0f;
+    ZoomRatioMapper mapperNoZoomRange;
+    deviceInfo.update(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &maxDigitalZoom, 1);
+    bool supportNativeZoomRatio;
+    res = ZoomRatioMapper::overrideZoomRatioTags(&deviceInfo, &supportNativeZoomRatio);
+    ASSERT_EQ(res, OK);
+    ASSERT_EQ(supportNativeZoomRatio, false);
+    mapperNoZoomRange = ZoomRatioMapper(&deviceInfo,
+            supportNativeZoomRatio, true/*usePreCorrectArray*/);
+    ASSERT_TRUE(mapperNoZoomRange.isValid());
+    mapperNoZoomRange = ZoomRatioMapper(&deviceInfo,
+            supportNativeZoomRatio, false/*usePreCorrectArray*/);
+    ASSERT_TRUE(mapperNoZoomRange.isValid());
+
+    entry = deviceInfo.find(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
+    ASSERT_EQ(entry.count, 2U);
+    ASSERT_EQ(entry.data.f[0], 1.0);
+    ASSERT_EQ(entry.data.f[1], maxDigitalZoom);
+
+    entry = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+    ASSERT_GT(entry.count, 0U);
+    ASSERT_NE(std::find(entry.data.i32, entry.data.i32 + entry.count,
+            ANDROID_CONTROL_ZOOM_RATIO_RANGE), entry.data.i32 + entry.count);
+
+    entry = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
+    ASSERT_GT(entry.count, 0U);
+    ASSERT_NE(std::find(entry.data.i32, entry.data.i32 + entry.count,
+            ANDROID_CONTROL_ZOOM_RATIO), entry.data.i32 + entry.count);
+
+    entry = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS);
+    ASSERT_GT(entry.count, 0U);
+    ASSERT_NE(std::find(entry.data.i32, entry.data.i32 + entry.count,
+            ANDROID_CONTROL_ZOOM_RATIO), entry.data.i32 + entry.count);
+
+    // Test initialization from devices supporting zoomRange
+    float ratioRange[2] = {0.2f, maxDigitalZoom};
+    deviceInfo.update(ANDROID_CONTROL_ZOOM_RATIO_RANGE, ratioRange, 2);
+    res = ZoomRatioMapper::overrideZoomRatioTags(&deviceInfo, &supportNativeZoomRatio);
+    ASSERT_EQ(res, OK);
+    ASSERT_EQ(supportNativeZoomRatio, true);
+    ZoomRatioMapper mapperWithZoomRange;
+    mapperWithZoomRange = ZoomRatioMapper(&deviceInfo,
+            supportNativeZoomRatio, true/*usePreCorrectArray*/);
+    ASSERT_TRUE(mapperWithZoomRange.isValid());
+    mapperWithZoomRange = ZoomRatioMapper(&deviceInfo,
+            supportNativeZoomRatio, false/*usePreCorrectArray*/);
+    ASSERT_TRUE(mapperWithZoomRange.isValid());
+
+    entry = deviceInfo.find(ANDROID_CONTROL_ZOOM_RATIO_RANGE);
+    ASSERT_EQ(entry.count, 2U);
+    ASSERT_EQ(entry.data.f[0], ratioRange[0]);
+    ASSERT_EQ(entry.data.f[1], ratioRange[1]);
+
+    // Test default zoom ratio in template
+    CameraMetadata requestTemplate;
+    res = ZoomRatioMapper::initZoomRatioInTemplate(&requestTemplate);
+    ASSERT_EQ(res, OK);
+    entry = requestTemplate.find(ANDROID_CONTROL_ZOOM_RATIO);
+    ASSERT_EQ(entry.count, 1U);
+    ASSERT_EQ(entry.data.f[0], 1.0f);
+
+    float customRatio = 0.5f;
+    res = requestTemplate.update(ANDROID_CONTROL_ZOOM_RATIO, &customRatio, 1);
+    ASSERT_EQ(res, OK);
+    res = ZoomRatioMapper::initZoomRatioInTemplate(&requestTemplate);
+    ASSERT_EQ(res, OK);
+    entry = requestTemplate.find(ANDROID_CONTROL_ZOOM_RATIO);
+    ASSERT_EQ(entry.count, 1U);
+    ASSERT_EQ(entry.data.f[0], customRatio);
+}
+
+void subScaleCoordinatesTest(bool usePreCorrectArray) {
+    ZoomRatioMapper mapper;
+    float maxDigitalZoom = 4.0f;
+    float zoomRatioRange[2];
+    ASSERT_EQ(OK, setupTestMapper(&mapper, maxDigitalZoom,
+            testActiveArraySize, testPreCorrActiveArraySize,
+            false/*hasZoomRatioRange*/, zoomRatioRange,
+            usePreCorrectArray));
+
+    size_t index = 0;
+    int32_t width = testActiveArraySize[2];
+    int32_t height = testActiveArraySize[3];
+    if (usePreCorrectArray) {
+        index = 1;
+        width = testPreCorrActiveArraySize[2];
+        height = testPreCorrActiveArraySize[3];
+    }
+
+    std::array<int32_t, 16> originalCoords = {
+            0, 0, // top-left
+            width - 1, 0, // top-right
+            0, height - 1, // bottom-left
+            width - 1, height - 1, // bottom-right
+            (width - 1) / 2, (height - 1) / 2, // center
+            (width - 1) / 4, (height - 1) / 4, // top-left after 2x
+            (width - 1) / 3, (height - 1) * 2 / 3, // bottom-left after 3x zoom
+            (width - 1) * 7 / 8, (height - 1) / 2, // middle-right after 1.33x zoom
+    };
+
+    // Verify 1.0x zoom doesn't change the coordinates
+    auto coords = originalCoords;
+    mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f, false /*clamp*/);
+    for (size_t i = 0; i < coords.size(); i++) {
+        EXPECT_EQ(coords[i], originalCoords[i]);
+    }
+
+    // Verify 2.0x zoom work as expected (no clamping)
+    std::array<float, 16> expected2xCoords = {
+            - (width - 1) / 2.0f, - (height - 1) / 2.0f,// top-left
+            (width - 1) * 3 / 2.0f, - (height - 1) / 2.0f, // top-right
+            - (width - 1) / 2.0f, (height - 1) * 3 / 2.0f, // bottom-left
+            (width - 1) * 3 / 2.0f, (height - 1) * 3 / 2.0f, // bottom-right
+            (width - 1) / 2.0f, (height - 1) / 2.0f, // center
+            0, 0, // top-left after 2x
+            (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f, // bottom-left after 3x zoom
+            (width - 1) * 5.0f / 4.0f, (height - 1) / 2.0f, // middle-right after 1.33x zoom
+    };
+    coords = originalCoords;
+    mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, false /*clamp*/);
+    for (size_t i = 0; i < coords.size(); i++) {
+        EXPECT_LE(std::abs(coords[i] - expected2xCoords[i]), kMaxAllowedPixelError);
+    }
+
+    // Verify 2.0x zoom work as expected (with inclusive clamping)
+    std::array<float, 16> expected2xCoordsClampedInc = {
+            0, 0, // top-left
+            width - 1.0f, 0, // top-right
+            0, height - 1.0f, // bottom-left
+            width - 1.0f, height - 1.0f, // bottom-right
+            (width - 1) / 2.0f, (height - 1) / 2.0f, // center
+            0, 0, // top-left after 2x
+            (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f , // bottom-left after 3x zoom
+            width - 1.0f,  (height - 1) / 2.0f, // middle-right after 1.33x zoom
+    };
+    coords = originalCoords;
+    mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, true /*clamp*/);
+    for (size_t i = 0; i < coords.size(); i++) {
+        EXPECT_LE(std::abs(coords[i] - expected2xCoordsClampedInc[i]), kMaxAllowedPixelError);
+    }
+
+    // Verify 2.0x zoom work as expected (with exclusive clamping)
+    std::array<float, 16> expected2xCoordsClampedExc = {
+            0, 0, // top-left
+            width - 1.0f, 0, // top-right
+            0, height - 1.0f, // bottom-left
+            width - 1.0f, height - 1.0f, // bottom-right
+            width / 2.0f, height / 2.0f, // center
+            0, 0, // top-left after 2x
+            (width - 1) / 6.0f, (height - 1) * 5.0f / 6.0f , // bottom-left after 3x zoom
+            width - 1.0f,  height / 2.0f, // middle-right after 1.33x zoom
+    };
+    coords = originalCoords;
+    mapper.scaleCoordinates(coords.data(), coords.size()/2, 2.0f, true /*clamp*/);
+    for (size_t i = 0; i < coords.size(); i++) {
+        EXPECT_LE(std::abs(coords[i] - expected2xCoordsClampedExc[i]), kMaxAllowedPixelError);
+    }
+
+    // Verify 0.33x zoom work as expected
+    std::array<float, 16> expectedZoomOutCoords = {
+            (width - 1) / 3.0f, (height - 1) / 3.0f, // top-left
+            (width - 1) * 2 / 3.0f, (height - 1) / 3.0f, // top-right
+            (width - 1) / 3.0f, (height - 1) * 2 / 3.0f, // bottom-left
+            (width - 1) * 2 / 3.0f, (height - 1) * 2 / 3.0f, // bottom-right
+            (width - 1) / 2.0f, (height - 1) / 2.0f, // center
+            (width - 1) * 5 / 12.0f, (height - 1) * 5 / 12.0f, // top-left after 2x
+            (width - 1) * 4 / 9.0f, (height - 1) * 5 / 9.0f, // bottom-left after 3x zoom-in
+            (width - 1) * 5 / 8.0f, (height - 1) / 2.0f, // middle-right after 1.33x zoom-in
+    };
+    coords = originalCoords;
+    mapper.scaleCoordinates(coords.data(), coords.size()/2, 1.0f/3, false /*clamp*/);
+    for (size_t i = 0; i < coords.size(); i++) {
+        EXPECT_LE(std::abs(coords[i] - expectedZoomOutCoords[i]), kMaxAllowedPixelError);
+    }
+}
+
+TEST(ZoomRatioTest, scaleCoordinatesTest) {
+    subScaleCoordinatesTest(false/*usePreCorrectArray*/);
+    subScaleCoordinatesTest(true/*usePreCorrectArray*/);
+}
+
+void subCropOverMaxDigitalZoomTest(bool usePreCorrectArray) {
+    status_t res;
+    ZoomRatioMapper mapper;
+    float noZoomRatioRange[2];
+    res = setupTestMapper(&mapper, 4.0/*maxDigitalZoom*/,
+            testActiveArraySize, testPreCorrActiveArraySize,
+            false/*hasZoomRatioRange*/, noZoomRatioRange,
+            usePreCorrectArray);
+    ASSERT_EQ(res, OK);
+
+    CameraMetadata metadata;
+    camera_metadata_entry_t entry;
+
+    size_t index = usePreCorrectArray ? 1 : 0;
+    metadata.update(ANDROID_SCALER_CROP_REGION, testDefaultCropSize[index], 4);
+    res = mapper.updateCaptureRequest(&metadata);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i ++) {
+        EXPECT_EQ(entry.data.i32[i], testDefaultCropSize[index][i]);
+    }
+
+    metadata.update(ANDROID_SCALER_CROP_REGION, test2xCropRegion[index], 4);
+    res = mapper.updateCaptureResult(&metadata, true/*requestedZoomRatioIs1*/);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i ++) {
+        EXPECT_EQ(entry.data.i32[i], test2xCropRegion[index][i]);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    ASSERT_TRUE(entry.count == 0 || (entry.count == 1 && entry.data.f[0] == 1.0f));
+}
+
+TEST(ZoomRatioTest, CropOverMaxDigitalZoomTest) {
+    subCropOverMaxDigitalZoomTest(false/*usePreCorrectArray*/);
+    subCropOverMaxDigitalZoomTest(true/*usePreCorrectArray*/);
+}
+
+void subCropOverZoomRangeTest(bool usePreCorrectArray) {
+    status_t res;
+    ZoomRatioMapper mapper;
+    float zoomRatioRange[2] = {0.5f, 4.0f};
+    res = setupTestMapper(&mapper, 4.0/*maxDigitalZoom*/,
+            testActiveArraySize, testPreCorrActiveArraySize,
+            true/*hasZoomRatioRange*/, zoomRatioRange,
+            usePreCorrectArray);
+    ASSERT_EQ(res, OK);
+
+    CameraMetadata metadata;
+    camera_metadata_entry_t entry;
+
+    size_t index = usePreCorrectArray ? 1 : 0;
+
+    // 2x zoom crop region, zoomRatio is 1.0f
+    metadata.update(ANDROID_SCALER_CROP_REGION, test2xCropRegion[index], 4);
+    res = mapper.updateCaptureRequest(&metadata);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i++) {
+        EXPECT_LE(std::abs(entry.data.i32[i] - testDefaultCropSize[index][i]),
+                kMaxAllowedPixelError);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    EXPECT_NEAR(entry.data.f[0], 2.0f, kMaxAllowedRatioError);
+
+    res = mapper.updateCaptureResult(&metadata, true/*requestedZoomRatioIs1*/);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    EXPECT_NEAR(entry.data.f[0], 1.0f, kMaxAllowedRatioError);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i++) {
+        EXPECT_LE(std::abs(entry.data.i32[i] - test2xCropRegion[index][i]), kMaxAllowedPixelError);
+    }
+
+    // Letter boxing crop region, zoomRatio is 1.0
+    float zoomRatio = 1.0f;
+    metadata.update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+    metadata.update(ANDROID_SCALER_CROP_REGION, testLetterBoxSize[index], 4);
+    res = mapper.updateCaptureRequest(&metadata);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i++) {
+        EXPECT_EQ(entry.data.i32[i], testLetterBoxSize[index][i]);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    EXPECT_NEAR(entry.data.f[0], 1.0f, kMaxAllowedRatioError);
+
+    res = mapper.updateCaptureResult(&metadata, true/*requestedZoomRatioIs1*/);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i++) {
+        EXPECT_EQ(entry.data.i32[i], testLetterBoxSize[index][i]);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    EXPECT_NEAR(entry.data.f[0], 1.0f, kMaxAllowedRatioError);
+}
+
+TEST(ZoomRatioTest, CropOverZoomRangeTest) {
+    subCropOverZoomRangeTest(false/*usePreCorrectArray*/);
+    subCropOverZoomRangeTest(true/*usePreCorrectArray*/);
+}
+
+void subZoomOverMaxDigitalZoomTest(bool usePreCorrectArray) {
+    status_t res;
+    ZoomRatioMapper mapper;
+    float noZoomRatioRange[2];
+    res = setupTestMapper(&mapper, 4.0/*maxDigitalZoom*/,
+            testActiveArraySize, testPreCorrActiveArraySize,
+            false/*hasZoomRatioRange*/, noZoomRatioRange,
+            usePreCorrectArray);
+    ASSERT_EQ(res, OK);
+
+    CameraMetadata metadata;
+    float zoomRatio = 3.0f;
+    camera_metadata_entry_t entry;
+
+    size_t index = usePreCorrectArray ? 1 : 0;
+
+    // Full active array crop, zoomRatio is 3.0f
+    metadata.update(ANDROID_SCALER_CROP_REGION, testDefaultCropSize[index], 4);
+    metadata.update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+    res = mapper.updateCaptureRequest(&metadata);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    std::array<float, 4> expectedCrop = {
+        testDefaultCropSize[index][2] / 3.0f, /*x*/
+        testDefaultCropSize[index][3] / 3.0f, /*y*/
+        testDefaultCropSize[index][2] / 3.0f, /*width*/
+        testDefaultCropSize[index][3] / 3.0f, /*height*/
+    };
+    for (int i = 0; i < 4; i++) {
+        EXPECT_LE(std::abs(entry.data.i32[i] - expectedCrop[i]), kMaxAllowedPixelError);
+    }
+
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    if (entry.count == 1) {
+        EXPECT_NEAR(entry.data.f[0], 1.0f, kMaxAllowedRatioError);
+    }
+}
+
+TEST(ZoomRatioTest, ZoomOverMaxDigitalZoomTest) {
+    subZoomOverMaxDigitalZoomTest(false/*usePreCorrectArray*/);
+    subZoomOverMaxDigitalZoomTest(true/*usePreCorrectArray*/);
+}
+
+void subZoomOverZoomRangeTest(bool usePreCorrectArray) {
+    status_t res;
+    ZoomRatioMapper mapper;
+    float zoomRatioRange[2] = {1.0f, 4.0f};
+    res = setupTestMapper(&mapper, 4.0/*maxDigitalZoom*/,
+            testActiveArraySize, testPreCorrActiveArraySize,
+            true/*hasZoomRatioRange*/, zoomRatioRange,
+            usePreCorrectArray);
+    ASSERT_EQ(res, OK);
+
+    CameraMetadata metadata;
+    float zoomRatio = 3.0f;
+    camera_metadata_entry_t entry;
+    size_t index = usePreCorrectArray ? 1 : 0;
+
+    // Full active array crop, zoomRatio is 3.0f
+    metadata.update(ANDROID_SCALER_CROP_REGION, testDefaultCropSize[index], 4);
+    metadata.update(ANDROID_CONTROL_ZOOM_RATIO, &zoomRatio, 1);
+    res = mapper.updateCaptureRequest(&metadata);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i ++) {
+        EXPECT_EQ(entry.data.i32[i], testDefaultCropSize[index][i]);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    ASSERT_EQ(entry.data.f[0], zoomRatio);
+
+    res = mapper.updateCaptureResult(&metadata, false/*requestedZoomRatioIs1*/);
+    ASSERT_EQ(res, OK);
+    entry = metadata.find(ANDROID_SCALER_CROP_REGION);
+    ASSERT_EQ(entry.count, 4U);
+    for (int i = 0; i < 4; i ++) {
+        EXPECT_EQ(entry.data.i32[i], testDefaultCropSize[index][i]);
+    }
+    entry = metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
+    ASSERT_EQ(entry.data.f[0], zoomRatio);
+}
+
+TEST(ZoomRatioTest, ZoomOverZoomRangeTest) {
+    subZoomOverZoomRangeTest(false/*usePreCorrectArray*/);
+    subZoomOverZoomRangeTest(true/*usePreCorrectArray*/);
+}
diff --git a/services/camera/libcameraservice/utils/CameraThreadState.cpp b/services/camera/libcameraservice/utils/CameraThreadState.cpp
index b9e344b..2352b80 100644
--- a/services/camera/libcameraservice/utils/CameraThreadState.cpp
+++ b/services/camera/libcameraservice/utils/CameraThreadState.cpp
@@ -17,33 +17,34 @@
 #include "CameraThreadState.h"
 #include <binder/IPCThreadState.h>
 #include <hwbinder/IPCThreadState.h>
+#include <binderthreadstate/CallerUtils.h>
 #include <unistd.h>
 
 namespace android {
 
 int CameraThreadState::getCallingUid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingUid();
     }
     return IPCThreadState::self()->getCallingUid();
 }
 
 int CameraThreadState::getCallingPid() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->getCallingPid();
     }
     return IPCThreadState::self()->getCallingPid();
 }
 
 int64_t CameraThreadState::clearCallingIdentity() {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         return hardware::IPCThreadState::self()->clearCallingIdentity();
     }
     return IPCThreadState::self()->clearCallingIdentity();
 }
 
 void CameraThreadState::restoreCallingIdentity(int64_t token) {
-    if (hardware::IPCThreadState::self()->isServingCall()) {
+    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
         hardware::IPCThreadState::self()->restoreCallingIdentity(token);
     } else {
         IPCThreadState::self()->restoreCallingIdentity(token);
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index ec6f01c..64be6c5 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -35,7 +35,7 @@
 public:
     /**
      * Choosing to set mIsVendorClient through a parameter instead of calling
-     * hardware::IPCThreadState::self()->isServingCall() to protect against the
+     * getCurrentServingCall() == BinderCallType::HWBINDER to protect against the
      * case where the construction is offloaded to another thread which isn't a
      * hwbinder thread.
      */
@@ -237,7 +237,7 @@
     // We don't use the usual copy constructor here since we want to remember
     // whether a client is a vendor client or not. This could have been wiped
     // off in the incoming priority argument since an AIDL thread might have
-    // called hardware::IPCThreadState::self()->isServingCall() after refreshing
+    // called getCurrentServingCall() == BinderCallType::HWBINDER after refreshing
     // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
     mPriority.setScore(priority.getScore());
     mPriority.setState(priority.getState());
@@ -496,6 +496,20 @@
                 evictList.clear();
                 evictList.push_back(client);
                 return evictList;
+            } else if (conflicting && owner == curOwner) {
+                // Pre-existing conflicting client with the same client owner exists
+                // Open the same device twice -> most recent open wins
+                // Otherwise let the existing client wins to avoid behaviors difference
+                // due to how HAL advertising conflicting devices (which is hidden from
+                // application)
+                if (curKey == key) {
+                    evictList.push_back(i);
+                    totalCost -= curCost;
+                } else {
+                    evictList.clear();
+                    evictList.push_back(client);
+                    return evictList;
+                }
             } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
                     (curPriority >= priority) &&
                     !(highestPriorityOwner == owner && owner == curOwner))) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
new file mode 100644
index 0000000..888671c
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "SessionConfigurationUtils.h"
+#include "../api2/CameraDeviceClient.h"
+
+namespace android {
+
+binder::Status
+SessionConfigurationUtils::convertToHALStreamCombination(
+        const SessionConfiguration& sessionConfiguration,
+        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+        hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration, bool *earlyExit) {
+    // TODO: http://b/148329298 Move the other dependencies from
+    // CameraDeviceClient into SessionConfigurationUtils.
+    return CameraDeviceClient::convertToHALStreamCombination(sessionConfiguration, logicalCameraId,
+            deviceInfo, getMetadata, physicalCameraIds, streamConfiguration, earlyExit);
+}
+
+}// namespace android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
new file mode 100644
index 0000000..cfb9f17
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_SERVERS_CAMERA_SESSION_CONFIGURATION_UTILS_H
+#define ANDROID_SERVERS_CAMERA_SESSION_CONFIGURATION_UTILS_H
+
+#include <android/hardware/camera2/BnCameraDeviceUser.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
+#include <camera/camera2/SubmitInfo.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+
+#include <stdint.h>
+
+namespace android {
+
+typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
+
+class SessionConfigurationUtils {
+public:
+    // utility function to convert AIDL SessionConfiguration to HIDL
+    // streamConfiguration. Also checks for validity of SessionConfiguration and
+    // returns a non-ok binder::Status if the passed in session configuration
+    // isn't valid.
+    static binder::Status
+    convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
+            const String8 &cameraId, const CameraMetadata &deviceInfo,
+            metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+            hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+            bool *earlyExit);
+};
+
+} // android
+#endif
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 4037a66..262f962 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -33,6 +33,16 @@
         mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
 {}
 
+TagMonitor::TagMonitor(const TagMonitor& other):
+        mMonitoringEnabled(other.mMonitoringEnabled.load()),
+        mMonitoredTagList(other.mMonitoredTagList),
+        mLastMonitoredRequestValues(other.mLastMonitoredRequestValues),
+        mLastMonitoredResultValues(other.mLastMonitoredResultValues),
+        mLastMonitoredPhysicalRequestKeys(other.mLastMonitoredPhysicalRequestKeys),
+        mLastMonitoredPhysicalResultKeys(other.mLastMonitoredPhysicalResultKeys),
+        mMonitoringEvents(other.mMonitoringEvents),
+        mVendorTagId(other.mVendorTagId) {}
+
 const String16 TagMonitor::kMonitorOption = String16("-m");
 
 const char* TagMonitor::k3aTags =
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index 1b7b033..413f502 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -50,6 +50,8 @@
 
     TagMonitor();
 
+    TagMonitor(const TagMonitor& other);
+
     void initialize(metadata_vendor_id_t id) { mVendorTagId = id; }
 
     // Parse tag name list (comma-separated) and if valid, enable monitoring
diff --git a/services/camera/libcameraservice/utils/TraceHFR.h b/services/camera/libcameraservice/utils/TraceHFR.h
new file mode 100644
index 0000000..3a1900f
--- /dev/null
+++ b/services/camera/libcameraservice/utils/TraceHFR.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_ENABLE_HFR_TRACES_H_
+#define ANDROID_SERVERS_ENABLE_HFR_TRACES_H_
+
+#include <utils/Trace.h>
+
+#ifdef HFR_ENABLE_TRACING
+#define ATRACE_HFR_CALL() ATRACE_CALL()
+#else
+#define ATRACE_HFR_CALL()
+#endif
+
+#endif
diff --git a/services/mediaanalytics/Android.bp b/services/mediaanalytics/Android.bp
deleted file mode 100644
index 72f4b52..0000000
--- a/services/mediaanalytics/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// Media Statistics service
-//
-
-cc_binary {
-    name: "mediametrics",
-
-    srcs: [
-        "main_mediametrics.cpp",
-        "MediaAnalyticsService.cpp",
-        "iface_statsd.cpp",
-        "statsd_audiopolicy.cpp",
-        "statsd_audiorecord.cpp",
-        "statsd_audiothread.cpp",
-        "statsd_audiotrack.cpp",
-        "statsd_codec.cpp",
-        "statsd_drm.cpp",
-        "statsd_extractor.cpp",
-        "statsd_nuplayer.cpp",
-        "statsd_recorder.cpp",
-    ],
-
-    proto: {
-        type: "lite",
-    },
-
-    shared_libs: [
-        "libcutils",
-        "liblog",
-        "libmedia",
-        "libutils",
-        "libbinder",
-        "libdl",
-        "libgui",
-        "libmedia",
-        "libmediautils",
-        "libmediametrics",
-        "libstagefright_foundation",
-        "libstatslog",
-        "libutils",
-        "libprotobuf-cpp-lite",
-    ],
-
-    static_libs: [
-        "libplatformprotos",
-        "libregistermsext",
-    ],
-
-    include_dirs: [
-        "frameworks/av/media/libstagefright/include",
-        "frameworks/av/media/libstagefright/rtsp",
-        "frameworks/av/media/libstagefright/webm",
-        "frameworks/av/include/media",
-        "frameworks/av/include/camera",
-        "frameworks/native/include/media/openmax",
-        "frameworks/native/include/media/hardware",
-        "external/tremolo/Tremolo",
-    ],
-
-    init_rc: ["mediametrics.rc"],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-        "-Wno-error=deprecated-declarations",
-    ],
-    clang: true,
-
-}
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
deleted file mode 100644
index 0e7edfd..0000000
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaAnalyticsService"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#include <string.h>
-#include <pwd.h>
-
-#include <cutils/atomic.h>
-#include <cutils/properties.h> // for property_get
-
-#include <utils/misc.h>
-
-#include <android/content/pm/IPackageManagerNative.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
-#include <gui/Surface.h>
-#include <utils/Errors.h>  // for status_t
-#include <utils/List.h>
-#include <utils/String8.h>
-#include <utils/SystemClock.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
-#include <media/IMediaHTTPService.h>
-#include <media/IRemoteDisplay.h>
-#include <media/IRemoteDisplayClient.h>
-#include <media/MediaPlayerInterface.h>
-#include <media/mediarecorder.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-#include <media/Metadata.h>
-#include <media/AudioTrack.h>
-#include <media/MemoryLeakTrackUtil.h>
-#include <media/stagefright/MediaCodecList.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooperRoster.h>
-#include <mediautils/BatteryNotifier.h>
-
-//#include <memunreachable/memunreachable.h>
-#include <system/audio.h>
-
-#include <private/android_filesystem_config.h>
-
-#include "MediaAnalyticsService.h"
-
-namespace android {
-
-// individual records kept in memory: age or count
-// age: <= 28 hours (1 1/6 days)
-// count: hard limit of # records
-// (0 for either of these disables that threshold)
-//
-static constexpr nsecs_t kMaxRecordAgeNs =  28 * 3600 * (1000*1000*1000ll);
-// 2019/6: average daily per device is currently 375-ish;
-// setting this to 2000 is large enough to catch most devices
-// we'll lose some data on very very media-active devices, but only for
-// the gms collection; statsd will have already covered those for us.
-// This also retains enough information to help with bugreports
-static constexpr int kMaxRecords    = 2000;
-
-// max we expire in a single call, to constrain how long we hold the
-// mutex, which also constrains how long a client might wait.
-static constexpr int kMaxExpiredAtOnce = 50;
-
-// TODO: need to look at tuning kMaxRecords and friends for low-memory devices
-
-static const char *kServiceName = "media.metrics";
-
-void MediaAnalyticsService::instantiate() {
-    defaultServiceManager()->addService(
-            String16(kServiceName), new MediaAnalyticsService());
-}
-
-MediaAnalyticsService::MediaAnalyticsService()
-        : mMaxRecords(kMaxRecords),
-          mMaxRecordAgeNs(kMaxRecordAgeNs),
-          mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce),
-          mDumpProto(MediaAnalyticsItem::PROTO_V1),
-          mDumpProtoDefault(MediaAnalyticsItem::PROTO_V1) {
-
-    ALOGD("MediaAnalyticsService created");
-
-    mItemsSubmitted = 0;
-    mItemsFinalized = 0;
-    mItemsDiscarded = 0;
-    mItemsDiscardedExpire = 0;
-    mItemsDiscardedCount = 0;
-
-    mLastSessionID = 0;
-    // recover any persistency we set up
-    // etc
-}
-
-MediaAnalyticsService::~MediaAnalyticsService() {
-        ALOGD("MediaAnalyticsService destroyed");
-
-    while (mItems.size() > 0) {
-        MediaAnalyticsItem * oitem = *(mItems.begin());
-        mItems.erase(mItems.begin());
-        delete oitem;
-        mItemsDiscarded++;
-        mItemsDiscardedCount++;
-    }
-}
-
-
-MediaAnalyticsItem::SessionID_t MediaAnalyticsService::generateUniqueSessionID() {
-    // generate a new sessionid
-
-    Mutex::Autolock _l(mLock_ids);
-    return (++mLastSessionID);
-}
-
-// caller surrenders ownership of 'item'
-MediaAnalyticsItem::SessionID_t MediaAnalyticsService::submit(MediaAnalyticsItem *item, bool forcenew)
-{
-    UNUSED(forcenew);
-
-    // fill in a sessionID if we do not yet have one
-    if (item->getSessionID() <= MediaAnalyticsItem::SessionIDNone) {
-        item->setSessionID(generateUniqueSessionID());
-    }
-
-    // we control these, generally not trusting user input
-    nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
-    // round nsecs to seconds
-    now = ((now + 500000000) / 1000000000) * 1000000000;
-    item->setTimestamp(now);
-    int pid = IPCThreadState::self()->getCallingPid();
-    int uid = IPCThreadState::self()->getCallingUid();
-
-    int uid_given = item->getUid();
-    int pid_given = item->getPid();
-
-    // although we do make exceptions for some trusted client uids
-    bool isTrusted = false;
-
-    ALOGV("caller has uid=%d, embedded uid=%d", uid, uid_given);
-
-    switch (uid)  {
-        case AID_MEDIA:
-        case AID_MEDIA_CODEC:
-        case AID_MEDIA_EX:
-        case AID_MEDIA_DRM:
-            // trusted source, only override default values
-            isTrusted = true;
-            if (uid_given == (-1)) {
-                item->setUid(uid);
-            }
-            if (pid_given == (-1)) {
-                item->setPid(pid);
-            }
-            break;
-        default:
-            isTrusted = false;
-            item->setPid(pid);
-            item->setUid(uid);
-            break;
-    }
-
-    // Overwrite package name and version if the caller was untrusted.
-    if (!isTrusted) {
-      setPkgInfo(item, item->getUid(), true, true);
-    } else if (item->getPkgName().empty()) {
-      // empty, so fill out both parts
-      setPkgInfo(item, item->getUid(), true, true);
-    } else {
-      // trusted, provided a package, do nothing
-    }
-
-    ALOGV("given uid %d; sanitized uid: %d sanitized pkg: %s "
-          "sanitized pkg version: %"  PRId64,
-          uid_given, item->getUid(),
-          item->getPkgName().c_str(),
-          item->getPkgVersionCode());
-
-    mItemsSubmitted++;
-
-    // validate the record; we discard if we don't like it
-    if (contentValid(item, isTrusted) == false) {
-        delete item;
-        return MediaAnalyticsItem::SessionIDInvalid;
-    }
-
-    // XXX: if we have a sessionid in the new record, look to make
-    // sure it doesn't appear in the finalized list.
-
-    if (item->count() == 0) {
-        ALOGV("dropping empty record...");
-        delete item;
-        item = NULL;
-        return MediaAnalyticsItem::SessionIDInvalid;
-    }
-
-    // save the new record
-    //
-    // send a copy to statsd
-    dump2Statsd(item);
-
-    // and keep our copy for dumpsys
-    MediaAnalyticsItem::SessionID_t id = item->getSessionID();
-    saveItem(item);
-    mItemsFinalized++;
-
-    return id;
-}
-
-
-status_t MediaAnalyticsService::dump(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 512;
-    char buffer[SIZE];
-    String8 result;
-
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        snprintf(buffer, SIZE, "Permission Denial: "
-                "can't dump MediaAnalyticsService from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
-                IPCThreadState::self()->getCallingUid());
-        result.append(buffer);
-        write(fd, result.string(), result.size());
-        return NO_ERROR;
-    }
-
-    // crack any parameters
-    String16 protoOption("-proto");
-    int chosenProto = mDumpProtoDefault;
-    String16 clearOption("-clear");
-    bool clear = false;
-    String16 sinceOption("-since");
-    nsecs_t ts_since = 0;
-    String16 helpOption("-help");
-    String16 onlyOption("-only");
-    std::string only;
-    int n = args.size();
-
-    for (int i = 0; i < n; i++) {
-        String8 myarg(args[i]);
-        if (args[i] == clearOption) {
-            clear = true;
-        } else if (args[i] == protoOption) {
-            i++;
-            if (i < n) {
-                String8 value(args[i]);
-                int proto = MediaAnalyticsItem::PROTO_V0;
-                char *endp;
-                const char *p = value.string();
-                proto = strtol(p, &endp, 10);
-                if (endp != p || *endp == '\0') {
-                    if (proto < MediaAnalyticsItem::PROTO_FIRST) {
-                        proto = MediaAnalyticsItem::PROTO_FIRST;
-                    } else if (proto > MediaAnalyticsItem::PROTO_LAST) {
-                        proto = MediaAnalyticsItem::PROTO_LAST;
-                    }
-                    chosenProto = proto;
-                } else {
-                    result.append("unable to parse value for -proto\n\n");
-                }
-            } else {
-                result.append("missing value for -proto\n\n");
-            }
-        } else if (args[i] == sinceOption) {
-            i++;
-            if (i < n) {
-                String8 value(args[i]);
-                char *endp;
-                const char *p = value.string();
-                ts_since = strtoll(p, &endp, 10);
-                if (endp == p || *endp != '\0') {
-                    ts_since = 0;
-                }
-            } else {
-                ts_since = 0;
-            }
-            // command line is milliseconds; internal units are nano-seconds
-            ts_since *= 1000*1000;
-        } else if (args[i] == onlyOption) {
-            i++;
-            if (i < n) {
-                String8 value(args[i]);
-                only = value.string();
-            }
-        } else if (args[i] == helpOption) {
-            result.append("Recognized parameters:\n");
-            result.append("-help        this help message\n");
-            result.append("-proto #     dump using protocol #");
-            result.append("-clear       clears out saved records\n");
-            result.append("-only X      process records for component X\n");
-            result.append("-since X     include records since X\n");
-            result.append("             (X is milliseconds since the UNIX epoch)\n");
-            write(fd, result.string(), result.size());
-            return NO_ERROR;
-        }
-    }
-
-    Mutex::Autolock _l(mLock);
-    // mutex between insertion and dumping the contents
-
-    mDumpProto = chosenProto;
-
-    // we ALWAYS dump this piece
-    snprintf(buffer, SIZE, "Dump of the %s process:\n", kServiceName);
-    result.append(buffer);
-
-    dumpHeaders(result, ts_since);
-
-    dumpRecent(result, ts_since, only.c_str());
-
-
-    if (clear) {
-        // remove everything from the finalized queue
-        while (mItems.size() > 0) {
-            MediaAnalyticsItem * oitem = *(mItems.begin());
-            mItems.erase(mItems.begin());
-            delete oitem;
-            mItemsDiscarded++;
-        }
-
-        // shall we clear the summary data too?
-
-    }
-
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-// dump headers
-void MediaAnalyticsService::dumpHeaders(String8 &result, nsecs_t ts_since)
-{
-    const size_t SIZE = 512;
-    char buffer[SIZE];
-
-    snprintf(buffer, SIZE, "Protocol Version: %d\n", mDumpProto);
-    result.append(buffer);
-
-    int enabled = MediaAnalyticsItem::isEnabled();
-    if (enabled) {
-        snprintf(buffer, SIZE, "Metrics gathering: enabled\n");
-    } else {
-        snprintf(buffer, SIZE, "Metrics gathering: DISABLED via property\n");
-    }
-    result.append(buffer);
-
-    snprintf(buffer, SIZE,
-        "Since Boot: Submissions: %8" PRId64
-            " Accepted: %8" PRId64 "\n",
-        mItemsSubmitted, mItemsFinalized);
-    result.append(buffer);
-    snprintf(buffer, SIZE,
-        "Records Discarded: %8" PRId64
-            " (by Count: %" PRId64 " by Expiration: %" PRId64 ")\n",
-         mItemsDiscarded, mItemsDiscardedCount, mItemsDiscardedExpire);
-    result.append(buffer);
-    if (ts_since != 0) {
-        snprintf(buffer, SIZE,
-            "Emitting Queue entries more recent than: %" PRId64 "\n",
-            (int64_t) ts_since);
-        result.append(buffer);
-    }
-}
-
-// the recent, detailed queues
-void MediaAnalyticsService::dumpRecent(String8 &result, nsecs_t ts_since, const char * only)
-{
-    const size_t SIZE = 512;
-    char buffer[SIZE];
-
-    if (only != NULL && *only == '\0') {
-        only = NULL;
-    }
-
-    // show the recently recorded records
-    snprintf(buffer, sizeof(buffer), "\nFinalized Metrics (oldest first):\n");
-    result.append(buffer);
-    result.append(this->dumpQueue(ts_since, only));
-
-    // show who is connected and injecting records?
-    // talk about # records fed to the 'readers'
-    // talk about # records we discarded, perhaps "discarded w/o reading" too
-}
-
-// caller has locked mLock...
-String8 MediaAnalyticsService::dumpQueue() {
-    return dumpQueue((nsecs_t) 0, NULL);
-}
-
-String8 MediaAnalyticsService::dumpQueue(nsecs_t ts_since, const char * only) {
-    String8 result;
-    int slot = 0;
-
-    if (mItems.empty()) {
-            result.append("empty\n");
-    } else {
-        List<MediaAnalyticsItem *>::iterator it = mItems.begin();
-        for (; it != mItems.end(); it++) {
-            nsecs_t when = (*it)->getTimestamp();
-            if (when < ts_since) {
-                continue;
-            }
-            if (only != NULL &&
-                strcmp(only, (*it)->getKey().c_str()) != 0) {
-                ALOGV("Omit '%s', it's not '%s'", (*it)->getKey().c_str(), only);
-                continue;
-            }
-            std::string entry = (*it)->toString(mDumpProto);
-            result.appendFormat("%5d: %s\n", slot, entry.c_str());
-            slot++;
-        }
-    }
-
-    return result;
-}
-
-//
-// Our Cheap in-core, non-persistent records management.
-
-
-// we hold mLock when we get here
-// if item != NULL, it's the item we just inserted
-// true == more items eligible to be recovered
-bool MediaAnalyticsService::expirations_l(MediaAnalyticsItem *item)
-{
-    bool more = false;
-    int handled = 0;
-
-    // keep removing old records the front until we're in-bounds (count)
-    // since we invoke this with each insertion, it should be 0/1 iterations.
-    if (mMaxRecords > 0) {
-        while (mItems.size() > (size_t) mMaxRecords) {
-            MediaAnalyticsItem * oitem = *(mItems.begin());
-            if (oitem == item) {
-                break;
-            }
-            if (handled >= mMaxRecordsExpiredAtOnce) {
-                // unlikely in this loop
-                more = true;
-                break;
-            }
-            handled++;
-            mItems.erase(mItems.begin());
-            delete oitem;
-            mItemsDiscarded++;
-            mItemsDiscardedCount++;
-        }
-    }
-
-    // keep removing old records the front until we're in-bounds (age)
-    // limited to mMaxRecordsExpiredAtOnce items per invocation.
-    if (mMaxRecordAgeNs > 0) {
-        nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
-        while (mItems.size() > 0) {
-            MediaAnalyticsItem * oitem = *(mItems.begin());
-            nsecs_t when = oitem->getTimestamp();
-            if (oitem == item) {
-                break;
-            }
-            // careful about timejumps too
-            if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
-                // this (and the rest) are recent enough to keep
-                break;
-            }
-            if (handled >= mMaxRecordsExpiredAtOnce) {
-                // this represents "one too many"; tell caller there are
-                // more to be reclaimed.
-                more = true;
-                break;
-            }
-            handled++;
-            mItems.erase(mItems.begin());
-            delete oitem;
-            mItemsDiscarded++;
-            mItemsDiscardedExpire++;
-        }
-    }
-
-    // we only indicate whether there's more to clean;
-    // caller chooses whether to schedule further cleanup.
-    return more;
-}
-
-// process expirations in bite sized chunks, allowing new insertions through
-// runs in a pthread specifically started for this (which then exits)
-bool MediaAnalyticsService::processExpirations()
-{
-    bool more;
-    do {
-        sleep(1);
-        {
-            Mutex::Autolock _l(mLock);
-            more = expirations_l(NULL);
-            if (!more) {
-                break;
-            }
-        }
-    } while (more);
-    return true;        // value is for std::future thread synchronization
-}
-
-// insert appropriately into queue
-void MediaAnalyticsService::saveItem(MediaAnalyticsItem * item)
-{
-
-    Mutex::Autolock _l(mLock);
-    // mutex between insertion and dumping the contents
-
-    // we want to dump 'in FIFO order', so insert at the end
-    mItems.push_back(item);
-
-    // clean old stuff from the queue
-    bool more = expirations_l(item);
-
-    // consider scheduling some asynchronous cleaning, if not running
-    if (more) {
-        if (!mExpireFuture.valid()
-            || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
-
-            mExpireFuture = std::async(std::launch::async, [this]()
-                                       {return this->processExpirations();});
-        }
-    }
-}
-
-static std::string allowedKeys[] =
-{
-    "audiopolicy",
-    "audiorecord",
-    "audiothread",
-    "audiotrack",
-    "codec",
-    "extractor",
-    "nuplayer",
-};
-
-static const int nAllowedKeys = sizeof(allowedKeys) / sizeof(allowedKeys[0]);
-
-// are the contents good
-bool MediaAnalyticsService::contentValid(MediaAnalyticsItem *item, bool isTrusted) {
-
-    // untrusted uids can only send us a limited set of keys
-    if (isTrusted == false) {
-        // restrict to a specific set of keys
-        std::string key = item->getKey();
-
-        size_t i;
-        for(i = 0; i < nAllowedKeys; i++) {
-            if (key == allowedKeys[i]) {
-                break;
-            }
-        }
-        if (i == nAllowedKeys) {
-            ALOGD("Ignoring (key): %s", item->toString().c_str());
-            return false;
-        }
-    }
-
-    // internal consistency
-
-    return true;
-}
-
-// are we rate limited, normally false
-bool MediaAnalyticsService::rateLimited(MediaAnalyticsItem *) {
-
-    return false;
-}
-
-// how long we hold package info before we re-fetch it
-#define PKG_EXPIRATION_NS (30*60*1000000000ll)   // 30 minutes, in nsecs
-
-// give me the package name, perhaps going to find it
-// manages its own mutex operations internally
-void MediaAnalyticsService::setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion)
-{
-    ALOGV("asking for packagename to go with uid=%d", uid);
-
-    if (!setName && !setVersion) {
-        // setting nothing? strange
-        return;
-    }
-
-    nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
-    struct UidToPkgMap mapping;
-    mapping.uid = (uid_t)(-1);
-
-    {
-        Mutex::Autolock _l(mLock_mappings);
-        int i = mPkgMappings.indexOfKey(uid);
-        if (i >= 0) {
-            mapping = mPkgMappings.valueAt(i);
-            ALOGV("Expiration? uid %d expiration %" PRId64 " now %" PRId64,
-                  uid, mapping.expiration, now);
-            if (mapping.expiration <= now) {
-                // purge the stale entry and fall into re-fetching
-                ALOGV("entry for uid %d expired, now= %" PRId64 "", uid, now);
-                mPkgMappings.removeItemsAt(i);
-                mapping.uid = (uid_t)(-1);
-            }
-        }
-    }
-
-    // if we did not find it
-    if (mapping.uid == (uid_t)(-1)) {
-        std::string pkg;
-        std::string installer = "";
-        int64_t versionCode = 0;
-
-        struct passwd *pw = getpwuid(uid);
-        if (pw) {
-            pkg = pw->pw_name;
-        }
-
-        // find the proper value
-
-        sp<IBinder> binder = NULL;
-        sp<IServiceManager> sm = defaultServiceManager();
-        if (sm == NULL) {
-            ALOGE("defaultServiceManager failed");
-        } else {
-            binder = sm->getService(String16("package_native"));
-            if (binder == NULL) {
-                ALOGE("getService package_native failed");
-            }
-        }
-
-        if (binder != NULL) {
-            sp<content::pm::IPackageManagerNative> package_mgr =
-                            interface_cast<content::pm::IPackageManagerNative>(binder);
-            binder::Status status;
-
-            std::vector<int> uids;
-            std::vector<std::string> names;
-
-            uids.push_back(uid);
-
-            status = package_mgr->getNamesForUids(uids, &names);
-            if (!status.isOk()) {
-                ALOGE("package_native::getNamesForUids failed: %s",
-                      status.exceptionMessage().c_str());
-            } else {
-                if (!names[0].empty()) {
-                    pkg = names[0].c_str();
-                }
-            }
-
-            // strip any leading "shared:" strings that came back
-            if (pkg.compare(0, 7, "shared:") == 0) {
-                pkg.erase(0, 7);
-            }
-
-            // determine how pkg was installed and the versionCode
-            //
-            if (pkg.empty()) {
-                // no name for us to manage
-            } else if (strchr(pkg.c_str(), '.') == NULL) {
-                // not of form 'com.whatever...'; assume internal and ok
-            } else if (strncmp(pkg.c_str(), "android.", 8) == 0) {
-                // android.* packages are assumed fine
-            } else {
-                String16 pkgName16(pkg.c_str());
-                status = package_mgr->getInstallerForPackage(pkgName16, &installer);
-                if (!status.isOk()) {
-                    ALOGE("package_native::getInstallerForPackage failed: %s",
-                          status.exceptionMessage().c_str());
-                }
-
-                // skip if we didn't get an installer
-                if (status.isOk()) {
-                    status = package_mgr->getVersionCodeForPackage(pkgName16, &versionCode);
-                    if (!status.isOk()) {
-                        ALOGE("package_native::getVersionCodeForPackage failed: %s",
-                          status.exceptionMessage().c_str());
-                    }
-                }
-
-
-                ALOGV("package '%s' installed by '%s' versioncode %"  PRId64 " / %" PRIx64,
-                      pkg.c_str(), installer.c_str(), versionCode, versionCode);
-
-                if (strncmp(installer.c_str(), "com.android.", 12) == 0) {
-                        // from play store, we keep info
-                } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) {
-                        // some google source, we keep info
-                } else if (strcmp(installer.c_str(), "preload") == 0) {
-                        // preloads, we keep the info
-                } else if (installer.c_str()[0] == '\0') {
-                        // sideload (no installer); do not report
-                        pkg = "";
-                        versionCode = 0;
-                } else {
-                        // unknown installer; do not report
-                        pkg = "";
-                        versionCode = 0;
-                }
-            }
-        }
-
-        // add it to the map, to save a subsequent lookup
-        if (!pkg.empty()) {
-            Mutex::Autolock _l(mLock_mappings);
-            ALOGV("Adding uid %d pkg '%s'", uid, pkg.c_str());
-            ssize_t i = mPkgMappings.indexOfKey(uid);
-            if (i < 0) {
-                mapping.uid = uid;
-                mapping.pkg = pkg;
-                mapping.installer = installer.c_str();
-                mapping.versionCode = versionCode;
-                mapping.expiration = now + PKG_EXPIRATION_NS;
-                ALOGV("expiration for uid %d set to %" PRId64 "", uid, mapping.expiration);
-
-                mPkgMappings.add(uid, mapping);
-            }
-        }
-    }
-
-    if (mapping.uid != (uid_t)(-1)) {
-        if (setName) {
-            item->setPkgName(mapping.pkg);
-        }
-        if (setVersion) {
-            item->setPkgVersionCode(mapping.versionCode);
-        }
-    }
-}
-
-} // namespace android
diff --git a/services/mediaanalytics/MediaAnalyticsService.h b/services/mediaanalytics/MediaAnalyticsService.h
deleted file mode 100644
index 6c9cbaa..0000000
--- a/services/mediaanalytics/MediaAnalyticsService.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2017 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 ANDROID_MEDIAANALYTICSSERVICE_H
-#define ANDROID_MEDIAANALYTICSSERVICE_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/List.h>
-
-#include <future>
-
-#include <media/IMediaAnalyticsService.h>
-
-namespace android {
-
-class MediaAnalyticsService : public BnMediaAnalyticsService
-{
-
- public:
-
-    // on this side, caller surrenders ownership
-    virtual int64_t submit(MediaAnalyticsItem *item, bool forcenew);
-
-    static  void            instantiate();
-    virtual status_t        dump(int fd, const Vector<String16>& args);
-
-                            MediaAnalyticsService();
-    virtual                 ~MediaAnalyticsService();
-
-    bool processExpirations();
-
- private:
-    MediaAnalyticsItem::SessionID_t generateUniqueSessionID();
-
-    // statistics about our analytics
-    int64_t mItemsSubmitted;
-    int64_t mItemsFinalized;
-    int64_t mItemsDiscarded;
-    int64_t mItemsDiscardedExpire;
-    int64_t mItemsDiscardedCount;
-    MediaAnalyticsItem::SessionID_t mLastSessionID;
-
-    // partitioned a bit so we don't over serialize
-    mutable Mutex           mLock;
-    mutable Mutex           mLock_ids;
-    mutable Mutex           mLock_mappings;
-
-    // limit how many records we'll retain
-    // by count (in each queue (open, finalized))
-    int32_t mMaxRecords;
-    // by time (none older than this long agan
-    nsecs_t mMaxRecordAgeNs;
-    // max to expire per expirations_l() invocation
-    int32_t mMaxRecordsExpiredAtOnce;
-    //
-    // # of sets of summaries
-    int32_t mMaxRecordSets;
-    // nsecs until we start a new record set
-    nsecs_t mNewSetInterval;
-
-    // input validation after arrival from client
-    bool contentValid(MediaAnalyticsItem *item, bool isTrusted);
-    bool rateLimited(MediaAnalyticsItem *);
-
-    // (oldest at front) so it prints nicely for dumpsys
-    List<MediaAnalyticsItem *> mItems;
-    void saveItem(MediaAnalyticsItem *);
-
-    bool expirations_l(MediaAnalyticsItem *);
-    std::future<bool> mExpireFuture;
-
-    // support for generating output
-    int mDumpProto;
-    int mDumpProtoDefault;
-    String8 dumpQueue();
-    String8 dumpQueue(nsecs_t, const char *only);
-
-    void dumpHeaders(String8 &result, nsecs_t ts_since);
-    void dumpSummaries(String8 &result, nsecs_t ts_since, const char * only);
-    void dumpRecent(String8 &result, nsecs_t ts_since, const char * only);
-
-    // mapping uids to package names
-    struct UidToPkgMap {
-        uid_t uid;
-        std::string pkg;
-        std::string installer;
-        int64_t versionCode;
-        nsecs_t expiration;
-    };
-
-    KeyedVector<uid_t,struct UidToPkgMap>  mPkgMappings;
-    void setPkgInfo(MediaAnalyticsItem *item, uid_t uid, bool setName, bool setVersion);
-
-};
-
-// hook to send things off to the statsd subsystem
-extern bool dump2Statsd(MediaAnalyticsItem *item);
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIAANALYTICSSERVICE_H
diff --git a/services/mediaanalytics/OWNERS b/services/mediaanalytics/OWNERS
deleted file mode 100644
index 9af258b..0000000
--- a/services/mediaanalytics/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-essick@google.com
diff --git a/services/mediaanalytics/iface_statsd.cpp b/services/mediaanalytics/iface_statsd.cpp
deleted file mode 100644
index 6845f06..0000000
--- a/services/mediaanalytics/iface_statsd.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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 "iface_statsd"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#include <string.h>
-#include <pwd.h>
-
-#include "MediaAnalyticsService.h"
-#include "iface_statsd.h"
-
-#include <statslog.h>
-
-namespace android {
-
-// set of routines that crack a MediaAnalyticsItem
-// and send it off to statsd with the appropriate hooks
-//
-// each MediaAnalyticsItem type (extractor, codec, nuplayer, etc)
-// has its own routine to handle this.
-//
-
-bool enabled_statsd = true;
-
-struct statsd_hooks {
-    const char *key;
-    bool (*handler)(MediaAnalyticsItem *);
-};
-
-// keep this sorted, so we can do binary searches
-struct statsd_hooks  statsd_handlers[] =
-{
-    { "audiopolicy", statsd_audiopolicy },
-    { "audiorecord", statsd_audiorecord },
-    { "audiothread", statsd_audiothread },
-    { "audiotrack", statsd_audiotrack },
-    { "codec", statsd_codec},
-    { "drm.vendor.Google.WidevineCDM", statsd_widevineCDM },
-    { "extractor", statsd_extractor },
-    { "mediadrm", statsd_mediadrm },
-    { "nuplayer", statsd_nuplayer },
-    { "nuplayer2", statsd_nuplayer },
-    { "recorder", statsd_recorder },
-};
-
-
-// give me a record, i'll look at the type and upload appropriately
-bool dump2Statsd(MediaAnalyticsItem *item) {
-    if (item == NULL) return false;
-
-    // get the key
-    std::string key = item->getKey();
-
-    if (!enabled_statsd) {
-        ALOGV("statsd logging disabled for record key=%s", key.c_str());
-        return false;
-    }
-
-    int i;
-    for(i = 0;i < sizeof(statsd_handlers) / sizeof(statsd_handlers[0]) ; i++) {
-        if (key == statsd_handlers[i].key) {
-            return (*statsd_handlers[i].handler)(item);
-        }
-    }
-    return false;
-}
-
-} // namespace android
diff --git a/services/mediaanalytics/iface_statsd.h b/services/mediaanalytics/iface_statsd.h
deleted file mode 100644
index f85d303..0000000
--- a/services/mediaanalytics/iface_statsd.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-namespace android {
-
-extern bool enabled_statsd;
-
-// component specific dumpers
-extern bool statsd_audiopolicy(MediaAnalyticsItem *);
-extern bool statsd_audiorecord(MediaAnalyticsItem *);
-extern bool statsd_audiothread(MediaAnalyticsItem *);
-extern bool statsd_audiotrack(MediaAnalyticsItem *);
-extern bool statsd_codec(MediaAnalyticsItem *);
-extern bool statsd_extractor(MediaAnalyticsItem *);
-extern bool statsd_nuplayer(MediaAnalyticsItem *);
-extern bool statsd_recorder(MediaAnalyticsItem *);
-
-extern bool statsd_mediadrm(MediaAnalyticsItem *);
-extern bool statsd_widevineCDM(MediaAnalyticsItem *);
-
-} // namespace android
diff --git a/services/mediaanalytics/main_mediametrics.cpp b/services/mediaanalytics/main_mediametrics.cpp
deleted file mode 100644
index 8020a03..0000000
--- a/services/mediaanalytics/main_mediametrics.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2016 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_TAG "mediametrics"
-//#define LOG_NDEBUG 0
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-//#include "RegisterExtensions.h"
-
-// from LOCAL_C_INCLUDES
-#include "MediaAnalyticsService.h"
-
-using namespace android;
-
-int main(int argc __unused, char **argv __unused)
-{
-    signal(SIGPIPE, SIG_IGN);
-
-    // to match the service name
-    // we're replacing "/system/bin/mediametrics" with "media.metrics"
-    // we add a ".", but discard the path components: we finish with a shorter string
-    strcpy(argv[0], "media.metrics");
-
-    sp<ProcessState> proc(ProcessState::self());
-    sp<IServiceManager> sm(defaultServiceManager());
-    ALOGI("ServiceManager: %p", sm.get());
-
-    MediaAnalyticsService::instantiate();
-
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
-}
diff --git a/services/mediaanalytics/mediametrics.rc b/services/mediaanalytics/mediametrics.rc
deleted file mode 100644
index 1efde5e..0000000
--- a/services/mediaanalytics/mediametrics.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service mediametrics /system/bin/mediametrics
-    class main
-    user media
-    group media
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
diff --git a/services/mediaanalytics/statsd_audiopolicy.cpp b/services/mediaanalytics/statsd_audiopolicy.cpp
deleted file mode 100644
index 06c4dde..0000000
--- a/services/mediaanalytics/statsd_audiopolicy.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_audiopolicy"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_audiopolicy(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::AudioPolicyData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-    //int32 char kAudioPolicyStatus[] = "android.media.audiopolicy.status";
-    int32_t status = -1;
-    if (item->getInt32("android.media.audiopolicy.status", &status)) {
-        metrics_proto.set_status(status);
-    }
-    //string char kAudioPolicyRqstSrc[] = "android.media.audiopolicy.rqst.src";
-    char *rqst_src = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.src", &rqst_src)) {
-        metrics_proto.set_request_source(rqst_src);
-    }
-    //string char kAudioPolicyRqstPkg[] = "android.media.audiopolicy.rqst.pkg";
-    char *rqst_pkg = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.pkg", &rqst_pkg)) {
-        metrics_proto.set_request_package(rqst_pkg);
-    }
-    //int32 char kAudioPolicyRqstSession[] = "android.media.audiopolicy.rqst.session";
-    int32_t rqst_session = -1;
-    if (item->getInt32("android.media.audiopolicy.rqst.session", &rqst_session)) {
-        metrics_proto.set_request_session(rqst_session);
-    }
-    //string char kAudioPolicyRqstDevice[] = "android.media.audiopolicy.rqst.device";
-    char *rqst_device = NULL;
-    if (item->getCString("android.media.audiopolicy.rqst.device", &rqst_device)) {
-        metrics_proto.set_request_device(rqst_device);
-    }
-
-    //string char kAudioPolicyActiveSrc[] = "android.media.audiopolicy.active.src";
-    char *active_src = NULL;
-    if (item->getCString("android.media.audiopolicy.active.src", &active_src)) {
-        metrics_proto.set_active_source(active_src);
-    }
-    //string char kAudioPolicyActivePkg[] = "android.media.audiopolicy.active.pkg";
-    char *active_pkg = NULL;
-    if (item->getCString("android.media.audiopolicy.active.pkg", &active_pkg)) {
-        metrics_proto.set_active_package(active_pkg);
-    }
-    //int32 char kAudioPolicyActiveSession[] = "android.media.audiopolicy.active.session";
-    int32_t active_session = -1;
-    if (item->getInt32("android.media.audiopolicy.active.session", &active_session)) {
-        metrics_proto.set_active_session(active_session);
-    }
-    //string char kAudioPolicyActiveDevice[] = "android.media.audiopolicy.active.device";
-    char *active_device = NULL;
-    if (item->getCString("android.media.audiopolicy.active.device", &active_device)) {
-        metrics_proto.set_active_device(active_device);
-    }
-
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize audipolicy metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(rqst_src);
-    free(rqst_pkg);
-    free(rqst_device);
-    free(active_src);
-    free(active_pkg);
-    free(active_device);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_audiorecord.cpp b/services/mediaanalytics/statsd_audiorecord.cpp
deleted file mode 100644
index c9edb27..0000000
--- a/services/mediaanalytics/statsd_audiorecord.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_audiorecord"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_audiorecord(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::AudioRecordData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-    char *encoding = NULL;
-    if (item->getCString("android.media.audiorecord.encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
-    }
-
-    char *source = NULL;
-    if (item->getCString("android.media.audiorecord.source", &source)) {
-        metrics_proto.set_source(source);
-    }
-
-    int32_t latency = -1;
-    if (item->getInt32("android.media.audiorecord.latency", &latency)) {
-        metrics_proto.set_latency(latency);
-    }
-
-    int32_t samplerate = -1;
-    if (item->getInt32("android.media.audiorecord.samplerate", &samplerate)) {
-        metrics_proto.set_samplerate(samplerate);
-    }
-
-    int32_t channels = -1;
-    if (item->getInt32("android.media.audiorecord.channels", &channels)) {
-        metrics_proto.set_channels(channels);
-    }
-
-    int64_t createdMs = -1;
-    if (item->getInt64("android.media.audiorecord.createdMs", &createdMs)) {
-        metrics_proto.set_created_millis(createdMs);
-    }
-
-    int64_t durationMs = -1;
-    if (item->getInt64("android.media.audiorecord.durationMs", &durationMs)) {
-        metrics_proto.set_duration_millis(durationMs);
-    }
-
-    int32_t count = -1;
-    if (item->getInt32("android.media.audiorecord.n", &count)) {
-        metrics_proto.set_count(count);
-    }
-
-    int32_t errcode = -1;
-    if (item->getInt32("android.media.audiorecord.errcode", &errcode)) {
-        metrics_proto.set_error_code(errcode);
-    } else if (item->getInt32("android.media.audiorecord.lastError.code", &errcode)) {
-        metrics_proto.set_error_code(errcode);
-    }
-
-    char *errfunc = NULL;
-    if (item->getCString("android.media.audiorecord.errfunc", &errfunc)) {
-        metrics_proto.set_error_function(errfunc);
-    } else if (item->getCString("android.media.audiorecord.lastError.at", &errfunc)) {
-        metrics_proto.set_error_function(errfunc);
-    }
-
-    // portId (int32)
-    int32_t port_id = -1;
-    if (item->getInt32("android.media.audiorecord.portId", &port_id)) {
-        metrics_proto.set_port_id(count);
-    }
-    // frameCount (int32)
-    int32_t frameCount = -1;
-    if (item->getInt32("android.media.audiorecord.frameCount", &frameCount)) {
-        metrics_proto.set_frame_count(frameCount);
-    }
-    // attributes (string)
-    char *attributes = NULL;
-    if (item->getCString("android.media.audiorecord.attributes", &attributes)) {
-        metrics_proto.set_attributes(attributes);
-    }
-    // channelMask (int64)
-    int64_t channelMask = -1;
-    if (item->getInt64("android.media.audiorecord.channelMask", &channelMask)) {
-        metrics_proto.set_channel_mask(channelMask);
-    }
-    // startcount (int64)
-    int64_t startcount = -1;
-    if (item->getInt64("android.media.audiorecord.startcount", &startcount)) {
-        metrics_proto.set_start_count(startcount);
-    }
-
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize audiorecord metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(encoding);
-    free(source);
-    free(errfunc);
-    free(attributes);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_audiothread.cpp b/services/mediaanalytics/statsd_audiothread.cpp
deleted file mode 100644
index 8232424..0000000
--- a/services/mediaanalytics/statsd_audiothread.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_audiothread"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_audiothread(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::AudioThreadData metrics_proto;
-
-#define	MM_PREFIX "android.media.audiothread."
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-    char *mytype = NULL;
-    if (item->getCString(MM_PREFIX "type", &mytype)) {
-        metrics_proto.set_type(mytype);
-    }
-    int32_t framecount = -1;
-    if (item->getInt32(MM_PREFIX "framecount", &framecount)) {
-        metrics_proto.set_framecount(framecount);
-    }
-    int32_t samplerate = -1;
-    if (item->getInt32(MM_PREFIX "samplerate", &samplerate)) {
-        metrics_proto.set_samplerate(samplerate);
-    }
-    char *workhist = NULL;
-    if (item->getCString(MM_PREFIX "workMs.hist", &workhist)) {
-        metrics_proto.set_work_millis_hist(workhist);
-    }
-    char *latencyhist = NULL;
-    if (item->getCString(MM_PREFIX "latencyMs.hist", &latencyhist)) {
-        metrics_proto.set_latency_millis_hist(latencyhist);
-    }
-    char *warmuphist = NULL;
-    if (item->getCString(MM_PREFIX "warmupMs.hist", &warmuphist)) {
-        metrics_proto.set_warmup_millis_hist(warmuphist);
-    }
-    int64_t underruns = -1;
-    if (item->getInt64(MM_PREFIX "underruns", &underruns)) {
-        metrics_proto.set_underruns(underruns);
-    }
-    int64_t overruns = -1;
-    if (item->getInt64(MM_PREFIX "overruns", &overruns)) {
-        metrics_proto.set_overruns(overruns);
-    }
-    int64_t activeMs = -1;
-    if (item->getInt64(MM_PREFIX "activeMs", &activeMs)) {
-        metrics_proto.set_active_millis(activeMs);
-    }
-    int64_t durationMs = -1;
-    if (item->getInt64(MM_PREFIX "durationMs", &durationMs)) {
-        metrics_proto.set_duration_millis(durationMs);
-    }
-
-    // item->setInt32(MM_PREFIX "id", (int32_t)mId); // IO handle
-    int32_t id = -1;
-    if (item->getInt32(MM_PREFIX "id", &id)) {
-        metrics_proto.set_id(id);
-    }
-    // item->setInt32(MM_PREFIX "portId", (int32_t)mPortId);
-    int32_t port_id = -1;
-    if (item->getInt32(MM_PREFIX "portId", &id)) {
-        metrics_proto.set_port_id(port_id);
-    }
-    // item->setCString(MM_PREFIX "type", threadTypeToString(mType));
-    char *type = NULL;
-    if (item->getCString(MM_PREFIX "type", &type)) {
-        metrics_proto.set_type(type);
-    }
-    // item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate);
-    int32_t sample_rate = -1;
-    if (item->getInt32(MM_PREFIX "sampleRate", &sample_rate)) {
-        metrics_proto.set_sample_rate(sample_rate);
-    }
-    // item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
-    int32_t channel_mask = -1;
-    if (item->getInt32(MM_PREFIX "channelMask", &channel_mask)) {
-        metrics_proto.set_channel_mask(channel_mask);
-    }
-    // item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
-    char *encoding = NULL;
-    if (item->getCString(MM_PREFIX "encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
-    }
-    // item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
-    int32_t frame_count = -1;
-    if (item->getInt32(MM_PREFIX "frameCount", &frame_count)) {
-        metrics_proto.set_frame_count(frame_count);
-    }
-    // item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
-    char *outDevice = NULL;
-    if (item->getCString(MM_PREFIX "outDevice", &outDevice)) {
-        metrics_proto.set_output_device(outDevice);
-    }
-    // item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
-    char *inDevice = NULL;
-    if (item->getCString(MM_PREFIX "inDevice", &inDevice)) {
-        metrics_proto.set_input_device(inDevice);
-    }
-    // item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean());
-    double iojitters_ms_mean = -1;
-    if (item->getDouble(MM_PREFIX "ioJitterMs.mean", &iojitters_ms_mean)) {
-        metrics_proto.set_io_jitter_mean_millis(iojitters_ms_mean);
-    }
-    // item->setDouble(MM_PREFIX "ioJitterMs.std", mIoJitterMs.getStdDev());
-    double iojitters_ms_std = -1;
-    if (item->getDouble(MM_PREFIX "ioJitterMs.std", &iojitters_ms_std)) {
-        metrics_proto.set_io_jitter_stddev_millis(iojitters_ms_std);
-    }
-    // item->setDouble(MM_PREFIX "processTimeMs.mean", mProcessTimeMs.getMean());
-    double process_time_ms_mean = -1;
-    if (item->getDouble(MM_PREFIX "processTimeMs.mean", &process_time_ms_mean)) {
-        metrics_proto.set_process_time_mean_millis(process_time_ms_mean);
-    }
-    // item->setDouble(MM_PREFIX "processTimeMs.std", mProcessTimeMs.getStdDev());
-    double process_time_ms_std = -1;
-    if (item->getDouble(MM_PREFIX "processTimeMs.std", &process_time_ms_std)) {
-        metrics_proto.set_process_time_stddev_millis(process_time_ms_std);
-    }
-    // item->setDouble(MM_PREFIX "timestampJitterMs.mean", tsjitter.getMean());
-    double timestamp_jitter_ms_mean = -1;
-    if (item->getDouble(MM_PREFIX "timestampJitterMs.mean", &timestamp_jitter_ms_mean)) {
-        metrics_proto.set_timestamp_jitter_mean_millis(timestamp_jitter_ms_mean);
-    }
-    // item->setDouble(MM_PREFIX "timestampJitterMs.std", tsjitter.getStdDev());
-    double timestamp_jitter_ms_stddev = -1;
-    if (item->getDouble(MM_PREFIX "timestampJitterMs.std", &timestamp_jitter_ms_stddev)) {
-        metrics_proto.set_timestamp_jitter_stddev_millis(timestamp_jitter_ms_stddev);
-    }
-    // item->setDouble(MM_PREFIX "latencyMs.mean", mLatencyMs.getMean());
-    double latency_ms_mean = -1;
-    if (item->getDouble(MM_PREFIX "latencyMs.mean", &latency_ms_mean)) {
-        metrics_proto.set_latency_mean_millis(latency_ms_mean);
-    }
-    // item->setDouble(MM_PREFIX "latencyMs.std", mLatencyMs.getStdDev());
-    double latency_ms_stddev = -1;
-    if (item->getDouble(MM_PREFIX "latencyMs.std", &latency_ms_stddev)) {
-        metrics_proto.set_latency_stddev_millis(latency_ms_stddev);
-    }
-
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize audiothread metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(mytype);
-    free(workhist);
-    free(latencyhist);
-    free(warmuphist);
-    free(type);
-    free(encoding);
-    free(inDevice);
-    free(outDevice);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_audiotrack.cpp b/services/mediaanalytics/statsd_audiotrack.cpp
deleted file mode 100644
index f250ced..0000000
--- a/services/mediaanalytics/statsd_audiotrack.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_audiotrack"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_audiotrack(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::AudioTrackData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-
-    // static constexpr char kAudioTrackStreamType[] = "android.media.audiotrack.streamtype";
-    // optional string streamType;
-    char *streamtype = NULL;
-    if (item->getCString("android.media.audiotrack.streamtype", &streamtype)) {
-        metrics_proto.set_stream_type(streamtype);
-    }
-
-    // static constexpr char kAudioTrackContentType[] = "android.media.audiotrack.type";
-    // optional string contentType;
-    char *contenttype = NULL;
-    if (item->getCString("android.media.audiotrack.type", &contenttype)) {
-        metrics_proto.set_content_type(contenttype);
-    }
-
-    // static constexpr char kAudioTrackUsage[] = "android.media.audiotrack.usage";
-    // optional string trackUsage;
-    char *trackusage = NULL;
-    if (item->getCString("android.media.audiotrack.usage", &trackusage)) {
-        metrics_proto.set_track_usage(trackusage);
-    }
-
-    // static constexpr char kAudioTrackSampleRate[] = "android.media.audiotrack.samplerate";
-    // optional int32 samplerate;
-    int32_t samplerate = -1;
-    if (item->getInt32("android.media.audiotrack.samplerate", &samplerate)) {
-        metrics_proto.set_sample_rate(samplerate);
-    }
-
-    // static constexpr char kAudioTrackChannelMask[] = "android.media.audiotrack.channelmask";
-    // optional int64 channelMask;
-    int64_t channelMask = -1;
-    if (item->getInt64("android.media.audiotrack.channelmask", &channelMask)) {
-        metrics_proto.set_channel_mask(channelMask);
-    }
-
-    // NB: These are not yet exposed as public Java API constants.
-    // static constexpr char kAudioTrackUnderrunFrames[] = "android.media.audiotrack.underrunframes";
-    // optional int32 underrunframes;
-    int32_t underrunframes = -1;
-    if (item->getInt32("android.media.audiotrack.underrunframes", &underrunframes)) {
-        metrics_proto.set_underrun_frames(underrunframes);
-    }
-
-    // static constexpr char kAudioTrackStartupGlitch[] = "android.media.audiotrack.glitch.startup";
-    // optional int32 startupglitch;
-    int32_t startupglitch = -1;
-    if (item->getInt32("android.media.audiotrack.glitch.startup", &startupglitch)) {
-        metrics_proto.set_startup_glitch(startupglitch);
-    }
-
-    // portId (int32)
-    int32_t port_id = -1;
-    if (item->getInt32("android.media.audiotrack.portId", &port_id)) {
-        metrics_proto.set_port_id(port_id);
-    }
-    // encoding (string)
-    char *encoding = NULL;
-    if (item->getCString("android.media.audiotrack.encoding", &encoding)) {
-        metrics_proto.set_encoding(encoding);
-    }
-    // frameCount (int32)
-    int32_t frame_count = -1;
-    if (item->getInt32("android.media.audiotrack.frameCount", &frame_count)) {
-        metrics_proto.set_frame_count(frame_count);
-    }
-    // attributes (string)
-    char *attributes = NULL;
-    if (item->getCString("android.media.audiotrack.attributes", &attributes)) {
-        metrics_proto.set_attributes(attributes);
-    }
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize audiotrack metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(streamtype);
-    free(contenttype);
-    free(trackusage);
-    free(encoding);
-    free(attributes);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_codec.cpp b/services/mediaanalytics/statsd_codec.cpp
deleted file mode 100644
index dc8e4ef..0000000
--- a/services/mediaanalytics/statsd_codec.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_codec"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_codec(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::CodecData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-    // android.media.mediacodec.codec   string
-    char *codec = NULL;
-    if (item->getCString("android.media.mediacodec.codec", &codec)) {
-        metrics_proto.set_codec(codec);
-    }
-    // android.media.mediacodec.mime    string
-    char *mime = NULL;
-    if (item->getCString("android.media.mediacodec.mime", &mime)) {
-        metrics_proto.set_mime(mime);
-    }
-    // android.media.mediacodec.mode    string
-    char *mode = NULL;
-    if ( item->getCString("android.media.mediacodec.mode", &mode)) {
-        metrics_proto.set_mode(mode);
-    }
-    // android.media.mediacodec.encoder int32
-    int32_t encoder = -1;
-    if ( item->getInt32("android.media.mediacodec.encoder", &encoder)) {
-        metrics_proto.set_encoder(encoder);
-    }
-    // android.media.mediacodec.secure  int32
-    int32_t secure = -1;
-    if ( item->getInt32("android.media.mediacodec.secure", &secure)) {
-        metrics_proto.set_secure(secure);
-    }
-    // android.media.mediacodec.width   int32
-    int32_t width = -1;
-    if ( item->getInt32("android.media.mediacodec.width", &width)) {
-        metrics_proto.set_width(width);
-    }
-    // android.media.mediacodec.height  int32
-    int32_t height = -1;
-    if ( item->getInt32("android.media.mediacodec.height", &height)) {
-        metrics_proto.set_height(height);
-    }
-    // android.media.mediacodec.rotation-degrees        int32
-    int32_t rotation = -1;
-    if ( item->getInt32("android.media.mediacodec.rotation-degrees", &rotation)) {
-        metrics_proto.set_rotation(rotation);
-    }
-    // android.media.mediacodec.crypto  int32 (although missing if not needed
-    int32_t crypto = -1;
-    if ( item->getInt32("android.media.mediacodec.crypto", &crypto)) {
-        metrics_proto.set_crypto(crypto);
-    }
-    // android.media.mediacodec.profile int32
-    int32_t profile = -1;
-    if ( item->getInt32("android.media.mediacodec.profile", &profile)) {
-        metrics_proto.set_profile(profile);
-    }
-    // android.media.mediacodec.level   int32
-    int32_t level = -1;
-    if ( item->getInt32("android.media.mediacodec.level", &level)) {
-        metrics_proto.set_level(level);
-    }
-    // android.media.mediacodec.maxwidth        int32
-    int32_t maxwidth = -1;
-    if ( item->getInt32("android.media.mediacodec.maxwidth", &maxwidth)) {
-        metrics_proto.set_max_width(maxwidth);
-    }
-    // android.media.mediacodec.maxheight       int32
-    int32_t maxheight = -1;
-    if ( item->getInt32("android.media.mediacodec.maxheight", &maxheight)) {
-        metrics_proto.set_max_height(maxheight);
-    }
-    // android.media.mediacodec.errcode         int32
-    int32_t errcode = -1;
-    if ( item->getInt32("android.media.mediacodec.errcode", &errcode)) {
-        metrics_proto.set_error_code(errcode);
-    }
-    // android.media.mediacodec.errstate        string
-    char *errstate = NULL;
-    if ( item->getCString("android.media.mediacodec.errstate", &errstate)) {
-        metrics_proto.set_error_state(errstate);
-    }
-    // android.media.mediacodec.latency.max  int64
-    int64_t latency_max = -1;
-    if ( item->getInt64("android.media.mediacodec.latency.max", &latency_max)) {
-        metrics_proto.set_latency_max(latency_max);
-    }
-    // android.media.mediacodec.latency.min  int64
-    int64_t latency_min = -1;
-    if ( item->getInt64("android.media.mediacodec.latency.min", &latency_min)) {
-        metrics_proto.set_latency_min(latency_min);
-    }
-    // android.media.mediacodec.latency.avg  int64
-    int64_t latency_avg = -1;
-    if ( item->getInt64("android.media.mediacodec.latency.avg", &latency_avg)) {
-        metrics_proto.set_latency_avg(latency_avg);
-    }
-    // android.media.mediacodec.latency.n    int64
-    int64_t latency_count = -1;
-    if ( item->getInt64("android.media.mediacodec.latency.n", &latency_count)) {
-        metrics_proto.set_latency_count(latency_count);
-    }
-    // android.media.mediacodec.latency.unknown    int64
-    int64_t latency_unknown = -1;
-    if ( item->getInt64("android.media.mediacodec.latency.unknown", &latency_unknown)) {
-        metrics_proto.set_latency_unknown(latency_unknown);
-    }
-    // android.media.mediacodec.latency.hist    NOT EMITTED
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize codec metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_CODEC_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(codec);
-    free(mime);
-    free(mode);
-    free(errstate);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_drm.cpp b/services/mediaanalytics/statsd_drm.cpp
deleted file mode 100644
index 902483a..0000000
--- a/services/mediaanalytics/statsd_drm.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_drm"
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#include <string.h>
-#include <pwd.h>
-
-#include "MediaAnalyticsService.h"
-#include "iface_statsd.h"
-
-#include <statslog.h>
-
-namespace android {
-
-// mediadrm
-bool statsd_mediadrm(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-    char *vendor = NULL;
-    (void) item->getCString("vendor", &vendor);
-    char *description = NULL;
-    (void) item->getCString("description", &description);
-    char *serialized_metrics = NULL;
-    (void) item->getCString("serialized_metrics", &serialized_metrics);
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized(serialized_metrics ? serialized_metrics : NULL,
-                                                serialized_metrics ? strlen(serialized_metrics)
-                                                                   : 0);
-        android::util::stats_write(android::util::MEDIAMETRICS_MEDIADRM_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   vendor, description,
-                                   bf_serialized);
-    } else {
-        ALOGV("NOT sending: mediadrm private data (len=%zu)",
-              serialized_metrics ? strlen(serialized_metrics) : 0);
-    }
-
-    free(vendor);
-    free(description);
-    free(serialized_metrics);
-    return true;
-}
-
-// widevineCDM
-bool statsd_widevineCDM(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-    char *serialized_metrics = NULL;
-    (void) item->getCString("serialized_metrics", &serialized_metrics);
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized(serialized_metrics ? serialized_metrics : NULL,
-                                                serialized_metrics ? strlen(serialized_metrics)
-                                                                   : 0);
-        android::util::stats_write(android::util::MEDIAMETRICS_DRM_WIDEVINE_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-    } else {
-        ALOGV("NOT sending: widevine private data (len=%zu)",
-              serialized_metrics ? strlen(serialized_metrics) : 0);
-    }
-
-    free(serialized_metrics);
-    return true;
-}
-
-} // namespace android
diff --git a/services/mediaanalytics/statsd_extractor.cpp b/services/mediaanalytics/statsd_extractor.cpp
deleted file mode 100644
index 395c912..0000000
--- a/services/mediaanalytics/statsd_extractor.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_extractor"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_extractor(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::ExtractorData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-
-    // android.media.mediaextractor.fmt         string
-    char *fmt = NULL;
-    if (item->getCString("android.media.mediaextractor.fmt", &fmt)) {
-        metrics_proto.set_format(fmt);
-    }
-    // android.media.mediaextractor.mime        string
-    char *mime = NULL;
-    if (item->getCString("android.media.mediaextractor.mime", &mime)) {
-        metrics_proto.set_mime(mime);
-    }
-    // android.media.mediaextractor.ntrk        int32
-    int32_t ntrk = -1;
-    if (item->getInt32("android.media.mediaextractor.ntrk", &ntrk)) {
-        metrics_proto.set_tracks(ntrk);
-    }
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize extractor metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(fmt);
-    free(mime);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_nuplayer.cpp b/services/mediaanalytics/statsd_nuplayer.cpp
deleted file mode 100644
index 5ec118a..0000000
--- a/services/mediaanalytics/statsd_nuplayer.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_nuplayer"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-/*
- *  handles nuplayer AND nuplayer2
- *  checks for the union of what the two players generate
- */
-bool statsd_nuplayer(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::NuPlayerData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-
-    // differentiate between nuplayer and nuplayer2
-    metrics_proto.set_whichplayer(item->getKey().c_str());
-
-    char *video_mime = NULL;
-    if (item->getCString("android.media.mediaplayer.video.mime", &video_mime)) {
-        metrics_proto.set_video_mime(video_mime);
-    }
-    char *video_codec = NULL;
-    if (item->getCString("android.media.mediaplayer.video.codec", &video_codec)) {
-        metrics_proto.set_video_codec(video_codec);
-    }
-
-    int32_t width = -1;
-    if (item->getInt32("android.media.mediaplayer.width", &width)) {
-        metrics_proto.set_width(width);
-    }
-    int32_t height = -1;
-    if (item->getInt32("android.media.mediaplayer.height", &height)) {
-        metrics_proto.set_height(height);
-    }
-
-    int64_t frames = -1;
-    if (item->getInt64("android.media.mediaplayer.frames", &frames)) {
-        metrics_proto.set_frames(frames);
-    }
-    int64_t frames_dropped = -1;
-    if (item->getInt64("android.media.mediaplayer.dropped", &frames_dropped)) {
-        metrics_proto.set_frames_dropped(frames_dropped);
-    }
-    int64_t frames_dropped_startup = -1;
-    if (item->getInt64("android.media.mediaplayer.startupdropped", &frames_dropped_startup)) {
-        metrics_proto.set_frames_dropped_startup(frames_dropped_startup);
-    }
-    double fps = -1.0;
-    if (item->getDouble("android.media.mediaplayer.fps", &fps)) {
-        metrics_proto.set_framerate(fps);
-    }
-
-    char *audio_mime = NULL;
-    if (item->getCString("android.media.mediaplayer.audio.mime", &audio_mime)) {
-        metrics_proto.set_audio_mime(audio_mime);
-    }
-    char *audio_codec = NULL;
-    if (item->getCString("android.media.mediaplayer.audio.codec", &audio_codec)) {
-        metrics_proto.set_audio_codec(audio_codec);
-    }
-
-    int64_t duration_ms = -1;
-    if (item->getInt64("android.media.mediaplayer.durationMs", &duration_ms)) {
-        metrics_proto.set_duration_millis(duration_ms);
-    }
-    int64_t playing_ms = -1;
-    if (item->getInt64("android.media.mediaplayer.playingMs", &playing_ms)) {
-        metrics_proto.set_playing_millis(playing_ms);
-    }
-
-    int32_t err = -1;
-    if (item->getInt32("android.media.mediaplayer.err", &err)) {
-        metrics_proto.set_error(err);
-    }
-    int32_t error_code = -1;
-    if (item->getInt32("android.media.mediaplayer.errcode", &error_code)) {
-        metrics_proto.set_error_code(error_code);
-    }
-    char *error_state = NULL;
-    if (item->getCString("android.media.mediaplayer.errstate", &error_state)) {
-        metrics_proto.set_error_state(error_state);
-    }
-
-    char *data_source_type = NULL;
-    if (item->getCString("android.media.mediaplayer.dataSource", &data_source_type)) {
-        metrics_proto.set_data_source_type(data_source_type);
-    }
-
-    int64_t rebufferingMs = -1;
-    if (item->getInt64("android.media.mediaplayer.rebufferingMs", &rebufferingMs)) {
-        metrics_proto.set_rebuffering_millis(rebufferingMs);
-    }
-    int32_t rebuffers = -1;
-    if (item->getInt32("android.media.mediaplayer.rebuffers", &rebuffers)) {
-        metrics_proto.set_rebuffers(rebuffers);
-    }
-    int32_t rebufferExit = -1;
-    if (item->getInt32("android.media.mediaplayer.rebufferExit", &rebufferExit)) {
-        metrics_proto.set_rebuffer_at_exit(rebufferExit);
-    }
-
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize nuplayer metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_NUPLAYER_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(video_mime);
-    free(video_codec);
-    free(audio_mime);
-    free(audio_codec);
-    free(error_state);
-    free(data_source_type);
-
-    return true;
-}
-
-};
diff --git a/services/mediaanalytics/statsd_recorder.cpp b/services/mediaanalytics/statsd_recorder.cpp
deleted file mode 100644
index 4d981b4..0000000
--- a/services/mediaanalytics/statsd_recorder.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2019 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 "statsd_recorder"
-#include <utils/Log.h>
-
-#include <dirent.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <statslog.h>
-
-#include "MediaAnalyticsService.h"
-#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
-#include "iface_statsd.h"
-
-namespace android {
-
-bool statsd_recorder(MediaAnalyticsItem *item)
-{
-    if (item == NULL) return false;
-
-    // these go into the statsd wrapper
-    nsecs_t timestamp = item->getTimestamp();
-    std::string pkgName = item->getPkgName();
-    int64_t pkgVersionCode = item->getPkgVersionCode();
-    int64_t mediaApexVersion = 0;
-
-
-    // the rest into our own proto
-    //
-    ::android::stats::mediametrics::RecorderData metrics_proto;
-
-    // flesh out the protobuf we'll hand off with our data
-    //
-
-    // string kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
-    char *audio_mime = NULL;
-    if (item->getCString("android.media.mediarecorder.audio.mime", &audio_mime)) {
-        metrics_proto.set_audio_mime(audio_mime);
-    }
-    // string kRecorderVideoMime = "android.media.mediarecorder.video.mime";
-    char *video_mime = NULL;
-    if (item->getCString("android.media.mediarecorder.video.mime", &video_mime)) {
-        metrics_proto.set_video_mime(video_mime);
-    }
-    // int32 kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
-    int32_t videoProfile = -1;
-    if (item->getInt32("android.media.mediarecorder.video-encoder-profile", &videoProfile)) {
-        metrics_proto.set_video_profile(videoProfile);
-    }
-    // int32 kRecorderVideoLevel = "android.media.mediarecorder.video-encoder-level";
-    int32_t videoLevel = -1;
-    if (item->getInt32("android.media.mediarecorder.video-encoder-level", &videoLevel)) {
-        metrics_proto.set_video_level(videoLevel);
-    }
-    // int32 kRecorderWidth = "android.media.mediarecorder.width";
-    int32_t width = -1;
-    if (item->getInt32("android.media.mediarecorder.width", &width)) {
-        metrics_proto.set_width(width);
-    }
-    // int32 kRecorderHeight = "android.media.mediarecorder.height";
-    int32_t height = -1;
-    if (item->getInt32("android.media.mediarecorder.height", &height)) {
-        metrics_proto.set_height(height);
-    }
-    // int32 kRecorderRotation = "android.media.mediarecorder.rotation";
-    int32_t rotation = -1;                      // default to 0?
-    if (item->getInt32("android.media.mediarecorder.rotation", &rotation)) {
-        metrics_proto.set_rotation(rotation);
-    }
-    // int32 kRecorderFrameRate = "android.media.mediarecorder.frame-rate";
-    int32_t framerate = -1;
-    if (item->getInt32("android.media.mediarecorder.frame-rate", &framerate)) {
-        metrics_proto.set_framerate(framerate);
-    }
-
-    // int32 kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
-    int32_t captureFps = -1;
-    if (item->getInt32("android.media.mediarecorder.capture-fps", &captureFps)) {
-        metrics_proto.set_capture_fps(captureFps);
-    }
-    // double kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
-    double captureFpsEnable = -1;
-    if (item->getDouble("android.media.mediarecorder.capture-fpsenable", &captureFpsEnable)) {
-        metrics_proto.set_capture_fps_enable(captureFpsEnable);
-    }
-
-    // int64 kRecorderDurationMs = "android.media.mediarecorder.durationMs";
-    int64_t durationMs = -1;
-    if (item->getInt64("android.media.mediarecorder.durationMs", &durationMs)) {
-        metrics_proto.set_duration_millis(durationMs);
-    }
-    // int64 kRecorderPaused = "android.media.mediarecorder.pausedMs";
-    int64_t pausedMs = -1;
-    if (item->getInt64("android.media.mediarecorder.pausedMs", &pausedMs)) {
-        metrics_proto.set_paused_millis(pausedMs);
-    }
-    // int32 kRecorderNumPauses = "android.media.mediarecorder.NPauses";
-    int32_t pausedCount = -1;
-    if (item->getInt32("android.media.mediarecorder.NPauses", &pausedCount)) {
-        metrics_proto.set_paused_count(pausedCount);
-    }
-
-    // int32 kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
-    int32_t audioBitrate = -1;
-    if (item->getInt32("android.media.mediarecorder.audio-bitrate", &audioBitrate)) {
-        metrics_proto.set_audio_bitrate(audioBitrate);
-    }
-    // int32 kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
-    int32_t audioChannels = -1;
-    if (item->getInt32("android.media.mediarecorder.audio-channels", &audioChannels)) {
-        metrics_proto.set_audio_channels(audioChannels);
-    }
-    // int32 kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
-    int32_t audioSampleRate = -1;
-    if (item->getInt32("android.media.mediarecorder.audio-samplerate", &audioSampleRate)) {
-        metrics_proto.set_audio_samplerate(audioSampleRate);
-    }
-
-    // int32 kRecorderMovieTimescale = "android.media.mediarecorder.movie-timescale";
-    int32_t movieTimescale = -1;
-    if (item->getInt32("android.media.mediarecorder.movie-timescale", &movieTimescale)) {
-        metrics_proto.set_movie_timescale(movieTimescale);
-    }
-    // int32 kRecorderAudioTimescale = "android.media.mediarecorder.audio-timescale";
-    int32_t audioTimescale = -1;
-    if (item->getInt32("android.media.mediarecorder.audio-timescale", &audioTimescale)) {
-        metrics_proto.set_audio_timescale(audioTimescale);
-    }
-    // int32 kRecorderVideoTimescale = "android.media.mediarecorder.video-timescale";
-    int32_t videoTimescale = -1;
-    if (item->getInt32("android.media.mediarecorder.video-timescale", &videoTimescale)) {
-        metrics_proto.set_video_timescale(videoTimescale);
-    }
-
-    // int32 kRecorderVideoBitrate = "android.media.mediarecorder.video-bitrate";
-    int32_t videoBitRate = -1;
-    if (item->getInt32("android.media.mediarecorder.video-bitrate", &videoBitRate)) {
-        metrics_proto.set_video_bitrate(videoBitRate);
-    }
-    // int32 kRecorderVideoIframeInterval = "android.media.mediarecorder.video-iframe-interval";
-    int32_t iFrameInterval = -1;
-    if (item->getInt32("android.media.mediarecorder.video-iframe-interval", &iFrameInterval)) {
-        metrics_proto.set_iframe_interval(iFrameInterval);
-    }
-
-    std::string serialized;
-    if (!metrics_proto.SerializeToString(&serialized)) {
-        ALOGE("Failed to serialize recorder metrics");
-        return false;
-    }
-
-    if (enabled_statsd) {
-        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-        (void)android::util::stats_write(android::util::MEDIAMETRICS_RECORDER_REPORTED,
-                                   timestamp, pkgName.c_str(), pkgVersionCode,
-                                   mediaApexVersion,
-                                   bf_serialized);
-
-    } else {
-        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
-    }
-
-    // must free the strings that we were given
-    free(audio_mime);
-    free(video_mime);
-
-    return true;
-}
-
-};
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 2f3cad9..c4efbaa 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -1,6 +1,7 @@
 cc_binary {
     name: "mediaswcodec",
     vendor_available: true,
+    min_sdk_version: "29",
 
     srcs: [
         "main_swcodecservice.cpp",
@@ -10,17 +11,11 @@
         "libavservices_minijail",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libmedia_codecserviceregistrant",
     ],
 
     target: {
-        vendor: {
-            exclude_shared_libs: ["libavservices_minijail"],
-            shared_libs: ["libavservices_minijail_vendor"],
-        },
         android: {
             product_variables: {
                 malloc_not_svelte: {
@@ -38,8 +33,6 @@
 
     init_rc: ["mediaswcodec.rc"],
 
-    required: ["mediaswcodec.policy"],
-
     cflags: [
         "-Werror",
         "-Wall",
@@ -58,10 +51,100 @@
             src: "seccomp_policy/mediaswcodec-arm64.policy",
         },
         x86: {
+            src: "seccomp_policy/mediaswcodec-x86.policy",
+        },
+        x86_64: {
+            src: "seccomp_policy/mediaswcodec-x86_64.policy",
+        },
+    },
+    required: [
+        "crash_dump.policy",
+        "code_coverage.policy",
+    ],
+}
+
+// media.codec -- the one that handles vendor & HW codecs
+
+cc_binary {
+    name: "android.hardware.media.omx@1.0-service",
+    relative_install_path: "hw",
+    vendor: true,
+
+    srcs: [
+        "main_codecservice.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "liblog",
+        "libbase",
+        "libavservices_minijail",
+        "libcutils",
+        "libhidlbase",
+        "libstagefright_omx",
+        "libstagefright_xmlparser",
+        "android.hardware.media.omx@1.0",
+        "android.hidl.memory@1.0",
+    ],
+
+    runtime_libs: [
+        "libstagefright_soft_aacdec",
+        "libstagefright_soft_aacenc",
+        "libstagefright_soft_amrdec",
+        "libstagefright_soft_amrnbenc",
+        "libstagefright_soft_amrwbenc",
+        "libstagefright_soft_avcdec",
+        "libstagefright_soft_avcenc",
+        "libstagefright_soft_flacdec",
+        "libstagefright_soft_flacenc",
+        "libstagefright_soft_g711dec",
+        "libstagefright_soft_gsmdec",
+        "libstagefright_soft_hevcdec",
+        "libstagefright_soft_mp3dec",
+        "libstagefright_soft_mpeg2dec",
+        "libstagefright_soft_mpeg4dec",
+        "libstagefright_soft_mpeg4enc",
+        "libstagefright_soft_opusdec",
+        "libstagefright_soft_rawdec",
+        "libstagefright_soft_vorbisdec",
+        "libstagefright_soft_vpxdec",
+        "libstagefright_soft_vpxenc",
+        "libstagefright_softomx_plugin",
+    ],
+
+    // OMX interfaces force this to stay in 32-bit mode;
+    compile_multilib: "32",
+
+    init_rc: ["android.hardware.media.omx@1.0-service.rc"],
+
+    required: [
+        "mediacodec.policy",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-Wno-error=deprecated-declarations",
+    ],
+}
+
+
+prebuilt_etc {
+    name: "mediacodec.policy",
+    sub_dir: "seccomp_policy",
+    arch: {
+        arm: {
+            src: "seccomp_policy/mediacodec-arm.policy",
+        },
+        arm64: {
+            src: "seccomp_policy/mediacodec-arm64.policy",
+        },
+        x86: {
             src: "seccomp_policy/mediacodec-x86.policy",
         },
         x86_64: {
-            src: "seccomp_policy/mediacodec-x86.policy",
+            src: "seccomp_policy/mediacodec-x86_64.policy",
         },
     },
     required: [
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
deleted file mode 100644
index 15bc503..0000000
--- a/services/mediacodec/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-_software_codecs := \
-    libstagefright_soft_aacdec \
-    libstagefright_soft_aacenc \
-    libstagefright_soft_amrdec \
-    libstagefright_soft_amrnbenc \
-    libstagefright_soft_amrwbenc \
-    libstagefright_soft_avcdec \
-    libstagefright_soft_avcenc \
-    libstagefright_soft_flacdec \
-    libstagefright_soft_flacenc \
-    libstagefright_soft_g711dec \
-    libstagefright_soft_gsmdec \
-    libstagefright_soft_hevcdec \
-    libstagefright_soft_mp3dec \
-    libstagefright_soft_mpeg2dec \
-    libstagefright_soft_mpeg4dec \
-    libstagefright_soft_mpeg4enc \
-    libstagefright_soft_opusdec \
-    libstagefright_soft_rawdec \
-    libstagefright_soft_vorbisdec \
-    libstagefright_soft_vpxdec \
-    libstagefright_soft_vpxenc \
-    libstagefright_softomx_plugin \
-
-# service executable
-include $(CLEAR_VARS)
-# seccomp is not required for coverage build.
-ifneq ($(NATIVE_COVERAGE),true)
-LOCAL_REQUIRED_MODULES_arm := mediacodec.policy
-LOCAL_REQUIRED_MODULES_x86 := mediacodec.policy
-endif
-LOCAL_SRC_FILES := main_codecservice.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libutils \
-    liblog \
-    libbase \
-    libavservices_minijail_vendor \
-    libcutils \
-    libhwbinder \
-    libhidlbase \
-    libhidltransport \
-    libstagefright_omx \
-    libstagefright_xmlparser \
-    android.hardware.media.omx@1.0 \
-    android.hidl.memory@1.0
-
-LOCAL_MODULE := android.hardware.media.omx@1.0-service
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_VENDOR_MODULE := true
-LOCAL_32_BIT_ONLY := true
-# Since this is 32-bit-only module, only 32-bit version of the codecs are installed.
-# TODO(b/72343507): eliminate the need for manually adding .vendor suffix. This should be done
-# by the build system.
-LOCAL_REQUIRED_MODULES += \
-$(foreach codec,$(_software_codecs),\
-  $(eval _vendor_suffix := $(if $(BOARD_VNDK_VERSION),.vendor))\
-  $(codec)$(_vendor_suffix)\
-)
-_software_codecs :=
-LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
-
-include $(BUILD_EXECUTABLE)
-
-####################################################################
-
-# service seccomp policy
-ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64 arm arm64))
-include $(CLEAR_VARS)
-LOCAL_MODULE := mediacodec.policy
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
-LOCAL_REQUIRED_MODULES := crash_dump.policy code_coverage.policy
-# mediacodec runs in 32-bit combatibility mode. For 64 bit architectures,
-# use the 32 bit policy
-ifdef TARGET_2ND_ARCH
-  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-    LOCAL_SRC_FILES := seccomp_policy/mediacodec-$(TARGET_2ND_ARCH).policy
-  else
-    LOCAL_SRC_FILES := seccomp_policy/mediacodec-$(TARGET_ARCH).policy
-  endif
-else
-    LOCAL_SRC_FILES := seccomp_policy/mediacodec-$(TARGET_ARCH).policy
-endif
-include $(BUILD_PREBUILT)
-endif
-
-####################################################################
-
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index fa5bc4a..0441cfa 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -9,11 +9,14 @@
         "libmedia_headers",
     ],
 
+    defaults: [
+        "libcodec2-hidl-defaults",
+    ],
     shared_libs: [
-        "android.hardware.media.c2@1.0",
         "libbase",
         "libcodec2_hidl@1.0",
         "libcodec2_vndk",
+        "libhidlbase",
         "libutils",
     ],
 
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 706ebee..184251a 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -17,29 +17,455 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "CodecServiceRegistrant"
 
+#include <android-base/properties.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 
+#include <C2Component.h>
 #include <C2PlatformSupport.h>
 #include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+#include <hidl/HidlSupport.h>
 #include <media/CodecServiceRegistrant.h>
 
-extern "C" void RegisterCodecServices() {
-    using namespace ::android::hardware::media::c2::V1_0;
-    LOG(INFO) << "Creating software Codec2 service...";
-    android::sp<IComponentStore> store =
-        new utils::ComponentStore(
-                android::GetCodec2PlatformComponentStore());
-    if (store == nullptr) {
-        LOG(ERROR) <<
-                "Cannot create software Codec2 service.";
-    } else {
-        if (store->registerAsService("software") != android::OK) {
-            LOG(ERROR) <<
-                    "Cannot register software Codec2 service.";
-        } else {
-            LOG(INFO) <<
-                    "Software Codec2 service created.";
+namespace /* unnamed */ {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using namespace ::android::hardware::media::c2::V1_1;
+using namespace ::android::hardware::media::c2::V1_1::utils;
+
+constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
+
+// Converter from IComponentStore to C2ComponentStore.
+class H2C2ComponentStore : public C2ComponentStore {
+protected:
+    using IComponentStore =
+        ::android::hardware::media::c2::V1_0::IComponentStore;
+    using IConfigurable =
+        ::android::hardware::media::c2::V1_0::IConfigurable;
+    sp<IComponentStore> mStore;
+    sp<IConfigurable> mConfigurable;
+public:
+    explicit H2C2ComponentStore(sp<IComponentStore> const& store)
+          : mStore{store},
+            mConfigurable{[store]() -> sp<IConfigurable>{
+                if (!store) {
+                    return nullptr;
+                }
+                Return<sp<IConfigurable>> transResult =
+                    store->getConfigurable();
+                return transResult.isOk() ?
+                        static_cast<sp<IConfigurable>>(transResult) :
+                        nullptr;
+            }()} {
+        if (!mConfigurable) {
+            LOG(ERROR) << "Preferred store is corrupted.";
         }
     }
+
+    virtual ~H2C2ComponentStore() override = default;
+
+    virtual c2_status_t config_sm(
+            std::vector<C2Param*> const &params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures
+            ) override {
+        Params hidlParams;
+        if (!createParamsBlob(&hidlParams, params)) {
+            LOG(ERROR) << "config -- bad input.";
+            return C2_TRANSACTION_FAILED;
+        }
+        c2_status_t status{};
+        Return<void> transResult = mConfigurable->config(
+                hidlParams,
+                true,
+                [&status, &params, failures](
+                        Status s,
+                        const hidl_vec<SettingResult> f,
+                        const Params& o) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK && status != C2_BAD_INDEX) {
+                        LOG(DEBUG) << "config -- call failed: "
+                                   << status << ".";
+                    }
+                    size_t i = failures->size();
+                    failures->resize(i + f.size());
+                    for (const SettingResult& sf : f) {
+                        if (!objcpy(&(*failures)[i++], sf)) {
+                            LOG(ERROR) << "config -- "
+                                       << "invalid SettingResult returned.";
+                            return;
+                        }
+                    }
+                    if (!updateParamsFromBlob(params, o)) {
+                        LOG(ERROR) << "config -- "
+                                   << "failed to parse returned params.";
+                        status = C2_CORRUPTED;
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "config -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    };
+
+    virtual c2_status_t copyBuffer(
+            std::shared_ptr<C2GraphicBuffer>,
+            std::shared_ptr<C2GraphicBuffer>) override {
+        LOG(ERROR) << "copyBuffer -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createComponent(
+            C2String, std::shared_ptr<C2Component> *const component) override {
+        component->reset();
+        LOG(ERROR) << "createComponent -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createInterface(
+            C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
+        interface->reset();
+        LOG(ERROR) << "createInterface -- not supported.";
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t query_sm(
+            const std::vector<C2Param *> &stackParams,
+            const std::vector<C2Param::Index> &heapParamIndices,
+            std::vector<std::unique_ptr<C2Param>> *const heapParams) const
+            override {
+        hidl_vec<ParamIndex> 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++] = 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> transResult = mConfigurable->query(
+                indices,
+                true,
+                [&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) << "query -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    std::vector<C2Param*> paramPointers;
+                    if (!parseParamsBlob(&paramPointers, p)) {
+                        LOG(ERROR) << "query -- 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(WARNING) << "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;
+                                return;
+                            }
+                            if (stackParams[i]->index() != paramPointer->index()) {
+                                LOG(WARNING) << "query -- param skipped: "
+                                                "index = "
+                                             << stackParams[i]->index() << ".";
+                                stackParams[i++]->invalidate();
+                                continue;
+                            }
+                            if (!stackParams[i++]->updateFrom(*paramPointer)) {
+                                LOG(WARNING) << "query -- param update failed: "
+                                                "index = "
+                                             << paramPointer->index() << ".";
+                            }
+                        } else {
+                            if (!paramPointer) {
+                                LOG(WARNING) << "query -- null heap param.";
+                                ++it;
+                                continue;
+                            }
+                            if (!heapParams) {
+                                LOG(WARNING) << "query -- "
+                                                "unexpected extra stack param.";
+                            } else {
+                                heapParams->emplace_back(
+                                        C2Param::Copy(*paramPointer));
+                            }
+                        }
+                        ++it;
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "query -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+        c2_status_t status;
+        Return<void> transResult = mConfigurable->querySupportedParams(
+                std::numeric_limits<uint32_t>::min(),
+                std::numeric_limits<uint32_t>::max(),
+                [&status, params](
+                        Status s,
+                        const hidl_vec<ParamDescriptor>& p) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "querySupportedParams -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    size_t i = params->size();
+                    params->resize(i + p.size());
+                    for (const ParamDescriptor& sp : p) {
+                        if (!objcpy(&(*params)[i++], sp)) {
+                            LOG(ERROR) << "querySupportedParams -- "
+                                       << "invalid returned ParamDescriptor.";
+                            return;
+                        }
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "querySupportedParams -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual c2_status_t querySupportedValues_sm(
+            std::vector<C2FieldSupportedValuesQuery> &fields) const {
+        hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
+        for (size_t i = 0; i < fields.size(); ++i) {
+            if (!objcpy(&inFields[i], fields[i])) {
+                LOG(ERROR) << "querySupportedValues -- bad input";
+                return C2_TRANSACTION_FAILED;
+            }
+        }
+
+        c2_status_t status;
+        Return<void> transResult = mConfigurable->querySupportedValues(
+                inFields,
+                true,
+                [&status, &inFields, &fields](
+                        Status s,
+                        const hidl_vec<FieldSupportedValuesQueryResult>& r) {
+                    status = static_cast<c2_status_t>(s);
+                    if (status != C2_OK) {
+                        LOG(DEBUG) << "querySupportedValues -- call failed: "
+                                   << status << ".";
+                        return;
+                    }
+                    if (r.size() != fields.size()) {
+                        LOG(ERROR) << "querySupportedValues -- "
+                                      "input and output lists "
+                                      "have different sizes.";
+                        status = C2_CORRUPTED;
+                        return;
+                    }
+                    for (size_t i = 0; i < fields.size(); ++i) {
+                        if (!objcpy(&fields[i], inFields[i], r[i])) {
+                            LOG(ERROR) << "querySupportedValues -- "
+                                          "invalid returned value.";
+                            status = C2_CORRUPTED;
+                            return;
+                        }
+                    }
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "querySupportedValues -- transaction failed.";
+            return C2_TRANSACTION_FAILED;
+        }
+        return status;
+    }
+
+    virtual C2String getName() const {
+        C2String outName;
+        Return<void> transResult = mConfigurable->getName(
+                [&outName](const hidl_string& name) {
+                    outName = name.c_str();
+                });
+        if (!transResult.isOk()) {
+            LOG(ERROR) << "getName -- transaction failed.";
+        }
+        return outName;
+    }
+
+    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
+            override {
+        struct SimpleParamReflector : public C2ParamReflector {
+            virtual std::unique_ptr<C2StructDescriptor> describe(
+                    C2Param::CoreIndex coreIndex) const {
+                hidl_vec<ParamIndex> indices(1);
+                indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
+                std::unique_ptr<C2StructDescriptor> descriptor;
+                Return<void> transResult = mBase->getStructDescriptors(
+                        indices,
+                        [&descriptor](
+                                Status s,
+                                const hidl_vec<StructDescriptor>& sd) {
+                            c2_status_t status = static_cast<c2_status_t>(s);
+                            if (status != C2_OK) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() failed: "
+                                           << status << ".";
+                                descriptor.reset();
+                                return;
+                            }
+                            if (sd.size() != 1) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() "
+                                              "returned vector of size "
+                                           << sd.size() << ". "
+                                              "It should be 1.";
+                                descriptor.reset();
+                                return;
+                            }
+                            if (!objcpy(&descriptor, sd[0])) {
+                                LOG(DEBUG) << "SimpleParamReflector -- "
+                                              "getStructDescriptors() returned "
+                                              "corrupted data.";
+                                descriptor.reset();
+                                return;
+                            }
+                        });
+                return descriptor;
+            }
+
+            explicit SimpleParamReflector(sp<IComponentStore> base)
+                : mBase(base) { }
+
+            sp<IComponentStore> mBase;
+        };
+
+        return std::make_shared<SimpleParamReflector>(mStore);
+    }
+
+    virtual std::vector<std::shared_ptr<const C2Component::Traits>>
+            listComponents() override {
+        LOG(ERROR) << "listComponents -- not supported.";
+        return {};
+    }
+};
+
+bool ionPropertiesDefined() {
+    using namespace ::android::base;
+    std::string heapMask =
+        GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
+    std::string flags =
+        GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
+    std::string align =
+        GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
+    if (heapMask != "undefined" ||
+            flags != "undefined" ||
+            align != "undefined") {
+        LOG(INFO)
+                << "Some system properties for mediaswcodec ION usage are set: "
+                << "heapmask = " << heapMask << ", "
+                << "flags = " << flags << ", "
+                << "align = " << align << ". "
+                << "Preferred Codec2 store is defaulted to \"software\".";
+        return true;
+    }
+    return false;
+}
+
+} // unnamed namespace
+
+extern "C" void RegisterCodecServices() {
+    LOG(INFO) << "Creating software Codec2 service...";
+    std::shared_ptr<C2ComponentStore> store =
+        android::GetCodec2PlatformComponentStore();
+    if (!store) {
+        LOG(ERROR) << "Failed to create Codec2 service.";
+        return;
+    }
+
+    using namespace ::android::hardware::media::c2;
+
+    int platformVersion =
+        android::base::GetIntProperty("ro.build.version.sdk", int32_t(29));
+    // STOPSHIP: Remove code name checking once platform version bumps up to 30.
+    std::string codeName =
+        android::base::GetProperty("ro.build.version.codename", "");
+    if (codeName == "R") {
+        platformVersion = 30;
+    }
+
+    switch (platformVersion) {
+        case 30: {
+            android::sp<V1_1::IComponentStore> storeV1_1 =
+                new V1_1::utils::ComponentStore(store);
+            if (storeV1_1->registerAsService("software") != android::OK) {
+                LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
+                return;
+            }
+            break;
+        }
+        case 29: {
+            android::sp<V1_0::IComponentStore> storeV1_0 =
+                new V1_0::utils::ComponentStore(store);
+            if (storeV1_0->registerAsService("software") != android::OK) {
+                LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
+                return;
+            }
+            break;
+        }
+        default: {
+            LOG(ERROR) << "The platform version " << platformVersion <<
+                          " is not supported.";
+            return;
+        }
+    }
+    if (!ionPropertiesDefined()) {
+        using IComponentStore =
+            ::android::hardware::media::c2::V1_0::IComponentStore;
+        std::string const preferredStoreName = "default";
+        sp<IComponentStore> preferredStore =
+            IComponentStore::getService(preferredStoreName.c_str());
+        if (preferredStore) {
+            ::android::SetPreferredCodec2ComponentStore(
+                    std::make_shared<H2C2ComponentStore>(preferredStore));
+            LOG(INFO) <<
+                    "Preferred Codec2 store is set to \"" <<
+                    preferredStoreName << "\".";
+        } else {
+            LOG(INFO) <<
+                    "Preferred Codec2 store is defaulted to \"software\".";
+        }
+    }
+    LOG(INFO) << "Software Codec2 service created and registered.";
 }
 
diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm.policy b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
index 835f8bb..b4a9ff6 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
@@ -23,7 +23,7 @@
 # on ARM is statically loaded at 0xffff 0000. See
 # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
 # for more details.
-mremap: arg3 == 3
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
 munmap: 1
 mprotect: 1
 madvise: 1
diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm64.policy b/services/mediacodec/seccomp_policy/mediacodec-arm64.policy
new file mode 100644
index 0000000..b4a9ff6
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediacodec-arm64.policy
@@ -0,0 +1,63 @@
+# Organized by frequency of systemcall - in descending order for
+# best performance.
+futex: 1
+ioctl: 1
+write: 1
+prctl: 1
+clock_gettime: 1
+getpriority: 1
+read: 1
+close: 1
+writev: 1
+dup: 1
+ppoll: 1
+mmap2: 1
+getrandom: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
+# parser support for '<' is in this needs to be modified to also prevent
+# |old_address| and |new_address| from touching the exception vector page, which
+# on ARM is statically loaded at 0xffff 0000. See
+# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
+# for more details.
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
+munmap: 1
+mprotect: 1
+madvise: 1
+openat: 1
+sigaltstack: 1
+clone: 1
+setpriority: 1
+getuid32: 1
+fstat64: 1
+fstatfs64: 1
+pread64: 1
+faccessat: 1
+readlinkat: 1
+exit: 1
+rt_sigprocmask: 1
+set_tid_address: 1
+restart_syscall: 1
+exit_group: 1
+rt_sigreturn: 1
+pipe2: 1
+gettimeofday: 1
+sched_yield: 1
+nanosleep: 1
+lseek: 1
+_llseek: 1
+sched_get_priority_max: 1
+sched_get_priority_min: 1
+statfs64: 1
+sched_setscheduler: 1
+fstatat64: 1
+ugetrlimit: 1
+getdents64: 1
+getrandom: 1
+
+@include /system/etc/seccomp_policy/crash_dump.arm.policy
+
+@include /system/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
new file mode 100644
index 0000000..a9d32d6
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86_64.policy
@@ -0,0 +1,72 @@
+# Copyright (C) 2017 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+open: 1
+getuid32: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap2: 1
+mmap: 1
+fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
+madvise: 1
+fstatat64: 1
+newfstatat: 1
+futex: 1
+munmap: 1
+faccessat: 1
+_llseek: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+ugetrlimit: 1
+readlink: 1
+readlinkat: 1
+_llseek: 1
+fstatfs64: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+gettid: 1
+
+@include /system/etc/seccomp_policy/crash_dump.x86.policy
+@include /system/etc/seccomp_policy/code_coverage.x86.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
index 93b4852..9058f10 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
@@ -31,7 +31,7 @@
 # on ARM is statically loaded at 0xffff 0000. See
 # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
 # for more details.
-mremap: arg3 == 3
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
 munmap: 1
 prctl: 1
 getuid32: 1
@@ -85,4 +85,4 @@
 getegid32: 1
 getgroups32: 1
 
-@include /system/etc/seccomp_policy/code_coverage.arm.policy
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
index bb05770..4c51a9c 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
@@ -35,7 +35,7 @@
 # on ARM is statically loaded at 0xffff 0000. See
 # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
 # for more details.
-mremap: arg3 == 3
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
 munmap: 1
 prctl: 1
 writev: 1
@@ -79,4 +79,4 @@
 getegid: 1
 getgroups: 1
 
-@include /system/etc/seccomp_policy/code_coverage.arm64.policy
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.arm64.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
deleted file mode 120000
index ab2592a..0000000
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
+++ /dev/null
@@ -1 +0,0 @@
-mediacodec-x86.policy
\ No newline at end of file
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
new file mode 100644
index 0000000..eb71e28
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86.policy
@@ -0,0 +1,72 @@
+# Copyright (C) 2017 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+open: 1
+getuid32: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap2: 1
+mmap: 1
+fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
+madvise: 1
+fstatat64: 1
+newfstatat: 1
+futex: 1
+munmap: 1
+faccessat: 1
+_llseek: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+ugetrlimit: 1
+readlink: 1
+readlinkat: 1
+_llseek: 1
+fstatfs64: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+gettid: 1
+
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/crash_dump.x86.policy
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.x86.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
deleted file mode 120000
index ab2592a..0000000
--- a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
+++ /dev/null
@@ -1 +0,0 @@
-mediacodec-x86.policy
\ No newline at end of file
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
new file mode 100644
index 0000000..e72d4db
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-x86_64.policy
@@ -0,0 +1,72 @@
+# Copyright (C) 2017 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+open: 1
+getuid32: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap2: 1
+mmap: 1
+fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
+madvise: 1
+fstatat64: 1
+newfstatat: 1
+futex: 1
+munmap: 1
+faccessat: 1
+_llseek: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+ugetrlimit: 1
+readlink: 1
+readlinkat: 1
+_llseek: 1
+fstatfs64: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+gettid: 1
+
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/crash_dump.x86_64.policy
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.x86_64.policy
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
deleted file mode 100644
index 227a29d..0000000
--- a/services/mediadrm/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2014 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    MediaDrmService.cpp \
-    main_mediadrmserver.cpp
-
-LOCAL_SHARED_LIBRARIES:= \
-    libbinder \
-    liblog \
-    libmediadrm \
-    libutils \
-    libhidlbase \
-    libhidlmemory \
-    libhidltransport \
-    android.hardware.drm@1.0 \
-    android.hardware.drm@1.1 \
-    android.hardware.drm@1.2
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-LOCAL_MODULE:= mediadrmserver
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-LOCAL_INIT_RC := mediadrmserver.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
deleted file mode 100644
index 5afd079..0000000
--- a/services/mediadrm/MediaDrmService.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-**
-** Copyright 2008, 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.
-*/
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaDrmService"
-
-#include "MediaDrmService.h"
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-
-#include <mediadrm/CryptoHal.h>
-#include <mediadrm/DrmHal.h>
-
-namespace android {
-
-void MediaDrmService::instantiate() {
-    defaultServiceManager()->addService(
-            String16("media.drm"), new MediaDrmService());
-}
-
-sp<ICrypto> MediaDrmService::makeCrypto() {
-    return new CryptoHal;
-}
-
-sp<IDrm> MediaDrmService::makeDrm() {
-    return new DrmHal;
-}
-
-} // namespace android
diff --git a/services/mediadrm/MediaDrmService.h b/services/mediadrm/MediaDrmService.h
deleted file mode 100644
index 3607201..0000000
--- a/services/mediadrm/MediaDrmService.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-**
-** Copyright 2008, 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 ANDROID_MEDIADRMSERVICE_H
-#define ANDROID_MEDIADRMSERVICE_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-
-#include <media/Metadata.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediadrm/IMediaDrmService.h>
-
-namespace android {
-
-class MediaDrmService : public BnMediaDrmService
-{
-public:
-    static void instantiate();
-
-    // IMediaDrmService interface
-    virtual sp<ICrypto> makeCrypto();
-    virtual sp<IDrm> makeDrm();
-private:
-    MediaDrmService() {}
-    virtual ~MediaDrmService() {}
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIADRMSERVICE_H
diff --git a/services/mediadrm/OWNERS b/services/mediadrm/OWNERS
deleted file mode 100644
index 6d3b533..0000000
--- a/services/mediadrm/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jtinker@google.com
-marcone@google.com
diff --git a/services/mediadrm/main_mediadrmserver.cpp b/services/mediadrm/main_mediadrmserver.cpp
deleted file mode 100644
index b767b8c..0000000
--- a/services/mediadrm/main_mediadrmserver.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-**
-** Copyright 2008, 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_TAG "mediaserver"
-//#define LOG_NDEBUG 0
-
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include "MediaDrmService.h"
-
-using namespace android;
-
-int main()
-{
-    signal(SIGPIPE, SIG_IGN);
-
-    sp<ProcessState> proc(ProcessState::self());
-    sp<IServiceManager> sm = defaultServiceManager();
-    ALOGI("ServiceManager: %p", sm.get());
-    MediaDrmService::instantiate();
-    ProcessState::self()->startThreadPool();
-    IPCThreadState::self()->joinThreadPool();
-}
diff --git a/services/mediadrm/mediadrmserver.rc b/services/mediadrm/mediadrmserver.rc
deleted file mode 100644
index 359c2cf..0000000
--- a/services/mediadrm/mediadrmserver.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service mediadrm /system/bin/mediadrmserver
-    class main
-    user media
-    group mediadrm drmrpc
-    ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 0c701d7..0b25d62 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -8,10 +8,16 @@
     srcs: ["MediaExtractorService.cpp"],
 
     shared_libs: [
+        "libdatasource",
         "libmedia",
         "libstagefright",
+        "libstagefright_foundation",
         "libbinder",
         "libutils",
+        "liblog",
+    ],
+    header_libs: [
+        "libmediametrics_headers",
     ],
 }
 
@@ -23,11 +29,15 @@
     shared_libs: [
         "libmedia",
         "libmediaextractorservice",
+        "libmediautils",
         "libbinder",
         "libutils",
         "liblog",
         "libavservices_minijail",
     ],
+    header_libs: [
+        "bionic_libc_platform_headers",
+    ],
     target: {
         android: {
             product_variables: {
@@ -41,12 +51,12 @@
     },
     init_rc: ["mediaextractor.rc"],
 
-    include_dirs: ["frameworks/av/media/libmedia"],
-
     cflags: [
         "-Wall",
         "-Werror",
     ],
+
+    required: ["mediaextractor.policy"],
 }
 
 prebuilt_etc {
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 36e084b..9992d1c 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -20,8 +20,8 @@
 
 #include <utils/Vector.h>
 
+#include <datasource/DataSourceFactory.h>
 #include <media/DataSource.h>
-#include <media/stagefright/DataSourceFactory.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/RemoteDataSource.h>
@@ -29,48 +29,56 @@
 
 namespace android {
 
-MediaExtractorService::MediaExtractorService()
-        : BnMediaExtractorService() {
+MediaExtractorService::MediaExtractorService() {
     MediaExtractorFactory::LoadExtractors();
 }
 
-sp<IMediaExtractor> MediaExtractorService::makeExtractor(
-        const sp<IDataSource> &remoteSource, const char *mime) {
-    ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime);
+MediaExtractorService::~MediaExtractorService() {
+    ALOGE("should not be in ~MediaExtractorService");
+}
+
+::android::binder::Status MediaExtractorService::makeExtractor(
+        const ::android::sp<::android::IDataSource>& remoteSource,
+        const ::std::unique_ptr< ::std::string> &mime,
+        ::android::sp<::android::IMediaExtractor>* _aidl_return) {
+    ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime.get()->c_str());
 
     sp<DataSource> localSource = CreateDataSourceFromIDataSource(remoteSource);
 
-    sp<IMediaExtractor> extractor = MediaExtractorFactory::CreateFromService(localSource, mime);
+    MediaBuffer::useSharedMemory();
+    sp<IMediaExtractor> extractor = MediaExtractorFactory::CreateFromService(
+            localSource,
+            mime.get() ? mime.get()->c_str() : nullptr);
 
     ALOGV("extractor service created %p (%s)",
             extractor.get(),
             extractor == nullptr ? "" : extractor->name());
 
     if (extractor != nullptr) {
-        registerMediaExtractor(extractor, localSource, mime);
-        return extractor;
+        registerMediaExtractor(extractor, localSource, mime.get() ? mime.get()->c_str() : nullptr);
     }
-    return nullptr;
+    *_aidl_return = extractor;
+    return binder::Status::ok();
 }
 
-sp<IDataSource> MediaExtractorService::makeIDataSource(int fd, int64_t offset, int64_t length)
-{
-    sp<DataSource> source = DataSourceFactory::CreateFromFd(fd, offset, length);
-    return CreateIDataSourceFromDataSource(source);
+::android::binder::Status MediaExtractorService::makeIDataSource(
+        base::unique_fd fd,
+        int64_t offset,
+        int64_t length,
+        ::android::sp<::android::IDataSource>* _aidl_return) {
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(fd.release(), offset, length);
+    *_aidl_return = CreateIDataSourceFromDataSource(source);
+    return binder::Status::ok();
 }
 
-std::unordered_set<std::string> MediaExtractorService::getSupportedTypes() {
-    return MediaExtractorFactory::getSupportedTypes();
+::android::binder::Status MediaExtractorService::getSupportedTypes(
+        ::std::vector<::std::string>* _aidl_return) {
+    *_aidl_return = MediaExtractorFactory::getSupportedTypes();
+    return binder::Status::ok();
 }
 
 status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
     return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
 }
 
-status_t MediaExtractorService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-        uint32_t flags)
-{
-    return BnMediaExtractorService::onTransact(code, data, reply, flags);
-}
-
 }   // namespace android
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index c9cebcf..1b40bf9 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -18,31 +18,33 @@
 #define ANDROID_MEDIA_EXTRACTOR_SERVICE_H
 
 #include <binder/BinderService.h>
-#include <media/IMediaExtractorService.h>
-#include <media/IMediaExtractor.h>
+#include <android/BnMediaExtractorService.h>
+#include <android/IMediaExtractor.h>
 
 namespace android {
 
 class MediaExtractorService : public BinderService<MediaExtractorService>, public BnMediaExtractorService
 {
-    friend class BinderService<MediaExtractorService>;    // for MediaExtractorService()
 public:
     MediaExtractorService();
-    virtual ~MediaExtractorService() { }
-    virtual void onFirstRef() { }
+    virtual ~MediaExtractorService();
 
     static const char*  getServiceName() { return "media.extractor"; }
 
-    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime);
+    virtual ::android::binder::Status makeExtractor(
+            const ::android::sp<::android::IDataSource>& source,
+            const ::std::unique_ptr< ::std::string> &mime,
+            ::android::sp<::android::IMediaExtractor>* _aidl_return);
 
-    virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length);
+    virtual ::android::binder::Status makeIDataSource(
+            base::unique_fd fd,
+            int64_t offset,
+            int64_t length,
+            ::android::sp<::android::IDataSource>* _aidl_return);
 
-    virtual std::unordered_set<std::string> getSupportedTypes();
+    virtual ::android::binder::Status getSupportedTypes(::std::vector<::std::string>* _aidl_return);
 
-    virtual status_t    dump(int fd, const Vector<String16>& args);
-
-    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags);
+    virtual status_t dump(int fd, const Vector<String16>& args);
 
 private:
     Mutex               mLock;
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 3c4125b..f21574f 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -21,16 +21,17 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
-
+#include <mediautils/LimitProcessMemory.h>
 #include <string>
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <utils/misc.h>
 
+#include <bionic/reserved_signals.h>
+
 // from LOCAL_C_INCLUDES
 #include "MediaExtractorService.h"
-#include "MediaUtils.h"
 #include "minijail.h"
 
 using namespace android;
@@ -49,6 +50,10 @@
 
     signal(SIGPIPE, SIG_IGN);
 
+    // Do not assist platform profilers (relevant only on debug builds).
+    // Otherwise, the signal handler can violate the seccomp policy.
+    signal(BIONIC_SIGNAL_PROFILER, SIG_IGN);
+
     //b/62255959: this forces libutis.so to dlopen vendor version of libutils.so
     //before minijail is on. This is dirty but required since some syscalls such
     //as pread64 are used by linker but aren't allowed in the minijail. By
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 118072e..e1f7fe7 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -48,9 +48,17 @@
 # for dynamically loading extractors
 pread64: 1
 
+# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
+# parser support for '<' is in this needs to be modified to also prevent
+# |old_address| and |new_address| from touching the exception vector page, which
+# on ARM is statically loaded at 0xffff 0000. See
+# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
+# for more details.
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
+
 # for FileSource
 readlinkat: 1
 _llseek: 1
 
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-@include /system/etc/seccomp_policy/code_coverage.arm.policy
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.arm.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
index 481e29e..9bbd53b 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
@@ -46,5 +46,5 @@
 # Required by Sanitizers
 sched_yield: 1
 
-@include /system/etc/seccomp_policy/crash_dump.arm64.policy
-@include /system/etc/seccomp_policy/code_coverage.arm64.policy
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.arm64.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.arm64.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index 15fb24e..5b37627 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -59,5 +59,5 @@
 getpid: 1
 gettid: 1
 
-@include /system/etc/seccomp_policy/crash_dump.x86.policy
-@include /system/etc/seccomp_policy/code_coverage.x86.policy
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.x86.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.x86.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 4f2646c..51df1a2 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -53,5 +53,5 @@
 getpid: 1
 gettid: 1
 
-@include /system/etc/seccomp_policy/crash_dump.x86_64.policy
-@include /system/etc/seccomp_policy/code_coverage.x86_64.policy
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.x86_64.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.x86_64.policy
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index bee5d25..74b63d5 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -6,6 +6,10 @@
         "MediaLogService.cpp",
     ],
 
+    header_libs: [
+        "libmedia_headers",
+    ],
+
     shared_libs: [
         "libaudioutils",
         "libbinder",
diff --git a/services/mediametrics/AnalyticsActions.h b/services/mediametrics/AnalyticsActions.h
new file mode 100644
index 0000000..897e567
--- /dev/null
+++ b/services/mediametrics/AnalyticsActions.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <media/MediaMetricsItem.h>
+#include <mutex>
+
+namespace android::mediametrics {
+
+/**
+ * AnalyticsActions consists of a map of pairs <trigger, action> which
+ * are evaluated for a given incoming MediaMetrics item.
+ *
+ * A vector of Actions are returned from getActionsForItem() which
+ * should be executed outside of any locks.
+ *
+ * Mediametrics assumes weak consistency, which is fine as the analytics database
+ * is generally strictly increasing in size (until gc removes values that are
+ * supposedly no longer needed).
+ */
+
+class AnalyticsActions {
+public:
+
+    using Elem = mediametrics::Item::Prop::Elem;
+    /**
+     * Trigger: a pair consisting of
+     * std::string: A wildcard url specifying a property in the item,
+     *              where '*' indicates 0 or more arbitrary characters
+     *              for the item key match.
+     * Elem: A value that needs to match exactly.
+     *
+     * Trigger is used in a map sort;  default less with std::string as primary key.
+     * The wildcard accepts a string with '*' as being 0 or more arbitrary
+     * characters for the item key match.  A wildcard is preferred over general
+     * regexp for simple fast lookup.
+     *
+     * TODO: incorporate a regexp option.
+     */
+    using Trigger = std::pair<std::string, Elem>;
+
+    /**
+     * Function: The function to be executed.
+     */
+    using Function = std::function<
+            void(const std::shared_ptr<const mediametrics::Item>& item)>;
+
+    /**
+     * Action:  An action to execute.  This is a shared pointer to Function.
+     */
+    using Action = std::shared_ptr<Function>;
+
+    /**
+     * Adds a new action.
+     *
+     * \param url references a property in the item with wildcards
+     * \param value references a value (cast to Elem automatically)
+     *              so be careful of the type.  It must be one of
+     *              the types acceptable to Elem.
+     * \param action is a function or lambda to execute if the url matches value
+     *               in the item.
+     */
+    template <typename T, typename U, typename A>
+    void addAction(T&& url, U&& value, A&& action) {
+        std::lock_guard l(mLock);
+        mFilters.emplace(Trigger{ std::forward<T>(url), std::forward<U>(value) },
+                std::forward<A>(action));
+    }
+
+    // TODO: remove an action.
+
+    /**
+     * Get all the actions triggered for a particular item.
+     *
+     * \param item to be analyzed for actions.
+     */
+    std::vector<Action>
+    getActionsForItem(const std::shared_ptr<const mediametrics::Item>& item) {
+        std::vector<Action> actions;
+        std::lock_guard l(mLock);
+
+        for (const auto &[trigger, action] : mFilters) {
+            if (isWildcardMatch(trigger, item) ==
+                    mediametrics::Item::RECURSIVE_WILDCARD_CHECK_MATCH_FOUND) {
+                actions.push_back(action);
+            }
+        }
+
+        // TODO: Optimize for prefix search and wildcarding.
+
+        return actions;
+    }
+
+private:
+
+    static inline bool isMatch(const Trigger& trigger,
+            const std::shared_ptr<const mediametrics::Item>& item) {
+        const auto& [key, elem] = trigger;
+        if (!startsWith(key, item->getKey())) return false;
+        // The trigger key is in format (item key).propName, so + 1 skips '.' delimeter.
+        const char *propName = key.c_str() + item->getKey().size() + 1;
+        return item->hasPropElem(propName, elem);
+    }
+
+    static inline int isWildcardMatch(const Trigger& trigger,
+            const std::shared_ptr<const mediametrics::Item>& item) {
+        const auto& [key, elem] = trigger;
+        return item->recursiveWildcardCheckElem(key.c_str(), elem);
+    }
+
+    mutable std::mutex mLock;
+
+    using FilterType = std::multimap<Trigger, Action>;
+    FilterType mFilters GUARDED_BY(mLock);
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/AnalyticsState.h b/services/mediametrics/AnalyticsState.h
new file mode 100644
index 0000000..09c0b4c
--- /dev/null
+++ b/services/mediametrics/AnalyticsState.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "TimeMachine.h"
+#include "TransactionLog.h"
+
+namespace android::mediametrics {
+
+/**
+ * AnalyticsState consists of a TimeMachine and TransactionLog for a set
+ * of MediaMetrics Items.
+ *
+ * One can add new Items with the submit() method.
+ *
+ * The AnalyticsState may be cleared or duplicated to preserve state after crashes
+ * in services are detected.
+ *
+ * As its members may not be moveable due to mutexes, we use this encapsulation
+ * with a shared pointer in order to save it or duplicate it.
+ */
+class AnalyticsState {
+public:
+    /**
+     * Returns success if AnalyticsState accepts the item.
+     *
+     * A trusted source can create a new key, an untrusted source
+     * can only modify the key if the uid will match that authorized
+     * on the existing key.
+     *
+     * \param item the item to be submitted.
+     * \param isTrusted whether the transaction comes from a trusted source.
+     *        In this case, a trusted source is verified by binder
+     *        UID to be a system service by MediaMetrics service.
+     *        Do not use true if you haven't really checked!
+     *
+     * \return NO_ERROR on success or
+     *         PERMISSION_DENIED if the item cannot be put into the AnalyticsState.
+     */
+    status_t submit(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted) {
+        return mTimeMachine.put(item, isTrusted) ?: mTransactionLog.put(item);
+    }
+
+    /**
+     * Returns the TimeMachine.
+     *
+     * The TimeMachine object is internally locked, so access is safe and defined,
+     * but multiple threaded access may change results after calling.
+     */
+    TimeMachine& timeMachine() { return mTimeMachine; }
+    const TimeMachine& timeMachine() const { return mTimeMachine; }
+
+    /**
+     * Returns the TransactionLog.
+     *
+     * The TransactionLog object is internally locked, so access is safe and defined,
+     * but multiple threaded access may change results after calling.
+     */
+    TransactionLog& transactionLog() { return mTransactionLog; }
+    const TransactionLog& transactionLog() const { return mTransactionLog; }
+
+    /**
+     * Returns a pair consisting of the dump string, and the number of lines in the string.
+     *
+     * The number of lines in the returned pair is used as an optimization
+     * for subsequent line limiting.
+     *
+     * The TimeMachine and the TransactionLog are dumped separately under
+     * different locks, so may not be 100% consistent with the last data
+     * delivered.
+     *
+     * \param lines the maximum number of lines in the string returned.
+     * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+     * \param prefix the desired key prefix to match (nullptr shows all)
+     */
+    std::pair<std::string, int32_t> dump(
+            int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
+        std::stringstream ss;
+        int32_t ll = lines;
+
+        if (ll > 0) {
+            ss << "TransactionLog: gc(" << mTransactionLog.getGarbageCollectionCount() << ")\n";
+            --ll;
+        }
+        if (ll > 0) {
+            auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix);
+            ss << s;
+            ll -= l;
+        }
+        if (ll > 0) {
+            ss << "TimeMachine: gc(" << mTimeMachine.getGarbageCollectionCount() << ")\n";
+            --ll;
+        }
+        if (ll > 0) {
+            auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix);
+            ss << s;
+            ll -= l;
+        }
+        return { ss.str(), lines - ll };
+    }
+
+    /**
+     * Clears the AnalyticsState.
+     */
+    void clear() {
+        mTimeMachine.clear();
+        mTransactionLog.clear();
+    }
+
+private:
+    // Note: TimeMachine and TransactionLog are individually locked.
+    // Access to these objects under multiple threads will be weakly synchronized,
+    // which is acceptable as modifications only increase the history (or with GC,
+    // eliminates very old history).
+
+    TimeMachine    mTimeMachine;
+    TransactionLog mTransactionLog;
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
new file mode 100644
index 0000000..f033d5c
--- /dev/null
+++ b/services/mediametrics/Android.bp
@@ -0,0 +1,164 @@
+// Media Statistics service
+//
+
+tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    "modernize-use-auto",  // debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+]
+
+cc_defaults {
+    name: "mediametrics_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        "-Werror=conditional-uninitialized",
+        "-Wextra",
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: tidy_errors,
+    tidy_checks_as_errors: tidy_errors,
+    tidy_flags: [
+      "-format-style='file'",
+      "--header-filter='frameworks/av/services/mediametrics/'",
+    ],
+}
+
+cc_binary {
+    name: "mediametrics",
+    defaults: [
+        "mediametrics_flags_defaults",
+    ],
+
+    srcs: [
+        "main_mediametrics.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libmediametricsservice",
+        "libmediautils",
+        "libutils",
+    ],
+    header_libs: [
+        "libaudioutils_headers",
+        "libmediametrics_headers",
+    ],
+
+    init_rc: [
+        "mediametrics.rc",
+    ],
+}
+
+cc_library_shared {
+    name: "libmediametricsservice",
+    defaults: [
+        "mediametrics_flags_defaults",
+    ],
+
+    srcs: [
+        "AudioAnalytics.cpp",
+        "AudioPowerUsage.cpp",
+        "AudioTypes.cpp",
+        "cleaner.cpp",
+        "iface_statsd.cpp",
+        "MediaMetricsService.cpp",
+        "statsd_audiopolicy.cpp",
+        "statsd_audiorecord.cpp",
+        "statsd_audiothread.cpp",
+        "statsd_audiotrack.cpp",
+        "statsd_codec.cpp",
+        "statsd_drm.cpp",
+        "statsd_extractor.cpp",
+        "statsd_nuplayer.cpp",
+        "statsd_recorder.cpp",
+        "StringUtils.cpp"
+    ],
+
+    proto: {
+        type: "lite",
+    },
+
+    shared_libs: [
+        "libbase", // android logging
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libmedia_helper",
+        "libmediametrics",
+        "libmediautils",
+        "libmemunreachable",
+        "libprotobuf-cpp-lite",
+        "libstatslog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libplatformprotos",
+    ],
+
+    include_dirs: [
+        "system/media/audio_utils/include",
+    ],
+}
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
new file mode 100644
index 0000000..d78d1e3
--- /dev/null
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -0,0 +1,846 @@
+/*
+ * Copyright (C) 2019 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 "AudioAnalytics"
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "AudioAnalytics.h"
+
+#include <audio_utils/clock.h>    // clock conversions
+#include <cutils/properties.h>
+#include <statslog.h>             // statsd
+
+#include "AudioTypes.h"           // string to int conversions
+#include "MediaMetricsService.h"  // package info
+#include "StringUtils.h"
+
+#define PROP_AUDIO_ANALYTICS_CLOUD_ENABLED "persist.audio.analytics.cloud.enabled"
+
+namespace android::mediametrics {
+
+// Enable for testing of delivery to statsd. Caution if this is enabled, all protos MUST exist.
+#define STATSD_ENABLE
+
+#ifdef STATSD_ENABLE
+#define CONDITION(INT_VALUE) (INT_VALUE)  // allow value
+#else
+#define CONDITION(INT_VALUE) (int(0))     // mask value since the proto may not be defined yet.
+#endif
+
+// Maximum length of a device name.
+// static constexpr size_t STATSD_DEVICE_NAME_MAX_LENGTH = 32; // unused since we suppress
+
+// Transmit Enums to statsd in integer or strings  (this must match the atoms.proto)
+static constexpr bool STATSD_USE_INT_FOR_ENUM = false;
+
+// derive types based on integer or strings.
+using short_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int32_t, std::string>;
+using long_enum_type_t = std::conditional_t<STATSD_USE_INT_FOR_ENUM, int64_t, std::string>;
+
+// Convert std::string to char *
+template <typename T>
+auto ENUM_EXTRACT(const T& x) {
+    if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
+        return x.c_str();
+    } else {
+        return x;
+    }
+}
+
+static constexpr const auto LOG_LEVEL = android::base::VERBOSE;
+
+static constexpr int PREVIOUS_STATE_EXPIRE_SEC = 60 * 60; // 1 hour.
+
+static constexpr const char * SUPPRESSED = "SUPPRESSED";
+
+/*
+ * For logging purposes, we list all of the MediaMetrics atom fields,
+ * which can then be associated with consecutive arguments to the statsd write.
+ */
+
+static constexpr const char * const AudioRecordDeviceUsageFields[] = {
+    "mediametrics_audiorecorddeviceusage_reported", // proto number
+    "devices",
+    "device_names",
+    "device_time_nanos",
+    "encoding",
+    "frame_count",
+    "interval_count",
+    "sample_rate",
+    "flags",
+    "package_name",
+    "selected_device_id",
+    "caller",
+    "source",
+};
+
+static constexpr const char * const AudioThreadDeviceUsageFields[] = {
+    "mediametrics_audiothreaddeviceusage_reported",
+    "devices",
+    "device_names",
+    "device_time_nanos",
+    "encoding",
+    "frame_count",
+    "interval_count",
+    "sample_rate",
+    "flags",
+    "xruns",
+    "type",
+};
+
+static constexpr const char * const AudioTrackDeviceUsageFields[] = {
+    "mediametrics_audiotrackdeviceusage_reported",
+    "devices",
+    "device_names",
+    "device_time_nanos",
+    "encoding",
+    "frame_count",
+    "interval_count",
+    "sample_rate",
+    "flags",
+    "xruns",
+    "package_name",
+    "device_latency_millis",
+    "device_startup_millis",
+    "device_volume",
+    "selected_device_id",
+    "stream_type",
+    "usage",
+    "content_type",
+    "caller",
+    "traits",
+};
+
+static constexpr const char * const AudioDeviceConnectionFields[] = {
+    "mediametrics_audiodeviceconnection_reported",
+    "input_devices",
+    "output_devices",
+    "device_names",
+    "result",
+    "time_to_connect_millis",
+    "connection_count",
+};
+
+/**
+ * sendToStatsd is a helper method that sends the arguments to statsd
+ * and returns a pair { result, summary_string }.
+ */
+template <size_t N, typename ...Types>
+std::pair<int, std::string> sendToStatsd(const char * const (& fields)[N], Types ... args)
+{
+    int result = 0;
+    std::stringstream ss;
+
+#ifdef STATSD_ENABLE
+    result = android::util::stats_write(args...);
+    ss << "result:" << result;
+#endif
+    ss << " { ";
+    stringutils::fieldPrint(ss, fields, args...);
+    ss << "}";
+    return { result, ss.str() };
+}
+
+AudioAnalytics::AudioAnalytics()
+    : mDeliverStatistics(property_get_bool(PROP_AUDIO_ANALYTICS_CLOUD_ENABLED, true))
+{
+    SetMinimumLogSeverity(android::base::DEBUG); // for LOG().
+    ALOGD("%s", __func__);
+
+    // Add action to save AnalyticsState if audioserver is restarted.
+    // This triggers on an item of "audio.flinger"
+    // with a property "event" set to "AudioFlinger" (the constructor).
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                ALOGW("(key=%s) Audioflinger constructor event detected", item->getKey().c_str());
+                mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
+                        *mAnalyticsState.get()));
+                // Note: get returns shared_ptr temp, whose lifetime is extended
+                // to end of full expression.
+                mAnalyticsState->clear();  // TODO: filter the analytics state.
+                // Perhaps report this.
+
+                // Set up a timer to expire the previous audio state to save space.
+                // Use the transaction log size as a cookie to see if it is the
+                // same as before.  A benign race is possible where a state is cleared early.
+                const size_t size = mPreviousAnalyticsState->transactionLog().size();
+                mTimedAction.postIn(
+                        std::chrono::seconds(PREVIOUS_STATE_EXPIRE_SEC), [this, size](){
+                    if (mPreviousAnalyticsState->transactionLog().size() == size) {
+                        ALOGD("expiring previous audio state after %d seconds.",
+                                PREVIOUS_STATE_EXPIRE_SEC);
+                        mPreviousAnalyticsState->clear();  // removes data from the state.
+                    }
+                });
+            }));
+
+    // Handle device use record statistics
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::RECORD);
+            }));
+
+    // Handle device use thread statistics
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::THREAD);
+            }));
+
+    // Handle device use track statistics
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceUse.endAudioIntervalGroup(item, DeviceUse::TRACK);
+            }));
+
+
+    // Handle device connection statistics
+
+    // We track connections (not disconnections) for the time to connect.
+    // TODO: consider BT requests in their A2dp service
+    // AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
+    // AudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
+    // AudioDeviceBroker.postA2dpActiveDeviceChange
+    mActions.addAction(
+        "audio.device.a2dp.state",
+        "connected",
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceConnection.a2dpConnected(item);
+            }));
+    // If audio is active, we expect to see a createAudioPatch after the device is connected.
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string("createAudioPatch"),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceConnection.createPatch(item);
+            }));
+
+    // Called from BT service
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE
+        "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent"
+        "." AMEDIAMETRICS_PROP_STATE,
+        "connected",
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mDeviceConnection.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(item);
+            }));
+
+    // Handle power usage
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mAudioPowerUsage.checkTrackRecord(item, true /* isTrack */);
+            }));
+
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mAudioPowerUsage.checkTrackRecord(item, false /* isTrack */);
+            }));
+
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                // ALOGD("(key=%s) Audioflinger setMode", item->getKey().c_str());
+                mAudioPowerUsage.checkMode(item);
+            }));
+
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_AUDIO_FLINGER "." AMEDIAMETRICS_PROP_EVENT,
+        std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                // ALOGD("(key=%s) Audioflinger setVoiceVolume", item->getKey().c_str());
+                mAudioPowerUsage.checkVoiceVolume(item);
+            }));
+
+    mActions.addAction(
+        AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*." AMEDIAMETRICS_PROP_EVENT,
+        std::string("createAudioPatch"),
+        std::make_shared<AnalyticsActions::Function>(
+            [this](const std::shared_ptr<const android::mediametrics::Item> &item){
+                mAudioPowerUsage.checkCreatePatch(item);
+            }));
+}
+
+AudioAnalytics::~AudioAnalytics()
+{
+    ALOGD("%s", __func__);
+    mTimedAction.quit(); // ensure no deferred access during destructor.
+}
+
+status_t AudioAnalytics::submit(
+        const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
+{
+    if (!startsWith(item->getKey(), AMEDIAMETRICS_KEY_PREFIX_AUDIO)) return BAD_VALUE;
+    status_t status = mAnalyticsState->submit(item, isTrusted);
+    if (status != NO_ERROR) return status;  // may not be permitted.
+
+    // Only if the item was successfully submitted (permission)
+    // do we check triggered actions.
+    checkActions(item);
+    return NO_ERROR;
+}
+
+std::pair<std::string, int32_t> AudioAnalytics::dump(
+        int32_t lines, int64_t sinceNs, const char *prefix) const
+{
+    std::stringstream ss;
+    int32_t ll = lines;
+
+    if (ll > 0) {
+        auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
+        ss << s;
+        ll -= l;
+    }
+    if (ll > 0) {
+        ss << "Prior audioserver state:\n";
+        --ll;
+    }
+    if (ll > 0) {
+        auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
+        ss << s;
+        ll -= l;
+    }
+
+    if (ll > 0) {
+        // Print the statsd atoms we sent out.
+        const std::string statsd = mStatsdLog.dumpToString("  " /* prefix */, ll - 1);
+        const size_t n = std::count(statsd.begin(), statsd.end(), '\n') + 1; // we control this.
+        if ((size_t)ll >= n) {
+            if (n == 1) {
+                ss << "Statsd atoms: empty or truncated\n";
+            } else {
+                ss << "Statsd atoms:\n" << statsd;
+            }
+            ll -= n;
+        }
+    }
+
+    if (ll > 0 && prefix == nullptr) {
+        auto [s, l] = mAudioPowerUsage.dump(ll);
+        ss << s;
+        ll -= l;
+    }
+
+    return { ss.str(), lines - ll };
+}
+
+void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    auto actions = mActions.getActionsForItem(item); // internally locked.
+    // Execute actions with no lock held.
+    for (const auto& action : actions) {
+        (*action)(item);
+    }
+}
+
+// HELPER METHODS
+
+std::string AudioAnalytics::getThreadFromTrack(const std::string& track) const
+{
+    int32_t threadId_int32{};
+    if (mAnalyticsState->timeMachine().get(
+            track, AMEDIAMETRICS_PROP_THREADID, &threadId_int32) != NO_ERROR) {
+        return {};
+    }
+    return std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(threadId_int32);
+}
+
+// DeviceUse helper class.
+void AudioAnalytics::DeviceUse::endAudioIntervalGroup(
+       const std::shared_ptr<const android::mediametrics::Item> &item, ItemType itemType) const {
+    const std::string& key = item->getKey();
+    const std::string id = key.substr(
+            (itemType == THREAD ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD)
+            : itemType == TRACK ? sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK)
+            : sizeof(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD))
+             - 1);
+    // deliver statistics
+    int64_t deviceTimeNs = 0;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs);
+    std::string encoding;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_ENCODING, &encoding);
+    int32_t frameCount = 0;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
+    std::string inputDevicePairs;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
+    int32_t intervalCount = 0;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
+    std::string outputDevicePairs;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
+    int32_t sampleRate = 0;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
+    std::string flags;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_FLAGS, &flags);
+
+    // We may have several devices.
+    // Accumulate the bit flags for input and output devices.
+    std::stringstream oss;
+    long_enum_type_t outputDeviceBits{};
+    {   // compute outputDevices
+        const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
+        for (const auto& [device, addr] : devaddrvec) {
+            if (oss.tellp() > 0) oss << "|";  // delimit devices with '|'.
+            oss << device;
+            outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
+        }
+    }
+    const std::string outputDevices = oss.str();
+
+    std::stringstream iss;
+    long_enum_type_t inputDeviceBits{};
+    {   // compute inputDevices
+        const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
+        for (const auto& [device, addr] : devaddrvec) {
+            if (iss.tellp() > 0) iss << "|";  // delimit devices with '|'.
+            iss << device;
+            inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
+        }
+    }
+    const std::string inputDevices = iss.str();
+
+    // Get connected device name if from bluetooth.
+    bool isBluetooth = false;
+
+    std::string inputDeviceNames;  // not filled currently.
+    std::string outputDeviceNames;
+    if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
+        isBluetooth = true;
+        outputDeviceNames = SUPPRESSED;
+#if 0   // TODO(b/161554630) sanitize name
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
+        // Remove | if present
+        stringutils::replace(outputDeviceNames, "|", '?');
+        if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
+            outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
+        }
+#endif
+    }
+
+    switch (itemType) {
+    case RECORD: {
+        std::string callerName;
+        const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
+
+        std::string packageName;
+        int64_t versionCode = 0;
+        int32_t uid = -1;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
+        if (uid != -1) {
+            std::tie(packageName, versionCode) =
+                    MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
+        }
+
+        int32_t selectedDeviceId = 0;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
+        std::string source;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_SOURCE, &source);
+
+        const auto callerNameForStats =
+                types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
+        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
+        const auto flagsForStats = types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags);
+        const auto sourceForStats = types::lookup<types::SOURCE_TYPE, short_enum_type_t>(source);
+
+        LOG(LOG_LEVEL) << "key:" << key
+              << " id:" << id
+              << " inputDevices:" << inputDevices << "(" << inputDeviceBits
+              << ") inputDeviceNames:" << inputDeviceNames
+              << " deviceTimeNs:" << deviceTimeNs
+              << " encoding:" << encoding << "(" << encodingForStats
+              << ") frameCount:" << frameCount
+              << " intervalCount:" << intervalCount
+              << " sampleRate:" << sampleRate
+              << " flags:" << flags << "(" << flagsForStats
+              << ") packageName:" << packageName
+              << " selectedDeviceId:" << selectedDeviceId
+              << " callerName:" << callerName << "(" << callerNameForStats
+              << ") source:" << source << "(" << sourceForStats << ")";
+        if (clientCalled  // only log if client app called AudioRecord.
+                && mAudioAnalytics.mDeliverStatistics) {
+            const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
+                    CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
+                    , ENUM_EXTRACT(inputDeviceBits)
+                    , inputDeviceNames.c_str()
+                    , deviceTimeNs
+                    , ENUM_EXTRACT(encodingForStats)
+                    , frameCount
+                    , intervalCount
+                    , sampleRate
+                    , ENUM_EXTRACT(flagsForStats)
+
+                    , packageName.c_str()
+                    , selectedDeviceId
+                    , ENUM_EXTRACT(callerNameForStats)
+                    , ENUM_EXTRACT(sourceForStats)
+                    );
+            ALOGV("%s: statsd %s", __func__, str.c_str());
+            mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+        }
+    } break;
+    case THREAD: {
+        std::string type;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_TYPE, &type);
+        int32_t underrun = 0; // zero for record types
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
+
+        const bool isInput = types::isInputThreadType(type);
+        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
+        const auto flagsForStats =
+                (isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
+                        : types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
+        const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
+
+        LOG(LOG_LEVEL) << "key:" << key
+              << " id:" << id
+              << " inputDevices:" << inputDevices << "(" << inputDeviceBits
+              << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
+              << ") inputDeviceNames:" << inputDeviceNames
+              << " outputDeviceNames:" << outputDeviceNames
+              << " deviceTimeNs:" << deviceTimeNs
+              << " encoding:" << encoding << "(" << encodingForStats
+              << ") frameCount:" << frameCount
+              << " intervalCount:" << intervalCount
+              << " sampleRate:" << sampleRate
+              << " underrun:" << underrun
+              << " flags:" << flags << "(" << flagsForStats
+              << ") type:" << type << "(" << typeForStats
+              << ")";
+        if (mAudioAnalytics.mDeliverStatistics) {
+            const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
+                CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
+                , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
+                , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
+                , deviceTimeNs
+                , ENUM_EXTRACT(encodingForStats)
+                , frameCount
+                , intervalCount
+                , sampleRate
+                , ENUM_EXTRACT(flagsForStats)
+                , underrun
+                , ENUM_EXTRACT(typeForStats)
+            );
+            ALOGV("%s: statsd %s", __func__, str.c_str());
+            mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+        }
+    } break;
+    case TRACK: {
+        std::string callerName;
+        const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
+
+        std::string contentType;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_CONTENTTYPE, &contentType);
+        double deviceLatencyMs = 0.;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_DEVICELATENCYMS, &deviceLatencyMs);
+        double deviceStartupMs = 0.;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_DEVICESTARTUPMS, &deviceStartupMs);
+        double deviceVolume = 0.;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume);
+        std::string packageName;
+        int64_t versionCode = 0;
+        int32_t uid = -1;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_ALLOWUID, &uid);
+        if (uid != -1) {
+            std::tie(packageName, versionCode) =
+                    MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid);
+        }
+        double playbackPitch = 0.;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_PLAYBACK_PITCH, &playbackPitch);
+        double playbackSpeed = 0.;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_PLAYBACK_SPEED, &playbackSpeed);
+        int32_t selectedDeviceId = 0;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_SELECTEDDEVICEID, &selectedDeviceId);
+        std::string streamType;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_STREAMTYPE, &streamType);
+        std::string traits;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_TRAITS, &traits);
+        int32_t underrun = 0;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
+        std::string usage;
+        mAudioAnalytics.mAnalyticsState->timeMachine().get(
+                key, AMEDIAMETRICS_PROP_USAGE, &usage);
+
+        const auto callerNameForStats =
+                types::lookup<types::CALLER_NAME, short_enum_type_t>(callerName);
+        const auto contentTypeForStats =
+                types::lookup<types::CONTENT_TYPE, short_enum_type_t>(contentType);
+        const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
+        const auto flagsForStats = types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags);
+        const auto streamTypeForStats =
+                types::lookup<types::STREAM_TYPE, short_enum_type_t>(streamType);
+        const auto traitsForStats =
+                 types::lookup<types::TRACK_TRAITS, short_enum_type_t>(traits);
+        const auto usageForStats = types::lookup<types::USAGE, short_enum_type_t>(usage);
+
+        LOG(LOG_LEVEL) << "key:" << key
+              << " id:" << id
+              << " outputDevices:" << outputDevices << "(" << outputDeviceBits
+              << ") outputDeviceNames:" << outputDeviceNames
+              << " deviceTimeNs:" << deviceTimeNs
+              << " encoding:" << encoding << "(" << encodingForStats
+              << ") frameCount:" << frameCount
+              << " intervalCount:" << intervalCount
+              << " sampleRate:" << sampleRate
+              << " underrun:" << underrun
+              << " flags:" << flags << "(" << flagsForStats
+              << ") callerName:" << callerName << "(" << callerNameForStats
+              << ") contentType:" << contentType << "(" << contentTypeForStats
+              << ") deviceLatencyMs:" << deviceLatencyMs
+              << " deviceStartupMs:" << deviceStartupMs
+              << " deviceVolume:" << deviceVolume
+              << " packageName:" << packageName
+              << " playbackPitch:" << playbackPitch
+              << " playbackSpeed:" << playbackSpeed
+              << " selectedDeviceId:" << selectedDeviceId
+              << " streamType:" << streamType << "(" << streamTypeForStats
+              << ") traits:" << traits << "(" << traitsForStats
+              << ") usage:" << usage << "(" << usageForStats
+              << ")";
+        if (clientCalled // only log if client app called AudioTracks
+                && mAudioAnalytics.mDeliverStatistics) {
+            const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
+                    CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
+                    , ENUM_EXTRACT(outputDeviceBits)
+                    , outputDeviceNames.c_str()
+                    , deviceTimeNs
+                    , ENUM_EXTRACT(encodingForStats)
+                    , frameCount
+                    , intervalCount
+                    , sampleRate
+                    , ENUM_EXTRACT(flagsForStats)
+                    , underrun
+                    , packageName.c_str()
+                    , (float)deviceLatencyMs
+                    , (float)deviceStartupMs
+                    , (float)deviceVolume
+                    , selectedDeviceId
+                    , ENUM_EXTRACT(streamTypeForStats)
+                    , ENUM_EXTRACT(usageForStats)
+                    , ENUM_EXTRACT(contentTypeForStats)
+                    , ENUM_EXTRACT(callerNameForStats)
+                    , ENUM_EXTRACT(traitsForStats)
+                    );
+            ALOGV("%s: statsd %s", __func__, str.c_str());
+            mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+        }
+        } break;
+    }
+
+    // Report this as needed.
+    if (isBluetooth) {
+        // report this for Bluetooth
+    }
+}
+
+// DeviceConnection helper class.
+void AudioAnalytics::DeviceConnection::a2dpConnected(
+       const std::shared_ptr<const android::mediametrics::Item> &item) {
+    const std::string& key = item->getKey();
+    const int64_t atNs = item->getTimestamp();
+    {
+        std::lock_guard l(mLock);
+        mA2dpConnectionServiceNs = atNs;
+        ++mA2dpConnectionServices;
+
+        if (mA2dpConnectionRequestNs == 0) {
+            mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
+        }
+        // This sets the time we were connected.  Now we look for the delta in the future.
+    }
+    std::string name;
+    item->get(AMEDIAMETRICS_PROP_NAME, &name);
+    ALOGD("(key=%s) a2dp connected device:%s atNs:%lld",
+            key.c_str(), name.c_str(), (long long)atNs);
+}
+
+void AudioAnalytics::DeviceConnection::createPatch(
+       const std::shared_ptr<const android::mediametrics::Item> &item) {
+    std::lock_guard l(mLock);
+    if (mA2dpConnectionServiceNs == 0) return; // patch unrelated to us.
+    const std::string& key = item->getKey();
+    std::string outputDevices;
+    item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices);
+    if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH_A2DP") != std::string::npos) {
+        // TODO compare address
+        int64_t timeDiffNs = item->getTimestamp();
+        if (mA2dpConnectionRequestNs == 0) {
+            ALOGD("%s: A2DP create patch didn't see a connection request", __func__);
+            timeDiffNs -= mA2dpConnectionServiceNs;
+        } else {
+            timeDiffNs -= mA2dpConnectionRequestNs;
+        }
+
+        mA2dpConnectionRequestNs = 0;
+        mA2dpConnectionServiceNs = 0;
+        ++mA2dpConnectionSuccesses;
+
+        const auto connectionTimeMs = float(timeDiffNs * 1e-6);
+
+        const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
+                "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
+
+        LOG(LOG_LEVEL) << "key:" << key
+                << " A2DP SUCCESS"
+                << " outputDevices:" << outputDeviceBits
+                << " deviceName:" << mA2dpDeviceName
+                << " connectionTimeMs:" <<  connectionTimeMs;
+        if (mAudioAnalytics.mDeliverStatistics) {
+            const long_enum_type_t inputDeviceBits{};
+
+            const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
+                    CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                    , ENUM_EXTRACT(inputDeviceBits)
+                    , ENUM_EXTRACT(outputDeviceBits)
+                    , mA2dpDeviceName.c_str()
+                    , types::DEVICE_CONNECTION_RESULT_SUCCESS
+                    , connectionTimeMs
+                    , /* connection_count */ 1
+                    );
+            ALOGV("%s: statsd %s", __func__, str.c_str());
+            mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+        }
+    }
+}
+
+// Called through AudioManager when the BT service wants to enable
+void AudioAnalytics::DeviceConnection::postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+        const std::shared_ptr<const android::mediametrics::Item> &item) {
+    const int64_t atNs = item->getTimestamp();
+    const std::string& key = item->getKey();
+    std::string state;
+    item->get(AMEDIAMETRICS_PROP_STATE, &state);
+    if (state != "connected") return;
+
+    std::string name;
+    item->get(AMEDIAMETRICS_PROP_NAME, &name);
+    {
+        std::lock_guard l(mLock);
+        mA2dpConnectionRequestNs = atNs;
+        ++mA2dpConnectionRequests;
+        mA2dpDeviceName = SUPPRESSED; // TODO(b/161554630) sanitize name
+    }
+    ALOGD("(key=%s) a2dp connection name:%s request atNs:%lld",
+            key.c_str(), name.c_str(), (long long)atNs);
+    // TODO: attempt to cancel a timed event, rather than let it expire.
+    mAudioAnalytics.mTimedAction.postIn(std::chrono::seconds(5), [this](){ expire(); });
+}
+
+void AudioAnalytics::DeviceConnection::expire() {
+    std::lock_guard l(mLock);
+    if (mA2dpConnectionRequestNs == 0) return; // ignore (this was an internal connection).
+
+    const long_enum_type_t inputDeviceBits{};
+    const auto outputDeviceBits = types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(
+            "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP");
+
+    if (mA2dpConnectionServiceNs == 0) {
+        ++mA2dpConnectionJavaServiceCancels;  // service did not connect to A2DP
+
+        LOG(LOG_LEVEL) << "A2DP CANCEL"
+                << " outputDevices:" << outputDeviceBits
+                << " deviceName:" << mA2dpDeviceName;
+        if (mAudioAnalytics.mDeliverStatistics) {
+            const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
+                    CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                    , ENUM_EXTRACT(inputDeviceBits)
+                    , ENUM_EXTRACT(outputDeviceBits)
+                    , mA2dpDeviceName.c_str()
+                    , types::DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL
+                    , /* connection_time_ms */ 0.f
+                    , /* connection_count */ 1
+                    );
+            ALOGV("%s: statsd %s", __func__, str.c_str());
+            mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+        }
+        return;
+    }
+
+    // AudioFlinger didn't play - an expiration may occur because there is no audio playing.
+    // Should we check elsewhere?
+    // TODO: disambiguate this case.
+    mA2dpConnectionRequestNs = 0;
+    mA2dpConnectionServiceNs = 0;
+    ++mA2dpConnectionUnknowns;  // connection result unknown
+
+    LOG(LOG_LEVEL) << "A2DP UNKNOWN"
+            << " outputDevices:" << outputDeviceBits
+            << " deviceName:" << mA2dpDeviceName;
+    if (mAudioAnalytics.mDeliverStatistics) {
+        const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
+                CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                , ENUM_EXTRACT(inputDeviceBits)
+                , ENUM_EXTRACT(outputDeviceBits)
+                , mA2dpDeviceName.c_str()
+                , types::DEVICE_CONNECTION_RESULT_UNKNOWN
+                , /* connection_time_ms */ 0.f
+                , /* connection_count */ 1
+                );
+        ALOGV("%s: statsd %s", __func__, str.c_str());
+        mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+    }
+}
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/AudioAnalytics.h
new file mode 100644
index 0000000..df097b1
--- /dev/null
+++ b/services/mediametrics/AudioAnalytics.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_utils/SimpleLog.h>
+#include "AnalyticsActions.h"
+#include "AnalyticsState.h"
+#include "AudioPowerUsage.h"
+#include "TimedAction.h"
+#include "Wrap.h"
+
+namespace android::mediametrics {
+
+class AudioAnalytics
+{
+    // AudioAnalytics action / state helper classes
+    friend AudioPowerUsage;
+
+public:
+    AudioAnalytics();
+    ~AudioAnalytics();
+
+    /**
+     * Returns success if AudioAnalytics recognizes item.
+     *
+     * AudioAnalytics requires the item key to start with "audio.".
+     *
+     * A trusted source can create a new key, an untrusted source
+     * can only modify the key if the uid will match that authorized
+     * on the existing key.
+     *
+     * \param item the item to be submitted.
+     * \param isTrusted whether the transaction comes from a trusted source.
+     *        In this case, a trusted source is verified by binder
+     *        UID to be a system service by MediaMetrics service.
+     *        Do not use true if you haven't really checked!
+     *
+     * \return NO_ERROR on success,
+     *         PERMISSION_DENIED if the item cannot be put into the AnalyticsState,
+     *         BAD_VALUE if the item key does not start with "audio.".
+     */
+    status_t submit(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted);
+
+    /**
+     * Returns a pair consisting of the dump string, and the number of lines in the string.
+     *
+     * The number of lines in the returned pair is used as an optimization
+     * for subsequent line limiting.
+     *
+     * The TimeMachine and the TransactionLog are dumped separately under
+     * different locks, so may not be 100% consistent with the last data
+     * delivered.
+     *
+     * \param lines the maximum number of lines in the string returned.
+     * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+     * \param prefix the desired key prefix to match (nullptr shows all)
+     */
+    std::pair<std::string, int32_t> dump(
+            int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const;
+
+    void clear() {
+        // underlying state is locked.
+        mPreviousAnalyticsState->clear();
+        mAnalyticsState->clear();
+
+        // Clear power usage state.
+        mAudioPowerUsage.clear();
+    }
+
+private:
+
+    /*
+     * AudioAnalytics class does not contain a monitor mutex.
+     * Instead, all of its variables are individually locked for access.
+     * Since data and items are generally added only (gc removes it), this is a reasonable
+     * compromise for availability/concurrency versus consistency.
+     *
+     * It is possible for concurrent threads to be reading and writing inside of AudioAnalytics.
+     * Reads based on a prior time (e.g. one second) in the past from the TimeMachine can be
+     * used to achieve better consistency if needed.
+     */
+
+    /**
+     * Checks for any pending actions for a particular item.
+     *
+     * \param item to check against the current AnalyticsActions.
+     */
+    void checkActions(const std::shared_ptr<const mediametrics::Item>& item);
+
+    // HELPER METHODS
+    /**
+     * Return the audio thread associated with an audio track name.
+     * e.g. "audio.track.32" -> "audio.thread.10" if the associated
+     * threadId for the audio track is 10.
+     */
+    std::string getThreadFromTrack(const std::string& track) const;
+
+    const bool mDeliverStatistics;
+
+    // Actions is individually locked
+    AnalyticsActions mActions;
+
+    // AnalyticsState is individually locked, and we use SharedPtrWrap
+    // to allow safe access even if the shared pointer changes underneath.
+    // These wrap pointers always point to a valid state object.
+    SharedPtrWrap<AnalyticsState> mAnalyticsState;
+    SharedPtrWrap<AnalyticsState> mPreviousAnalyticsState;
+
+    TimedAction mTimedAction; // locked internally
+
+    SimpleLog mStatsdLog{16 /* log lines */}; // locked internally
+
+    // DeviceUse is a nested class which handles audio device usage accounting.
+    // We define this class at the end to ensure prior variables all properly constructed.
+    // TODO: Track / Thread interaction
+    // TODO: Consider statistics aggregation.
+    class DeviceUse {
+    public:
+        enum ItemType {
+            RECORD = 0,
+            THREAD = 1,
+            TRACK = 2,
+        };
+
+        explicit DeviceUse(AudioAnalytics &audioAnalytics) : mAudioAnalytics{audioAnalytics} {}
+
+        // Called every time an endAudioIntervalGroup message is received.
+        void endAudioIntervalGroup(
+                const std::shared_ptr<const android::mediametrics::Item> &item,
+                ItemType itemType) const;
+
+    private:
+        AudioAnalytics &mAudioAnalytics;
+    } mDeviceUse{*this};
+
+    // DeviceConnected is a nested class which handles audio device connection
+    // We define this class at the end to ensure prior variables all properly constructed.
+    // TODO: Track / Thread interaction
+    // TODO: Consider statistics aggregation.
+    class DeviceConnection {
+    public:
+        explicit DeviceConnection(AudioAnalytics &audioAnalytics)
+            : mAudioAnalytics{audioAnalytics} {}
+
+        // Called every time an endAudioIntervalGroup message is received.
+        void a2dpConnected(
+                const std::shared_ptr<const android::mediametrics::Item> &item);
+
+        // Called when we have an AudioFlinger createPatch
+        void createPatch(
+                const std::shared_ptr<const android::mediametrics::Item> &item);
+
+        // Called through AudioManager when the BT service wants to notify connection
+        void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+                const std::shared_ptr<const android::mediametrics::Item> &item);
+
+        // When the timer expires.
+        void expire();
+
+    private:
+        AudioAnalytics &mAudioAnalytics;
+
+        mutable std::mutex mLock;
+        std::string mA2dpDeviceName;
+        int64_t mA2dpConnectionRequestNs GUARDED_BY(mLock) = 0;  // Time for BT service request.
+        int64_t mA2dpConnectionServiceNs GUARDED_BY(mLock) = 0;  // Time audio service agrees.
+
+        int32_t mA2dpConnectionRequests GUARDED_BY(mLock) = 0;
+        int32_t mA2dpConnectionServices GUARDED_BY(mLock) = 0;
+
+        // See the statsd atoms.proto
+        int32_t mA2dpConnectionSuccesses GUARDED_BY(mLock) = 0;
+        int32_t mA2dpConnectionJavaServiceCancels GUARDED_BY(mLock) = 0;
+        int32_t mA2dpConnectionUnknowns GUARDED_BY(mLock) = 0;
+    } mDeviceConnection{*this};
+
+    AudioPowerUsage mAudioPowerUsage{this};
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
new file mode 100644
index 0000000..cca6b41
--- /dev/null
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioPowerUsage"
+#include <utils/Log.h>
+
+#include "AudioAnalytics.h"
+#include "MediaMetricsService.h"
+#include "StringUtils.h"
+#include <map>
+#include <sstream>
+#include <string>
+#include <audio_utils/clock.h>
+#include <cutils/properties.h>
+#include <statslog.h>
+#include <sys/timerfd.h>
+#include <system/audio-base.h>
+
+// property to disable audio power use metrics feature, default is enabled
+#define PROP_AUDIO_METRICS_DISABLED "persist.media.audio_metrics.power_usage_disabled"
+#define AUDIO_METRICS_DISABLED_DEFAULT (false)
+
+// property to set how long to send audio power use metrics data to statsd, default is 24hrs
+#define PROP_AUDIO_METRICS_INTERVAL_HR "persist.media.audio_metrics.interval_hr"
+#define INTERVAL_HR_DEFAULT (24)
+
+// for Audio Power Usage Metrics
+#define AUDIO_POWER_USAGE_KEY_AUDIO_USAGE     "audio.power.usage"
+
+#define AUDIO_POWER_USAGE_PROP_DEVICE         "device"     // int32
+#define AUDIO_POWER_USAGE_PROP_DURATION_NS    "durationNs" // int64
+#define AUDIO_POWER_USAGE_PROP_TYPE           "type"       // int32
+#define AUDIO_POWER_USAGE_PROP_VOLUME         "volume"     // double
+
+namespace android::mediametrics {
+
+/* static */
+bool AudioPowerUsage::typeFromString(const std::string& type_string, int32_t& type) {
+    static std::map<std::string, int32_t> typeTable = {
+        { "AUDIO_STREAM_VOICE_CALL",          VOIP_CALL_TYPE },
+        { "AUDIO_STREAM_SYSTEM",              MEDIA_TYPE },
+        { "AUDIO_STREAM_RING",                RINGTONE_NOTIFICATION_TYPE },
+        { "AUDIO_STREAM_MUSIC",               MEDIA_TYPE },
+        { "AUDIO_STREAM_ALARM",               ALARM_TYPE },
+        { "AUDIO_STREAM_NOTIFICATION",        RINGTONE_NOTIFICATION_TYPE },
+
+        { "AUDIO_CONTENT_TYPE_SPEECH",        VOIP_CALL_TYPE },
+        { "AUDIO_CONTENT_TYPE_MUSIC",         MEDIA_TYPE },
+        { "AUDIO_CONTENT_TYPE_MOVIE",         MEDIA_TYPE },
+        { "AUDIO_CONTENT_TYPE_SONIFICATION",  RINGTONE_NOTIFICATION_TYPE },
+
+        { "AUDIO_USAGE_MEDIA",                MEDIA_TYPE },
+        { "AUDIO_USAGE_VOICE_COMMUNICATION",  VOIP_CALL_TYPE },
+        { "AUDIO_USAGE_ALARM",                ALARM_TYPE },
+        { "AUDIO_USAGE_NOTIFICATION",         RINGTONE_NOTIFICATION_TYPE },
+
+        { "AUDIO_SOURCE_CAMCORDER",           CAMCORDER_TYPE },
+        { "AUDIO_SOURCE_VOICE_COMMUNICATION", VOIP_CALL_TYPE },
+        { "AUDIO_SOURCE_DEFAULT",             RECORD_TYPE },
+        { "AUDIO_SOURCE_MIC",                 RECORD_TYPE },
+        { "AUDIO_SOURCE_UNPROCESSED",         RECORD_TYPE },
+        { "AUDIO_SOURCE_VOICE_RECOGNITION",   RECORD_TYPE },
+    };
+
+    auto it = typeTable.find(type_string);
+    if (it == typeTable.end()) {
+        type = UNKNOWN_TYPE;
+        return false;
+    }
+
+    type = it->second;
+    return true;
+}
+
+/* static */
+bool AudioPowerUsage::deviceFromString(const std::string& device_string, int32_t& device) {
+    static std::map<std::string, int32_t> deviceTable = {
+        { "AUDIO_DEVICE_OUT_EARPIECE",             OUTPUT_EARPIECE },
+        { "AUDIO_DEVICE_OUT_SPEAKER_SAFE",         OUTPUT_SPEAKER_SAFE },
+        { "AUDIO_DEVICE_OUT_SPEAKER",              OUTPUT_SPEAKER },
+        { "AUDIO_DEVICE_OUT_WIRED_HEADSET",        OUTPUT_WIRED_HEADSET },
+        { "AUDIO_DEVICE_OUT_WIRED_HEADPHONE",      OUTPUT_WIRED_HEADSET },
+        { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO",        OUTPUT_BLUETOOTH_SCO },
+        { "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP",       OUTPUT_BLUETOOTH_A2DP },
+        { "AUDIO_DEVICE_OUT_USB_HEADSET",          OUTPUT_USB_HEADSET },
+        { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET", OUTPUT_BLUETOOTH_SCO },
+
+        { "AUDIO_DEVICE_IN_BUILTIN_MIC",           INPUT_BUILTIN_MIC },
+        { "AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", INPUT_BLUETOOTH_SCO },
+        { "AUDIO_DEVICE_IN_WIRED_HEADSET",         INPUT_WIRED_HEADSET_MIC },
+        { "AUDIO_DEVICE_IN_USB_DEVICE",            INPUT_USB_HEADSET_MIC },
+        { "AUDIO_DEVICE_IN_BACK_MIC",              INPUT_BUILTIN_BACK_MIC },
+    };
+
+    auto it = deviceTable.find(device_string);
+    if (it == deviceTable.end()) {
+        device = 0;
+        return false;
+    }
+
+    device = it->second;
+    return true;
+}
+
+int32_t AudioPowerUsage::deviceFromStringPairs(const std::string& device_strings) {
+    int32_t deviceMask = 0;
+    const auto devaddrvec = stringutils::getDeviceAddressPairs(device_strings);
+    for (const auto &[device, addr] : devaddrvec) {
+        int32_t combo_device = 0;
+        deviceFromString(device, combo_device);
+        deviceMask |= combo_device;
+    }
+    return deviceMask;
+}
+
+/* static */
+void AudioPowerUsage::sendItem(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    int32_t type;
+    if (!item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &type)) return;
+
+    int32_t device;
+    if (!item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &device)) return;
+
+    int64_t duration_ns;
+    if (!item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &duration_ns)) return;
+
+    double volume;
+    if (!item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &volume)) return;
+
+    (void)android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
+                                         device,
+                                         (int32_t)(duration_ns / NANOS_PER_SECOND),
+                                         (float)volume,
+                                         type);
+}
+
+bool AudioPowerUsage::saveAsItem_l(
+        int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+{
+    ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
+                                   (long long)duration_ns, average_vol );
+    if (duration_ns == 0) {
+        return true; // skip duration 0 usage
+    }
+    if (device == 0) {
+        return true; //ignore unknown device
+    }
+
+    for (const auto& item : mItems) {
+        int32_t item_type = 0, item_device = 0;
+        double item_volume = 0.;
+        int64_t item_duration_ns = 0;
+        item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &item_device);
+        item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &item_duration_ns);
+        item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &item_type);
+        item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &item_volume);
+
+        // aggregate by device and type
+        if (item_device == device && item_type == type) {
+            int64_t final_duration_ns = item_duration_ns + duration_ns;
+            double final_volume = (device & INPUT_DEVICE_BIT) ? 1.0:
+                            ((item_volume * item_duration_ns +
+                            average_vol * duration_ns) / final_duration_ns);
+
+            item->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, final_duration_ns);
+            item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
+            item->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
+
+            ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f)", __func__,
+                  device, type,
+                  (long long)item_duration_ns, item_volume,
+                  (long long)final_duration_ns, final_volume);
+
+            return true;
+        }
+    }
+
+    auto sitem = std::make_shared<mediametrics::Item>(AUDIO_POWER_USAGE_KEY_AUDIO_USAGE);
+    sitem->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
+    sitem->setInt32(AUDIO_POWER_USAGE_PROP_DEVICE, device);
+    sitem->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, duration_ns);
+    sitem->setInt32(AUDIO_POWER_USAGE_PROP_TYPE, type);
+    sitem->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, average_vol);
+    mItems.emplace_back(sitem);
+    return true;
+}
+
+void AudioPowerUsage::checkTrackRecord(
+        const std::shared_ptr<const mediametrics::Item>& item, bool isTrack)
+{
+    const std::string key = item->getKey();
+
+    int64_t deviceTimeNs = 0;
+    if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs)) {
+        return;
+    }
+    double deviceVolume = 1.;
+    if (isTrack && !item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
+        return;
+    }
+    int32_t type = 0;
+    std::string type_string;
+    if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
+               key, AMEDIAMETRICS_PROP_STREAMTYPE, &type_string) == OK) ||
+        (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
+               key, AMEDIAMETRICS_PROP_SOURCE, &type_string) == OK)) {
+        typeFromString(type_string, type);
+
+        if (isTrack && type == UNKNOWN_TYPE &&
+                   mAudioAnalytics->mAnalyticsState->timeMachine().get(
+                   key, AMEDIAMETRICS_PROP_USAGE, &type_string) == OK) {
+            typeFromString(type_string, type);
+        }
+        if (isTrack && type == UNKNOWN_TYPE &&
+                   mAudioAnalytics->mAnalyticsState->timeMachine().get(
+                   key, AMEDIAMETRICS_PROP_CONTENTTYPE, &type_string) == OK) {
+            typeFromString(type_string, type);
+        }
+        ALOGV("type = %s => %d", type_string.c_str(), type);
+    }
+
+    int32_t device = 0;
+    std::string device_strings;
+    if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
+         key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &device_strings) == OK) ||
+        (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
+         key, AMEDIAMETRICS_PROP_INPUTDEVICES, &device_strings) == OK)) {
+
+        device = deviceFromStringPairs(device_strings);
+        ALOGV("device = %s => %d", device_strings.c_str(), device);
+    }
+    std::lock_guard l(mLock);
+    saveAsItem_l(device, deviceTimeNs, type, deviceVolume);
+}
+
+void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    std::string mode;
+    if (!item->getString(AMEDIAMETRICS_PROP_AUDIOMODE, &mode)) return;
+
+    std::lock_guard l(mLock);
+    if (mode == mMode) return;  // no change in mode.
+
+    if (mMode == "AUDIO_MODE_IN_CALL") { // leaving call mode
+        const int64_t endCallNs = item->getTimestamp();
+        const int64_t durationNs = endCallNs - mDeviceTimeNs;
+        if (durationNs > 0) {
+            mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
+                    mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / durationNs;
+            saveAsItem_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+        }
+    } else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
+        mStartCallNs = item->getTimestamp(); // advisory only
+
+        mDeviceVolume = 0;
+        mVolumeTimeNs = mStartCallNs;
+        mDeviceTimeNs = mStartCallNs;
+    }
+    ALOGV("%s: new mode:%s  old mode:%s", __func__, mode.c_str(), mMode.c_str());
+    mMode = mode;
+}
+
+void AudioPowerUsage::checkVoiceVolume(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    double voiceVolume = 0.;
+    if (!item->getDouble(AMEDIAMETRICS_PROP_VOICEVOLUME, &voiceVolume)) return;
+
+    std::lock_guard l(mLock);
+    if (voiceVolume == mVoiceVolume) return;  // no change in volume
+
+    // we only track average device volume when we are in-call
+    if (mMode == "AUDIO_MODE_IN_CALL") {
+        const int64_t timeNs = item->getTimestamp();
+        const int64_t durationNs = timeNs - mDeviceTimeNs;
+        if (durationNs > 0) {
+            mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
+                    mVoiceVolume * double(timeNs - mVolumeTimeNs)) / durationNs;
+            mVolumeTimeNs = timeNs;
+        }
+    }
+    ALOGV("%s: new voice volume:%lf  old voice volume:%lf", __func__, voiceVolume, mVoiceVolume);
+    mVoiceVolume = voiceVolume;
+}
+
+void AudioPowerUsage::checkCreatePatch(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    std::string outputDevices;
+    if (!item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices)) return;
+
+    const std::string& key = item->getKey();
+    std::string flags;
+    if (mAudioAnalytics->mAnalyticsState->timeMachine().get(
+         key, AMEDIAMETRICS_PROP_FLAGS, &flags) != OK) return;
+
+    if (flags.find("AUDIO_OUTPUT_FLAG_PRIMARY") == std::string::npos) return;
+
+    const int32_t device = deviceFromStringPairs(outputDevices);
+
+    std::lock_guard l(mLock);
+    if (mPrimaryDevice == device) return;
+
+    if (mMode == "AUDIO_MODE_IN_CALL") {
+        // Save statistics
+        const int64_t endDeviceNs = item->getTimestamp();
+        const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
+        if (durationNs > 0) {
+            mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
+                    mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / durationNs;
+            saveAsItem_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+        }
+        // reset statistics
+        mDeviceVolume = 0;
+        mDeviceTimeNs = endDeviceNs;
+        mVolumeTimeNs = endDeviceNs;
+    }
+    ALOGV("%s: new primary device:%#x  old primary device:%#x", __func__, device, mPrimaryDevice);
+    mPrimaryDevice = device;
+}
+
+AudioPowerUsage::AudioPowerUsage(AudioAnalytics *audioAnalytics)
+    : mAudioAnalytics(audioAnalytics)
+    , mDisabled(property_get_bool(PROP_AUDIO_METRICS_DISABLED, AUDIO_METRICS_DISABLED_DEFAULT))
+    , mIntervalHours(property_get_int32(PROP_AUDIO_METRICS_INTERVAL_HR, INTERVAL_HR_DEFAULT))
+{
+    ALOGD("%s", __func__);
+    ALOGI_IF(mDisabled, "AudioPowerUsage is disabled.");
+    collect(); // send items
+}
+
+AudioPowerUsage::~AudioPowerUsage()
+{
+    ALOGD("%s", __func__);
+}
+
+void AudioPowerUsage::clear()
+{
+    std::lock_guard _l(mLock);
+    mItems.clear();
+}
+
+void AudioPowerUsage::collect()
+{
+    std::lock_guard _l(mLock);
+    for (const auto &item : mItems) {
+        sendItem(item);
+    }
+    mItems.clear();
+    mAudioAnalytics->mTimedAction.postIn(
+        mIntervalHours <= 0 ? std::chrono::seconds(5) : std::chrono::hours(mIntervalHours),
+        [this](){ collect(); });
+}
+
+std::pair<std::string, int32_t> AudioPowerUsage::dump(int limit) const {
+    if (limit <= 2) {
+        return {{}, 0};
+    }
+    std::lock_guard _l(mLock);
+    if (mDisabled) {
+        return {"AudioPowerUsage disabled\n", 1};
+    }
+    if (mItems.empty()) {
+        return {"AudioPowerUsage empty\n", 1};
+    }
+
+    int slot = 1;
+    std::stringstream ss;
+    ss << "AudioPowerUsage:\n";
+    for (const auto &item : mItems) {
+        if (slot >= limit - 1) {
+            ss << "-- AudioPowerUsage may be truncated!\n";
+            ++slot;
+            break;
+        }
+        ss << " " << slot << " " << item->toString() << "\n";
+        slot++;
+    }
+    return { ss.str(), slot };
+}
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioPowerUsage.h b/services/mediametrics/AudioPowerUsage.h
new file mode 100644
index 0000000..446ff4f
--- /dev/null
+++ b/services/mediametrics/AudioPowerUsage.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <deque>
+#include <media/MediaMetricsItem.h>
+#include <mutex>
+#include <thread>
+
+namespace android::mediametrics {
+
+class AudioAnalytics;
+
+class AudioPowerUsage {
+public:
+    explicit AudioPowerUsage(AudioAnalytics *audioAnalytics);
+    ~AudioPowerUsage();
+
+    void checkTrackRecord(const std::shared_ptr<const mediametrics::Item>& item, bool isTrack);
+    void checkMode(const std::shared_ptr<const mediametrics::Item>& item);
+    void checkVoiceVolume(const std::shared_ptr<const mediametrics::Item>& item);
+    void checkCreatePatch(const std::shared_ptr<const mediametrics::Item>& item);
+    void clear();
+
+    /**
+     * Returns a pair consisting of the dump string, and the number of lines in the string.
+     *
+     * The number of lines in the returned pair is used as an optimization
+     * for subsequent line limiting.
+     *
+     * \param lines the maximum number of lines in the string returned.
+     */
+    std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const;
+
+    // align with message AudioUsageDataReported in frameworks/base/cmds/statsd/src/atoms.proto
+    enum AudioType {
+        UNKNOWN_TYPE = 0,
+        VOICE_CALL_TYPE = 1,            // voice call
+        VOIP_CALL_TYPE = 2,             // voip call, including uplink and downlink
+        MEDIA_TYPE = 3,                 // music and system sound
+        RINGTONE_NOTIFICATION_TYPE = 4, // ringtone and notification
+        ALARM_TYPE = 5,                 // alarm type
+        // record type
+        CAMCORDER_TYPE = 6,             // camcorder
+        RECORD_TYPE = 7,                // other recording
+    };
+
+    enum AudioDevice {
+        OUTPUT_EARPIECE         = 0x1,
+        OUTPUT_SPEAKER          = 0x2,
+        OUTPUT_WIRED_HEADSET    = 0x4,
+        OUTPUT_USB_HEADSET      = 0x8,
+        OUTPUT_BLUETOOTH_SCO    = 0x10,
+        OUTPUT_BLUETOOTH_A2DP   = 0x20,
+        OUTPUT_SPEAKER_SAFE     = 0x40,
+
+        INPUT_DEVICE_BIT        = 0x40000000,
+        INPUT_BUILTIN_MIC       = INPUT_DEVICE_BIT | 0x1, // non-negative positive int32.
+        INPUT_BUILTIN_BACK_MIC  = INPUT_DEVICE_BIT | 0x2,
+        INPUT_WIRED_HEADSET_MIC = INPUT_DEVICE_BIT | 0x4,
+        INPUT_USB_HEADSET_MIC   = INPUT_DEVICE_BIT | 0x8,
+        INPUT_BLUETOOTH_SCO     = INPUT_DEVICE_BIT | 0x10,
+    };
+
+    static bool typeFromString(const std::string& type_string, int32_t& type);
+    static bool deviceFromString(const std::string& device_string, int32_t& device);
+    static int32_t deviceFromStringPairs(const std::string& device_strings);
+private:
+    bool saveAsItem_l(int32_t device, int64_t duration, int32_t type, double average_vol)
+         REQUIRES(mLock);
+    static void sendItem(const std::shared_ptr<const mediametrics::Item>& item);
+    void collect();
+
+    AudioAnalytics * const mAudioAnalytics;
+    const bool mDisabled;
+    const int32_t mIntervalHours;
+
+    mutable std::mutex mLock;
+    std::deque<std::shared_ptr<mediametrics::Item>> mItems GUARDED_BY(mLock);
+
+    double mVoiceVolume GUARDED_BY(mLock) = 0.;
+    double mDeviceVolume GUARDED_BY(mLock) = 0.;
+    int64_t mStartCallNs GUARDED_BY(mLock) = 0; // advisory only
+    int64_t mVolumeTimeNs GUARDED_BY(mLock) = 0;
+    int64_t mDeviceTimeNs GUARDED_BY(mLock) = 0;
+    int32_t mPrimaryDevice GUARDED_BY(mLock) = OUTPUT_SPEAKER;
+    std::string mMode GUARDED_BY(mLock) {"AUDIO_MODE_NORMAL"};
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
new file mode 100644
index 0000000..aa44447
--- /dev/null
+++ b/services/mediametrics/AudioTypes.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioTypes.h"
+#include "StringUtils.h"
+#include <media/TypeConverter.h> // requires libmedia_helper to get the Audio code.
+
+namespace android::mediametrics::types {
+
+const std::unordered_map<std::string, int32_t>& getAudioCallerNameMap() {
+    // DO NOT MODIFY VALUES (OK to add new ones).
+    // This may be found in frameworks/av/media/libmediametrics/include/MediaMetricsConstants.h
+    static std::unordered_map<std::string, int32_t> map{
+        {"unknown",       0},           // callerName not set
+        {"aaudio",        1},           // Native AAudio
+        {"java",          2},           // Java API layer
+        {"media",         3},           // libmedia (mediaplayer)
+        {"opensles",      4},           // Open SLES
+        {"rtp",           5},           // RTP communication
+        {"soundpool",     6},           // SoundPool
+        {"tonegenerator", 7},           // dial tones
+        // R values above.
+    };
+    return map;
+}
+
+// A map in case we need to return a flag for input devices.
+// This is 64 bits (and hence not the same as audio_device_t) because we need extra
+// bits to represent new devices.
+// NOT USED FOR R.  We do not use int64 flags.
+// This can be out of date for now, as it is unused even for string validation
+// (instead TypeConverter<InputDeviceTraits> is used).
+const std::unordered_map<std::string, int64_t>& getAudioDeviceInMap() {
+    // DO NOT MODIFY VALUES (OK to add new ones).  This does NOT match audio_device_t.
+    static std::unordered_map<std::string, int64_t> map{
+        {"AUDIO_DEVICE_IN_COMMUNICATION",          1LL << 0},
+        {"AUDIO_DEVICE_IN_AMBIENT",                1LL << 1},
+        {"AUDIO_DEVICE_IN_BUILTIN_MIC",            1LL << 2},
+        {"AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET",  1LL << 3},
+        {"AUDIO_DEVICE_IN_WIRED_HEADSET",          1LL << 4},
+        {"AUDIO_DEVICE_IN_AUX_DIGITAL",            1LL << 5},
+        {"AUDIO_DEVICE_IN_HDMI",                   1LL << 5}, // HDMI == AUX_DIGITAL (6 reserved)
+        {"AUDIO_DEVICE_IN_VOICE_CALL",             1LL << 7},
+        {"AUDIO_DEVICE_IN_TELEPHONY_RX",           1LL << 7}, // TELEPHONY_RX == VOICE_CALL (8 reserved)
+        {"AUDIO_DEVICE_IN_BACK_MIC",               1LL << 9},
+        {"AUDIO_DEVICE_IN_REMOTE_SUBMIX",          1LL << 10},
+        {"AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET",      1LL << 11},
+        {"AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET",      1LL << 12},
+        {"AUDIO_DEVICE_IN_USB_ACCESSORY",          1LL << 13},
+        {"AUDIO_DEVICE_IN_USB_DEVICE",             1LL << 14},
+        {"AUDIO_DEVICE_IN_FM_TUNER",               1LL << 15},
+        {"AUDIO_DEVICE_IN_TV_TUNER",               1LL << 16},
+        {"AUDIO_DEVICE_IN_LINE",                   1LL << 17},
+        {"AUDIO_DEVICE_IN_SPDIF",                  1LL << 18},
+        {"AUDIO_DEVICE_IN_BLUETOOTH_A2DP",         1LL << 19},
+        {"AUDIO_DEVICE_IN_LOOPBACK",               1LL << 20},
+        {"AUDIO_DEVICE_IN_IP",                     1LL << 21},
+        {"AUDIO_DEVICE_IN_BUS",                    1LL << 22},
+        {"AUDIO_DEVICE_IN_PROXY",                  1LL << 23},
+        {"AUDIO_DEVICE_IN_USB_HEADSET",            1LL << 24},
+        {"AUDIO_DEVICE_IN_BLUETOOTH_BLE",          1LL << 25},
+        {"AUDIO_DEVICE_IN_HDMI_ARC",               1LL << 26},
+        {"AUDIO_DEVICE_IN_ECHO_REFERENCE",         1LL << 27},
+        {"AUDIO_DEVICE_IN_DEFAULT",                1LL << 28},
+        // R values above.
+    };
+    return map;
+}
+
+// A map in case we need to return a flag for output devices.
+// This is 64 bits (and hence not the same as audio_device_t) because we need extra
+// bits to represent new devices.
+// NOT USED FOR R.  We do not use int64 flags.
+// This can be out of date for now, as it is unused even for string validation
+// (instead TypeConverter<OutputDeviceTraits> is used).
+const std::unordered_map<std::string, int64_t>& getAudioDeviceOutMap() {
+    // DO NOT MODIFY VALUES (OK to add new ones).  This does NOT match audio_device_t.
+    static std::unordered_map<std::string, int64_t> map{
+        {"AUDIO_DEVICE_OUT_EARPIECE",                  1LL << 0},
+        {"AUDIO_DEVICE_OUT_SPEAKER",                   1LL << 1},
+        {"AUDIO_DEVICE_OUT_WIRED_HEADSET",             1LL << 2},
+        {"AUDIO_DEVICE_OUT_WIRED_HEADPHONE",           1LL << 3},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO",             1LL << 4},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET",     1LL << 5},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT",      1LL << 6},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP",            1LL << 7},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES", 1LL << 8},
+        {"AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER",    1LL << 9},
+        {"AUDIO_DEVICE_OUT_AUX_DIGITAL",               1LL << 10},
+        {"AUDIO_DEVICE_OUT_HDMI",                      1LL << 10}, // HDMI == AUX_DIGITAL (11 reserved)
+        {"AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET",         1LL << 12},
+        {"AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET",         1LL << 13},
+        {"AUDIO_DEVICE_OUT_USB_ACCESSORY",             1LL << 14},
+        {"AUDIO_DEVICE_OUT_USB_DEVICE",                1LL << 15},
+        {"AUDIO_DEVICE_OUT_REMOTE_SUBMIX",             1LL << 16},
+        {"AUDIO_DEVICE_OUT_TELEPHONY_TX",              1LL << 17},
+        {"AUDIO_DEVICE_OUT_LINE",                      1LL << 18},
+        {"AUDIO_DEVICE_OUT_HDMI_ARC",                  1LL << 19},
+        {"AUDIO_DEVICE_OUT_SPDIF",                     1LL << 20},
+        {"AUDIO_DEVICE_OUT_FM",                        1LL << 21},
+        {"AUDIO_DEVICE_OUT_AUX_LINE",                  1LL << 22},
+        {"AUDIO_DEVICE_OUT_SPEAKER_SAFE",              1LL << 23},
+        {"AUDIO_DEVICE_OUT_IP",                        1LL << 24},
+        {"AUDIO_DEVICE_OUT_BUS",                       1LL << 25},
+        {"AUDIO_DEVICE_OUT_PROXY",                     1LL << 26},
+        {"AUDIO_DEVICE_OUT_USB_HEADSET",               1LL << 27},
+        {"AUDIO_DEVICE_OUT_HEARING_AID",               1LL << 28},
+        {"AUDIO_DEVICE_OUT_ECHO_CANCELLER",            1LL << 29},
+        {"AUDIO_DEVICE_OUT_DEFAULT",                   1LL << 30},
+        // R values above.
+    };
+    return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAudioThreadTypeMap() {
+    // DO NOT MODIFY VALUES (OK to add new ones).
+    // This may be found in frameworks/av/services/audioflinger/Threads.h
+    static std::unordered_map<std::string, int32_t> map{
+        // UNKNOWN is -1
+        {"MIXER",         0},          // Thread class is MixerThread
+        {"DIRECT",        1},          // Thread class is DirectOutputThread
+        {"DUPLICATING",   2},          // Thread class is DuplicatingThread
+        {"RECORD",        3},          // Thread class is RecordThread
+        {"OFFLOAD",       4},          // Thread class is OffloadThread
+        {"MMAP_PLAYBACK", 5},          // Thread class for MMAP playback stream
+        {"MMAP_CAPTURE",  6},          // Thread class for MMAP capture stream
+        // R values above.
+    };
+    return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap() {
+    // DO NOT MODIFY VALUES (OK to add new ones).
+    static std::unordered_map<std::string, int32_t> map{
+        {"static",        (1 << 0)},  // A static track
+        // R values above.
+    };
+    return map;
+}
+
+// Helper: Create the corresponding int32 from string flags split with '|'.
+template <typename Traits>
+int32_t int32FromFlags(const std::string &flags)
+{
+    const auto result = stringutils::split(flags, "|");
+    int32_t intFlags = 0;
+    for (const auto& flag : result) {
+        typename Traits::Type value;
+        if (!TypeConverter<Traits>::fromString(flag, value)) {
+            break;
+        }
+        intFlags |= value;
+    }
+    return intFlags;
+}
+
+template <typename Traits>
+std::string stringFromFlags(const std::string &flags, size_t len)
+{
+    const auto result = stringutils::split(flags, "|");
+    std::string sFlags;
+    for (const auto& flag : result) {
+        typename Traits::Type value;
+        if (!TypeConverter<Traits>::fromString(flag, value)) {
+            break;
+        }
+        if (len >= flag.size()) continue;
+        if (!sFlags.empty()) sFlags += "|";
+        sFlags += flag.c_str() + len;
+    }
+    return sFlags;
+}
+
+template <typename M>
+std::string validateStringFromMap(const std::string &str, const M& map)
+{
+    if (str.empty()) return {};
+
+    const auto result = stringutils::split(str, "|");
+    std::stringstream ss;
+    for (const auto &s : result) {
+        if (map.count(s) > 0) {
+            if (ss.tellp() > 0) ss << "|";
+            ss << s;
+        }
+    }
+    return ss.str();
+}
+
+template <typename M>
+typename M::mapped_type flagsFromMap(const std::string &str, const M& map)
+{
+    if (str.empty()) return {};
+
+    const auto result = stringutils::split(str, "|");
+    typename M::mapped_type value{};
+    for (const auto &s : result) {
+        auto it = map.find(s);
+        if (it == map.end()) continue;
+        value |= it->second;
+    }
+    return value;
+}
+
+template <>
+int32_t lookup<CONTENT_TYPE>(const std::string &contentType)
+{
+    AudioContentTraits::Type value;
+    if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
+        value = AUDIO_CONTENT_TYPE_UNKNOWN;
+    }
+    return (int32_t)value;
+}
+
+template <>
+std::string lookup<CONTENT_TYPE>(const std::string &contentType)
+{
+    AudioContentTraits::Type value;
+    if (!TypeConverter<AudioContentTraits>::fromString(contentType, value)) {
+        return "";
+    }
+    return contentType.c_str() + sizeof("AUDIO_CONTENT_TYPE");
+}
+
+template <>
+int32_t lookup<ENCODING>(const std::string &encoding)
+{
+    FormatTraits::Type value;
+    if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
+        value = AUDIO_FORMAT_INVALID;
+    }
+    return (int32_t)value;
+}
+
+template <>
+std::string lookup<ENCODING>(const std::string &encoding)
+{
+    FormatTraits::Type value;
+    if (!TypeConverter<FormatTraits>::fromString(encoding, value)) {
+        return "";
+    }
+    return encoding.c_str() + sizeof("AUDIO_FORMAT");
+}
+
+template <>
+int32_t lookup<INPUT_FLAG>(const std::string &inputFlag)
+{
+    return int32FromFlags<InputFlagTraits>(inputFlag);
+}
+
+template <>
+std::string lookup<INPUT_FLAG>(const std::string &inputFlag)
+{
+    return stringFromFlags<InputFlagTraits>(inputFlag, sizeof("AUDIO_INPUT_FLAG"));
+}
+
+template <>
+int32_t lookup<OUTPUT_FLAG>(const std::string &outputFlag)
+{
+    return int32FromFlags<OutputFlagTraits>(outputFlag);
+}
+
+template <>
+std::string lookup<OUTPUT_FLAG>(const std::string &outputFlag)
+{
+    return stringFromFlags<OutputFlagTraits>(outputFlag, sizeof("AUDIO_OUTPUT_FLAG"));
+}
+
+template <>
+int32_t lookup<SOURCE_TYPE>(const std::string &sourceType)
+{
+    SourceTraits::Type value;
+    if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
+        value = AUDIO_SOURCE_DEFAULT;
+    }
+    return (int32_t)value;
+}
+
+template <>
+std::string lookup<SOURCE_TYPE>(const std::string &sourceType)
+{
+    SourceTraits::Type value;
+    if (!TypeConverter<SourceTraits>::fromString(sourceType, value)) {
+        return "";
+    }
+    return sourceType.c_str() + sizeof("AUDIO_SOURCE");
+}
+
+template <>
+int32_t lookup<STREAM_TYPE>(const std::string &streamType)
+{
+    StreamTraits::Type value;
+    if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
+        value = AUDIO_STREAM_DEFAULT;
+    }
+    return (int32_t)value;
+}
+
+template <>
+std::string lookup<STREAM_TYPE>(const std::string &streamType)
+{
+    StreamTraits::Type value;
+    if (!TypeConverter<StreamTraits>::fromString(streamType, value)) {
+        return "";
+    }
+    return streamType.c_str() + sizeof("AUDIO_STREAM");
+}
+
+template <>
+int32_t lookup<USAGE>(const std::string &usage)
+{
+    UsageTraits::Type value;
+    if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
+        value = AUDIO_USAGE_UNKNOWN;
+    }
+    return (int32_t)value;
+}
+
+template <>
+std::string lookup<USAGE>(const std::string &usage)
+{
+    UsageTraits::Type value;
+    if (!TypeConverter<UsageTraits>::fromString(usage, value)) {
+        return "";
+    }
+    return usage.c_str() + sizeof("AUDIO_USAGE");
+}
+
+template <>
+int64_t lookup<INPUT_DEVICE>(const std::string &inputDevice)
+{
+    // NOT USED FOR R.
+    // Returns a set of bits, each one representing a device in inputDevice.
+    // This is a 64 bit integer, not the same as audio_device_t.
+    return flagsFromMap(inputDevice, getAudioDeviceInMap());
+}
+
+template <>
+std::string lookup<INPUT_DEVICE>(const std::string &inputDevice)
+{
+    return stringFromFlags<InputDeviceTraits>(inputDevice, sizeof("AUDIO_DEVICE_IN"));
+}
+
+template <>
+int64_t lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
+{
+    // NOT USED FOR R.
+    // Returns a set of bits, each one representing a device in outputDevice.
+    // This is a 64 bit integer, not the same as audio_device_t.
+    return flagsFromMap(outputDevice, getAudioDeviceOutMap());
+}
+
+template <>
+std::string lookup<OUTPUT_DEVICE>(const std::string &outputDevice)
+{
+    return stringFromFlags<OutputDeviceTraits>(outputDevice, sizeof("AUDIO_DEVICE_OUT"));
+}
+
+template <>
+int32_t lookup<CALLER_NAME>(const std::string &callerName)
+{
+    auto& map = getAudioCallerNameMap();
+    auto it = map.find(callerName);
+    if (it == map.end()) {
+        return 0;      // return unknown
+    }
+    return it->second;
+}
+
+template <>
+std::string lookup<CALLER_NAME>(const std::string &callerName)
+{
+    auto& map = getAudioCallerNameMap();
+    auto it = map.find(callerName);
+    if (it == map.end()) {
+        return "";
+    }
+    return callerName;
+}
+
+template <>
+int32_t lookup<THREAD_TYPE>(const std::string &threadType)
+{
+    auto& map = getAudioThreadTypeMap();
+    auto it = map.find(threadType);
+    if (it == map.end()) {
+        return -1; // note this as an illegal thread value as we don't have unknown here.
+    }
+    return it->second;
+}
+
+template <>
+std::string lookup<THREAD_TYPE>(const std::string &threadType)
+{
+    auto& map = getAudioThreadTypeMap();
+    auto it = map.find(threadType);
+    if (it == map.end()) {
+        return "";
+    }
+    return threadType;
+}
+
+bool isInputThreadType(const std::string &threadType)
+{
+    return threadType == "RECORD" || threadType == "MMAP_CAPTURE";
+}
+
+template <>
+std::string lookup<TRACK_TRAITS>(const std::string &traits)
+{
+    return validateStringFromMap(traits, getAudioTrackTraitsMap());
+}
+
+template <>
+int32_t lookup<TRACK_TRAITS>(const std::string &traits)
+{
+    return flagsFromMap(traits, getAudioTrackTraitsMap());
+}
+
+} // namespace android::mediametrics::types
diff --git a/services/mediametrics/AudioTypes.h b/services/mediametrics/AudioTypes.h
new file mode 100644
index 0000000..e1deeb1
--- /dev/null
+++ b/services/mediametrics/AudioTypes.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+namespace android::mediametrics::types {
+
+// Helper methods that map mediametrics logged strings to integer codes.
+// In R we do not use the integer codes, but rather we can use these maps
+// to validate correct strings.
+const std::unordered_map<std::string, int32_t>& getAudioCallerNameMap();
+const std::unordered_map<std::string, int64_t>& getAudioDeviceInMap();
+const std::unordered_map<std::string, int64_t>& getAudioDeviceOutMap();
+const std::unordered_map<std::string, int32_t>& getAudioThreadTypeMap();
+const std::unordered_map<std::string, int32_t>& getAudioTrackTraitsMap();
+
+// Enumeration for the device connection results.
+enum DeviceConnectionResult : int32_t {
+    DEVICE_CONNECTION_RESULT_SUCCESS = 0,              // Audio delivered
+    DEVICE_CONNECTION_RESULT_UNKNOWN = 1,              // Success is unknown.
+    DEVICE_CONNECTION_RESULT_JAVA_SERVICE_CANCEL = 2,  // Canceled in Java service
+    // Do not modify the constants above after R.  Adding new constants is fine.
+};
+
+// Enumeration for all the string translations to integers (generally int32_t) unless noted.
+enum AudioEnumCategory {
+    CALLER_NAME,
+    CONTENT_TYPE,
+    ENCODING,
+    INPUT_DEVICE,  // int64_t
+    INPUT_FLAG,
+    OUTPUT_DEVICE, // int64_t
+    OUTPUT_FLAG,
+    SOURCE_TYPE,
+    STREAM_TYPE,
+    THREAD_TYPE,
+    TRACK_TRAITS,
+    USAGE,
+};
+
+// Convert a string (or arbitrary S) from an AudioEnumCategory to a particular type.
+// This is used to convert log std::strings back to the original type (int32_t or int64_t).
+//
+// For a string, generally there is a prefix "AUDIO_INPUT_FLAG" or some such that could
+// actually indicate the category so the AudioEnumCategory could be superfluous, but
+// we use it to find the proper default value in case of an unknown string.
+//
+// lookup<ENCODING, int32_t>("AUDIO_FORMAT_PCM_16_BIT") -> 1
+//
+template <AudioEnumCategory C, typename T, typename S>
+T lookup(const S &str);
+
+// Helper: Allow using a const char * in lieu of std::string.
+template <AudioEnumCategory C, typename T>
+T lookup(const char *str) {
+    return lookup<C, T, std::string>(str);
+}
+
+bool isInputThreadType(const std::string &threadType);
+
+} // namespace android::mediametrics::types
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
new file mode 100644
index 0000000..48e766e
--- /dev/null
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2017 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 "MediaMetricsService"
+#include <utils/Log.h>
+
+#include "MediaMetricsService.h"
+
+#include <pwd.h> //getpwuid
+
+#include <android/content/pm/IPackageManagerNative.h>  // package info
+#include <audio_utils/clock.h>                 // clock conversions
+#include <binder/IPCThreadState.h>             // get calling uid
+#include <cutils/properties.h>                 // for property_get
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
+#include <private/android_filesystem_config.h> // UID
+
+namespace android {
+
+using mediametrics::Item;
+using mediametrics::startsWith;
+
+// individual records kept in memory: age or count
+// age: <= 28 hours (1 1/6 days)
+// count: hard limit of # records
+// (0 for either of these disables that threshold)
+//
+static constexpr nsecs_t kMaxRecordAgeNs = 28 * 3600 * NANOS_PER_SECOND;
+// 2019/6: average daily per device is currently 375-ish;
+// setting this to 2000 is large enough to catch most devices
+// we'll lose some data on very very media-active devices, but only for
+// the gms collection; statsd will have already covered those for us.
+// This also retains enough information to help with bugreports
+static constexpr size_t kMaxRecords = 2000;
+
+// max we expire in a single call, to constrain how long we hold the
+// mutex, which also constrains how long a client might wait.
+static constexpr size_t kMaxExpiredAtOnce = 50;
+
+// TODO: need to look at tuning kMaxRecords and friends for low-memory devices
+
+/* static */
+nsecs_t MediaMetricsService::roundTime(nsecs_t timeNs)
+{
+    return (timeNs + NANOS_PER_SECOND / 2) / NANOS_PER_SECOND * NANOS_PER_SECOND;
+}
+
+/* static */
+bool MediaMetricsService::useUidForPackage(
+        const std::string& package, const std::string& installer)
+{
+    if (strchr(package.c_str(), '.') == nullptr) {
+        return false;  // not of form 'com.whatever...'; assume internal and ok
+    } else if (strncmp(package.c_str(), "android.", 8) == 0) {
+        return false;  // android.* packages are assumed fine
+    } else if (strncmp(installer.c_str(), "com.android.", 12) == 0) {
+        return false;  // from play store
+    } else if (strncmp(installer.c_str(), "com.google.", 11) == 0) {
+        return false;  // some google source
+    } else if (strcmp(installer.c_str(), "preload") == 0) {
+        return false;  // preloads
+    } else {
+        return true;  // we're not sure where it came from, use uid only.
+    }
+}
+
+/* static */
+std::pair<std::string, int64_t>
+MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid_t uid) {
+    // Meyer's singleton, initialized on first access.
+    // mUidInfo is locked internally.
+    static mediautils::UidInfo uidInfo;
+
+    // get info.
+    mediautils::UidInfo::Info info = uidInfo.getInfo(uid);
+    if (useUidForPackage(info.package, info.installer)) {
+        return { std::to_string(uid), /* versionCode */ 0 };
+    } else {
+        return { info.package, info.versionCode };
+    }
+}
+
+MediaMetricsService::MediaMetricsService()
+        : mMaxRecords(kMaxRecords),
+          mMaxRecordAgeNs(kMaxRecordAgeNs),
+          mMaxRecordsExpiredAtOnce(kMaxExpiredAtOnce)
+{
+    ALOGD("%s", __func__);
+}
+
+MediaMetricsService::~MediaMetricsService()
+{
+    ALOGD("%s", __func__);
+    // the class destructor clears anyhow, but we enforce clearing items first.
+    mItemsDiscarded += mItems.size();
+    mItems.clear();
+}
+
+status_t MediaMetricsService::submitInternal(mediametrics::Item *item, bool release)
+{
+    // calling PID is 0 for one-way calls.
+    const pid_t pid = IPCThreadState::self()->getCallingPid();
+    const pid_t pid_given = item->getPid();
+    const uid_t uid = IPCThreadState::self()->getCallingUid();
+    const uid_t uid_given = item->getUid();
+
+    //ALOGD("%s: caller pid=%d uid=%d,  item pid=%d uid=%d", __func__,
+    //        (int)pid, (int)uid, (int) pid_given, (int)uid_given);
+
+    bool isTrusted;
+    switch (uid) {
+    case AID_AUDIOSERVER:
+    case AID_BLUETOOTH:
+    case AID_CAMERA:
+    case AID_DRM:
+    case AID_MEDIA:
+    case AID_MEDIA_CODEC:
+    case AID_MEDIA_EX:
+    case AID_MEDIA_DRM:
+    // case AID_SHELL: // DEBUG ONLY - used for mediametrics_tests to add new keys
+    case AID_SYSTEM:
+        // trusted source, only override default values
+        isTrusted = true;
+        if (uid_given == (uid_t)-1) {
+            item->setUid(uid);
+        }
+        if (pid_given == (pid_t)-1) {
+            item->setPid(pid); // if one-way then this is 0.
+        }
+        break;
+    default:
+        isTrusted = false;
+        item->setPid(pid); // always use calling pid, if one-way then this is 0.
+        item->setUid(uid);
+        break;
+    }
+
+    // Overwrite package name and version if the caller was untrusted or empty
+    if (!isTrusted || item->getPkgName().empty()) {
+        const uid_t uidItem = item->getUid();
+        const auto [ pkgName, version ] =
+                MediaMetricsService::getSanitizedPackageNameAndVersionCode(uidItem);
+        item->setPkgName(pkgName);
+        item->setPkgVersionCode(version);
+    }
+
+    ALOGV("%s: isTrusted:%d given uid %d; sanitized uid: %d sanitized pkg: %s "
+          "sanitized pkg version: %lld",
+          __func__,
+          (int)isTrusted,
+          uid_given, item->getUid(),
+          item->getPkgName().c_str(),
+          (long long)item->getPkgVersionCode());
+
+    mItemsSubmitted++;
+
+    // validate the record; we discard if we don't like it
+    if (isContentValid(item, isTrusted) == false) {
+        if (release) delete item;
+        return PERMISSION_DENIED;
+    }
+
+    // XXX: if we have a sessionid in the new record, look to make
+    // sure it doesn't appear in the finalized list.
+
+    if (item->count() == 0) {
+        ALOGV("%s: dropping empty record...", __func__);
+        if (release) delete item;
+        return BAD_VALUE;
+    }
+
+    if (!isTrusted || item->getTimestamp() == 0) {
+        // Statsd logs two times for events: ElapsedRealTimeNs (BOOTTIME) and
+        // WallClockTimeNs (REALTIME), but currently logs REALTIME to cloud.
+        //
+        // For consistency and correlation with other logging mechanisms
+        // we use REALTIME here.
+        const int64_t now = systemTime(SYSTEM_TIME_REALTIME);
+        item->setTimestamp(now);
+    }
+
+    // now attach either the item or its dup to a const shared pointer
+    std::shared_ptr<const mediametrics::Item> sitem(release ? item : item->dup());
+
+    (void)mAudioAnalytics.submit(sitem, isTrusted);
+
+    extern bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item);
+    (void)dump2Statsd(sitem);  // failure should be logged in function.
+    saveItem(sitem);
+    return NO_ERROR;
+}
+
+status_t MediaMetricsService::dump(int fd, const Vector<String16>& args)
+{
+    String8 result;
+
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        result.appendFormat("Permission Denial: "
+                "can't dump MediaMetricsService from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        write(fd, result.string(), result.size());
+        return NO_ERROR;
+    }
+
+    static const String16 allOption("--all");
+    static const String16 clearOption("--clear");
+    static const String16 heapOption("--heap");
+    static const String16 helpOption("--help");
+    static const String16 prefixOption("--prefix");
+    static const String16 sinceOption("--since");
+    static const String16 unreachableOption("--unreachable");
+
+    bool all = false;
+    bool clear = false;
+    bool heap = false;
+    bool unreachable = false;
+    int64_t sinceNs = 0;
+    std::string prefix;
+
+    const size_t n = args.size();
+    for (size_t i = 0; i < n; i++) {
+        if (args[i] == allOption) {
+            all = true;
+        } else if (args[i] == clearOption) {
+            clear = true;
+        } else if (args[i] == heapOption) {
+            heap = true;
+        } else if (args[i] == helpOption) {
+            // TODO: consider function area dumping.
+            // dumpsys media.metrics audiotrack,codec
+            // or dumpsys media.metrics audiotrack codec
+
+            result.append("Recognized parameters:\n");
+            result.append("--all         show all records\n");
+            result.append("--clear       clear out saved records\n");
+            result.append("--heap        show heap usage (top 100)\n");
+            result.append("--help        display help\n");
+            result.append("--prefix X    process records for component X\n");
+            result.append("--since X     X < 0: records from -X seconds in the past\n");
+            result.append("              X = 0: ignore\n");
+            result.append("              X > 0: records from X seconds since Unix epoch\n");
+            result.append("--unreachable show unreachable memory (leaks)\n");
+            write(fd, result.string(), result.size());
+            return NO_ERROR;
+        } else if (args[i] == prefixOption) {
+            ++i;
+            if (i < n) {
+                prefix = String8(args[i]).string();
+            }
+        } else if (args[i] == sinceOption) {
+            ++i;
+            if (i < n) {
+                String8 value(args[i]);
+                char *endp;
+                const char *p = value.string();
+                const auto sec = (int64_t)strtoll(p, &endp, 10);
+                if (endp == p || *endp != '\0' || sec == 0) {
+                    sinceNs = 0;
+                } else if (sec < 0) {
+                    sinceNs = systemTime(SYSTEM_TIME_REALTIME) + sec * NANOS_PER_SECOND;
+                } else {
+                    sinceNs = sec * NANOS_PER_SECOND;
+                }
+            }
+        } else if (args[i] == unreachableOption) {
+            unreachable = true;
+        }
+    }
+
+    {
+        std::lock_guard _l(mLock);
+
+        if (clear) {
+            mItemsDiscarded += mItems.size();
+            mItems.clear();
+            mAudioAnalytics.clear();
+        } else {
+            result.appendFormat("Dump of the %s process:\n", kServiceName);
+            const char *prefixptr = prefix.size() > 0 ? prefix.c_str() : nullptr;
+            dumpHeaders(result, sinceNs, prefixptr);
+            dumpQueue(result, sinceNs, prefixptr);
+
+            // TODO: maybe consider a better way of dumping audio analytics info.
+            const int32_t linesToDump = all ? INT32_MAX : 1000;
+            auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr);
+            result.append(dumpString.c_str());
+            if (lines == linesToDump) {
+                result.append("-- some lines may be truncated --\n");
+            }
+        }
+    }
+    write(fd, result.string(), result.size());
+
+    // Check heap and unreachable memory outside of lock.
+    if (heap) {
+        dprintf(fd, "\nDumping heap:\n");
+        std::string s = dumpMemoryAddresses(100 /* limit */);
+        write(fd, s.c_str(), s.size());
+    }
+    if (unreachable) {
+        dprintf(fd, "\nDumping unreachable memory:\n");
+        // TODO - should limit be an argument parameter?
+        std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+        write(fd, s.c_str(), s.size());
+    }
+    return NO_ERROR;
+}
+
+// dump headers
+void MediaMetricsService::dumpHeaders(String8 &result, int64_t sinceNs, const char* prefix)
+{
+    if (mediametrics::Item::isEnabled()) {
+        result.append("Metrics gathering: enabled\n");
+    } else {
+        result.append("Metrics gathering: DISABLED via property\n");
+    }
+    result.appendFormat(
+            "Since Boot: Submissions: %lld Accepted: %lld\n",
+            (long long)mItemsSubmitted.load(), (long long)mItemsFinalized);
+    result.appendFormat(
+            "Records Discarded: %lld (by Count: %lld by Expiration: %lld)\n",
+            (long long)mItemsDiscarded, (long long)mItemsDiscardedCount,
+            (long long)mItemsDiscardedExpire);
+    if (prefix != nullptr) {
+        result.appendFormat("Restricting to prefix %s", prefix);
+    }
+    if (sinceNs != 0) {
+        result.appendFormat(
+            "Emitting Queue entries more recent than: %lld\n",
+            (long long)sinceNs);
+    }
+}
+
+// TODO: should prefix be a set<string>?
+void MediaMetricsService::dumpQueue(String8 &result, int64_t sinceNs, const char* prefix)
+{
+    if (mItems.empty()) {
+        result.append("empty\n");
+        return;
+    }
+
+    int slot = 0;
+    for (const auto &item : mItems) {         // TODO: consider std::lower_bound() on mItems
+        if (item->getTimestamp() < sinceNs) { // sinceNs == 0 means all items shown
+            continue;
+        }
+        if (prefix != nullptr && !startsWith(item->getKey(), prefix)) {
+            ALOGV("%s: omit '%s', it's not '%s'",
+                    __func__, item->getKey().c_str(), prefix);
+            continue;
+        }
+        result.appendFormat("%5d: %s\n", slot, item->toString().c_str());
+        slot++;
+    }
+}
+
+//
+// Our Cheap in-core, non-persistent records management.
+
+// if item != NULL, it's the item we just inserted
+// true == more items eligible to be recovered
+bool MediaMetricsService::expirations(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    bool more = false;
+
+    // check queue size
+    size_t overlimit = 0;
+    if (mMaxRecords > 0 && mItems.size() > mMaxRecords) {
+        overlimit = mItems.size() - mMaxRecords;
+        if (overlimit > mMaxRecordsExpiredAtOnce) {
+            more = true;
+            overlimit = mMaxRecordsExpiredAtOnce;
+        }
+    }
+
+    // check queue times
+    size_t expired = 0;
+    if (!more && mMaxRecordAgeNs > 0) {
+        const nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
+        // we check one at a time, skip search would be more efficient.
+        size_t i = overlimit;
+        for (; i < mItems.size(); ++i) {
+            auto &oitem = mItems[i];
+            nsecs_t when = oitem->getTimestamp();
+            if (oitem.get() == item.get()) {
+                break;
+            }
+            if (now > when && (now - when) <= mMaxRecordAgeNs) {
+                break; // Note SYSTEM_TIME_REALTIME may not be monotonic.
+            }
+            if (i >= mMaxRecordsExpiredAtOnce) {
+                // this represents "one too many"; tell caller there are
+                // more to be reclaimed.
+                more = true;
+                break;
+            }
+        }
+        expired = i - overlimit;
+    }
+
+    if (const size_t toErase = overlimit + expired;
+            toErase > 0) {
+        mItemsDiscardedCount += overlimit;
+        mItemsDiscardedExpire += expired;
+        mItemsDiscarded += toErase;
+        mItems.erase(mItems.begin(), mItems.begin() + toErase); // erase from front
+    }
+    return more;
+}
+
+void MediaMetricsService::processExpirations()
+{
+    bool more;
+    do {
+        sleep(1);
+        std::lock_guard _l(mLock);
+        more = expirations(nullptr);
+    } while (more);
+}
+
+void MediaMetricsService::saveItem(const std::shared_ptr<const mediametrics::Item>& item)
+{
+    std::lock_guard _l(mLock);
+    // we assume the items are roughly in time order.
+    mItems.emplace_back(item);
+    ++mItemsFinalized;
+    if (expirations(item)
+            && (!mExpireFuture.valid()
+               || mExpireFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)) {
+        mExpireFuture = std::async(std::launch::async, [this] { processExpirations(); });
+    }
+}
+
+/* static */
+bool MediaMetricsService::isContentValid(const mediametrics::Item *item, bool isTrusted)
+{
+    if (isTrusted) return true;
+    // untrusted uids can only send us a limited set of keys
+    const std::string &key = item->getKey();
+    if (startsWith(key, "audio.")) return true;
+    if (startsWith(key, "drm.vendor.")) return true;
+    // the list of allowedKey uses statsd_handlers
+    // in iface_statsd.cpp as reference
+    // drmmanager is from a trusted uid, therefore not needed here
+    for (const char *allowedKey : {
+                                     // legacy audio
+                                     "audiopolicy",
+                                     "audiorecord",
+                                     "audiothread",
+                                     "audiotrack",
+                                     // other media
+                                     "codec",
+                                     "extractor",
+                                     "mediadrm",
+                                     "nuplayer",
+                                 }) {
+        if (key == allowedKey) {
+            return true;
+        }
+    }
+    ALOGD("%s: invalid key: %s", __func__, item->toString().c_str());
+    return false;
+}
+
+// are we rate limited, normally false
+bool MediaMetricsService::isRateLimited(mediametrics::Item *) const
+{
+    return false;
+}
+
+} // namespace android
diff --git a/services/mediametrics/MediaMetricsService.h b/services/mediametrics/MediaMetricsService.h
new file mode 100644
index 0000000..792b7f0
--- /dev/null
+++ b/services/mediametrics/MediaMetricsService.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <deque>
+#include <future>
+#include <mutex>
+#include <unordered_map>
+
+// IMediaMetricsService must include Vector, String16, Errors
+#include <android-base/thread_annotations.h>
+#include <media/IMediaMetricsService.h>
+#include <mediautils/ServiceUtilities.h>
+#include <utils/String8.h>
+
+#include "AudioAnalytics.h"
+
+namespace android {
+
+class MediaMetricsService : public BnMediaMetricsService
+{
+public:
+    MediaMetricsService();
+    ~MediaMetricsService() override;
+
+    /**
+     * Submits the indicated record to the mediaanalytics service.
+     *
+     * \param item the item to submit.
+     * \return status failure, which is negative on binder transaction failure.
+     *         As the transaction is one-way, remote failures will not be reported.
+     */
+    status_t submit(mediametrics::Item *item) override {
+        return submitInternal(item, false /* release */);
+    }
+
+    status_t submitBuffer(const char *buffer, size_t length) override {
+        mediametrics::Item *item = new mediametrics::Item();
+        return item->readFromByteString(buffer, length)
+                ?: submitInternal(item, true /* release */);
+    }
+
+    status_t dump(int fd, const Vector<String16>& args) override;
+
+    static constexpr const char * const kServiceName = "media.metrics";
+
+    /**
+     * Rounds time to the nearest second.
+     */
+    static nsecs_t roundTime(nsecs_t timeNs);
+
+    /**
+     * Returns true if we should use uid for package name when uploading to statsd.
+     */
+    static bool useUidForPackage(const std::string& package, const std::string& installer);
+
+    /**
+     * Returns a std::pair of packageName and versionCode for a given uid.
+     *
+     * The value is sanitized - i.e. if the result is not approved to send,
+     * we use the uid as a string and a version code of 0.
+     */
+    static std::pair<std::string, int64_t> getSanitizedPackageNameAndVersionCode(uid_t uid);
+
+protected:
+
+    // Internal call where release is true if ownership of item is transferred
+    // to the service (that is, the service will eventually delete the item).
+    status_t submitInternal(mediametrics::Item *item, bool release) override;
+
+private:
+    void processExpirations();
+    // input validation after arrival from client
+    static bool isContentValid(const mediametrics::Item *item, bool isTrusted);
+    bool isRateLimited(mediametrics::Item *) const;
+    void saveItem(const std::shared_ptr<const mediametrics::Item>& item);
+
+    bool expirations(const std::shared_ptr<const mediametrics::Item>& item) REQUIRES(mLock);
+
+    // support for generating output
+    void dumpQueue(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock);
+    void dumpHeaders(String8 &result, int64_t sinceNs, const char* prefix) REQUIRES(mLock);
+
+    // The following variables accessed without mLock
+
+    // limit how many records we'll retain
+    // by count (in each queue (open, finalized))
+    const size_t mMaxRecords;
+    // by time (none older than this)
+    const nsecs_t mMaxRecordAgeNs;
+    // max to expire per expirations_l() invocation
+    const size_t mMaxRecordsExpiredAtOnce;
+
+    std::atomic<int64_t> mItemsSubmitted{}; // accessed outside of lock.
+
+    mediametrics::AudioAnalytics mAudioAnalytics; // mAudioAnalytics is locked internally.
+
+    std::mutex mLock;
+    // statistics about our analytics
+    int64_t mItemsFinalized GUARDED_BY(mLock) = 0;
+    int64_t mItemsDiscarded GUARDED_BY(mLock) = 0;
+    int64_t mItemsDiscardedExpire GUARDED_BY(mLock) = 0;
+    int64_t mItemsDiscardedCount GUARDED_BY(mLock) = 0;
+
+    // If we have a worker thread to garbage collect
+    std::future<void> mExpireFuture GUARDED_BY(mLock);
+
+    // Our item queue, generally (oldest at front)
+    // TODO: Make separate class, use segmented queue, write lock only end.
+    // Note: Another analytics module might have ownership of an item longer than the log.
+    std::deque<std::shared_ptr<const mediametrics::Item>> mItems GUARDED_BY(mLock);
+};
+
+} // namespace android
diff --git a/services/mediametrics/OWNERS b/services/mediametrics/OWNERS
new file mode 100644
index 0000000..e37a1f8
--- /dev/null
+++ b/services/mediametrics/OWNERS
@@ -0,0 +1,2 @@
+essick@google.com
+hunga@google.com
diff --git a/services/mediametrics/StringUtils.cpp b/services/mediametrics/StringUtils.cpp
new file mode 100644
index 0000000..50525bc
--- /dev/null
+++ b/services/mediametrics/StringUtils.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaMetricsService::stringutils"
+#include <utils/Log.h>
+
+#include "StringUtils.h"
+
+namespace android::mediametrics::stringutils {
+
+std::string tokenizer(std::string::const_iterator& it,
+        const std::string::const_iterator& end, const char *reserved)
+{
+    // consume leading white space
+    for (; it != end && std::isspace(*it); ++it);
+    if (it == end) return {};
+
+    auto start = it;
+    // parse until we hit a reserved keyword or space
+    if (strchr(reserved, *it)) return {start, ++it};
+    for (;;) {
+        ++it;
+        if (it == end || std::isspace(*it) || strchr(reserved, *it)) return {start, it};
+    }
+}
+
+std::vector<std::string> split(const std::string& flags, const char *delim)
+{
+    std::vector<std::string> result;
+    for (auto it = flags.begin(); ; ) {
+        auto flag = tokenizer(it, flags.end(), delim);
+        if (flag.empty() || !std::isalnum(flag[0])) return result;
+        result.emplace_back(std::move(flag));
+
+        // look for the delimeter and discard
+        auto token = tokenizer(it, flags.end(), delim);
+        if (token.size() != 1 || strchr(delim, token[0]) == nullptr) return result;
+    }
+}
+
+std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string& devices)
+{
+    std::vector<std::pair<std::string, std::string>> result;
+
+    // Currently, the device format is EXACTLY
+    // (device1, addr1)|(device2, addr2)|...
+
+    static constexpr char delim[] = "()|,";
+    for (auto it = devices.begin(); ; ) {
+        auto token = tokenizer(it, devices.end(), delim);
+        if (token != "(") return result;
+
+        auto device = tokenizer(it, devices.end(), delim);
+        if (device.empty() || !std::isalnum(device[0])) return result;
+
+        token = tokenizer(it, devices.end(), delim);
+        if (token != ",") return result;
+
+        // special handling here for empty addresses
+        auto address = tokenizer(it, devices.end(), delim);
+        if (address.empty() || !std::isalnum(device[0])) return result;
+        if (address == ")") {  // no address, just the ")"
+            address.clear();
+        } else {
+            token = tokenizer(it, devices.end(), delim);
+            if (token != ")") return result;
+        }
+
+        result.emplace_back(std::move(device), std::move(address));
+
+        token = tokenizer(it, devices.end(), delim);
+        if (token != "|") return result;  // this includes end of string detection
+    }
+}
+
+size_t replace(std::string &str, const char *targetChars, const char replaceChar)
+{
+    size_t replaced = 0;
+    for (char &c : str) {
+        if (strchr(targetChars, c) != nullptr) {
+            c = replaceChar;
+            ++replaced;
+        }
+    }
+    return replaced;
+}
+
+} // namespace android::mediametrics::stringutils
diff --git a/services/mediametrics/StringUtils.h b/services/mediametrics/StringUtils.h
new file mode 100644
index 0000000..7a8bbee
--- /dev/null
+++ b/services/mediametrics/StringUtils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace android::mediametrics::stringutils {
+
+/**
+ * fieldPrint is a helper method that logs to a stringstream a sequence of
+ * field names (in a fixed size array) together with a variable number of arg parameters.
+ *
+ * stringstream << field[0] << ":" << arg0 << " ";
+ * stringstream << field[1] << ":" << arg1 << " ";
+ * ...
+ * stringstream << field[N-1] << ":" << arg{N-1} << " ";
+ *
+ * The number of fields must exactly match the (variable) arguments.
+ *
+ * Example:
+ *
+ * const char * const fields[] = { "integer" };
+ * std::stringstream ss;
+ * fieldPrint(ss, fields, int(10));
+ */
+template <size_t N, typename... Targs>
+void fieldPrint(std::stringstream& ss, const char * const (& fields)[N], Targs... args) {
+    static_assert(N == sizeof...(args));          // guarantee #fields == #args
+    auto fptr = fields;                           // get a pointer to the base of fields array
+    ((ss << *fptr++ << ":" << args << " "), ...); // (fold expression), send to stringstream.
+}
+
+/**
+ * Return string tokens from iterator, separated by spaces and reserved chars.
+ */
+std::string tokenizer(std::string::const_iterator& it,
+        const std::string::const_iterator& end, const char *reserved);
+
+/**
+ * Splits flags string based on delimeters (or, whitespace which is removed).
+ */
+std::vector<std::string> split(const std::string& flags, const char *delim);
+
+/**
+ * Parse the devices string and return a vector of device address pairs.
+ *
+ * A failure to parse returns early with the contents that were able to be parsed.
+ */
+std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string &devices);
+
+/**
+ * Replaces targetChars with replaceChar in string, returns number of chars replaced.
+ */
+size_t replace(std::string &str, const char *targetChars, const char replaceChar);
+
+} // namespace android::mediametrics::stringutils
diff --git a/services/mediametrics/TEST_MAPPING b/services/mediametrics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/services/mediametrics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+       "name": "mediametrics_tests"
+    },
+    {
+       "name": "CtsNativeMediaMetricsTestCases"
+    }
+  ]
+}
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
new file mode 100644
index 0000000..ce579b3
--- /dev/null
+++ b/services/mediametrics/TimeMachine.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <any>
+#include <map>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <variant>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <media/MediaMetricsItem.h>
+#include <utils/Timers.h>
+
+namespace android::mediametrics {
+
+// define a way of printing the monostate
+inline std::ostream & operator<< (std::ostream& s,
+                           std::monostate const& v __unused) {
+    s << "none_item";
+    return s;
+}
+
+// define a way of printing a std::pair.
+template <typename T, typename U>
+std::ostream & operator<< (std::ostream& s,
+                           const std::pair<T, U>& v) {
+    s << "{ " << v.first << ", " << v.second << " }";
+    return s;
+}
+
+// define a way of printing a variant
+// see https://en.cppreference.com/w/cpp/utility/variant/visit
+template <typename T0, typename ... Ts>
+std::ostream & operator<< (std::ostream& s,
+                           std::variant<T0, Ts...> const& v) {
+    std::visit([&s](auto && arg){ s << std::forward<decltype(arg)>(arg); }, v);
+    return s;
+}
+
+/**
+ * The TimeMachine is used to record timing changes of MediaAnalyticItem
+ * properties.
+ *
+ * Any URL that ends with '#' (AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED)
+ * will have a time sequence that keeps duplicates.
+ *
+ * The TimeMachine is NOT thread safe.
+ */
+class TimeMachine final { // made final as we have copy constructor instead of dup() override.
+public:
+    using Elem = Item::Prop::Elem;  // use the Item property element.
+    using PropertyHistory = std::multimap<int64_t /* time */, Elem>;
+
+private:
+
+    // KeyHistory contains no lock.
+    // Access is through the TimeMachine, and a hash-striped lock is used
+    // before calling into KeyHistory.
+    class KeyHistory  {
+    public:
+        template <typename T>
+        KeyHistory(T key, uid_t allowUid, int64_t time)
+            : mKey(key)
+            , mAllowUid(allowUid)
+            , mCreationTime(time)
+            , mLastModificationTime(time)
+        {
+            (void)mCreationTime; // suppress unused warning.
+
+            // allowUid allows an untrusted client with a matching uid to set properties
+            // in this key.
+            // If allowUid == (uid_t)-1, no untrusted client may set properties in the key.
+            if (allowUid != (uid_t)-1) {
+                // Set ALLOWUID property here; does not change after key creation.
+                putValue(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)allowUid, time);
+            }
+        }
+
+        KeyHistory(const KeyHistory &other) = default;
+
+        // Return NO_ERROR only if the passed in uidCheck is -1 or matches
+        // the internal mAllowUid.
+        // An external submit will always have a valid uidCheck parameter.
+        // An internal get request within mediametrics will have a uidCheck == -1 which
+        // we allow to proceed.
+        status_t checkPermission(uid_t uidCheck) const {
+            return uidCheck != (uid_t)-1 && uidCheck != mAllowUid ? PERMISSION_DENIED : NO_ERROR;
+        }
+
+        template <typename T>
+        status_t getValue(const std::string &property, T* value, int64_t time = 0) const
+                REQUIRES(mPseudoKeyHistoryLock) {
+            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
+            const auto tsptr = mPropertyMap.find(property);
+            if (tsptr == mPropertyMap.end()) return BAD_VALUE;
+            const auto& timeSequence = tsptr->second;
+            auto eptr = timeSequence.upper_bound(time);
+            if (eptr == timeSequence.begin()) return BAD_VALUE;
+            --eptr;
+            if (eptr == timeSequence.end()) return BAD_VALUE;
+            const T* vptr = std::get_if<T>(&eptr->second);
+            if (vptr == nullptr) return BAD_VALUE;
+            *value = *vptr;
+            return NO_ERROR;
+        }
+
+        template <typename T>
+        status_t getValue(const std::string &property, T defaultValue, int64_t time = 0) const
+                REQUIRES(mPseudoKeyHistoryLock){
+            T value;
+            return getValue(property, &value, time) != NO_ERROR ? defaultValue : value;
+        }
+
+        void putProp(
+                const std::string &name, const mediametrics::Item::Prop &prop, int64_t time = 0)
+                REQUIRES(mPseudoKeyHistoryLock) {
+            //alternatively: prop.visit([&](auto value) { putValue(name, value, time); });
+            putValue(name, prop.get(), time);
+        }
+
+        template <typename T>
+        void putValue(const std::string &property, T&& e, int64_t time = 0)
+                REQUIRES(mPseudoKeyHistoryLock) {
+            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
+            mLastModificationTime = time;
+            if (mPropertyMap.size() >= kKeyMaxProperties &&
+                    !mPropertyMap.count(property)) {
+                ALOGV("%s: too many properties, rejecting %s", __func__, property.c_str());
+                return;
+            }
+            auto& timeSequence = mPropertyMap[property];
+            Elem el{std::forward<T>(e)};
+            if (timeSequence.empty()           // no elements
+                    || property.back() == AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED
+                    || timeSequence.rbegin()->second != el) { // value changed
+                timeSequence.emplace_hint(timeSequence.end(), time, std::move(el));
+
+                if (timeSequence.size() > kTimeSequenceMaxElements) {
+                    ALOGV("%s: restricting maximum elements (discarding oldest) for %s",
+                            __func__, property.c_str());
+                    timeSequence.erase(timeSequence.begin());
+                }
+            }
+        }
+
+        std::pair<std::string, int32_t> dump(int32_t lines, int64_t time) const
+                REQUIRES(mPseudoKeyHistoryLock) {
+            std::stringstream ss;
+            int32_t ll = lines;
+            for (auto& tsPair : mPropertyMap) {
+                if (ll <= 0) break;
+                std::string s = dump(mKey, tsPair, time);
+                if (s.size() > 0) {
+                    --ll;
+                    ss << s;
+                }
+            }
+            return { ss.str(), lines - ll };
+        }
+
+        int64_t getLastModificationTime() const REQUIRES(mPseudoKeyHistoryLock) {
+            return mLastModificationTime;
+        }
+
+    private:
+        static std::string dump(
+                const std::string &key,
+                const std::pair<std::string /* prop */, PropertyHistory>& tsPair,
+                int64_t time) {
+            const auto timeSequence = tsPair.second;
+            auto eptr = timeSequence.lower_bound(time);
+            if (eptr == timeSequence.end()) {
+                return {}; // don't dump anything. tsPair.first + "={};\n";
+            }
+            std::stringstream ss;
+            ss << key << "." << tsPair.first << "={";
+
+            time_string_t last_timestring{}; // last timestring used.
+            while (true) {
+                const time_string_t timestring = mediametrics::timeStringFromNs(eptr->first);
+                // find common prefix offset.
+                const size_t offset = commonTimePrefixPosition(timestring.time,
+                        last_timestring.time);
+                last_timestring = timestring;
+                ss << "(" << (offset == 0 ? "" : "~") << &timestring.time[offset]
+                    << ") " << eptr->second;
+                if (++eptr == timeSequence.end()) {
+                    break;
+                }
+                ss << ", ";
+            }
+            ss << "};\n";
+            return ss.str();
+        }
+
+        const std::string mKey;
+        const uid_t mAllowUid;
+        const int64_t mCreationTime;
+
+        int64_t mLastModificationTime;
+        std::map<std::string /* property */, PropertyHistory> mPropertyMap;
+    };
+
+    using History = std::map<std::string /* key */, std::shared_ptr<KeyHistory>>;
+
+    static inline constexpr size_t kTimeSequenceMaxElements = 50;
+    static inline constexpr size_t kKeyMaxProperties = 50;
+    static inline constexpr size_t kKeyLowWaterMark = 400;
+    static inline constexpr size_t kKeyHighWaterMark = 500;
+
+    // Estimated max data space usage is 3KB * kKeyHighWaterMark.
+
+public:
+
+    TimeMachine() = default;
+    TimeMachine(size_t keyLowWaterMark, size_t keyHighWaterMark)
+        : mKeyLowWaterMark(keyLowWaterMark)
+        , mKeyHighWaterMark(keyHighWaterMark) {
+        LOG_ALWAYS_FATAL_IF(keyHighWaterMark <= keyLowWaterMark,
+              "%s: required that keyHighWaterMark:%zu > keyLowWaterMark:%zu",
+                  __func__, keyHighWaterMark, keyLowWaterMark);
+    }
+
+    // The TimeMachine copy constructor/assignment uses a deep copy,
+    // though the snapshot is not instantaneous nor isochronous.
+    //
+    // If there are concurrent operations ongoing in the other TimeMachine
+    // then there may be some history more recent than others (a time shear).
+    // This is expected to be a benign addition in history as small number of
+    // future elements are incorporated.
+    TimeMachine(const TimeMachine& other) {
+        *this = other;
+    }
+    TimeMachine& operator=(const TimeMachine& other) {
+        std::lock_guard lock(mLock);
+        mHistory.clear();
+
+        {
+            std::lock_guard lock2(other.mLock);
+            mHistory = other.mHistory;
+            mGarbageCollectionCount = other.mGarbageCollectionCount.load();
+        }
+
+        // Now that we safely have our own shared pointers, let's dup them
+        // to ensure they are decoupled.  We do this by acquiring the other lock.
+        for (const auto &[lkey, lhist] : mHistory) {
+            std::lock_guard lock2(other.getLockForKey(lkey));
+            mHistory[lkey] = std::make_shared<KeyHistory>(*lhist);
+        }
+        return *this;
+    }
+
+    /**
+     * Put all the properties from an item into the Time Machine log.
+     */
+    status_t put(const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted = false) {
+        const int64_t time = item->getTimestamp();
+        const std::string &key = item->getKey();
+
+        ALOGV("%s(%zu, %zu): key: %s  isTrusted:%d  size:%zu",
+                __func__, mKeyLowWaterMark, mKeyHighWaterMark,
+                key.c_str(), (int)isTrusted, item->count());
+        std::shared_ptr<KeyHistory> keyHistory;
+        {
+            std::vector<std::any> garbage;
+            std::lock_guard lock(mLock);
+
+            auto it = mHistory.find(key);
+            if (it == mHistory.end()) {
+                if (!isTrusted) return PERMISSION_DENIED;
+
+                (void)gc(garbage);
+
+                // We set the allowUid for client access on key creation.
+                int32_t allowUid = -1;
+                (void)item->get(AMEDIAMETRICS_PROP_ALLOWUID, &allowUid);
+                // no keylock needed here as we are sole owner
+                // until placed on mHistory.
+                keyHistory = std::make_shared<KeyHistory>(
+                    key, allowUid, time);
+                mHistory[key] = keyHistory;
+            } else {
+                keyHistory = it->second;
+            }
+        }
+
+        // deferred contains remote properties (for other keys) to do later.
+        std::vector<const mediametrics::Item::Prop *> deferred;
+        {
+            // handle local properties
+            std::lock_guard lock(getLockForKey(key));
+            if (!isTrusted) {
+                status_t status = keyHistory->checkPermission(item->getUid());
+                if (status != NO_ERROR) return status;
+            }
+
+            for (const auto &prop : *item) {
+                const std::string &name = prop.getName();
+                if (name.size() == 0 || name[0] == '_') continue;
+
+                // Cross key settings are with [key]property
+                if (name[0] == '[') {
+                    if (!isTrusted) continue;
+                    deferred.push_back(&prop);
+                } else {
+                    keyHistory->putProp(name, prop, time);
+                }
+            }
+        }
+
+        // handle remote properties, if any
+        for (const auto propptr : deferred) {
+            const auto &prop = *propptr;
+            const std::string &name = prop.getName();
+            size_t end = name.find_first_of(']'); // TODO: handle nested [] or escape?
+            if (end == 0) continue;
+            std::string remoteKey = name.substr(1, end - 1);
+            std::string remoteName = name.substr(end + 1);
+            if (remoteKey.size() == 0 || remoteName.size() == 0) continue;
+            std::shared_ptr<KeyHistory> remoteKeyHistory;
+            {
+                std::lock_guard lock(mLock);
+                auto it = mHistory.find(remoteKey);
+                if (it == mHistory.end()) continue;
+                remoteKeyHistory = it->second;
+            }
+            std::lock_guard lock(getLockForKey(remoteKey));
+            remoteKeyHistory->putProp(remoteName, prop, time);
+        }
+        return NO_ERROR;
+    }
+
+    template <typename T>
+    status_t get(const std::string &key, const std::string &property,
+            T* value, int32_t uidCheck = -1, int64_t time = 0) const {
+        std::shared_ptr<KeyHistory> keyHistory;
+        {
+            std::lock_guard lock(mLock);
+            const auto it = mHistory.find(key);
+            if (it == mHistory.end()) return BAD_VALUE;
+            keyHistory = it->second;
+        }
+        std::lock_guard lock(getLockForKey(key));
+        return keyHistory->checkPermission(uidCheck)
+                ?: keyHistory->getValue(property, value, time);
+    }
+
+    /**
+     * Individual property put.
+     *
+     * Put takes in a time (if none is provided then SYSTEM_TIME_REALTIME is used).
+     */
+    template <typename T>
+    status_t put(const std::string &url, T &&e, int64_t time = 0) {
+        std::string key;
+        std::string prop;
+        std::shared_ptr<KeyHistory> keyHistory =
+            getKeyHistoryFromUrl(url, &key, &prop);
+        if (keyHistory == nullptr) return BAD_VALUE;
+        if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
+        std::lock_guard lock(getLockForKey(key));
+        keyHistory->putValue(prop, std::forward<T>(e), time);
+        return NO_ERROR;
+    }
+
+    /**
+     * Individual property get
+     */
+    template <typename T>
+    status_t get(const std::string &url, T* value, int32_t uidCheck, int64_t time = 0) const {
+        std::string key;
+        std::string prop;
+        std::shared_ptr<KeyHistory> keyHistory =
+            getKeyHistoryFromUrl(url, &key, &prop);
+        if (keyHistory == nullptr) return BAD_VALUE;
+
+        std::lock_guard lock(getLockForKey(key));
+        return keyHistory->checkPermission(uidCheck)
+               ?: keyHistory->getValue(prop, value, time);
+    }
+
+    /**
+     * Individual property get with default
+     */
+    template <typename T>
+    T get(const std::string &url, const T &defaultValue, int32_t uidCheck,
+            int64_t time = 0) const {
+        T value;
+        return get(url, &value, uidCheck, time) == NO_ERROR
+                ? value : defaultValue;
+    }
+
+    /**
+     *  Returns number of keys in the Time Machine.
+     */
+    size_t size() const {
+        std::lock_guard lock(mLock);
+        return mHistory.size();
+    }
+
+    /**
+     * Clears all properties from the Time Machine.
+     */
+    void clear() {
+        std::lock_guard lock(mLock);
+        mHistory.clear();
+        mGarbageCollectionCount = 0;
+    }
+
+    /**
+     * Returns a pair consisting of the TimeMachine state as a string
+     * and the number of lines in the string.
+     *
+     * The number of lines in the returned pair is used as an optimization
+     * for subsequent line limiting.
+     *
+     * \param lines the maximum number of lines in the string returned.
+     * \param key selects only that key.
+     * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+     * \param prefix the desired key prefix to match (nullptr shows all)
+     */
+    std::pair<std::string, int32_t> dump(
+            int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
+        std::lock_guard lock(mLock);
+        std::stringstream ss;
+        int32_t ll = lines;
+
+        for (auto it = prefix != nullptr ? mHistory.lower_bound(prefix) : mHistory.begin();
+                it != mHistory.end();
+                ++it) {
+            if (ll <= 0) break;
+            if (prefix != nullptr && !startsWith(it->first, prefix)) break;
+            std::lock_guard lock2(getLockForKey(it->first));
+            auto [s, l] = it->second->dump(ll, sinceNs);
+            ss << s;
+            ll -= l;
+        }
+        return { ss.str(), lines - ll };
+    }
+
+    size_t getGarbageCollectionCount() const {
+        return mGarbageCollectionCount;
+    }
+
+private:
+
+    // Obtains the lock for a KeyHistory.
+    std::mutex &getLockForKey(const std::string &key) const
+            RETURN_CAPABILITY(mPseudoKeyHistoryLock) {
+        return mKeyLocks[std::hash<std::string>{}(key) % std::size(mKeyLocks)];
+    }
+
+    // Finds a KeyHistory from a URL.  Returns nullptr if not found.
+    std::shared_ptr<KeyHistory> getKeyHistoryFromUrl(
+            const std::string& url, std::string* key, std::string *prop) const {
+        std::lock_guard lock(mLock);
+
+        auto it = mHistory.upper_bound(url);
+        if (it == mHistory.begin()) {
+           return nullptr;
+        }
+        --it;  // go to the actual key, if it exists.
+
+        const std::string& itKey = it->first;
+        if (strncmp(itKey.c_str(), url.c_str(), itKey.size())) {
+            return nullptr;
+        }
+        if (key) *key = itKey;
+        if (prop) *prop = url.substr(itKey.size() + 1);
+        return it->second;
+    }
+
+    /**
+     * Garbage collects if the TimeMachine size exceeds the high water mark.
+     *
+     * This GC operation limits the number of keys stored (not the size of properties
+     * stored in each key).
+     *
+     * \param garbage a type-erased vector of elements to be destroyed
+     *        outside of lock.  Move large items to be destroyed here.
+     *
+     * \return true if garbage collection was done.
+     */
+    bool gc(std::vector<std::any>& garbage) REQUIRES(mLock) {
+        // TODO: something better than this for garbage collection.
+        if (mHistory.size() < mKeyHighWaterMark) return false;
+
+        // erase everything explicitly expired.
+        std::multimap<int64_t, std::string> accessList;
+        // use a stale vector with precise type to avoid type erasure overhead in garbage
+        std::vector<std::shared_ptr<KeyHistory>> stale;
+
+        for (auto it = mHistory.begin(); it != mHistory.end();) {
+            const std::string& key = it->first;
+            std::shared_ptr<KeyHistory> &keyHist = it->second;
+
+            std::lock_guard lock(getLockForKey(it->first));
+            int64_t expireTime = keyHist->getValue("_expire", -1 /* default */);
+            if (expireTime != -1) {
+                stale.emplace_back(std::move(it->second));
+                it = mHistory.erase(it);
+            } else {
+                accessList.emplace(keyHist->getLastModificationTime(), key);
+                ++it;
+            }
+        }
+
+        if (mHistory.size() > mKeyLowWaterMark) {
+           const size_t toDelete = mHistory.size() - mKeyLowWaterMark;
+           auto it = accessList.begin();
+           for (size_t i = 0; i < toDelete; ++i) {
+               auto it2 = mHistory.find(it->second);
+               stale.emplace_back(std::move(it2->second));
+               mHistory.erase(it2);
+               ++it;
+           }
+        }
+        garbage.emplace_back(std::move(accessList));
+        garbage.emplace_back(std::move(stale));
+
+        ALOGD("%s(%zu, %zu): key size:%zu",
+                __func__, mKeyLowWaterMark, mKeyHighWaterMark,
+                mHistory.size());
+
+        ++mGarbageCollectionCount;
+        return true;
+    }
+
+    const size_t mKeyLowWaterMark = kKeyLowWaterMark;
+    const size_t mKeyHighWaterMark = kKeyHighWaterMark;
+
+    std::atomic<size_t> mGarbageCollectionCount{};
+
+    /**
+     * Locking Strategy
+     *
+     * Each key in the History has a KeyHistory. To get a shared pointer to
+     * the KeyHistory requires a lookup of mHistory under mLock.  Once the shared
+     * pointer to KeyHistory is obtained, the mLock for mHistory can be released.
+     *
+     * Once the shared pointer to the key's KeyHistory is obtained, the KeyHistory
+     * can be locked for read and modification through the method getLockForKey().
+     *
+     * Instead of having a mutex per KeyHistory, we use a hash striped lock
+     * which assigns a mutex based on the hash of the key string.
+     *
+     * Once the last shared pointer reference to KeyHistory is released, it is
+     * destroyed.  This is done through the garbage collection method.
+     *
+     * This two level locking allows multiple threads to access the TimeMachine
+     * in parallel.
+     */
+
+    mutable std::mutex mLock;           // Lock for mHistory
+    History mHistory GUARDED_BY(mLock);
+
+    // KEY_LOCKS is the number of mutexes for keys.
+    // It need not be a power of 2, but faster that way.
+    static inline constexpr size_t KEY_LOCKS = 256;
+    mutable std::mutex mKeyLocks[KEY_LOCKS];  // Hash-striped lock for KeyHistory based on key.
+
+    // Used for thread-safety analysis, we create a fake mutex object to represent
+    // the hash stripe lock mechanism, which is then tracked by the compiler.
+    class CAPABILITY("mutex") PseudoLock {};
+    static inline PseudoLock mPseudoKeyHistoryLock;
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/TimedAction.h b/services/mediametrics/TimedAction.h
new file mode 100644
index 0000000..c7ef585
--- /dev/null
+++ b/services/mediametrics/TimedAction.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <chrono>
+#include <map>
+#include <mutex>
+#include <thread>
+
+namespace android::mediametrics {
+
+class TimedAction {
+public:
+    TimedAction() : mThread{[this](){threadLoop();}} {}
+
+    ~TimedAction() {
+        quit();
+    }
+
+    // TODO: return a handle for cancelling the action?
+    template <typename T> // T is in units of std::chrono::duration.
+    void postIn(const T& time, std::function<void()> f) {
+        postAt(std::chrono::steady_clock::now() + time, f);
+    }
+
+    template <typename T> // T is in units of std::chrono::time_point
+    void postAt(const T& targetTime, std::function<void()> f) {
+        std::lock_guard l(mLock);
+        if (mQuit) return;
+        if (mMap.empty() || targetTime < mMap.begin()->first) {
+            mMap.emplace_hint(mMap.begin(), targetTime, std::move(f));
+            mCondition.notify_one();
+        } else {
+            mMap.emplace(targetTime, std::move(f));
+        }
+    }
+
+    void clear() {
+        std::lock_guard l(mLock);
+        mMap.clear();
+    }
+
+    void quit() {
+        {
+            std::lock_guard l(mLock);
+            if (mQuit) return;
+            mQuit = true;
+            mMap.clear();
+            mCondition.notify_all();
+        }
+        mThread.join();
+    }
+
+    size_t size() const {
+        std::lock_guard l(mLock);
+        return mMap.size();
+    }
+
+private:
+    void threadLoop() NO_THREAD_SAFETY_ANALYSIS { // thread safety doesn't cover unique_lock
+        std::unique_lock l(mLock);
+        while (!mQuit) {
+            auto sleepUntilTime = std::chrono::time_point<std::chrono::steady_clock>::max();
+            if (!mMap.empty()) {
+                sleepUntilTime = mMap.begin()->first;
+                if (sleepUntilTime <= std::chrono::steady_clock::now()) {
+                    auto node = mMap.extract(mMap.begin()); // removes from mMap.
+                    l.unlock();
+                    node.mapped()();
+                    l.lock();
+                    continue;
+                }
+            }
+            mCondition.wait_until(l, sleepUntilTime);
+        }
+    }
+
+    mutable std::mutex mLock;
+    std::condition_variable mCondition GUARDED_BY(mLock);
+    bool mQuit GUARDED_BY(mLock) = false;
+    std::multimap<std::chrono::time_point<std::chrono::steady_clock>, std::function<void()>>
+            mMap GUARDED_BY(mLock); // multiple functions could execute at the same time.
+
+    // needs to be initialized after the variables above, done in constructor initializer list.
+    std::thread mThread;
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/TransactionLog.h b/services/mediametrics/TransactionLog.h
new file mode 100644
index 0000000..0ca4639
--- /dev/null
+++ b/services/mediametrics/TransactionLog.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <any>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include <android-base/thread_annotations.h>
+#include <media/MediaMetricsItem.h>
+
+namespace android::mediametrics {
+
+/**
+ * The TransactionLog is used to record mediametrics::Items to present
+ * different views on the time information (selected by audio, and sorted by key).
+ *
+ * The TransactionLog will always present data in timestamp order. (Perhaps we
+ * just make this submit order).
+ *
+ * These Views have a cost in shared pointer storage, so they aren't quite free.
+ *
+ * The TransactionLog is NOT thread safe.
+ */
+class TransactionLog final { // made final as we have copy constructor instead of dup() override.
+public:
+    // In long term run, the garbage collector aims to keep the
+    // Transaction Log between the Low Water Mark and the High Water Mark.
+
+    // low water mark
+    static inline constexpr size_t kLogItemsLowWater = 1700;
+    // high water mark
+    static inline constexpr size_t kLogItemsHighWater = 2000;
+
+    // Estimated max data usage is 1KB * kLogItemsHighWater.
+
+    TransactionLog() = default;
+
+    TransactionLog(size_t lowWaterMark, size_t highWaterMark)
+        : mLowWaterMark(lowWaterMark)
+        , mHighWaterMark(highWaterMark) {
+        LOG_ALWAYS_FATAL_IF(highWaterMark <= lowWaterMark,
+              "%s: required that highWaterMark:%zu > lowWaterMark:%zu",
+                  __func__, highWaterMark, lowWaterMark);
+    }
+
+    // The TransactionLog copy constructor/assignment is effectively an
+    // instantaneous, isochronous snapshot of the other TransactionLog.
+    //
+    // The contents of the Transaction Log are shared pointers to immutable instances -
+    // std::shared_ptr<const mediametrics::Item>, so we use a shallow copy,
+    // which is more efficient in space and execution time than a deep copy,
+    // and gives the same results.
+
+    TransactionLog(const TransactionLog &other) {
+        *this = other;
+    }
+
+    TransactionLog& operator=(const TransactionLog &other) {
+        std::lock_guard lock(mLock);
+        mLog.clear();
+        mItemMap.clear();
+
+        std::lock_guard lock2(other.mLock);
+        mLog = other.mLog;
+        mItemMap = other.mItemMap;
+        mGarbageCollectionCount = other.mGarbageCollectionCount.load();
+
+        return *this;
+    }
+
+    /**
+     * Put an item in the TransactionLog.
+     */
+    status_t put(const std::shared_ptr<const mediametrics::Item>& item) {
+        const std::string& key = item->getKey();
+        const int64_t time = item->getTimestamp();
+
+        std::vector<std::any> garbage;  // objects destroyed after lock.
+        std::lock_guard lock(mLock);
+
+        (void)gc(garbage);
+        mLog.emplace_hint(mLog.end(), time, item);
+        mItemMap[key].emplace_hint(mItemMap[key].end(), time, item);
+        return NO_ERROR;  // no errors for now.
+    }
+
+    /**
+     * Returns all records within [startTime, endTime]
+     */
+    std::vector<std::shared_ptr<const mediametrics::Item>> get(
+            int64_t startTime = 0, int64_t endTime = INT64_MAX) const {
+        std::lock_guard lock(mLock);
+        return getItemsInRange(mLog, startTime, endTime);
+    }
+
+    /**
+     * Returns all records for a key within [startTime, endTime]
+     */
+    std::vector<std::shared_ptr<const mediametrics::Item>> get(
+            const std::string& key,
+            int64_t startTime = 0, int64_t endTime = INT64_MAX) const {
+        std::lock_guard lock(mLock);
+        auto mapIt = mItemMap.find(key);
+        if (mapIt == mItemMap.end()) return {};
+        return getItemsInRange(mapIt->second, startTime, endTime);
+    }
+
+    /**
+     * Returns a pair consisting of the Transaction Log as a string
+     * and the number of lines in the string.
+     *
+     * The number of lines in the returned pair is used as an optimization
+     * for subsequent line limiting.
+     *
+     * \param lines the maximum number of lines in the string returned.
+     * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
+     * \param prefix the desired key prefix to match (nullptr shows all)
+     */
+    std::pair<std::string, int32_t> dump(
+            int32_t lines, int64_t sinceNs, const char *prefix = nullptr) const {
+        std::stringstream ss;
+        int32_t ll = lines;
+        std::lock_guard lock(mLock);
+
+        // All audio items in time order.
+        if (ll > 0) {
+            ss << "Consolidated:\n";
+            --ll;
+        }
+        auto [s, l] = dumpMapTimeItem(mLog, ll, sinceNs, prefix);
+        ss << s;
+        ll -= l;
+
+        // Grouped by item key (category)
+        if (ll > 0) {
+            ss << "Categorized:\n";
+            --ll;
+        }
+
+        for (auto it = prefix != nullptr ? mItemMap.lower_bound(prefix) : mItemMap.begin();
+                it != mItemMap.end();
+                ++it) {
+            if (ll <= 0) break;
+            if (prefix != nullptr && !startsWith(it->first, prefix)) break;
+            auto [s, l] = dumpMapTimeItem(it->second, ll - 1, sinceNs, prefix);
+            if (l == 0) continue; // don't show empty groups (due to sinceNs).
+            ss << " " << it->first << "\n" << s;
+            ll -= l + 1;
+        }
+        return { ss.str(), lines - ll };
+    }
+
+    /**
+     *  Returns number of Items in the TransactionLog.
+     */
+    size_t size() const {
+        std::lock_guard lock(mLock);
+        return mLog.size();
+    }
+
+    /**
+     * Clears all Items from the TransactionLog.
+     */
+    // TODO: Garbage Collector, sweep and expire old values
+    void clear() {
+        std::lock_guard lock(mLock);
+        mLog.clear();
+        mItemMap.clear();
+        mGarbageCollectionCount = 0;
+    }
+
+    size_t getGarbageCollectionCount() const {
+        return mGarbageCollectionCount;
+    }
+
+private:
+    using MapTimeItem =
+            std::multimap<int64_t /* time */, std::shared_ptr<const mediametrics::Item>>;
+
+    static std::pair<std::string, int32_t> dumpMapTimeItem(
+            const MapTimeItem& mapTimeItem,
+            int32_t lines, int64_t sinceNs = 0, const char *prefix = nullptr) {
+        std::stringstream ss;
+        int32_t ll = lines;
+        // Note: for our data, mapTimeItem.lower_bound(0) == mapTimeItem.begin().
+        for (auto it = mapTimeItem.lower_bound(sinceNs);
+                it != mapTimeItem.end(); ++it) {
+            if (ll <= 0) break;
+            if (prefix != nullptr && !startsWith(it->second->getKey(), prefix)) {
+                continue;
+            }
+            ss << "  " << it->second->toString() << "\n";
+            --ll;
+        }
+        return { ss.str(), lines - ll };
+    }
+
+    /**
+     * Garbage collects if the TimeMachine size exceeds the high water mark.
+     *
+     * \param garbage a type-erased vector of elements to be destroyed
+     *        outside of lock.  Move large items to be destroyed here.
+     *
+     * \return true if garbage collection was done.
+     */
+    bool gc(std::vector<std::any>& garbage) REQUIRES(mLock) {
+        if (mLog.size() < mHighWaterMark) return false;
+
+        auto eraseEnd = mLog.begin();
+        size_t toRemove = mLog.size() - mLowWaterMark;
+        // remove at least those elements.
+
+        // use a stale vector with precise type to avoid type erasure overhead in garbage
+        std::vector<std::shared_ptr<const mediametrics::Item>> stale;
+
+        for (size_t i = 0; i < toRemove; ++i) {
+            stale.emplace_back(std::move(eraseEnd->second));
+            ++eraseEnd; // amortized O(1)
+        }
+        // ensure that eraseEnd is an lower bound on timeToErase.
+        const int64_t timeToErase = eraseEnd->first;
+        while (eraseEnd != mLog.end()) {
+            auto it = eraseEnd;
+            --it;  // amortized O(1)
+            if (it->first != timeToErase) {
+                break;  // eraseEnd represents a unique time jump.
+            }
+            stale.emplace_back(std::move(eraseEnd->second));
+            ++eraseEnd;
+        }
+
+        mLog.erase(mLog.begin(), eraseEnd);  // O(ptr_diff)
+
+        size_t itemMapCount = 0;
+        for (auto it = mItemMap.begin(); it != mItemMap.end();) {
+            auto &keyHist = it->second;
+            auto it2 = keyHist.lower_bound(timeToErase);
+            if (it2 == keyHist.end()) {
+                garbage.emplace_back(std::move(keyHist)); // directly move keyhist to garbage
+                it = mItemMap.erase(it);
+            } else {
+                for (auto it3 = keyHist.begin(); it3 != it2; ++it3) {
+                    stale.emplace_back(std::move(it3->second));
+                }
+                keyHist.erase(keyHist.begin(), it2);
+                itemMapCount += keyHist.size();
+                 ++it;
+            }
+        }
+
+        garbage.emplace_back(std::move(stale));
+
+        ALOGD("%s(%zu, %zu): log size:%zu item map size:%zu, item map items:%zu",
+                __func__, mLowWaterMark, mHighWaterMark,
+                mLog.size(), mItemMap.size(), itemMapCount);
+        ++mGarbageCollectionCount;
+        return true;
+    }
+
+    static std::vector<std::shared_ptr<const mediametrics::Item>> getItemsInRange(
+            const MapTimeItem& map,
+            int64_t startTime = 0, int64_t endTime = INT64_MAX) {
+        auto it = map.lower_bound(startTime);
+        if (it == map.end()) return {};
+
+        auto it2 = map.upper_bound(endTime);
+
+        std::vector<std::shared_ptr<const mediametrics::Item>> ret;
+        while (it != it2) {
+            ret.push_back(it->second);
+            ++it;
+        }
+        return ret;
+    }
+
+    const size_t mLowWaterMark = kLogItemsLowWater;
+    const size_t mHighWaterMark = kLogItemsHighWater;
+
+    std::atomic<size_t> mGarbageCollectionCount{};
+
+    mutable std::mutex mLock;
+
+    MapTimeItem mLog GUARDED_BY(mLock);
+    std::map<std::string /* item_key */, MapTimeItem> mItemMap GUARDED_BY(mLock);
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/Wrap.h b/services/mediametrics/Wrap.h
new file mode 100644
index 0000000..3584e08
--- /dev/null
+++ b/services/mediametrics/Wrap.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+
+namespace android::mediametrics {
+
+/**
+ * Wraps a shared-ptr for which member access through operator->() behaves
+ * as if the shared-ptr is atomically copied and then (without a lock) -> called.
+ *
+ * See related C++ 20:
+ * https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic2
+ *
+ * EXAMPLE:
+ *
+ * SharedPtrWrap<T> t{};
+ *
+ * thread1() {
+ *   t->func();  // safely executes either the original t or the one created by thread2.
+ * }
+ *
+ * thread2() {
+ *  t.set(std::make_shared<T>()); // overwrites the original t.
+ * }
+ */
+template <typename T>
+class SharedPtrWrap {
+    mutable std::mutex mLock;
+    std::shared_ptr<T> mPtr;
+
+public:
+    template <typename... Args>
+    explicit SharedPtrWrap(Args&&... args)
+        : mPtr(std::make_shared<T>(std::forward<Args>(args)...))
+    {}
+
+    /**
+     * Gets the current shared pointer.  This must return a value, not a reference.
+     *
+     * For compatibility with existing shared_ptr, we do not pass back a
+     * shared_ptr<const T> for the const getter.
+     */
+    std::shared_ptr<T> get() const {
+        std::lock_guard lock(mLock);
+        return mPtr;
+    }
+
+    /**
+     * Sets the current shared pointer, returning the previous shared pointer.
+     */
+    std::shared_ptr<T> set(std::shared_ptr<T> ptr) { // pass by value as we use swap.
+        std::lock_guard lock(mLock);
+        std::swap(ptr, mPtr);
+        return ptr;
+    }
+
+    /**
+     * Returns a shared pointer value representing T at the instant of time when
+     * the call executes. The lifetime of the shared pointer will
+     * be extended as we are returning an instance of the shared_ptr
+     * not a reference to it.  The destructor to the returned shared_ptr
+     * will be called sometime after the expression including the member function or
+     * the member variable is evaluated. Do not change to a reference!
+     */
+
+    // For compatibility with existing shared_ptr, we do not pass back a
+    // shared_ptr<const T> for the const operator pointer access.
+    std::shared_ptr<T> operator->() const {
+        return get();
+    }
+    /**
+     * We do not overload operator*() as the reference is not stable if the
+     * lock is not held.
+     */
+};
+
+/**
+ * Wraps member access to the class T by a lock.
+ *
+ * The object T is constructed within the LockWrap to guarantee
+ * locked access at all times.  When T's methods are accessed through ->,
+ * a monitor style lock is obtained to prevent multiple threads from executing
+ * methods in the object T at the same time.
+ * Suggested by Kevin R.
+ *
+ * EXAMPLE:
+ *
+ * // Accumulator class which is very slow, requires locking for multiple threads.
+ *
+ * class Accumulator {
+ *   int32_t value_ = 0;
+ * public:
+ *   void add(int32_t incr) {
+ *     const int32_t temp = value_;
+ *     sleep(0);  // yield
+ *     value_ = temp + incr;
+ *   }
+ *   int32_t get() { return value_; }
+ * };
+ *
+ * // We use LockWrap on Accumulator to have safe multithread access.
+ * android::mediametrics::LockWrap<Accumulator> a{}; // locked accumulator succeeds
+ *
+ * // Conversely, the following line fails:
+ * // auto a = std::make_shared<Accumulator>(); // this fails, only 50% adds atomic.
+ *
+ * constexpr size_t THREADS = 100;
+ * constexpr size_t ITERATIONS = 10;
+ * constexpr int32_t INCREMENT = 1;
+ *
+ * // Test by generating multiple threads, all adding simultaneously.
+ * std::vector<std::future<void>> threads(THREADS);
+ * for (size_t i = 0; i < THREADS; ++i) {
+ *     threads.push_back(std::async(std::launch::async, [&] {
+ *         for (size_t j = 0; j < ITERATIONS; ++j) {
+ *             a->add(INCREMENT);  // add needs locked access here.
+ *         }
+ *     }));
+ * }
+ * threads.clear();
+ *
+ * // If the add operations are not atomic, value will be smaller than expected.
+ * ASSERT_EQ(INCREMENT * THREADS * ITERATIONS, (size_t)a->get());
+ *
+ */
+template <typename T>
+class LockWrap {
+    /**
+      * Holding class that keeps the pointer and the lock.
+      *
+      * We return this holding class from operator->() to keep the lock until the
+      * method function or method variable access is completed.
+      */
+    class LockedPointer {
+        friend LockWrap;
+        LockedPointer(T *t, std::recursive_mutex *lock, std::atomic<size_t> *recursionDepth)
+            : mT(t), mLock(*lock), mRecursionDepth(recursionDepth) { ++*mRecursionDepth; }
+
+        T* const mT;
+        std::lock_guard<std::recursive_mutex> mLock;
+        std::atomic<size_t>* mRecursionDepth;
+    public:
+        ~LockedPointer() {
+            --*mRecursionDepth; // Used for testing, we do not check underflow.
+        }
+
+        const T* operator->() const {
+            return mT;
+        }
+        T* operator->() {
+            return mT;
+        }
+    };
+
+    // We must use a recursive mutex because the end of the full expression may
+    // involve another reference to T->.
+    //
+    // A recursive mutex allows the same thread to recursively acquire,
+    // but different thread would block.
+    //
+    // Example which fails with a normal mutex:
+    //
+    // android::mediametrics::LockWrap<std::vector<int>> v{std::initializer_list<int>{1, 2}};
+    // const int sum = v->operator[](0) + v->operator[](1);
+    //
+    mutable std::recursive_mutex mLock;
+    mutable T mT;
+    mutable std::atomic<size_t> mRecursionDepth{};  // Used for testing.
+
+public:
+    template <typename... Args>
+    explicit LockWrap(Args&&... args) : mT(std::forward<Args>(args)...) {}
+
+    const LockedPointer operator->() const {
+        return LockedPointer(&mT, &mLock, &mRecursionDepth);
+    }
+    LockedPointer operator->() {
+        return LockedPointer(&mT, &mLock, &mRecursionDepth);
+    }
+
+    // Returns the lock depth of the recursive mutex.
+    // @TestApi
+    size_t getRecursionDepth() const {
+        return mRecursionDepth;
+    }
+};
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/benchmarks/Android.bp b/services/mediametrics/benchmarks/Android.bp
new file mode 100644
index 0000000..b61f44f
--- /dev/null
+++ b/services/mediametrics/benchmarks/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+    name: "mediametrics_benchmarks",
+    srcs: ["mediametrics_benchmarks.cpp"],
+    shared_libs: ["libbinder", "libmediametrics",],
+    static_libs: ["libgoogle-benchmark"],
+}
diff --git a/services/mediametrics/benchmarks/README.md b/services/mediametrics/benchmarks/README.md
new file mode 100644
index 0000000..7cf767b
--- /dev/null
+++ b/services/mediametrics/benchmarks/README.md
@@ -0,0 +1,4 @@
+This benchmark may fail occasionally, probably due to the binder queue being full.
+If that happens, just re-run it and it will usually work eventually.
+
+adb shell /data/nativetest64/media\_metrics/media\_metrics
diff --git a/services/mediametrics/benchmarks/mediametrics_benchmarks.cpp b/services/mediametrics/benchmarks/mediametrics_benchmarks.cpp
new file mode 100644
index 0000000..f434867
--- /dev/null
+++ b/services/mediametrics/benchmarks/mediametrics_benchmarks.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/MediaMetricsItem.h>
+#include <benchmark/benchmark.h>
+
+class MyItem : public android::mediametrics::BaseItem {
+public:
+    static bool mySubmitBuffer() {
+        // Deliberately lame so that we're measuring just the cost to deliver things to the service.
+        return submitBuffer("", 0);
+    }
+};
+
+static void BM_SubmitBuffer(benchmark::State& state)
+{
+    while (state.KeepRunning()) {
+        MyItem myItem;
+        bool ok = myItem.mySubmitBuffer();
+        if (ok == false) {
+            // submitBuffer() currently uses one-way binder IPC, which provides unreliable delivery
+            // with at-most-one guarantee.
+            // It is expected that the call may occasionally fail if the one-way queue is full.
+            // The Iterations magic number below was tuned to reduce, but not eliminate, failures.
+            state.SkipWithError("failed");
+            return;
+        }
+        benchmark::ClobberMemory();
+    }
+}
+
+BENCHMARK(BM_SubmitBuffer)->Iterations(4000);   // Adjust magic number until test runs
+
+BENCHMARK_MAIN();
diff --git a/services/mediametrics/cleaner.cpp b/services/mediametrics/cleaner.cpp
new file mode 100644
index 0000000..e746842
--- /dev/null
+++ b/services/mediametrics/cleaner.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MetricsCleaner"
+#include <utils/Log.h>
+
+#include "cleaner.h"
+
+namespace android::mediametrics {
+
+// place time into buckets at 0,1,2,4,8,16,32 seconds and then at minute boundaries.
+// time is rounded up to the next boundary.
+//
+int64_t bucket_time_minutes(int64_t in_millis) {
+
+    const int64_t SEC_TO_MS = 1000;
+    const int64_t MIN_TO_MS = (60 * SEC_TO_MS);
+
+    if (in_millis <= 0) {
+        return 0;
+    }
+    if (in_millis <= 32 * SEC_TO_MS) {
+        for (int sec = 1; sec <= 32; sec *= 2) {
+            if (in_millis <= sec * SEC_TO_MS) {
+                return sec * SEC_TO_MS;
+            }
+        }
+    }
+    /* up to next 1 minute boundary */
+    int64_t minutes = (in_millis + MIN_TO_MS - 1) / MIN_TO_MS;
+    in_millis = minutes * MIN_TO_MS;
+    return in_millis;
+}
+
+} // namespace android::mediametrics
diff --git a/services/mediametrics/cleaner.h b/services/mediametrics/cleaner.h
new file mode 100644
index 0000000..72e24f9
--- /dev/null
+++ b/services/mediametrics/cleaner.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIAMETRICS_CLEANER_H
+#define MEDIAMETRICS_CLEANER_H
+
+namespace android::mediametrics {
+
+// break time into buckets at 1,2,4,8,16,32 seconds
+// and then at minute boundaries
+//
+extern int64_t bucket_time_minutes(int64_t incomingMs);
+
+} // namespace android::mediametrics
+
+#endif  // MEDIAMETRICS_CLEANER_H
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
new file mode 100644
index 0000000..6e51f72
--- /dev/null
+++ b/services/mediametrics/iface_statsd.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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 "iface_statsd"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <memory>
+#include <string.h>
+#include <pwd.h>
+
+#include "MediaMetricsService.h"
+#include "iface_statsd.h"
+
+#include <statslog.h>
+
+namespace android {
+
+// set of routines that crack a mediametrics::Item
+// and send it off to statsd with the appropriate hooks
+//
+// each mediametrics::Item type (extractor, codec, nuplayer, etc)
+// has its own routine to handle this.
+//
+
+bool enabled_statsd = true;
+
+struct statsd_hooks {
+    const char *key;
+    bool (*handler)(const mediametrics::Item *);
+};
+
+// keep this sorted, so we can do binary searches
+static constexpr struct statsd_hooks statsd_handlers[] =
+{
+    { "audiopolicy", statsd_audiopolicy },
+    { "audiorecord", statsd_audiorecord },
+    { "audiothread", statsd_audiothread },
+    { "audiotrack", statsd_audiotrack },
+    { "codec", statsd_codec},
+    { "drm.vendor.Google.WidevineCDM", statsd_widevineCDM },
+    { "drmmanager", statsd_drmmanager },
+    { "extractor", statsd_extractor },
+    { "mediadrm", statsd_mediadrm },
+    { "nuplayer", statsd_nuplayer },
+    { "nuplayer2", statsd_nuplayer },
+    { "recorder", statsd_recorder },
+};
+
+// give me a record, i'll look at the type and upload appropriately
+bool dump2Statsd(const std::shared_ptr<const mediametrics::Item>& item) {
+    if (item == nullptr) return false;
+
+    // get the key
+    std::string key = item->getKey();
+
+    if (!enabled_statsd) {
+        ALOGV("statsd logging disabled for record key=%s", key.c_str());
+        return false;
+    }
+
+    for (const auto &statsd_handler : statsd_handlers) {
+        if (key == statsd_handler.key) {
+            return statsd_handler.handler(item.get());
+        }
+    }
+    return false;
+}
+
+} // namespace android
diff --git a/services/mediametrics/iface_statsd.h b/services/mediametrics/iface_statsd.h
new file mode 100644
index 0000000..19505a4
--- /dev/null
+++ b/services/mediametrics/iface_statsd.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+namespace android {
+
+extern bool enabled_statsd;
+
+// component specific dumpers
+extern bool statsd_audiopolicy(const mediametrics::Item *);
+extern bool statsd_audiorecord(const mediametrics::Item *);
+extern bool statsd_audiothread(const mediametrics::Item *);
+extern bool statsd_audiotrack(const mediametrics::Item *);
+extern bool statsd_codec(const mediametrics::Item *);
+extern bool statsd_extractor(const mediametrics::Item *);
+extern bool statsd_nuplayer(const mediametrics::Item *);
+extern bool statsd_recorder(const mediametrics::Item *);
+
+extern bool statsd_mediadrm(const mediametrics::Item *);
+extern bool statsd_widevineCDM(const mediametrics::Item *);
+extern bool statsd_drmmanager(const mediametrics::Item *);
+
+} // namespace android
diff --git a/services/mediametrics/main_mediametrics.cpp b/services/mediametrics/main_mediametrics.cpp
new file mode 100644
index 0000000..3a66538
--- /dev/null
+++ b/services/mediametrics/main_mediametrics.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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_TAG "mediametrics"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "MediaMetricsService.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <mediautils/LimitProcessMemory.h>
+
+int main(int argc __unused, char **argv)
+{
+    using namespace android; // NOLINT (clang-tidy)
+
+    limitProcessMemory(
+        "media.metrics.maxmem", /* property that defines limit */
+        (size_t)128 * (1 << 20), /* SIZE_MAX, upper limit in bytes */
+        10 /* upper limit as percentage of physical RAM */);
+
+    signal(SIGPIPE, SIG_IGN);
+
+    // to match the service name
+    // we're replacing "/system/bin/mediametrics" with "media.metrics"
+    // we add a ".", but discard the path components: we finish with a shorter string
+    const size_t origSize = strlen(argv[0]) + 1; // include null termination.
+    strlcpy(argv[0], MediaMetricsService::kServiceName, origSize);
+
+    defaultServiceManager()->addService(
+            String16(MediaMetricsService::kServiceName), new MediaMetricsService());
+
+    sp<ProcessState> processState(ProcessState::self());
+    // processState->setThreadPoolMaxThreadCount(8);
+    processState->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+
+    return EXIT_SUCCESS;
+}
diff --git a/services/mediametrics/mediametrics.rc b/services/mediametrics/mediametrics.rc
new file mode 100644
index 0000000..2a6c817
--- /dev/null
+++ b/services/mediametrics/mediametrics.rc
@@ -0,0 +1,6 @@
+service mediametrics /system/bin/mediametrics
+    class main
+    user media
+    group media
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/services/mediametrics/statsd_audiopolicy.cpp b/services/mediametrics/statsd_audiopolicy.cpp
new file mode 100644
index 0000000..393c6ae
--- /dev/null
+++ b/services/mediametrics/statsd_audiopolicy.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 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 "statsd_audiopolicy"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_audiopolicy(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::AudioPolicyData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+    //int32 char kAudioPolicyStatus[] = "android.media.audiopolicy.status";
+    int32_t status = -1;
+    if (item->getInt32("android.media.audiopolicy.status", &status)) {
+        metrics_proto.set_status(status);
+    }
+    //string char kAudioPolicyRqstSrc[] = "android.media.audiopolicy.rqst.src";
+    std::string rqst_src;
+    if (item->getString("android.media.audiopolicy.rqst.src", &rqst_src)) {
+        metrics_proto.set_request_source(std::move(rqst_src));
+    }
+    //string char kAudioPolicyRqstPkg[] = "android.media.audiopolicy.rqst.pkg";
+    std::string rqst_pkg;
+    if (item->getString("android.media.audiopolicy.rqst.pkg", &rqst_pkg)) {
+        metrics_proto.set_request_package(std::move(rqst_pkg));
+    }
+    //int32 char kAudioPolicyRqstSession[] = "android.media.audiopolicy.rqst.session";
+    int32_t rqst_session = -1;
+    if (item->getInt32("android.media.audiopolicy.rqst.session", &rqst_session)) {
+        metrics_proto.set_request_session(rqst_session);
+    }
+    //string char kAudioPolicyRqstDevice[] = "android.media.audiopolicy.rqst.device";
+    std::string rqst_device;
+    if (item->getString("android.media.audiopolicy.rqst.device", &rqst_device)) {
+        metrics_proto.set_request_device(std::move(rqst_device));
+    }
+
+    //string char kAudioPolicyActiveSrc[] = "android.media.audiopolicy.active.src";
+    std::string active_src;
+    if (item->getString("android.media.audiopolicy.active.src", &active_src)) {
+        metrics_proto.set_active_source(std::move(active_src));
+    }
+    //string char kAudioPolicyActivePkg[] = "android.media.audiopolicy.active.pkg";
+    std::string active_pkg;
+    if (item->getString("android.media.audiopolicy.active.pkg", &active_pkg)) {
+        metrics_proto.set_active_package(std::move(active_pkg));
+    }
+    //int32 char kAudioPolicyActiveSession[] = "android.media.audiopolicy.active.session";
+    int32_t active_session = -1;
+    if (item->getInt32("android.media.audiopolicy.active.session", &active_session)) {
+        metrics_proto.set_active_session(active_session);
+    }
+    //string char kAudioPolicyActiveDevice[] = "android.media.audiopolicy.active.device";
+    std::string active_device;
+    if (item->getString("android.media.audiopolicy.active.device", &active_device)) {
+        metrics_proto.set_active_device(std::move(active_device));
+    }
+
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize audipolicy metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_audiorecord.cpp b/services/mediametrics/statsd_audiorecord.cpp
new file mode 100644
index 0000000..43feda1
--- /dev/null
+++ b/services/mediametrics/statsd_audiorecord.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 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 "statsd_audiorecord"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_audiorecord(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::AudioRecordData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+    std::string encoding;
+    if (item->getString("android.media.audiorecord.encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
+    }
+
+    std::string source;
+    if (item->getString("android.media.audiorecord.source", &source)) {
+        metrics_proto.set_source(std::move(source));
+    }
+
+    int32_t latency = -1;
+    if (item->getInt32("android.media.audiorecord.latency", &latency)) {
+        metrics_proto.set_latency(latency);
+    }
+
+    int32_t samplerate = -1;
+    if (item->getInt32("android.media.audiorecord.samplerate", &samplerate)) {
+        metrics_proto.set_samplerate(samplerate);
+    }
+
+    int32_t channels = -1;
+    if (item->getInt32("android.media.audiorecord.channels", &channels)) {
+        metrics_proto.set_channels(channels);
+    }
+
+    int64_t createdMs = -1;
+    if (item->getInt64("android.media.audiorecord.createdMs", &createdMs)) {
+        metrics_proto.set_created_millis(createdMs);
+    }
+
+    int64_t durationMs = -1;
+    if (item->getInt64("android.media.audiorecord.durationMs", &durationMs)) {
+        metrics_proto.set_duration_millis(durationMs);
+    }
+
+    int32_t count = -1;
+    if (item->getInt32("android.media.audiorecord.n", &count)) {
+        metrics_proto.set_count(count);
+    }
+
+    int32_t errcode = -1;
+    if (item->getInt32("android.media.audiorecord.errcode", &errcode)) {
+        metrics_proto.set_error_code(errcode);
+    } else if (item->getInt32("android.media.audiorecord.lastError.code", &errcode)) {
+        metrics_proto.set_error_code(errcode);
+    }
+
+    std::string errfunc;
+    if (item->getString("android.media.audiorecord.errfunc", &errfunc)) {
+        metrics_proto.set_error_function(std::move(errfunc));
+    } else if (item->getString("android.media.audiorecord.lastError.at", &errfunc)) {
+        metrics_proto.set_error_function(std::move(errfunc));
+    }
+
+    // portId (int32)
+    int32_t port_id = -1;
+    if (item->getInt32("android.media.audiorecord.portId", &port_id)) {
+        metrics_proto.set_port_id(count);
+    }
+    // frameCount (int32)
+    int32_t frameCount = -1;
+    if (item->getInt32("android.media.audiorecord.frameCount", &frameCount)) {
+        metrics_proto.set_frame_count(frameCount);
+    }
+    // attributes (string)
+    std::string attributes;
+    if (item->getString("android.media.audiorecord.attributes", &attributes)) {
+        metrics_proto.set_attributes(std::move(attributes));
+    }
+    // channelMask (int64)
+    int64_t channelMask = -1;
+    if (item->getInt64("android.media.audiorecord.channelMask", &channelMask)) {
+        metrics_proto.set_channel_mask(channelMask);
+    }
+    // startcount (int64)
+    int64_t startcount = -1;
+    if (item->getInt64("android.media.audiorecord.startcount", &startcount)) {
+        metrics_proto.set_start_count(startcount);
+    }
+
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize audiorecord metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_audiothread.cpp b/services/mediametrics/statsd_audiothread.cpp
new file mode 100644
index 0000000..e867f5b
--- /dev/null
+++ b/services/mediametrics/statsd_audiothread.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 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 "statsd_audiothread"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_audiothread(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::AudioThreadData metrics_proto;
+
+#define	MM_PREFIX "android.media.audiothread."
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+    std::string mytype;
+    if (item->getString(MM_PREFIX "type", &mytype)) {
+        metrics_proto.set_type(std::move(mytype));
+    }
+    int32_t framecount = -1;
+    if (item->getInt32(MM_PREFIX "framecount", &framecount)) {
+        metrics_proto.set_framecount(framecount);
+    }
+    int32_t samplerate = -1;
+    if (item->getInt32(MM_PREFIX "samplerate", &samplerate)) {
+        metrics_proto.set_samplerate(samplerate);
+    }
+    std::string workhist;
+    if (item->getString(MM_PREFIX "workMs.hist", &workhist)) {
+        metrics_proto.set_work_millis_hist(std::move(workhist));
+    }
+    std::string latencyhist;
+    if (item->getString(MM_PREFIX "latencyMs.hist", &latencyhist)) {
+        metrics_proto.set_latency_millis_hist(std::move(latencyhist));
+    }
+    std::string warmuphist;
+    if (item->getString(MM_PREFIX "warmupMs.hist", &warmuphist)) {
+        metrics_proto.set_warmup_millis_hist(std::move(warmuphist));
+    }
+    int64_t underruns = -1;
+    if (item->getInt64(MM_PREFIX "underruns", &underruns)) {
+        metrics_proto.set_underruns(underruns);
+    }
+    int64_t overruns = -1;
+    if (item->getInt64(MM_PREFIX "overruns", &overruns)) {
+        metrics_proto.set_overruns(overruns);
+    }
+    int64_t activeMs = -1;
+    if (item->getInt64(MM_PREFIX "activeMs", &activeMs)) {
+        metrics_proto.set_active_millis(activeMs);
+    }
+    int64_t durationMs = -1;
+    if (item->getInt64(MM_PREFIX "durationMs", &durationMs)) {
+        metrics_proto.set_duration_millis(durationMs);
+    }
+
+    // item->setInt32(MM_PREFIX "id", (int32_t)mId); // IO handle
+    int32_t id = -1;
+    if (item->getInt32(MM_PREFIX "id", &id)) {
+        metrics_proto.set_id(id);
+    }
+    // item->setInt32(MM_PREFIX "portId", (int32_t)mPortId);
+    int32_t port_id = -1;
+    if (item->getInt32(MM_PREFIX "portId", &id)) {
+        metrics_proto.set_port_id(port_id);
+    }
+    // item->setCString(MM_PREFIX "type", threadTypeToString(mType));
+    std::string type;
+    if (item->getString(MM_PREFIX "type", &type)) {
+        metrics_proto.set_type(std::move(type));
+    }
+    // item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate);
+    int32_t sample_rate = -1;
+    if (item->getInt32(MM_PREFIX "sampleRate", &sample_rate)) {
+        metrics_proto.set_sample_rate(sample_rate);
+    }
+    // item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
+    int32_t channel_mask = -1;
+    if (item->getInt32(MM_PREFIX "channelMask", &channel_mask)) {
+        metrics_proto.set_channel_mask(channel_mask);
+    }
+    // item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
+    std::string encoding;
+    if (item->getString(MM_PREFIX "encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
+    }
+    // item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
+    int32_t frame_count = -1;
+    if (item->getInt32(MM_PREFIX "frameCount", &frame_count)) {
+        metrics_proto.set_frame_count(frame_count);
+    }
+    // item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
+    std::string outDevice;
+    if (item->getString(MM_PREFIX "outDevice", &outDevice)) {
+        metrics_proto.set_output_device(std::move(outDevice));
+    }
+    // item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+    std::string inDevice;
+    if (item->getString(MM_PREFIX "inDevice", &inDevice)) {
+        metrics_proto.set_input_device(std::move(inDevice));
+    }
+    // item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean());
+    double iojitters_ms_mean = -1;
+    if (item->getDouble(MM_PREFIX "ioJitterMs.mean", &iojitters_ms_mean)) {
+        metrics_proto.set_io_jitter_mean_millis(iojitters_ms_mean);
+    }
+    // item->setDouble(MM_PREFIX "ioJitterMs.std", mIoJitterMs.getStdDev());
+    double iojitters_ms_std = -1;
+    if (item->getDouble(MM_PREFIX "ioJitterMs.std", &iojitters_ms_std)) {
+        metrics_proto.set_io_jitter_stddev_millis(iojitters_ms_std);
+    }
+    // item->setDouble(MM_PREFIX "processTimeMs.mean", mProcessTimeMs.getMean());
+    double process_time_ms_mean = -1;
+    if (item->getDouble(MM_PREFIX "processTimeMs.mean", &process_time_ms_mean)) {
+        metrics_proto.set_process_time_mean_millis(process_time_ms_mean);
+    }
+    // item->setDouble(MM_PREFIX "processTimeMs.std", mProcessTimeMs.getStdDev());
+    double process_time_ms_std = -1;
+    if (item->getDouble(MM_PREFIX "processTimeMs.std", &process_time_ms_std)) {
+        metrics_proto.set_process_time_stddev_millis(process_time_ms_std);
+    }
+    // item->setDouble(MM_PREFIX "timestampJitterMs.mean", tsjitter.getMean());
+    double timestamp_jitter_ms_mean = -1;
+    if (item->getDouble(MM_PREFIX "timestampJitterMs.mean", &timestamp_jitter_ms_mean)) {
+        metrics_proto.set_timestamp_jitter_mean_millis(timestamp_jitter_ms_mean);
+    }
+    // item->setDouble(MM_PREFIX "timestampJitterMs.std", tsjitter.getStdDev());
+    double timestamp_jitter_ms_stddev = -1;
+    if (item->getDouble(MM_PREFIX "timestampJitterMs.std", &timestamp_jitter_ms_stddev)) {
+        metrics_proto.set_timestamp_jitter_stddev_millis(timestamp_jitter_ms_stddev);
+    }
+    // item->setDouble(MM_PREFIX "latencyMs.mean", mLatencyMs.getMean());
+    double latency_ms_mean = -1;
+    if (item->getDouble(MM_PREFIX "latencyMs.mean", &latency_ms_mean)) {
+        metrics_proto.set_latency_mean_millis(latency_ms_mean);
+    }
+    // item->setDouble(MM_PREFIX "latencyMs.std", mLatencyMs.getStdDev());
+    double latency_ms_stddev = -1;
+    if (item->getDouble(MM_PREFIX "latencyMs.std", &latency_ms_stddev)) {
+        metrics_proto.set_latency_stddev_millis(latency_ms_stddev);
+    }
+
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize audiothread metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_audiotrack.cpp b/services/mediametrics/statsd_audiotrack.cpp
new file mode 100644
index 0000000..ee5b9b2
--- /dev/null
+++ b/services/mediametrics/statsd_audiotrack.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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 "statsd_audiotrack"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_audiotrack(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::AudioTrackData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+
+    // static constexpr char kAudioTrackStreamType[] = "android.media.audiotrack.streamtype";
+    // optional string streamType;
+    std::string streamtype;
+    if (item->getString("android.media.audiotrack.streamtype", &streamtype)) {
+        metrics_proto.set_stream_type(std::move(streamtype));
+    }
+
+    // static constexpr char kAudioTrackContentType[] = "android.media.audiotrack.type";
+    // optional string contentType;
+    std::string contenttype;
+    if (item->getString("android.media.audiotrack.type", &contenttype)) {
+        metrics_proto.set_content_type(std::move(contenttype));
+    }
+
+    // static constexpr char kAudioTrackUsage[] = "android.media.audiotrack.usage";
+    // optional string trackUsage;
+    std::string trackusage;
+    if (item->getString("android.media.audiotrack.usage", &trackusage)) {
+        metrics_proto.set_track_usage(std::move(trackusage));
+    }
+
+    // static constexpr char kAudioTrackSampleRate[] = "android.media.audiotrack.samplerate";
+    // optional int32 samplerate;
+    int32_t samplerate = -1;
+    if (item->getInt32("android.media.audiotrack.samplerate", &samplerate)) {
+        metrics_proto.set_sample_rate(samplerate);
+    }
+
+    // static constexpr char kAudioTrackChannelMask[] = "android.media.audiotrack.channelmask";
+    // optional int64 channelMask;
+    int64_t channelMask = -1;
+    if (item->getInt64("android.media.audiotrack.channelmask", &channelMask)) {
+        metrics_proto.set_channel_mask(channelMask);
+    }
+
+    // NB: These are not yet exposed as public Java API constants.
+    // static constexpr char kAudioTrackUnderrunFrames[] = "android.media.audiotrack.underrunframes";
+    // optional int32 underrunframes;
+    int32_t underrunframes = -1;
+    if (item->getInt32("android.media.audiotrack.underrunframes", &underrunframes)) {
+        metrics_proto.set_underrun_frames(underrunframes);
+    }
+
+    // static constexpr char kAudioTrackStartupGlitch[] = "android.media.audiotrack.glitch.startup";
+    // optional int32 startupglitch;
+    int32_t startupglitch = -1;
+    if (item->getInt32("android.media.audiotrack.glitch.startup", &startupglitch)) {
+        metrics_proto.set_startup_glitch(startupglitch);
+    }
+
+    // portId (int32)
+    int32_t port_id = -1;
+    if (item->getInt32("android.media.audiotrack.portId", &port_id)) {
+        metrics_proto.set_port_id(port_id);
+    }
+    // encoding (string)
+    std::string encoding;
+    if (item->getString("android.media.audiotrack.encoding", &encoding)) {
+        metrics_proto.set_encoding(std::move(encoding));
+    }
+    // frameCount (int32)
+    int32_t frame_count = -1;
+    if (item->getInt32("android.media.audiotrack.frameCount", &frame_count)) {
+        metrics_proto.set_frame_count(frame_count);
+    }
+    // attributes (string)
+    std::string attributes;
+    if (item->getString("android.media.audiotrack.attributes", &attributes)) {
+        metrics_proto.set_attributes(std::move(attributes));
+    }
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize audiotrack metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
new file mode 100644
index 0000000..ec9354f
--- /dev/null
+++ b/services/mediametrics/statsd_codec.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2019 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 "statsd_codec"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "cleaner.h"
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_codec(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::CodecData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+    // android.media.mediacodec.codec   string
+    std::string codec;
+    if (item->getString("android.media.mediacodec.codec", &codec)) {
+        metrics_proto.set_codec(std::move(codec));
+    }
+    // android.media.mediacodec.mime    string
+    std::string mime;
+    if (item->getString("android.media.mediacodec.mime", &mime)) {
+        metrics_proto.set_mime(std::move(mime));
+    }
+    // android.media.mediacodec.mode    string
+    std::string mode;
+    if ( item->getString("android.media.mediacodec.mode", &mode)) {
+        metrics_proto.set_mode(std::move(mode));
+    }
+    // android.media.mediacodec.encoder int32
+    int32_t encoder = -1;
+    if ( item->getInt32("android.media.mediacodec.encoder", &encoder)) {
+        metrics_proto.set_encoder(encoder);
+    }
+    // android.media.mediacodec.secure  int32
+    int32_t secure = -1;
+    if ( item->getInt32("android.media.mediacodec.secure", &secure)) {
+        metrics_proto.set_secure(secure);
+    }
+    // android.media.mediacodec.width   int32
+    int32_t width = -1;
+    if ( item->getInt32("android.media.mediacodec.width", &width)) {
+        metrics_proto.set_width(width);
+    }
+    // android.media.mediacodec.height  int32
+    int32_t height = -1;
+    if ( item->getInt32("android.media.mediacodec.height", &height)) {
+        metrics_proto.set_height(height);
+    }
+    // android.media.mediacodec.rotation-degrees        int32
+    int32_t rotation = -1;
+    if ( item->getInt32("android.media.mediacodec.rotation-degrees", &rotation)) {
+        metrics_proto.set_rotation(rotation);
+    }
+    // android.media.mediacodec.crypto  int32 (although missing if not needed
+    int32_t crypto = -1;
+    if ( item->getInt32("android.media.mediacodec.crypto", &crypto)) {
+        metrics_proto.set_crypto(crypto);
+    }
+    // android.media.mediacodec.profile int32
+    int32_t profile = -1;
+    if ( item->getInt32("android.media.mediacodec.profile", &profile)) {
+        metrics_proto.set_profile(profile);
+    }
+    // android.media.mediacodec.level   int32
+    int32_t level = -1;
+    if ( item->getInt32("android.media.mediacodec.level", &level)) {
+        metrics_proto.set_level(level);
+    }
+    // android.media.mediacodec.maxwidth        int32
+    int32_t maxwidth = -1;
+    if ( item->getInt32("android.media.mediacodec.maxwidth", &maxwidth)) {
+        metrics_proto.set_max_width(maxwidth);
+    }
+    // android.media.mediacodec.maxheight       int32
+    int32_t maxheight = -1;
+    if ( item->getInt32("android.media.mediacodec.maxheight", &maxheight)) {
+        metrics_proto.set_max_height(maxheight);
+    }
+    // android.media.mediacodec.errcode         int32
+    int32_t errcode = -1;
+    if ( item->getInt32("android.media.mediacodec.errcode", &errcode)) {
+        metrics_proto.set_error_code(errcode);
+    }
+    // android.media.mediacodec.errstate        string
+    std::string errstate;
+    if ( item->getString("android.media.mediacodec.errstate", &errstate)) {
+        metrics_proto.set_error_state(std::move(errstate));
+    }
+    // android.media.mediacodec.latency.max  int64
+    int64_t latency_max = -1;
+    if ( item->getInt64("android.media.mediacodec.latency.max", &latency_max)) {
+        metrics_proto.set_latency_max(latency_max);
+    }
+    // android.media.mediacodec.latency.min  int64
+    int64_t latency_min = -1;
+    if ( item->getInt64("android.media.mediacodec.latency.min", &latency_min)) {
+        metrics_proto.set_latency_min(latency_min);
+    }
+    // android.media.mediacodec.latency.avg  int64
+    int64_t latency_avg = -1;
+    if ( item->getInt64("android.media.mediacodec.latency.avg", &latency_avg)) {
+        metrics_proto.set_latency_avg(latency_avg);
+    }
+    // android.media.mediacodec.latency.n    int64
+    int64_t latency_count = -1;
+    if ( item->getInt64("android.media.mediacodec.latency.n", &latency_count)) {
+        metrics_proto.set_latency_count(latency_count);
+    }
+    // android.media.mediacodec.latency.unknown    int64
+    int64_t latency_unknown = -1;
+    if ( item->getInt64("android.media.mediacodec.latency.unknown", &latency_unknown)) {
+        metrics_proto.set_latency_unknown(latency_unknown);
+    }
+    // android.media.mediacodec.queueSecureInputBufferError  int32
+    if (int32_t queueSecureInputBufferError = -1;
+        item->getInt32("android.media.mediacodec.queueSecureInputBufferError",
+                &queueSecureInputBufferError)) {
+        metrics_proto.set_queue_secure_input_buffer_error(queueSecureInputBufferError);
+    }
+    // android.media.mediacodec.queueInputBufferError  int32
+    if (int32_t queueInputBufferError = -1;
+        item->getInt32("android.media.mediacodec.queueInputBufferError",
+                &queueInputBufferError)) {
+        metrics_proto.set_queue_input_buffer_error(queueInputBufferError);
+    }
+    // android.media.mediacodec.latency.hist    NOT EMITTED
+
+    // android.media.mediacodec.bitrate_mode string
+    std::string bitrate_mode;
+    if (item->getString("android.media.mediacodec.bitrate_mode", &bitrate_mode)) {
+        metrics_proto.set_bitrate_mode(std::move(bitrate_mode));
+    }
+    // android.media.mediacodec.bitrate int32
+    int32_t bitrate = -1;
+    if (item->getInt32("android.media.mediacodec.bitrate", &bitrate)) {
+        metrics_proto.set_bitrate(bitrate);
+    }
+    // android.media.mediacodec.lifetimeMs int64
+    int64_t lifetimeMs = -1;
+    if ( item->getInt64("android.media.mediacodec.lifetimeMs", &lifetimeMs)) {
+        lifetimeMs = mediametrics::bucket_time_minutes(lifetimeMs);
+        metrics_proto.set_lifetime_millis(lifetimeMs);
+    }
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize codec metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_CODEC_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
new file mode 100644
index 0000000..ac58929
--- /dev/null
+++ b/services/mediametrics/statsd_drm.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 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 "statsd_drm"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <pwd.h>
+
+#include "MediaMetricsService.h"
+#include "iface_statsd.h"
+
+#include <statslog.h>
+
+#include <array>
+#include <string>
+
+namespace android {
+
+// mediadrm
+bool statsd_mediadrm(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+    std::string vendor;
+    (void) item->getString("vendor", &vendor);
+    std::string description;
+    (void) item->getString("description", &description);
+    std::string serialized_metrics;
+    (void) item->getString("serialized_metrics", &serialized_metrics);
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized(serialized_metrics.c_str(),
+                                                serialized_metrics.size());
+        android::util::stats_write(android::util::MEDIAMETRICS_MEDIADRM_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   vendor.c_str(),
+                                   description.c_str(),
+                                   bf_serialized);
+    } else {
+        ALOGV("NOT sending: mediadrm private data (len=%zu)", serialized_metrics.size());
+    }
+
+    return true;
+}
+
+// widevineCDM
+bool statsd_widevineCDM(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+    std::string serialized_metrics;
+    (void) item->getString("serialized_metrics", &serialized_metrics);
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized(serialized_metrics.c_str(),
+                                                serialized_metrics.size());
+        android::util::stats_write(android::util::MEDIAMETRICS_DRM_WIDEVINE_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+    } else {
+        ALOGV("NOT sending: widevine private data (len=%zu)", serialized_metrics.size());
+    }
+
+    return true;
+}
+
+// drmmanager
+bool statsd_drmmanager(const mediametrics::Item *item)
+{
+    using namespace std::string_literals;
+    if (item == nullptr) return false;
+
+    if (!enabled_statsd) {
+        ALOGV("NOT sending: drmmanager data");
+        return true;
+    }
+
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+    std::string plugin_id;
+    (void) item->getString("plugin_id", &plugin_id);
+    std::string description;
+    (void) item->getString("description", &description);
+    int32_t method_id = -1;
+    (void) item->getInt32("method_id", &method_id);
+    std::string mime_types;
+    (void) item->getString("mime_types", &mime_types);
+
+    // Corresponds to the 13 APIs tracked in the MediametricsDrmManagerReported statsd proto
+    // Please see also DrmManager::kMethodIdMap
+    std::array<int64_t, 13> methodCounts{};
+    for (size_t i = 0; i < methodCounts.size() ; i++) {
+        item->getInt64(("method"s + std::to_string(i)).c_str(), &methodCounts[i]);
+    }
+
+    android::util::stats_write(android::util::MEDIAMETRICS_DRMMANAGER_REPORTED,
+                               timestamp, pkgName.c_str(), pkgVersionCode, mediaApexVersion,
+                               plugin_id.c_str(), description.c_str(),
+                               method_id, mime_types.c_str(),
+                               methodCounts[0], methodCounts[1], methodCounts[2],
+                               methodCounts[3], methodCounts[4], methodCounts[5],
+                               methodCounts[6], methodCounts[7], methodCounts[8],
+                               methodCounts[9], methodCounts[10], methodCounts[11],
+                               methodCounts[12]);
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
new file mode 100644
index 0000000..3d5739f
--- /dev/null
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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 "statsd_extractor"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_extractor(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::ExtractorData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+
+    // android.media.mediaextractor.fmt         string
+    std::string fmt;
+    if (item->getString("android.media.mediaextractor.fmt", &fmt)) {
+        metrics_proto.set_format(std::move(fmt));
+    }
+    // android.media.mediaextractor.mime        string
+    std::string mime;
+    if (item->getString("android.media.mediaextractor.mime", &mime)) {
+        metrics_proto.set_mime(std::move(mime));
+    }
+    // android.media.mediaextractor.ntrk        int32
+    int32_t ntrk = -1;
+    if (item->getInt32("android.media.mediaextractor.ntrk", &ntrk)) {
+        metrics_proto.set_tracks(ntrk);
+    }
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize extractor metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_nuplayer.cpp b/services/mediametrics/statsd_nuplayer.cpp
new file mode 100644
index 0000000..488bdcb
--- /dev/null
+++ b/services/mediametrics/statsd_nuplayer.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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 "statsd_nuplayer"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+/*
+ *  handles nuplayer AND nuplayer2
+ *  checks for the union of what the two players generate
+ */
+bool statsd_nuplayer(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::NuPlayerData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+
+    // differentiate between nuplayer and nuplayer2
+    metrics_proto.set_whichplayer(item->getKey().c_str());
+
+    std::string video_mime;
+    if (item->getString("android.media.mediaplayer.video.mime", &video_mime)) {
+        metrics_proto.set_video_mime(std::move(video_mime));
+    }
+    std::string video_codec;
+    if (item->getString("android.media.mediaplayer.video.codec", &video_codec)) {
+        metrics_proto.set_video_codec(std::move(video_codec));
+    }
+
+    int32_t width = -1;
+    if (item->getInt32("android.media.mediaplayer.width", &width)) {
+        metrics_proto.set_width(width);
+    }
+    int32_t height = -1;
+    if (item->getInt32("android.media.mediaplayer.height", &height)) {
+        metrics_proto.set_height(height);
+    }
+
+    int64_t frames = -1;
+    if (item->getInt64("android.media.mediaplayer.frames", &frames)) {
+        metrics_proto.set_frames(frames);
+    }
+    int64_t frames_dropped = -1;
+    if (item->getInt64("android.media.mediaplayer.dropped", &frames_dropped)) {
+        metrics_proto.set_frames_dropped(frames_dropped);
+    }
+    int64_t frames_dropped_startup = -1;
+    if (item->getInt64("android.media.mediaplayer.startupdropped", &frames_dropped_startup)) {
+        metrics_proto.set_frames_dropped_startup(frames_dropped_startup);
+    }
+    double fps = -1.0;
+    if (item->getDouble("android.media.mediaplayer.fps", &fps)) {
+        metrics_proto.set_framerate(fps);
+    }
+
+    std::string audio_mime;
+    if (item->getString("android.media.mediaplayer.audio.mime", &audio_mime)) {
+        metrics_proto.set_audio_mime(std::move(audio_mime));
+    }
+    std::string audio_codec;
+    if (item->getString("android.media.mediaplayer.audio.codec", &audio_codec)) {
+        metrics_proto.set_audio_codec(std::move(audio_codec));
+    }
+
+    int64_t duration_ms = -1;
+    if (item->getInt64("android.media.mediaplayer.durationMs", &duration_ms)) {
+        metrics_proto.set_duration_millis(duration_ms);
+    }
+    int64_t playing_ms = -1;
+    if (item->getInt64("android.media.mediaplayer.playingMs", &playing_ms)) {
+        metrics_proto.set_playing_millis(playing_ms);
+    }
+
+    int32_t err = -1;
+    if (item->getInt32("android.media.mediaplayer.err", &err)) {
+        metrics_proto.set_error(err);
+    }
+    int32_t error_code = -1;
+    if (item->getInt32("android.media.mediaplayer.errcode", &error_code)) {
+        metrics_proto.set_error_code(error_code);
+    }
+    std::string error_state;
+    if (item->getString("android.media.mediaplayer.errstate", &error_state)) {
+        metrics_proto.set_error_state(std::move(error_state));
+    }
+
+    std::string data_source_type;
+    if (item->getString("android.media.mediaplayer.dataSource", &data_source_type)) {
+        metrics_proto.set_data_source_type(std::move(data_source_type));
+    }
+
+    int64_t rebufferingMs = -1;
+    if (item->getInt64("android.media.mediaplayer.rebufferingMs", &rebufferingMs)) {
+        metrics_proto.set_rebuffering_millis(rebufferingMs);
+    }
+    int32_t rebuffers = -1;
+    if (item->getInt32("android.media.mediaplayer.rebuffers", &rebuffers)) {
+        metrics_proto.set_rebuffers(rebuffers);
+    }
+    int32_t rebufferExit = -1;
+    if (item->getInt32("android.media.mediaplayer.rebufferExit", &rebufferExit)) {
+        metrics_proto.set_rebuffer_at_exit(rebufferExit);
+    }
+
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize nuplayer metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_NUPLAYER_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/statsd_recorder.cpp b/services/mediametrics/statsd_recorder.cpp
new file mode 100644
index 0000000..6d5fca0
--- /dev/null
+++ b/services/mediametrics/statsd_recorder.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2019 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 "statsd_recorder"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_recorder(const mediametrics::Item *item)
+{
+    if (item == nullptr) return false;
+
+    // these go into the statsd wrapper
+    const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+    std::string pkgName = item->getPkgName();
+    int64_t pkgVersionCode = item->getPkgVersionCode();
+    int64_t mediaApexVersion = 0;
+
+
+    // the rest into our own proto
+    //
+    ::android::stats::mediametrics::RecorderData metrics_proto;
+
+    // flesh out the protobuf we'll hand off with our data
+    //
+
+    // string kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
+    std::string audio_mime;
+    if (item->getString("android.media.mediarecorder.audio.mime", &audio_mime)) {
+        metrics_proto.set_audio_mime(std::move(audio_mime));
+    }
+    // string kRecorderVideoMime = "android.media.mediarecorder.video.mime";
+    std::string video_mime;
+    if (item->getString("android.media.mediarecorder.video.mime", &video_mime)) {
+        metrics_proto.set_video_mime(std::move(video_mime));
+    }
+    // int32 kRecorderVideoProfile = "android.media.mediarecorder.video-encoder-profile";
+    int32_t videoProfile = -1;
+    if (item->getInt32("android.media.mediarecorder.video-encoder-profile", &videoProfile)) {
+        metrics_proto.set_video_profile(videoProfile);
+    }
+    // int32 kRecorderVideoLevel = "android.media.mediarecorder.video-encoder-level";
+    int32_t videoLevel = -1;
+    if (item->getInt32("android.media.mediarecorder.video-encoder-level", &videoLevel)) {
+        metrics_proto.set_video_level(videoLevel);
+    }
+    // int32 kRecorderWidth = "android.media.mediarecorder.width";
+    int32_t width = -1;
+    if (item->getInt32("android.media.mediarecorder.width", &width)) {
+        metrics_proto.set_width(width);
+    }
+    // int32 kRecorderHeight = "android.media.mediarecorder.height";
+    int32_t height = -1;
+    if (item->getInt32("android.media.mediarecorder.height", &height)) {
+        metrics_proto.set_height(height);
+    }
+    // int32 kRecorderRotation = "android.media.mediarecorder.rotation";
+    int32_t rotation = -1;                      // default to 0?
+    if (item->getInt32("android.media.mediarecorder.rotation", &rotation)) {
+        metrics_proto.set_rotation(rotation);
+    }
+    // int32 kRecorderFrameRate = "android.media.mediarecorder.frame-rate";
+    int32_t framerate = -1;
+    if (item->getInt32("android.media.mediarecorder.frame-rate", &framerate)) {
+        metrics_proto.set_framerate(framerate);
+    }
+
+    // int32 kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
+    int32_t captureFps = -1;
+    if (item->getInt32("android.media.mediarecorder.capture-fps", &captureFps)) {
+        metrics_proto.set_capture_fps(captureFps);
+    }
+    // double kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
+    double captureFpsEnable = -1;
+    if (item->getDouble("android.media.mediarecorder.capture-fpsenable", &captureFpsEnable)) {
+        metrics_proto.set_capture_fps_enable(captureFpsEnable);
+    }
+
+    // int64 kRecorderDurationMs = "android.media.mediarecorder.durationMs";
+    int64_t durationMs = -1;
+    if (item->getInt64("android.media.mediarecorder.durationMs", &durationMs)) {
+        metrics_proto.set_duration_millis(durationMs);
+    }
+    // int64 kRecorderPaused = "android.media.mediarecorder.pausedMs";
+    int64_t pausedMs = -1;
+    if (item->getInt64("android.media.mediarecorder.pausedMs", &pausedMs)) {
+        metrics_proto.set_paused_millis(pausedMs);
+    }
+    // int32 kRecorderNumPauses = "android.media.mediarecorder.NPauses";
+    int32_t pausedCount = -1;
+    if (item->getInt32("android.media.mediarecorder.NPauses", &pausedCount)) {
+        metrics_proto.set_paused_count(pausedCount);
+    }
+
+    // int32 kRecorderAudioBitrate = "android.media.mediarecorder.audio-bitrate";
+    int32_t audioBitrate = -1;
+    if (item->getInt32("android.media.mediarecorder.audio-bitrate", &audioBitrate)) {
+        metrics_proto.set_audio_bitrate(audioBitrate);
+    }
+    // int32 kRecorderAudioChannels = "android.media.mediarecorder.audio-channels";
+    int32_t audioChannels = -1;
+    if (item->getInt32("android.media.mediarecorder.audio-channels", &audioChannels)) {
+        metrics_proto.set_audio_channels(audioChannels);
+    }
+    // int32 kRecorderAudioSampleRate = "android.media.mediarecorder.audio-samplerate";
+    int32_t audioSampleRate = -1;
+    if (item->getInt32("android.media.mediarecorder.audio-samplerate", &audioSampleRate)) {
+        metrics_proto.set_audio_samplerate(audioSampleRate);
+    }
+
+    // int32 kRecorderMovieTimescale = "android.media.mediarecorder.movie-timescale";
+    int32_t movieTimescale = -1;
+    if (item->getInt32("android.media.mediarecorder.movie-timescale", &movieTimescale)) {
+        metrics_proto.set_movie_timescale(movieTimescale);
+    }
+    // int32 kRecorderAudioTimescale = "android.media.mediarecorder.audio-timescale";
+    int32_t audioTimescale = -1;
+    if (item->getInt32("android.media.mediarecorder.audio-timescale", &audioTimescale)) {
+        metrics_proto.set_audio_timescale(audioTimescale);
+    }
+    // int32 kRecorderVideoTimescale = "android.media.mediarecorder.video-timescale";
+    int32_t videoTimescale = -1;
+    if (item->getInt32("android.media.mediarecorder.video-timescale", &videoTimescale)) {
+        metrics_proto.set_video_timescale(videoTimescale);
+    }
+
+    // int32 kRecorderVideoBitrate = "android.media.mediarecorder.video-bitrate";
+    int32_t videoBitRate = -1;
+    if (item->getInt32("android.media.mediarecorder.video-bitrate", &videoBitRate)) {
+        metrics_proto.set_video_bitrate(videoBitRate);
+    }
+    // int32 kRecorderVideoIframeInterval = "android.media.mediarecorder.video-iframe-interval";
+    int32_t iFrameInterval = -1;
+    if (item->getInt32("android.media.mediarecorder.video-iframe-interval", &iFrameInterval)) {
+        metrics_proto.set_iframe_interval(iFrameInterval);
+    }
+
+    std::string serialized;
+    if (!metrics_proto.SerializeToString(&serialized)) {
+        ALOGE("Failed to serialize recorder metrics");
+        return false;
+    }
+
+    if (enabled_statsd) {
+        android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
+        (void)android::util::stats_write(android::util::MEDIAMETRICS_RECORDER_REPORTED,
+                                   timestamp, pkgName.c_str(), pkgVersionCode,
+                                   mediaApexVersion,
+                                   bf_serialized);
+
+    } else {
+        ALOGV("NOT sending: private data (len=%zu)", strlen(serialized.c_str()));
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
new file mode 100644
index 0000000..c2e0759
--- /dev/null
+++ b/services/mediametrics/tests/Android.bp
@@ -0,0 +1,31 @@
+cc_test {
+    name: "mediametrics_tests",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/mediametrics",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libmediametrics",
+        "libmediametricsservice",
+        "libmediautils",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudioutils_headers",
+    ],
+
+    srcs: [
+        "mediametrics_tests.cpp",
+    ],
+}
diff --git a/services/mediametrics/tests/build_and_run_all_unit_tests.sh b/services/mediametrics/tests/build_and_run_all_unit_tests.sh
new file mode 100755
index 0000000..382be47
--- /dev/null
+++ b/services/mediametrics/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+    echo "Android build environment not set"
+    exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount
+
+echo "========================================"
+
+echo "testing mediametrics"
+adb push $OUT/data/nativetest64/mediametrics_tests/mediametrics_tests /system/bin
+adb shell /system/bin/mediametrics_tests
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
new file mode 100644
index 0000000..478355b
--- /dev/null
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -0,0 +1,1084 @@
+/*
+ * Copyright (C) 2019 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_TAG "mediametrics_tests"
+#include <utils/Log.h>
+
+#include "MediaMetricsService.h"
+
+#include <stdio.h>
+#include <unordered_set>
+
+#include <gtest/gtest.h>
+#include <media/MediaMetricsItem.h>
+#include <system/audio.h>
+
+#include "AudioTypes.h"
+#include "StringUtils.h"
+
+using namespace android;
+
+static size_t countNewlines(const char *s) {
+    size_t count = 0;
+    while ((s = strchr(s, '\n')) != nullptr) {
+        ++s;
+        ++count;
+    }
+    return count;
+}
+
+template <typename M>
+ssize_t countDuplicates(const M& map) {
+    std::unordered_set<typename M::mapped_type> s;
+    for (const auto &m : map) {
+        s.emplace(m.second);
+    }
+    return map.size() - s.size();
+}
+
+TEST(mediametrics_tests, startsWith) {
+  std::string s("test");
+  ASSERT_EQ(true, android::mediametrics::startsWith(s, "te"));
+  ASSERT_EQ(true, android::mediametrics::startsWith(s, std::string("tes")));
+  ASSERT_EQ(false, android::mediametrics::startsWith(s, "ts"));
+  ASSERT_EQ(false, android::mediametrics::startsWith(s, std::string("est")));
+}
+
+TEST(mediametrics_tests, defer) {
+  bool check = false;
+  {
+      android::mediametrics::Defer defer([&] { check = true; });
+      ASSERT_EQ(false, check);
+  }
+  ASSERT_EQ(true, check);
+}
+
+TEST(mediametrics_tests, shared_ptr_wrap) {
+  // Test shared pointer wrap with simple access
+  android::mediametrics::SharedPtrWrap<std::string> s("123");
+  ASSERT_EQ('1', s->at(0));
+  ASSERT_EQ('2', s->at(1));
+  s->push_back('4');
+  ASSERT_EQ('4', s->at(3));
+
+  const android::mediametrics::SharedPtrWrap<std::string> s2("345");
+  ASSERT_EQ('3', s2->operator[](0));  // s2[0] == '3'
+  // we allow modification through a const shared pointer wrap
+  // for compatibility with shared_ptr.
+  s2->push_back('6');
+  ASSERT_EQ('6', s2->operator[](3));  // s2[3] == '6'
+
+  android::mediametrics::SharedPtrWrap<std::string> s3("");
+  s3.set(std::make_shared<std::string>("abc"));
+  ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
+
+  // Use Thunk to check whether the destructor was called prematurely
+  // when setting the shared ptr wrap in the middle of a method.
+
+  class Thunk {
+    std::function<void(int)> mF;
+    const int mFinal;
+
+    public:
+      explicit Thunk(decltype(mF) f, int final) : mF(std::move(f)), mFinal(final) {}
+      ~Thunk() { mF(mFinal); }
+      void thunk(int value) { mF(value); }
+  };
+
+  int counter = 0;
+  android::mediametrics::SharedPtrWrap<Thunk> s4(
+    [&](int value) {
+      s4.set(std::make_shared<Thunk>([](int){}, 0)); // recursively set s4 while in s4.
+      ++counter;
+      ASSERT_EQ(value, counter);  // on thunk() value is 1, on destructor this is 2.
+    }, 2);
+
+  // This will fail if the shared ptr wrap doesn't hold a ref count during method access.
+  s4->thunk(1);
+}
+
+TEST(mediametrics_tests, lock_wrap) {
+  // Test lock wrap with simple access
+  android::mediametrics::LockWrap<std::string> s("123");
+  ASSERT_EQ('1', s->at(0));
+  ASSERT_EQ('2', s->at(1));
+  s->push_back('4');
+  ASSERT_EQ('4', s->at(3));
+
+  const android::mediametrics::LockWrap<std::string> s2("345");
+  ASSERT_EQ('3', s2->operator[](0));  // s2[0] == '3'
+  // note: we can't modify s2 due to const, s2->push_back('6');
+
+  android::mediametrics::LockWrap<std::string> s3("");
+  s3->operator=("abc");
+  ASSERT_EQ('b', s3->operator[](1)); // s2[1] = 'b';
+
+  // Check that we can recursively hold lock.
+  android::mediametrics::LockWrap<std::vector<int>> v{std::initializer_list<int>{1, 2}};
+  v->push_back(3);
+  v->push_back(4);
+  ASSERT_EQ(1, v->operator[](0));
+  ASSERT_EQ(2, v->operator[](1));
+  ASSERT_EQ(3, v->operator[](2));
+  ASSERT_EQ(4, v->operator[](3));
+  // The end of the full expression here requires recursive depth of 4.
+  ASSERT_EQ(10, v->operator[](0) + v->operator[](1) + v->operator[](2) + v->operator[](3));
+
+  // Mikhail's note: a non-recursive lock implementation could be used if one obtains
+  // the LockedPointer helper object like this and directly hold the lock through RAII,
+  // though it is trickier in use.
+  //
+  // We include an example here for completeness.
+  {
+    auto l = v.operator->();
+    ASSERT_EQ(10, l->operator[](0) + l->operator[](1) + l->operator[](2) + l->operator[](3));
+  }
+
+  // Use Thunk to check whether we have the lock when calling a method through LockWrap.
+
+  class Thunk {
+    std::function<void()> mF;
+
+    public:
+      explicit Thunk(decltype(mF) f) : mF(std::move(f)) {}
+      void thunk() { mF(); }
+  };
+
+  android::mediametrics::LockWrap<Thunk> s4([&]{
+    ASSERT_EQ((size_t)1, s4.getRecursionDepth()); // we must be locked when thunk() is called.
+  });
+
+  ASSERT_EQ((size_t)0, s4.getRecursionDepth());
+  // This will fail if we are not locked during method access.
+  s4->thunk();
+  ASSERT_EQ((size_t)0, s4.getRecursionDepth());
+}
+
+TEST(mediametrics_tests, lock_wrap_multithread) {
+  class Accumulator {
+    int32_t value_ = 0;
+  public:
+    void add(int32_t incr) {
+      const int32_t temp = value_;
+      sleep(0);  // yield
+      value_ = temp + incr;
+    }
+    int32_t get() { return value_; }
+  };
+
+  android::mediametrics::LockWrap<Accumulator> a{}; // locked accumulator succeeds
+  // auto a = std::make_shared<Accumulator>(); // this fails, only 50% adds atomic.
+
+  constexpr size_t THREADS = 100;
+  constexpr size_t ITERATIONS = 10;
+  constexpr int32_t INCREMENT = 1;
+
+  std::vector<std::future<void>> threads(THREADS);
+  for (size_t i = 0; i < THREADS; ++i) {
+    threads.push_back(std::async(std::launch::async, [&] {
+        for (size_t j = 0; j < ITERATIONS; ++j) {
+          a->add(INCREMENT);
+        }
+      }));
+  }
+  threads.clear();
+
+  // If the add operations are not atomic, value will be smaller than expected.
+  ASSERT_EQ(INCREMENT * THREADS * ITERATIONS, (size_t)a->get());
+}
+
+TEST(mediametrics_tests, instantiate) {
+  sp mediaMetrics = new MediaMetricsService();
+  status_t status;
+
+  // random keys ignored when empty
+  std::unique_ptr<mediametrics::Item> random_key(mediametrics::Item::create("random_key"));
+  status = mediaMetrics->submit(random_key.get());
+  ASSERT_EQ(PERMISSION_DENIED, status);
+
+  // random keys ignored with data
+  random_key->setInt32("foo", 10);
+  status = mediaMetrics->submit(random_key.get());
+  ASSERT_EQ(PERMISSION_DENIED, status);
+
+  // known keys ignored if empty
+  std::unique_ptr<mediametrics::Item> audiotrack_key(mediametrics::Item::create("audiotrack"));
+  status = mediaMetrics->submit(audiotrack_key.get());
+  ASSERT_EQ(BAD_VALUE, status);
+
+  // known keys not ignored if not empty
+  audiotrack_key->addInt32("foo", 10);
+  status = mediaMetrics->submit(audiotrack_key.get());
+  ASSERT_EQ(NO_ERROR, status);
+
+
+  /*
+  // fluent style that goes directly to mediametrics
+  ASSERT_EQ(true, mediametrics::Item("audiorecord")
+                     .setInt32("value", 2)
+                     .addInt32("bar", 1)
+                     .addInt32("value", 3)
+                     .selfrecord());
+  */
+
+  mediaMetrics->dump(fileno(stdout), {} /* args */);
+}
+
+TEST(mediametrics_tests, package_installer_check) {
+  ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
+      "abcd", "installer"));  // ok, package name has no dot.
+  ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
+      "android.com", "installer"));  // ok, package name starts with android
+
+  ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
+      "abc.def", "com.android.foo"));  // ok, installer name starts with com.android
+  ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
+      "123.456", "com.google.bar"));  // ok, installer name starts with com.google
+  ASSERT_EQ(false, MediaMetricsService::useUidForPackage(
+      "r2.d2", "preload"));  // ok, installer name is preload
+
+  ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
+      "abc.def", "installer"));  // unknown installer
+  ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
+      "123.456", "installer")); // unknown installer
+  ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
+      "r2.d2", "preload23"));  // unknown installer
+
+  ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
+      "com.android.foo", "abc.def"));  // unknown installer
+  ASSERT_EQ(true, MediaMetricsService::useUidForPackage(
+      "com.google.bar", "123.456"));  // unknown installer
+}
+
+TEST(mediametrics_tests, item_manipulation) {
+  mediametrics::Item item("audiorecord");
+
+  item.setInt32("value", 2).addInt32("bar", 3).addInt32("value", 4);
+
+  int32_t i32;
+  ASSERT_TRUE(item.getInt32("value", &i32));
+  ASSERT_EQ(6, i32);
+
+  ASSERT_TRUE(item.getInt32("bar", &i32));
+  ASSERT_EQ(3, i32);
+
+  item.setInt64("big", INT64_MAX).setInt64("smaller", INT64_MAX - 1).addInt64("smaller", -2);
+
+  int64_t i64;
+  ASSERT_TRUE(item.getInt64("big", &i64));
+  ASSERT_EQ(INT64_MAX, i64);
+
+  ASSERT_TRUE(item.getInt64("smaller", &i64));
+  ASSERT_EQ(INT64_MAX - 3, i64);
+
+  item.setDouble("precise", 10.5).setDouble("small", 0.125).addDouble("precise", 0.25);
+
+  double d;
+  ASSERT_TRUE(item.getDouble("precise", &d));
+  ASSERT_EQ(10.75, d);
+
+  ASSERT_TRUE(item.getDouble("small", &d));
+  ASSERT_EQ(0.125, d);
+
+  char *s;
+  item.setCString("name", "Frank").setCString("mother", "June").setCString("mother", "July");
+  ASSERT_TRUE(item.getCString("name", &s));
+  ASSERT_EQ(0, strcmp(s, "Frank"));
+  free(s);
+
+  ASSERT_TRUE(item.getCString("mother", &s));
+  ASSERT_EQ(0, strcmp(s, "July"));  // "July" overwrites "June"
+  free(s);
+
+  item.setRate("burgersPerHour", 5, 2);
+  int64_t b, h;
+  ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
+  ASSERT_EQ(5, b);
+  ASSERT_EQ(2, h);
+  ASSERT_EQ(2.5, d);
+
+  item.addRate("burgersPerHour", 4, 2);
+  ASSERT_TRUE(item.getRate("burgersPerHour", &b, &h, &d));
+  ASSERT_EQ(9, b);
+  ASSERT_EQ(4, h);
+  ASSERT_EQ(2.25, d);
+
+  printf("item: %s\n", item.toString().c_str());
+  fflush(stdout);
+
+  sp mediaMetrics = new MediaMetricsService();
+  status_t status = mediaMetrics->submit(&item);
+  ASSERT_EQ(NO_ERROR, status);
+  mediaMetrics->dump(fileno(stdout), {} /* args */);
+}
+
+TEST(mediametrics_tests, superbig_item) {
+  mediametrics::Item item("TheBigOne");
+  constexpr size_t count = 10000;
+
+  for (size_t i = 0; i < count; ++i) {
+    item.setInt32(std::to_string(i).c_str(), i);
+  }
+  for (size_t i = 0; i < count; ++i) {
+    int32_t i32;
+    ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+    ASSERT_EQ((int32_t)i, i32);
+  }
+}
+
+TEST(mediametrics_tests, superbig_item_removal) {
+  mediametrics::Item item("TheOddBigOne");
+  constexpr size_t count = 10000;
+
+  for (size_t i = 0; i < count; ++i) {
+    item.setInt32(std::to_string(i).c_str(), i);
+  }
+  for (size_t i = 0; i < count; i += 2) {
+    item.filter(std::to_string(i).c_str()); // filter out all the evens.
+  }
+  for (size_t i = 0; i < count; ++i) {
+    int32_t i32;
+    if (i & 1) { // check to see that only the odds are left.
+        ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+        ASSERT_EQ((int32_t)i, i32);
+    } else {
+        ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
+    }
+  }
+}
+
+TEST(mediametrics_tests, superbig_item_removal2) {
+  mediametrics::Item item("TheOne");
+  constexpr size_t count = 10000;
+
+  for (size_t i = 0; i < count; ++i) {
+    item.setInt32(std::to_string(i).c_str(), i);
+  }
+  static const char *attrs[] = { "1", };
+  item.filterNot(1, attrs);
+
+  for (size_t i = 0; i < count; ++i) {
+    int32_t i32;
+    if (i == 1) { // check to see that there is only one
+        ASSERT_TRUE(item.getInt32(std::to_string(i).c_str(), &i32));
+        ASSERT_EQ((int32_t)i, i32);
+    } else {
+        ASSERT_FALSE(item.getInt32(std::to_string(i).c_str(), &i32));
+    }
+  }
+}
+
+TEST(mediametrics_tests, item_transmutation) {
+  mediametrics::Item item("Alchemist's Stone");
+
+  item.setInt64("convert", 123);
+  int64_t i64;
+  ASSERT_TRUE(item.getInt64("convert", &i64));
+  ASSERT_EQ(123, i64);
+
+  item.addInt32("convert", 2);     // changes type of 'convert' from i64 to i32 (and re-init).
+  ASSERT_FALSE(item.getInt64("convert", &i64));  // should be false, no value in i64.
+
+  int32_t i32;
+  ASSERT_TRUE(item.getInt32("convert", &i32));   // check it is i32 and 2 (123 is discarded).
+  ASSERT_EQ(2, i32);
+}
+
+TEST(mediametrics_tests, item_binderization) {
+  mediametrics::Item item;
+  item.setInt32("i32", 1)
+      .setInt64("i64", 2)
+      .setDouble("double", 3.1)
+      .setCString("string", "abc")
+      .setRate("rate", 11, 12);
+
+  Parcel p;
+  item.writeToParcel(&p);
+
+  p.setDataPosition(0); // rewind for reading
+  mediametrics::Item item2;
+  item2.readFromParcel(p);
+
+  ASSERT_EQ(item, item2);
+}
+
+TEST(mediametrics_tests, item_byteserialization) {
+  mediametrics::Item item;
+  item.setInt32("i32", 1)
+      .setInt64("i64", 2)
+      .setDouble("double", 3.1)
+      .setCString("string", "abc")
+      .setRate("rate", 11, 12);
+
+  char *data;
+  size_t length;
+  ASSERT_EQ(0, item.writeToByteString(&data, &length));
+  ASSERT_GT(length, (size_t)0);
+
+  mediametrics::Item item2;
+  item2.readFromByteString(data, length);
+
+  printf("item: %s\n", item.toString().c_str());
+  printf("item2: %s\n", item2.toString().c_str());
+  ASSERT_EQ(item, item2);
+
+  free(data);
+}
+
+TEST(mediametrics_tests, item_iteration) {
+  mediametrics::Item item;
+  item.setInt32("i32", 1)
+      .setInt64("i64", 2)
+      .setDouble("double", 3.125)
+      .setCString("string", "abc")
+      .setRate("rate", 11, 12);
+
+  int mask = 0;
+  for (auto &prop : item) {
+      const char *name = prop.getName();
+      if (!strcmp(name, "i32")) {
+          int32_t i32;
+          ASSERT_TRUE(prop.get(&i32));
+          ASSERT_EQ(1, i32);
+          ASSERT_EQ(1, std::get<int32_t>(prop.get()));
+          mask |= 1;
+      } else if (!strcmp(name, "i64")) {
+          int64_t i64;
+          ASSERT_TRUE(prop.get(&i64));
+          ASSERT_EQ(2, i64);
+          ASSERT_EQ(2, std::get<int64_t>(prop.get()));
+          mask |= 2;
+      } else if (!strcmp(name, "double")) {
+          double d;
+          ASSERT_TRUE(prop.get(&d));
+          ASSERT_EQ(3.125, d);
+          ASSERT_EQ(3.125, std::get<double>(prop.get()));
+          mask |= 4;
+      } else if (!strcmp(name, "string")) {
+          std::string s;
+          ASSERT_TRUE(prop.get(&s));
+          ASSERT_EQ("abc", s);
+          ASSERT_EQ(s, std::get<std::string>(prop.get()));
+          mask |= 8;
+      } else if (!strcmp(name, "rate")) {
+          std::pair<int64_t, int64_t> r;
+          ASSERT_TRUE(prop.get(&r));
+          ASSERT_EQ(11, r.first);
+          ASSERT_EQ(12, r.second);
+          ASSERT_EQ(r, std::get<decltype(r)>(prop.get()));
+          mask |= 16;
+      } else {
+          FAIL();
+      }
+  }
+  ASSERT_EQ(31, mask);
+}
+
+TEST(mediametrics_tests, item_expansion) {
+  mediametrics::LogItem<1> item("I");
+  item.set("i32", (int32_t)1)
+      .set("i64", (int64_t)2)
+      .set("double", (double)3.125)
+      .set("string", "abcdefghijklmnopqrstuvwxyz")
+      .set("rate", std::pair<int64_t, int64_t>(11, 12));
+  ASSERT_TRUE(item.updateHeader());
+
+  mediametrics::Item item2;
+  item2.readFromByteString(item.getBuffer(), item.getLength());
+  ASSERT_EQ((pid_t)-1, item2.getPid());
+  ASSERT_EQ((uid_t)-1, item2.getUid());
+  int mask = 0;
+  for (auto &prop : item2) {
+      const char *name = prop.getName();
+      if (!strcmp(name, "i32")) {
+          int32_t i32;
+          ASSERT_TRUE(prop.get(&i32));
+          ASSERT_EQ(1, i32);
+          mask |= 1;
+      } else if (!strcmp(name, "i64")) {
+          int64_t i64;
+          ASSERT_TRUE(prop.get(&i64));
+          ASSERT_EQ(2, i64);
+          mask |= 2;
+      } else if (!strcmp(name, "double")) {
+          double d;
+          ASSERT_TRUE(prop.get(&d));
+          ASSERT_EQ(3.125, d);
+          mask |= 4;
+      } else if (!strcmp(name, "string")) {
+          std::string s;
+          ASSERT_TRUE(prop.get(&s));
+          ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
+          mask |= 8;
+      } else if (!strcmp(name, "rate")) {
+          std::pair<int64_t, int64_t> r;
+          ASSERT_TRUE(prop.get(&r));
+          ASSERT_EQ(11, r.first);
+          ASSERT_EQ(12, r.second);
+          mask |= 16;
+      } else {
+          FAIL();
+      }
+  }
+  ASSERT_EQ(31, mask);
+}
+
+TEST(mediametrics_tests, item_expansion2) {
+  mediametrics::LogItem<1> item("Bigly");
+  item.setPid(123)
+      .setUid(456);
+  constexpr size_t count = 10000;
+
+  for (size_t i = 0; i < count; ++i) {
+    // printf("recording %zu, %p, len:%zu of %zu  remaining:%zu \n", i, item.getBuffer(), item.getLength(), item.getCapacity(), item.getRemaining());
+    item.set(std::to_string(i).c_str(), (int32_t)i);
+  }
+  ASSERT_TRUE(item.updateHeader());
+
+  mediametrics::Item item2;
+  printf("begin buffer:%p  length:%zu\n", item.getBuffer(), item.getLength());
+  fflush(stdout);
+  item2.readFromByteString(item.getBuffer(), item.getLength());
+
+  ASSERT_EQ((pid_t)123, item2.getPid());
+  ASSERT_EQ((uid_t)456, item2.getUid());
+  for (size_t i = 0; i < count; ++i) {
+    int32_t i32;
+    ASSERT_TRUE(item2.getInt32(std::to_string(i).c_str(), &i32));
+    ASSERT_EQ((int32_t)i, i32);
+  }
+}
+
+TEST(mediametrics_tests, time_machine_storage) {
+  auto item = std::make_shared<mediametrics::Item>("Key");
+  (*item).set("i32", (int32_t)1)
+      .set("i64", (int64_t)2)
+      .set("double", (double)3.125)
+      .set("string", "abcdefghijklmnopqrstuvwxyz")
+      .set("rate", std::pair<int64_t, int64_t>(11, 12));
+
+  // Let's put the item in
+  android::mediametrics::TimeMachine timeMachine;
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+  // Can we read the values?
+  int32_t i32;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i32", &i32, -1));
+  ASSERT_EQ(1, i32);
+
+  int64_t i64;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "i64", &i64, -1));
+  ASSERT_EQ(2, i64);
+
+  double d;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "double", &d, -1));
+  ASSERT_EQ(3.125, d);
+
+  std::string s;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key", "string", &s, -1));
+  ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
+
+  // Using fully qualified name?
+  i32 = 0;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i32", &i32, -1));
+  ASSERT_EQ(1, i32);
+
+  i64 = 0;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key.i64", &i64, -1));
+  ASSERT_EQ(2, i64);
+
+  d = 0.;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key.double", &d, -1));
+  ASSERT_EQ(3.125, d);
+
+  s.clear();
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key.string", &s, -1));
+  ASSERT_EQ("abcdefghijklmnopqrstuvwxyz", s);
+}
+
+TEST(mediametrics_tests, time_machine_remote_key) {
+  auto item = std::make_shared<mediametrics::Item>("Key1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2);
+
+  android::mediametrics::TimeMachine timeMachine;
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+  auto item2 = std::make_shared<mediametrics::Item>("Key2");
+  (*item2).set("three", (int32_t)3)
+         .set("[Key1]four", (int32_t)4)   // affects Key1
+         .set("[Key1]five", (int32_t)5);  // affects key1
+
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
+
+  auto item3 = std::make_shared<mediametrics::Item>("Key2");
+  (*item3).set("six", (int32_t)6)
+         .set("[Key1]seven", (int32_t)7);   // affects Key1
+
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item3, false)); // remote keys not allowed.
+
+  // Can we read the values?
+  int32_t i32;
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.one", &i32, -1));
+  ASSERT_EQ(1, i32);
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.two", &i32, -1));
+  ASSERT_EQ(2, i32);
+
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
+  ASSERT_EQ(3, i32);
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.four", &i32, -1));
+  ASSERT_EQ(4, i32);
+
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.four", &i32, -1));
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key1.five", &i32, -1));
+  ASSERT_EQ(5, i32);
+
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.five", &i32, -1));
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.six", &i32, -1));
+  ASSERT_EQ(6, i32);
+
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key2.seven", &i32, -1));
+}
+
+TEST(mediametrics_tests, time_machine_gc) {
+  auto item = std::make_shared<mediametrics::Item>("Key1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2)
+         .setTimestamp(10);
+
+  android::mediametrics::TimeMachine timeMachine(1, 2); // keep at most 2 keys.
+
+  ASSERT_EQ((size_t)0, timeMachine.size());
+
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item, true));
+
+  ASSERT_EQ((size_t)1, timeMachine.size());
+
+  auto item2 = std::make_shared<mediametrics::Item>("Key2");
+  (*item2).set("three", (int32_t)3)
+         .set("[Key1]three", (int32_t)3)
+         .setTimestamp(11);
+
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item2, true));
+  ASSERT_EQ((size_t)2, timeMachine.size());
+
+  //printf("Before\n%s\n\n", timeMachine.dump().c_str());
+
+  auto item3 = std::make_shared<mediametrics::Item>("Key3");
+  (*item3).set("six", (int32_t)6)
+          .set("[Key1]four", (int32_t)4)   // affects Key1
+          .set("[Key1]five", (int32_t)5)   // affects key1
+          .setTimestamp(12);
+
+  ASSERT_EQ(NO_ERROR, timeMachine.put(item3, true));
+
+  ASSERT_EQ((size_t)2, timeMachine.size());
+
+  // Can we read the values?
+  int32_t i32;
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.one", &i32, -1));
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.two", &i32, -1));
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.three", &i32, -1));
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.four", &i32, -1));
+  ASSERT_EQ(BAD_VALUE, timeMachine.get("Key1.five", &i32, -1));
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key2.three", &i32, -1));
+  ASSERT_EQ(3, i32);
+
+  ASSERT_EQ(NO_ERROR, timeMachine.get("Key3.six", &i32, -1));
+  ASSERT_EQ(6, i32);
+
+  printf("After\n%s\n", timeMachine.dump().first.c_str());
+}
+
+TEST(mediametrics_tests, transaction_log_gc) {
+  auto item = std::make_shared<mediametrics::Item>("Key1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2)
+         .setTimestamp(10);
+
+  android::mediametrics::TransactionLog transactionLog(1, 2); // keep at most 2 items
+  ASSERT_EQ((size_t)0, transactionLog.size());
+
+  ASSERT_EQ(NO_ERROR, transactionLog.put(item));
+  ASSERT_EQ((size_t)1, transactionLog.size());
+
+  auto item2 = std::make_shared<mediametrics::Item>("Key2");
+  (*item2).set("three", (int32_t)3)
+         .set("[Key1]three", (int32_t)3)
+         .setTimestamp(11);
+
+  ASSERT_EQ(NO_ERROR, transactionLog.put(item2));
+  ASSERT_EQ((size_t)2, transactionLog.size());
+
+  auto item3 = std::make_shared<mediametrics::Item>("Key3");
+  (*item3).set("six", (int32_t)6)
+          .set("[Key1]four", (int32_t)4)   // affects Key1
+          .set("[Key1]five", (int32_t)5)   // affects key1
+          .setTimestamp(12);
+
+  ASSERT_EQ(NO_ERROR, transactionLog.put(item3));
+  ASSERT_EQ((size_t)2, transactionLog.size());
+}
+
+TEST(mediametrics_tests, analytics_actions) {
+  mediametrics::AnalyticsActions analyticsActions;
+  bool action1 = false;
+  bool action2 = false;
+  bool action3 = false;
+  bool action4 = false;
+
+  // check to see whether various actions have been matched.
+  analyticsActions.addAction(
+      "audio.flinger.event",
+      std::string("AudioFlinger"),
+      std::make_shared<mediametrics::AnalyticsActions::Function>(
+          [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+            action1 = true;
+          }));
+
+  analyticsActions.addAction(
+      "audio.*.event",
+      std::string("AudioFlinger"),
+      std::make_shared<mediametrics::AnalyticsActions::Function>(
+          [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+            action2 = true;
+          }));
+
+  analyticsActions.addAction("audio.fl*n*g*r.event",
+      std::string("AudioFlinger"),
+      std::make_shared<mediametrics::AnalyticsActions::Function>(
+          [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+            action3 = true;
+          }));
+
+  analyticsActions.addAction("audio.fl*gn*r.event",
+      std::string("AudioFlinger"),
+      std::make_shared<mediametrics::AnalyticsActions::Function>(
+          [&](const std::shared_ptr<const android::mediametrics::Item> &) {
+            action4 = true;
+          }));
+
+  // make a test item
+  auto item = std::make_shared<mediametrics::Item>("audio.flinger");
+  (*item).set("event", "AudioFlinger");
+
+  // get the actions and execute them
+  auto actions = analyticsActions.getActionsForItem(item);
+  for (const auto& action : actions) {
+    action->operator()(item);
+  }
+
+  // The following should match.
+  ASSERT_EQ(true, action1);
+  ASSERT_EQ(true, action2);
+  ASSERT_EQ(true, action3);
+  ASSERT_EQ(false, action4); // audio.fl*gn*r != audio.flinger
+}
+
+TEST(mediametrics_tests, audio_analytics_permission) {
+  auto item = std::make_shared<mediametrics::Item>("audio.1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2)
+         .setTimestamp(10);
+
+  auto item2 = std::make_shared<mediametrics::Item>("audio.1");
+  (*item2).set("three", (int32_t)3)
+         .setTimestamp(11);
+
+  auto item3 = std::make_shared<mediametrics::Item>("audio.2");
+  (*item3).set("four", (int32_t)4)
+          .setTimestamp(12);
+
+  android::mediametrics::AudioAnalytics audioAnalytics;
+
+  // untrusted entities cannot create a new key.
+  ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
+  ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
+
+  // TODO: Verify contents of AudioAnalytics.
+  // Currently there is no getter API in AudioAnalytics besides dump.
+  ASSERT_EQ(11, audioAnalytics.dump(1000).second /* lines */);
+
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+  // untrusted entities can add to an existing key
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+
+  // Check that we have some info in the dump.
+  ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
+}
+
+TEST(mediametrics_tests, audio_analytics_permission2) {
+  constexpr int32_t transactionUid = 1010; // arbitrary
+  auto item = std::make_shared<mediametrics::Item>("audio.1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2)
+         .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid)
+         .setTimestamp(10);
+
+  // item2 submitted untrusted
+  auto item2 = std::make_shared<mediametrics::Item>("audio.1");
+  (*item2).set("three", (int32_t)3)
+         .setUid(transactionUid)
+         .setTimestamp(11);
+
+  auto item3 = std::make_shared<mediametrics::Item>("audio.2");
+  (*item3).set("four", (int32_t)4)
+          .setTimestamp(12);
+
+  android::mediametrics::AudioAnalytics audioAnalytics;
+
+  // untrusted entities cannot create a new key.
+  ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item, false /* isTrusted */));
+  ASSERT_EQ(PERMISSION_DENIED, audioAnalytics.submit(item2, false /* isTrusted */));
+
+  // TODO: Verify contents of AudioAnalytics.
+  // Currently there is no getter API in AudioAnalytics besides dump.
+  ASSERT_EQ(11, audioAnalytics.dump(1000).second /* lines */);
+
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+  // untrusted entities can add to an existing key
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+
+  // Check that we have some info in the dump.
+  ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
+}
+
+TEST(mediametrics_tests, audio_analytics_dump) {
+  auto item = std::make_shared<mediametrics::Item>("audio.1");
+  (*item).set("one", (int32_t)1)
+         .set("two", (int32_t)2)
+         .setTimestamp(10);
+
+  auto item2 = std::make_shared<mediametrics::Item>("audio.1");
+  (*item2).set("three", (int32_t)3)
+         .setTimestamp(11);
+
+  auto item3 = std::make_shared<mediametrics::Item>("audio.2");
+  (*item3).set("four", (int32_t)4)
+          .setTimestamp(12);
+
+  android::mediametrics::AudioAnalytics audioAnalytics;
+
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
+  // untrusted entities can add to an existing key
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
+  ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
+
+  // find out how many lines we have.
+  auto [string, lines] = audioAnalytics.dump(1000);
+  ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
+
+  printf("AudioAnalytics: %s", string.c_str());
+  // ensure that dump operates over those lines.
+  for (int32_t ll = 0; ll < lines; ++ll) {
+      auto [s, l] = audioAnalytics.dump(ll);
+      ASSERT_EQ(ll, l);
+      ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
+  }
+}
+
+TEST(mediametrics_tests, device_parsing) {
+    auto devaddr = android::mediametrics::stringutils::getDeviceAddressPairs("(DEVICE, )");
+    ASSERT_EQ((size_t)1, devaddr.size());
+    ASSERT_EQ("DEVICE", devaddr[0].first);
+    ASSERT_EQ("", devaddr[0].second);
+
+    devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
+            "(DEVICE1, A)|(D, ADDRB)");
+    ASSERT_EQ((size_t)2, devaddr.size());
+    ASSERT_EQ("DEVICE1", devaddr[0].first);
+    ASSERT_EQ("A", devaddr[0].second);
+    ASSERT_EQ("D", devaddr[1].first);
+    ASSERT_EQ("ADDRB", devaddr[1].second);
+
+    devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
+            "(A,B)|(C,D)");
+    ASSERT_EQ((size_t)2, devaddr.size());
+    ASSERT_EQ("A", devaddr[0].first);
+    ASSERT_EQ("B", devaddr[0].second);
+    ASSERT_EQ("C", devaddr[1].first);
+    ASSERT_EQ("D", devaddr[1].second);
+
+    devaddr = android::mediametrics::stringutils::getDeviceAddressPairs(
+            "  ( A1 , B )  | ( C , D2 )  ");
+    ASSERT_EQ((size_t)2, devaddr.size());
+    ASSERT_EQ("A1", devaddr[0].first);
+    ASSERT_EQ("B", devaddr[0].second);
+    ASSERT_EQ("C", devaddr[1].first);
+    ASSERT_EQ("D2", devaddr[1].second);
+}
+
+TEST(mediametrics_tests, timed_action) {
+    android::mediametrics::TimedAction timedAction;
+    std::atomic_int value1 = 0;
+
+    timedAction.postIn(std::chrono::seconds(0), [&value1] { ++value1; });
+    timedAction.postIn(std::chrono::seconds(1000), [&value1] { ++value1; });
+    usleep(100000);
+    ASSERT_EQ(1, value1);
+    ASSERT_EQ((size_t)1, timedAction.size());
+}
+
+// Ensure we don't introduce unexpected duplicates into our maps.
+TEST(mediametrics_tests, audio_types_tables) {
+    using namespace android::mediametrics::types;
+
+    ASSERT_EQ(0, countDuplicates(getAudioCallerNameMap()));
+    ASSERT_EQ(2, countDuplicates(getAudioDeviceInMap()));  // has dups
+    ASSERT_EQ(1, countDuplicates(getAudioDeviceOutMap())); // has dups
+    ASSERT_EQ(0, countDuplicates(getAudioThreadTypeMap()));
+    ASSERT_EQ(0, countDuplicates(getAudioTrackTraitsMap()));
+}
+
+// Check our string validation (before logging to statsd).
+// This variant checks the logged, possibly shortened string.
+TEST(mediametrics_tests, audio_types_string) {
+    using namespace android::mediametrics::types;
+
+    ASSERT_EQ("java", (lookup<CALLER_NAME, std::string>)("java"));
+    ASSERT_EQ("", (lookup<CALLER_NAME, std::string>)("random"));
+
+    ASSERT_EQ("SPEECH", (lookup<CONTENT_TYPE, std::string>)("AUDIO_CONTENT_TYPE_SPEECH"));
+    ASSERT_EQ("", (lookup<CONTENT_TYPE, std::string>)("random"));
+
+    ASSERT_EQ("FLAC", (lookup<ENCODING, std::string>)("AUDIO_FORMAT_FLAC"));
+    ASSERT_EQ("", (lookup<ENCODING, std::string>)("random"));
+
+    ASSERT_EQ("USB_DEVICE", (lookup<INPUT_DEVICE, std::string>)("AUDIO_DEVICE_IN_USB_DEVICE"));
+    ASSERT_EQ("BUILTIN_MIC|WIRED_HEADSET", (lookup<INPUT_DEVICE, std::string>)(
+            "AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET"));
+    ASSERT_EQ("", (lookup<INPUT_DEVICE, std::string>)("random"));
+
+    ASSERT_EQ("RAW", (lookup<INPUT_FLAG, std::string>)("AUDIO_INPUT_FLAG_RAW"));
+    ASSERT_EQ("HW_AV_SYNC|VOIP_TX", (lookup<INPUT_FLAG, std::string>)(
+            "AUDIO_INPUT_FLAG_HW_AV_SYNC|AUDIO_INPUT_FLAG_VOIP_TX"));
+    ASSERT_EQ("", (lookup<INPUT_FLAG, std::string>)("random"));
+
+    ASSERT_EQ("BLUETOOTH_SCO_CARKIT",
+            (lookup<OUTPUT_DEVICE, std::string>)("AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"));
+    ASSERT_EQ("SPEAKER|HDMI", (lookup<OUTPUT_DEVICE, std::string>)(
+            "AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_HDMI"));
+    ASSERT_EQ("", (lookup<OUTPUT_DEVICE, std::string>)("random"));
+
+    ASSERT_EQ("PRIMARY", (lookup<OUTPUT_FLAG, std::string>)("AUDIO_OUTPUT_FLAG_PRIMARY"));
+    ASSERT_EQ("DEEP_BUFFER|NON_BLOCKING", (lookup<OUTPUT_FLAG, std::string>)(
+            "AUDIO_OUTPUT_FLAG_DEEP_BUFFER|AUDIO_OUTPUT_FLAG_NON_BLOCKING"));
+    ASSERT_EQ("", (lookup<OUTPUT_FLAG, std::string>)("random"));
+
+    ASSERT_EQ("MIC", (lookup<SOURCE_TYPE, std::string>)("AUDIO_SOURCE_MIC"));
+    ASSERT_EQ("", (lookup<SOURCE_TYPE, std::string>)("random"));
+
+    ASSERT_EQ("TTS", (lookup<STREAM_TYPE, std::string>)("AUDIO_STREAM_TTS"));
+    ASSERT_EQ("", (lookup<STREAM_TYPE, std::string>)("random"));
+
+    ASSERT_EQ("DIRECT", (lookup<THREAD_TYPE, std::string>)("DIRECT"));
+    ASSERT_EQ("", (lookup<THREAD_TYPE, std::string>)("random"));
+
+    ASSERT_EQ("static", (lookup<TRACK_TRAITS, std::string>)("static"));
+    ASSERT_EQ("", (lookup<TRACK_TRAITS, std::string>)("random"));
+
+    ASSERT_EQ("VOICE_COMMUNICATION",
+            (lookup<USAGE, std::string>)("AUDIO_USAGE_VOICE_COMMUNICATION"));
+    ASSERT_EQ("", (lookup<USAGE, std::string>)("random"));
+}
+
+// Check our string validation (before logging to statsd).
+// This variant checks integral value logging.
+TEST(mediametrics_tests, audio_types_integer) {
+    using namespace android::mediametrics::types;
+
+    ASSERT_EQ(2, (lookup<CALLER_NAME, int32_t>)("java"));
+    ASSERT_EQ(0, (lookup<CALLER_NAME, int32_t>)("random")); // 0 == unknown
+
+    ASSERT_EQ((int32_t)AUDIO_CONTENT_TYPE_SPEECH,
+            (lookup<CONTENT_TYPE, int32_t>)("AUDIO_CONTENT_TYPE_SPEECH"));
+    ASSERT_EQ((int32_t)AUDIO_CONTENT_TYPE_UNKNOWN, (lookup<CONTENT_TYPE, int32_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_FORMAT_FLAC, (lookup<ENCODING, int32_t>)("AUDIO_FORMAT_FLAC"));
+    ASSERT_EQ((int32_t)AUDIO_FORMAT_INVALID, (lookup<ENCODING, int32_t>)("random"));
+
+    ASSERT_EQ(getAudioDeviceInMap().at("AUDIO_DEVICE_IN_USB_DEVICE"),
+            (lookup<INPUT_DEVICE, int64_t>)("AUDIO_DEVICE_IN_USB_DEVICE"));
+    ASSERT_EQ(getAudioDeviceInMap().at("AUDIO_DEVICE_IN_BUILTIN_MIC")
+            | getAudioDeviceInMap().at("AUDIO_DEVICE_IN_WIRED_HEADSET"),
+            (lookup<INPUT_DEVICE, int64_t>)(
+            "AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET"));
+    ASSERT_EQ(0, (lookup<INPUT_DEVICE, int64_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_INPUT_FLAG_RAW,
+            (lookup<INPUT_FLAG, int32_t>)("AUDIO_INPUT_FLAG_RAW"));
+    ASSERT_EQ((int32_t)AUDIO_INPUT_FLAG_HW_AV_SYNC
+            | (int32_t)AUDIO_INPUT_FLAG_VOIP_TX,
+            (lookup<INPUT_FLAG, int32_t>)(
+            "AUDIO_INPUT_FLAG_HW_AV_SYNC|AUDIO_INPUT_FLAG_VOIP_TX"));
+    ASSERT_EQ(0, (lookup<INPUT_FLAG, int32_t>)("random"));
+
+    ASSERT_EQ(getAudioDeviceOutMap().at("AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"),
+            (lookup<OUTPUT_DEVICE, int64_t>)("AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"));
+    ASSERT_EQ(getAudioDeviceOutMap().at("AUDIO_DEVICE_OUT_SPEAKER")
+            | getAudioDeviceOutMap().at("AUDIO_DEVICE_OUT_HDMI"),
+            (lookup<OUTPUT_DEVICE, int64_t>)(
+            "AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_HDMI"));
+    ASSERT_EQ(0, (lookup<OUTPUT_DEVICE, int64_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_OUTPUT_FLAG_PRIMARY,
+            (lookup<OUTPUT_FLAG, int32_t>)("AUDIO_OUTPUT_FLAG_PRIMARY"));
+    ASSERT_EQ((int32_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER | (int32_t)AUDIO_OUTPUT_FLAG_NON_BLOCKING,
+            (lookup<OUTPUT_FLAG, int32_t>)(
+            "AUDIO_OUTPUT_FLAG_DEEP_BUFFER|AUDIO_OUTPUT_FLAG_NON_BLOCKING"));
+    ASSERT_EQ(0, (lookup<OUTPUT_FLAG, int32_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_SOURCE_MIC, (lookup<SOURCE_TYPE, int32_t>)("AUDIO_SOURCE_MIC"));
+    ASSERT_EQ((int32_t)AUDIO_SOURCE_DEFAULT, (lookup<SOURCE_TYPE, int32_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_STREAM_TTS, (lookup<STREAM_TYPE, int32_t>)("AUDIO_STREAM_TTS"));
+    ASSERT_EQ((int32_t)AUDIO_STREAM_DEFAULT, (lookup<STREAM_TYPE, int32_t>)("random"));
+
+    ASSERT_EQ(1, (lookup<THREAD_TYPE, int32_t>)("DIRECT"));
+    ASSERT_EQ(-1, (lookup<THREAD_TYPE, int32_t>)("random"));
+
+    ASSERT_EQ(getAudioTrackTraitsMap().at("static"), (lookup<TRACK_TRAITS, int32_t>)("static"));
+    ASSERT_EQ(0, (lookup<TRACK_TRAITS, int32_t>)("random"));
+
+    ASSERT_EQ((int32_t)AUDIO_USAGE_VOICE_COMMUNICATION,
+            (lookup<USAGE, int32_t>)("AUDIO_USAGE_VOICE_COMMUNICATION"));
+    ASSERT_EQ((int32_t)AUDIO_USAGE_UNKNOWN, (lookup<USAGE, int32_t>)("random"));
+}
+
+#if 0
+// Stress test code for garbage collection, you need to enable AID_SHELL as trusted to run
+// in MediaMetricsService.cpp.
+//
+// TODO: Make a dedicated stress test.
+//
+TEST(mediametrics_tests, gc_same_key) {
+  // random keys ignored when empty
+  for (int i = 0; i < 10000000; ++i) {
+      std::unique_ptr<mediametrics::Item> test_key(mediametrics::Item::create("audio.zzz.123"));
+      test_key->set("event#", "hello");
+      test_key->set("value",  (int)10);
+      test_key->selfrecord();
+  }
+  //mediaMetrics->dump(fileno(stdout), {} /* args */);
+}
+#endif
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index f3339a0..a3519d5 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -12,6 +12,7 @@
         "libmedia",
         "libmediautils",
         "libbinder",
+        "libbinder_ndk",
         "libutils",
         "liblog",
     ],
@@ -23,4 +24,6 @@
         "-Wall",
     ],
 
+    export_include_dirs: ["."],
+
 }
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index bdcd5e4..3d36f8e 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -19,10 +19,13 @@
 #define LOG_TAG "ResourceManagerService"
 #include <utils/Log.h>
 
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <binder/IMediaResourceMonitor.h>
 #include <binder/IServiceManager.h>
 #include <cutils/sched_policy.h>
 #include <dirent.h>
+#include <media/MediaResourcePolicy.h>
 #include <media/stagefright/ProcessInfo.h>
 #include <mediautils/BatteryNotifier.h>
 #include <mediautils/SchedulingPolicyService.h>
@@ -37,43 +40,42 @@
 
 namespace android {
 
-namespace {
+DeathNotifier::DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
+        int pid, int64_t clientId)
+    : mService(service), mPid(pid), mClientId(clientId) {}
 
-class DeathNotifier : public IBinder::DeathRecipient {
-public:
-    DeathNotifier(const wp<ResourceManagerService> &service, int pid, int64_t clientId)
-        : mService(service), mPid(pid), mClientId(clientId) {}
+//static
+void DeathNotifier::BinderDiedCallback(void* cookie) {
+    auto thiz = static_cast<DeathNotifier*>(cookie);
+    thiz->binderDied();
+}
 
-    virtual void binderDied(const wp<IBinder> & /* who */) override {
-        // Don't check for pid validity since we know it's already dead.
-        sp<ResourceManagerService> service = mService.promote();
-        if (service == nullptr) {
-            ALOGW("ResourceManagerService is dead as well.");
-            return;
-        }
-        service->removeResource(mPid, mClientId, false);
+void DeathNotifier::binderDied() {
+    // Don't check for pid validity since we know it's already dead.
+    std::shared_ptr<ResourceManagerService> service = mService.lock();
+    if (service == nullptr) {
+        ALOGW("ResourceManagerService is dead as well.");
+        return;
     }
 
-private:
-    wp<ResourceManagerService> mService;
-    int mPid;
-    int64_t mClientId;
-};
+    service->overridePid(mPid, -1);
+    // thiz is freed in the call below, so it must be last call referring thiz
+    service->removeResource(mPid, mClientId, false);
 
-}  // namespace
+}
 
 template <typename T>
-static String8 getString(const Vector<T> &items) {
+static String8 getString(const std::vector<T> &items) {
     String8 itemsStr;
     for (size_t i = 0; i < items.size(); ++i) {
-        itemsStr.appendFormat("%s ", items[i].toString().string());
+        itemsStr.appendFormat("%s ", toString(items[i]).string());
     }
     return itemsStr;
 }
 
 static bool hasResourceType(MediaResource::Type type, const ResourceList& resources) {
     for (auto it = resources.begin(); it != resources.end(); it++) {
-        if (it->second.mType == type) {
+        if (it->second.type == type) {
             return true;
         }
     }
@@ -105,7 +107,7 @@
 static ResourceInfo& getResourceInfoForEdit(
         uid_t uid,
         int64_t clientId,
-        const sp<IResourceManagerClient>& client,
+        const std::shared_ptr<IResourceManagerClient>& client,
         ResourceInfos& infos) {
     ssize_t index = infos.indexOfKey(clientId);
 
@@ -114,6 +116,7 @@
         info.uid = uid;
         info.clientId = clientId;
         info.client = client;
+        info.pendingRemoval = false;
 
         index = infos.add(clientId, info);
     }
@@ -121,29 +124,30 @@
     return infos.editValueAt(index);
 }
 
-static void notifyResourceGranted(int pid, const Vector<MediaResource> &resources) {
+static void notifyResourceGranted(int pid, const std::vector<MediaResourceParcel> &resources) {
     static const char* const kServiceName = "media_resource_monitor";
     sp<IBinder> binder = defaultServiceManager()->checkService(String16(kServiceName));
     if (binder != NULL) {
         sp<IMediaResourceMonitor> service = interface_cast<IMediaResourceMonitor>(binder);
         for (size_t i = 0; i < resources.size(); ++i) {
-            if (resources[i].mSubType == MediaResource::kAudioCodec) {
+            if (resources[i].subType == MediaResource::SubType::kAudioCodec) {
                 service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_AUDIO_CODEC);
-            } else if (resources[i].mSubType == MediaResource::kVideoCodec) {
+            } else if (resources[i].subType == MediaResource::SubType::kVideoCodec) {
                 service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_VIDEO_CODEC);
             }
         }
     }
 }
 
-status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */) {
+binder_status_t ResourceManagerService::dump(
+        int fd, const char** /*args*/, uint32_t /*numArgs*/) {
     String8 result;
 
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         result.format("Permission Denial: "
                 "can't dump ResourceManagerService from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
-                IPCThreadState::self()->getCallingUid());
+                AIBinder_getCallingPid(),
+                AIBinder_getCallingUid());
         write(fd, result.string(), result.size());
         return PERMISSION_DENIED;
     }
@@ -151,6 +155,7 @@
     PidResourceInfosMap mapCopy;
     bool supportsMultipleSecureCodecs;
     bool supportsSecureWithNonSecureCodec;
+    std::map<int, int> overridePidMapCopy;
     String8 serviceLog;
     {
         Mutex::Autolock lock(mLock);
@@ -158,6 +163,7 @@
         supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs;
         supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec;
         serviceLog = mServiceLog->toString("    " /* linePrefix */);
+        overridePidMapCopy = mOverridePidMap;
     }
 
     const size_t SIZE = 256;
@@ -182,17 +188,28 @@
             snprintf(buffer, SIZE, "        Id: %lld\n", (long long)infos[j].clientId);
             result.append(buffer);
 
-            snprintf(buffer, SIZE, "        Name: %s\n", infos[j].client->getName().string());
+            std::string clientName;
+            Status status = infos[j].client->getName(&clientName);
+            if (!status.isOk()) {
+                clientName = "<unknown client>";
+            }
+            snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
             result.append(buffer);
 
             const ResourceList &resources = infos[j].resources;
             result.append("        Resources:\n");
             for (auto it = resources.begin(); it != resources.end(); it++) {
-                snprintf(buffer, SIZE, "          %s\n", it->second.toString().string());
+                snprintf(buffer, SIZE, "          %s\n", toString(it->second).string());
                 result.append(buffer);
             }
         }
     }
+    result.append("  Process Pid override:\n");
+    for (auto it = overridePidMapCopy.begin(); it != overridePidMapCopy.end(); ++it) {
+        snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n",
+            it->first, it->second);
+        result.append(buffer);
+    }
     result.append("  Events logs (most recent at top):\n");
     result.append(serviceLog);
 
@@ -202,7 +219,7 @@
 
 struct SystemCallbackImpl :
         public ResourceManagerService::SystemCallbackInterface {
-    SystemCallbackImpl() {}
+    SystemCallbackImpl() : mClientToken(new BBinder()) {}
 
     virtual void noteStartVideo(int uid) override {
         BatteryNotifier::getInstance().noteStartVideo(uid);
@@ -213,9 +230,8 @@
     virtual void noteResetVideo() override {
         BatteryNotifier::getInstance().noteResetVideo();
     }
-    virtual bool requestCpusetBoost(
-            bool enable, const sp<IInterface> &client) override {
-        return android::requestCpusetBoost(enable, client);
+    virtual bool requestCpusetBoost(bool enable) override {
+        return android::requestCpusetBoost(enable, mClientToken);
     }
 
 protected:
@@ -223,6 +239,7 @@
 
 private:
     DISALLOW_EVIL_CONSTRUCTORS(SystemCallbackImpl);
+    sp<IBinder> mClientToken;
 };
 
 ResourceManagerService::ResourceManagerService()
@@ -236,66 +253,100 @@
       mServiceLog(new ServiceLog()),
       mSupportsMultipleSecureCodecs(true),
       mSupportsSecureWithNonSecureCodec(true),
-      mCpuBoostCount(0) {
+      mCpuBoostCount(0),
+      mDeathRecipient(AIBinder_DeathRecipient_new(DeathNotifier::BinderDiedCallback)) {
     mSystemCB->noteResetVideo();
 }
 
+//static
+void ResourceManagerService::instantiate() {
+    std::shared_ptr<ResourceManagerService> service =
+            ::ndk::SharedRefBase::make<ResourceManagerService>();
+    binder_status_t status =
+            AServiceManager_addService(service->asBinder().get(), getServiceName());
+    if (status != STATUS_OK) {
+        return;
+    }
+    // TODO: mediaserver main() is already starting the thread pool,
+    // move this to mediaserver main() when other services in mediaserver
+    // are converted to ndk-platform aidl.
+    //ABinderProcess_startThreadPool();
+}
+
 ResourceManagerService::~ResourceManagerService() {}
 
-void ResourceManagerService::config(const Vector<MediaResourcePolicy> &policies) {
+Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
     String8 log = String8::format("config(%s)", getString(policies).string());
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
     for (size_t i = 0; i < policies.size(); ++i) {
-        String8 type = policies[i].mType;
-        String8 value = policies[i].mValue;
-        if (type == kPolicySupportsMultipleSecureCodecs) {
+        const std::string &type = policies[i].type;
+        const std::string &value = policies[i].value;
+        if (type == MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs()) {
             mSupportsMultipleSecureCodecs = (value == "true");
-        } else if (type == kPolicySupportsSecureWithNonSecureCodec) {
+        } else if (type == MediaResourcePolicy::kPolicySupportsSecureWithNonSecureCodec()) {
             mSupportsSecureWithNonSecureCodec = (value == "true");
         }
     }
+    return Status::ok();
 }
 
 void ResourceManagerService::onFirstAdded(
-        const MediaResource& resource, const ResourceInfo& clientInfo) {
+        const MediaResourceParcel& resource, const ResourceInfo& clientInfo) {
     // first time added
-    if (resource.mType == MediaResource::kCpuBoost
-     && resource.mSubType == MediaResource::kUnspecifiedSubType) {
+    if (resource.type == MediaResource::Type::kCpuBoost
+     && resource.subType == MediaResource::SubType::kUnspecifiedSubType) {
         // Request it on every new instance of kCpuBoost, as the media.codec
         // could have died, if we only do it the first time subsequent instances
         // never gets the boost.
-        if (mSystemCB->requestCpusetBoost(true, this) != OK) {
+        if (mSystemCB->requestCpusetBoost(true) != OK) {
             ALOGW("couldn't request cpuset boost");
         }
         mCpuBoostCount++;
-    } else if (resource.mType == MediaResource::kBattery
-            && resource.mSubType == MediaResource::kVideoCodec) {
+    } else if (resource.type == MediaResource::Type::kBattery
+            && resource.subType == MediaResource::SubType::kVideoCodec) {
         mSystemCB->noteStartVideo(clientInfo.uid);
     }
 }
 
 void ResourceManagerService::onLastRemoved(
-        const MediaResource& resource, const ResourceInfo& clientInfo) {
-    if (resource.mType == MediaResource::kCpuBoost
-            && resource.mSubType == MediaResource::kUnspecifiedSubType
+        const MediaResourceParcel& resource, const ResourceInfo& clientInfo) {
+    if (resource.type == MediaResource::Type::kCpuBoost
+            && resource.subType == MediaResource::SubType::kUnspecifiedSubType
             && mCpuBoostCount > 0) {
         if (--mCpuBoostCount == 0) {
-            mSystemCB->requestCpusetBoost(false, this);
+            mSystemCB->requestCpusetBoost(false);
         }
-    } else if (resource.mType == MediaResource::kBattery
-            && resource.mSubType == MediaResource::kVideoCodec) {
+    } else if (resource.type == MediaResource::Type::kBattery
+            && resource.subType == MediaResource::SubType::kVideoCodec) {
         mSystemCB->noteStopVideo(clientInfo.uid);
     }
 }
 
-void ResourceManagerService::addResource(
-        int pid,
-        int uid,
+void ResourceManagerService::mergeResources(
+        MediaResourceParcel& r1, const MediaResourceParcel& r2) {
+    // The resource entry on record is maintained to be in [0,INT64_MAX].
+    // Clamp if merging in the new resource value causes it to go out of bound.
+    // Note that the new resource value could be negative, eg.DrmSession, the
+    // value goes lower when the session is used more often. During reclaim
+    // the session with the highest value (lowest usage) would be closed.
+    if (r2.value < INT64_MAX - r1.value) {
+        r1.value += r2.value;
+        if (r1.value < 0) {
+            r1.value = 0;
+        }
+    } else {
+        r1.value = INT64_MAX;
+    }
+}
+
+Status ResourceManagerService::addResource(
+        int32_t pid,
+        int32_t uid,
         int64_t clientId,
-        const sp<IResourceManagerClient> client,
-        const Vector<MediaResource> &resources) {
+        const std::shared_ptr<IResourceManagerClient>& client,
+        const std::vector<MediaResourceParcel>& resources) {
     String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
             pid, (long long) clientId, getString(resources).string());
     mServiceLog->add(log);
@@ -303,29 +354,44 @@
     Mutex::Autolock lock(mLock);
     if (!mProcessInfo->isValidPid(pid)) {
         ALOGE("Rejected addResource call with invalid pid.");
-        return;
+        return Status::fromServiceSpecificError(BAD_VALUE);
     }
     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
     ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
 
     for (size_t i = 0; i < resources.size(); ++i) {
-        const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
+        const auto &res = resources[i];
+        const auto resType = std::tuple(res.type, res.subType, res.id);
+
+        if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
+            ALOGW("Ignoring request to remove negative value of non-drm resource");
+            continue;
+        }
         if (info.resources.find(resType) == info.resources.end()) {
-            onFirstAdded(resources[i], info);
-            info.resources[resType] = resources[i];
+            if (res.value <= 0) {
+                // We can't init a new entry with negative value, although it's allowed
+                // to merge in negative values after the initial add.
+                ALOGW("Ignoring request to add new resource entry with value <= 0");
+                continue;
+            }
+            onFirstAdded(res, info);
+            info.resources[resType] = res;
         } else {
-            info.resources[resType].mValue += resources[i].mValue;
+            mergeResources(info.resources[resType], res);
         }
     }
-    if (info.deathNotifier == nullptr) {
-        info.deathNotifier = new DeathNotifier(this, pid, clientId);
-        IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
+    if (info.deathNotifier == nullptr && client != nullptr) {
+        info.deathNotifier = new DeathNotifier(ref<ResourceManagerService>(), pid, clientId);
+        AIBinder_linkToDeath(client->asBinder().get(),
+                mDeathRecipient.get(), info.deathNotifier.get());
     }
     notifyResourceGranted(pid, resources);
+    return Status::ok();
 }
 
-void ResourceManagerService::removeResource(int pid, int64_t clientId,
-        const Vector<MediaResource> &resources) {
+Status ResourceManagerService::removeResource(
+        int32_t pid, int64_t clientId,
+        const std::vector<MediaResourceParcel>& resources) {
     String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
             pid, (long long) clientId, getString(resources).string());
     mServiceLog->add(log);
@@ -333,43 +399,51 @@
     Mutex::Autolock lock(mLock);
     if (!mProcessInfo->isValidPid(pid)) {
         ALOGE("Rejected removeResource call with invalid pid.");
-        return;
+        return Status::fromServiceSpecificError(BAD_VALUE);
     }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
-        return;
+        return Status::ok();
     }
     ResourceInfos &infos = mMap.editValueAt(index);
 
     index = infos.indexOfKey(clientId);
     if (index < 0) {
         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
-        return;
+        return Status::ok();
     }
 
     ResourceInfo &info = infos.editValueAt(index);
 
     for (size_t i = 0; i < resources.size(); ++i) {
-        const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
+        const auto &res = resources[i];
+        const auto resType = std::tuple(res.type, res.subType, res.id);
+
+        if (res.value < 0) {
+            ALOGW("Ignoring request to remove negative value of resource");
+            continue;
+        }
         // ignore if we don't have it
         if (info.resources.find(resType) != info.resources.end()) {
-            MediaResource &resource = info.resources[resType];
-            if (resource.mValue > resources[i].mValue) {
-                resource.mValue -= resources[i].mValue;
+            MediaResourceParcel &resource = info.resources[resType];
+            if (resource.value > res.value) {
+                resource.value -= res.value;
             } else {
-                onLastRemoved(resources[i], info);
+                onLastRemoved(res, info);
                 info.resources.erase(resType);
             }
         }
     }
+    return Status::ok();
 }
 
-void ResourceManagerService::removeClient(int pid, int64_t clientId) {
+Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
     removeResource(pid, clientId, true);
+    return Status::ok();
 }
 
-void ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
+Status ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
     String8 log = String8::format(
             "removeResource(pid %d, clientId %lld)",
             pid, (long long) clientId);
@@ -378,19 +452,19 @@
     Mutex::Autolock lock(mLock);
     if (checkValid && !mProcessInfo->isValidPid(pid)) {
         ALOGE("Rejected removeResource call with invalid pid.");
-        return;
+        return Status::fromServiceSpecificError(BAD_VALUE);
     }
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
-        return;
+        return Status::ok();
     }
     ResourceInfos &infos = mMap.editValueAt(index);
 
     index = infos.indexOfKey(clientId);
     if (index < 0) {
         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
-        return;
+        return Status::ok();
     }
 
     const ResourceInfo &info = infos[index];
@@ -398,69 +472,84 @@
         onLastRemoved(it->second, info);
     }
 
-    IInterface::asBinder(info.client)->unlinkToDeath(info.deathNotifier);
+    AIBinder_unlinkToDeath(info.client->asBinder().get(),
+            mDeathRecipient.get(), info.deathNotifier.get());
 
     infos.removeItemsAt(index);
+    return Status::ok();
 }
 
 void ResourceManagerService::getClientForResource_l(
-        int callingPid, const MediaResource *res, Vector<sp<IResourceManagerClient>> *clients) {
+        int callingPid, const MediaResourceParcel *res,
+        Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
     if (res == NULL) {
         return;
     }
-    sp<IResourceManagerClient> client;
-    if (getLowestPriorityBiggestClient_l(callingPid, res->mType, &client)) {
+    std::shared_ptr<IResourceManagerClient> client;
+    if (getLowestPriorityBiggestClient_l(callingPid, res->type, &client)) {
         clients->push_back(client);
     }
 }
 
-bool ResourceManagerService::reclaimResource(
-        int callingPid, const Vector<MediaResource> &resources) {
+Status ResourceManagerService::reclaimResource(
+        int32_t callingPid,
+        const std::vector<MediaResourceParcel>& resources,
+        bool* _aidl_return) {
     String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
             callingPid, getString(resources).string());
     mServiceLog->add(log);
+    *_aidl_return = false;
 
-    Vector<sp<IResourceManagerClient>> clients;
+    Vector<std::shared_ptr<IResourceManagerClient>> clients;
     {
         Mutex::Autolock lock(mLock);
         if (!mProcessInfo->isValidPid(callingPid)) {
             ALOGE("Rejected reclaimResource call with invalid callingPid.");
-            return false;
+            return Status::fromServiceSpecificError(BAD_VALUE);
         }
-        const MediaResource *secureCodec = NULL;
-        const MediaResource *nonSecureCodec = NULL;
-        const MediaResource *graphicMemory = NULL;
+        const MediaResourceParcel *secureCodec = NULL;
+        const MediaResourceParcel *nonSecureCodec = NULL;
+        const MediaResourceParcel *graphicMemory = NULL;
+        const MediaResourceParcel *drmSession = NULL;
         for (size_t i = 0; i < resources.size(); ++i) {
-            MediaResource::Type type = resources[i].mType;
-            if (resources[i].mType == MediaResource::kSecureCodec) {
+            MediaResource::Type type = resources[i].type;
+            if (resources[i].type == MediaResource::Type::kSecureCodec) {
                 secureCodec = &resources[i];
-            } else if (type == MediaResource::kNonSecureCodec) {
+            } else if (type == MediaResource::Type::kNonSecureCodec) {
                 nonSecureCodec = &resources[i];
-            } else if (type == MediaResource::kGraphicMemory) {
+            } else if (type == MediaResource::Type::kGraphicMemory) {
                 graphicMemory = &resources[i];
+            } else if (type == MediaResource::Type::kDrmSession) {
+                drmSession = &resources[i];
             }
         }
 
         // first pass to handle secure/non-secure codec conflict
         if (secureCodec != NULL) {
             if (!mSupportsMultipleSecureCodecs) {
-                if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
-                    return false;
+                if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec, &clients)) {
+                    return Status::ok();
                 }
             }
             if (!mSupportsSecureWithNonSecureCodec) {
-                if (!getAllClients_l(callingPid, MediaResource::kNonSecureCodec, &clients)) {
-                    return false;
+                if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec, &clients)) {
+                    return Status::ok();
                 }
             }
         }
         if (nonSecureCodec != NULL) {
             if (!mSupportsSecureWithNonSecureCodec) {
-                if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
-                    return false;
+                if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec, &clients)) {
+                    return Status::ok();
                 }
             }
         }
+        if (drmSession != NULL) {
+            getClientForResource_l(callingPid, drmSession, &clients);
+            if (clients.size() == 0) {
+                return Status::ok();
+            }
+        }
 
         if (clients.size() == 0) {
             // if no secure/non-secure codec conflict, run second pass to handle other resources.
@@ -476,32 +565,35 @@
         if (clients.size() == 0) {
             // if we are here, run the fourth pass to free one codec with the different type.
             if (secureCodec != NULL) {
-                MediaResource temp(MediaResource::kNonSecureCodec, 1);
+                MediaResource temp(MediaResource::Type::kNonSecureCodec, 1);
                 getClientForResource_l(callingPid, &temp, &clients);
             }
             if (nonSecureCodec != NULL) {
-                MediaResource temp(MediaResource::kSecureCodec, 1);
+                MediaResource temp(MediaResource::Type::kSecureCodec, 1);
                 getClientForResource_l(callingPid, &temp, &clients);
             }
         }
     }
 
     if (clients.size() == 0) {
-        return false;
+        return Status::ok();
     }
 
-    sp<IResourceManagerClient> failedClient;
+    std::shared_ptr<IResourceManagerClient> failedClient;
     for (size_t i = 0; i < clients.size(); ++i) {
         log = String8::format("reclaimResource from client %p", clients[i].get());
         mServiceLog->add(log);
-        if (!clients[i]->reclaimResource()) {
+        bool success;
+        Status status = clients[i]->reclaimResource(&success);
+        if (!status.isOk() || !success) {
             failedClient = clients[i];
             break;
         }
     }
 
     if (failedClient == NULL) {
-        return true;
+        *_aidl_return = true;
+        return Status::ok();
     }
 
     {
@@ -526,12 +618,85 @@
         }
     }
 
-    return false;
+    return Status::ok();
+}
+
+Status ResourceManagerService::overridePid(
+        int originalPid,
+        int newPid) {
+    String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
+            originalPid, newPid);
+    mServiceLog->add(log);
+
+    // allow if this is called from the same process or the process has
+    // permission.
+    if ((AIBinder_getCallingPid() != getpid()) &&
+        (checkCallingPermission(String16(
+             "android.permission.MEDIA_RESOURCE_OVERRIDE_PID")) == false)) {
+      ALOGE(
+          "Permission Denial: can't access overridePid method from pid=%d, "
+          "self pid=%d\n",
+          AIBinder_getCallingPid(), getpid());
+      return Status::fromServiceSpecificError(PERMISSION_DENIED);
+    }
+
+    {
+        Mutex::Autolock lock(mLock);
+        mOverridePidMap.erase(originalPid);
+        if (newPid != -1) {
+            mOverridePidMap.emplace(originalPid, newPid);
+        }
+    }
+
+    return Status::ok();
+}
+
+Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) {
+    String8 log = String8::format(
+            "markClientForPendingRemoval(pid %d, clientId %lld)",
+            pid, (long long) clientId);
+    mServiceLog->add(log);
+
+    Mutex::Autolock lock(mLock);
+    if (!mProcessInfo->isValidPid(pid)) {
+        ALOGE("Rejected markClientForPendingRemoval call with invalid pid.");
+        return Status::fromServiceSpecificError(BAD_VALUE);
+    }
+    ssize_t index = mMap.indexOfKey(pid);
+    if (index < 0) {
+        ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld",
+              pid, (long long)clientId);
+        return Status::ok();
+    }
+    ResourceInfos &infos = mMap.editValueAt(index);
+
+    index = infos.indexOfKey(clientId);
+    if (index < 0) {
+        ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId);
+        return Status::ok();
+    }
+
+    ResourceInfo &info = infos.editValueAt(index);
+    info.pendingRemoval = true;
+    return Status::ok();
+}
+
+bool ResourceManagerService::getPriority_l(int pid, int* priority) {
+    int newPid = pid;
+
+    if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
+        newPid = mOverridePidMap[pid];
+        ALOGD("getPriority_l: use override pid %d instead original pid %d",
+                newPid, pid);
+    }
+
+    return mProcessInfo->getPriority(newPid, priority);
 }
 
 bool ResourceManagerService::getAllClients_l(
-        int callingPid, MediaResource::Type type, Vector<sp<IResourceManagerClient>> *clients) {
-    Vector<sp<IResourceManagerClient>> temp;
+        int callingPid, MediaResource::Type type,
+        Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
+    Vector<std::shared_ptr<IResourceManagerClient>> temp;
     for (size_t i = 0; i < mMap.size(); ++i) {
         ResourceInfos &infos = mMap.editValueAt(i);
         for (size_t j = 0; j < infos.size(); ++j) {
@@ -556,11 +721,18 @@
 }
 
 bool ResourceManagerService::getLowestPriorityBiggestClient_l(
-        int callingPid, MediaResource::Type type, sp<IResourceManagerClient> *client) {
+        int callingPid, MediaResource::Type type,
+        std::shared_ptr<IResourceManagerClient> *client) {
     int lowestPriorityPid;
     int lowestPriority;
     int callingPriority;
-    if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
+
+    // Before looking into other processes, check if we have clients marked for
+    // pending removal in the same process.
+    if (getBiggestClient_l(callingPid, type, client, true /* pendingRemovalOnly */)) {
+        return true;
+    }
+    if (!getPriority_l(callingPid, &callingPriority)) {
         ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d",
                 callingPid);
         return false;
@@ -595,7 +767,7 @@
         }
         int tempPid = mMap.keyAt(i);
         int tempPriority;
-        if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
+        if (!getPriority_l(tempPid, &tempPriority)) {
             ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
             // TODO: remove this pid from mMap?
             continue;
@@ -615,12 +787,12 @@
 
 bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
     int callingPidPriority;
-    if (!mProcessInfo->getPriority(callingPid, &callingPidPriority)) {
+    if (!getPriority_l(callingPid, &callingPidPriority)) {
         return false;
     }
 
     int priority;
-    if (!mProcessInfo->getPriority(pid, &priority)) {
+    if (!getPriority_l(pid, &priority)) {
         return false;
     }
 
@@ -628,23 +800,27 @@
 }
 
 bool ResourceManagerService::getBiggestClient_l(
-        int pid, MediaResource::Type type, sp<IResourceManagerClient> *client) {
+        int pid, MediaResource::Type type, std::shared_ptr<IResourceManagerClient> *client,
+        bool pendingRemovalOnly) {
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
         ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
         return false;
     }
 
-    sp<IResourceManagerClient> clientTemp;
+    std::shared_ptr<IResourceManagerClient> clientTemp;
     uint64_t largestValue = 0;
     const ResourceInfos &infos = mMap.valueAt(index);
     for (size_t i = 0; i < infos.size(); ++i) {
         const ResourceList &resources = infos[i].resources;
+        if (pendingRemovalOnly && !infos[i].pendingRemoval) {
+            continue;
+        }
         for (auto it = resources.begin(); it != resources.end(); it++) {
-            const MediaResource &resource = it->second;
-            if (resource.mType == type) {
-                if (resource.mValue > largestValue) {
-                    largestValue = resource.mValue;
+            const MediaResourceParcel &resource = it->second;
+            if (resource.type == type) {
+                if (resource.value > largestValue) {
+                    largestValue = resource.value;
                     clientTemp = infos[i].client;
                 }
             }
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index f086dc3..ee982b7 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -15,83 +15,119 @@
 ** limitations under the License.
 */
 
-#ifndef ANDROID_RESOURCEMANAGERSERVICE_H
-#define ANDROID_RESOURCEMANAGERSERVICE_H
+#ifndef ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
+#define ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
 
+#include <map>
+
+#include <aidl/android/media/BnResourceManagerService.h>
 #include <arpa/inet.h>
-#include <binder/BinderService.h>
+#include <media/MediaResource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 #include <utils/Vector.h>
 
-#include <media/IResourceManagerService.h>
-
 namespace android {
 
+class DeathNotifier;
+class ResourceManagerService;
 class ServiceLog;
 struct ProcessInfoInterface;
 
-typedef std::map<std::pair<MediaResource::Type, MediaResource::SubType>, MediaResource> ResourceList;
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::IResourceManagerClient;
+using ::aidl::android::media::BnResourceManagerService;
+using ::aidl::android::media::MediaResourceParcel;
+using ::aidl::android::media::MediaResourcePolicyParcel;
+
+typedef std::map<std::tuple<
+        MediaResource::Type, MediaResource::SubType, std::vector<int8_t>>,
+        MediaResourceParcel> ResourceList;
+
 struct ResourceInfo {
     int64_t clientId;
     uid_t uid;
-    sp<IResourceManagerClient> client;
-    sp<IBinder::DeathRecipient> deathNotifier;
+    std::shared_ptr<IResourceManagerClient> client;
+    sp<DeathNotifier> deathNotifier;
     ResourceList resources;
+    bool pendingRemoval{false};
 };
 
 // TODO: convert these to std::map
 typedef KeyedVector<int64_t, ResourceInfo> ResourceInfos;
 typedef KeyedVector<int, ResourceInfos> PidResourceInfosMap;
 
-class ResourceManagerService
-    : public BinderService<ResourceManagerService>,
-      public BnResourceManagerService
-{
+class DeathNotifier : public RefBase {
+public:
+    DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
+            int pid, int64_t clientId);
+
+    ~DeathNotifier() {}
+
+    // Implement death recipient
+    static void BinderDiedCallback(void* cookie);
+    void binderDied();
+
+private:
+    std::weak_ptr<ResourceManagerService> mService;
+    int mPid;
+    int64_t mClientId;
+};
+class ResourceManagerService : public BnResourceManagerService {
 public:
     struct SystemCallbackInterface : public RefBase {
         virtual void noteStartVideo(int uid) = 0;
         virtual void noteStopVideo(int uid) = 0;
         virtual void noteResetVideo() = 0;
-        virtual bool requestCpusetBoost(
-                bool enable, const sp<IInterface> &client) = 0;
+        virtual bool requestCpusetBoost(bool enable) = 0;
     };
 
     static char const *getServiceName() { return "media.resource_manager"; }
+    static void instantiate();
 
-    virtual status_t dump(int fd, const Vector<String16>& args);
+    virtual inline binder_status_t dump(
+            int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
 
     ResourceManagerService();
     explicit ResourceManagerService(
             const sp<ProcessInfoInterface> &processInfo,
             const sp<SystemCallbackInterface> &systemResource);
+    virtual ~ResourceManagerService();
 
     // IResourceManagerService interface
-    virtual void config(const Vector<MediaResourcePolicy> &policies);
+    Status config(const std::vector<MediaResourcePolicyParcel>& policies) override;
 
-    virtual void addResource(
-            int pid,
-            int uid,
+    Status addResource(
+            int32_t pid,
+            int32_t uid,
             int64_t clientId,
-            const sp<IResourceManagerClient> client,
-            const Vector<MediaResource> &resources);
+            const std::shared_ptr<IResourceManagerClient>& client,
+            const std::vector<MediaResourceParcel>& resources) override;
 
-    virtual void removeResource(int pid, int64_t clientId,
-            const Vector<MediaResource> &resources);
+    Status removeResource(
+            int32_t pid,
+            int64_t clientId,
+            const std::vector<MediaResourceParcel>& resources) override;
 
-    virtual void removeClient(int pid, int64_t clientId);
+    Status removeClient(int32_t pid, int64_t clientId) override;
 
     // Tries to reclaim resource from processes with lower priority than the calling process
     // according to the requested resources.
     // Returns true if any resource has been reclaimed, otherwise returns false.
-    virtual bool reclaimResource(int callingPid, const Vector<MediaResource> &resources);
+    Status reclaimResource(
+            int32_t callingPid,
+            const std::vector<MediaResourceParcel>& resources,
+            bool* _aidl_return) override;
 
-    void removeResource(int pid, int64_t clientId, bool checkValid);
+    Status overridePid(
+            int originalPid,
+            int newPid) override;
 
-protected:
-    virtual ~ResourceManagerService();
+    Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
+
+    Status removeResource(int pid, int64_t clientId, bool checkValid);
 
 private:
     friend class ResourceManagerServiceTest;
@@ -100,13 +136,13 @@
     // Returns false if any client belongs to a process with higher priority than the
     // calling process. The clients will remain unchanged if returns false.
     bool getAllClients_l(int callingPid, MediaResource::Type type,
-            Vector<sp<IResourceManagerClient>> *clients);
+            Vector<std::shared_ptr<IResourceManagerClient>> *clients);
 
     // Gets the client who owns specified resource type from lowest possible priority process.
     // Returns false if the calling process priority is not higher than the lowest process
     // priority. The client will remain unchanged if returns false.
     bool getLowestPriorityBiggestClient_l(int callingPid, MediaResource::Type type,
-            sp<IResourceManagerClient> *client);
+            std::shared_ptr<IResourceManagerClient> *client);
 
     // Gets lowest priority process that has the specified resource type.
     // Returns false if failed. The output parameters will remain unchanged if failed.
@@ -114,17 +150,25 @@
 
     // Gets the client who owns biggest piece of specified resource type from pid.
     // Returns false if failed. The client will remain unchanged if failed.
-    bool getBiggestClient_l(int pid, MediaResource::Type type, sp<IResourceManagerClient> *client);
+    bool getBiggestClient_l(int pid, MediaResource::Type type,
+            std::shared_ptr<IResourceManagerClient> *client,
+            bool pendingRemovalOnly = false);
 
     bool isCallingPriorityHigher_l(int callingPid, int pid);
 
-    // A helper function basically calls getLowestPriorityBiggestClient_l and add the result client
-    // to the given Vector.
-    void getClientForResource_l(
-        int callingPid, const MediaResource *res, Vector<sp<IResourceManagerClient>> *clients);
+    // A helper function basically calls getLowestPriorityBiggestClient_l and add
+    // the result client to the given Vector.
+    void getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+            Vector<std::shared_ptr<IResourceManagerClient>> *clients);
 
-    void onFirstAdded(const MediaResource& res, const ResourceInfo& clientInfo);
-    void onLastRemoved(const MediaResource& res, const ResourceInfo& clientInfo);
+    void onFirstAdded(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
+    void onLastRemoved(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
+
+    // Merge r2 into r1
+    void mergeResources(MediaResourceParcel& r1, const MediaResourceParcel& r2);
+
+    // Get priority from process's pid
+    bool getPriority_l(int pid, int* priority);
 
     mutable Mutex mLock;
     sp<ProcessInfoInterface> mProcessInfo;
@@ -134,10 +178,11 @@
     bool mSupportsMultipleSecureCodecs;
     bool mSupportsSecureWithNonSecureCodec;
     int32_t mCpuBoostCount;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+    std::map<int, int> mOverridePidMap;
 };
 
 // ----------------------------------------------------------------------------
+} // namespace android
 
-}; // namespace android
-
-#endif // ANDROID_RESOURCEMANAGERSERVICE_H
+#endif // ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index 543c87c..b6c548c 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -5,6 +5,7 @@
     test_suites: ["device-tests"],
     shared_libs: [
         "libbinder",
+        "libbinder_ndk",
         "liblog",
         "libmedia",
         "libresourcemanagerservice",
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index ae97ec8..702935d 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -21,15 +21,28 @@
 #include <gtest/gtest.h>
 
 #include "ResourceManagerService.h"
-#include <media/IResourceManagerService.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
 #include <media/MediaResource.h>
 #include <media/MediaResourcePolicy.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/ProcessInfoInterface.h>
 
+namespace aidl {
+namespace android {
+namespace media {
+bool operator== (const MediaResourceParcel& lhs, const MediaResourceParcel& rhs) {
+    return lhs.type == rhs.type && lhs.subType == rhs.subType &&
+            lhs.id == rhs.id && lhs.value == rhs.value;
+}}}}
+
 namespace android {
 
-static int64_t getId(const sp<IResourceManagerClient>& client) {
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::BnResourceManagerClient;
+using ::aidl::android::media::IResourceManagerService;
+using ::aidl::android::media::IResourceManagerClient;
+
+static int64_t getId(const std::shared_ptr<IResourceManagerClient>& client) {
     return (int64_t) client.get();
 }
 
@@ -86,8 +99,7 @@
         mEventCount++;
     }
 
-    virtual bool requestCpusetBoost(
-            bool enable, const sp<IInterface> &/*client*/) override {
+    virtual bool requestCpusetBoost(bool enable) override {
         mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
         mEventCount++;
         return true;
@@ -109,18 +121,19 @@
 
 
 struct TestClient : public BnResourceManagerClient {
-    TestClient(int pid, sp<ResourceManagerService> service)
+    TestClient(int pid, const std::shared_ptr<ResourceManagerService> &service)
         : mReclaimed(false), mPid(pid), mService(service) {}
 
-    virtual bool reclaimResource() {
-        sp<IResourceManagerClient> client(this);
-        mService->removeClient(mPid, (int64_t) client.get());
+    Status reclaimResource(bool* _aidl_return) override {
+        mService->removeClient(mPid, getId(ref<TestClient>()));
         mReclaimed = true;
-        return true;
+        *_aidl_return = true;
+        return Status::ok();
     }
 
-    virtual String8 getName() {
-        return String8("test_client");
+    Status getName(::std::string* _aidl_return) override {
+        *_aidl_return = "test_client";
+        return Status::ok();
     }
 
     bool reclaimed() const {
@@ -131,13 +144,12 @@
         mReclaimed = false;
     }
 
-protected:
     virtual ~TestClient() {}
 
 private:
     bool mReclaimed;
     int mPid;
-    sp<ResourceManagerService> mService;
+    std::shared_ptr<ResourceManagerService> mService;
     DISALLOW_EVIL_CONSTRUCTORS(TestClient);
 };
 
@@ -157,32 +169,40 @@
     return lhs.type == rhs.type && lhs.arg == rhs.arg;
 }
 
+#define CHECK_STATUS_TRUE(condition) \
+    EXPECT_TRUE((condition).isOk() && (result))
+
+#define CHECK_STATUS_FALSE(condition) \
+    EXPECT_TRUE((condition).isOk() && !(result))
+
 class ResourceManagerServiceTest : public ::testing::Test {
 public:
     ResourceManagerServiceTest()
         : mSystemCB(new TestSystemCallback()),
-          mService(new ResourceManagerService(new TestProcessInfo, mSystemCB)),
-          mTestClient1(new TestClient(kTestPid1, mService)),
-          mTestClient2(new TestClient(kTestPid2, mService)),
-          mTestClient3(new TestClient(kTestPid2, mService)) {
+          mService(::ndk::SharedRefBase::make<ResourceManagerService>(
+                  new TestProcessInfo, mSystemCB)),
+          mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, mService)),
+          mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)),
+          mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)) {
     }
 
 protected:
-    static bool isEqualResources(const Vector<MediaResource> &resources1,
+    static bool isEqualResources(const std::vector<MediaResourceParcel> &resources1,
             const ResourceList &resources2) {
         // convert resource1 to ResourceList
         ResourceList r1;
         for (size_t i = 0; i < resources1.size(); ++i) {
-            const auto resType = std::make_pair(resources1[i].mType, resources1[i].mSubType);
-            r1[resType] = resources1[i];
+            const auto &res = resources1[i];
+            const auto resType = std::tuple(res.type, res.subType, res.id);
+            r1[resType] = res;
         }
         return r1 == resources2;
     }
 
     static void expectEqResourceInfo(const ResourceInfo &info,
             int uid,
-            sp<IResourceManagerClient> client,
-            const Vector<MediaResource> &resources) {
+            std::shared_ptr<IResourceManagerClient> client,
+            const std::vector<MediaResourceParcel> &resources) {
         EXPECT_EQ(uid, info.uid);
         EXPECT_EQ(client, info.client);
         EXPECT_TRUE(isEqualResources(resources, info.resources));
@@ -218,25 +238,25 @@
     // ---------------------------------------------------------------------------------
     void addResource() {
         // kTestPid1 mTestClient1
-        Vector<MediaResource> resources1;
-        resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
-        resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
-        Vector<MediaResource> resources11;
-        resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
+        resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
+        std::vector<MediaResourceParcel> resources11;
+        resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
 
         // kTestPid2 mTestClient2
-        Vector<MediaResource> resources2;
-        resources2.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
-        resources2.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
+        std::vector<MediaResourceParcel> resources2;
+        resources2.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+        resources2.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
 
         // kTestPid2 mTestClient3
-        Vector<MediaResource> resources3;
+        std::vector<MediaResourceParcel> resources3;
         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
-        resources3.push_back(MediaResource(MediaResource::kSecureCodec, 1));
-        resources3.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
+        resources3.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
+        resources3.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
 
         const PidResourceInfosMap &map = mService->mMap;
@@ -255,32 +275,92 @@
         expectEqResourceInfo(infos2.valueFor(getId(mTestClient3)), kTestUid2, mTestClient3, resources3);
     }
 
+    void testCombineResourceWithNegativeValues() {
+        // kTestPid1 mTestClient1
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -100));
+        resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -100));
+        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+
+        // Expected result:
+        // 1) the client should have been added;
+        // 2) both resource entries should have been rejected, resource list should be empty.
+        const PidResourceInfosMap &map = mService->mMap;
+        EXPECT_EQ(1u, map.size());
+        ssize_t index1 = map.indexOfKey(kTestPid1);
+        ASSERT_GE(index1, 0);
+        const ResourceInfos &infos1 = map[index1];
+        EXPECT_EQ(1u, infos1.size());
+        std::vector<MediaResourceParcel> expected;
+        expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
+
+        resources1.clear();
+        resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
+        resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
+        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        resources1.clear();
+        resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, 10));
+        resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 10));
+        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+
+        // Expected result:
+        // Both values should saturate to INT64_MAX
+        expected.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
+        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
+        expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
+
+        resources1.clear();
+        resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -10));
+        resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -10));
+        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+
+        // Expected result:
+        // 1) DrmSession resource should allow negative value addition, and value should drop accordingly
+        // 2) Non-drm session resource should ignore negative value addition.
+        expected.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX - 10));
+        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
+        expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
+
+        resources1.clear();
+        resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
+        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
+        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+
+        // Expected result:
+        // 1) DrmSession resource value should drop to 0, but the entry shouldn't be removed.
+        // 2) Non-drm session resource should ignore negative value addition.
+        expected.clear();
+        expected.push_back(MediaResource(MediaResource::Type::kDrmSession, 0));
+        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
+        expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
+    }
+
     void testConfig() {
         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
 
-        Vector<MediaResourcePolicy> policies1;
+        std::vector<MediaResourcePolicyParcel> policies1;
         policies1.push_back(
                 MediaResourcePolicy(
-                        String8(kPolicySupportsMultipleSecureCodecs),
-                        String8("true")));
+                        IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
+                        "true"));
         policies1.push_back(
                 MediaResourcePolicy(
-                        String8(kPolicySupportsSecureWithNonSecureCodec),
-                        String8("false")));
+                        IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
+                        "false"));
         mService->config(policies1);
         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
 
-        Vector<MediaResourcePolicy> policies2;
+        std::vector<MediaResourcePolicyParcel> policies2;
         policies2.push_back(
                 MediaResourcePolicy(
-                        String8(kPolicySupportsMultipleSecureCodecs),
-                        String8("false")));
+                        IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
+                        "false"));
         policies2.push_back(
                 MediaResourcePolicy(
-                        String8(kPolicySupportsSecureWithNonSecureCodec),
-                        String8("true")));
+                        IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
+                        "true"));
         mService->config(policies2);
         EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
@@ -288,12 +368,12 @@
 
     void testCombineResource() {
         // kTestPid1 mTestClient1
-        Vector<MediaResource> resources1;
-        resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
 
-        Vector<MediaResource> resources11;
-        resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
+        std::vector<MediaResourceParcel> resources11;
+        resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
 
         const PidResourceInfosMap &map = mService->mMap;
@@ -304,35 +384,35 @@
         EXPECT_EQ(1u, infos1.size());
 
         // test adding existing types to combine values
-        resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
+        resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
 
-        Vector<MediaResource> expected;
-        expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
-        expected.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
+        std::vector<MediaResourceParcel> expected;
+        expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
+        expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
 
         // test adding new types (including types that differs only in subType)
-        resources11.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
-        resources11.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
+        resources11.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+        resources11.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
 
         expected.clear();
-        expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
-        expected.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
-        expected.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
-        expected.push_back(MediaResource(MediaResource::kGraphicMemory, 500));
+        expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
+        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+        expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
+        expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 500));
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
     }
 
     void testRemoveResource() {
         // kTestPid1 mTestClient1
-        Vector<MediaResource> resources1;
-        resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
 
-        Vector<MediaResource> resources11;
-        resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
+        std::vector<MediaResourceParcel> resources11;
+        resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
 
         const PidResourceInfosMap &map = mService->mMap;
@@ -343,23 +423,105 @@
         EXPECT_EQ(1u, infos1.size());
 
         // test partial removal
-        resources11.editItemAt(0).mValue = 100;
+        resources11[0].value = 100;
         mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
 
-        Vector<MediaResource> expected;
-        expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
-        expected.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
+        std::vector<MediaResourceParcel> expected;
+        expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
+        expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
+        expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
+
+        // test removal request with negative value, should be ignored
+        resources11[0].value = -10000;
+        mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
 
         // test complete removal with overshoot value
-        resources11.editItemAt(0).mValue = 1000;
+        resources11[0].value = 1000;
         mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
 
         expected.clear();
-        expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
+        expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
     }
 
+    void testOverridePid() {
+
+        bool result;
+        std::vector<MediaResourceParcel> resources;
+        resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
+        resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
+
+        // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
+        {
+            addResource();
+            mService->mSupportsMultipleSecureCodecs = false;
+            mService->mSupportsSecureWithNonSecureCodec = true;
+
+            // priority too low to reclaim resource
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+
+            // override Low Priority Pid with High Priority Pid
+            mService->overridePid(kLowPriorityPid, kHighPriorityPid);
+            CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+
+            // restore Low Priority Pid
+            mService->overridePid(kLowPriorityPid, -1);
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+        }
+    }
+
+    void testMarkClientForPendingRemoval() {
+        bool result;
+
+        {
+            addResource();
+            mService->mSupportsSecureWithNonSecureCodec = true;
+
+            std::vector<MediaResourceParcel> resources;
+            resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+
+            // Remove low priority clients
+            mService->removeClient(kTestPid1, getId(mTestClient1));
+
+            // no lower priority client
+            CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
+            verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
+
+            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+
+            // client marked for pending removal from the same process got reclaimed
+            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
+
+            // clean up client 3 which still left
+            mService->removeClient(kTestPid2, getId(mTestClient3));
+        }
+
+        {
+            addResource();
+            mService->mSupportsSecureWithNonSecureCodec = true;
+
+            std::vector<MediaResourceParcel> resources;
+            resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+
+            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+
+            // client marked for pending removal from the same process got reclaimed
+            // first, even though there are lower priority process
+            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
+
+            // lower priority client got reclaimed
+            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
+
+            // clean up client 3 which still left
+            mService->removeClient(kTestPid2, getId(mTestClient3));
+        }
+    }
+
     void testRemoveClient() {
         addResource();
 
@@ -379,8 +541,8 @@
     void testGetAllClients() {
         addResource();
 
-        MediaResource::Type type = MediaResource::kSecureCodec;
-        Vector<sp<IResourceManagerClient> > clients;
+        MediaResource::Type type = MediaResource::Type::kSecureCodec;
+        Vector<std::shared_ptr<IResourceManagerClient> > clients;
         EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, &clients));
         // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
         // will fail.
@@ -394,9 +556,10 @@
     }
 
     void testReclaimResourceSecure() {
-        Vector<MediaResource> resources;
-        resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
-        resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
+        bool result;
+        std::vector<MediaResourceParcel> resources;
+        resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
+        resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
 
         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
         {
@@ -405,19 +568,19 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
-            EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
 
             // reclaim all secure codecs
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
 
             // call again should reclaim one largest graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
         // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
@@ -427,15 +590,15 @@
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
-            EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
 
             // reclaim all secure and non-secure codecs
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(true /* c1 */, true /* c2 */, true /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
 
@@ -446,23 +609,23 @@
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
-            EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
 
             // reclaim all non-secure codecs
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // call again should reclaim one largest graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
 
             // call again should reclaim another largest graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -472,22 +635,22 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
 
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             // one largest graphic memory from lowest process got reclaimed
             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
 
             // call again should reclaim another graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // call again should reclaim another graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -496,27 +659,28 @@
             mService->mSupportsMultipleSecureCodecs = true;
             mService->mSupportsSecureWithNonSecureCodec = true;
 
-            Vector<MediaResource> resources;
-            resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
+            std::vector<MediaResourceParcel> resources;
+            resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
 
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             // secure codec from lowest process got reclaimed
             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
 
             // call again should reclaim another secure codec from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
 
             // no more secure codec, non-secure codec will be reclaimed.
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
         }
     }
 
     void testReclaimResourceNonSecure() {
-        Vector<MediaResource> resources;
-        resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
-        resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
+        bool result;
+        std::vector<MediaResourceParcel> resources;
+        resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
+        resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
 
         // ### secure codec can't coexist with non-secure codec ###
         {
@@ -524,19 +688,19 @@
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
-            EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
 
             // reclaim all secure codecs
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
 
             // call again should reclaim one graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
 
@@ -546,22 +710,22 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
 
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             // one largest graphic memory from lowest process got reclaimed
             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
 
             // call again should reclaim another graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // call again should reclaim another graphic memory from lowest process
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
 
             // nothing left
-            EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
         }
 
         // ### secure codec can coexist with non-secure codec ###
@@ -569,15 +733,15 @@
             addResource();
             mService->mSupportsSecureWithNonSecureCodec = true;
 
-            Vector<MediaResource> resources;
-            resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
+            std::vector<MediaResourceParcel> resources;
+            resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
 
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             // one non secure codec from lowest process got reclaimed
             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
 
             // no more non-secure codec, secure codec from lowest priority process will be reclaimed
-            EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
+            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
 
             // clean up client 3 which still left
@@ -586,8 +750,8 @@
     }
 
     void testGetLowestPriorityBiggestClient() {
-        MediaResource::Type type = MediaResource::kGraphicMemory;
-        sp<IResourceManagerClient> client;
+        MediaResource::Type type = MediaResource::Type::kGraphicMemory;
+        std::shared_ptr<IResourceManagerClient> client;
         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
 
         addResource();
@@ -595,8 +759,8 @@
         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, &client));
         EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
 
-        // kTestPid1 is the lowest priority process with MediaResource::kGraphicMemory.
-        // mTestClient1 has the largest MediaResource::kGraphicMemory within kTestPid1.
+        // kTestPid1 is the lowest priority process with MediaResource::Type::kGraphicMemory.
+        // mTestClient1 has the largest MediaResource::Type::kGraphicMemory within kTestPid1.
         EXPECT_EQ(mTestClient1, client);
     }
 
@@ -605,7 +769,7 @@
         int priority;
         TestProcessInfo processInfo;
 
-        MediaResource::Type type = MediaResource::kGraphicMemory;
+        MediaResource::Type type = MediaResource::Type::kGraphicMemory;
         EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority));
 
         addResource();
@@ -616,7 +780,7 @@
         processInfo.getPriority(kTestPid1, &priority1);
         EXPECT_EQ(priority1, priority);
 
-        type = MediaResource::kNonSecureCodec;
+        type = MediaResource::Type::kNonSecureCodec;
         EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
         EXPECT_EQ(kTestPid2, pid);
         int priority2;
@@ -625,8 +789,8 @@
     }
 
     void testGetBiggestClient() {
-        MediaResource::Type type = MediaResource::kGraphicMemory;
-        sp<IResourceManagerClient> client;
+        MediaResource::Type type = MediaResource::Type::kGraphicMemory;
+        std::shared_ptr<IResourceManagerClient> client;
         EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client));
 
         addResource();
@@ -647,8 +811,8 @@
         EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
 
         // new client request should cause VIDEO_ON
-        Vector<MediaResource> resources1;
-        resources1.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1));
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
@@ -658,8 +822,8 @@
         EXPECT_EQ(2u, mSystemCB->eventCount());
 
         // new client request should cause VIDEO_ON
-        Vector<MediaResource> resources2;
-        resources2.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 2));
+        std::vector<MediaResourceParcel> resources2;
+        resources2.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 2));
         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
         EXPECT_EQ(3u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
@@ -686,8 +850,8 @@
         EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
 
         // new client request should cause CPUSET_ENABLE
-        Vector<MediaResource> resources1;
-        resources1.push_back(MediaResource(MediaResource::kCpuBoost, 1));
+        std::vector<MediaResourceParcel> resources1;
+        resources1.push_back(MediaResource(MediaResource::Type::kCpuBoost, 1));
         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
@@ -697,8 +861,8 @@
         EXPECT_EQ(2u, mSystemCB->eventCount());
 
         // new client request should cause CPUSET_ENABLE
-        Vector<MediaResource> resources2;
-        resources2.push_back(MediaResource(MediaResource::kCpuBoost, 2));
+        std::vector<MediaResourceParcel> resources2;
+        resources2.push_back(MediaResource(MediaResource::Type::kCpuBoost, 2));
         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
         EXPECT_EQ(3u, mSystemCB->eventCount());
         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
@@ -719,10 +883,10 @@
     }
 
     sp<TestSystemCallback> mSystemCB;
-    sp<ResourceManagerService> mService;
-    sp<IResourceManagerClient> mTestClient1;
-    sp<IResourceManagerClient> mTestClient2;
-    sp<IResourceManagerClient> mTestClient3;
+    std::shared_ptr<ResourceManagerService> mService;
+    std::shared_ptr<IResourceManagerClient> mTestClient1;
+    std::shared_ptr<IResourceManagerClient> mTestClient2;
+    std::shared_ptr<IResourceManagerClient> mTestClient3;
 };
 
 TEST_F(ResourceManagerServiceTest, config) {
@@ -737,6 +901,10 @@
     testCombineResource();
 }
 
+TEST_F(ResourceManagerServiceTest, combineResourceNegative) {
+    testCombineResourceWithNegativeValues();
+}
+
 TEST_F(ResourceManagerServiceTest, removeResource) {
     testRemoveResource();
 }
@@ -778,4 +946,12 @@
     testCpusetBoost();
 }
 
+TEST_F(ResourceManagerServiceTest, overridePid) {
+    testOverridePid();
+}
+
+TEST_F(ResourceManagerServiceTest, markClientForPendingRemoval) {
+    testMarkClientForPendingRemoval();
+}
+
 } // namespace android
diff --git a/services/mediatranscoding/.clang-format b/services/mediatranscoding/.clang-format
new file mode 100644
index 0000000..f14cc88
--- /dev/null
+++ b/services/mediatranscoding/.clang-format
@@ -0,0 +1,33 @@
+---
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+
+# Deviations from the above file:
+# "Don't indent the section label"
+AccessModifierOffset: -4
+# "Each line of text in your code should be at most 100 columns long."
+ColumnLimit: 100
+# "Constructor initializer lists can be all on one line or with subsequent
+# lines indented eight spaces.". clang-format does not support having the colon
+# on the same line as the constructor function name, so this is the best
+# approximation of that rule, which makes all entries in the list (except the
+# first one) have an eight space indentation.
+ConstructorInitializerIndentWidth: 6
+# There is nothing in go/droidcppstyle about case labels, but there seems to be
+# more code that does not indent the case labels in frameworks/base.
+IndentCaseLabels: false
+# There have been some bugs in which subsequent formatting operations introduce
+# weird comment jumps.
+ReflowComments: false
+# Android does support C++11 now.
+Standard: Cpp11
\ No newline at end of file
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
new file mode 100644
index 0000000..17347a9
--- /dev/null
+++ b/services/mediatranscoding/Android.bp
@@ -0,0 +1,65 @@
+// service library
+cc_library_shared {
+    name: "libmediatranscodingservice",
+
+    srcs: ["MediaTranscodingService.cpp"],
+
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "liblog",
+        "libmediatranscoding",
+        "libutils",
+    ],
+
+    static_libs: [
+        "mediatranscoding_aidl_interface-ndk_platform",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
+
+cc_binary {
+    name: "mediatranscoding",
+
+    srcs: [
+        "main_mediatranscodingservice.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        // TODO(hkuang): Use libbinder_ndk
+        "libbinder",
+        "libutils",
+        "liblog",
+        "libbase",
+        "libmediatranscoding",
+        "libmediatranscodingservice",
+    ],
+
+    static_libs: [
+        "mediatranscoding_aidl_interface-ndk_platform",
+    ],
+
+    target: {
+        android: {
+            product_variables: {
+                malloc_not_svelte: {
+                    // Scudo increases memory footprint, so only enable on
+                    // non-svelte devices.
+                    shared_libs: ["libc_scudo"],
+                },
+            },
+        },
+    },
+
+    init_rc: ["mediatranscoding.rc"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
diff --git a/media/libmediaplayer2/nuplayer2/MODULE_LICENSE_APACHE2 b/services/mediatranscoding/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libmediaplayer2/nuplayer2/MODULE_LICENSE_APACHE2
rename to services/mediatranscoding/MODULE_LICENSE_APACHE2
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
new file mode 100644
index 0000000..82d4161
--- /dev/null
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2019 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 "MediaTranscodingService"
+#include <MediaTranscodingService.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+// Convenience methods for constructing binder::Status objects for error returns
+#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
+    Status::fromServiceSpecificErrorWithMessage(      \
+            errorCode,                                \
+            String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, ##__VA_ARGS__))
+
+// Can MediaTranscoding service trust the caller based on the calling UID?
+// TODO(hkuang): Add MediaProvider's UID.
+static bool isTrustedCallingUid(uid_t uid) {
+    switch (uid) {
+    case AID_ROOT:  // root user
+    case AID_SYSTEM:
+    case AID_SHELL:
+    case AID_MEDIA:  // mediaserver
+        return true;
+    default:
+        return false;
+    }
+}
+
+MediaTranscodingService::MediaTranscodingService()
+      : mTranscodingClientManager(TranscodingClientManager::getInstance()) {
+    ALOGV("MediaTranscodingService is created");
+}
+
+MediaTranscodingService::~MediaTranscodingService() {
+    ALOGE("Should not be in ~MediaTranscodingService");
+}
+
+binder_status_t MediaTranscodingService::dump(int fd, const char** /*args*/, uint32_t /*numArgs*/) {
+    String8 result;
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "MediaTranscodingService: %p\n", this);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    Vector<String16> args;
+    mTranscodingClientManager.dumpAllClients(fd, args);
+    return OK;
+}
+
+//static
+void MediaTranscodingService::instantiate() {
+    std::shared_ptr<MediaTranscodingService> service =
+            ::ndk::SharedRefBase::make<MediaTranscodingService>();
+    binder_status_t status =
+            AServiceManager_addService(service->asBinder().get(), getServiceName());
+    if (status != STATUS_OK) {
+        return;
+    }
+}
+
+Status MediaTranscodingService::registerClient(
+        const std::shared_ptr<ITranscodingServiceClient>& in_client,
+        const std::string& in_opPackageName, int32_t in_clientUid, int32_t in_clientPid,
+        int32_t* _aidl_return) {
+    if (in_client == nullptr) {
+        ALOGE("Client can not be null");
+        *_aidl_return = kInvalidJobId;
+        return Status::fromServiceSpecificError(ERROR_ILLEGAL_ARGUMENT);
+    }
+
+    int32_t callingPid = AIBinder_getCallingPid();
+    int32_t callingUid = AIBinder_getCallingUid();
+
+    // Check if we can trust clientUid. Only privilege caller could forward the uid on app client's behalf.
+    if (in_clientUid == USE_CALLING_UID) {
+        in_clientUid = callingUid;
+    } else if (!isTrustedCallingUid(callingUid)) {
+        ALOGE("MediaTranscodingService::registerClient failed (calling PID %d, calling UID %d) "
+              "rejected "
+              "(don't trust clientUid %d)",
+              in_clientPid, in_clientUid, in_clientUid);
+        return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+                                "Untrusted caller (calling PID %d, UID %d) trying to "
+                                "register client",
+                                in_clientPid, in_clientUid);
+    }
+
+    // Check if we can trust clientPid. Only privilege caller could forward the pid on app client's behalf.
+    if (in_clientPid == USE_CALLING_PID) {
+        in_clientPid = callingPid;
+    } else if (!isTrustedCallingUid(callingUid)) {
+        ALOGE("MediaTranscodingService::registerClient client failed (calling PID %d, calling UID "
+              "%d) rejected "
+              "(don't trust clientPid %d)",
+              in_clientPid, in_clientUid, in_clientPid);
+        return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+                                "Untrusted caller (calling PID %d, UID %d) trying to "
+                                "register client",
+                                in_clientPid, in_clientUid);
+    }
+
+    // We know the clientId must be equal to its pid as we assigned client's pid as its clientId.
+    int32_t clientId = in_clientPid;
+
+    // Checks if the client already registers.
+    if (mTranscodingClientManager.isClientIdRegistered(clientId)) {
+        return Status::fromServiceSpecificError(ERROR_ALREADY_EXISTS);
+    }
+
+    // Creates the client and uses its process id as client id.
+    std::unique_ptr<TranscodingClientManager::ClientInfo> newClient =
+            std::make_unique<TranscodingClientManager::ClientInfo>(
+                    in_client, clientId, in_clientPid, in_clientUid, in_opPackageName);
+    status_t err = mTranscodingClientManager.addClient(std::move(newClient));
+    if (err != OK) {
+        *_aidl_return = kInvalidClientId;
+        return STATUS_ERROR_FMT(err, "Failed to add client to TranscodingClientManager");
+    }
+
+    ALOGD("Assign client: %s pid: %d, uid: %d with id: %d", in_opPackageName.c_str(), in_clientPid,
+          in_clientUid, clientId);
+
+    *_aidl_return = clientId;
+    return Status::ok();
+}
+
+Status MediaTranscodingService::unregisterClient(int32_t clientId, bool* _aidl_return) {
+    ALOGD("unregisterClient id: %d", clientId);
+    int32_t callingUid = AIBinder_getCallingUid();
+    int32_t callingPid = AIBinder_getCallingPid();
+
+    // Only the client with clientId or the trusted caller could unregister the client.
+    if (callingPid != clientId) {
+        if (!isTrustedCallingUid(callingUid)) {
+            ALOGE("Untrusted caller (calling PID %d, UID %d) trying to "
+                  "unregister client with id: %d",
+                  callingUid, callingPid, clientId);
+            *_aidl_return = true;
+            return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+                                    "Untrusted caller (calling PID %d, UID %d) trying to "
+                                    "unregister client with id: %d",
+                                    callingUid, callingPid, clientId);
+        }
+    }
+
+    *_aidl_return = (mTranscodingClientManager.removeClient(clientId) == OK);
+    return Status::ok();
+}
+
+Status MediaTranscodingService::getNumOfClients(int32_t* _aidl_return) {
+    ALOGD("MediaTranscodingService::getNumOfClients");
+    *_aidl_return = mTranscodingClientManager.getNumOfClients();
+    return Status::ok();
+}
+
+Status MediaTranscodingService::submitRequest(int32_t /*clientId*/,
+                                              const TranscodingRequestParcel& /*request*/,
+                                              TranscodingJobParcel* /*job*/,
+                                              int32_t* /*_aidl_return*/) {
+    // TODO(hkuang): Add implementation.
+    return Status::ok();
+}
+
+Status MediaTranscodingService::cancelJob(int32_t /*in_clientId*/, int32_t /*in_jobId*/,
+                                          bool* /*_aidl_return*/) {
+    // TODO(hkuang): Add implementation.
+    return Status::ok();
+}
+
+Status MediaTranscodingService::getJobWithId(int32_t /*in_jobId*/,
+                                             TranscodingJobParcel* /*out_job*/,
+                                             bool* /*_aidl_return*/) {
+    // TODO(hkuang): Add implementation.
+    return Status::ok();
+}
+
+}  // namespace android
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/services/mediatranscoding/MediaTranscodingService.h
new file mode 100644
index 0000000..cc69727
--- /dev/null
+++ b/services/mediatranscoding/MediaTranscodingService.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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 ANDROID_MEDIA_TRANSCODING_SERVICE_H
+#define ANDROID_MEDIA_TRANSCODING_SERVICE_H
+
+#include <aidl/android/media/BnMediaTranscodingService.h>
+#include <binder/IServiceManager.h>
+#include <media/TranscodingClientManager.h>
+
+namespace android {
+
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::BnMediaTranscodingService;
+using ::aidl::android::media::ITranscodingServiceClient;
+using ::aidl::android::media::TranscodingJobParcel;
+using ::aidl::android::media::TranscodingRequestParcel;
+
+class MediaTranscodingService : public BnMediaTranscodingService {
+public:
+    static constexpr int32_t kInvalidJobId = -1;
+    static constexpr int32_t kInvalidClientId = -1;
+
+    MediaTranscodingService();
+    virtual ~MediaTranscodingService();
+
+    static void instantiate();
+
+    static const char* getServiceName() { return "media.transcoding"; }
+
+    Status registerClient(const std::shared_ptr<ITranscodingServiceClient>& in_client,
+                          const std::string& in_opPackageName, int32_t in_clientUid,
+                          int32_t in_clientPid, int32_t* _aidl_return) override;
+
+    Status unregisterClient(int32_t clientId, bool* _aidl_return) override;
+
+    Status getNumOfClients(int32_t* _aidl_return) override;
+
+    Status submitRequest(int32_t in_clientId, const TranscodingRequestParcel& in_request,
+                         TranscodingJobParcel* out_job, int32_t* _aidl_return) override;
+
+    Status cancelJob(int32_t in_clientId, int32_t in_jobId, bool* _aidl_return) override;
+
+    Status getJobWithId(int32_t in_jobId, TranscodingJobParcel* out_job,
+                        bool* _aidl_return) override;
+
+    virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
+
+private:
+    friend class MediaTranscodingServiceTest;
+
+    mutable std::mutex mServiceLock;
+
+    TranscodingClientManager& mTranscodingClientManager;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_MEDIA_TRANSCODING_SERVICE_H
diff --git a/services/mediatranscoding/NOTICE b/services/mediatranscoding/NOTICE
new file mode 100644
index 0000000..9f46052
--- /dev/null
+++ b/services/mediatranscoding/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2019, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/services/mediatranscoding/OWNERS b/services/mediatranscoding/OWNERS
new file mode 100644
index 0000000..825c586
--- /dev/null
+++ b/services/mediatranscoding/OWNERS
@@ -0,0 +1,4 @@
+akersten@google.com
+hkuang@google.com
+lnilsson@google.com
+
diff --git a/services/mediatranscoding/main_mediatranscodingservice.cpp b/services/mediatranscoding/main_mediatranscodingservice.cpp
new file mode 100644
index 0000000..7d862e6
--- /dev/null
+++ b/services/mediatranscoding/main_mediatranscodingservice.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 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 <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+
+#include "MediaTranscodingService.h"
+
+using namespace android;
+
+int main(int argc __unused, char** argv) {
+    LOG(INFO) << "media transcoding service starting";
+
+    // TODO(hkuang): Start the service with libbinder_ndk.
+    strcpy(argv[0], "media.transcoding");
+    sp<ProcessState> proc(ProcessState::self());
+    sp<IServiceManager> sm = defaultServiceManager();
+    android::MediaTranscodingService::instantiate();
+
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/services/mediatranscoding/mediatranscoding.rc b/services/mediatranscoding/mediatranscoding.rc
new file mode 100644
index 0000000..5bfef59
--- /dev/null
+++ b/services/mediatranscoding/mediatranscoding.rc
@@ -0,0 +1,6 @@
+service media.transcoding /system/bin/mediatranscoding
+    class main
+    user media
+    group media
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/services/mediatranscoding/tests/Android.bp b/services/mediatranscoding/tests/Android.bp
new file mode 100644
index 0000000..e0e040c
--- /dev/null
+++ b/services/mediatranscoding/tests/Android.bp
@@ -0,0 +1,35 @@
+// Build the unit tests for MediaTranscodingService
+
+cc_defaults {
+    name: "mediatranscodingservice_test_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/mediatranscoding",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "liblog",
+        "libutils",
+        "libmediatranscodingservice",
+    ],
+
+    static_libs: [
+        "mediatranscoding_aidl_interface-ndk_platform",
+    ],
+}
+
+// MediaTranscodingService unit test
+cc_test {
+    name: "mediatranscodingservice_tests",
+    defaults: ["mediatranscodingservice_test_defaults"],
+
+    srcs: ["mediatranscodingservice_tests.cpp"],
+}
\ No newline at end of file
diff --git a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
new file mode 100644
index 0000000..bcdc7f7
--- /dev/null
+++ b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+    echo "Android build environment not set"
+    exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount && adb sync
+
+echo "========================================"
+
+echo "testing mediatranscodingservice"
+adb shell /data/nativetest64/mediatranscodingservice_tests/mediatranscodingservice_tests
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
new file mode 100644
index 0000000..5a791fe
--- /dev/null
+++ b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Unit Test for MediaTranscoding Service.
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaTranscodingServiceTest"
+
+#include <aidl/android/media/BnTranscodingServiceClient.h>
+#include <aidl/android/media/IMediaTranscodingService.h>
+#include <aidl/android/media/ITranscodingServiceClient.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <android/binder_ibinder_jni.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <cutils/ashmem.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+
+namespace android {
+
+namespace media {
+
+using Status = ::ndk::ScopedAStatus;
+using aidl::android::media::BnTranscodingServiceClient;
+using aidl::android::media::IMediaTranscodingService;
+using aidl::android::media::ITranscodingServiceClient;
+
+constexpr int32_t kInvalidClientId = -5;
+
+// Note that -1 is valid and means using calling pid/uid for the service. But only privilege caller could
+// use them. This test is not a privilege caller.
+constexpr int32_t kInvalidClientPid = -5;
+constexpr int32_t kInvalidClientUid = -5;
+constexpr const char* kInvalidClientOpPackageName = "";
+
+constexpr int32_t kClientUseCallingPid = -1;
+constexpr int32_t kClientUseCallingUid = -1;
+constexpr const char* kClientOpPackageName = "TestClient";
+
+class MediaTranscodingServiceTest : public ::testing::Test {
+public:
+    MediaTranscodingServiceTest() { ALOGD("MediaTranscodingServiceTest created"); }
+
+    void SetUp() override {
+        ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
+        mService = IMediaTranscodingService::fromBinder(binder);
+        if (mService == nullptr) {
+            ALOGE("Failed to connect to the media.trascoding service.");
+            return;
+        }
+    }
+
+    ~MediaTranscodingServiceTest() { ALOGD("MediaTranscodingingServiceTest destroyed"); }
+
+    std::shared_ptr<IMediaTranscodingService> mService = nullptr;
+};
+
+struct TestClient : public BnTranscodingServiceClient {
+    TestClient(const std::shared_ptr<IMediaTranscodingService>& service) : mService(service) {
+        ALOGD("TestClient Created");
+    }
+
+    Status getName(std::string* _aidl_return) override {
+        *_aidl_return = "test_client";
+        return Status::ok();
+    }
+
+    Status onTranscodingFinished(
+            int32_t /* in_jobId */,
+            const ::aidl::android::media::TranscodingResultParcel& /* in_result */) override {
+        return Status::ok();
+    }
+
+    Status onTranscodingFailed(
+            int32_t /* in_jobId */,
+            ::aidl::android::media::TranscodingErrorCode /*in_errorCode */) override {
+        return Status::ok();
+    }
+
+    Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
+                                      int32_t /* in_newAwaitNumber */) override {
+        return Status::ok();
+    }
+
+    Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
+        return Status::ok();
+    }
+
+    virtual ~TestClient() { ALOGI("TestClient destroyed"); };
+
+private:
+    std::shared_ptr<IMediaTranscodingService> mService;
+};
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterNullClient) {
+    std::shared_ptr<ITranscodingServiceClient> client = nullptr;
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+                                             kClientUseCallingPid, &clientId);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPid) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+                                             kInvalidClientPid, &clientId);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientUid) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kInvalidClientUid,
+                                             kClientUseCallingPid, &clientId);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPackageName) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kInvalidClientOpPackageName,
+                                             kClientUseCallingUid, kClientUseCallingPid, &clientId);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterOneClient) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingPid,
+                                             kClientUseCallingUid, &clientId);
+    ALOGD("client id is %d", clientId);
+    EXPECT_TRUE(status.isOk());
+
+    // Validate the clientId.
+    EXPECT_TRUE(clientId > 0);
+
+    // Check the number of Clients.
+    int32_t numOfClients;
+    status = mService->getNumOfClients(&numOfClients);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_EQ(1, numOfClients);
+
+    // Unregister the client.
+    bool res;
+    status = mService->unregisterClient(clientId, &res);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(res);
+}
+
+TEST_F(MediaTranscodingServiceTest, TestUnRegisterClientWithInvalidClientId) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+                                             kClientUseCallingPid, &clientId);
+    ALOGD("client id is %d", clientId);
+    EXPECT_TRUE(status.isOk());
+
+    // Validate the clientId.
+    EXPECT_TRUE(clientId > 0);
+
+    // Check the number of Clients.
+    int32_t numOfClients;
+    status = mService->getNumOfClients(&numOfClients);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_EQ(1, numOfClients);
+
+    // Unregister the client with invalid ID
+    bool res;
+    mService->unregisterClient(kInvalidClientId, &res);
+    EXPECT_FALSE(res);
+
+    // Unregister the valid client.
+    mService->unregisterClient(clientId, &res);
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {
+    std::shared_ptr<ITranscodingServiceClient> client =
+            ::ndk::SharedRefBase::make<TestClient>(mService);
+    EXPECT_TRUE(client != nullptr);
+
+    // Register the client with the service.
+    int32_t clientId = 0;
+    Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+                                             kClientUseCallingPid, &clientId);
+    EXPECT_TRUE(status.isOk());
+
+    // Validate the clientId.
+    EXPECT_TRUE(clientId > 0);
+
+    // Register the client again and expects failure.
+    status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+                                      kClientUseCallingPid, &clientId);
+    EXPECT_FALSE(status.isOk());
+
+    // Unregister the valid client.
+    bool res;
+    mService->unregisterClient(clientId, &res);
+}
+
+}  // namespace media
+}  // namespace android
diff --git a/services/minijail/Android.bp b/services/minijail/Android.bp
index 07a94cc..b057968 100644
--- a/services/minijail/Android.bp
+++ b/services/minijail/Android.bp
@@ -17,10 +17,15 @@
 cc_library_shared {
     name: "libavservices_minijail",
     defaults: ["libavservices_minijail_defaults"],
+    vendor_available: true,
+    min_sdk_version: "29",
     export_include_dirs: ["."],
 }
 
-// Small library for media.extractor and media.codec sandboxing.
+// By adding "vendor_available: true" to "libavservices_minijail", we don't
+// need to have "libavservices_minijail_vendor" any longer.
+// "libavservices_minijail_vendor" will be removed, once we replace it with
+// "libavservices_minijail" in all vendor modules. (b/146313710)
 cc_library_shared {
     name: "libavservices_minijail_vendor",
     vendor: true,
@@ -35,4 +40,5 @@
     srcs: [
         "av_services_minijail_unittest.cpp",
     ],
+    test_suites: ["device-tests"],
 }
diff --git a/services/minijail/TEST_MAPPING b/services/minijail/TEST_MAPPING
new file mode 100644
index 0000000..0d89760
--- /dev/null
+++ b/services/minijail/TEST_MAPPING
@@ -0,0 +1,5 @@
+{
+  "presubmit": [
+    { "name": "libavservices_minijail_unittest" }
+  ]
+}
diff --git a/services/minijail/av_services_minijail_unittest.cpp b/services/minijail/av_services_minijail_unittest.cpp
index 31313f8..896a764 100644
--- a/services/minijail/av_services_minijail_unittest.cpp
+++ b/services/minijail/av_services_minijail_unittest.cpp
@@ -34,13 +34,32 @@
         "mmap: 1\n"
         "munmap: 1\n";
 
+    const std::string third_policy_ =
+        "open: 1\n"
+        "close: 1\n";
+
     const std::string full_policy_ = base_policy_ + std::string("\n") + additional_policy_;
+    const std::string triple_policy_ = base_policy_ +
+                                       std::string("\n") + additional_policy_ +
+                                       std::string("\n") + third_policy_;
 };
 
 TEST_F(WritePolicyTest, OneFile)
 {
     std::string final_string;
-    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, std::string()));
+    // vector with an empty pathname
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {std::string()}));
+    EXPECT_LE(0, fd.get());
+    bool success = android::base::ReadFdToString(fd.get(), &final_string);
+    EXPECT_TRUE(success);
+    EXPECT_EQ(final_string, base_policy_);
+}
+
+TEST_F(WritePolicyTest, OneFileAlternate)
+{
+    std::string final_string;
+    // empty vector
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {}));
     EXPECT_LE(0, fd.get());
     bool success = android::base::ReadFdToString(fd.get(), &final_string);
     EXPECT_TRUE(success);
@@ -50,9 +69,19 @@
 TEST_F(WritePolicyTest, TwoFiles)
 {
     std::string final_string;
-    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, additional_policy_));
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {additional_policy_}));
     EXPECT_LE(0, fd.get());
     bool success = android::base::ReadFdToString(fd.get(), &final_string);
     EXPECT_TRUE(success);
     EXPECT_EQ(final_string, full_policy_);
 }
+
+TEST_F(WritePolicyTest, ThreeFiles)
+{
+    std::string final_string;
+    android::base::unique_fd fd(android::WritePolicyToPipe(base_policy_, {additional_policy_, third_policy_}));
+    EXPECT_LE(0, fd.get());
+    bool success = android::base::ReadFdToString(fd.get(), &final_string);
+    EXPECT_TRUE(success);
+    EXPECT_EQ(final_string, triple_policy_);
+}
diff --git a/services/minijail/minijail.cpp b/services/minijail/minijail.cpp
index f213287..c7832b9 100644
--- a/services/minijail/minijail.cpp
+++ b/services/minijail/minijail.cpp
@@ -29,7 +29,7 @@
 namespace android {
 
 int WritePolicyToPipe(const std::string& base_policy_content,
-                      const std::string& additional_policy_content)
+                      const std::vector<std::string>& additional_policy_contents)
 {
     int pipefd[2];
     if (pipe(pipefd) == -1) {
@@ -40,9 +40,11 @@
     base::unique_fd write_end(pipefd[1]);
     std::string content = base_policy_content;
 
-    if (additional_policy_content.length() > 0) {
-        content += "\n";
-        content += additional_policy_content;
+    for (auto one_content : additional_policy_contents) {
+        if (one_content.length() > 0) {
+            content += "\n";
+            content += one_content;
+        }
     }
 
     if (!base::WriteStringToFd(content, write_end.get())) {
@@ -53,29 +55,34 @@
     return pipefd[0];
 }
 
-void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path)
+void SetUpMinijail(const std::string& base_policy_path,
+                   const std::string& additional_policy_path)
 {
-    // No seccomp policy defined for this architecture.
-    if (access(base_policy_path.c_str(), R_OK) == -1) {
-        LOG(WARNING) << "No seccomp policy defined for this architecture.";
-        return;
-    }
+    SetUpMinijailList(base_policy_path, {additional_policy_path});
+}
 
+void SetUpMinijailList(const std::string& base_policy_path,
+                   const std::vector<std::string>& additional_policy_paths)
+{
     std::string base_policy_content;
-    std::string additional_policy_content;
+    std::vector<std::string> additional_policy_contents;
     if (!base::ReadFileToString(base_policy_path, &base_policy_content,
                                 false /* follow_symlinks */)) {
         LOG(FATAL) << "Could not read base policy file '" << base_policy_path << "'";
     }
 
-    if (additional_policy_path.length() > 0 &&
-        !base::ReadFileToString(additional_policy_path, &additional_policy_content,
-                                false /* follow_symlinks */)) {
-        LOG(WARNING) << "Could not read additional policy file '" << additional_policy_path << "'";
-        additional_policy_content = std::string();
+    for (auto one_policy_path : additional_policy_paths) {
+        std::string one_policy_content;
+        if (one_policy_path.length() > 0 &&
+                !base::ReadFileToString(one_policy_path, &one_policy_content,
+                    false /* follow_symlinks */)) {
+            // TODO: harder failure (fatal unless ENOENT?)
+            LOG(WARNING) << "Could not read additional policy file '" << one_policy_path << "'";
+        }
+        additional_policy_contents.push_back(one_policy_content);
     }
 
-    base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_content));
+    base::unique_fd policy_fd(WritePolicyToPipe(base_policy_content, additional_policy_contents));
     if (policy_fd.get() == -1) {
         LOG(FATAL) << "Could not write seccomp policy to fd";
     }
diff --git a/services/minijail/minijail.h b/services/minijail/minijail.h
index c8a2149..298af86 100644
--- a/services/minijail/minijail.h
+++ b/services/minijail/minijail.h
@@ -16,11 +16,15 @@
 #define AV_SERVICES_MINIJAIL_MINIJAIL
 
 #include <string>
+#include <vector>
 
 namespace android {
 int WritePolicyToPipe(const std::string& base_policy_content,
-                      const std::string& additional_policy_content);
-void SetUpMinijail(const std::string& base_policy_path, const std::string& additional_policy_path);
+                      const std::vector<std::string>& additional_policy_contents);
+void SetUpMinijail(const std::string& base_policy_path,
+                   const std::string& additional_policy_path);
+void SetUpMinijailList(const std::string& base_policy_path,
+                       const std::vector<std::string>& additional_policy_paths);
 }
 
 #endif  // AV_SERVICES_MINIJAIL_MINIJAIL
diff --git a/services/oboeservice/AAudioClientTracker.cpp b/services/oboeservice/AAudioClientTracker.cpp
index 8572561..9d9ca63 100644
--- a/services/oboeservice/AAudioClientTracker.cpp
+++ b/services/oboeservice/AAudioClientTracker.cpp
@@ -75,10 +75,10 @@
 
     std::lock_guard<std::mutex> lock(mLock);
     if (mNotificationClients.count(pid) == 0) {
-        sp<NotificationClient> notificationClient = new NotificationClient(pid);
+        sp<IBinder> binder = IInterface::asBinder(client);
+        sp<NotificationClient> notificationClient = new NotificationClient(pid, binder);
         mNotificationClients[pid] = notificationClient;
 
-        sp<IBinder> binder = IInterface::asBinder(client);
         status_t status = binder->linkToDeath(notificationClient);
         ALOGW_IF(status != NO_ERROR, "registerClient() linkToDeath = %d\n", status);
         return AAudioConvert_androidToAAudioResult(status);
@@ -106,18 +106,9 @@
 
 aaudio_result_t
 AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
-    aaudio_result_t result = AAUDIO_OK;
     ALOGV("registerClientStream(%d,)\n", pid);
     std::lock_guard<std::mutex> lock(mLock);
-    sp<NotificationClient> notificationClient = mNotificationClients[pid];
-    if (notificationClient == 0) {
-        // This will get called the first time the audio server registers an internal stream.
-        ALOGV("registerClientStream(%d,) unrecognized pid\n", pid);
-        notificationClient = new NotificationClient(pid);
-        mNotificationClients[pid] = notificationClient;
-    }
-    notificationClient->registerClientStream(serviceStream);
-    return result;
+    return getNotificationClient_l(pid)->registerClientStream(serviceStream);
 }
 
 // Find the tracker for this process and remove it.
@@ -136,8 +127,35 @@
     return AAUDIO_OK;
 }
 
-AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
-        : mProcessId(pid) {
+void AAudioClientTracker::setExclusiveEnabled(pid_t pid, bool enabled) {
+    ALOGD("%s(%d, %d)\n", __func__, pid, enabled);
+    std::lock_guard<std::mutex> lock(mLock);
+    getNotificationClient_l(pid)->setExclusiveEnabled(enabled);
+}
+
+bool AAudioClientTracker::isExclusiveEnabled(pid_t pid) {
+    std::lock_guard<std::mutex> lock(mLock);
+    return getNotificationClient_l(pid)->isExclusiveEnabled();
+}
+
+sp<AAudioClientTracker::NotificationClient>
+        AAudioClientTracker::getNotificationClient_l(pid_t pid) {
+    sp<NotificationClient> notificationClient = mNotificationClients[pid];
+    if (notificationClient == nullptr) {
+        // This will get called the first time the audio server uses this PID.
+        ALOGV("%s(%d,) unrecognized PID\n", __func__, pid);
+        notificationClient = new AAudioClientTracker::NotificationClient(pid, nullptr);
+        mNotificationClients[pid] = notificationClient;
+    }
+    return notificationClient;
+}
+
+// =======================================
+// AAudioClientTracker::NotificationClient
+// =======================================
+
+AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid, const sp<IBinder>& binder)
+        : mProcessId(pid), mBinder(binder) {
 }
 
 AAudioClientTracker::NotificationClient::~NotificationClient() {
diff --git a/services/oboeservice/AAudioClientTracker.h b/services/oboeservice/AAudioClientTracker.h
index accf1a7..943b809 100644
--- a/services/oboeservice/AAudioClientTracker.h
+++ b/services/oboeservice/AAudioClientTracker.h
@@ -58,6 +58,15 @@
     aaudio_result_t unregisterClientStream(pid_t pid,
                                            android::sp<AAudioServiceStreamBase> serviceStream);
 
+    /**
+     * Specify whether a process is allowed to create an EXCLUSIVE MMAP stream.
+     * @param pid
+     * @param enabled
+     */
+    void setExclusiveEnabled(pid_t pid, bool enabled);
+
+    bool isExclusiveEnabled(pid_t pid);
+
     android::AAudioService *getAAudioService() const {
         return mAAudioService;
     }
@@ -73,7 +82,7 @@
      */
     class NotificationClient : public IBinder::DeathRecipient {
     public:
-        NotificationClient(pid_t pid);
+        NotificationClient(pid_t pid, const android::sp<IBinder>& binder);
         virtual ~NotificationClient();
 
         int32_t getStreamCount();
@@ -84,15 +93,29 @@
 
         aaudio_result_t unregisterClientStream(android::sp<AAudioServiceStreamBase> serviceStream);
 
+        void setExclusiveEnabled(bool enabled) {
+            mExclusiveEnabled = enabled;
+        }
+
+        bool isExclusiveEnabled() {
+            return mExclusiveEnabled;
+        }
+
         // IBinder::DeathRecipient
         virtual     void    binderDied(const android::wp<IBinder>& who);
 
-    protected:
+    private:
         mutable std::mutex                              mLock;
         const pid_t                                     mProcessId;
         std::set<android::sp<AAudioServiceStreamBase>>  mStreams;
+        // hold onto binder to receive death notifications
+        android::sp<IBinder>                            mBinder;
+        bool                                            mExclusiveEnabled = true;
     };
 
+    // This must be called under mLock
+    android::sp<NotificationClient> getNotificationClient_l(pid_t pid);
+
     mutable std::mutex                               mLock;
     std::map<pid_t, android::sp<NotificationClient>> mNotificationClients;
     android::AAudioService                          *mAAudioService = nullptr;
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index a1fc0ea..9f34153 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -25,6 +25,7 @@
 #include <sstream>
 #include <utility/AAudioUtilities.h>
 
+#include "AAudioClientTracker.h"
 #include "AAudioEndpointManager.h"
 #include "AAudioServiceEndpointShared.h"
 #include "AAudioServiceEndpointMMAP.h"
@@ -76,6 +77,7 @@
         result << "  ExclusiveFoundCount:   " << mExclusiveFoundCount << "\n";
         result << "  ExclusiveOpenCount:    " << mExclusiveOpenCount << "\n";
         result << "  ExclusiveCloseCount:   " << mExclusiveCloseCount << "\n";
+        result << "  ExclusiveStolenCount:  " << mExclusiveStolenCount << "\n";
         result << "\n";
 
         if (isExclusiveLocked) {
@@ -142,7 +144,13 @@
 sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
                                         const aaudio::AAudioStreamRequest &request) {
     if (request.getConstantConfiguration().getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
-        return openExclusiveEndpoint(audioService, request);
+        sp<AAudioServiceEndpoint> endpointToSteal;
+        sp<AAudioServiceEndpoint> foundEndpoint =
+                openExclusiveEndpoint(audioService, request, endpointToSteal);
+        if (endpointToSteal.get()) {
+            endpointToSteal->releaseRegisteredStreams(); // free the MMAP resource
+        }
+        return foundEndpoint;
     } else {
         return openSharedEndpoint(audioService, request);
     }
@@ -150,7 +158,8 @@
 
 sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
         AAudioService &aaudioService,
-        const aaudio::AAudioStreamRequest &request) {
+        const aaudio::AAudioStreamRequest &request,
+        sp<AAudioServiceEndpoint> &endpointToSteal) {
 
     std::lock_guard<std::mutex> lock(mExclusiveLock);
 
@@ -161,18 +170,30 @@
 
     // If we find an existing one then this one cannot be exclusive.
     if (endpoint.get() != nullptr) {
-        ALOGW("openExclusiveEndpoint() already in use");
-        // Already open so do not allow a second stream.
+        if (kStealingEnabled
+                && !endpoint->isForSharing() // not currently SHARED
+                && !request.isSharingModeMatchRequired()) { // app did not request a shared stream
+            ALOGD("%s() endpoint in EXCLUSIVE use. Steal it!", __func__);
+            mExclusiveStolenCount++;
+            // Prevent this process from getting another EXCLUSIVE stream.
+            // This will prevent two clients from colliding after a DISCONNECTION
+            // when they both try to open an exclusive stream at the same time.
+            // That can result in a stream getting disconnected between the OPEN
+            // and START calls. This will help preserve app compatibility.
+            // An app can avoid having this happen by closing their streams when
+            // the app is paused.
+            AAudioClientTracker::getInstance().setExclusiveEnabled(request.getProcessId(), false);
+            endpointToSteal = endpoint; // return it to caller
+        }
         return nullptr;
     } else {
         sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP(aaudioService);
-        ALOGV("openExclusiveEndpoint(), no match so try to open MMAP %p for dev %d",
-              endpointMMap.get(), configuration.getDeviceId());
+        ALOGV("%s(), no match so try to open MMAP %p for dev %d",
+              __func__, endpointMMap.get(), configuration.getDeviceId());
         endpoint = endpointMMap;
 
         aaudio_result_t result = endpoint->open(request);
         if (result != AAUDIO_OK) {
-            ALOGV("openExclusiveEndpoint(), open failed");
             endpoint.clear();
         } else {
             mExclusiveStreams.push_back(endpointMMap);
@@ -183,7 +204,9 @@
     if (endpoint.get() != nullptr) {
         // Increment the reference count under this lock.
         endpoint->setOpenCount(endpoint->getOpenCount() + 1);
+        endpoint->setForSharing(request.isSharingModeMatchRequired());
     }
+
     return endpoint;
 }
 
@@ -284,7 +307,7 @@
 
         serviceEndpoint->close();
         mSharedCloseCount++;
-        ALOGV("%s() %p for device %d",
+        ALOGV("%s(%p) closed for device %d",
               __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
     }
 }
diff --git a/services/oboeservice/AAudioEndpointManager.h b/services/oboeservice/AAudioEndpointManager.h
index ba17853..ae776b1 100644
--- a/services/oboeservice/AAudioEndpointManager.h
+++ b/services/oboeservice/AAudioEndpointManager.h
@@ -19,6 +19,7 @@
 
 #include <map>
 #include <mutex>
+#include <sys/types.h>
 #include <utils/Singleton.h>
 
 #include "binding/AAudioServiceMessage.h"
@@ -62,7 +63,8 @@
 
 private:
     android::sp<AAudioServiceEndpoint> openExclusiveEndpoint(android::AAudioService &aaudioService,
-                                                 const aaudio::AAudioStreamRequest &request);
+                                                 const aaudio::AAudioStreamRequest &request,
+                                                 sp<AAudioServiceEndpoint> &endpointToSteal);
 
     android::sp<AAudioServiceEndpoint> openSharedEndpoint(android::AAudioService &aaudioService,
                                               const aaudio::AAudioStreamRequest &request);
@@ -91,11 +93,16 @@
     int32_t mExclusiveFoundCount  = 0; // number of times we FOUND an exclusive endpoint
     int32_t mExclusiveOpenCount   = 0; // number of times we OPENED an exclusive endpoint
     int32_t mExclusiveCloseCount  = 0; // number of times we CLOSED an exclusive endpoint
+    int32_t mExclusiveStolenCount = 0; // number of times we STOLE an exclusive endpoint
+
     // Same as above but for SHARED endpoints.
     int32_t mSharedSearchCount    = 0;
     int32_t mSharedFoundCount     = 0;
     int32_t mSharedOpenCount      = 0;
     int32_t mSharedCloseCount     = 0;
+
+    // For easily disabling the stealing of exclusive streams.
+    static constexpr bool kStealingEnabled = true;
 };
 } /* namespace aaudio */
 
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index e6a8375..22cdb35 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -23,7 +23,6 @@
 #include <sstream>
 
 #include <aaudio/AAudio.h>
-#include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 #include <utils/String16.h>
 
@@ -78,8 +77,24 @@
     AAudioClientTracker::getInstance().registerClient(pid, client);
 }
 
+bool AAudioService::isCallerInService() {
+    return mAudioClient.clientPid == IPCThreadState::self()->getCallingPid() &&
+        mAudioClient.clientUid == IPCThreadState::self()->getCallingUid();
+}
+
 aaudio_handle_t AAudioService::openStream(const aaudio::AAudioStreamRequest &request,
                                           aaudio::AAudioStreamConfiguration &configurationOutput) {
+    // A lock in is used to order the opening of endpoints when an
+    // EXCLUSIVE endpoint is stolen. We want the order to be:
+    // 1) Thread A opens exclusive MMAP endpoint
+    // 2) Thread B wants to open an exclusive MMAP endpoint so it steals the one from A
+    //    under this lock.
+    // 3) Thread B opens a shared MMAP endpoint.
+    // 4) Thread A can then get the lock and also open a shared stream.
+    // Without the lock. Thread A might sneak in and reallocate an exclusive stream
+    // before B can open the shared stream.
+    std::unique_lock<std::recursive_mutex> lock(mOpenLock);
+
     aaudio_result_t result = AAUDIO_OK;
     sp<AAudioServiceStreamBase> serviceStream;
     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
@@ -102,11 +117,11 @@
         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     }
 
-    if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+    if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+        && AAudioClientTracker::getInstance().isExclusiveEnabled(request.getProcessId())) {
         // only trust audioserver for in service indication
         bool inService = false;
-        if (mAudioClient.clientPid == IPCThreadState::self()->getCallingPid() &&
-                mAudioClient.clientUid == IPCThreadState::self()->getCallingUid()) {
+        if (isCallerInService()) {
             inService = request.isInService();
         }
         serviceStream = new AAudioServiceStreamMMAP(*this, inService);
@@ -135,37 +150,18 @@
         return result;
     } else {
         aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
-        ALOGV("openStream(): handle = 0x%08X", handle);
         serviceStream->setHandle(handle);
         pid_t pid = request.getProcessId();
         AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
         configurationOutput.copyFrom(*serviceStream);
+        // Log open in MediaMetrics after we have the handle because we need the handle to
+        // create the metrics ID.
+        serviceStream->logOpen(handle);
+        ALOGV("%s(): return handle = 0x%08X", __func__, handle);
         return handle;
     }
 }
 
-// If a close request is pending then close the stream
-bool AAudioService::releaseStream(const sp<AAudioServiceStreamBase> &serviceStream) {
-    bool closed = false;
-    // decrementAndRemoveStreamByHandle() uses a lock so that if there are two simultaneous closes
-    // then only one will get the pointer and do the close.
-    sp<AAudioServiceStreamBase> foundStream = mStreamTracker.decrementAndRemoveStreamByHandle(
-            serviceStream->getHandle());
-    if (foundStream.get() != nullptr) {
-        foundStream->close();
-        pid_t pid = foundStream->getOwnerProcessId();
-        AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
-        closed = true;
-    }
-    return closed;
-}
-
-aaudio_result_t AAudioService::checkForPendingClose(
-        const sp<AAudioServiceStreamBase> &serviceStream,
-        aaudio_result_t defaultResult) {
-    return releaseStream(serviceStream) ? AAUDIO_ERROR_INVALID_STATE : defaultResult;
-}
-
 aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
     // Check permission and ownership first.
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
@@ -173,18 +169,24 @@
         ALOGE("closeStream(0x%0x), illegal stream handle", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
+    return closeStream(serviceStream);
+}
 
+aaudio_result_t AAudioService::closeStream(sp<AAudioServiceStreamBase> serviceStream) {
+    // This is protected by a lock in AAudioClientTracker.
+    // It is safe to unregister the same stream twice.
     pid_t pid = serviceStream->getOwnerProcessId();
     AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
+    // This is protected by a lock in mStreamTracker.
+    // It is safe to remove the same stream twice.
+    mStreamTracker.removeStreamByHandle(serviceStream->getHandle());
 
-    serviceStream->markCloseNeeded();
-    (void) releaseStream(serviceStream);
-    return AAUDIO_OK;
+    return serviceStream->close();
 }
 
 sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
         aaudio_handle_t streamHandle) {
-    sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandleAndIncrement(
+    sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(
             streamHandle);
     if (serviceStream.get() != nullptr) {
         // Only allow owner or the aaudio service to access the stream.
@@ -197,8 +199,6 @@
         if (!allowed) {
             ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
                   callingUserId, streamHandle, ownerUserId);
-            // We incremented the reference count so we must check if it needs to be closed.
-            checkForPendingClose(serviceStream, AAUDIO_OK);
             serviceStream.clear();
         }
     }
@@ -213,117 +213,88 @@
         ALOGE("getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-
-    aaudio_result_t result = serviceStream->getDescription(parcelable);
-    // parcelable.dump();
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->getDescription(parcelable);
 }
 
 aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("startStream(), illegal stream handle = 0x%0x", streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-
-    aaudio_result_t result = serviceStream->start();
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->start();
 }
 
 aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("pauseStream(), illegal stream handle = 0x%0x", streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    aaudio_result_t result = serviceStream->pause();
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->pause();
 }
 
 aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("stopStream(), illegal stream handle = 0x%0x", streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    aaudio_result_t result = serviceStream->stop();
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->stop();
 }
 
 aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("flushStream(), illegal stream handle = 0x%0x", streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    aaudio_result_t result = serviceStream->flush();
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->flush();
 }
 
 aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
                                                    pid_t clientThreadId,
-                                                   int64_t periodNanoseconds) {
-    aaudio_result_t result = AAUDIO_OK;
+                                                   int64_t /* periodNanoseconds */) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    if (serviceStream->getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
-        ALOGE("AAudioService::registerAudioThread(), thread already registered");
-        result = AAUDIO_ERROR_INVALID_STATE;
-    } else {
-        const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
-        serviceStream->setRegisteredThread(clientThreadId);
-        int err = android::requestPriority(ownerPid, clientThreadId,
-                                           DEFAULT_AUDIO_PRIORITY, true /* isForApp */);
-        if (err != 0) {
-            ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
-                  clientThreadId, errno, DEFAULT_AUDIO_PRIORITY);
-            result = AAUDIO_ERROR_INTERNAL;
-        }
-    }
-    return checkForPendingClose(serviceStream, result);
+    int32_t priority = isCallerInService()
+        ? kRealTimeAudioPriorityService : kRealTimeAudioPriorityClient;
+    return serviceStream->registerAudioThread(clientThreadId, priority);
 }
 
 aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
                                                      pid_t clientThreadId) {
-    aaudio_result_t result = AAUDIO_OK;
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    if (serviceStream->getRegisteredThread() != clientThreadId) {
-        ALOGE("%s(), wrong thread", __func__);
-        result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-    } else {
-        serviceStream->setRegisteredThread(0);
-    }
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->unregisterAudioThread(clientThreadId);
 }
 
 aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
-                                  const android::AudioClient& client,
-                                  audio_port_handle_t *clientHandle) {
+                                           const android::AudioClient& client,
+                                           const audio_attributes_t *attr,
+                                           audio_port_handle_t *clientHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    aaudio_result_t result = serviceStream->startClient(client, clientHandle);
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->startClient(client, attr, clientHandle);
 }
 
 aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
                                           audio_port_handle_t portHandle) {
     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream.get() == nullptr) {
-        ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
+        ALOGW("%s(), invalid streamHandle = 0x%0x", __func__, streamHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
-    aaudio_result_t result = serviceStream->stopClient(portHandle);
-    return checkForPendingClose(serviceStream, result);
+    return serviceStream->stopClient(portHandle);
 }
 
 // This is only called internally when AudioFlinger wants to tear down a stream.
@@ -331,12 +302,13 @@
 aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
     ALOGD("%s(%d) called", __func__, portHandle);
     sp<AAudioServiceStreamBase> serviceStream =
-            mStreamTracker.findStreamByPortHandleAndIncrement(portHandle);
+            mStreamTracker.findStreamByPortHandle(portHandle);
     if (serviceStream.get() == nullptr) {
         ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
         return AAUDIO_ERROR_INVALID_HANDLE;
     }
+    // This is protected by a lock and will just return if already stopped.
     aaudio_result_t result = serviceStream->stop();
     serviceStream->disconnect();
-    return checkForPendingClose(serviceStream, result);
+    return result;
 }
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index d21b1cd..caf48a5 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -55,6 +55,10 @@
                                        aaudio::AAudioStreamConfiguration &configurationOutput)
                                        override;
 
+    /*
+     * This is called from Binder. It checks for permissions
+     * and converts the handle passed through Binder to a stream pointer.
+     */
     aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) override;
 
     aaudio_result_t getStreamDescription(
@@ -77,16 +81,31 @@
                                                   pid_t tid) override;
 
     aaudio_result_t startClient(aaudio::aaudio_handle_t streamHandle,
-                                      const android::AudioClient& client,
-                                      audio_port_handle_t *clientHandle) override;
+                                const android::AudioClient& client,
+                                const audio_attributes_t *attr,
+                                audio_port_handle_t *clientHandle) override;
 
     aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
                                        audio_port_handle_t clientHandle) override;
 
+ // ===============================================================================
+ // The following public methods are only called from the service and NOT by Binder.
+ // ===============================================================================
+
     aaudio_result_t disconnectStreamByPortHandle(audio_port_handle_t portHandle);
 
+    /*
+     * This is only called from within the Service.
+     * It bypasses the permission checks in closeStream(handle).
+     */
+    aaudio_result_t closeStream(sp<aaudio::AAudioServiceStreamBase> serviceStream);
+
 private:
 
+    /** @return true if the client is the audioserver
+     */
+    bool isCallerInService();
+
     /**
      * Lookup stream and then validate access to the stream.
      * @param streamHandle
@@ -95,20 +114,19 @@
     sp<aaudio::AAudioServiceStreamBase> convertHandleToServiceStream(
             aaudio::aaudio_handle_t streamHandle);
 
-
-
-    bool releaseStream(const sp<aaudio::AAudioServiceStreamBase> &serviceStream);
-
-    aaudio_result_t checkForPendingClose(const sp<aaudio::AAudioServiceStreamBase> &serviceStream,
-                                         aaudio_result_t defaultResult);
-
     android::AudioClient            mAudioClient;
 
     aaudio::AAudioStreamTracker     mStreamTracker;
 
-    enum constants {
-        DEFAULT_AUDIO_PRIORITY = 2
-    };
+    // We use a lock to prevent thread A from reopening an exclusive stream
+    // after thread B steals thread A's exclusive MMAP resource stream.
+    std::recursive_mutex            mOpenLock;
+
+    // TODO  Extract the priority constants from services/audioflinger/Threads.cpp
+    // and share them with this code. Look for "kPriorityFastMixer".
+    static constexpr int32_t        kRealTimeAudioPriorityClient = 2;
+    static constexpr int32_t        kRealTimeAudioPriorityService = 3;
+
 };
 
 } /* namespace android */
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 553754e..ceefe93 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -27,13 +27,13 @@
 
 #include <utils/Singleton.h>
 
-#include "AAudioEndpointManager.h"
-#include "AAudioServiceEndpoint.h"
 
 #include "core/AudioStreamBuilder.h"
+
+#include "AAudioEndpointManager.h"
+#include "AAudioClientTracker.h"
 #include "AAudioServiceEndpoint.h"
 #include "AAudioServiceStreamShared.h"
-#include "AAudioServiceEndpointShared.h"
 
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
@@ -62,6 +62,7 @@
     result << "    InputPreset:          " << getInputPreset() << "\n";
     result << "    Reference Count:      " << mOpenCount << "\n";
     result << "    Session Id:           " << getSessionId() << "\n";
+    result << "    Privacy Sensitive:    " << isPrivacySensitive() << "\n";
     result << "    Connected:            " << mConnected.load() << "\n";
     result << "    Registered Streams:" << "\n";
     result << AAudioServiceStreamShared::dumpHeader() << "\n";
@@ -86,16 +87,40 @@
     return false;
 }
 
-void AAudioServiceEndpoint::disconnectRegisteredStreams() {
-    std::lock_guard<std::mutex> lock(mLockStreams);
+std::vector<android::sp<AAudioServiceStreamBase>>
+        AAudioServiceEndpoint::disconnectRegisteredStreams() {
+    std::vector<android::sp<AAudioServiceStreamBase>> streamsDisconnected;
+    {
+        std::lock_guard<std::mutex> lock(mLockStreams);
+        mRegisteredStreams.swap(streamsDisconnected);
+    }
     mConnected.store(false);
-    for (const auto& stream : mRegisteredStreams) {
-        ALOGD("disconnectRegisteredStreams() stop and disconnect port %d",
-              stream->getPortHandle());
+    // We need to stop all the streams before we disconnect them.
+    // Otherwise there is a race condition where the first disconnected app
+    // tries to reopen a stream as MMAP but is blocked by the second stream,
+    // which hasn't stopped yet. Then the first app ends up with a Legacy stream.
+    for (const auto &stream : streamsDisconnected) {
+        ALOGD("%s() - stop(), port = %d", __func__, stream->getPortHandle());
         stream->stop();
+    }
+    for (const auto &stream : streamsDisconnected) {
+        ALOGD("%s() - disconnect(), port = %d", __func__, stream->getPortHandle());
         stream->disconnect();
     }
-    mRegisteredStreams.clear();
+    return streamsDisconnected;
+}
+
+void AAudioServiceEndpoint::releaseRegisteredStreams() {
+    // List of streams to be closed after we disconnect everything.
+    std::vector<android::sp<AAudioServiceStreamBase>> streamsToClose
+            = disconnectRegisteredStreams();
+
+    // Close outside the lock to avoid recursive locks.
+    AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
+    for (const auto& serviceStream : streamsToClose) {
+        ALOGD("%s() - close stream 0x%08X", __func__, serviceStream->getHandle());
+        aaudioService->closeStream(serviceStream);
+    }
 }
 
 aaudio_result_t AAudioServiceEndpoint::registerStream(sp<AAudioServiceStreamBase>stream) {
@@ -137,3 +162,36 @@
     }
     return true;
 }
+
+// static
+audio_attributes_t AAudioServiceEndpoint::getAudioAttributesFrom(
+        const AAudioStreamParameters *params) {
+    if (params == nullptr) {
+        return {};
+    }
+    const aaudio_direction_t direction = params->getDirection();
+
+    const audio_content_type_t contentType =
+            AAudioConvert_contentTypeToInternal(params->getContentType());
+    // Usage only used for OUTPUT
+    const audio_usage_t usage = (direction == AAUDIO_DIRECTION_OUTPUT)
+            ? AAudioConvert_usageToInternal(params->getUsage())
+            : AUDIO_USAGE_UNKNOWN;
+    const audio_source_t source = (direction == AAUDIO_DIRECTION_INPUT)
+            ? AAudioConvert_inputPresetToAudioSource(params->getInputPreset())
+            : AUDIO_SOURCE_DEFAULT;
+    audio_flags_mask_t flags;
+    if (direction == AAUDIO_DIRECTION_OUTPUT) {
+        flags = AUDIO_FLAG_LOW_LATENCY
+            | AAudioConvert_allowCapturePolicyToAudioFlagsMask(params->getAllowedCapturePolicy());
+    } else {
+        flags = AUDIO_FLAG_LOW_LATENCY
+            | AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive());
+    }
+    return {
+            .content_type = contentType,
+            .usage = usage,
+            .source = source,
+            .flags = flags,
+            .tags = "" };
+}
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a2f66a5..a171cb0 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -60,6 +60,7 @@
                                        audio_port_handle_t clientHandle) = 0;
 
     virtual aaudio_result_t startClient(const android::AudioClient& client,
+                                        const audio_attributes_t *attr,
                                         audio_port_handle_t *clientHandle) {
         ALOGD("AAudioServiceEndpoint::startClient(...) AAUDIO_ERROR_UNAVAILABLE");
         return AAUDIO_ERROR_UNAVAILABLE;
@@ -108,6 +109,23 @@
         return mConnected;
     }
 
+    static audio_attributes_t getAudioAttributesFrom(const AAudioStreamParameters *params);
+
+    // Stop, disconnect and release any streams registered on this endpoint.
+    void releaseRegisteredStreams();
+
+    bool isForSharing() const {
+        return mForSharing;
+    }
+
+    /**
+     *
+     * @param flag true if this endpoint is to be shared between multiple streams
+     */
+    void setForSharing(bool flag) {
+        mForSharing = flag;
+    }
+
 protected:
 
     /**
@@ -116,7 +134,7 @@
      */
     bool                     isStreamRegistered(audio_port_handle_t portHandle);
 
-    void                     disconnectRegisteredStreams();
+    std::vector<android::sp<AAudioServiceStreamBase>> disconnectRegisteredStreams();
 
     mutable std::mutex       mLockStreams;
     std::vector<android::sp<AAudioServiceStreamBase>> mRegisteredStreams;
@@ -129,7 +147,11 @@
     int32_t                  mOpenCount = 0;
     int32_t                  mRequestedDeviceId = 0;
 
+    // True if this will be shared by one or more other streams.
+    bool                     mForSharing = false;
+
     std::atomic<bool>        mConnected{true};
+
 };
 
 } /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index b05baa4..0843e0b 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -23,10 +23,10 @@
 #include <map>
 #include <mutex>
 #include <sstream>
+#include <thread>
 #include <utils/Singleton.h>
 #include <vector>
 
-
 #include "AAudioEndpointManager.h"
 #include "AAudioServiceEndpoint.h"
 
@@ -36,7 +36,6 @@
 #include "AAudioServiceEndpointPlay.h"
 #include "AAudioServiceEndpointMMAP.h"
 
-
 #define AAUDIO_BUFFER_CAPACITY_MIN    4 * 512
 #define AAUDIO_SAMPLE_RATE_DEFAULT    48000
 
@@ -48,7 +47,6 @@
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
 
-
 AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP(AAudioService &audioService)
         : mMmapStream(nullptr)
         , mAAudioService(audioService) {}
@@ -79,27 +77,7 @@
 
     copyFrom(request.getConstantConfiguration());
 
-    aaudio_direction_t direction = getDirection();
-
-    const audio_content_type_t contentType =
-            AAudioConvert_contentTypeToInternal(getContentType());
-    // Usage only used for OUTPUT
-    const audio_usage_t usage = (direction == AAUDIO_DIRECTION_OUTPUT)
-            ? AAudioConvert_usageToInternal(getUsage())
-            : AUDIO_USAGE_UNKNOWN;
-    const audio_source_t source = (direction == AAUDIO_DIRECTION_INPUT)
-            ? AAudioConvert_inputPresetToAudioSource(getInputPreset())
-            : AUDIO_SOURCE_DEFAULT;
-    const audio_flags_mask_t flags = AUDIO_FLAG_LOW_LATENCY |
-            AAudioConvert_allowCapturePolicyToAudioFlagsMask(getAllowedCapturePolicy());
-
-    const audio_attributes_t attributes = {
-            .content_type = contentType,
-            .usage = usage,
-            .source = source,
-            .flags = flags,
-            .tags = ""
-    };
+    const audio_attributes_t attributes = getAudioAttributesFrom(this);
 
     mMmapClient.clientUid = request.getUserId();
     mMmapClient.clientPid = request.getProcessId();
@@ -122,6 +100,8 @@
 
     int32_t aaudioSamplesPerFrame = getSamplesPerFrame();
 
+    const aaudio_direction_t direction = getDirection();
+
     if (direction == AAUDIO_DIRECTION_OUTPUT) {
         config.channel_mask = (aaudioSamplesPerFrame == AAUDIO_UNSPECIFIED)
                               ? AUDIO_CHANNEL_OUT_STEREO
@@ -247,7 +227,7 @@
 }
 
 aaudio_result_t AAudioServiceEndpointMMAP::close() {
-    if (mMmapStream != 0) {
+    if (mMmapStream != nullptr) {
         // Needs to be explicitly cleared or CTS will fail but it is not clear why.
         mMmapStream.clear();
         // Apparently the above close is asynchronous. An attempt to open a new device
@@ -264,7 +244,12 @@
     // Start the client on behalf of the AAudio service.
     // Use the port handle that was provided by openMmapStream().
     audio_port_handle_t tempHandle = mPortHandle;
-    aaudio_result_t result = startClient(mMmapClient, &tempHandle);
+    audio_attributes_t attr = {};
+    if (stream != nullptr) {
+        attr = getAudioAttributesFrom(stream.get());
+    }
+    aaudio_result_t result = startClient(
+            mMmapClient, stream == nullptr ? nullptr : &attr, &tempHandle);
     // When AudioFlinger is passed a valid port handle then it should not change it.
     LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
                         "%s() port handle not expected to change from %d to %d",
@@ -289,9 +274,10 @@
 }
 
 aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
+                                                       const audio_attributes_t *attr,
                                                        audio_port_handle_t *clientHandle) {
     if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-    status_t status = mMmapStream->start(client, clientHandle);
+    status_t status = mMmapStream->start(client, attr, clientHandle);
     return AAudioConvert_androidToAAudioResult(status);
 }
 
@@ -330,9 +316,8 @@
     return 0; // TODO
 }
 
-// This is called by AudioFlinger when it wants to destroy a stream.
-void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
-    ALOGD("%s(portHandle = %d) called", __func__, portHandle);
+// This is called by onTearDown() in a separate thread to avoid deadlocks.
+void AAudioServiceEndpointMMAP::handleTearDownAsync(audio_port_handle_t portHandle) {
     // Are we tearing down the EXCLUSIVE MMAP stream?
     if (isStreamRegistered(portHandle)) {
         ALOGD("%s(%d) tearing down this entire MMAP endpoint", __func__, portHandle);
@@ -345,6 +330,13 @@
     }
 };
 
+// This is called by AudioFlinger when it wants to destroy a stream.
+void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
+    ALOGD("%s(portHandle = %d) called", __func__, portHandle);
+    std::thread asyncTask(&AAudioServiceEndpointMMAP::handleTearDownAsync, this, portHandle);
+    asyncTask.detach();
+}
+
 void AAudioServiceEndpointMMAP::onVolumeChanged(audio_channel_mask_t channels,
                                               android::Vector<float> values) {
     // TODO Do we really need a different volume for each channel?
@@ -357,12 +349,20 @@
     }
 };
 
-void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
+void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t portHandle) {
+    const int32_t deviceId = static_cast<int32_t>(portHandle);
     ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
-    if (getDeviceId() != AUDIO_PORT_HANDLE_NONE  && getDeviceId() != deviceId) {
-        disconnectRegisteredStreams();
+    if (getDeviceId() != deviceId) {
+        if (getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
+            std::thread asyncTask([this, deviceId]() {
+                disconnectRegisteredStreams();
+                setDeviceId(deviceId);
+            });
+            asyncTask.detach();
+        } else {
+            setDeviceId(deviceId);
+        }
     }
-    setDeviceId(deviceId);
 };
 
 /**
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 5e815e0..3d10861 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -59,7 +59,8 @@
                                audio_port_handle_t clientHandle) override;
 
     aaudio_result_t startClient(const android::AudioClient& client,
-                                        audio_port_handle_t *clientHandle)  override;
+                                const audio_attributes_t *attr,
+                                audio_port_handle_t *clientHandle)  override;
 
     aaudio_result_t stopClient(audio_port_handle_t clientHandle)  override;
 
@@ -67,13 +68,15 @@
 
     aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
 
+    void handleTearDownAsync(audio_port_handle_t portHandle);
+
     // -------------- Callback functions for MmapStreamCallback ---------------------
-    void onTearDown(audio_port_handle_t handle) override;
+    void onTearDown(audio_port_handle_t portHandle) override;
 
     void onVolumeChanged(audio_channel_mask_t channels,
                          android::Vector<float> values) override;
 
-    void onRoutingChanged(audio_port_handle_t deviceId) override;
+    void onRoutingChanged(audio_port_handle_t portHandle) override;
     // ------------------------------------------------------------------------------
 
     aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable);
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 0a415fd..dc21886 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -85,7 +85,7 @@
 }
 
 aaudio_result_t AAudioServiceEndpointShared::close() {
-    return getStreamInternal()->close();
+    return getStreamInternal()->releaseCloseFinal();
 }
 
 // Glue between C and C++ callbacks.
@@ -152,7 +152,9 @@
     }
 
     if (result == AAUDIO_OK) {
-        result = getStreamInternal()->startClient(sharedStream->getAudioClient(), clientHandle);
+        const audio_attributes_t attr = getAudioAttributesFrom(sharedStream.get());
+        result = getStreamInternal()->startClient(
+                sharedStream->getAudioClient(), &attr, clientHandle);
         if (result != AAUDIO_OK) {
             if (--mRunningStreamCount == 0) { // atomic
                 stopSharingThread();
@@ -166,13 +168,11 @@
 
 aaudio_result_t AAudioServiceEndpointShared::stopStream(sp<AAudioServiceStreamBase> sharedStream,
                                                         audio_port_handle_t clientHandle) {
-    // Don't lock here because the disconnectRegisteredStreams also uses the lock.
-
     // Ignore result.
     (void) getStreamInternal()->stopClient(clientHandle);
 
     if (--mRunningStreamCount == 0) { // atomic
-        stopSharingThread();
+        stopSharingThread(); // the sharing thread locks mLockStreams
         getStreamInternal()->requestStop();
     }
     return AAUDIO_OK;
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 880a3d7..663dae2 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -22,8 +22,13 @@
 #include <iostream>
 #include <mutex>
 
+#include <media/MediaMetricsItem.h>
+#include <media/TypeConverter.h>
+#include <mediautils/SchedulingPolicyService.h>
+
 #include "binding/IAAudioService.h"
 #include "binding/AAudioServiceMessage.h"
+#include "core/AudioGlobal.h"
 #include "utility/AudioClock.h"
 
 #include "AAudioEndpointManager.h"
@@ -51,12 +56,21 @@
 }
 
 AAudioServiceStreamBase::~AAudioServiceStreamBase() {
+    // May not be set if open failed.
+    if (mMetricsId.size() > 0) {
+        mediametrics::LogItem(mMetricsId)
+                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
+                .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+                .record();
+    }
+
     // If the stream is deleted when OPEN or in use then audio resources will leak.
     // This would indicate an internal error. So we want to find this ASAP.
     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
                         || getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
                         || getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
-                        "service stream still open, state = %d", getState());
+                        "service stream %p still open, state = %d",
+                        this, getState());
 }
 
 std::string AAudioServiceStreamBase::dumpHeader() {
@@ -80,6 +94,36 @@
     return result.str();
 }
 
+void AAudioServiceStreamBase::logOpen(aaudio_handle_t streamHandle) {
+    // This is the first log sent from the AAudio Service for a stream.
+    mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM)
+            + std::to_string(streamHandle);
+
+    audio_attributes_t attributes = AAudioServiceEndpoint::getAudioAttributesFrom(this);
+
+    // Once this item is logged by the server, the client with the same PID, UID
+    // can also log properties.
+    mediametrics::LogItem(mMetricsId)
+        .setPid(getOwnerProcessId())
+        .setUid(getOwnerUserId())
+        .set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)getOwnerUserId())
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
+        // the following are immutable
+        .set(AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, (int32_t)getBufferCapacity())
+        .set(AMEDIAMETRICS_PROP_BURSTFRAMES, (int32_t)getFramesPerBurst())
+        .set(AMEDIAMETRICS_PROP_CHANNELCOUNT, (int32_t)getSamplesPerFrame())
+        .set(AMEDIAMETRICS_PROP_CONTENTTYPE, toString(attributes.content_type).c_str())
+        .set(AMEDIAMETRICS_PROP_DIRECTION,
+                AudioGlobal_convertDirectionToText(getDirection()))
+        .set(AMEDIAMETRICS_PROP_ENCODING, toString(getFormat()).c_str())
+        .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)getDeviceId())
+        .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)getSampleRate())
+        .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)getSessionId())
+        .set(AMEDIAMETRICS_PROP_SOURCE, toString(attributes.source).c_str())
+        .set(AMEDIAMETRICS_PROP_USAGE, toString(attributes.usage).c_str())
+        .record();
+}
+
 aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request) {
     AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
     aaudio_result_t result = AAUDIO_OK;
@@ -126,13 +170,18 @@
 }
 
 aaudio_result_t AAudioServiceStreamBase::close() {
-    aaudio_result_t result = AAUDIO_OK;
+    std::lock_guard<std::mutex> lock(mLock);
+    return close_l();
+}
+
+aaudio_result_t AAudioServiceStreamBase::close_l() {
     if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
         return AAUDIO_OK;
     }
 
-    stop();
+    stop_l();
 
+    aaudio_result_t result = AAUDIO_OK;
     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
     if (endpoint == nullptr) {
         result = AAUDIO_ERROR_INVALID_STATE;
@@ -142,7 +191,7 @@
         endpointManager.closeEndpoint(endpoint);
 
         // AAudioService::closeStream() prevents two threads from closing at the same time.
-        mServiceEndpoint.clear(); // endpoint will hold the pointer until this method returns.
+        mServiceEndpoint.clear(); // endpoint will hold the pointer after this method returns.
     }
 
     {
@@ -153,6 +202,10 @@
     }
 
     setState(AAUDIO_STREAM_STATE_CLOSED);
+
+    mediametrics::LogItem(mMetricsId)
+        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE)
+        .record();
     return result;
 }
 
@@ -172,10 +225,28 @@
  * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
  */
 aaudio_result_t AAudioServiceStreamBase::start() {
+    std::lock_guard<std::mutex> lock(mLock);
+
+    const int64_t beginNs = AudioClock::getNanoseconds();
     aaudio_result_t result = AAUDIO_OK;
 
+    if (auto state = getState();
+        state == AAUDIO_STREAM_STATE_CLOSED || state == AAUDIO_STREAM_STATE_DISCONNECTED) {
+        ALOGW("%s() already CLOSED, returns INVALID_STATE, handle = %d",
+                __func__, getHandle());
+        return AAUDIO_ERROR_INVALID_STATE;
+    }
+
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .record(); });
+
     if (isRunning()) {
-        return AAUDIO_OK;
+        return result;
     }
 
     setFlowing(false);
@@ -198,15 +269,29 @@
     return result;
 
 error:
-    disconnect();
+    disconnect_l();
     return result;
 }
 
 aaudio_result_t AAudioServiceStreamBase::pause() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return pause_l();
+}
+
+aaudio_result_t AAudioServiceStreamBase::pause_l() {
     aaudio_result_t result = AAUDIO_OK;
     if (!isRunning()) {
         return result;
     }
+    const int64_t beginNs = AudioClock::getNanoseconds();
+
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_PAUSE)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .record(); });
 
     // Send it now because the timestamp gets rounded up when stopStream() is called below.
     // Also we don't need the timestamps while we are shutting down.
@@ -214,19 +299,20 @@
 
     result = stopTimestampThread();
     if (result != AAUDIO_OK) {
-        disconnect();
+        disconnect_l();
         return result;
     }
 
     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
     if (endpoint == nullptr) {
         ALOGE("%s() has no endpoint", __func__);
-        return AAUDIO_ERROR_INVALID_STATE;
+        result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
+        return result;
     }
     result = endpoint->stopStream(this, mClientHandle);
     if (result != AAUDIO_OK) {
         ALOGE("%s() mServiceEndpoint returned %d, %s", __func__, result, getTypeText());
-        disconnect(); // TODO should we return or pause Base first?
+        disconnect_l(); // TODO should we return or pause Base first?
     }
 
     sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
@@ -235,10 +321,24 @@
 }
 
 aaudio_result_t AAudioServiceStreamBase::stop() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return stop_l();
+}
+
+aaudio_result_t AAudioServiceStreamBase::stop_l() {
     aaudio_result_t result = AAUDIO_OK;
     if (!isRunning()) {
         return result;
     }
+    const int64_t beginNs = AudioClock::getNanoseconds();
+
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .record(); });
 
     setState(AAUDIO_STREAM_STATE_STOPPING);
 
@@ -247,20 +347,21 @@
     sendCurrentTimestamp(); // warning - this calls a virtual function
     result = stopTimestampThread();
     if (result != AAUDIO_OK) {
-        disconnect();
+        disconnect_l();
         return result;
     }
 
     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
     if (endpoint == nullptr) {
         ALOGE("%s() has no endpoint", __func__);
-        return AAUDIO_ERROR_INVALID_STATE;
+        result =  AAUDIO_ERROR_INVALID_STATE; // for MediaMetric tracking
+        return result;
     }
     // TODO wait for data to be played out
     result = endpoint->stopStream(this, mClientHandle);
     if (result != AAUDIO_OK) {
         ALOGE("%s() stopStream returned %d, %s", __func__, result, getTypeText());
-        disconnect();
+        disconnect_l();
         // TODO what to do with result here?
     }
 
@@ -279,10 +380,20 @@
 }
 
 aaudio_result_t AAudioServiceStreamBase::flush() {
+    std::lock_guard<std::mutex> lock(mLock);
     aaudio_result_t result = AAudio_isFlushAllowed(getState());
     if (result != AAUDIO_OK) {
         return result;
     }
+    const int64_t beginNs = AudioClock::getNanoseconds();
+
+    mediametrics::Defer defer([&] {
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH)
+            .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(AudioClock::getNanoseconds() - beginNs))
+            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+            .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
+            .record(); });
 
     // Data will get flushed when the client receives the FLUSHED event.
     sendServiceEvent(AAUDIO_SERVICE_EVENT_FLUSHED);
@@ -319,12 +430,66 @@
 }
 
 void AAudioServiceStreamBase::disconnect() {
-    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
+    std::lock_guard<std::mutex> lock(mLock);
+    disconnect_l();
+}
+
+void AAudioServiceStreamBase::disconnect_l() {
+    if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED
+        && getState() != AAUDIO_STREAM_STATE_CLOSED) {
+
+        mediametrics::LogItem(mMetricsId)
+            .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
+            .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+            .record();
+
         sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
         setState(AAUDIO_STREAM_STATE_DISCONNECTED);
     }
 }
 
+aaudio_result_t AAudioServiceStreamBase::registerAudioThread(pid_t clientThreadId,
+        int priority) {
+    std::lock_guard<std::mutex> lock(mLock);
+    aaudio_result_t result = AAUDIO_OK;
+    if (getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
+        ALOGE("AAudioService::registerAudioThread(), thread already registered");
+        result = AAUDIO_ERROR_INVALID_STATE;
+    } else {
+        const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
+        setRegisteredThread(clientThreadId);
+        int err = android::requestPriority(ownerPid, clientThreadId,
+                                           priority, true /* isForApp */);
+        if (err != 0) {
+            ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
+                  clientThreadId, errno, priority);
+            result = AAUDIO_ERROR_INTERNAL;
+        }
+    }
+    return result;
+}
+
+aaudio_result_t AAudioServiceStreamBase::unregisterAudioThread(pid_t clientThreadId) {
+    std::lock_guard<std::mutex> lock(mLock);
+    aaudio_result_t result = AAUDIO_OK;
+    if (getRegisteredThread() != clientThreadId) {
+        ALOGE("%s(), wrong thread", __func__);
+        result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+    } else {
+        setRegisteredThread(0);
+    }
+    return result;
+}
+
+void AAudioServiceStreamBase::setState(aaudio_stream_state_t state) {
+    // CLOSED is a final state.
+    if (mState != AAUDIO_STREAM_STATE_CLOSED) {
+        mState = state;
+    } else {
+        ALOGW_IF(mState != state, "%s(%d) when already CLOSED", __func__, state);
+    }
+}
+
 aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
                                                           double  dataDouble) {
     AAudioServiceMessage command;
@@ -422,6 +587,7 @@
  * used to communicate with the underlying HAL or Service.
  */
 aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
+    std::lock_guard<std::mutex> lock(mLock);
     {
         std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
         if (mUpMessageQueue == nullptr) {
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 097bc64..94cc980 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -68,13 +68,16 @@
     // does not include EOL
     virtual std::string dump() const;
 
-    // -------------------------------------------------------------------
     /**
      * Open the device.
      */
     virtual aaudio_result_t open(const aaudio::AAudioStreamRequest &request) = 0;
 
-    virtual aaudio_result_t close();
+    // We log the CLOSE from the close() method. We needed this separate method to log the OPEN
+    // because we had to wait until we generated the handle.
+    void logOpen(aaudio_handle_t streamHandle);
+
+    aaudio_result_t close();
 
     /**
      * Start the flow of audio data.
@@ -82,7 +85,7 @@
      * This is not guaranteed to be synchronous but it currently is.
      * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
      */
-    virtual aaudio_result_t start();
+    aaudio_result_t start();
 
     /**
      * Stop the flow of data so that start() can resume without loss of data.
@@ -90,7 +93,7 @@
      * This is not guaranteed to be synchronous but it currently is.
      * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
     */
-    virtual aaudio_result_t pause();
+    aaudio_result_t pause();
 
     /**
      * Stop the flow of data after the currently queued data has finished playing.
@@ -99,19 +102,17 @@
      * An AAUDIO_SERVICE_EVENT_STOPPED will be sent to the client when complete.
      *
      */
-    virtual aaudio_result_t stop();
-
-    aaudio_result_t stopTimestampThread();
+    aaudio_result_t stop();
 
     /**
      * Discard any data held by the underlying HAL or Service.
      *
      * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
      */
-    virtual aaudio_result_t flush();
+    aaudio_result_t flush();
 
-
-    virtual aaudio_result_t startClient(const android::AudioClient& client __unused,
+    virtual aaudio_result_t startClient(const android::AudioClient& client,
+                                        const audio_attributes_t *attr __unused,
                                         audio_port_handle_t *clientHandle __unused) {
         ALOGD("AAudioServiceStreamBase::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
         return AAUDIO_ERROR_UNAVAILABLE;
@@ -122,29 +123,19 @@
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
+    aaudio_result_t registerAudioThread(pid_t clientThreadId, int priority);
+
+    aaudio_result_t unregisterAudioThread(pid_t clientThreadId);
+
     bool isRunning() const {
         return mState == AAUDIO_STREAM_STATE_STARTED;
     }
 
-    // -------------------------------------------------------------------
-
-    /**
-     * Send a message to the client with an int64_t data value.
-     */
-    aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
-                                     int64_t dataLong = 0);
-    /**
-     * Send a message to the client with an double data value.
-     */
-    aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
-                                     double  dataDouble);
-
     /**
      * Fill in a parcelable description of stream.
      */
     aaudio_result_t getDescription(AudioEndpointParcelable &parcelable);
 
-
     void setRegisteredThread(pid_t pid) {
         mRegisteredClientThread = pid;
     }
@@ -258,9 +249,13 @@
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
                          aaudio_sharing_mode_t sharingMode);
 
-    void setState(aaudio_stream_state_t state) {
-        mState = state;
-    }
+    // These must be called under mLock
+    virtual aaudio_result_t close_l();
+    virtual aaudio_result_t pause_l();
+    virtual aaudio_result_t stop_l();
+    void disconnect_l();
+
+    void setState(aaudio_stream_state_t state);
 
     /**
      * Device specific startup.
@@ -311,8 +306,23 @@
     android::sp<AAudioServiceEndpoint> mServiceEndpoint;
     android::wp<AAudioServiceEndpoint> mServiceEndpointWeak;
 
+    std::string mMetricsId;  // set once during open()
+
 private:
 
+    aaudio_result_t stopTimestampThread();
+
+    /**
+     * Send a message to the client with an int64_t data value.
+     */
+    aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
+                                     int64_t dataLong = 0);
+    /**
+     * Send a message to the client with a double data value.
+     */
+    aaudio_result_t sendServiceEvent(aaudio_service_event_t event,
+                                     double dataDouble);
+
     /**
      * @return true if the queue is getting full.
      */
@@ -330,6 +340,10 @@
     // This indicate that a running stream should not be processed because of an error,
     // for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
     std::atomic<bool>       mSuspended{false};
+
+    // Locking order is important.
+    // Always acquire mLock before acquiring AAudioServiceEndpoint::mLockStreams
+    std::mutex              mLock; // Prevent start/stop/close etcetera from colliding
 };
 
 } /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 837b080..54d7d06 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -49,16 +49,6 @@
         , mInService(inService) {
 }
 
-aaudio_result_t AAudioServiceStreamMMAP::close() {
-    if (getState() == AAUDIO_STREAM_STATE_CLOSED) {
-        return AAUDIO_OK;
-    }
-
-    stop();
-
-    return AAudioServiceStreamBase::close();
-}
-
 // Open stream on HAL and pass information about the shared memory buffer back to the client.
 aaudio_result_t AAudioServiceStreamMMAP::open(const aaudio::AAudioStreamRequest &request) {
 
@@ -96,17 +86,17 @@
     aaudio_result_t result = AAudioServiceStreamBase::startDevice();
     if (!mInService && result == AAUDIO_OK) {
         // Note that this can sometimes take 200 to 300 msec for a cold start!
-        result = startClient(mMmapClient, &mClientHandle);
+        result = startClient(mMmapClient, nullptr /*const audio_attributes_t* */, &mClientHandle);
     }
     return result;
 }
 
 // Stop the flow of data such that start() can resume with loss of data.
-aaudio_result_t AAudioServiceStreamMMAP::pause() {
+aaudio_result_t AAudioServiceStreamMMAP::pause_l() {
     if (!isRunning()) {
         return AAUDIO_OK;
     }
-    aaudio_result_t result = AAudioServiceStreamBase::pause();
+    aaudio_result_t result = AAudioServiceStreamBase::pause_l();
     // TODO put before base::pause()?
     if (!mInService) {
         (void) stopClient(mClientHandle);
@@ -114,11 +104,11 @@
     return result;
 }
 
-aaudio_result_t AAudioServiceStreamMMAP::stop() {
+aaudio_result_t AAudioServiceStreamMMAP::stop_l() {
     if (!isRunning()) {
         return AAUDIO_OK;
     }
-    aaudio_result_t result = AAudioServiceStreamBase::stop();
+    aaudio_result_t result = AAudioServiceStreamBase::stop_l();
     // TODO put before base::stop()?
     if (!mInService) {
         (void) stopClient(mClientHandle);
@@ -127,14 +117,15 @@
 }
 
 aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
-                                                       audio_port_handle_t *clientHandle) {
+                                                     const audio_attributes_t *attr,
+                                                     audio_port_handle_t *clientHandle) {
     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
     if (endpoint == nullptr) {
         ALOGE("%s() has no endpoint", __func__);
         return AAUDIO_ERROR_INVALID_STATE;
     }
     // Start the client on behalf of the application. Generate a new porthandle.
-    aaudio_result_t result = endpoint->startClient(client, clientHandle);
+    aaudio_result_t result = endpoint->startClient(client, attr, clientHandle);
     return result;
 }
 
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 1509f7d..5902613 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -52,26 +52,25 @@
 
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
+    aaudio_result_t startClient(const android::AudioClient& client,
+                                const audio_attributes_t *attr,
+                                audio_port_handle_t *clientHandle) override;
+
+    aaudio_result_t stopClient(audio_port_handle_t clientHandle) override;
+
+    const char *getTypeText() const override { return "MMAP"; }
+
+protected:
+
     /**
      * Stop the flow of data so that start() can resume without loss of data.
      *
      * This is not guaranteed to be synchronous but it currently is.
      * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
     */
-    aaudio_result_t pause() override;
+    aaudio_result_t pause_l() override;
 
-    aaudio_result_t stop() override;
-
-    aaudio_result_t startClient(const android::AudioClient& client,
-                                audio_port_handle_t *clientHandle) override;
-
-    aaudio_result_t stopClient(audio_port_handle_t clientHandle) override;
-
-    aaudio_result_t close() override;
-
-    const char *getTypeText() const override { return "MMAP"; }
-
-protected:
+    aaudio_result_t stop_l() override;
 
     aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
 
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 2ca847a..01b1c2e 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -203,9 +203,8 @@
     return result;
 }
 
-
-aaudio_result_t AAudioServiceStreamShared::close()  {
-    aaudio_result_t result = AAudioServiceStreamBase::close();
+aaudio_result_t AAudioServiceStreamShared::close_l()  {
+    aaudio_result_t result = AAudioServiceStreamBase::close_l();
 
     {
         std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
diff --git a/services/oboeservice/AAudioServiceStreamShared.h b/services/oboeservice/AAudioServiceStreamShared.h
index 61769b5..abcb782 100644
--- a/services/oboeservice/AAudioServiceStreamShared.h
+++ b/services/oboeservice/AAudioServiceStreamShared.h
@@ -52,7 +52,7 @@
 
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
-    aaudio_result_t close() override;
+    aaudio_result_t close_l() override;
 
     /**
      * This must be locked when calling getAudioDataFifoBuffer_l() and while
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
index 3328159..8e66b94 100644
--- a/services/oboeservice/AAudioStreamTracker.cpp
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -30,32 +30,20 @@
 using namespace android;
 using namespace aaudio;
 
-sp<AAudioServiceStreamBase> AAudioStreamTracker::decrementAndRemoveStreamByHandle(
+int32_t AAudioStreamTracker::removeStreamByHandle(
         aaudio_handle_t streamHandle) {
     std::lock_guard<std::mutex> lock(mHandleLock);
-    sp<AAudioServiceStreamBase> serviceStream;
-    auto it = mStreamsByHandle.find(streamHandle);
-    if (it != mStreamsByHandle.end()) {
-        sp<AAudioServiceStreamBase> tempStream = it->second;
-        // Does the caller need to close the stream?
-        // The reference count should never be negative.
-        // But it is safer to check for <= 0 than == 0.
-        if ((tempStream->decrementServiceReferenceCount_l() <= 0) && tempStream->isCloseNeeded()) {
-            serviceStream = tempStream; // Only return stream if ready to be closed.
-            mStreamsByHandle.erase(it);
-        }
-    }
-    return serviceStream;
+    auto count = mStreamsByHandle.erase(streamHandle);
+    return static_cast<int32_t>(count);
 }
 
-sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandleAndIncrement(
+sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle(
         aaudio_handle_t streamHandle) {
     std::lock_guard<std::mutex> lock(mHandleLock);
     sp<AAudioServiceStreamBase> serviceStream;
     auto it = mStreamsByHandle.find(streamHandle);
     if (it != mStreamsByHandle.end()) {
         serviceStream = it->second;
-        serviceStream->incrementServiceReferenceCount_l();
     }
     return serviceStream;
 }
@@ -63,7 +51,7 @@
 // The port handle is only available when the stream is started.
 // So we have to iterate over all the streams.
 // Luckily this rarely happens.
-sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandleAndIncrement(
+sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandle(
         audio_port_handle_t portHandle) {
     std::lock_guard<std::mutex> lock(mHandleLock);
     sp<AAudioServiceStreamBase> serviceStream;
@@ -72,7 +60,6 @@
         auto candidate = it->second;
         if (candidate->getPortHandle() == portHandle) {
             serviceStream = candidate;
-            serviceStream->incrementServiceReferenceCount_l();
             break;
         }
         it++;
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
index 57ec426..d1301a2 100644
--- a/services/oboeservice/AAudioStreamTracker.h
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -32,25 +32,20 @@
 
 public:
     /**
-     * Find the stream associated with the handle.
-     * Decrement its reference counter. If zero and the stream needs
-     * to be closed then remove the stream and return a pointer to the stream.
-     * Otherwise return null if it does not need to be closed.
+     * Remove any streams with the matching handle.
      *
      * @param streamHandle
-     * @return strong pointer to the stream if it needs to be closed, or nullptr
+     * @return number of streams removed
      */
-    android::sp<AAudioServiceStreamBase> decrementAndRemoveStreamByHandle(
-            aaudio_handle_t streamHandle);
+    int32_t removeStreamByHandle(aaudio_handle_t streamHandle);
 
     /**
      * Look up a stream based on the handle.
-     * Increment its service reference count if found.
      *
      * @param streamHandle
      * @return strong pointer to the stream if found, or nullptr
      */
-    android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandleAndIncrement(
+    android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(
             aaudio_handle_t streamHandle);
 
     /**
@@ -60,7 +55,7 @@
      * @param portHandle
      * @return strong pointer to the stream if found, or nullptr
      */
-    android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandleAndIncrement(
+    android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandle(
             audio_port_handle_t portHandle);
 
     /**
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
new file mode 100644
index 0000000..8b1e2c0
--- /dev/null
+++ b/services/oboeservice/Android.bp
@@ -0,0 +1,68 @@
+// Copyright (C) 2019 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.
+
+cc_library_shared {
+
+    name: "libaaudioservice",
+
+    srcs: [
+        "AAudioClientTracker.cpp",
+        "AAudioEndpointManager.cpp",
+        "AAudioMixer.cpp",
+        "AAudioService.cpp",
+        "AAudioServiceEndpoint.cpp",
+        "AAudioServiceEndpointCapture.cpp",
+        "AAudioServiceEndpointMMAP.cpp",
+        "AAudioServiceEndpointPlay.cpp",
+        "AAudioServiceEndpointShared.cpp",
+        "AAudioServiceStreamBase.cpp",
+        "AAudioServiceStreamMMAP.cpp",
+        "AAudioServiceStreamShared.cpp",
+        "AAudioStreamTracker.cpp",
+        "AAudioThread.cpp",
+        "SharedMemoryProxy.cpp",
+        "SharedRingBuffer.cpp",
+        "TimestampScheduler.cpp",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libaaudio_internal",
+        "libaudioclient",
+        "libaudioflinger",
+        "libaudioutils",
+        "libmedia_helper",
+        "libmediametrics",
+        "libmediautils",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudiohal_headers",
+    ],
+
+    include_dirs: [
+        "frameworks/av/media/libnbaio/include_mono",
+        "frameworks/av/media/libnbaio/include",
+    ],
+}
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
deleted file mode 100644
index 3d5f140..0000000
--- a/services/oboeservice/Android.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# AAudio Service
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaaudioservice
-LOCAL_MODULE_TAGS := optional
-
-LIBAAUDIO_DIR := ../../media/libaaudio
-LIBAAUDIO_SRC_DIR := $(LIBAAUDIO_DIR)/src
-
-LOCAL_C_INCLUDES := \
-    $(TOPDIR)frameworks/av/services/audioflinger \
-    $(call include-path-for, audio-utils) \
-    frameworks/native/include \
-    system/core/base/include \
-    $(TOP)/frameworks/native/media/libaaudio/include/include \
-    $(TOP)/frameworks/av/media/libaaudio/include \
-    $(TOP)/frameworks/av/media/utils/include \
-    frameworks/native/include \
-    $(TOP)/external/tinyalsa/include \
-    $(TOP)/frameworks/av/media/libaaudio/src
-
-LOCAL_SRC_FILES += \
-    SharedMemoryProxy.cpp \
-    SharedRingBuffer.cpp \
-    AAudioClientTracker.cpp \
-    AAudioEndpointManager.cpp \
-    AAudioMixer.cpp \
-    AAudioService.cpp \
-    AAudioServiceEndpoint.cpp \
-    AAudioServiceEndpointCapture.cpp \
-    AAudioServiceEndpointMMAP.cpp \
-    AAudioServiceEndpointPlay.cpp \
-    AAudioServiceEndpointShared.cpp \
-    AAudioServiceStreamBase.cpp \
-    AAudioServiceStreamMMAP.cpp \
-    AAudioServiceStreamShared.cpp \
-    AAudioStreamTracker.cpp \
-    TimestampScheduler.cpp \
-    AAudioThread.cpp
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-# LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_CFLAGS += -Wno-unused-parameter
-LOCAL_CFLAGS += -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES :=  \
-    libaaudio \
-    libaudioflinger \
-    libaudioclient \
-    libbinder \
-    libcutils \
-    libmediautils \
-    libutils \
-    liblog
-
-include $(BUILD_SHARED_LIBRARY)
-
-
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
deleted file mode 100644
index 3f02f48..0000000
--- a/services/soundtrigger/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 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.
-
-cc_library_shared {
-    name: "libsoundtriggerservice",
-
-    srcs: [
-        "SoundTriggerHwService.cpp",
-        "SoundTriggerHalHidl.cpp",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libutils",
-        "libbinder",
-        "libcutils",
-        "libhardware",
-        "libsoundtrigger",
-        "libaudioclient",
-        "libaudioutils",
-        "libmediautils",
-
-        "libhwbinder",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libbase",
-        "libaudiohal",
-        "libaudiohal_deathhandler",
-        "android.hardware.soundtrigger@2.0",
-        "android.hardware.soundtrigger@2.1",
-        "android.hardware.soundtrigger@2.2",
-        "android.hardware.audio.common@2.0",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-    ],
-
-    include_dirs: ["frameworks/av/services/audioflinger"],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-}
diff --git a/services/soundtrigger/OWNERS b/services/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/services/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
deleted file mode 100644
index 68d54c7..0000000
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Copyright (C) 2016 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_TAG "SoundTriggerHalHidl"
-//#define LOG_NDEBUG 0
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <media/audiohal/hidl/HalDeathHandler.h>
-#include <utils/Log.h>
-#include "SoundTriggerHalHidl.h"
-#include <hidlmemory/mapping.h>
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-
-namespace android {
-
-using ::android::hardware::ProcessState;
-using ::android::hardware::Return;
-using ::android::hardware::Status;
-using ::android::hardware::Void;
-using ::android::hardware::audio::common::V2_0::AudioDevice;
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-
-namespace {
-
-// Backs up by the vector with the contents of shared memory.
-// It is assumed that the passed hidl_vector is empty, so it's
-// not cleared if the memory is a null object.
-// The caller needs to keep the returned sp<IMemory> as long as
-// the data is needed.
-std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
-    sp<IMemory> memory;
-    if (m.size() == 0) {
-        return std::make_pair(true, memory);
-    }
-    memory = mapMemory(m);
-    if (memory != nullptr) {
-        memory->read();
-        vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
-                memory->getSize());
-        return std::make_pair(true, memory);
-    }
-    ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
-    return std::make_pair(false, memory);
-}
-
-// Moves the data from the vector into allocated shared memory,
-// emptying the vector.
-// It is assumed that the passed hidl_memory is a null object, so it's
-// not reset if the vector is empty.
-// The caller needs to keep the returned sp<IMemory> as long as
-// the data is needed.
-std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
-    sp<IMemory> memory;
-    if (v->size() == 0) {
-        return std::make_pair(true, memory);
-    }
-    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
-    if (ashmem == 0) {
-        ALOGE("Failed to retrieve ashmem allocator service");
-        return std::make_pair(false, memory);
-    }
-    bool success = false;
-    Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
-        success = s;
-        if (success) *mem = m;
-    });
-    if (r.isOk() && success) {
-        memory = hardware::mapMemory(*mem);
-        if (memory != 0) {
-            memory->update();
-            memcpy(memory->getPointer(), v->data(), v->size());
-            memory->commit();
-            v->resize(0);
-            return std::make_pair(true, memory);
-        } else {
-            ALOGE("Failed to map allocated ashmem");
-        }
-    } else {
-        ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
-    }
-    return std::make_pair(false, memory);
-}
-
-}  // namespace
-
-/* static */
-sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
-{
-    return new SoundTriggerHalHidl(moduleName);
-}
-
-int SoundTriggerHalHidl::getProperties(struct sound_trigger_properties *properties)
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    ISoundTriggerHw::Properties halProperties;
-    Return<void> hidlReturn;
-    int ret;
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger->getProperties([&](int rc, auto res) {
-            ret = rc;
-            halProperties = res;
-            ALOGI("getProperties res implementor %s", res.implementor.c_str());
-        });
-    }
-
-    if (hidlReturn.isOk()) {
-        if (ret == 0) {
-            convertPropertiesFromHal(properties, &halProperties);
-        }
-    } else {
-        ALOGE("getProperties error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    ALOGI("getProperties ret %d", ret);
-    return ret;
-}
-
-int SoundTriggerHalHidl::loadSoundModel(struct sound_trigger_sound_model *sound_model,
-                        sound_model_callback_t callback,
-                        void *cookie,
-                        sound_model_handle_t *handle)
-{
-    if (handle == NULL) {
-        return -EINVAL;
-    }
-
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    uint32_t modelId;
-    {
-        AutoMutex lock(mLock);
-        do {
-            modelId = nextUniqueId();
-            ALOGI("loadSoundModel modelId %u", modelId);
-            sp<SoundModel> model = mSoundModels.valueFor(modelId);
-            ALOGI("loadSoundModel model %p", model.get());
-        } while (mSoundModels.valueFor(modelId) != 0 && modelId != 0);
-    }
-    LOG_ALWAYS_FATAL_IF(modelId == 0,
-                        "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd",
-                        mSoundModels.size());
-
-    Return<void> hidlReturn;
-    int ret;
-    SoundModelHandle halHandle;
-    sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
-    sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
-    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        if (soundtrigger_2_2) {
-            V2_2_ISoundTriggerHw::PhraseSoundModel halSoundModel;
-            auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
-            if (result.first) {
-                AutoMutex lock(mHalLock);
-                hidlReturn = soundtrigger_2_2->loadPhraseSoundModel_2_1(
-                        halSoundModel,
-                        this, modelId, [&](int32_t retval, auto res) {
-                            ret = retval;
-                            halHandle = res;
-                        });
-            } else {
-                return NO_MEMORY;
-            }
-        } else if (soundtrigger_2_1) {
-            V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel;
-            auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
-            if (result.first) {
-                AutoMutex lock(mHalLock);
-                hidlReturn = soundtrigger_2_1->loadPhraseSoundModel_2_1(
-                        halSoundModel,
-                        this, modelId, [&](int32_t retval, auto res) {
-                            ret = retval;
-                            halHandle = res;
-                        });
-            } else {
-                return NO_MEMORY;
-            }
-        } else {
-            ISoundTriggerHw::PhraseSoundModel halSoundModel;
-            convertPhraseSoundModelToHal(&halSoundModel, sound_model);
-            AutoMutex lock(mHalLock);
-            hidlReturn = soundtrigger->loadPhraseSoundModel(
-                    halSoundModel,
-                    this, modelId, [&](int32_t retval, auto res) {
-                        ret = retval;
-                        halHandle = res;
-                    });
-        }
-    } else {
-        if (soundtrigger_2_2) {
-            V2_2_ISoundTriggerHw::SoundModel halSoundModel;
-            auto result = convertSoundModelToHal(&halSoundModel, sound_model);
-            if (result.first) {
-                AutoMutex lock(mHalLock);
-                hidlReturn = soundtrigger_2_2->loadSoundModel_2_1(halSoundModel,
-                        this, modelId, [&](int32_t retval, auto res) {
-                            ret = retval;
-                            halHandle = res;
-                        });
-            } else {
-                return NO_MEMORY;
-            }
-        } else if (soundtrigger_2_1) {
-            V2_1_ISoundTriggerHw::SoundModel halSoundModel;
-            auto result = convertSoundModelToHal(&halSoundModel, sound_model);
-            if (result.first) {
-                AutoMutex lock(mHalLock);
-                hidlReturn = soundtrigger_2_1->loadSoundModel_2_1(halSoundModel,
-                        this, modelId, [&](int32_t retval, auto res) {
-                            ret = retval;
-                            halHandle = res;
-                        });
-            } else {
-                return NO_MEMORY;
-            }
-        } else {
-            ISoundTriggerHw::SoundModel halSoundModel;
-            convertSoundModelToHal(&halSoundModel, sound_model);
-            AutoMutex lock(mHalLock);
-            hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
-                    this, modelId, [&](int32_t retval, auto res) {
-                        ret = retval;
-                        halHandle = res;
-                    });
-        }
-    }
-
-    if (hidlReturn.isOk()) {
-        if (ret == 0) {
-            AutoMutex lock(mLock);
-            *handle = (sound_model_handle_t)modelId;
-            sp<SoundModel> model = new SoundModel(*handle, callback, cookie, halHandle);
-            mSoundModels.add(*handle, model);
-        }
-    } else {
-        ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-
-    return ret;
-}
-
-int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle)
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    sp<SoundModel> model = removeModel(handle);
-    if (model == 0) {
-        ALOGE("unloadSoundModel model not found for handle %u", handle);
-        return -EINVAL;
-    }
-
-    Return<int32_t> hidlReturn(0);
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
-    }
-
-    if (!hidlReturn.isOk()) {
-        ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-
-    return hidlReturn;
-}
-
-int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
-                         const struct sound_trigger_recognition_config *config,
-                         recognition_callback_t callback,
-                         void *cookie)
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    sp<SoundModel> model = getModel(handle);
-    if (model == 0) {
-        ALOGE("startRecognition model not found for handle %u", handle);
-        return -EINVAL;
-    }
-
-    model->mRecognitionCallback = callback;
-    model->mRecognitionCookie = cookie;
-
-    sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
-    sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
-    Return<int32_t> hidlReturn(0);
-
-    if (soundtrigger_2_2) {
-        V2_2_ISoundTriggerHw::RecognitionConfig halConfig;
-        auto result = convertRecognitionConfigToHal(&halConfig, config);
-        if (result.first) {
-            AutoMutex lock(mHalLock);
-            hidlReturn = soundtrigger_2_2->startRecognition_2_1(
-                    model->mHalHandle, halConfig, this, handle);
-        } else {
-            return NO_MEMORY;
-        }
-    } else if (soundtrigger_2_1) {
-        V2_1_ISoundTriggerHw::RecognitionConfig halConfig;
-        auto result = convertRecognitionConfigToHal(&halConfig, config);
-        if (result.first) {
-            AutoMutex lock(mHalLock);
-            hidlReturn = soundtrigger_2_1->startRecognition_2_1(
-                    model->mHalHandle, halConfig, this, handle);
-        } else {
-            return NO_MEMORY;
-        }
-    } else {
-        ISoundTriggerHw::RecognitionConfig halConfig;
-        convertRecognitionConfigToHal(&halConfig, config);
-        {
-            AutoMutex lock(mHalLock);
-            hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
-        }
-    }
-
-    if (!hidlReturn.isOk()) {
-        ALOGE("startRecognition error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    return hidlReturn;
-}
-
-int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle)
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    sp<SoundModel> model = getModel(handle);
-    if (model == 0) {
-        ALOGE("stopRecognition model not found for handle %u", handle);
-        return -EINVAL;
-    }
-
-    Return<int32_t> hidlReturn(0);
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
-    }
-
-    if (!hidlReturn.isOk()) {
-        ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    return hidlReturn;
-}
-
-int SoundTriggerHalHidl::stopAllRecognitions()
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    Return<int32_t> hidlReturn(0);
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger->stopAllRecognitions();
-    }
-
-    if (!hidlReturn.isOk()) {
-        ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
-        return FAILED_TRANSACTION;
-    }
-    return hidlReturn;
-}
-
-int SoundTriggerHalHidl::getModelState(sound_model_handle_t handle)
-{
-    sp<ISoundTriggerHw> soundtrigger = getService();
-    if (soundtrigger == 0) {
-        return -ENODEV;
-    }
-
-    sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
-    if (soundtrigger_2_2 == 0) {
-        ALOGE("getModelState not supported");
-        return -ENODEV;
-    }
-
-    sp<SoundModel> model = getModel(handle);
-    if (model == 0) {
-        ALOGE("getModelState model not found for handle %u", handle);
-        return -EINVAL;
-    }
-
-    int ret = NO_ERROR;
-    Return<int32_t> hidlReturn(0);
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger_2_2->getModelState(model->mHalHandle);
-    }
-    if (!hidlReturn.isOk()) {
-        ALOGE("getModelState error %s", hidlReturn.description().c_str());
-        ret = FAILED_TRANSACTION;
-    }
-    return ret;
-}
-
-SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
-    : mModuleName(moduleName), mNextUniqueId(1)
-{
-    LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0,
-            "Treble soundtrigger only supports primary module");
-}
-
-SoundTriggerHalHidl::~SoundTriggerHalHidl()
-{
-}
-
-sp<ISoundTriggerHw> SoundTriggerHalHidl::getService()
-{
-    AutoMutex lock(mLock);
-    if (mISoundTrigger == 0) {
-        if (mModuleName == NULL) {
-            mModuleName = "primary";
-        }
-        mISoundTrigger = ISoundTriggerHw::getService();
-        if (mISoundTrigger != 0) {
-            mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
-        }
-    }
-    return mISoundTrigger;
-}
-
-sp<V2_1_ISoundTriggerHw> SoundTriggerHalHidl::toService2_1(const sp<ISoundTriggerHw>& s)
-{
-    auto castResult_2_1 = V2_1_ISoundTriggerHw::castFrom(s);
-    return castResult_2_1.isOk() ? static_cast<sp<V2_1_ISoundTriggerHw>>(castResult_2_1) : nullptr;
-}
-
-sp<V2_2_ISoundTriggerHw> SoundTriggerHalHidl::toService2_2(const sp<ISoundTriggerHw>& s)
-{
-    auto castResult_2_2 = V2_2_ISoundTriggerHw::castFrom(s);
-    return castResult_2_2.isOk() ? static_cast<sp<V2_2_ISoundTriggerHw>>(castResult_2_2) : nullptr;
-}
-
-sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
-{
-    AutoMutex lock(mLock);
-    return mSoundModels.valueFor(handle);
-}
-
-sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::removeModel(sound_model_handle_t handle)
-{
-    AutoMutex lock(mLock);
-    sp<SoundModel> model = mSoundModels.valueFor(handle);
-    mSoundModels.removeItem(handle);
-    return model;
-}
-
-uint32_t SoundTriggerHalHidl::nextUniqueId()
-{
-    return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
-                (uint_fast32_t) 1, memory_order_acq_rel);
-}
-
-void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid,
-                                           const sound_trigger_uuid_t *uuid)
-{
-    halUuid->timeLow = uuid->timeLow;
-    halUuid->timeMid = uuid->timeMid;
-    halUuid->versionAndTimeHigh = uuid->timeHiAndVersion;
-    halUuid->variantAndClockSeqHigh = uuid->clockSeq;
-    memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node));
-}
-
-void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid,
-                                             const Uuid *halUuid)
-{
-    uuid->timeLow = halUuid->timeLow;
-    uuid->timeMid = halUuid->timeMid;
-    uuid->timeHiAndVersion = halUuid->versionAndTimeHigh;
-    uuid->clockSeq = halUuid->variantAndClockSeqHigh;
-    memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node));
-}
-
-void SoundTriggerHalHidl::convertPropertiesFromHal(
-        struct sound_trigger_properties *properties,
-        const ISoundTriggerHw::Properties *halProperties)
-{
-    strlcpy(properties->implementor,
-            halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
-    strlcpy(properties->description,
-            halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
-    properties->version = halProperties->version;
-    convertUuidFromHal(&properties->uuid, &halProperties->uuid);
-    properties->max_sound_models = halProperties->maxSoundModels;
-    properties->max_key_phrases = halProperties->maxKeyPhrases;
-    properties->max_users = halProperties->maxUsers;
-    properties->recognition_modes = halProperties->recognitionModes;
-    properties->capture_transition = (bool)halProperties->captureTransition;
-    properties->max_buffer_ms = halProperties->maxBufferMs;
-    properties->concurrent_capture = (bool)halProperties->concurrentCapture;
-    properties->trigger_in_event = (bool)halProperties->triggerInEvent;
-    properties->power_consumption_mw = halProperties->powerConsumptionMw;
-}
-
-void SoundTriggerHalHidl::convertTriggerPhraseToHal(
-        ISoundTriggerHw::Phrase *halTriggerPhrase,
-        const struct sound_trigger_phrase *triggerPhrase)
-{
-    halTriggerPhrase->id = triggerPhrase->id;
-    halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode;
-    halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users);
-    halTriggerPhrase->locale = triggerPhrase->locale;
-    halTriggerPhrase->text = triggerPhrase->text;
-}
-
-
-void SoundTriggerHalHidl::convertTriggerPhrasesToHal(
-        hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
-        struct sound_trigger_phrase_sound_model *keyPhraseModel)
-{
-    halTriggerPhrases->resize(keyPhraseModel->num_phrases);
-    for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
-        convertTriggerPhraseToHal(&(*halTriggerPhrases)[i], &keyPhraseModel->phrases[i]);
-    }
-}
-
-void SoundTriggerHalHidl::convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
-        const struct sound_trigger_sound_model *soundModel)
-{
-    halModel->type = (SoundModelType)soundModel->type;
-    convertUuidToHal(&halModel->uuid, &soundModel->uuid);
-    convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid);
-    halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertSoundModelToHal(
-        V2_1_ISoundTriggerHw::SoundModel *halModel,
-        const struct sound_trigger_sound_model *soundModel)
-{
-    convertSoundModelToHal(&halModel->header, soundModel);
-    return moveVectorToMemory(&halModel->header.data, &halModel->data);
-}
-
-void SoundTriggerHalHidl::convertPhraseSoundModelToHal(
-        ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
-        const struct sound_trigger_sound_model *soundModel)
-{
-    struct sound_trigger_phrase_sound_model *keyPhraseModel =
-            (struct sound_trigger_phrase_sound_model *)soundModel;
-    convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
-    convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertPhraseSoundModelToHal(
-        V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
-        const struct sound_trigger_sound_model *soundModel)
-{
-    struct sound_trigger_phrase_sound_model *keyPhraseModel =
-            (struct sound_trigger_phrase_sound_model *)soundModel;
-    convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
-    return convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
-}
-
-void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal(
-        PhraseRecognitionExtra *halExtra,
-        const struct sound_trigger_phrase_recognition_extra *extra)
-{
-    halExtra->id = extra->id;
-    halExtra->recognitionModes = extra->recognition_modes;
-    halExtra->confidenceLevel = extra->confidence_level;
-    halExtra->levels.resize(extra->num_levels);
-    for (unsigned int i = 0; i < extra->num_levels; i++) {
-        halExtra->levels[i].userId = extra->levels[i].user_id;
-        halExtra->levels[i].levelPercent = extra->levels[i].level;
-    }
-}
-
-void SoundTriggerHalHidl::convertRecognitionConfigToHal(
-        ISoundTriggerHw::RecognitionConfig *halConfig,
-        const struct sound_trigger_recognition_config *config)
-{
-    halConfig->captureHandle = config->capture_handle;
-    halConfig->captureDevice = (AudioDevice)config->capture_device;
-    halConfig->captureRequested = (uint32_t)config->capture_requested;
-
-    halConfig->phrases.resize(config->num_phrases);
-    for (unsigned int i = 0; i < config->num_phrases; i++) {
-        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
-                                  &config->phrases[i]);
-    }
-
-    halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size);
-}
-
-std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertRecognitionConfigToHal(
-        V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
-        const struct sound_trigger_recognition_config *config)
-{
-    convertRecognitionConfigToHal(&halConfig->header, config);
-    return moveVectorToMemory(&halConfig->header.data, &halConfig->data);
-}
-
-
-// ISoundTriggerHwCallback
-::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
-        const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent,
-        CallbackCookie cookie)
-{
-    sp<SoundModel> model;
-    {
-        AutoMutex lock(mLock);
-        model = mSoundModels.valueFor((SoundModelHandle)cookie);
-        if (model == 0) {
-            return Return<void>();
-        }
-    }
-    struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent);
-    if (event == NULL) {
-        return Return<void>();
-    }
-    event->model = model->mHandle;
-    model->mRecognitionCallback(event, model->mRecognitionCookie);
-
-    free(event);
-
-    return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback(
-        const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
-        CallbackCookie cookie)
-{
-    sp<SoundModel> model;
-    {
-        AutoMutex lock(mLock);
-        model = mSoundModels.valueFor((SoundModelHandle)cookie);
-        if (model == 0) {
-            return Return<void>();
-        }
-    }
-
-    struct sound_trigger_phrase_recognition_event *event =
-            convertPhraseRecognitionEventFromHal(&halEvent);
-    if (event == NULL) {
-        return Return<void>();
-    }
-    event->common.model = model->mHandle;
-    model->mRecognitionCallback(&event->common, model->mRecognitionCookie);
-
-    free(event);
-
-    return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback(
-        const V2_0_ISoundTriggerHwCallback::ModelEvent& halEvent,
-        CallbackCookie cookie)
-{
-    sp<SoundModel> model;
-    {
-        AutoMutex lock(mLock);
-        model = mSoundModels.valueFor((SoundModelHandle)cookie);
-        if (model == 0) {
-            return Return<void>();
-        }
-    }
-
-    struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent);
-    if (event == NULL) {
-        return Return<void>();
-    }
-
-    event->model = model->mHandle;
-    model->mSoundModelCallback(event, model->mSoundModelCookie);
-
-    free(event);
-
-    return Return<void>();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback_2_1(
-        const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie) {
-    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
-    V2_0_ISoundTriggerHwCallback::RecognitionEvent event_2_0 = event.header;
-    auto result = memoryAsVector(event.data, &event_2_0.data);
-    return result.first ? recognitionCallback(event_2_0, cookie) : Void();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback_2_1(
-        const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie) {
-    V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
-    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
-    event_2_0.common = event.common.header;
-    event_2_0.phraseExtras.setToExternal(
-            const_cast<PhraseRecognitionExtra*>(event.phraseExtras.data()),
-            event.phraseExtras.size());
-    auto result = memoryAsVector(event.common.data, &event_2_0.common.data);
-    return result.first ? phraseRecognitionCallback(event_2_0, cookie) : Void();
-}
-
-::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback_2_1(
-        const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie) {
-    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
-    V2_0_ISoundTriggerHwCallback::ModelEvent event_2_0 = event.header;
-    auto result = memoryAsVector(event.data, &event_2_0.data);
-    return result.first ? soundModelCallback(event_2_0, cookie) : Void();
-}
-
-
-struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal(
-                                              const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent)
-{
-    struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc(
-            sizeof(struct sound_trigger_model_event) +
-            halEvent->data.size());
-    if (event == NULL) {
-        return NULL;
-    }
-
-    event->status = (int)halEvent->status;
-    // event->model to be set by caller
-    event->data_offset = sizeof(struct sound_trigger_model_event);
-    event->data_size = halEvent->data.size();
-    uint8_t *dst = (uint8_t *)event + event->data_offset;
-    uint8_t *src = (uint8_t *)&halEvent->data[0];
-    memcpy(dst, src, halEvent->data.size());
-
-    return event;
-}
-
-void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal(
-        struct sound_trigger_phrase_recognition_extra *extra,
-        const PhraseRecognitionExtra *halExtra)
-{
-    extra->id = halExtra->id;
-    extra->recognition_modes = halExtra->recognitionModes;
-    extra->confidence_level = halExtra->confidenceLevel;
-
-    size_t i;
-    for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
-        extra->levels[i].user_id = halExtra->levels[i].userId;
-        extra->levels[i].level = halExtra->levels[i].levelPercent;
-    }
-    extra->num_levels = (unsigned int)i;
-}
-
-
-struct sound_trigger_phrase_recognition_event* SoundTriggerHalHidl::convertPhraseRecognitionEventFromHal(
-        const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent)
-{
-    if (halPhraseEvent->common.type != SoundModelType::KEYPHRASE) {
-        ALOGE("Received non-keyphrase event type as PhraseRecognitionEvent");
-        return NULL;
-    }
-    struct sound_trigger_phrase_recognition_event *phraseEvent =
-            (struct sound_trigger_phrase_recognition_event *)malloc(
-                    sizeof(struct sound_trigger_phrase_recognition_event) +
-                    halPhraseEvent->common.data.size());
-    if (phraseEvent == NULL) {
-        return NULL;
-    }
-    phraseEvent->common.data_offset = sizeof(sound_trigger_phrase_recognition_event);
-
-    for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
-        convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
-                                             &halPhraseEvent->phraseExtras[i]);
-    }
-    phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
-
-    fillRecognitionEventFromHal(&phraseEvent->common, &halPhraseEvent->common);
-    return phraseEvent;
-}
-
-struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
-        const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
-{
-    if (halEvent->type == SoundModelType::KEYPHRASE) {
-        ALOGE("Received keyphrase event type as RecognitionEvent");
-        return NULL;
-    }
-    struct sound_trigger_recognition_event *event;
-    event = (struct sound_trigger_recognition_event *)malloc(
-            sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
-    if (event == NULL) {
-        return NULL;
-    }
-    event->data_offset = sizeof(sound_trigger_recognition_event);
-
-    fillRecognitionEventFromHal(event, halEvent);
-    return event;
-}
-
-void SoundTriggerHalHidl::fillRecognitionEventFromHal(
-        struct sound_trigger_recognition_event *event,
-        const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
-{
-    event->status = (int)halEvent->status;
-    event->type = (sound_trigger_sound_model_type_t)halEvent->type;
-    // event->model to be set by caller
-    event->capture_available = (bool)halEvent->captureAvailable;
-    event->capture_session = halEvent->captureSession;
-    event->capture_delay_ms = halEvent->captureDelayMs;
-    event->capture_preamble_ms = halEvent->capturePreambleMs;
-    event->trigger_in_data = (bool)halEvent->triggerInData;
-    event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz;
-    event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask;
-    event->audio_config.format = (audio_format_t)halEvent->audioConfig.format;
-
-    event->data_size = halEvent->data.size();
-    uint8_t *dst = (uint8_t *)event + event->data_offset;
-    uint8_t *src = (uint8_t *)&halEvent->data[0];
-    memcpy(dst, src, halEvent->data.size());
-}
-
-} // namespace android
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
deleted file mode 100644
index fb9e39e..0000000
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
-
-#include <utility>
-
-#include <stdatomic.h>
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include "SoundTriggerHalInterface.h"
-#include <android/hardware/soundtrigger/2.0/types.h>
-#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
-#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
-#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
-#include <android/hardware/soundtrigger/2.1/ISoundTriggerHwCallback.h>
-
-namespace android {
-
-using ::android::hardware::audio::common::V2_0::Uuid;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::soundtrigger::V2_0::ConfidenceLevel;
-using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
-using ::android::hardware::soundtrigger::V2_0::SoundModelType;
-using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
-using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
-using V2_0_ISoundTriggerHwCallback =
-        ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
-using V2_1_ISoundTriggerHw =
-        ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
-using V2_1_ISoundTriggerHwCallback =
-        ::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using V2_2_ISoundTriggerHw =
-        ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
-
-class SoundTriggerHalHidl : public SoundTriggerHalInterface,
-                            public virtual V2_1_ISoundTriggerHwCallback
-
-{
-public:
-        virtual int getProperties(struct sound_trigger_properties *properties);
-
-        /*
-         * Load a sound model. Once loaded, recognition of this model can be started and stopped.
-         * Only one active recognition per model at a time. The SoundTrigger service will handle
-         * concurrent recognition requests by different users/applications on the same model.
-         * The implementation returns a unique handle used by other functions (unload_sound_model(),
-         * start_recognition(), etc...
-         */
-        virtual int loadSoundModel(struct sound_trigger_sound_model *sound_model,
-                                sound_model_callback_t callback,
-                                void *cookie,
-                                sound_model_handle_t *handle);
-
-        /*
-         * Unload a sound model. A sound model can be unloaded to make room for a new one to overcome
-         * implementation limitations.
-         */
-        virtual int unloadSoundModel(sound_model_handle_t handle);
-
-        /* Start recognition on a given model. Only one recognition active at a time per model.
-         * Once recognition succeeds of fails, the callback is called.
-         * TODO: group recognition configuration parameters into one struct and add key phrase options.
-         */
-        virtual int startRecognition(sound_model_handle_t handle,
-                                 const struct sound_trigger_recognition_config *config,
-                                 recognition_callback_t callback,
-                                 void *cookie);
-
-        /* Stop recognition on a given model.
-         * The implementation does not have to call the callback when stopped via this method.
-         */
-        virtual int stopRecognition(sound_model_handle_t handle);
-
-        /* Stop recognition on all models.
-         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_1 or above.
-         * If no implementation is provided, stop_recognition will be called for each running model.
-         */
-        virtual int stopAllRecognitions();
-
-        /* Get the current state of a given model.
-         * Returns 0 or an error code. If successful the state will be returned asynchronously
-         * via a recognition event in the callback method that was registered in the
-         * startRecognition() method.
-         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
-         */
-        virtual int getModelState(sound_model_handle_t handle);
-
-        // ISoundTriggerHwCallback
-        virtual ::android::hardware::Return<void> recognitionCallback(
-                const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
-        virtual ::android::hardware::Return<void> phraseRecognitionCallback(
-                const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie);
-        virtual ::android::hardware::Return<void> soundModelCallback(
-                const V2_0_ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie);
-        virtual ::android::hardware::Return<void> recognitionCallback_2_1(
-                const RecognitionEvent& event, CallbackCookie cookie);
-        virtual ::android::hardware::Return<void> phraseRecognitionCallback_2_1(
-                const PhraseRecognitionEvent& event, int32_t cookie);
-        virtual ::android::hardware::Return<void> soundModelCallback_2_1(
-                const ModelEvent& event, CallbackCookie cookie);
-private:
-        class SoundModel : public RefBase {
-        public:
-            SoundModel(sound_model_handle_t handle, sound_model_callback_t callback,
-                       void *cookie, android::hardware::soundtrigger::V2_0::SoundModelHandle halHandle)
-                 : mHandle(handle), mHalHandle(halHandle),
-                   mSoundModelCallback(callback), mSoundModelCookie(cookie),
-                   mRecognitionCallback(NULL), mRecognitionCookie(NULL) {}
-            ~SoundModel() {}
-
-            sound_model_handle_t   mHandle;
-            android::hardware::soundtrigger::V2_0::SoundModelHandle mHalHandle;
-            sound_model_callback_t mSoundModelCallback;
-            void *                 mSoundModelCookie;
-            recognition_callback_t mRecognitionCallback;
-            void *                 mRecognitionCookie;
-        };
-
-        friend class SoundTriggerHalInterface;
-
-        explicit SoundTriggerHalHidl(const char *moduleName = NULL);
-        virtual  ~SoundTriggerHalHidl();
-
-        void convertUuidToHal(Uuid *halUuid,
-                              const sound_trigger_uuid_t *uuid);
-        void convertUuidFromHal(sound_trigger_uuid_t *uuid,
-                                const Uuid *halUuid);
-
-        void convertPropertiesFromHal(
-                struct sound_trigger_properties *properties,
-                const ISoundTriggerHw::Properties *halProperties);
-
-        void convertTriggerPhraseToHal(
-                ISoundTriggerHw::Phrase *halTriggerPhrase,
-                const struct sound_trigger_phrase *triggerPhrase);
-        void convertTriggerPhrasesToHal(
-                hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
-                struct sound_trigger_phrase_sound_model *keyPhraseModel);
-        void convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
-                const struct sound_trigger_sound_model *soundModel);
-        std::pair<bool, sp<IMemory>> convertSoundModelToHal(
-                V2_1_ISoundTriggerHw::SoundModel *halModel,
-                const struct sound_trigger_sound_model *soundModel)
-                __attribute__((warn_unused_result));
-        void convertPhraseSoundModelToHal(ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
-                const struct sound_trigger_sound_model *soundModel);
-        std::pair<bool, sp<IMemory>> convertPhraseSoundModelToHal(
-                V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
-                const struct sound_trigger_sound_model *soundModel)
-                __attribute__((warn_unused_result));
-
-        void convertPhraseRecognitionExtraToHal(
-                PhraseRecognitionExtra *halExtra,
-                const struct sound_trigger_phrase_recognition_extra *extra);
-        void convertRecognitionConfigToHal(ISoundTriggerHw::RecognitionConfig *halConfig,
-                const struct sound_trigger_recognition_config *config);
-        std::pair<bool, sp<IMemory>> convertRecognitionConfigToHal(
-                V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
-                const struct sound_trigger_recognition_config *config)
-                __attribute__((warn_unused_result));
-
-        struct sound_trigger_model_event *convertSoundModelEventFromHal(
-                                              const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent);
-        void convertPhraseRecognitionExtraFromHal(
-                struct sound_trigger_phrase_recognition_extra *extra,
-                const PhraseRecognitionExtra *halExtra);
-        struct sound_trigger_phrase_recognition_event* convertPhraseRecognitionEventFromHal(
-                const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent);
-        struct sound_trigger_recognition_event *convertRecognitionEventFromHal(
-                const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
-        void fillRecognitionEventFromHal(
-                struct sound_trigger_recognition_event *event,
-                const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
-
-        uint32_t nextUniqueId();
-        sp<ISoundTriggerHw> getService();
-        sp<V2_1_ISoundTriggerHw> toService2_1(const sp<ISoundTriggerHw>& s);
-        sp<V2_2_ISoundTriggerHw> toService2_2(const sp<ISoundTriggerHw>& s);
-        sp<SoundModel> getModel(sound_model_handle_t handle);
-        sp<SoundModel> removeModel(sound_model_handle_t handle);
-
-        static pthread_once_t sOnceControl;
-        static void sOnceInit();
-
-        Mutex mLock;
-        Mutex mHalLock;
-        const char *mModuleName;
-        volatile atomic_uint_fast32_t  mNextUniqueId;
-        // Effect chains without a valid thread
-        DefaultKeyedVector< sound_model_handle_t , sp<SoundModel> > mSoundModels;
-        sp<::android::hardware::soundtrigger::V2_0::ISoundTriggerHw> mISoundTrigger;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
diff --git a/services/soundtrigger/SoundTriggerHalInterface.h b/services/soundtrigger/SoundTriggerHalInterface.h
deleted file mode 100644
index 0183ece..0000000
--- a/services/soundtrigger/SoundTriggerHalInterface.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
-
-#include <utils/RefBase.h>
-#include <system/sound_trigger.h>
-#include <hardware/sound_trigger.h>
-
-namespace android {
-
-class SoundTriggerHalInterface : public virtual RefBase
-{
-public:
-        /* get a sound trigger HAL instance */
-        static sp<SoundTriggerHalInterface> connectModule(const char *moduleName);
-
-        virtual     ~SoundTriggerHalInterface() {}
-
-        virtual int getProperties(struct sound_trigger_properties *properties) = 0;
-
-        /*
-         * Load a sound model. Once loaded, recognition of this model can be started and stopped.
-         * Only one active recognition per model at a time. The SoundTrigger service will handle
-         * concurrent recognition requests by different users/applications on the same model.
-         * The implementation returns a unique handle used by other functions (unload_sound_model(),
-         * start_recognition(), etc...
-         */
-        virtual int loadSoundModel(struct sound_trigger_sound_model *sound_model,
-                                sound_model_callback_t callback,
-                                void *cookie,
-                                sound_model_handle_t *handle) = 0;
-
-        /*
-         * Unload a sound model. A sound model can be unloaded to make room for a new one to overcome
-         * implementation limitations.
-         */
-        virtual int unloadSoundModel(sound_model_handle_t handle) = 0;
-
-        /* Start recognition on a given model. Only one recognition active at a time per model.
-         * Once recognition succeeds of fails, the callback is called.
-         * TODO: group recognition configuration parameters into one struct and add key phrase options.
-         */
-        virtual int startRecognition(sound_model_handle_t handle,
-                                 const struct sound_trigger_recognition_config *config,
-                                 recognition_callback_t callback,
-                                 void *cookie) = 0;
-
-        /* Stop recognition on a given model.
-         * The implementation does not have to call the callback when stopped via this method.
-         */
-        virtual int stopRecognition(sound_model_handle_t handle) = 0;
-
-        /* Stop recognition on all models.
-         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_1 or above.
-         * If no implementation is provided, stop_recognition will be called for each running model.
-         */
-        virtual int stopAllRecognitions() = 0;
-
-        /* Get the current state of a given model.
-         * Returns 0 or an error code. If successful the state will be returned asynchronously
-         * via a recognition event in the callback method that was registered in the
-         * startRecognition() method.
-         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
-         */
-        virtual int getModelState(sound_model_handle_t handle) = 0;
-
-protected:
-        SoundTriggerHalInterface() {}
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_INTERFACE_H
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
deleted file mode 100644
index 51afdcd..0000000
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Copyright (C) 2014 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_TAG "SoundTriggerHwService"
-//#define LOG_NDEBUG 0
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <pthread.h>
-
-#include <audio_utils/clock.h>
-#include <system/sound_trigger.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-#include <hardware/hardware.h>
-#include <media/AudioSystem.h>
-#include <mediautils/ServiceUtilities.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <system/sound_trigger.h>
-#include "SoundTriggerHwService.h"
-
-#define HW_MODULE_PREFIX "primary"
-namespace android {
-
-namespace {
-
-// Given an IMemory, returns a copy of its content along with its size.
-// Returns nullptr on failure or if input is nullptr.
-std::pair<std::unique_ptr<uint8_t[]>,
-          size_t> CopyToArray(const sp<IMemory>& mem) {
-    if (mem == nullptr) {
-        return std::make_pair(nullptr, 0);
-    }
-
-    const size_t size = mem->size();
-    if (size == 0) {
-        return std::make_pair(nullptr, 0);
-    }
-
-    std::unique_ptr<uint8_t[]> ar = std::make_unique<uint8_t[]>(size);
-    if (ar == nullptr) {
-        return std::make_pair(nullptr, 0);
-    }
-
-    memcpy(ar.get(), mem->pointer(), size);
-    return std::make_pair(std::move(ar), size);
-}
-
-}
-
-SoundTriggerHwService::SoundTriggerHwService()
-    : BnSoundTriggerHwService(),
-      mNextUniqueId(1),
-      mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
-      mCaptureState(false)
-{
-}
-
-void SoundTriggerHwService::onFirstRef()
-{
-    int rc;
-
-    sp<SoundTriggerHalInterface> halInterface =
-            SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
-
-    if (halInterface == 0) {
-        ALOGW("could not connect to HAL");
-        return;
-    }
-    sound_trigger_module_descriptor descriptor;
-    rc = halInterface->getProperties(&descriptor.properties);
-    if (rc != 0) {
-        ALOGE("could not read implementation properties");
-        return;
-    }
-    descriptor.handle =
-            (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
-    ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
-                                                 descriptor.handle);
-
-    sp<Module> module = new Module(this, halInterface, descriptor);
-    mModules.add(descriptor.handle, module);
-    mCallbackThread = new CallbackThread(this);
-}
-
-SoundTriggerHwService::~SoundTriggerHwService()
-{
-    if (mCallbackThread != 0) {
-        mCallbackThread->exit();
-    }
-}
-
-status_t SoundTriggerHwService::listModules(const String16& opPackageName,
-                             struct sound_trigger_module_descriptor *modules,
-                             uint32_t *numModules)
-{
-    ALOGV("listModules");
-    if (!captureHotwordAllowed(opPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-
-    AutoMutex lock(mServiceLock);
-    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
-        return BAD_VALUE;
-    }
-    size_t maxModules = *numModules;
-    *numModules = mModules.size();
-    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
-        modules[i] = mModules.valueAt(i)->descriptor();
-    }
-    return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::attach(const String16& opPackageName,
-                        const sound_trigger_module_handle_t handle,
-                        const sp<ISoundTriggerClient>& client,
-                        sp<ISoundTrigger>& moduleInterface)
-{
-    ALOGV("attach module %d", handle);
-    if (!captureHotwordAllowed(opPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-
-    AutoMutex lock(mServiceLock);
-    moduleInterface.clear();
-    if (client == 0) {
-        return BAD_VALUE;
-    }
-    ssize_t index = mModules.indexOfKey(handle);
-    if (index < 0) {
-        return BAD_VALUE;
-    }
-    sp<Module> module = mModules.valueAt(index);
-
-    sp<ModuleClient> moduleClient = module->addClient(client, opPackageName);
-    if (moduleClient == 0) {
-        return NO_INIT;
-    }
-
-    moduleClient->setCaptureState_l(mCaptureState);
-    moduleInterface = moduleClient;
-
-    return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::setCaptureState(bool active)
-{
-    ALOGV("setCaptureState %d", active);
-    AutoMutex lock(mServiceLock);
-    mCaptureState = active;
-    for (size_t i = 0; i < mModules.size(); i++) {
-        mModules.valueAt(i)->setCaptureState_l(active);
-    }
-    return NO_ERROR;
-}
-
-
-static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-
-static bool dumpTryLock(Mutex& mutex)
-{
-    status_t err = mutex.timedLock(kDumpLockTimeoutNs);
-    return err == NO_ERROR;
-}
-
-status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
-    String8 result;
-    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
-        write(fd, result.string(), result.size());
-    } else {
-        bool locked = dumpTryLock(mServiceLock);
-        // failed to lock - SoundTriggerHwService is probably deadlocked
-        if (!locked) {
-            result.append("SoundTriggerHwService may be deadlocked\n");
-            write(fd, result.string(), result.size());
-        }
-
-        if (locked) mServiceLock.unlock();
-    }
-    return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
-    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
-}
-
-
-// static
-void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
-                                                void *cookie)
-{
-    Module *module = (Module *)cookie;
-    if (module == NULL) {
-        return;
-    }
-    sp<SoundTriggerHwService> service = module->service().promote();
-    if (service == 0) {
-        return;
-    }
-
-    service->sendRecognitionEvent(event, module);
-}
-
-sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent(
-                                                    struct sound_trigger_recognition_event *event)
-{
-    AutoMutex lock(mMemoryDealerLock);
-    sp<IMemory> eventMemory;
-
-    //sanitize event
-    switch (event->type) {
-    case SOUND_MODEL_TYPE_KEYPHRASE:
-        ALOGW_IF(event->data_size != 0 && event->data_offset !=
-                    sizeof(struct sound_trigger_phrase_recognition_event),
-                    "prepareRecognitionEvent(): invalid data offset %u for keyphrase event type",
-                    event->data_offset);
-        event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
-        break;
-    case SOUND_MODEL_TYPE_GENERIC:
-        ALOGW_IF(event->data_size != 0 && event->data_offset !=
-                    sizeof(struct sound_trigger_generic_recognition_event),
-                    "prepareRecognitionEvent(): invalid data offset %u for generic event type",
-                    event->data_offset);
-        event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
-        break;
-    case SOUND_MODEL_TYPE_UNKNOWN:
-        ALOGW_IF(event->data_size != 0 && event->data_offset !=
-                    sizeof(struct sound_trigger_recognition_event),
-                    "prepareRecognitionEvent(): invalid data offset %u for unknown event type",
-                    event->data_offset);
-        event->data_offset = sizeof(struct sound_trigger_recognition_event);
-        break;
-    default:
-        return eventMemory;
-    }
-
-    size_t size = event->data_offset + event->data_size;
-    eventMemory = mMemoryDealer->allocate(size);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        eventMemory.clear();
-        return eventMemory;
-    }
-    memcpy(eventMemory->pointer(), event, size);
-
-    return eventMemory;
-}
-
-void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
-                                                 Module *module)
-{
-    if (module == NULL) {
-        return;
-    }
-    sp<IMemory> eventMemory = prepareRecognitionEvent(event);
-    if (eventMemory == 0) {
-        return;
-    }
-
-    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
-                                                        eventMemory);
-    callbackEvent->setModule(module);
-    sendCallbackEvent(callbackEvent);
-}
-
-// static
-void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
-                                               void *cookie)
-{
-    Module *module = (Module *)cookie;
-    if (module == NULL) {
-        return;
-    }
-    sp<SoundTriggerHwService> service = module->service().promote();
-    if (service == 0) {
-        return;
-    }
-
-    service->sendSoundModelEvent(event, module);
-}
-
-sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent(struct sound_trigger_model_event *event)
-{
-    AutoMutex lock(mMemoryDealerLock);
-    sp<IMemory> eventMemory;
-
-    size_t size = event->data_offset + event->data_size;
-    eventMemory = mMemoryDealer->allocate(size);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        eventMemory.clear();
-        return eventMemory;
-    }
-    memcpy(eventMemory->pointer(), event, size);
-
-    return eventMemory;
-}
-
-void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
-                                                Module *module)
-{
-    sp<IMemory> eventMemory = prepareSoundModelEvent(event);
-    if (eventMemory == 0) {
-        return;
-    }
-    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
-                                                        eventMemory);
-    callbackEvent->setModule(module);
-    sendCallbackEvent(callbackEvent);
-}
-
-
-sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent(sound_trigger_service_state_t state)
-{
-    AutoMutex lock(mMemoryDealerLock);
-    sp<IMemory> eventMemory;
-
-    size_t size = sizeof(sound_trigger_service_state_t);
-    eventMemory = mMemoryDealer->allocate(size);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        eventMemory.clear();
-        return eventMemory;
-    }
-    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
-    return eventMemory;
-}
-
-void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
-                                                  Module *module)
-{
-    sp<IMemory> eventMemory = prepareServiceStateEvent(state);
-    if (eventMemory == 0) {
-        return;
-    }
-    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
-                                                        eventMemory);
-    callbackEvent->setModule(module);
-    sendCallbackEvent(callbackEvent);
-}
-
-void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
-                                                  ModuleClient *moduleClient)
-{
-    sp<IMemory> eventMemory = prepareServiceStateEvent(state);
-    if (eventMemory == 0) {
-        return;
-    }
-    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
-                                                        eventMemory);
-    callbackEvent->setModuleClient(moduleClient);
-    sendCallbackEvent(callbackEvent);
-}
-
-void SoundTriggerHwService::sendCallbackEvent(const sp<CallbackEvent>& event)
-{
-    mCallbackThread->sendCallbackEvent(event);
-}
-
-void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
-{
-    ALOGV("onCallbackEvent");
-    sp<Module> module;
-    sp<ModuleClient> moduleClient;
-    {
-        AutoMutex lock(mServiceLock);
-        //CallbackEvent is either for Module or ModuleClient
-        module = event->mModule.promote();
-        if (module == 0) {
-            moduleClient = event->mModuleClient.promote();
-            if (moduleClient == 0) {
-                return;
-            }
-        } else {
-            // Sanity check on this being a Module we know about.
-            bool foundModule = false;
-            for (size_t i = 0; i < mModules.size(); i++) {
-                if (mModules.valueAt(i).get() == module.get()) {
-                    foundModule = true;
-                    break;
-                }
-            }
-            if (!foundModule) {
-                ALOGE("onCallbackEvent for unknown module");
-                return;
-            }
-        }
-    }
-    if (module != 0) {
-        ALOGV("onCallbackEvent for module");
-        module->onCallbackEvent(event);
-    } else if (moduleClient != 0) {
-        ALOGV("onCallbackEvent for moduleClient");
-        moduleClient->onCallbackEvent(event);
-    }
-    {
-        AutoMutex lock(mServiceLock);
-        // clear now to execute with mServiceLock locked
-        event->mMemory.clear();
-    }
-}
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::CallbackThread"
-
-SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
-    : mService(service)
-{
-}
-
-SoundTriggerHwService::CallbackThread::~CallbackThread()
-{
-    while (!mEventQueue.isEmpty()) {
-        mEventQueue[0]->mMemory.clear();
-        mEventQueue.removeAt(0);
-    }
-}
-
-void SoundTriggerHwService::CallbackThread::onFirstRef()
-{
-    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-bool SoundTriggerHwService::CallbackThread::threadLoop()
-{
-    while (!exitPending()) {
-        sp<CallbackEvent> event;
-        sp<SoundTriggerHwService> service;
-        {
-            Mutex::Autolock _l(mCallbackLock);
-            while (mEventQueue.isEmpty() && !exitPending()) {
-                ALOGV("CallbackThread::threadLoop() sleep");
-                mCallbackCond.wait(mCallbackLock);
-                ALOGV("CallbackThread::threadLoop() wake up");
-            }
-            if (exitPending()) {
-                break;
-            }
-            event = mEventQueue[0];
-            mEventQueue.removeAt(0);
-            service = mService.promote();
-        }
-        if (service != 0) {
-            service->onCallbackEvent(event);
-        }
-    }
-    return false;
-}
-
-void SoundTriggerHwService::CallbackThread::exit()
-{
-    Mutex::Autolock _l(mCallbackLock);
-    requestExit();
-    mCallbackCond.broadcast();
-}
-
-void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
-                        const sp<SoundTriggerHwService::CallbackEvent>& event)
-{
-    AutoMutex lock(mCallbackLock);
-    mEventQueue.add(event);
-    mCallbackCond.signal();
-}
-
-SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
-    : mType(type), mMemory(memory)
-{
-}
-
-SoundTriggerHwService::CallbackEvent::~CallbackEvent()
-{
-}
-
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::Module"
-
-SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
-                                      const sp<SoundTriggerHalInterface>& halInterface,
-                                      sound_trigger_module_descriptor descriptor)
- : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
-   mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
-{
-}
-
-SoundTriggerHwService::Module::~Module() {
-    mModuleClients.clear();
-}
-
-sp<SoundTriggerHwService::ModuleClient>
-SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client,
-                                         const String16& opPackageName)
-{
-    AutoMutex lock(mLock);
-    sp<ModuleClient> moduleClient;
-
-    for (size_t i = 0; i < mModuleClients.size(); i++) {
-        if (mModuleClients[i]->client() == client) {
-            // Client already present, reuse client
-            return moduleClient;
-        }
-    }
-    moduleClient = new ModuleClient(this, client, opPackageName);
-
-    ALOGV("addClient() client %p", moduleClient.get());
-    mModuleClients.add(moduleClient);
-
-    return moduleClient;
-}
-
-void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
-{
-    ALOGV("Module::detach()");
-    Vector<audio_session_t> releasedSessions;
-
-    {
-        AutoMutex lock(mLock);
-        ssize_t index = -1;
-
-        for (size_t i = 0; i < mModuleClients.size(); i++) {
-            if (mModuleClients[i] == moduleClient) {
-                index = i;
-                break;
-            }
-        }
-        if (index == -1) {
-            return;
-        }
-
-        ALOGV("remove client %p", moduleClient.get());
-        mModuleClients.removeAt(index);
-
-        // Iterate in reverse order as models are removed from list inside the loop.
-        for (size_t i = mModels.size(); i > 0; i--) {
-            sp<Model> model = mModels.valueAt(i - 1);
-            if (moduleClient == model->mModuleClient) {
-                mModels.removeItemsAt(i - 1);
-                ALOGV("detach() unloading model %d", model->mHandle);
-                if (mHalInterface != 0) {
-                    if (model->mState == Model::STATE_ACTIVE) {
-                        mHalInterface->stopRecognition(model->mHandle);
-                    }
-                    mHalInterface->unloadSoundModel(model->mHandle);
-                }
-                releasedSessions.add(model->mCaptureSession);
-            }
-        }
-    }
-
-    for (size_t i = 0; i < releasedSessions.size(); i++) {
-        // do not call AudioSystem methods with mLock held
-        AudioSystem::releaseSoundTriggerSession(releasedSessions[i]);
-    }
-}
-
-status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
-                                                       sp<ModuleClient> moduleClient,
-                                                       sound_model_handle_t *handle)
-{
-    ALOGV("loadSoundModel() handle");
-    if (mHalInterface == 0) {
-        return NO_INIT;
-    }
-
-    auto immutableMemory = CopyToArray(modelMemory);
-    if (immutableMemory.first == nullptr) {
-        return NO_MEMORY;
-    }
-
-    struct sound_trigger_sound_model* sound_model =
-        (struct sound_trigger_sound_model*) immutableMemory.first.get();
-
-    size_t structSize;
-    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        structSize = sizeof(struct sound_trigger_phrase_sound_model);
-    } else {
-        structSize = sizeof(struct sound_trigger_sound_model);
-    }
-
-    if (sound_model->data_offset < structSize ||
-        sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
-        immutableMemory.second < sound_model->data_offset ||
-            sound_model->data_size >
-            (immutableMemory.second - sound_model->data_offset)) {
-        android_errorWriteLog(0x534e4554, "30148546");
-        ALOGE("loadSoundModel() data_size is too big");
-        return BAD_VALUE;
-    }
-
-    audio_session_t session;
-    audio_io_handle_t ioHandle;
-    audio_devices_t device;
-    // do not call AudioSystem methods with mLock held
-    status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
-    if (status != NO_ERROR) {
-        return status;
-    }
-
-    {
-        AutoMutex lock(mLock);
-
-        if (mModels.size() >= mDescriptor.properties.max_sound_models) {
-            ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
-                  mDescriptor.properties.max_sound_models);
-            status = INVALID_OPERATION;
-            goto exit;
-        }
-
-        status = mHalInterface->loadSoundModel(sound_model,
-                                                      SoundTriggerHwService::soundModelCallback,
-                                                      this, handle);
-        if (status != NO_ERROR) {
-            goto exit;
-        }
-
-        sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
-                                    moduleClient);
-        mModels.replaceValueFor(*handle, model);
-    }
-exit:
-    if (status != NO_ERROR) {
-        // do not call AudioSystem methods with mLock held
-        AudioSystem::releaseSoundTriggerSession(session);
-    }
-    return status;
-}
-
-status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
-{
-    ALOGV("unloadSoundModel() model handle %d", handle);
-    status_t status;
-    audio_session_t session;
-
-    {
-        AutoMutex lock(mLock);
-        if (mHalInterface == 0) {
-            return NO_INIT;
-        }
-        ssize_t index = mModels.indexOfKey(handle);
-        if (index < 0) {
-            return BAD_VALUE;
-        }
-        sp<Model> model = mModels.valueAt(index);
-        mModels.removeItem(handle);
-        if (model->mState == Model::STATE_ACTIVE) {
-            mHalInterface->stopRecognition(model->mHandle);
-            model->mState = Model::STATE_IDLE;
-        }
-        status = mHalInterface->unloadSoundModel(handle);
-        session = model->mCaptureSession;
-    }
-    // do not call AudioSystem methods with mLock held
-    AudioSystem::releaseSoundTriggerSession(session);
-    return status;
-}
-
-status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
-                                 const sp<IMemory>& dataMemory)
-{
-    ALOGV("startRecognition() model handle %d", handle);
-    if (mHalInterface == 0) {
-        return NO_INIT;
-    }
-
-    auto immutableMemory = CopyToArray(dataMemory);
-    if (immutableMemory.first == nullptr) {
-        return NO_MEMORY;
-    }
-
-    struct sound_trigger_recognition_config* config =
-        (struct sound_trigger_recognition_config*) immutableMemory.first.get();
-
-    if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
-        config->data_size > (UINT_MAX - config->data_offset) ||
-        immutableMemory.second < config->data_offset ||
-            config->data_size >
-            (immutableMemory.second - config->data_offset)) {
-        ALOGE("startRecognition() data_size is too big");
-        return BAD_VALUE;
-    }
-
-    AutoMutex lock(mLock);
-    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
-        return INVALID_OPERATION;
-    }
-    sp<Model> model = getModel(handle);
-    if (model == 0) {
-        return BAD_VALUE;
-    }
-
-    if (model->mState == Model::STATE_ACTIVE) {
-        return INVALID_OPERATION;
-    }
-
-
-    //TODO: get capture handle and device from audio policy service
-    config->capture_handle = model->mCaptureIOHandle;
-    config->capture_device = model->mCaptureDevice;
-    status_t status = mHalInterface->startRecognition(handle, config,
-                                        SoundTriggerHwService::recognitionCallback,
-                                        this);
-
-    if (status == NO_ERROR) {
-        model->mState = Model::STATE_ACTIVE;
-        model->mConfig = *config;
-    }
-
-    return status;
-}
-
-status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
-{
-    ALOGV("stopRecognition() model handle %d", handle);
-    if (mHalInterface == 0) {
-        return NO_INIT;
-    }
-    AutoMutex lock(mLock);
-    sp<Model> model = getModel(handle);
-    if (model == 0) {
-        return BAD_VALUE;
-    }
-
-    if (model->mState != Model::STATE_ACTIVE) {
-        return INVALID_OPERATION;
-    }
-    mHalInterface->stopRecognition(handle);
-    model->mState = Model::STATE_IDLE;
-    return NO_ERROR;
-}
-
-status_t SoundTriggerHwService::Module::getModelState(sound_model_handle_t handle)
-{
-    ALOGV("getModelState() model handle %d", handle);
-    if (mHalInterface == 0) {
-        return NO_INIT;
-    }
-    AutoMutex lock(mLock);
-    sp<Model> model = getModel(handle);
-    if (model == 0) {
-        return BAD_VALUE;
-    }
-
-    if (model->mState != Model::STATE_ACTIVE) {
-        return INVALID_OPERATION;
-    }
-
-    return mHalInterface->getModelState(handle);
-}
-
-void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
-{
-    ALOGV("onCallbackEvent type %d", event->mType);
-
-    sp<IMemory> eventMemory = event->mMemory;
-
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-    if (mModuleClients.isEmpty()) {
-        ALOGI("%s no clients", __func__);
-        return;
-    }
-
-    Vector< sp<ModuleClient> > clients;
-
-    switch (event->mType) {
-    case CallbackEvent::TYPE_RECOGNITION: {
-        struct sound_trigger_recognition_event *recognitionEvent =
-                (struct sound_trigger_recognition_event *)eventMemory->pointer();
-        {
-            AutoMutex lock(mLock);
-            sp<Model> model = getModel(recognitionEvent->model);
-            if (model == 0) {
-                ALOGW("%s model == 0", __func__);
-                return;
-            }
-            if (model->mState != Model::STATE_ACTIVE) {
-                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
-                return;
-            }
-
-            recognitionEvent->capture_session = model->mCaptureSession;
-            model->mState = Model::STATE_IDLE;
-            clients.add(model->mModuleClient);
-        }
-    } break;
-    case CallbackEvent::TYPE_SOUNDMODEL: {
-        struct sound_trigger_model_event *soundmodelEvent =
-                (struct sound_trigger_model_event *)eventMemory->pointer();
-        {
-            AutoMutex lock(mLock);
-            sp<Model> model = getModel(soundmodelEvent->model);
-            if (model == 0) {
-                ALOGW("%s model == 0", __func__);
-                return;
-            }
-            clients.add(model->mModuleClient);
-        }
-    } break;
-    case CallbackEvent::TYPE_SERVICE_STATE: {
-        {
-            AutoMutex lock(mLock);
-            for (size_t i = 0; i < mModuleClients.size(); i++) {
-                if (mModuleClients[i] != 0) {
-                    clients.add(mModuleClients[i]);
-                }
-            }
-        }
-    } break;
-    default:
-        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
-    }
-
-    for (size_t i = 0; i < clients.size(); i++) {
-        clients[i]->onCallbackEvent(event);
-    }
-}
-
-sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
-        sound_model_handle_t handle)
-{
-    sp<Model> model;
-    ssize_t index = mModels.indexOfKey(handle);
-    if (index >= 0) {
-        model = mModels.valueAt(index);
-    }
-    return model;
-}
-
-// Called with mServiceLock held
-void SoundTriggerHwService::Module::setCaptureState_l(bool active)
-{
-    ALOGV("Module::setCaptureState_l %d", active);
-    sp<SoundTriggerHwService> service;
-    sound_trigger_service_state_t state;
-
-    Vector< sp<IMemory> > events;
-    {
-        AutoMutex lock(mLock);
-        state = (active && !mDescriptor.properties.concurrent_capture) ?
-                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
-
-        if (state == mServiceState) {
-            return;
-        }
-
-        mServiceState = state;
-
-        service = mService.promote();
-        if (service == 0) {
-            return;
-        }
-
-        if (state == SOUND_TRIGGER_STATE_ENABLED) {
-            goto exit;
-        }
-
-        const bool supports_stop_all =
-                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() != -ENOSYS);
-
-        for (size_t i = 0; i < mModels.size(); i++) {
-            sp<Model> model = mModels.valueAt(i);
-            if (model->mState == Model::STATE_ACTIVE) {
-                if (mHalInterface != 0 && !supports_stop_all) {
-                    mHalInterface->stopRecognition(model->mHandle);
-                }
-                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
-                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
-                    struct sound_trigger_phrase_recognition_event event;
-                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
-                    event.num_phrases = model->mConfig.num_phrases;
-                    for (size_t i = 0; i < event.num_phrases; i++) {
-                        event.phrase_extras[i] = model->mConfig.phrases[i];
-                    }
-                    event.common.status = RECOGNITION_STATUS_ABORT;
-                    event.common.type = model->mType;
-                    event.common.model = model->mHandle;
-                    event.common.data_size = 0;
-                    sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
-                    if (eventMemory != 0) {
-                        events.add(eventMemory);
-                    }
-                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
-                    struct sound_trigger_generic_recognition_event event;
-                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
-                    event.common.status = RECOGNITION_STATUS_ABORT;
-                    event.common.type = model->mType;
-                    event.common.model = model->mHandle;
-                    event.common.data_size = 0;
-                    sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
-                    if (eventMemory != 0) {
-                        events.add(eventMemory);
-                    }
-                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
-                    struct sound_trigger_phrase_recognition_event event;
-                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
-                    event.common.status = RECOGNITION_STATUS_ABORT;
-                    event.common.type = model->mType;
-                    event.common.model = model->mHandle;
-                    event.common.data_size = 0;
-                    sp<IMemory> eventMemory = service->prepareRecognitionEvent(&event.common);
-                    if (eventMemory != 0) {
-                        events.add(eventMemory);
-                    }
-                } else {
-                    goto exit;
-                }
-            }
-        }
-    }
-
-    for (size_t i = 0; i < events.size(); i++) {
-        sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
-                                                            events[i]);
-        callbackEvent->setModule(this);
-        service->sendCallbackEvent(callbackEvent);
-    }
-
-exit:
-    service->sendServiceStateEvent(state, this);
-}
-
-
-SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
-                                    audio_io_handle_t ioHandle, audio_devices_t device,
-                                    sound_trigger_sound_model_type_t type,
-                                    sp<ModuleClient>& moduleClient) :
-    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
-    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
-    mModuleClient(moduleClient)
-{
-}
-
-#undef LOG_TAG
-#define LOG_TAG "SoundTriggerHwService::ModuleClient"
-
-SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
-                                                  const sp<ISoundTriggerClient>& client,
-                                                  const String16& opPackageName)
- : mModule(module), mClient(client), mOpPackageName(opPackageName)
-{
-}
-
-void SoundTriggerHwService::ModuleClient::onFirstRef()
-{
-    sp<IBinder> binder = IInterface::asBinder(mClient);
-    if (binder != 0) {
-        binder->linkToDeath(this);
-    }
-}
-
-SoundTriggerHwService::ModuleClient::~ModuleClient()
-{
-}
-
-status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
-                                                   const Vector<String16>& args __unused) {
-    String8 result;
-    return NO_ERROR;
-}
-
-void SoundTriggerHwService::ModuleClient::detach() {
-    ALOGV("detach()");
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return;
-    }
-
-    {
-        AutoMutex lock(mLock);
-        if (mClient != 0) {
-            IInterface::asBinder(mClient)->unlinkToDeath(this);
-            mClient.clear();
-        }
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return;
-    }
-    module->detach(this);
-}
-
-status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
-                                sound_model_handle_t *handle)
-{
-    ALOGV("loadSoundModel() handle");
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-    if (checkIMemory(modelMemory) != NO_ERROR) {
-        return BAD_VALUE;
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return NO_INIT;
-    }
-    return module->loadSoundModel(modelMemory, this, handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
-{
-    ALOGV("unloadSoundModel() model handle %d", handle);
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return NO_INIT;
-    }
-    return module->unloadSoundModel(handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
-                                 const sp<IMemory>& dataMemory)
-{
-    ALOGV("startRecognition() model handle %d", handle);
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-    if (checkIMemory(dataMemory) != NO_ERROR) {
-        return BAD_VALUE;
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return NO_INIT;
-    }
-    return module->startRecognition(handle, dataMemory);
-}
-
-status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
-{
-    ALOGV("stopRecognition() model handle %d", handle);
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return NO_INIT;
-    }
-    return module->stopRecognition(handle);
-}
-
-status_t SoundTriggerHwService::ModuleClient::getModelState(sound_model_handle_t handle)
-{
-    ALOGV("getModelState() model handle %d", handle);
-    if (!captureHotwordAllowed(mOpPackageName,
-                               IPCThreadState::self()->getCallingPid(),
-                               IPCThreadState::self()->getCallingUid())) {
-        return PERMISSION_DENIED;
-    }
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return NO_INIT;
-    }
-    return module->getModelState(handle);
-}
-
-void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
-{
-    ALOGV("ModuleClient::setCaptureState_l %d", active);
-    sp<SoundTriggerHwService> service;
-    sound_trigger_service_state_t state;
-
-    sp<Module> module = mModule.promote();
-    if (module == 0) {
-        return;
-    }
-    {
-        AutoMutex lock(mLock);
-        state = (active && !module->isConcurrentCaptureAllowed()) ?
-                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
-
-        service = module->service().promote();
-        if (service == 0) {
-            return;
-        }
-    }
-    service->sendServiceStateEvent(state, this);
-}
-
-void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
-{
-    ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
-
-    sp<IMemory> eventMemory = event->mMemory;
-
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    sp<ISoundTriggerClient> client;
-    {
-        AutoMutex lock(mLock);
-        client = mClient;
-    }
-
-    if (client != 0) {
-        switch (event->mType) {
-        case CallbackEvent::TYPE_RECOGNITION: {
-            client->onRecognitionEvent(eventMemory);
-        } break;
-        case CallbackEvent::TYPE_SOUNDMODEL: {
-            client->onSoundModelEvent(eventMemory);
-        } break;
-        case CallbackEvent::TYPE_SERVICE_STATE: {
-            client->onServiceStateChange(eventMemory);
-        } break;
-        default:
-            LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
-        }
-    }
-}
-
-void SoundTriggerHwService::ModuleClient::binderDied(
-    const wp<IBinder> &who __unused) {
-    ALOGW("client binder died for client %p", this);
-    detach();
-}
-
-}; // namespace android
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
deleted file mode 100644
index 43ad611..0000000
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2008 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 ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
-#define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
-
-#include <utils/Vector.h>
-//#include <binder/AppOpsManager.h>
-#include <binder/MemoryDealer.h>
-#include <binder/BinderService.h>
-#include <binder/IAppOpsCallback.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-#include "SoundTriggerHalInterface.h"
-
-namespace android {
-
-class MemoryHeapBase;
-
-class SoundTriggerHwService :
-    public BinderService<SoundTriggerHwService>,
-    public BnSoundTriggerHwService
-{
-    friend class BinderService<SoundTriggerHwService>;
-public:
-    class Module;
-    class ModuleClient;
-
-    static char const* getServiceName() { return "media.sound_trigger_hw"; }
-
-                        SoundTriggerHwService();
-    virtual             ~SoundTriggerHwService();
-
-    // ISoundTriggerHwService
-    virtual status_t listModules(const String16& opPackageName,
-                                 struct sound_trigger_module_descriptor *modules,
-                                 uint32_t *numModules);
-
-    virtual status_t attach(const String16& opPackageName,
-                            const sound_trigger_module_handle_t handle,
-                            const sp<ISoundTriggerClient>& client,
-                            sp<ISoundTrigger>& module);
-
-    virtual status_t setCaptureState(bool active);
-
-    virtual status_t    onTransact(uint32_t code, const Parcel& data,
-                                   Parcel* reply, uint32_t flags);
-
-    virtual status_t    dump(int fd, const Vector<String16>& args);
-
-    class Model : public RefBase {
-     public:
-
-        enum {
-            STATE_IDLE,
-            STATE_ACTIVE
-        };
-
-        Model(sound_model_handle_t handle, audio_session_t session, audio_io_handle_t ioHandle,
-              audio_devices_t device, sound_trigger_sound_model_type_t type,
-              sp<ModuleClient>& moduleClient);
-        ~Model() {}
-
-        sound_model_handle_t    mHandle;
-        int                     mState;
-        audio_session_t         mCaptureSession;
-        audio_io_handle_t       mCaptureIOHandle;
-        audio_devices_t         mCaptureDevice;
-        sound_trigger_sound_model_type_t mType;
-        struct sound_trigger_recognition_config mConfig;
-        sp<ModuleClient>        mModuleClient;
-    };
-
-    class CallbackEvent : public RefBase {
-    public:
-        typedef enum {
-            TYPE_RECOGNITION,
-            TYPE_SOUNDMODEL,
-            TYPE_SERVICE_STATE,
-        } event_type;
-        CallbackEvent(event_type type, sp<IMemory> memory);
-
-        virtual             ~CallbackEvent();
-
-        void setModule(wp<Module> module) { mModule = module; }
-        void setModuleClient(wp<ModuleClient> moduleClient) { mModuleClient = moduleClient; }
-
-        event_type mType;
-        sp<IMemory> mMemory;
-        wp<Module> mModule;
-        wp<ModuleClient> mModuleClient;
-    };
-
-    class Module : public RefBase {
-    public:
-
-       Module(const sp<SoundTriggerHwService>& service,
-              const sp<SoundTriggerHalInterface>& halInterface,
-              sound_trigger_module_descriptor descriptor);
-
-       virtual ~Module();
-
-       virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
-                                       sp<ModuleClient> moduleClient,
-                                       sound_model_handle_t *handle);
-
-       virtual status_t unloadSoundModel(sound_model_handle_t handle);
-
-       virtual status_t startRecognition(sound_model_handle_t handle,
-                                         const sp<IMemory>& dataMemory);
-       virtual status_t stopRecognition(sound_model_handle_t handle);
-       virtual status_t getModelState(sound_model_handle_t handle);
-
-       sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; }
-       struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
-       wp<SoundTriggerHwService> service() const { return mService; }
-       bool isConcurrentCaptureAllowed() const { return mDescriptor.properties.concurrent_capture; }
-
-       sp<Model> getModel(sound_model_handle_t handle);
-
-       void setCaptureState_l(bool active);
-
-       sp<ModuleClient> addClient(const sp<ISoundTriggerClient>& client,
-                                  const String16& opPackageName);
-
-       void detach(const sp<ModuleClient>& moduleClient);
-
-       void onCallbackEvent(const sp<CallbackEvent>& event);
-
-    private:
-
-        Mutex                                  mLock;
-        wp<SoundTriggerHwService>              mService;
-        sp<SoundTriggerHalInterface>           mHalInterface;
-        struct sound_trigger_module_descriptor mDescriptor;
-        Vector< sp<ModuleClient> >             mModuleClients;
-        DefaultKeyedVector< sound_model_handle_t, sp<Model> >     mModels;
-        sound_trigger_service_state_t          mServiceState;
-    }; // class Module
-
-    class ModuleClient : public virtual RefBase,
-                         public BnSoundTrigger,
-                         public IBinder::DeathRecipient {
-    public:
-
-       ModuleClient(const sp<Module>& module,
-              const sp<ISoundTriggerClient>& client,
-              const String16& opPackageName);
-
-       virtual ~ModuleClient();
-
-       virtual void detach();
-
-       virtual status_t loadSoundModel(const sp<IMemory>& modelMemory,
-                                       sound_model_handle_t *handle);
-
-       virtual status_t unloadSoundModel(sound_model_handle_t handle);
-
-       virtual status_t startRecognition(sound_model_handle_t handle,
-                                         const sp<IMemory>& dataMemory);
-       virtual status_t stopRecognition(sound_model_handle_t handle);
-       virtual status_t getModelState(sound_model_handle_t handle);
-
-       virtual status_t dump(int fd, const Vector<String16>& args);
-
-       virtual void onFirstRef();
-
-       // IBinder::DeathRecipient implementation
-       virtual void        binderDied(const wp<IBinder> &who);
-
-       void onCallbackEvent(const sp<CallbackEvent>& event);
-
-       void setCaptureState_l(bool active);
-
-       sp<ISoundTriggerClient> client() const { return mClient; }
-
-    private:
-
-        mutable Mutex               mLock;
-        wp<Module>                  mModule;
-        sp<ISoundTriggerClient>     mClient;
-        const String16              mOpPackageName;
-    }; // class ModuleClient
-
-    class CallbackThread : public Thread {
-    public:
-
-        explicit CallbackThread(const wp<SoundTriggerHwService>& service);
-
-        virtual             ~CallbackThread();
-
-        // Thread virtuals
-        virtual bool        threadLoop();
-
-        // RefBase
-        virtual void        onFirstRef();
-
-                void        exit();
-                void        sendCallbackEvent(const sp<CallbackEvent>& event);
-
-    private:
-        wp<SoundTriggerHwService>   mService;
-        Condition                   mCallbackCond;
-        Mutex                       mCallbackLock;
-        Vector< sp<CallbackEvent> > mEventQueue;
-    };
-
-    static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie);
-           sp<IMemory> prepareRecognitionEvent(struct sound_trigger_recognition_event *event);
-           void sendRecognitionEvent(struct sound_trigger_recognition_event *event, Module *module);
-
-    static void soundModelCallback(struct sound_trigger_model_event *event, void *cookie);
-           sp<IMemory> prepareSoundModelEvent(struct sound_trigger_model_event *event);
-           void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
-
-           sp<IMemory> prepareServiceStateEvent(sound_trigger_service_state_t state);
-           void sendServiceStateEvent(sound_trigger_service_state_t state, Module *module);
-           void sendServiceStateEvent(sound_trigger_service_state_t state,
-                                      ModuleClient *moduleClient);
-
-           void sendCallbackEvent(const sp<CallbackEvent>& event);
-           void onCallbackEvent(const sp<CallbackEvent>& event);
-
-private:
-
-    virtual void onFirstRef();
-
-    Mutex               mServiceLock;
-    volatile int32_t    mNextUniqueId;
-    DefaultKeyedVector< sound_trigger_module_handle_t, sp<Module> >     mModules;
-    sp<CallbackThread>  mCallbackThread;
-    sp<MemoryDealer>    mMemoryDealer;
-    Mutex               mMemoryDealerLock;
-    bool                mCaptureState;
-};
-
-} // namespace android
-
-#endif // ANDROID_HARDWARE_SOUNDTRIGGER_HAL_SERVICE_H
diff --git a/soundtrigger/Android.bp b/soundtrigger/Android.bp
deleted file mode 100644
index 6178153..0000000
--- a/soundtrigger/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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.
-
-cc_library_shared {
-    name: "libsoundtrigger",
-
-    srcs: [
-        "SoundTrigger.cpp",
-        "ISoundTrigger.cpp",
-        "ISoundTriggerClient.cpp",
-        "ISoundTriggerHwService.cpp",
-    ],
-
-    shared_libs: [
-        "libcutils",
-        "libutils",
-        "liblog",
-        "libbinder",
-    ],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-}
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
deleted file mode 100644
index f5b4b59..0000000
--- a/soundtrigger/ISoundTrigger.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-**
-** Copyright 2014, 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_TAG "ISoundTrigger"
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <binder/IMemory.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <system/sound_trigger.h>
-
-namespace android {
-
-enum {
-    DETACH = IBinder::FIRST_CALL_TRANSACTION,
-    LOAD_SOUND_MODEL,
-    UNLOAD_SOUND_MODEL,
-    START_RECOGNITION,
-    STOP_RECOGNITION,
-    GET_MODEL_STATE,
-};
-
-class BpSoundTrigger: public BpInterface<ISoundTrigger>
-{
-public:
-    explicit BpSoundTrigger(const sp<IBinder>& impl)
-        : BpInterface<ISoundTrigger>(impl)
-    {
-    }
-
-    void detach()
-    {
-        ALOGV("detach");
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        remote()->transact(DETACH, data, &reply);
-    }
-
-    status_t loadSoundModel(const sp<IMemory>&  modelMemory,
-                                    sound_model_handle_t *handle)
-    {
-        if (modelMemory == 0 || handle == NULL) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(modelMemory));
-        status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = (status_t)reply.readInt32();
-        if (status == NO_ERROR) {
-            reply.read(handle, sizeof(sound_model_handle_t));
-        }
-        return status;
-    }
-
-    virtual status_t unloadSoundModel(sound_model_handle_t handle)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.write(&handle, sizeof(sound_model_handle_t));
-        status_t status = remote()->transact(UNLOAD_SOUND_MODEL, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t startRecognition(sound_model_handle_t handle,
-                                      const sp<IMemory>& dataMemory)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.write(&handle, sizeof(sound_model_handle_t));
-        if (dataMemory == 0) {
-            data.writeInt32(0);
-        } else {
-            data.writeInt32(dataMemory->size());
-        }
-        data.writeStrongBinder(IInterface::asBinder(dataMemory));
-        status_t status = remote()->transact(START_RECOGNITION, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t stopRecognition(sound_model_handle_t handle)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.write(&handle, sizeof(sound_model_handle_t));
-        status_t status = remote()->transact(STOP_RECOGNITION, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-    virtual status_t getModelState(sound_model_handle_t handle)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.write(&handle, sizeof(sound_model_handle_t));
-        status_t status = remote()->transact(GET_MODEL_STATE, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-        }
-        return status;
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(SoundTrigger, "android.hardware.ISoundTrigger");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTrigger::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case DETACH: {
-            ALOGV("DETACH");
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            detach();
-            return NO_ERROR;
-        } break;
-        case LOAD_SOUND_MODEL: {
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            sp<IMemory> modelMemory = interface_cast<IMemory>(
-                data.readStrongBinder());
-            sound_model_handle_t handle;
-            status_t status = loadSoundModel(modelMemory, &handle);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->write(&handle, sizeof(sound_model_handle_t));
-            }
-            return NO_ERROR;
-        }
-        case UNLOAD_SOUND_MODEL: {
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            sound_model_handle_t handle;
-            data.read(&handle, sizeof(sound_model_handle_t));
-            status_t status = unloadSoundModel(handle);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case START_RECOGNITION: {
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            sound_model_handle_t handle;
-            data.read(&handle, sizeof(sound_model_handle_t));
-            sp<IMemory> dataMemory;
-            if (data.readInt32() != 0) {
-                dataMemory = interface_cast<IMemory>(data.readStrongBinder());
-            }
-            status_t status = startRecognition(handle, dataMemory);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case STOP_RECOGNITION: {
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            sound_model_handle_t handle;
-            data.read(&handle, sizeof(sound_model_handle_t));
-            status_t status = stopRecognition(handle);
-            reply->writeInt32(status);
-            return NO_ERROR;
-        }
-        case GET_MODEL_STATE: {
-            CHECK_INTERFACE(ISoundTrigger, data, reply);
-            sound_model_handle_t handle;
-            status_t status = UNKNOWN_ERROR;
-            status_t ret = data.read(&handle, sizeof(sound_model_handle_t));
-            if (ret == NO_ERROR) {
-                status = getModelState(handle);
-            }
-            reply->writeInt32(status);
-            return ret;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp
deleted file mode 100644
index 1385631..0000000
--- a/soundtrigger/ISoundTriggerClient.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-**
-** Copyright 2014, 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 <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-
-namespace android {
-
-enum {
-    ON_RECOGNITION_EVENT = IBinder::FIRST_CALL_TRANSACTION,
-    ON_SOUNDMODEL_EVENT,
-    ON_SERVICE_STATE_CHANGE
-};
-
-class BpSoundTriggerClient: public BpInterface<ISoundTriggerClient>
-{
-
-public:
-    explicit BpSoundTriggerClient(const sp<IBinder>& impl)
-        : BpInterface<ISoundTriggerClient>(impl)
-    {
-    }
-
-    virtual void onRecognitionEvent(const sp<IMemory>& eventMemory)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(eventMemory));
-        remote()->transact(ON_RECOGNITION_EVENT,
-                           data,
-                           &reply);
-    }
-
-    virtual void onSoundModelEvent(const sp<IMemory>& eventMemory)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(eventMemory));
-        remote()->transact(ON_SOUNDMODEL_EVENT,
-                           data,
-                           &reply);
-    }
-    virtual void onServiceStateChange(const sp<IMemory>& eventMemory)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(eventMemory));
-        remote()->transact(ON_SERVICE_STATE_CHANGE,
-                           data,
-                           &reply);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(SoundTriggerClient,
-                         "android.hardware.ISoundTriggerClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTriggerClient::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case ON_RECOGNITION_EVENT: {
-            CHECK_INTERFACE(ISoundTriggerClient, data, reply);
-            sp<IMemory> eventMemory = interface_cast<IMemory>(
-                data.readStrongBinder());
-            onRecognitionEvent(eventMemory);
-            return NO_ERROR;
-        } break;
-        case ON_SOUNDMODEL_EVENT: {
-            CHECK_INTERFACE(ISoundTriggerClient, data, reply);
-            sp<IMemory> eventMemory = interface_cast<IMemory>(
-                data.readStrongBinder());
-            onSoundModelEvent(eventMemory);
-            return NO_ERROR;
-        } break;
-        case ON_SERVICE_STATE_CHANGE: {
-            CHECK_INTERFACE(ISoundTriggerClient, data, reply);
-            sp<IMemory> eventMemory = interface_cast<IMemory>(
-                data.readStrongBinder());
-            onServiceStateChange(eventMemory);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
deleted file mode 100644
index bd107b4..0000000
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-**
-** Copyright 2014, 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_TAG "BpSoundTriggerHwService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-
-namespace android {
-
-enum {
-    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
-    ATTACH,
-    SET_CAPTURE_STATE,
-};
-
-#define MAX_ITEMS_PER_LIST 1024
-
-class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
-{
-public:
-    explicit BpSoundTriggerHwService(const sp<IBinder>& impl)
-        : BpInterface<ISoundTriggerHwService>(impl)
-    {
-    }
-
-    virtual status_t listModules(const String16& opPackageName,
-                                 struct sound_trigger_module_descriptor *modules,
-                                 uint32_t *numModules)
-    {
-        if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
-            return BAD_VALUE;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
-        data.writeString16(opPackageName);
-        unsigned int numModulesReq = (modules == NULL) ? 0 : *numModules;
-        data.writeInt32(numModulesReq);
-        status_t status = remote()->transact(LIST_MODULES, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            *numModules = (unsigned int)reply.readInt32();
-        }
-        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
-        if (status == NO_ERROR) {
-            if (numModulesReq > *numModules) {
-                numModulesReq = *numModules;
-            }
-            if (numModulesReq > 0) {
-                reply.read(modules, numModulesReq * sizeof(struct sound_trigger_module_descriptor));
-            }
-        }
-        return status;
-    }
-
-    virtual status_t attach(const String16& opPackageName,
-                            const sound_trigger_module_handle_t handle,
-                            const sp<ISoundTriggerClient>& client,
-                            sp<ISoundTrigger>& module)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
-        data.writeString16(opPackageName);
-        data.write(&handle, sizeof(sound_trigger_module_handle_t));
-        data.writeStrongBinder(IInterface::asBinder(client));
-        status_t status = remote()->transact(ATTACH, data, &reply);
-        if (status != NO_ERROR) {
-            return status;
-        }
-        status = reply.readInt32();
-        if (reply.readInt32() != 0) {
-            module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
-        }
-        return status;
-    }
-
-    virtual status_t setCaptureState(bool active)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
-        data.writeInt32(active);
-        status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
-        if (status == NO_ERROR) {
-            status = reply.readInt32();
-        }
-        return status;
-    }
-
-};
-
-IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
-
-// ----------------------------------------------------------------------
-
-status_t BnSoundTriggerHwService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case LIST_MODULES: {
-            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
-            String16 opPackageName;
-            status_t status = data.readString16(&opPackageName);
-            if (status != NO_ERROR) {
-                return status;
-            }
-            unsigned int numModulesReq = data.readInt32();
-            if (numModulesReq > MAX_ITEMS_PER_LIST) {
-                numModulesReq = MAX_ITEMS_PER_LIST;
-            }
-            unsigned int numModules = numModulesReq;
-            struct sound_trigger_module_descriptor *modules =
-                    (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
-                                                   sizeof(struct sound_trigger_module_descriptor));
-            if (modules == NULL) {
-                reply->writeInt32(NO_MEMORY);
-                reply->writeInt32(0);
-                return NO_ERROR;
-            }
-            status = listModules(opPackageName, modules, &numModules);
-            reply->writeInt32(status);
-            reply->writeInt32(numModules);
-            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
-
-            if (status == NO_ERROR) {
-                if (numModulesReq > numModules) {
-                    numModulesReq = numModules;
-                }
-                reply->write(modules,
-                             numModulesReq * sizeof(struct sound_trigger_module_descriptor));
-            }
-            free(modules);
-            return NO_ERROR;
-        }
-
-        case ATTACH: {
-            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
-            String16 opPackageName;
-            status_t status = data.readString16(&opPackageName);
-            if (status != NO_ERROR) {
-                return status;
-            }
-            sound_trigger_module_handle_t handle;
-            data.read(&handle, sizeof(sound_trigger_module_handle_t));
-            sp<ISoundTriggerClient> client =
-                    interface_cast<ISoundTriggerClient>(data.readStrongBinder());
-            sp<ISoundTrigger> module;
-            status = attach(opPackageName, handle, client, module);
-            reply->writeInt32(status);
-            if (module != 0) {
-                reply->writeInt32(1);
-                reply->writeStrongBinder(IInterface::asBinder(module));
-            } else {
-                reply->writeInt32(0);
-            }
-            return NO_ERROR;
-        } break;
-
-        case SET_CAPTURE_STATE: {
-            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
-            reply->writeInt32(setCaptureState((bool)data.readInt32()));
-            return NO_ERROR;
-        } break;
-
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/soundtrigger/OWNERS b/soundtrigger/OWNERS
deleted file mode 100644
index e83f6b9..0000000
--- a/soundtrigger/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-elaurent@google.com
-thorntonc@google.com
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
deleted file mode 100644
index 9708ea7..0000000
--- a/soundtrigger/SoundTrigger.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
-**
-** Copyright (C) 2014, 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_TAG "SoundTrigger"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
-
-#include <soundtrigger/SoundTrigger.h>
-#include <soundtrigger/ISoundTrigger.h>
-#include <soundtrigger/ISoundTriggerHwService.h>
-#include <soundtrigger/ISoundTriggerClient.h>
-#include <soundtrigger/SoundTriggerCallback.h>
-
-namespace android {
-
-namespace {
-    sp<ISoundTriggerHwService> gSoundTriggerHwService;
-    const int                  kSoundTriggerHwServicePollDelay = 500000; // 0.5s
-    const char*                kSoundTriggerHwServiceName      = "media.sound_trigger_hw";
-    Mutex                      gLock;
-
-    class DeathNotifier : public IBinder::DeathRecipient
-    {
-    public:
-        DeathNotifier() {
-        }
-
-        virtual void binderDied(const wp<IBinder>& who __unused) {
-            ALOGV("binderDied");
-            Mutex::Autolock _l(gLock);
-            gSoundTriggerHwService.clear();
-            ALOGW("Sound trigger service died!");
-        }
-    };
-
-    sp<DeathNotifier>         gDeathNotifier;
-}; // namespace anonymous
-
-const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
-{
-    Mutex::Autolock _l(gLock);
-    if (gSoundTriggerHwService.get() == 0) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16(kSoundTriggerHwServiceName));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("SoundTriggerHwService not published, waiting...");
-            usleep(kSoundTriggerHwServicePollDelay);
-        } while(true);
-        if (gDeathNotifier == NULL) {
-            gDeathNotifier = new DeathNotifier();
-        }
-        binder->linkToDeath(gDeathNotifier);
-        gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
-    }
-    ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
-    return gSoundTriggerHwService;
-}
-
-// Static methods
-status_t SoundTrigger::listModules(const String16& opPackageName,
-                                   struct sound_trigger_module_descriptor *modules,
-                                   uint32_t *numModules)
-{
-    ALOGV("listModules()");
-    const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
-    if (service == 0) {
-        return NO_INIT;
-    }
-    return service->listModules(opPackageName, modules, numModules);
-}
-
-sp<SoundTrigger> SoundTrigger::attach(const String16& opPackageName,
-                                      const sound_trigger_module_handle_t module,
-                                      const sp<SoundTriggerCallback>& callback)
-{
-    ALOGV("attach()");
-    sp<SoundTrigger> soundTrigger;
-    const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
-    if (service == 0) {
-        return soundTrigger;
-    }
-    soundTrigger = new SoundTrigger(module, callback);
-    status_t status = service->attach(opPackageName, module, soundTrigger,
-                                      soundTrigger->mISoundTrigger);
-
-    if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
-        IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
-    } else {
-        ALOGW("Error %d connecting to sound trigger service", status);
-        soundTrigger.clear();
-    }
-    return soundTrigger;
-}
-
-
-status_t SoundTrigger::setCaptureState(bool active)
-{
-    ALOGV("setCaptureState(%d)", active);
-    const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
-    if (service == 0) {
-        return NO_INIT;
-    }
-    return service->setCaptureState(active);
-}
-
-// SoundTrigger
-SoundTrigger::SoundTrigger(sound_trigger_module_handle_t /*module*/,
-                                 const sp<SoundTriggerCallback>& callback)
-    : mCallback(callback)
-{
-}
-
-SoundTrigger::~SoundTrigger()
-{
-    if (mISoundTrigger != 0) {
-        mISoundTrigger->detach();
-    }
-}
-
-
-void SoundTrigger::detach() {
-    ALOGV("detach()");
-    Mutex::Autolock _l(mLock);
-    mCallback.clear();
-    if (mISoundTrigger != 0) {
-        mISoundTrigger->detach();
-        IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
-        mISoundTrigger = 0;
-    }
-}
-
-status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
-                                sound_model_handle_t *handle)
-{
-    Mutex::Autolock _l(mLock);
-    if (mISoundTrigger == 0) {
-        return NO_INIT;
-    }
-
-    return mISoundTrigger->loadSoundModel(modelMemory, handle);
-}
-
-status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
-{
-    Mutex::Autolock _l(mLock);
-    if (mISoundTrigger == 0) {
-        return NO_INIT;
-    }
-    return mISoundTrigger->unloadSoundModel(handle);
-}
-
-status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
-                                        const sp<IMemory>& dataMemory)
-{
-    Mutex::Autolock _l(mLock);
-    if (mISoundTrigger == 0) {
-        return NO_INIT;
-    }
-    return mISoundTrigger->startRecognition(handle, dataMemory);
-}
-
-status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
-{
-    Mutex::Autolock _l(mLock);
-    if (mISoundTrigger == 0) {
-        return NO_INIT;
-    }
-    return mISoundTrigger->stopRecognition(handle);
-}
-
-status_t SoundTrigger::getModelState(sound_model_handle_t handle)
-{
-    Mutex::Autolock _l(mLock);
-    if (mISoundTrigger == 0) {
-        return NO_INIT;
-    }
-    return mISoundTrigger->getModelState(handle);
-}
-
-// BpSoundTriggerClient
-void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
-{
-    Mutex::Autolock _l(mLock);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    if (mCallback != 0) {
-        mCallback->onRecognitionEvent(
-                (struct sound_trigger_recognition_event *)eventMemory->pointer());
-    }
-}
-
-void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
-{
-    Mutex::Autolock _l(mLock);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    if (mCallback != 0) {
-        mCallback->onSoundModelEvent(
-                (struct sound_trigger_model_event *)eventMemory->pointer());
-    }
-}
-
-void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
-{
-    Mutex::Autolock _l(mLock);
-    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
-        return;
-    }
-
-    if (mCallback != 0) {
-        mCallback->onServiceStateChange(
-                *((sound_trigger_service_state_t *)eventMemory->pointer()));
-    }
-}
-
-//IBinder::DeathRecipient
-void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
-    Mutex::Autolock _l(mLock);
-    ALOGW("SoundTrigger server binder Died ");
-    mISoundTrigger = 0;
-    if (mCallback != 0) {
-        mCallback->onServiceDied();
-    }
-}
-
-status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
-{
-    if (str == NULL || guid == NULL) {
-        return BAD_VALUE;
-    }
-
-    int tmp[10];
-
-    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
-            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
-        return BAD_VALUE;
-    }
-    guid->timeLow = (uint32_t)tmp[0];
-    guid->timeMid = (uint16_t)tmp[1];
-    guid->timeHiAndVersion = (uint16_t)tmp[2];
-    guid->clockSeq = (uint16_t)tmp[3];
-    guid->node[0] = (uint8_t)tmp[4];
-    guid->node[1] = (uint8_t)tmp[5];
-    guid->node[2] = (uint8_t)tmp[6];
-    guid->node[3] = (uint8_t)tmp[7];
-    guid->node[4] = (uint8_t)tmp[8];
-    guid->node[5] = (uint8_t)tmp[9];
-
-    return NO_ERROR;
-}
-
-status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
-{
-    if (guid == NULL || str == NULL) {
-        return BAD_VALUE;
-    }
-
-    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
-            guid->timeLow,
-            guid->timeMid,
-            guid->timeHiAndVersion,
-            guid->clockSeq,
-            guid->node[0],
-            guid->node[1],
-            guid->node[2],
-            guid->node[3],
-            guid->node[4],
-            guid->node[5]);
-
-    return NO_ERROR;
-}
-
-}; // namespace android
diff --git a/tools/OWNERS b/tools/OWNERS
deleted file mode 100644
index f9cb567..0000000
--- a/tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-gkasten@google.com
diff --git a/tools/mainline_hook.sh b/tools/mainline_hook.sh
new file mode 100755
index 0000000..58afb49
--- /dev/null
+++ b/tools/mainline_hook.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
+
+MAINLINE_FRAMEWORKS_AV_PATHS=(
+    media/extractors/
+    media/codec2/components/
+    media/libstagefright/codecs/amrnb
+    media/libstagefright/codecs/amrwb
+    media/libstagefright/codecs/amrwbenc
+    media/libstagefright/codecs/common
+    media/libstagefright/codecs/mp3dec
+    media/libstagefright/codecs/m4v_h263
+    media/libstagefright/flac/dec
+    media/libstagefright/mpeg2ts
+)
+
+MAINLINE_EXTERNAL_PROJECTS=(
+    external/aac
+    external/flac
+    external/libaac
+    external/libaom
+    external/libavc
+    external/libgav1
+    external/libgsm
+    external/libhevc
+    external/libmpeg2
+    external/libopus
+    external/libvpx
+    external/libxaac
+    external/sonivox
+    external/tremolo
+)
+
+DEV_BRANCH=qt-aml-media-dev
+RED=$(tput setaf 1)
+NORMAL=$(tput sgr0)
+WARNING_FULL="${RED}Please upload this change in ${DEV_BRANCH} unless it is restricted
+from mainline release until next dessert release. Low/moderate security bugs
+are restricted this way.${NORMAL}"
+WARNING_PARTIAL="${RED}It looks like your change has mainline and non-mainline changes;
+Consider separating them into two separate CLs -- one for mainline files,
+one for non-mainline files.${NORMAL}"
+PWD=`pwd`
+
+if git branch -vv | grep -q -P "^\*[^\[]+\[goog/qt-aml-media-dev"; then
+    # Change appears to be in mainline dev branch
+    exit 0
+fi
+
+for path in "${MAINLINE_EXTERNAL_PROJECTS[@]}"; do
+    if [[ $PWD =~ $path ]]; then
+        echo -e "${RED}The source of truth for '$path' is in ${DEV_BRANCH}.${NORMAL}"
+        echo -e ${WARNING_FULL}
+        exit 1
+    fi
+done
+
+if [[ ! $PWD =~ frameworks/av ]]; then
+    exit 0
+fi
+
+mainline_count=0
+total_count=0
+echo
+while read -r file ; do
+    (( total_count++ ))
+    for path in "${MAINLINE_FRAMEWORKS_AV_PATHS[@]}"; do
+        if [[ $file =~ ^$path ]]; then
+            echo -e "${RED}The source of truth for '$file' is in ${DEV_BRANCH}.${NORMAL}"
+            (( mainline_count++ ))
+            break
+        fi
+    done
+done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
+
+if (( mainline_count != 0 )); then
+    if (( mainline_count == total_count )); then
+        echo -e ${WARNING_FULL}
+    else
+        echo -e ${WARNING_PARTIAL}
+    fi
+    exit 1
+fi
+exit 0
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
new file mode 100755
index 0000000..3dc6163
--- /dev/null
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
new file mode 100755
index 0000000..8d35470
--- /dev/null
+++ b/tools/mainline_hook_project.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#set -x
+
+# called for repo projects that are part of the media mainline modules
+# this is for projects where the entire project is part of mainline.
+# we have a separate script for projects where only part of that project gets
+# pulled into mainline.
+#
+# if the project's PREUPLOAD.cfg points to this script, it is by definition a project
+# which is entirely within mainline.
+#
+# example PREUPLOAD.cfg using this script
+# [Hook Scripts]
+# mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_project.sh
+#
+
+
+# tunables
+DEV_BRANCH=rvc-dev
+
+###
+RED=$(tput setaf 1)
+NORMAL=$(tput sgr0)
+
+## check the active branch:
+## * b131183694 d198c6a [goog/master] Fix to handle missing checks on error returned
+##
+current=`git branch -vv | grep -P "^\*[^\[]+\[goog/"|sed -e 's/^.*\[//' | sed -e 's/:.*$//'| sed -e 's/^goog\///'`
+if [ "${current}" = "" ] ; then
+        current=unknown
+fi
+
+if [ "${current}" = "${DEV_BRANCH}" ] ; then
+    # Change appears to be in mainline dev branch
+    exit 0
+fi
+
+## warn the user that about not being on the typical/desired branch.
+
+cat - <<EOF
+
+You are uploading repo  ${RED}${REPO_PATH}${NORMAL} to branch ${RED}${current}${NORMAL}. 
+The source of truth for ${RED}${REPO_PATH}${NORMAL} is branch ${RED}${DEV_BRANCH}${NORMAL}. 
+
+Please upload this change to branch ${RED}${DEV_BRANCH}${NORMAL} unless one or more of
+the following apply:
+- this is a security bug prohibited from disclosure before the next dessert release.
+  (moderate security bugs fall into this category).
+- this is new functionality prohibitied from disclosure before the next dessert release.
+EOF
+
+
+##
+## TODO: prompt the user y/n to continue right now instead of re-invoking with no-verify
+## this has to get around how repo buffers stdout from this script such that the output
+## is not flushed before we try to read the input.
+## 
+
+cat - <<EOF
+If you are sure you want to proceed uploading to branch ${RED}${current}${NORMAL},
+re-run your repo upload command with the '--no-verify' option
+
+EOF
+exit 1
+
diff --git a/tools/resampler_tools/Android.mk b/tools/resampler_tools/Android.mk
deleted file mode 100644
index bba5199..0000000
--- a/tools/resampler_tools/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for resampler_tools
-#
-
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	fir.cpp
-
-LOCAL_MODULE := fir
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/resampler_tools/OWNERS b/tools/resampler_tools/OWNERS
deleted file mode 100644
index b4a6798..0000000
--- a/tools/resampler_tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-hunga@google.com
diff --git a/tools/resampler_tools/fir.cpp b/tools/resampler_tools/fir.cpp
deleted file mode 100644
index fe4d212..0000000
--- a/tools/resampler_tools/fir.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 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 <math.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-static inline double sinc(double x) {
-    if (fabs(x) == 0.0f) return 1.0f;
-    return sin(x) / x;
-}
-
-static inline double sqr(double x) {
-    return x*x;
-}
-
-static inline int64_t toint(double x, int64_t maxval) {
-    int64_t v;
-
-    v = static_cast<int64_t>(floor(x * maxval + 0.5));
-    if (v >= maxval) {
-        return maxval - 1; // error!
-    }
-    return v;
-}
-
-static double I0(double x) {
-    // from the Numerical Recipes in C p. 237
-    double ax,ans,y;
-    ax=fabs(x);
-    if (ax < 3.75) {
-        y=x/3.75;
-        y*=y;
-        ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
-                +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
-    } else {
-        y=3.75/ax;
-        ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1
-                +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2
-                        +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
-                                +y*0.392377e-2))))))));
-    }
-    return ans;
-}
-
-static double kaiser(int k, int N, double beta) {
-    if (k < 0 || k > N)
-        return 0;
-    return I0(beta * sqrt(1.0 - sqr((2.0*k)/N - 1.0))) / I0(beta);
-}
-
-static void usage(char* name) {
-    fprintf(stderr,
-            "usage: %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
-            " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] [-l lerp]\n"
-            "       %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
-            " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] -p M/N\n"
-            "    -h    this help message\n"
-            "    -d    debug, print comma-separated coefficient table\n"
-            "    -D    generate extra declarations\n"
-            "    -p    generate poly-phase filter coefficients, with sample increment M/N\n"
-            "    -s    sample rate (48000)\n"
-            "    -c    cut-off frequency (20478)\n"
-            "    -n    number of zero-crossings on one side (8)\n"
-            "    -l    number of lerping bits (4)\n"
-            "    -m    number of polyphases (related to -l, default 16)\n"
-            "    -f    output format, can be fixed, fixed16, or float (fixed)\n"
-            "    -b    kaiser window parameter beta (7.865 [-80dB])\n"
-            "    -v    attenuation in dBFS (0)\n",
-            name, name
-    );
-    exit(0);
-}
-
-int main(int argc, char** argv)
-{
-    // nc is the number of bits to store the coefficients
-    int nc = 32;
-    bool polyphase = false;
-    unsigned int polyM = 160;
-    unsigned int polyN = 147;
-    bool debug = false;
-    double Fs = 48000;
-    double Fc = 20478;
-    double atten = 1;
-    int format = 0;     // 0=fixed, 1=float
-    bool declarations = false;
-
-    // in order to keep the errors associated with the linear
-    // interpolation of the coefficients below the quantization error
-    // we must satisfy:
-    //   2^nz >= 2^(nc/2)
-    //
-    // for 16 bit coefficients that would be 256
-    //
-    // note that increasing nz only increases memory requirements,
-    // but doesn't increase the amount of computation to do.
-    //
-    //
-    // see:
-    // Smith, J.O. Digital Audio Resampling Home Page
-    // https://ccrma.stanford.edu/~jos/resample/, 2011-03-29
-    //
-
-    //         | 0.1102*(A - 8.7)                         A > 50
-    //  beta = | 0.5842*(A - 21)^0.4 + 0.07886*(A - 21)   21 <= A <= 50
-    //         | 0                                        A < 21
-    //   with A is the desired stop-band attenuation in dBFS
-    //
-    // for eg:
-    //
-    //    30 dB    2.210
-    //    40 dB    3.384
-    //    50 dB    4.538
-    //    60 dB    5.658
-    //    70 dB    6.764
-    //    80 dB    7.865
-    //    90 dB    8.960
-    //   100 dB   10.056
-    double beta = 7.865;
-
-    // 2*nzc = (A - 8) / (2.285 * dw)
-    //      with dw the transition width = 2*pi*dF/Fs
-    //
-    int nzc = 8;
-
-    /*
-     * Example:
-     * 44.1 KHz to 48 KHz resampling
-     * 100 dB rejection above 28 KHz
-     *   (the spectrum will fold around 24 KHz and we want 100 dB rejection
-     *    at the point where the folding reaches 20 KHz)
-     *  ...___|_____
-     *        |     \|
-     *        | ____/|\____
-     *        |/alias|     \
-     *  ------/------+------\---------> KHz
-     *       20     24     28
-     *
-     * Transition band 8 KHz, or dw = 1.0472
-     *
-     * beta = 10.056
-     * nzc  = 20
-     */
-
-    int M = 1 << 4; // number of phases for interpolation
-    int ch;
-    while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:D")) != -1) {
-        switch (ch) {
-            case 'd':
-                debug = true;
-                break;
-            case 'D':
-                declarations = true;
-                break;
-            case 'p':
-                if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) {
-                    usage(argv[0]);
-                }
-                polyphase = true;
-                break;
-            case 's':
-                Fs = atof(optarg);
-                break;
-            case 'c':
-                Fc = atof(optarg);
-                break;
-            case 'n':
-                nzc = atoi(optarg);
-                break;
-            case 'm':
-                M = atoi(optarg);
-                break;
-            case 'l':
-                M = 1 << atoi(optarg);
-                break;
-            case 'f':
-                if (!strcmp(optarg, "fixed")) {
-                    format = 0;
-                }
-                else if (!strcmp(optarg, "fixed16")) {
-                    format = 0;
-                    nc = 16;
-                }
-                else if (!strcmp(optarg, "float")) {
-                    format = 1;
-                }
-                else {
-                    usage(argv[0]);
-                }
-                break;
-            case 'b':
-                beta = atof(optarg);
-                break;
-            case 'v':
-                atten = pow(10, -fabs(atof(optarg))*0.05 );
-                break;
-            case 'h':
-            default:
-                usage(argv[0]);
-                break;
-        }
-    }
-
-    // cut off frequency ratio Fc/Fs
-    double Fcr = Fc / Fs;
-
-    // total number of coefficients (one side)
-
-    const int N = M * nzc;
-
-    // lerp (which is most useful if M is a power of 2)
-
-    int nz = 0; // recalculate nz as the bits needed to represent M
-    for (int i = M-1 ; i; i>>=1, nz++);
-    // generate the right half of the filter
-    if (!debug) {
-        printf("// cmd-line:");
-        for (int i=0 ; i<argc ; i++) {
-            printf(" %s", argv[i]);
-        }
-        printf("\n");
-        if (declarations) {
-            if (!polyphase) {
-                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", N);
-                printf("const int32_t RESAMPLE_FIR_INT_PHASES     = %d;\n", M);
-                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", nzc);
-            } else {
-                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", 2*nzc*polyN);
-                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", 2*nzc);
-            }
-            if (!format) {
-                printf("const int32_t RESAMPLE_FIR_COEF_BITS      = %d;\n", nc);
-            }
-            printf("\n");
-            printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
-        }
-    }
-
-    if (!polyphase) {
-        for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation
-            for (int j=0 ; j<nzc ; j++) {
-                int ix = j*M + i;
-                double x = (2.0 * M_PI * ix * Fcr) / M;
-                double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
-                y *= atten;
-
-                if (!debug) {
-                    if (j == 0)
-                        printf("\n    ");
-                }
-                if (!format) {
-                    int64_t yi = toint(y, 1ULL<<(nc-1));
-                    if (nc > 16) {
-                        printf("0x%08x,", int32_t(yi));
-                    } else {
-                        printf("0x%04x,", int32_t(yi)&0xffff);
-                    }
-                } else {
-                    printf("%.9g%s", y, debug ? "," : "f,");
-                }
-                if (j != nzc-1) {
-                    printf(" ");
-                }
-            }
-        }
-    } else {
-        for (unsigned int j=0 ; j<polyN ; j++) {
-            // calculate the phase
-            double p = ((polyM*j) % polyN) / double(polyN);
-            if (!debug) printf("\n    ");
-            else        printf("\n");
-            // generate a FIR per phase
-            for (int i=-nzc ; i<nzc ; i++) {
-                double x = 2.0 * M_PI * Fcr * (i + p);
-                double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;;
-                y *= atten;
-                if (!format) {
-                    int64_t yi = toint(y, 1ULL<<(nc-1));
-                    if (nc > 16) {
-                        printf("0x%08x,", int32_t(yi));
-                    } else {
-                        printf("0x%04x,", int32_t(yi)&0xffff);
-                    }
-                } else {
-                    printf("%.9g%s", y, debug ? "," : "f,");
-                }
-
-                if (i != nzc-1) {
-                    printf(" ");
-                }
-            }
-        }
-    }
-
-    if (!debug && declarations) {
-        printf("\n};");
-    }
-    printf("\n");
-    return 0;
-}
-
-// http://www.csee.umbc.edu/help/sound/AFsp-V2R1/html/audio/ResampAudio.html